• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2011  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <stdio.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include <sys/types.h>
35 #include <netinet/in.h>
36 
37 #include "parser.h"
38 
opcode2str(uint8_t opcode)39 static char *opcode2str(uint8_t opcode)
40 {
41 	switch (opcode & 0x7f) {
42 	case 0x00:
43 		return "Connect";
44 	case 0x01:
45 		return "Disconnect";
46 	case 0x02:
47 		return "Put";
48 	case 0x03:
49 		return "Get";
50 	case 0x04:
51 		return "Reserved";
52 	case 0x05:
53 		return "SetPath";
54 	case 0x06:
55 		return "Reserved";
56 	case 0x07:
57 		return "Session";
58 	case 0x7f:
59 		return "Abort";
60 	case 0x10:
61 		return "Continue";
62 	case 0x20:
63 		return "Success";
64 	case 0x21:
65 		return "Created";
66 	case 0x22:
67 		return "Accepted";
68 	case 0x23:
69 		return "Non-authoritative information";
70 	case 0x24:
71 		return "No content";
72 	case 0x25:
73 		return "Reset content";
74 	case 0x26:
75 		return "Partial content";
76 	case 0x30:
77 		return "Multiple choices";
78 	case 0x31:
79 		return "Moved permanently";
80 	case 0x32:
81 		return "Moved temporarily";
82 	case 0x33:
83 		return "See other";
84 	case 0x34:
85 		return "Not modified";
86 	case 0x35:
87 		return "Use Proxy";
88 	case 0x40:
89 		return "Bad request";
90 	case 0x41:
91 		return "Unauthorized";
92 	case 0x42:
93 		return "Payment required";
94 	case 0x43:
95 		return "Forbidden";
96 	case 0x44:
97 		return "Not found";
98 	case 0x45:
99 		return "Method not allowed";
100 	case 0x46:
101 		return "Not acceptable";
102 	case 0x47:
103 		return "Proxy authentication required";
104 	case 0x48:
105 		return "Request timeout";
106 	case 0x49:
107 		return "Conflict";
108 	case 0x4a:
109 		return "Gone";
110 	case 0x4b:
111 		return "Length required";
112 	case 0x4c:
113 		return "Precondition failed";
114 	case 0x4d:
115 		return "Requested entity too large";
116 	case 0x4e:
117 		return "Requested URL too large";
118 	case 0x4f:
119 		return "Unsupported media type";
120 	case 0x50:
121 		return "Internal server error";
122 	case 0x51:
123 		return "Not implemented";
124 	case 0x52:
125 		return "Bad gateway";
126 	case 0x53:
127 		return "Service unavailable";
128 	case 0x54:
129 		return "Gateway timeout";
130 	case 0x55:
131 		return "HTTP version not supported";
132 	case 0x60:
133 		return "Database full";
134 	case 0x61:
135 		return "Database locked";
136 	default:
137 		return "Unknown";
138 	}
139 }
140 
hi2str(uint8_t hi)141 static char *hi2str(uint8_t hi)
142 {
143 	switch (hi & 0x3f) {
144 	case 0x00:
145 		return "Count";
146 	case 0x01:
147 		return "Name";
148 	case 0x02:
149 		return "Type";
150 	case 0x03:
151 		return "Length";
152 	case 0x04:
153 		return "Time";
154 	case 0x05:
155 		return "Description";
156 	case 0x06:
157 		return "Target";
158 	case 0x07:
159 		return "HTTP";
160 	case 0x08:
161 		return "Body";
162 	case 0x09:
163 		return "End of Body";
164 	case 0x0a:
165 		return "Who";
166 	case 0x0b:
167 		return "Connection ID";
168 	case 0x0c:
169 		return "App. Parameters";
170 	case 0x0d:
171 		return "Auth. Challenge";
172 	case 0x0e:
173 		return "Auth. Response";
174 	case 0x0f:
175 		return "Creator ID";
176 	case 0x10:
177 		return "WAN UUID";
178 	case 0x11:
179 		return "Object Class";
180 	case 0x12:
181 		return "Session Parameters";
182 	case 0x13:
183 		return "Session Sequence Number";
184 	default:
185 		return "Unknown";
186 	}
187 }
188 
parse_headers(int level,struct frame * frm)189 static void parse_headers(int level, struct frame *frm)
190 {
191 	uint8_t hi, hv8;
192 	uint16_t len;
193 	uint32_t hv32;
194 
195 	while (frm->len > 0) {
196 		hi = get_u8(frm);
197 
198 		p_indent(level, frm);
199 
200 		printf("%s (0x%02x)", hi2str(hi), hi);
201 		switch (hi & 0xc0) {
202 		case 0x00:	/* Unicode */
203 			if (frm->len < 2) {
204 				printf("\n");
205 				return;
206 			}
207 
208 			len = get_u16(frm) - 3;
209 			printf(" = Unicode length %d\n", len);
210 
211 			if (frm->len < len)
212 				return;
213 
214 			raw_ndump(level, frm, len);
215 			frm->ptr += len;
216 			frm->len -= len;
217 			break;
218 
219 		case 0x40:	/* Byte sequence */
220 			if (frm->len < 2) {
221 				printf("\n");
222 				return;
223 			}
224 
225 			len = get_u16(frm) - 3;
226 			printf(" = Sequence length %d\n", len);
227 
228 			if (frm->len < len)
229 				return;
230 
231 			raw_ndump(level, frm, len);
232 			frm->ptr += len;
233 			frm->len -= len;
234 			break;
235 
236 		case 0x80:	/* One byte */
237 			if (frm->len < 1) {
238 				printf("\n");
239 				return;
240 			}
241 
242 			hv8 = get_u8(frm);
243 			printf(" = %d\n", hv8);
244 			break;
245 
246 		case 0xc0:	/* Four bytes */
247 			if (frm->len < 4) {
248 				printf("\n");
249 				return;
250 			}
251 
252 			hv32 = get_u32(frm);
253 			printf(" = %u\n", hv32);
254 			break;
255 		}
256 	}
257 }
258 
obex_dump(int level,struct frame * frm)259 void obex_dump(int level, struct frame *frm)
260 {
261 	uint8_t last_opcode, opcode, status;
262 	uint8_t version, flags, constants;
263 	uint16_t length, pktlen;
264 
265 	frm = add_frame(frm);
266 
267 	while (frm->len > 2) {
268 		opcode = get_u8(frm);
269 		length = get_u16(frm);
270 		status = opcode & 0x7f;
271 
272 		if ((int) frm->len < length - 3) {
273 			frm->ptr -= 3;
274 			frm->len += 3;
275 			return;
276 		}
277 
278 		p_indent(level, frm);
279 
280 		last_opcode = get_opcode(frm->handle, frm->dlci);
281 
282 		if (!(opcode & 0x70)) {
283 			printf("OBEX: %s cmd(%c): len %d",
284 					opcode2str(opcode),
285 					opcode & 0x80 ? 'f' : 'c', length);
286 			set_opcode(frm->handle, frm->dlci, opcode);
287 		} else {
288 			printf("OBEX: %s rsp(%c): status %x%02d len %d",
289 					opcode2str(last_opcode),
290 					opcode & 0x80 ? 'f' : 'c',
291 					status >> 4, status & 0xf, length);
292 			opcode = last_opcode;
293 		}
294 
295 		if (get_status(frm->handle, frm->dlci) == 0x10)
296 			printf(" (continue)");
297 
298 		set_status(frm->handle, frm->dlci, status);
299 
300 		if (frm->len == 0) {
301 			printf("\n");
302 			break;
303 		}
304 
305 		switch (opcode & 0x7f) {
306 		case 0x00:	/* Connect */
307 			if (frm->len < 4) {
308 				printf("\n");
309 				return;
310 			}
311 
312 			version = get_u8(frm);
313 			flags   = get_u8(frm);
314 			pktlen  = get_u16(frm);
315 			printf(" version %d.%d flags %d mtu %d\n",
316 				version >> 4, version & 0xf, flags, pktlen);
317 			break;
318 
319 		case 0x05:	/* SetPath */
320 			if (frm->len < 2) {
321 				printf("\n");
322 				return;
323 			}
324 
325 			flags     = get_u8(frm);
326 			constants = get_u8(frm);
327 			printf(" flags %d constants %d\n", flags, constants);
328 			break;
329 
330 		default:
331 			printf("\n");
332 			break;
333 		}
334 
335 		if ((status & 0x70) && (parser.flags & DUMP_VERBOSE)) {
336 			p_indent(level, frm);
337 			printf("Status %x%02d = %s\n",
338 					status >> 4, status & 0xf,
339 							opcode2str(status));
340 		}
341 
342 		parse_headers(level, frm);
343 	}
344 }
345