print-dccp.c revision 214478
1162017Ssam/* 2162017Ssam * Copyright (C) Arnaldo Carvalho de Melo 2004 3162017Ssam * Copyright (C) Ian McDonald 2005 4162017Ssam * Copyright (C) Yoshifumi Nishida 2005 5162017Ssam * 6162017Ssam * This software may be distributed either under the terms of the 7162017Ssam * BSD-style license that accompanies tcpdump or the GNU GPL version 2 8162017Ssam */ 9162017Ssam 10162017Ssam#ifndef lint 11162017Ssamstatic const char rcsid[] _U_ = 12214478Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-dccp.c,v 1.8 2007-11-09 00:44:09 guy Exp $ (LBL)"; 13162017Ssam#endif 14162017Ssam 15162017Ssam#ifdef HAVE_CONFIG_H 16162017Ssam#include "config.h" 17162017Ssam#endif 18162017Ssam 19162017Ssam#include <tcpdump-stdinc.h> 20162017Ssam 21162017Ssam#include "dccp.h" 22162017Ssam 23162017Ssam#include <stdio.h> 24162017Ssam#include <string.h> 25162017Ssam 26162017Ssam#include "interface.h" 27162017Ssam#include "addrtoname.h" 28162017Ssam#include "extract.h" /* must come after interface.h */ 29162017Ssam#include "ip.h" 30162017Ssam#ifdef INET6 31162017Ssam#include "ip6.h" 32162017Ssam#endif 33162017Ssam#include "ipproto.h" 34162017Ssam 35162017Ssamstatic const char *dccp_reset_codes[] = { 36162017Ssam "unspecified", 37162017Ssam "closed", 38162017Ssam "aborted", 39162017Ssam "no_connection", 40162017Ssam "packet_error", 41162017Ssam "option_error", 42162017Ssam "mandatory_error", 43162017Ssam "connection_refused", 44162017Ssam "bad_service_code", 45162017Ssam "too_busy", 46162017Ssam "bad_init_cookie", 47162017Ssam "aggression_penalty", 48162017Ssam}; 49162017Ssam 50162017Ssamstatic const char *dccp_feature_nums[] = { 51162017Ssam "reserved", 52162017Ssam "ccid", 53162017Ssam "allow_short_seqno", 54162017Ssam "sequence_window", 55162017Ssam "ecn_incapable", 56162017Ssam "ack_ratio", 57162017Ssam "send_ack_vector", 58162017Ssam "send_ndp_count", 59162017Ssam "minimum checksum coverage", 60162017Ssam "check data checksum", 61162017Ssam}; 62162017Ssam 63190207Srpaulostatic inline int dccp_csum_coverage(const struct dccp_hdr* dh, u_int len) 64190207Srpaulo{ 65190207Srpaulo u_int cov; 66190207Srpaulo 67190207Srpaulo if (DCCPH_CSCOV(dh) == 0) 68190207Srpaulo return len; 69190207Srpaulo cov = (dh->dccph_doff + DCCPH_CSCOV(dh) - 1) * sizeof(u_int32_t); 70190207Srpaulo return (cov > len)? len : cov; 71190207Srpaulo} 72190207Srpaulo 73162017Ssamstatic int dccp_cksum(const struct ip *ip, 74162017Ssam const struct dccp_hdr *dh, u_int len) 75162017Ssam{ 76190207Srpaulo int cov = dccp_csum_coverage(dh, len); 77162017Ssam union phu { 78162017Ssam struct phdr { 79162017Ssam u_int32_t src; 80162017Ssam u_int32_t dst; 81162017Ssam u_char mbz; 82162017Ssam u_char proto; 83162017Ssam u_int16_t len; 84162017Ssam } ph; 85162017Ssam u_int16_t pa[6]; 86162017Ssam } phu; 87162017Ssam const u_int16_t *sp; 88162017Ssam 89162017Ssam /* pseudo-header.. */ 90162017Ssam phu.ph.mbz = 0; 91162017Ssam phu.ph.len = htons(len); 92162017Ssam phu.ph.proto = IPPROTO_DCCP; 93162017Ssam memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); 94162017Ssam if (IP_HL(ip) == 5) 95162017Ssam memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); 96162017Ssam else 97162017Ssam phu.ph.dst = ip_finddst(ip); 98162017Ssam 99162017Ssam sp = &phu.pa[0]; 100190207Srpaulo return in_cksum((u_short *)dh, cov, sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]); 101162017Ssam} 102162017Ssam 103162017Ssam#ifdef INET6 104162017Ssamstatic int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len) 105162017Ssam{ 106162017Ssam size_t i; 107190207Srpaulo u_int32_t sum = 0; 108190207Srpaulo int cov = dccp_csum_coverage(dh, len); 109162017Ssam union { 110162017Ssam struct { 111162017Ssam struct in6_addr ph_src; 112162017Ssam struct in6_addr ph_dst; 113162017Ssam u_int32_t ph_len; 114162017Ssam u_int8_t ph_zero[3]; 115162017Ssam u_int8_t ph_nxt; 116162017Ssam } ph; 117162017Ssam u_int16_t pa[20]; 118162017Ssam } phu; 119162017Ssam 120162017Ssam /* pseudo-header */ 121162017Ssam memset(&phu, 0, sizeof(phu)); 122162017Ssam phu.ph.ph_src = ip6->ip6_src; 123162017Ssam phu.ph.ph_dst = ip6->ip6_dst; 124162017Ssam phu.ph.ph_len = htonl(len); 125162017Ssam phu.ph.ph_nxt = IPPROTO_DCCP; 126162017Ssam 127162017Ssam for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) 128162017Ssam sum += phu.pa[i]; 129162017Ssam 130190207Srpaulo return in_cksum((u_short *)dh, cov, sum); 131162017Ssam} 132162017Ssam#endif 133162017Ssam 134162017Ssamstatic const char *dccp_reset_code(u_int8_t code) 135162017Ssam{ 136162017Ssam if (code >= __DCCP_RESET_CODE_LAST) 137162017Ssam return "invalid"; 138162017Ssam return dccp_reset_codes[code]; 139162017Ssam} 140162017Ssam 141162017Ssamstatic u_int64_t dccp_seqno(const struct dccp_hdr *dh) 142162017Ssam{ 143162017Ssam u_int32_t seq_high = DCCPH_SEQ(dh); 144162017Ssam u_int64_t seqno = EXTRACT_24BITS(&seq_high) & 0xFFFFFF; 145162017Ssam 146162017Ssam if (DCCPH_X(dh) != 0) { 147172683Smlaier const struct dccp_hdr_ext *dhx = (void *)(dh + 1); 148162017Ssam u_int32_t seq_low = dhx->dccph_seq_low; 149162017Ssam seqno &= 0x00FFFF; /* clear reserved field */ 150162017Ssam seqno = (seqno << 32) + EXTRACT_32BITS(&seq_low); 151162017Ssam } 152162017Ssam 153162017Ssam return seqno; 154162017Ssam} 155162017Ssam 156172683Smlaierstatic inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh) 157162017Ssam{ 158172683Smlaier return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0); 159172683Smlaier} 160162017Ssam 161172683Smlaierstatic void dccp_print_ack_no(const u_char *bp) 162172683Smlaier{ 163172683Smlaier const struct dccp_hdr *dh = (const struct dccp_hdr *)bp; 164172683Smlaier const struct dccp_hdr_ack_bits *dh_ack = 165172683Smlaier (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh)); 166172683Smlaier u_int32_t ack_high; 167172683Smlaier u_int64_t ackno; 168172683Smlaier 169172683Smlaier TCHECK2(*dh_ack,4); 170172683Smlaier ack_high = DCCPH_ACK(dh_ack); 171172683Smlaier ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF; 172172683Smlaier 173162017Ssam if (DCCPH_X(dh) != 0) { 174172683Smlaier u_int32_t ack_low; 175172683Smlaier 176172683Smlaier TCHECK2(*dh_ack,8); 177172683Smlaier ack_low = dh_ack->dccph_ack_nr_low; 178172683Smlaier 179162017Ssam ackno &= 0x00FFFF; /* clear reserved field */ 180162017Ssam ackno = (ackno << 32) + EXTRACT_32BITS(&ack_low); 181162017Ssam } 182162017Ssam 183172683Smlaier (void)printf("(ack=%" PRIu64 ") ", ackno); 184172683Smlaiertrunc: 185172683Smlaier return; 186162017Ssam} 187162017Ssam 188162017Ssamstatic inline unsigned int dccp_packet_hdr_len(const u_int8_t type) 189162017Ssam{ 190162017Ssam if (type == DCCP_PKT_DATA) 191162017Ssam return 0; 192162017Ssam if (type == DCCP_PKT_DATAACK || 193162017Ssam type == DCCP_PKT_ACK || 194162017Ssam type == DCCP_PKT_SYNC || 195162017Ssam type == DCCP_PKT_SYNCACK || 196162017Ssam type == DCCP_PKT_CLOSE || 197162017Ssam type == DCCP_PKT_CLOSEREQ) 198162017Ssam return sizeof(struct dccp_hdr_ack_bits); 199162017Ssam if (type == DCCP_PKT_REQUEST) 200162017Ssam return sizeof(struct dccp_hdr_request); 201162017Ssam if (type == DCCP_PKT_RESPONSE) 202162017Ssam return sizeof(struct dccp_hdr_response); 203162017Ssam return sizeof(struct dccp_hdr_reset); 204162017Ssam} 205162017Ssam 206162017Ssamstatic int dccp_print_option(const u_char *option); 207162017Ssam 208162017Ssam/** 209162017Ssam * dccp_print - show dccp packet 210162017Ssam * @bp - beginning of dccp packet 211162017Ssam * @data2 - beginning of enclosing 212162017Ssam * @len - lenght of ip packet 213162017Ssam */ 214162017Ssamvoid dccp_print(const u_char *bp, const u_char *data2, u_int len) 215162017Ssam{ 216162017Ssam const struct dccp_hdr *dh; 217162017Ssam const struct ip *ip; 218162017Ssam#ifdef INET6 219162017Ssam const struct ip6_hdr *ip6; 220162017Ssam#endif 221162017Ssam const u_char *cp; 222162017Ssam u_short sport, dport; 223162017Ssam u_int hlen; 224162017Ssam u_int extlen = 0; 225162017Ssam 226162017Ssam dh = (const struct dccp_hdr *)bp; 227162017Ssam 228162017Ssam ip = (struct ip *)data2; 229162017Ssam#ifdef INET6 230162017Ssam if (IP_V(ip) == 6) 231162017Ssam ip6 = (const struct ip6_hdr *)data2; 232162017Ssam else 233162017Ssam ip6 = NULL; 234162017Ssam#endif /*INET6*/ 235162017Ssam cp = (const u_char *)(dh + 1); 236162017Ssam if (cp > snapend) { 237162017Ssam printf("[Invalid packet|dccp]"); 238162017Ssam return; 239162017Ssam } 240162017Ssam 241162017Ssam if (len < sizeof(struct dccp_hdr)) { 242162017Ssam printf("truncated-dccp - %ld bytes missing!", 243162017Ssam (long)len - sizeof(struct dccp_hdr)); 244162017Ssam return; 245162017Ssam } 246162017Ssam 247162017Ssam sport = EXTRACT_16BITS(&dh->dccph_sport); 248162017Ssam dport = EXTRACT_16BITS(&dh->dccph_dport); 249162017Ssam hlen = dh->dccph_doff * 4; 250162017Ssam 251162017Ssam#ifdef INET6 252162017Ssam if (ip6) { 253162017Ssam (void)printf("%s.%d > %s.%d: ", 254162017Ssam ip6addr_string(&ip6->ip6_src), sport, 255162017Ssam ip6addr_string(&ip6->ip6_dst), dport); 256162017Ssam } else 257162017Ssam#endif /*INET6*/ 258162017Ssam { 259162017Ssam (void)printf("%s.%d > %s.%d: ", 260162017Ssam ipaddr_string(&ip->ip_src), sport, 261162017Ssam ipaddr_string(&ip->ip_dst), dport); 262162017Ssam } 263162017Ssam fflush(stdout); 264162017Ssam 265162017Ssam if (qflag) { 266162017Ssam (void)printf(" %d", len - hlen); 267162017Ssam if (hlen > len) { 268162017Ssam (void)printf("dccp [bad hdr length %u - too long, > %u]", 269162017Ssam hlen, len); 270162017Ssam } 271162017Ssam return; 272162017Ssam } 273162017Ssam 274162017Ssam /* other variables in generic header */ 275162017Ssam if (vflag) { 276162017Ssam (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); 277162017Ssam } 278162017Ssam 279162017Ssam /* checksum calculation */ 280190207Srpaulo if (vflag && TTEST2(bp[0], len)) { 281190207Srpaulo u_int16_t sum = 0, dccp_sum; 282190207Srpaulo 283190207Srpaulo dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); 284190207Srpaulo (void)printf("cksum 0x%04x ", dccp_sum); 285190207Srpaulo if (IP_V(ip) == 4) 286190207Srpaulo sum = dccp_cksum(ip, dh, len); 287162017Ssam#ifdef INET6 288190207Srpaulo else if (IP_V(ip) == 6) 289162017Ssam sum = dccp6_cksum(ip6, dh, len); 290190207Srpaulo#endif 291190207Srpaulo if (sum != 0) 292190207Srpaulo (void)printf("(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); 293190207Srpaulo else 294190207Srpaulo (void)printf("(correct), "); 295162017Ssam } 296162017Ssam 297162017Ssam switch (DCCPH_TYPE(dh)) { 298162017Ssam case DCCP_PKT_REQUEST: { 299162017Ssam struct dccp_hdr_request *dhr = 300162017Ssam (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh)); 301162017Ssam TCHECK(*dhr); 302172683Smlaier (void)printf("request (service=%d) ", 303172683Smlaier EXTRACT_32BITS(&dhr->dccph_req_service)); 304162017Ssam extlen += 4; 305162017Ssam break; 306162017Ssam } 307162017Ssam case DCCP_PKT_RESPONSE: { 308162017Ssam struct dccp_hdr_response *dhr = 309162017Ssam (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh)); 310162017Ssam TCHECK(*dhr); 311172683Smlaier (void)printf("response (service=%d) ", 312172683Smlaier EXTRACT_32BITS(&dhr->dccph_resp_service)); 313162017Ssam extlen += 12; 314162017Ssam break; 315162017Ssam } 316162017Ssam case DCCP_PKT_DATA: 317162017Ssam (void)printf("data "); 318162017Ssam break; 319162017Ssam case DCCP_PKT_ACK: { 320172683Smlaier (void)printf("ack "); 321162017Ssam extlen += 8; 322162017Ssam break; 323162017Ssam } 324162017Ssam case DCCP_PKT_DATAACK: { 325172683Smlaier (void)printf("dataack "); 326162017Ssam extlen += 8; 327162017Ssam break; 328162017Ssam } 329162017Ssam case DCCP_PKT_CLOSEREQ: 330162017Ssam (void)printf("closereq "); 331162017Ssam extlen += 8; 332162017Ssam break; 333162017Ssam case DCCP_PKT_CLOSE: 334162017Ssam (void)printf("close "); 335162017Ssam extlen += 8; 336162017Ssam break; 337162017Ssam case DCCP_PKT_RESET: { 338162017Ssam struct dccp_hdr_reset *dhr = 339162017Ssam (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh)); 340162017Ssam TCHECK(*dhr); 341162017Ssam (void)printf("reset (code=%s) ", 342162017Ssam dccp_reset_code(dhr->dccph_reset_code)); 343162017Ssam extlen += 12; 344162017Ssam break; 345162017Ssam } 346162017Ssam case DCCP_PKT_SYNC: 347162017Ssam (void)printf("sync "); 348162017Ssam extlen += 8; 349162017Ssam break; 350162017Ssam case DCCP_PKT_SYNCACK: 351162017Ssam (void)printf("syncack "); 352162017Ssam extlen += 8; 353162017Ssam break; 354162017Ssam default: 355162017Ssam (void)printf("invalid "); 356162017Ssam break; 357162017Ssam } 358162017Ssam 359172683Smlaier if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && 360172683Smlaier (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST)) 361172683Smlaier dccp_print_ack_no(bp); 362172683Smlaier 363162017Ssam if (vflag < 2) 364162017Ssam return; 365162017Ssam 366162017Ssam (void)printf("seq %" PRIu64, dccp_seqno(dh)); 367162017Ssam 368162017Ssam /* process options */ 369162017Ssam if (hlen > dccp_basic_hdr_len(dh) + extlen){ 370162017Ssam const u_char *cp; 371162017Ssam u_int optlen; 372162017Ssam cp = bp + dccp_basic_hdr_len(dh) + extlen; 373162017Ssam printf(" <"); 374162017Ssam 375162017Ssam hlen -= dccp_basic_hdr_len(dh) + extlen; 376162017Ssam while(1){ 377162017Ssam TCHECK(*cp); 378162017Ssam optlen = dccp_print_option(cp); 379162017Ssam if (!optlen) goto trunc2; 380162017Ssam if (hlen <= optlen) break; 381162017Ssam hlen -= optlen; 382162017Ssam cp += optlen; 383162017Ssam printf(", "); 384162017Ssam } 385162017Ssam printf(">"); 386162017Ssam } 387162017Ssam return; 388162017Ssamtrunc: 389162017Ssam printf("[|dccp]"); 390162017Ssamtrunc2: 391162017Ssam return; 392162017Ssam} 393162017Ssam 394162017Ssamstatic int dccp_print_option(const u_char *option) 395162017Ssam{ 396162017Ssam u_int8_t optlen, i; 397162017Ssam 398162017Ssam TCHECK(*option); 399162017Ssam 400162017Ssam if (*option >= 32) { 401162017Ssam TCHECK(*(option+1)); 402162017Ssam optlen = *(option +1); 403162017Ssam if (optlen < 2) { 404162017Ssam printf("Option %d optlen too short",*option); 405162017Ssam return 1; 406162017Ssam } 407162017Ssam } else optlen = 1; 408162017Ssam 409162017Ssam TCHECK2(*option,optlen); 410162017Ssam 411162017Ssam switch (*option){ 412162017Ssam case 0: 413162017Ssam printf("nop"); 414162017Ssam break; 415162017Ssam case 1: 416162017Ssam printf("mandatory"); 417162017Ssam break; 418162017Ssam case 2: 419162017Ssam printf("slowreceiver"); 420162017Ssam break; 421162017Ssam case 32: 422162017Ssam printf("change_l"); 423162017Ssam if (*(option +2) < 10){ 424162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 425162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 426162017Ssam } 427162017Ssam break; 428162017Ssam case 33: 429162017Ssam printf("confirm_l"); 430162017Ssam if (*(option +2) < 10){ 431162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 432162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 433162017Ssam } 434162017Ssam break; 435162017Ssam case 34: 436162017Ssam printf("change_r"); 437162017Ssam if (*(option +2) < 10){ 438162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 439162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 440162017Ssam } 441162017Ssam break; 442162017Ssam case 35: 443162017Ssam printf("confirm_r"); 444162017Ssam if (*(option +2) < 10){ 445162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 446162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 447162017Ssam } 448162017Ssam break; 449162017Ssam case 36: 450162017Ssam printf("initcookie 0x"); 451162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 452162017Ssam break; 453162017Ssam case 37: 454162017Ssam printf("ndp_count"); 455162017Ssam for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i)); 456162017Ssam break; 457162017Ssam case 38: 458162017Ssam printf("ack_vector0 0x"); 459162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 460162017Ssam break; 461162017Ssam case 39: 462162017Ssam printf("ack_vector1 0x"); 463162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 464162017Ssam break; 465162017Ssam case 40: 466162017Ssam printf("data_dropped 0x"); 467162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 468162017Ssam break; 469162017Ssam case 41: 470214478Srpaulo printf("timestamp %u", EXTRACT_32BITS(option + 2)); 471162017Ssam break; 472162017Ssam case 42: 473214478Srpaulo printf("timestamp_echo %u", EXTRACT_32BITS(option + 2)); 474162017Ssam break; 475162017Ssam case 43: 476162017Ssam printf("elapsed_time "); 477214478Srpaulo if (optlen == 6) 478214478Srpaulo printf("%u", EXTRACT_32BITS(option + 2)); 479214478Srpaulo else 480214478Srpaulo printf("%u", EXTRACT_16BITS(option + 2)); 481162017Ssam break; 482162017Ssam case 44: 483162017Ssam printf("data_checksum "); 484162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 485162017Ssam break; 486162017Ssam default : 487162017Ssam if (*option >= 128) { 488162017Ssam printf("CCID option %d",*option); 489162017Ssam switch (optlen) { 490162017Ssam case 4: 491214478Srpaulo printf(" %u", EXTRACT_16BITS(option + 2)); 492162017Ssam break; 493162017Ssam case 6: 494214478Srpaulo printf(" %u", EXTRACT_32BITS(option + 2)); 495162017Ssam break; 496162017Ssam default: 497162017Ssam break; 498162017Ssam } 499162017Ssam break; 500162017Ssam } 501162017Ssam 502162017Ssam printf("unknown_opt %d", *option); 503162017Ssam break; 504162017Ssam } 505162017Ssam 506162017Ssam return optlen; 507162017Ssamtrunc: 508162017Ssam printf("[|dccp]"); 509162017Ssam return 0; 510162017Ssam} 511