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.2 2005/09/20 06:25:45 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 + sizeof(*dh); 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 u_int64_t dccp_ack_no(const struct dccp_hdr *dh, 159 const struct dccp_hdr_ack_bits *dh_ack) 160 { 161 u_int32_t ack_high = DCCPH_ACK(dh_ack); 162 u_int64_t ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF; 163 164 if (DCCPH_X(dh) != 0) { 165 u_int32_t ack_low = dh_ack->dccph_ack_nr_low; 166 167 ackno &= 0x00FFFF; /* clear reserved field */ 168 ackno = (ackno << 32) + EXTRACT_32BITS(&ack_low); 169 } 170 171 return ackno; 172 } 173 174 static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh) 175 { 176 return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0); 177 } 178 179 static inline unsigned int dccp_packet_hdr_len(const u_int8_t type) 180 { 181 if (type == DCCP_PKT_DATA) 182 return 0; 183 if (type == DCCP_PKT_DATAACK || 184 type == DCCP_PKT_ACK || 185 type == DCCP_PKT_SYNC || 186 type == DCCP_PKT_SYNCACK || 187 type == DCCP_PKT_CLOSE || 188 type == DCCP_PKT_CLOSEREQ) 189 return sizeof(struct dccp_hdr_ack_bits); 190 if (type == DCCP_PKT_REQUEST) 191 return sizeof(struct dccp_hdr_request); 192 if (type == DCCP_PKT_RESPONSE) 193 return sizeof(struct dccp_hdr_response); 194 return sizeof(struct dccp_hdr_reset); 195 } 196 197 static int dccp_print_option(const u_char *option); 198 199 /** 200 * dccp_print - show dccp packet 201 * @bp - beginning of dccp packet 202 * @data2 - beginning of enclosing 203 * @len - lenght of ip packet 204 */ 205 void dccp_print(const u_char *bp, const u_char *data2, u_int len) 206 { 207 const struct dccp_hdr *dh; 208 const struct ip *ip; 209 #ifdef INET6 210 const struct ip6_hdr *ip6; 211 #endif 212 const u_char *cp; 213 u_short sport, dport; 214 u_int hlen; 215 u_int extlen = 0; 216 217 dh = (const struct dccp_hdr *)bp; 218 219 ip = (struct ip *)data2; 220 #ifdef INET6 221 if (IP_V(ip) == 6) 222 ip6 = (const struct ip6_hdr *)data2; 223 else 224 ip6 = NULL; 225 #endif /*INET6*/ 226 cp = (const u_char *)(dh + 1); 227 if (cp > snapend) { 228 printf("[Invalid packet|dccp]"); 229 return; 230 } 231 232 if (len < sizeof(struct dccp_hdr)) { 233 printf("truncated-dccp - %ld bytes missing!", 234 (long)len - sizeof(struct dccp_hdr)); 235 return; 236 } 237 238 sport = EXTRACT_16BITS(&dh->dccph_sport); 239 dport = EXTRACT_16BITS(&dh->dccph_dport); 240 hlen = dh->dccph_doff * 4; 241 242 #ifdef INET6 243 if (ip6) { 244 (void)printf("%s.%d > %s.%d: ", 245 ip6addr_string(&ip6->ip6_src), sport, 246 ip6addr_string(&ip6->ip6_dst), dport); 247 } else 248 #endif /*INET6*/ 249 { 250 (void)printf("%s.%d > %s.%d: ", 251 ipaddr_string(&ip->ip_src), sport, 252 ipaddr_string(&ip->ip_dst), dport); 253 } 254 fflush(stdout); 255 256 if (qflag) { 257 (void)printf(" %d", len - hlen); 258 if (hlen > len) { 259 (void)printf("dccp [bad hdr length %u - too long, > %u]", 260 hlen, len); 261 } 262 return; 263 } 264 265 /* other variables in generic header */ 266 if (vflag) { 267 (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); 268 } 269 270 /* checksum calculation */ 271 #ifdef INET6 272 if (ip6) { 273 if (ip6->ip6_plen && vflag) { 274 u_int16_t sum, dccp_sum; 275 276 sum = dccp6_cksum(ip6, dh, len); 277 dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); 278 printf("cksum 0x%04x", dccp_sum); 279 if (sum != 0) { 280 (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); 281 } else 282 (void)printf(" (correct), "); 283 } 284 } else 285 #endif /* INET6 */ 286 if (vflag) 287 { 288 u_int16_t sum, dccp_sum; 289 290 sum = dccp_cksum(ip, dh, len); 291 dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); 292 printf("cksum 0x%04x", dccp_sum); 293 if (sum != 0) { 294 (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); 295 } else 296 (void)printf(" (correct), "); 297 } 298 299 switch (DCCPH_TYPE(dh)) { 300 case DCCP_PKT_REQUEST: { 301 struct dccp_hdr_request *dhr = 302 (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh)); 303 TCHECK(*dhr); 304 (void)printf("request (service=%d) ", dhr->dccph_req_service); 305 extlen += 4; 306 break; 307 } 308 case DCCP_PKT_RESPONSE: { 309 struct dccp_hdr_response *dhr = 310 (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh)); 311 TCHECK(*dhr); 312 (void)printf("response (service=%d, ack=%" PRIu64 ") ", 313 dhr->dccph_resp_service, 314 dccp_ack_no(dh,&(dhr->dccph_resp_ack))); 315 extlen += 12; 316 break; 317 } 318 case DCCP_PKT_DATA: 319 (void)printf("data "); 320 break; 321 case DCCP_PKT_ACK: { 322 struct dccp_hdr_ack_bits *dha = 323 (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh)); 324 TCHECK(*dha); 325 (void)printf("ack (ack=%" PRIu64 ") ", 326 dccp_ack_no(dh,dha)); 327 extlen += 8; 328 break; 329 } 330 case DCCP_PKT_DATAACK: { 331 struct dccp_hdr_ack_bits *dha = 332 (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh)); 333 TCHECK(*dha); 334 (void)printf("dataack (ack=%" PRIu64 ") ", 335 dccp_ack_no(dh,dha)); 336 extlen += 8; 337 break; 338 } 339 case DCCP_PKT_CLOSEREQ: 340 (void)printf("closereq "); 341 extlen += 8; 342 break; 343 case DCCP_PKT_CLOSE: 344 (void)printf("close "); 345 extlen += 8; 346 break; 347 case DCCP_PKT_RESET: { 348 struct dccp_hdr_reset *dhr = 349 (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh)); 350 TCHECK(*dhr); 351 (void)printf("reset (code=%s) ", 352 dccp_reset_code(dhr->dccph_reset_code)); 353 extlen += 12; 354 break; 355 } 356 case DCCP_PKT_SYNC: 357 (void)printf("sync "); 358 extlen += 8; 359 break; 360 case DCCP_PKT_SYNCACK: 361 (void)printf("syncack "); 362 extlen += 8; 363 break; 364 default: 365 (void)printf("invalid "); 366 break; 367 } 368 369 if (vflag < 2) 370 return; 371 372 (void)printf("seq %" PRIu64, dccp_seqno(dh)); 373 374 /* process options */ 375 if (hlen > dccp_basic_hdr_len(dh) + extlen){ 376 const u_char *cp; 377 u_int optlen; 378 cp = bp + dccp_basic_hdr_len(dh) + extlen; 379 printf(" <"); 380 381 hlen -= dccp_basic_hdr_len(dh) + extlen; 382 while(1){ 383 TCHECK(*cp); 384 optlen = dccp_print_option(cp); 385 if (!optlen) goto trunc2; 386 if (hlen <= optlen) break; 387 hlen -= optlen; 388 cp += optlen; 389 printf(", "); 390 } 391 printf(">"); 392 } 393 return; 394 trunc: 395 printf("[|dccp]"); 396 trunc2: 397 return; 398 } 399 400 static int dccp_print_option(const u_char *option) 401 { 402 u_int8_t optlen, i; 403 u_int32_t *ts; 404 u_int16_t *var16; 405 u_int32_t *var32; 406 407 TCHECK(*option); 408 409 if (*option >= 32) { 410 TCHECK(*(option+1)); 411 optlen = *(option +1); 412 if (optlen < 2) { 413 printf("Option %d optlen too short",*option); 414 return 1; 415 } 416 } else optlen = 1; 417 418 TCHECK2(*option,optlen); 419 420 switch (*option){ 421 case 0: 422 printf("nop"); 423 break; 424 case 1: 425 printf("mandatory"); 426 break; 427 case 2: 428 printf("slowreceiver"); 429 break; 430 case 32: 431 printf("change_l"); 432 if (*(option +2) < 10){ 433 printf(" %s", dccp_feature_nums[*(option +2)]); 434 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 435 } 436 break; 437 case 33: 438 printf("confirm_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 34: 445 printf("change_r"); 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 35: 452 printf("confirm_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 36: 459 printf("initcookie 0x"); 460 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 461 break; 462 case 37: 463 printf("ndp_count"); 464 for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i)); 465 break; 466 case 38: 467 printf("ack_vector0 0x"); 468 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 469 break; 470 case 39: 471 printf("ack_vector1 0x"); 472 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 473 break; 474 case 40: 475 printf("data_dropped 0x"); 476 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 477 break; 478 case 41: 479 ts = (u_int32_t *)(option + 2); 480 printf("timestamp %u", (u_int32_t)ntohl(*ts)); 481 break; 482 case 42: 483 ts = (u_int32_t *)(option + 2); 484 printf("timestamp_echo %u", (u_int32_t)ntohl(*ts)); 485 break; 486 case 43: 487 printf("elapsed_time "); 488 if (optlen == 6){ 489 ts = (u_int32_t *)(option + 2); 490 printf("%u", (u_int32_t)ntohl(*ts)); 491 } else { 492 var16 = (u_int16_t *)(option + 2); 493 printf("%u", ntohs(*var16)); 494 } 495 break; 496 case 44: 497 printf("data_checksum "); 498 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 499 break; 500 default : 501 if (*option >= 128) { 502 printf("CCID option %d",*option); 503 switch (optlen) { 504 case 4: 505 var16 = (u_int16_t *)(option + 2); 506 printf(" %u",ntohs(*var16)); 507 break; 508 case 6: 509 var32 = (u_int32_t *)(option + 2); 510 printf(" %u",(u_int32_t)ntohl(*var32)); 511 break; 512 default: 513 break; 514 } 515 break; 516 } 517 518 printf("unknown_opt %d", *option); 519 break; 520 } 521 522 return optlen; 523 trunc: 524 printf("[|dccp]"); 525 return 0; 526 } 527