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