1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2004-2007 Marcel Holtmann <marcel (at) 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 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 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 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 len = get_u16(frm) - 3; 204 printf(" = Unicode length %d\n", len); 205 raw_ndump(level, frm, len); 206 frm->ptr += len; 207 frm->len -= len; 208 break; 209 210 case 0x40: /* Byte sequence */ 211 len = get_u16(frm) - 3; 212 printf(" = Sequence length %d\n", len); 213 raw_ndump(level, frm, len); 214 frm->ptr += len; 215 frm->len -= len; 216 break; 217 218 case 0x80: /* One byte */ 219 hv8 = get_u8(frm); 220 printf(" = %d\n", hv8); 221 break; 222 223 case 0xc0: /* Four bytes */ 224 hv32 = get_u32(frm); 225 printf(" = %u\n", hv32); 226 break; 227 } 228 } 229 } 230 231 void obex_dump(int level, struct frame *frm) 232 { 233 uint8_t last_opcode, opcode, status; 234 uint8_t version, flags, constants; 235 uint16_t length, pktlen; 236 237 frm = add_frame(frm); 238 239 while (frm->len > 0) { 240 opcode = get_u8(frm); 241 length = get_u16(frm); 242 status = opcode & 0x7f; 243 244 if (frm->len < length - 3) { 245 frm->ptr -= 3; 246 frm->len += 3; 247 return; 248 } 249 250 p_indent(level, frm); 251 252 last_opcode = get_opcode(frm->handle, frm->dlci); 253 254 if (!(opcode & 0x70)) { 255 printf("OBEX: %s cmd(%c): len %d", 256 opcode2str(opcode), 257 opcode & 0x80 ? 'f' : 'c', length); 258 set_opcode(frm->handle, frm->dlci, opcode); 259 } else { 260 printf("OBEX: %s rsp(%c): status %x%02d len %d", 261 opcode2str(last_opcode), 262 opcode & 0x80 ? 'f' : 'c', 263 status >> 4, status & 0xf, length); 264 opcode = last_opcode; 265 } 266 267 if (get_status(frm->handle, frm->dlci) == 0x10) 268 printf(" (continue)"); 269 270 set_status(frm->handle, frm->dlci, status); 271 272 if (frm->len == 0) { 273 printf("\n"); 274 break; 275 } 276 277 switch (opcode & 0x7f) { 278 case 0x00: /* Connect */ 279 version = get_u8(frm); 280 flags = get_u8(frm); 281 pktlen = get_u16(frm); 282 printf(" version %d.%d flags %d mtu %d\n", 283 version >> 4, version & 0xf, flags, pktlen); 284 break; 285 286 case 0x05: /* SetPath */ 287 if (length > 3) { 288 flags = get_u8(frm); 289 constants = get_u8(frm); 290 printf(" flags %d constants %d\n", 291 flags, constants); 292 } else 293 printf("\n"); 294 break; 295 296 default: 297 printf("\n"); 298 } 299 300 if ((status & 0x70) && (parser.flags & DUMP_VERBOSE)) { 301 p_indent(level, frm); 302 printf("Status %x%02d = %s\n", 303 status >> 4, status & 0xf, 304 opcode2str(status)); 305 } 306 307 parse_headers(level, frm); 308 } 309 } 310