Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / tools / parser / obex.c
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 "parser.h"
35
36 static char *opcode2str(uint8_t opcode)
37 {
38         switch (opcode & 0x7f) {
39         case 0x00:
40                 return "Connect";
41         case 0x01:
42                 return "Disconnect";
43         case 0x02:
44                 return "Put";
45         case 0x03:
46                 return "Get";
47         case 0x04:
48                 return "Reserved";
49         case 0x05:
50                 return "SetPath";
51         case 0x06:
52                 return "Action";
53         case 0x07:
54                 return "Session";
55         case 0x7f:
56                 return "Abort";
57         case 0x10:
58                 return "Continue";
59         case 0x20:
60                 return "Success";
61         case 0x21:
62                 return "Created";
63         case 0x22:
64                 return "Accepted";
65         case 0x23:
66                 return "Non-authoritative information";
67         case 0x24:
68                 return "No content";
69         case 0x25:
70                 return "Reset content";
71         case 0x26:
72                 return "Partial content";
73         case 0x30:
74                 return "Multiple choices";
75         case 0x31:
76                 return "Moved permanently";
77         case 0x32:
78                 return "Moved temporarily";
79         case 0x33:
80                 return "See other";
81         case 0x34:
82                 return "Not modified";
83         case 0x35:
84                 return "Use Proxy";
85         case 0x40:
86                 return "Bad request";
87         case 0x41:
88                 return "Unauthorized";
89         case 0x42:
90                 return "Payment required";
91         case 0x43:
92                 return "Forbidden";
93         case 0x44:
94                 return "Not found";
95         case 0x45:
96                 return "Method not allowed";
97         case 0x46:
98                 return "Not acceptable";
99         case 0x47:
100                 return "Proxy authentication required";
101         case 0x48:
102                 return "Request timeout";
103         case 0x49:
104                 return "Conflict";
105         case 0x4a:
106                 return "Gone";
107         case 0x4b:
108                 return "Length required";
109         case 0x4c:
110                 return "Precondition failed";
111         case 0x4d:
112                 return "Requested entity too large";
113         case 0x4e:
114                 return "Requested URL too large";
115         case 0x4f:
116                 return "Unsupported media type";
117         case 0x50:
118                 return "Internal server error";
119         case 0x51:
120                 return "Not implemented";
121         case 0x52:
122                 return "Bad gateway";
123         case 0x53:
124                 return "Service unavailable";
125         case 0x54:
126                 return "Gateway timeout";
127         case 0x55:
128                 return "HTTP version not supported";
129         case 0x60:
130                 return "Database full";
131         case 0x61:
132                 return "Database locked";
133         default:
134                 return "Unknown";
135         }
136 }
137
138 static char *hi2str(uint8_t hi)
139 {
140         switch (hi & 0x3f) {
141         case 0x00:
142                 return "Count";
143         case 0x01:
144                 return "Name";
145         case 0x02:
146                 return "Type";
147         case 0x03:
148                 return "Length";
149         case 0x04:
150                 return "Time";
151         case 0x05:
152                 return "Description";
153         case 0x06:
154                 return "Target";
155         case 0x07:
156                 return "HTTP";
157         case 0x08:
158                 return "Body";
159         case 0x09:
160                 return "End of Body";
161         case 0x0a:
162                 return "Who";
163         case 0x0b:
164                 return "Connection ID";
165         case 0x0c:
166                 return "App. Parameters";
167         case 0x0d:
168                 return "Auth. Challenge";
169         case 0x0e:
170                 return "Auth. Response";
171         case 0x0f:
172                 return "Creator ID";
173         case 0x10:
174                 return "WAN UUID";
175         case 0x11:
176                 return "Object Class";
177         case 0x12:
178                 return "Session Parameters";
179         case 0x13:
180                 return "Session Sequence Number";
181         case 0x14:
182                 return "Action ID";
183         case 0x15:
184                 return "DestName";
185         case 0x16:
186                 return "Permission";
187         case 0x17:
188                 return "Single Response Mode";
189         case 0x18:
190                 return "Single Response Mode Parameters";
191         default:
192                 return "Unknown";
193         }
194 }
195
196 static void parse_headers(int level, struct frame *frm)
197 {
198         uint8_t hi, hv8;
199         uint16_t len;
200         uint32_t hv32;
201
202         while (frm->len > 0) {
203                 hi = p_get_u8(frm);
204
205                 p_indent(level, frm);
206
207                 printf("%s (0x%02x)", hi2str(hi), hi);
208                 switch (hi & 0xc0) {
209                 case 0x00:      /* Unicode */
210                         if (frm->len < 2) {
211                                 printf("\n");
212                                 return;
213                         }
214
215                         len = p_get_u16(frm) - 3;
216                         printf(" = Unicode length %d\n", len);
217
218                         if (frm->len < len)
219                                 return;
220
221                         raw_ndump(level, frm, len);
222                         frm->ptr += len;
223                         frm->len -= len;
224                         break;
225
226                 case 0x40:      /* Byte sequence */
227                         if (frm->len < 2) {
228                                 printf("\n");
229                                 return;
230                         }
231
232                         len = p_get_u16(frm) - 3;
233                         printf(" = Sequence length %d\n", len);
234
235                         if (frm->len < len)
236                                 return;
237
238                         raw_ndump(level, frm, len);
239                         frm->ptr += len;
240                         frm->len -= len;
241                         break;
242
243                 case 0x80:      /* One byte */
244                         if (frm->len < 1) {
245                                 printf("\n");
246                                 return;
247                         }
248
249                         hv8 = p_get_u8(frm);
250                         printf(" = %d\n", hv8);
251                         break;
252
253                 case 0xc0:      /* Four bytes */
254                         if (frm->len < 4) {
255                                 printf("\n");
256                                 return;
257                         }
258
259                         hv32 = p_get_u32(frm);
260                         printf(" = %u\n", hv32);
261                         break;
262                 }
263         }
264 }
265
266 void obex_dump(int level, struct frame *frm)
267 {
268         uint8_t last_opcode, opcode, status;
269         uint8_t version, flags, constants;
270         uint16_t length, pktlen;
271
272         frm = add_frame(frm);
273
274         while (frm->len > 2) {
275                 opcode = p_get_u8(frm);
276                 length = p_get_u16(frm);
277                 status = opcode & 0x7f;
278
279                 if ((int) frm->len < length - 3) {
280                         frm->ptr -= 3;
281                         frm->len += 3;
282                         return;
283                 }
284
285                 p_indent(level, frm);
286
287                 last_opcode = get_opcode(frm->handle, frm->dlci);
288
289                 if (!(opcode & 0x70)) {
290                         printf("OBEX: %s cmd(%c): len %d",
291                                         opcode2str(opcode),
292                                         opcode & 0x80 ? 'f' : 'c', length);
293                         set_opcode(frm->handle, frm->dlci, opcode);
294                 } else {
295                         printf("OBEX: %s rsp(%c): status %x%02d len %d",
296                                         opcode2str(last_opcode),
297                                         opcode & 0x80 ? 'f' : 'c',
298                                         status >> 4, status & 0xf, length);
299                         opcode = last_opcode;
300                 }
301
302                 if (get_status(frm->handle, frm->dlci) == 0x10)
303                         printf(" (continue)");
304
305                 set_status(frm->handle, frm->dlci, status);
306
307                 if (frm->len == 0) {
308                         printf("\n");
309                         break;
310                 }
311
312                 switch (opcode & 0x7f) {
313                 case 0x00:      /* Connect */
314                         if (frm->len < 4) {
315                                 printf("\n");
316                                 return;
317                         }
318
319                         version = p_get_u8(frm);
320                         flags   = p_get_u8(frm);
321                         pktlen  = p_get_u16(frm);
322                         printf(" version %d.%d flags %d mtu %d\n",
323                                 version >> 4, version & 0xf, flags, pktlen);
324                         break;
325
326                 case 0x05:      /* SetPath */
327                         if (frm->len < 2) {
328                                 printf("\n");
329                                 return;
330                         }
331
332                         flags     = p_get_u8(frm);
333                         constants = p_get_u8(frm);
334                         printf(" flags %d constants %d\n", flags, constants);
335                         break;
336
337                 default:
338                         printf("\n");
339                         break;
340                 }
341
342                 if ((status & 0x70) && (parser.flags & DUMP_VERBOSE)) {
343                         p_indent(level, frm);
344                         printf("Status %x%02d = %s\n",
345                                         status >> 4, status & 0xf,
346                                                         opcode2str(status));
347                 }
348
349                 parse_headers(level, frm);
350         }
351 }