print-dccp.c revision 190207
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_ = 12190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-dccp.c,v 1.7.2.1 2007-11-09 00:45:16 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 u_int32_t *ts; 398162017Ssam u_int16_t *var16; 399162017Ssam u_int32_t *var32; 400162017Ssam 401162017Ssam TCHECK(*option); 402162017Ssam 403162017Ssam if (*option >= 32) { 404162017Ssam TCHECK(*(option+1)); 405162017Ssam optlen = *(option +1); 406162017Ssam if (optlen < 2) { 407162017Ssam printf("Option %d optlen too short",*option); 408162017Ssam return 1; 409162017Ssam } 410162017Ssam } else optlen = 1; 411162017Ssam 412162017Ssam TCHECK2(*option,optlen); 413162017Ssam 414162017Ssam switch (*option){ 415162017Ssam case 0: 416162017Ssam printf("nop"); 417162017Ssam break; 418162017Ssam case 1: 419162017Ssam printf("mandatory"); 420162017Ssam break; 421162017Ssam case 2: 422162017Ssam printf("slowreceiver"); 423162017Ssam break; 424162017Ssam case 32: 425162017Ssam printf("change_l"); 426162017Ssam if (*(option +2) < 10){ 427162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 428162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 429162017Ssam } 430162017Ssam break; 431162017Ssam case 33: 432162017Ssam printf("confirm_l"); 433162017Ssam if (*(option +2) < 10){ 434162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 435162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 436162017Ssam } 437162017Ssam break; 438162017Ssam case 34: 439162017Ssam printf("change_r"); 440162017Ssam if (*(option +2) < 10){ 441162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 442162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 443162017Ssam } 444162017Ssam break; 445162017Ssam case 35: 446162017Ssam printf("confirm_r"); 447162017Ssam if (*(option +2) < 10){ 448162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 449162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 450162017Ssam } 451162017Ssam break; 452162017Ssam case 36: 453162017Ssam printf("initcookie 0x"); 454162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 455162017Ssam break; 456162017Ssam case 37: 457162017Ssam printf("ndp_count"); 458162017Ssam for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i)); 459162017Ssam break; 460162017Ssam case 38: 461162017Ssam printf("ack_vector0 0x"); 462162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 463162017Ssam break; 464162017Ssam case 39: 465162017Ssam printf("ack_vector1 0x"); 466162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 467162017Ssam break; 468162017Ssam case 40: 469162017Ssam printf("data_dropped 0x"); 470162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 471162017Ssam break; 472162017Ssam case 41: 473162017Ssam ts = (u_int32_t *)(option + 2); 474162017Ssam printf("timestamp %u", (u_int32_t)ntohl(*ts)); 475162017Ssam break; 476162017Ssam case 42: 477162017Ssam ts = (u_int32_t *)(option + 2); 478162017Ssam printf("timestamp_echo %u", (u_int32_t)ntohl(*ts)); 479162017Ssam break; 480162017Ssam case 43: 481162017Ssam printf("elapsed_time "); 482162017Ssam if (optlen == 6){ 483162017Ssam ts = (u_int32_t *)(option + 2); 484162017Ssam printf("%u", (u_int32_t)ntohl(*ts)); 485162017Ssam } else { 486162017Ssam var16 = (u_int16_t *)(option + 2); 487162017Ssam printf("%u", ntohs(*var16)); 488162017Ssam } 489162017Ssam break; 490162017Ssam case 44: 491162017Ssam printf("data_checksum "); 492162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 493162017Ssam break; 494162017Ssam default : 495162017Ssam if (*option >= 128) { 496162017Ssam printf("CCID option %d",*option); 497162017Ssam switch (optlen) { 498162017Ssam case 4: 499162017Ssam var16 = (u_int16_t *)(option + 2); 500162017Ssam printf(" %u",ntohs(*var16)); 501162017Ssam break; 502162017Ssam case 6: 503162017Ssam var32 = (u_int32_t *)(option + 2); 504162017Ssam printf(" %u",(u_int32_t)ntohl(*var32)); 505162017Ssam break; 506162017Ssam default: 507162017Ssam break; 508162017Ssam } 509162017Ssam break; 510162017Ssam } 511162017Ssam 512162017Ssam printf("unknown_opt %d", *option); 513162017Ssam break; 514162017Ssam } 515162017Ssam 516162017Ssam return optlen; 517162017Ssamtrunc: 518162017Ssam printf("[|dccp]"); 519162017Ssam return 0; 520162017Ssam} 521