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.3 2013/04/06 19:33:08 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 u_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 return nextproto4_cksum(ip, (const u_int8_t *)(void *)dh, 82 dccp_csum_coverage(dh, len), IPPROTO_DCCP); 83 } 84 85 #ifdef INET6 86 static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len) 87 { 88 return nextproto6_cksum(ip6, (const u_int8_t *)(void *)dh, 89 dccp_csum_coverage(dh, len), IPPROTO_DCCP); 90 } 91 #endif 92 93 static const char *dccp_reset_code(u_int8_t code) 94 { 95 if (code >= __DCCP_RESET_CODE_LAST) 96 return "invalid"; 97 return dccp_reset_codes[code]; 98 } 99 100 static u_int64_t dccp_seqno(const struct dccp_hdr *dh) 101 { 102 u_int32_t seq_high = DCCPH_SEQ(dh); 103 u_int64_t seqno = EXTRACT_24BITS(&seq_high) & 0xFFFFFF; 104 105 if (DCCPH_X(dh) != 0) { 106 const struct dccp_hdr_ext *dhx = (void *)(dh + 1); 107 u_int32_t seq_low = dhx->dccph_seq_low; 108 seqno &= 0x00FFFF; /* clear reserved field */ 109 seqno = (seqno << 32) + EXTRACT_32BITS(&seq_low); 110 } 111 112 return seqno; 113 } 114 115 static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh) 116 { 117 return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0); 118 } 119 120 static void dccp_print_ack_no(const u_char *bp) 121 { 122 const struct dccp_hdr *dh = (const struct dccp_hdr *)bp; 123 const struct dccp_hdr_ack_bits *dh_ack = 124 (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh)); 125 u_int32_t ack_high; 126 u_int64_t ackno; 127 128 TCHECK2(*dh_ack,4); 129 ack_high = DCCPH_ACK(dh_ack); 130 ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF; 131 132 if (DCCPH_X(dh) != 0) { 133 u_int32_t ack_low; 134 135 TCHECK2(*dh_ack,8); 136 ack_low = dh_ack->dccph_ack_nr_low; 137 138 ackno &= 0x00FFFF; /* clear reserved field */ 139 ackno = (ackno << 32) + EXTRACT_32BITS(&ack_low); 140 } 141 142 (void)printf("(ack=%" PRIu64 ") ", ackno); 143 trunc: 144 return; 145 } 146 147 static inline unsigned int dccp_packet_hdr_len(const u_int8_t type) 148 { 149 if (type == DCCP_PKT_DATA) 150 return 0; 151 if (type == DCCP_PKT_DATAACK || 152 type == DCCP_PKT_ACK || 153 type == DCCP_PKT_SYNC || 154 type == DCCP_PKT_SYNCACK || 155 type == DCCP_PKT_CLOSE || 156 type == DCCP_PKT_CLOSEREQ) 157 return sizeof(struct dccp_hdr_ack_bits); 158 if (type == DCCP_PKT_REQUEST) 159 return sizeof(struct dccp_hdr_request); 160 if (type == DCCP_PKT_RESPONSE) 161 return sizeof(struct dccp_hdr_response); 162 return sizeof(struct dccp_hdr_reset); 163 } 164 165 static int dccp_print_option(const u_char *option); 166 167 /** 168 * dccp_print - show dccp packet 169 * @bp - beginning of dccp packet 170 * @data2 - beginning of enclosing 171 * @len - lenght of ip packet 172 */ 173 void dccp_print(const u_char *bp, const u_char *data2, u_int len) 174 { 175 const struct dccp_hdr *dh; 176 const struct ip *ip; 177 #ifdef INET6 178 const struct ip6_hdr *ip6; 179 #endif 180 const u_char *cp; 181 u_short sport, dport; 182 u_int hlen; 183 u_int extlen = 0; 184 185 dh = (const struct dccp_hdr *)bp; 186 187 ip = (struct ip *)data2; 188 #ifdef INET6 189 if (IP_V(ip) == 6) 190 ip6 = (const struct ip6_hdr *)data2; 191 else 192 ip6 = NULL; 193 #endif /*INET6*/ 194 cp = (const u_char *)(dh + 1); 195 if (cp > snapend) { 196 printf("[Invalid packet|dccp]"); 197 return; 198 } 199 200 if (len < sizeof(struct dccp_hdr)) { 201 printf("truncated-dccp - %ld bytes missing!", 202 (long)len - sizeof(struct dccp_hdr)); 203 return; 204 } 205 206 sport = EXTRACT_16BITS(&dh->dccph_sport); 207 dport = EXTRACT_16BITS(&dh->dccph_dport); 208 hlen = dh->dccph_doff * 4; 209 210 #ifdef INET6 211 if (ip6) { 212 (void)printf("%s.%d > %s.%d: ", 213 ip6addr_string(&ip6->ip6_src), sport, 214 ip6addr_string(&ip6->ip6_dst), dport); 215 } else 216 #endif /*INET6*/ 217 { 218 (void)printf("%s.%d > %s.%d: ", 219 ipaddr_string(&ip->ip_src), sport, 220 ipaddr_string(&ip->ip_dst), dport); 221 } 222 fflush(stdout); 223 224 if (qflag) { 225 (void)printf(" %d", len - hlen); 226 if (hlen > len) { 227 (void)printf("dccp [bad hdr length %u - too long, > %u]", 228 hlen, len); 229 } 230 return; 231 } 232 233 /* other variables in generic header */ 234 if (vflag) { 235 (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); 236 } 237 238 /* checksum calculation */ 239 if (vflag && TTEST2(bp[0], len)) { 240 u_int16_t sum = 0, dccp_sum; 241 242 dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); 243 (void)printf("cksum 0x%04x ", dccp_sum); 244 if (IP_V(ip) == 4) 245 sum = dccp_cksum(ip, dh, len); 246 #ifdef INET6 247 else if (IP_V(ip) == 6) 248 sum = dccp6_cksum(ip6, dh, len); 249 #endif 250 if (sum != 0) 251 (void)printf("(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); 252 else 253 (void)printf("(correct), "); 254 } 255 256 switch (DCCPH_TYPE(dh)) { 257 case DCCP_PKT_REQUEST: { 258 struct dccp_hdr_request *dhr = 259 (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh)); 260 TCHECK(*dhr); 261 (void)printf("request (service=%d) ", 262 EXTRACT_32BITS(&dhr->dccph_req_service)); 263 extlen += 4; 264 break; 265 } 266 case DCCP_PKT_RESPONSE: { 267 struct dccp_hdr_response *dhr = 268 (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh)); 269 TCHECK(*dhr); 270 (void)printf("response (service=%d) ", 271 EXTRACT_32BITS(&dhr->dccph_resp_service)); 272 extlen += 12; 273 break; 274 } 275 case DCCP_PKT_DATA: 276 (void)printf("data "); 277 break; 278 case DCCP_PKT_ACK: { 279 (void)printf("ack "); 280 extlen += 8; 281 break; 282 } 283 case DCCP_PKT_DATAACK: { 284 (void)printf("dataack "); 285 extlen += 8; 286 break; 287 } 288 case DCCP_PKT_CLOSEREQ: 289 (void)printf("closereq "); 290 extlen += 8; 291 break; 292 case DCCP_PKT_CLOSE: 293 (void)printf("close "); 294 extlen += 8; 295 break; 296 case DCCP_PKT_RESET: { 297 struct dccp_hdr_reset *dhr = 298 (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh)); 299 TCHECK(*dhr); 300 (void)printf("reset (code=%s) ", 301 dccp_reset_code(dhr->dccph_reset_code)); 302 extlen += 12; 303 break; 304 } 305 case DCCP_PKT_SYNC: 306 (void)printf("sync "); 307 extlen += 8; 308 break; 309 case DCCP_PKT_SYNCACK: 310 (void)printf("syncack "); 311 extlen += 8; 312 break; 313 default: 314 (void)printf("invalid "); 315 break; 316 } 317 318 if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && 319 (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST)) 320 dccp_print_ack_no(bp); 321 322 if (vflag < 2) 323 return; 324 325 (void)printf("seq %" PRIu64, dccp_seqno(dh)); 326 327 /* process options */ 328 if (hlen > dccp_basic_hdr_len(dh) + extlen){ 329 const u_char *cp; 330 u_int optlen; 331 cp = bp + dccp_basic_hdr_len(dh) + extlen; 332 printf(" <"); 333 334 hlen -= dccp_basic_hdr_len(dh) + extlen; 335 while(1){ 336 TCHECK(*cp); 337 optlen = dccp_print_option(cp); 338 if (!optlen) goto trunc2; 339 if (hlen <= optlen) break; 340 hlen -= optlen; 341 cp += optlen; 342 printf(", "); 343 } 344 printf(">"); 345 } 346 return; 347 trunc: 348 printf("[|dccp]"); 349 trunc2: 350 return; 351 } 352 353 static int dccp_print_option(const u_char *option) 354 { 355 u_int8_t optlen, i; 356 357 TCHECK(*option); 358 359 if (*option >= 32) { 360 TCHECK(*(option+1)); 361 optlen = *(option +1); 362 if (optlen < 2) { 363 printf("Option %d optlen too short",*option); 364 return 1; 365 } 366 } else optlen = 1; 367 368 TCHECK2(*option,optlen); 369 370 switch (*option){ 371 case 0: 372 printf("nop"); 373 break; 374 case 1: 375 printf("mandatory"); 376 break; 377 case 2: 378 printf("slowreceiver"); 379 break; 380 case 32: 381 printf("change_l"); 382 if (*(option +2) < 10){ 383 printf(" %s", dccp_feature_nums[*(option +2)]); 384 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 385 } 386 break; 387 case 33: 388 printf("confirm_l"); 389 if (*(option +2) < 10){ 390 printf(" %s", dccp_feature_nums[*(option +2)]); 391 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 392 } 393 break; 394 case 34: 395 printf("change_r"); 396 if (*(option +2) < 10){ 397 printf(" %s", dccp_feature_nums[*(option +2)]); 398 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 399 } 400 break; 401 case 35: 402 printf("confirm_r"); 403 if (*(option +2) < 10){ 404 printf(" %s", dccp_feature_nums[*(option +2)]); 405 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 406 } 407 break; 408 case 36: 409 printf("initcookie 0x"); 410 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 411 break; 412 case 37: 413 printf("ndp_count"); 414 for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i)); 415 break; 416 case 38: 417 printf("ack_vector0 0x"); 418 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 419 break; 420 case 39: 421 printf("ack_vector1 0x"); 422 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 423 break; 424 case 40: 425 printf("data_dropped 0x"); 426 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 427 break; 428 case 41: 429 printf("timestamp %u", EXTRACT_32BITS(option + 2)); 430 break; 431 case 42: 432 printf("timestamp_echo %u", EXTRACT_32BITS(option + 2)); 433 break; 434 case 43: 435 printf("elapsed_time "); 436 if (optlen == 6) 437 printf("%u", EXTRACT_32BITS(option + 2)); 438 else 439 printf("%u", EXTRACT_16BITS(option + 2)); 440 break; 441 case 44: 442 printf("data_checksum "); 443 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 444 break; 445 default : 446 if (*option >= 128) { 447 printf("CCID option %d",*option); 448 switch (optlen) { 449 case 4: 450 printf(" %u", EXTRACT_16BITS(option + 2)); 451 break; 452 case 6: 453 printf(" %u", EXTRACT_32BITS(option + 2)); 454 break; 455 default: 456 break; 457 } 458 break; 459 } 460 461 printf("unknown_opt %d", *option); 462 break; 463 } 464 465 return optlen; 466 trunc: 467 printf("[|dccp]"); 468 return 0; 469 } 470