1 /* 2 * Copyright (C) Arnaldo Carvalho de Melo 2004 3 * Copyright (C) Ian McDonald 2005 4 * Copyright (C) Yoshifumi Nishida 2005 5 * 6 * This software may be distributed either under the terms of the 7 * BSD-style license that accompanies tcpdump or the GNU GPL version 2 8 */ 9 10 #ifndef lint 11 static const char rcsid[] _U_ = 12 "@(#) $Header: /tcpdump/master/tcpdump/print-dccp.c,v 1.1.2.6 2006/02/19 05:08:44 guy Exp $ (LBL)"; 13 #endif 14 15 #ifdef HAVE_CONFIG_H 16 #include "config.h" 17 #endif 18 19 #include <tcpdump-stdinc.h> 20 21 #include "dccp.h" 22 23 #include <stdio.h> 24 #include <string.h> 25 26 #include "interface.h" 27 #include "addrtoname.h" 28 #include "extract.h" /* must come after interface.h */ 29 #include "ip.h" 30 #ifdef INET6 31 #include "ip6.h" 32 #endif 33 #include "ipproto.h" 34 35 static const char *dccp_reset_codes[] = { 36 "unspecified", 37 "closed", 38 "aborted", 39 "no_connection", 40 "packet_error", 41 "option_error", 42 "mandatory_error", 43 "connection_refused", 44 "bad_service_code", 45 "too_busy", 46 "bad_init_cookie", 47 "aggression_penalty", 48 }; 49 50 static const char *dccp_feature_nums[] = { 51 "reserved", 52 "ccid", 53 "allow_short_seqno", 54 "sequence_window", 55 "ecn_incapable", 56 "ack_ratio", 57 "send_ack_vector", 58 "send_ndp_count", 59 "minimum checksum coverage", 60 "check data checksum", 61 }; 62 63 static int dccp_cksum(const struct ip *ip, 64 const struct dccp_hdr *dh, u_int len) 65 { 66 union phu { 67 struct phdr { 68 u_int32_t src; 69 u_int32_t dst; 70 u_char mbz; 71 u_char proto; 72 u_int16_t len; 73 } ph; 74 u_int16_t pa[6]; 75 } phu; 76 const u_int16_t *sp; 77 78 /* pseudo-header.. */ 79 phu.ph.mbz = 0; 80 phu.ph.len = htons(len); 81 phu.ph.proto = IPPROTO_DCCP; 82 memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); 83 if (IP_HL(ip) == 5) 84 memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); 85 else 86 phu.ph.dst = ip_finddst(ip); 87 88 sp = &phu.pa[0]; 89 return in_cksum((u_short *)dh, len, sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]); 90 } 91 92 #ifdef INET6 93 static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len) 94 { 95 size_t i; 96 const u_int16_t *sp; 97 u_int32_t sum; 98 union { 99 struct { 100 struct in6_addr ph_src; 101 struct in6_addr ph_dst; 102 u_int32_t ph_len; 103 u_int8_t ph_zero[3]; 104 u_int8_t ph_nxt; 105 } ph; 106 u_int16_t pa[20]; 107 } phu; 108 109 /* pseudo-header */ 110 memset(&phu, 0, sizeof(phu)); 111 phu.ph.ph_src = ip6->ip6_src; 112 phu.ph.ph_dst = ip6->ip6_dst; 113 phu.ph.ph_len = htonl(len); 114 phu.ph.ph_nxt = IPPROTO_DCCP; 115 116 sum = 0; 117 for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) 118 sum += phu.pa[i]; 119 120 sp = (const u_int16_t *)dh; 121 122 for (i = 0; i < (len & ~1); i += 2) 123 sum += *sp++; 124 125 if (len & 1) 126 sum += htons((*(const u_int8_t *)sp) << 8); 127 128 while (sum > 0xffff) 129 sum = (sum & 0xffff) + (sum >> 16); 130 sum = ~sum & 0xffff; 131 132 return (sum); 133 } 134 #endif 135 136 static const char *dccp_reset_code(u_int8_t code) 137 { 138 if (code >= __DCCP_RESET_CODE_LAST) 139 return "invalid"; 140 return dccp_reset_codes[code]; 141 } 142 143 static u_int64_t dccp_seqno(const struct dccp_hdr *dh) 144 { 145 u_int32_t seq_high = DCCPH_SEQ(dh); 146 u_int64_t seqno = EXTRACT_24BITS(&seq_high) & 0xFFFFFF; 147 148 if (DCCPH_X(dh) != 0) { 149 const struct dccp_hdr_ext *dhx = (void *)(dh + 1); 150 u_int32_t seq_low = dhx->dccph_seq_low; 151 seqno &= 0x00FFFF; /* clear reserved field */ 152 seqno = (seqno << 32) + EXTRACT_32BITS(&seq_low); 153 } 154 155 return seqno; 156 } 157 158 static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh) 159 { 160 return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0); 161 } 162 163 static void dccp_print_ack_no(const u_char *bp) 164 { 165 const struct dccp_hdr *dh = (const struct dccp_hdr *)bp; 166 const struct dccp_hdr_ack_bits *dh_ack = 167 (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh)); 168 u_int32_t ack_high; 169 u_int64_t ackno; 170 171 TCHECK2(*dh_ack,4); 172 ack_high = DCCPH_ACK(dh_ack); 173 ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF; 174 175 if (DCCPH_X(dh) != 0) { 176 u_int32_t ack_low; 177 178 TCHECK2(*dh_ack,8); 179 ack_low = dh_ack->dccph_ack_nr_low; 180 181 ackno &= 0x00FFFF; /* clear reserved field */ 182 ackno = (ackno << 32) + EXTRACT_32BITS(&ack_low); 183 } 184 185 (void)printf("(ack=%" PRIu64 ") ", ackno); 186 trunc: 187 return; 188 } 189 190 static inline unsigned int dccp_packet_hdr_len(const u_int8_t type) 191 { 192 if (type == DCCP_PKT_DATA) 193 return 0; 194 if (type == DCCP_PKT_DATAACK || 195 type == DCCP_PKT_ACK || 196 type == DCCP_PKT_SYNC || 197 type == DCCP_PKT_SYNCACK || 198 type == DCCP_PKT_CLOSE || 199 type == DCCP_PKT_CLOSEREQ) 200 return sizeof(struct dccp_hdr_ack_bits); 201 if (type == DCCP_PKT_REQUEST) 202 return sizeof(struct dccp_hdr_request); 203 if (type == DCCP_PKT_RESPONSE) 204 return sizeof(struct dccp_hdr_response); 205 return sizeof(struct dccp_hdr_reset); 206 } 207 208 static int dccp_print_option(const u_char *option); 209 210 /** 211 * dccp_print - show dccp packet 212 * @bp - beginning of dccp packet 213 * @data2 - beginning of enclosing 214 * @len - lenght of ip packet 215 */ 216 void dccp_print(const u_char *bp, const u_char *data2, u_int len) 217 { 218 const struct dccp_hdr *dh; 219 const struct ip *ip; 220 #ifdef INET6 221 const struct ip6_hdr *ip6; 222 #endif 223 const u_char *cp; 224 u_short sport, dport; 225 u_int hlen; 226 u_int extlen = 0; 227 228 dh = (const struct dccp_hdr *)bp; 229 230 ip = (struct ip *)data2; 231 #ifdef INET6 232 if (IP_V(ip) == 6) 233 ip6 = (const struct ip6_hdr *)data2; 234 else 235 ip6 = NULL; 236 #endif /*INET6*/ 237 cp = (const u_char *)(dh + 1); 238 if (cp > snapend) { 239 printf("[Invalid packet|dccp]"); 240 return; 241 } 242 243 if (len < sizeof(struct dccp_hdr)) { 244 printf("truncated-dccp - %ld bytes missing!", 245 (long)len - sizeof(struct dccp_hdr)); 246 return; 247 } 248 249 sport = EXTRACT_16BITS(&dh->dccph_sport); 250 dport = EXTRACT_16BITS(&dh->dccph_dport); 251 hlen = dh->dccph_doff * 4; 252 253 #ifdef INET6 254 if (ip6) { 255 (void)printf("%s.%d > %s.%d: ", 256 ip6addr_string(&ip6->ip6_src), sport, 257 ip6addr_string(&ip6->ip6_dst), dport); 258 } else 259 #endif /*INET6*/ 260 { 261 (void)printf("%s.%d > %s.%d: ", 262 ipaddr_string(&ip->ip_src), sport, 263 ipaddr_string(&ip->ip_dst), dport); 264 } 265 fflush(stdout); 266 267 if (qflag) { 268 (void)printf(" %d", len - hlen); 269 if (hlen > len) { 270 (void)printf("dccp [bad hdr length %u - too long, > %u]", 271 hlen, len); 272 } 273 return; 274 } 275 276 /* other variables in generic header */ 277 if (vflag) { 278 (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); 279 } 280 281 /* checksum calculation */ 282 #ifdef INET6 283 if (ip6) { 284 if (ip6->ip6_plen && vflag) { 285 u_int16_t sum, dccp_sum; 286 287 sum = dccp6_cksum(ip6, dh, len); 288 dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); 289 printf("cksum 0x%04x", dccp_sum); 290 if (sum != 0) { 291 (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); 292 } else 293 (void)printf(" (correct), "); 294 } 295 } else 296 #endif /* INET6 */ 297 if (vflag) 298 { 299 u_int16_t sum, dccp_sum; 300 301 sum = dccp_cksum(ip, dh, len); 302 dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); 303 printf("cksum 0x%04x", dccp_sum); 304 if (sum != 0) { 305 (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); 306 } else 307 (void)printf(" (correct), "); 308 } 309 310 switch (DCCPH_TYPE(dh)) { 311 case DCCP_PKT_REQUEST: { 312 struct dccp_hdr_request *dhr = 313 (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh)); 314 TCHECK(*dhr); 315 (void)printf("request (service=%d) ", 316 EXTRACT_32BITS(&dhr->dccph_req_service)); 317 extlen += 4; 318 break; 319 } 320 case DCCP_PKT_RESPONSE: { 321 struct dccp_hdr_response *dhr = 322 (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh)); 323 TCHECK(*dhr); 324 (void)printf("response (service=%d) ", 325 EXTRACT_32BITS(&dhr->dccph_resp_service)); 326 extlen += 12; 327 break; 328 } 329 case DCCP_PKT_DATA: 330 (void)printf("data "); 331 break; 332 case DCCP_PKT_ACK: { 333 (void)printf("ack "); 334 extlen += 8; 335 break; 336 } 337 case DCCP_PKT_DATAACK: { 338 (void)printf("dataack "); 339 extlen += 8; 340 break; 341 } 342 case DCCP_PKT_CLOSEREQ: 343 (void)printf("closereq "); 344 extlen += 8; 345 break; 346 case DCCP_PKT_CLOSE: 347 (void)printf("close "); 348 extlen += 8; 349 break; 350 case DCCP_PKT_RESET: { 351 struct dccp_hdr_reset *dhr = 352 (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh)); 353 TCHECK(*dhr); 354 (void)printf("reset (code=%s) ", 355 dccp_reset_code(dhr->dccph_reset_code)); 356 extlen += 12; 357 break; 358 } 359 case DCCP_PKT_SYNC: 360 (void)printf("sync "); 361 extlen += 8; 362 break; 363 case DCCP_PKT_SYNCACK: 364 (void)printf("syncack "); 365 extlen += 8; 366 break; 367 default: 368 (void)printf("invalid "); 369 break; 370 } 371 372 if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && 373 (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST)) 374 dccp_print_ack_no(bp); 375 376 if (vflag < 2) 377 return; 378 379 (void)printf("seq %" PRIu64, dccp_seqno(dh)); 380 381 /* process options */ 382 if (hlen > dccp_basic_hdr_len(dh) + extlen){ 383 const u_char *cp; 384 u_int optlen; 385 cp = bp + dccp_basic_hdr_len(dh) + extlen; 386 printf(" <"); 387 388 hlen -= dccp_basic_hdr_len(dh) + extlen; 389 while(1){ 390 TCHECK(*cp); 391 optlen = dccp_print_option(cp); 392 if (!optlen) goto trunc2; 393 if (hlen <= optlen) break; 394 hlen -= optlen; 395 cp += optlen; 396 printf(", "); 397 } 398 printf(">"); 399 } 400 return; 401 trunc: 402 printf("[|dccp]"); 403 trunc2: 404 return; 405 } 406 407 static int dccp_print_option(const u_char *option) 408 { 409 u_int8_t optlen, i; 410 u_int32_t *ts; 411 u_int16_t *var16; 412 u_int32_t *var32; 413 414 TCHECK(*option); 415 416 if (*option >= 32) { 417 TCHECK(*(option+1)); 418 optlen = *(option +1); 419 if (optlen < 2) { 420 printf("Option %d optlen too short",*option); 421 return 1; 422 } 423 } else optlen = 1; 424 425 TCHECK2(*option,optlen); 426 427 switch (*option){ 428 case 0: 429 printf("nop"); 430 break; 431 case 1: 432 printf("mandatory"); 433 break; 434 case 2: 435 printf("slowreceiver"); 436 break; 437 case 32: 438 printf("change_l"); 439 if (*(option +2) < 10){ 440 printf(" %s", dccp_feature_nums[*(option +2)]); 441 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 442 } 443 break; 444 case 33: 445 printf("confirm_l"); 446 if (*(option +2) < 10){ 447 printf(" %s", dccp_feature_nums[*(option +2)]); 448 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 449 } 450 break; 451 case 34: 452 printf("change_r"); 453 if (*(option +2) < 10){ 454 printf(" %s", dccp_feature_nums[*(option +2)]); 455 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 456 } 457 break; 458 case 35: 459 printf("confirm_r"); 460 if (*(option +2) < 10){ 461 printf(" %s", dccp_feature_nums[*(option +2)]); 462 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 463 } 464 break; 465 case 36: 466 printf("initcookie 0x"); 467 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 468 break; 469 case 37: 470 printf("ndp_count"); 471 for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i)); 472 break; 473 case 38: 474 printf("ack_vector0 0x"); 475 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 476 break; 477 case 39: 478 printf("ack_vector1 0x"); 479 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 480 break; 481 case 40: 482 printf("data_dropped 0x"); 483 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 484 break; 485 case 41: 486 ts = (u_int32_t *)(option + 2); 487 printf("timestamp %u", (u_int32_t)ntohl(*ts)); 488 break; 489 case 42: 490 ts = (u_int32_t *)(option + 2); 491 printf("timestamp_echo %u", (u_int32_t)ntohl(*ts)); 492 break; 493 case 43: 494 printf("elapsed_time "); 495 if (optlen == 6){ 496 ts = (u_int32_t *)(option + 2); 497 printf("%u", (u_int32_t)ntohl(*ts)); 498 } else { 499 var16 = (u_int16_t *)(option + 2); 500 printf("%u", ntohs(*var16)); 501 } 502 break; 503 case 44: 504 printf("data_checksum "); 505 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 506 break; 507 default : 508 if (*option >= 128) { 509 printf("CCID option %d",*option); 510 switch (optlen) { 511 case 4: 512 var16 = (u_int16_t *)(option + 2); 513 printf(" %u",ntohs(*var16)); 514 break; 515 case 6: 516 var32 = (u_int32_t *)(option + 2); 517 printf(" %u",(u_int32_t)ntohl(*var32)); 518 break; 519 default: 520 break; 521 } 522 break; 523 } 524 525 printf("unknown_opt %d", *option); 526 break; 527 } 528 529 return optlen; 530 trunc: 531 printf("[|dccp]"); 532 return 0; 533 } 534