print-dccp.c revision 172683
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_ = 12172683Smlaier "@(#) $Header: /tcpdump/master/tcpdump/print-dccp.c,v 1.1.2.6 2006/02/19 05:08:44 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 63162017Ssamstatic int dccp_cksum(const struct ip *ip, 64162017Ssam const struct dccp_hdr *dh, u_int len) 65162017Ssam{ 66162017Ssam union phu { 67162017Ssam struct phdr { 68162017Ssam u_int32_t src; 69162017Ssam u_int32_t dst; 70162017Ssam u_char mbz; 71162017Ssam u_char proto; 72162017Ssam u_int16_t len; 73162017Ssam } ph; 74162017Ssam u_int16_t pa[6]; 75162017Ssam } phu; 76162017Ssam const u_int16_t *sp; 77162017Ssam 78162017Ssam /* pseudo-header.. */ 79162017Ssam phu.ph.mbz = 0; 80162017Ssam phu.ph.len = htons(len); 81162017Ssam phu.ph.proto = IPPROTO_DCCP; 82162017Ssam memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); 83162017Ssam if (IP_HL(ip) == 5) 84162017Ssam memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); 85162017Ssam else 86162017Ssam phu.ph.dst = ip_finddst(ip); 87162017Ssam 88162017Ssam sp = &phu.pa[0]; 89162017Ssam return in_cksum((u_short *)dh, len, sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]); 90162017Ssam} 91162017Ssam 92162017Ssam#ifdef INET6 93162017Ssamstatic int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len) 94162017Ssam{ 95162017Ssam size_t i; 96162017Ssam const u_int16_t *sp; 97162017Ssam u_int32_t sum; 98162017Ssam union { 99162017Ssam struct { 100162017Ssam struct in6_addr ph_src; 101162017Ssam struct in6_addr ph_dst; 102162017Ssam u_int32_t ph_len; 103162017Ssam u_int8_t ph_zero[3]; 104162017Ssam u_int8_t ph_nxt; 105162017Ssam } ph; 106162017Ssam u_int16_t pa[20]; 107162017Ssam } phu; 108162017Ssam 109162017Ssam /* pseudo-header */ 110162017Ssam memset(&phu, 0, sizeof(phu)); 111162017Ssam phu.ph.ph_src = ip6->ip6_src; 112162017Ssam phu.ph.ph_dst = ip6->ip6_dst; 113162017Ssam phu.ph.ph_len = htonl(len); 114162017Ssam phu.ph.ph_nxt = IPPROTO_DCCP; 115162017Ssam 116162017Ssam sum = 0; 117162017Ssam for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) 118162017Ssam sum += phu.pa[i]; 119162017Ssam 120162017Ssam sp = (const u_int16_t *)dh; 121162017Ssam 122162017Ssam for (i = 0; i < (len & ~1); i += 2) 123162017Ssam sum += *sp++; 124162017Ssam 125162017Ssam if (len & 1) 126162017Ssam sum += htons((*(const u_int8_t *)sp) << 8); 127162017Ssam 128162017Ssam while (sum > 0xffff) 129162017Ssam sum = (sum & 0xffff) + (sum >> 16); 130162017Ssam sum = ~sum & 0xffff; 131162017Ssam 132162017Ssam return (sum); 133162017Ssam} 134162017Ssam#endif 135162017Ssam 136162017Ssamstatic const char *dccp_reset_code(u_int8_t code) 137162017Ssam{ 138162017Ssam if (code >= __DCCP_RESET_CODE_LAST) 139162017Ssam return "invalid"; 140162017Ssam return dccp_reset_codes[code]; 141162017Ssam} 142162017Ssam 143162017Ssamstatic u_int64_t dccp_seqno(const struct dccp_hdr *dh) 144162017Ssam{ 145162017Ssam u_int32_t seq_high = DCCPH_SEQ(dh); 146162017Ssam u_int64_t seqno = EXTRACT_24BITS(&seq_high) & 0xFFFFFF; 147162017Ssam 148162017Ssam if (DCCPH_X(dh) != 0) { 149172683Smlaier const struct dccp_hdr_ext *dhx = (void *)(dh + 1); 150162017Ssam u_int32_t seq_low = dhx->dccph_seq_low; 151162017Ssam seqno &= 0x00FFFF; /* clear reserved field */ 152162017Ssam seqno = (seqno << 32) + EXTRACT_32BITS(&seq_low); 153162017Ssam } 154162017Ssam 155162017Ssam return seqno; 156162017Ssam} 157162017Ssam 158172683Smlaierstatic inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh) 159162017Ssam{ 160172683Smlaier return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0); 161172683Smlaier} 162162017Ssam 163172683Smlaierstatic void dccp_print_ack_no(const u_char *bp) 164172683Smlaier{ 165172683Smlaier const struct dccp_hdr *dh = (const struct dccp_hdr *)bp; 166172683Smlaier const struct dccp_hdr_ack_bits *dh_ack = 167172683Smlaier (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh)); 168172683Smlaier u_int32_t ack_high; 169172683Smlaier u_int64_t ackno; 170172683Smlaier 171172683Smlaier TCHECK2(*dh_ack,4); 172172683Smlaier ack_high = DCCPH_ACK(dh_ack); 173172683Smlaier ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF; 174172683Smlaier 175162017Ssam if (DCCPH_X(dh) != 0) { 176172683Smlaier u_int32_t ack_low; 177172683Smlaier 178172683Smlaier TCHECK2(*dh_ack,8); 179172683Smlaier ack_low = dh_ack->dccph_ack_nr_low; 180172683Smlaier 181162017Ssam ackno &= 0x00FFFF; /* clear reserved field */ 182162017Ssam ackno = (ackno << 32) + EXTRACT_32BITS(&ack_low); 183162017Ssam } 184162017Ssam 185172683Smlaier (void)printf("(ack=%" PRIu64 ") ", ackno); 186172683Smlaiertrunc: 187172683Smlaier return; 188162017Ssam} 189162017Ssam 190162017Ssamstatic inline unsigned int dccp_packet_hdr_len(const u_int8_t type) 191162017Ssam{ 192162017Ssam if (type == DCCP_PKT_DATA) 193162017Ssam return 0; 194162017Ssam if (type == DCCP_PKT_DATAACK || 195162017Ssam type == DCCP_PKT_ACK || 196162017Ssam type == DCCP_PKT_SYNC || 197162017Ssam type == DCCP_PKT_SYNCACK || 198162017Ssam type == DCCP_PKT_CLOSE || 199162017Ssam type == DCCP_PKT_CLOSEREQ) 200162017Ssam return sizeof(struct dccp_hdr_ack_bits); 201162017Ssam if (type == DCCP_PKT_REQUEST) 202162017Ssam return sizeof(struct dccp_hdr_request); 203162017Ssam if (type == DCCP_PKT_RESPONSE) 204162017Ssam return sizeof(struct dccp_hdr_response); 205162017Ssam return sizeof(struct dccp_hdr_reset); 206162017Ssam} 207162017Ssam 208162017Ssamstatic int dccp_print_option(const u_char *option); 209162017Ssam 210162017Ssam/** 211162017Ssam * dccp_print - show dccp packet 212162017Ssam * @bp - beginning of dccp packet 213162017Ssam * @data2 - beginning of enclosing 214162017Ssam * @len - lenght of ip packet 215162017Ssam */ 216162017Ssamvoid dccp_print(const u_char *bp, const u_char *data2, u_int len) 217162017Ssam{ 218162017Ssam const struct dccp_hdr *dh; 219162017Ssam const struct ip *ip; 220162017Ssam#ifdef INET6 221162017Ssam const struct ip6_hdr *ip6; 222162017Ssam#endif 223162017Ssam const u_char *cp; 224162017Ssam u_short sport, dport; 225162017Ssam u_int hlen; 226162017Ssam u_int extlen = 0; 227162017Ssam 228162017Ssam dh = (const struct dccp_hdr *)bp; 229162017Ssam 230162017Ssam ip = (struct ip *)data2; 231162017Ssam#ifdef INET6 232162017Ssam if (IP_V(ip) == 6) 233162017Ssam ip6 = (const struct ip6_hdr *)data2; 234162017Ssam else 235162017Ssam ip6 = NULL; 236162017Ssam#endif /*INET6*/ 237162017Ssam cp = (const u_char *)(dh + 1); 238162017Ssam if (cp > snapend) { 239162017Ssam printf("[Invalid packet|dccp]"); 240162017Ssam return; 241162017Ssam } 242162017Ssam 243162017Ssam if (len < sizeof(struct dccp_hdr)) { 244162017Ssam printf("truncated-dccp - %ld bytes missing!", 245162017Ssam (long)len - sizeof(struct dccp_hdr)); 246162017Ssam return; 247162017Ssam } 248162017Ssam 249162017Ssam sport = EXTRACT_16BITS(&dh->dccph_sport); 250162017Ssam dport = EXTRACT_16BITS(&dh->dccph_dport); 251162017Ssam hlen = dh->dccph_doff * 4; 252162017Ssam 253162017Ssam#ifdef INET6 254162017Ssam if (ip6) { 255162017Ssam (void)printf("%s.%d > %s.%d: ", 256162017Ssam ip6addr_string(&ip6->ip6_src), sport, 257162017Ssam ip6addr_string(&ip6->ip6_dst), dport); 258162017Ssam } else 259162017Ssam#endif /*INET6*/ 260162017Ssam { 261162017Ssam (void)printf("%s.%d > %s.%d: ", 262162017Ssam ipaddr_string(&ip->ip_src), sport, 263162017Ssam ipaddr_string(&ip->ip_dst), dport); 264162017Ssam } 265162017Ssam fflush(stdout); 266162017Ssam 267162017Ssam if (qflag) { 268162017Ssam (void)printf(" %d", len - hlen); 269162017Ssam if (hlen > len) { 270162017Ssam (void)printf("dccp [bad hdr length %u - too long, > %u]", 271162017Ssam hlen, len); 272162017Ssam } 273162017Ssam return; 274162017Ssam } 275162017Ssam 276162017Ssam /* other variables in generic header */ 277162017Ssam if (vflag) { 278162017Ssam (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); 279162017Ssam } 280162017Ssam 281162017Ssam /* checksum calculation */ 282162017Ssam#ifdef INET6 283162017Ssam if (ip6) { 284162017Ssam if (ip6->ip6_plen && vflag) { 285162017Ssam u_int16_t sum, dccp_sum; 286162017Ssam 287162017Ssam sum = dccp6_cksum(ip6, dh, len); 288162017Ssam dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); 289162017Ssam printf("cksum 0x%04x", dccp_sum); 290162017Ssam if (sum != 0) { 291162017Ssam (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); 292162017Ssam } else 293162017Ssam (void)printf(" (correct), "); 294162017Ssam } 295162017Ssam } else 296162017Ssam#endif /* INET6 */ 297162017Ssam if (vflag) 298162017Ssam { 299162017Ssam u_int16_t sum, dccp_sum; 300162017Ssam 301162017Ssam sum = dccp_cksum(ip, dh, len); 302162017Ssam dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); 303162017Ssam printf("cksum 0x%04x", dccp_sum); 304162017Ssam if (sum != 0) { 305162017Ssam (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); 306162017Ssam } else 307162017Ssam (void)printf(" (correct), "); 308162017Ssam } 309162017Ssam 310162017Ssam switch (DCCPH_TYPE(dh)) { 311162017Ssam case DCCP_PKT_REQUEST: { 312162017Ssam struct dccp_hdr_request *dhr = 313162017Ssam (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh)); 314162017Ssam TCHECK(*dhr); 315172683Smlaier (void)printf("request (service=%d) ", 316172683Smlaier EXTRACT_32BITS(&dhr->dccph_req_service)); 317162017Ssam extlen += 4; 318162017Ssam break; 319162017Ssam } 320162017Ssam case DCCP_PKT_RESPONSE: { 321162017Ssam struct dccp_hdr_response *dhr = 322162017Ssam (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh)); 323162017Ssam TCHECK(*dhr); 324172683Smlaier (void)printf("response (service=%d) ", 325172683Smlaier EXTRACT_32BITS(&dhr->dccph_resp_service)); 326162017Ssam extlen += 12; 327162017Ssam break; 328162017Ssam } 329162017Ssam case DCCP_PKT_DATA: 330162017Ssam (void)printf("data "); 331162017Ssam break; 332162017Ssam case DCCP_PKT_ACK: { 333172683Smlaier (void)printf("ack "); 334162017Ssam extlen += 8; 335162017Ssam break; 336162017Ssam } 337162017Ssam case DCCP_PKT_DATAACK: { 338172683Smlaier (void)printf("dataack "); 339162017Ssam extlen += 8; 340162017Ssam break; 341162017Ssam } 342162017Ssam case DCCP_PKT_CLOSEREQ: 343162017Ssam (void)printf("closereq "); 344162017Ssam extlen += 8; 345162017Ssam break; 346162017Ssam case DCCP_PKT_CLOSE: 347162017Ssam (void)printf("close "); 348162017Ssam extlen += 8; 349162017Ssam break; 350162017Ssam case DCCP_PKT_RESET: { 351162017Ssam struct dccp_hdr_reset *dhr = 352162017Ssam (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh)); 353162017Ssam TCHECK(*dhr); 354162017Ssam (void)printf("reset (code=%s) ", 355162017Ssam dccp_reset_code(dhr->dccph_reset_code)); 356162017Ssam extlen += 12; 357162017Ssam break; 358162017Ssam } 359162017Ssam case DCCP_PKT_SYNC: 360162017Ssam (void)printf("sync "); 361162017Ssam extlen += 8; 362162017Ssam break; 363162017Ssam case DCCP_PKT_SYNCACK: 364162017Ssam (void)printf("syncack "); 365162017Ssam extlen += 8; 366162017Ssam break; 367162017Ssam default: 368162017Ssam (void)printf("invalid "); 369162017Ssam break; 370162017Ssam } 371162017Ssam 372172683Smlaier if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && 373172683Smlaier (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST)) 374172683Smlaier dccp_print_ack_no(bp); 375172683Smlaier 376162017Ssam if (vflag < 2) 377162017Ssam return; 378162017Ssam 379162017Ssam (void)printf("seq %" PRIu64, dccp_seqno(dh)); 380162017Ssam 381162017Ssam /* process options */ 382162017Ssam if (hlen > dccp_basic_hdr_len(dh) + extlen){ 383162017Ssam const u_char *cp; 384162017Ssam u_int optlen; 385162017Ssam cp = bp + dccp_basic_hdr_len(dh) + extlen; 386162017Ssam printf(" <"); 387162017Ssam 388162017Ssam hlen -= dccp_basic_hdr_len(dh) + extlen; 389162017Ssam while(1){ 390162017Ssam TCHECK(*cp); 391162017Ssam optlen = dccp_print_option(cp); 392162017Ssam if (!optlen) goto trunc2; 393162017Ssam if (hlen <= optlen) break; 394162017Ssam hlen -= optlen; 395162017Ssam cp += optlen; 396162017Ssam printf(", "); 397162017Ssam } 398162017Ssam printf(">"); 399162017Ssam } 400162017Ssam return; 401162017Ssamtrunc: 402162017Ssam printf("[|dccp]"); 403162017Ssamtrunc2: 404162017Ssam return; 405162017Ssam} 406162017Ssam 407162017Ssamstatic int dccp_print_option(const u_char *option) 408162017Ssam{ 409162017Ssam u_int8_t optlen, i; 410162017Ssam u_int32_t *ts; 411162017Ssam u_int16_t *var16; 412162017Ssam u_int32_t *var32; 413162017Ssam 414162017Ssam TCHECK(*option); 415162017Ssam 416162017Ssam if (*option >= 32) { 417162017Ssam TCHECK(*(option+1)); 418162017Ssam optlen = *(option +1); 419162017Ssam if (optlen < 2) { 420162017Ssam printf("Option %d optlen too short",*option); 421162017Ssam return 1; 422162017Ssam } 423162017Ssam } else optlen = 1; 424162017Ssam 425162017Ssam TCHECK2(*option,optlen); 426162017Ssam 427162017Ssam switch (*option){ 428162017Ssam case 0: 429162017Ssam printf("nop"); 430162017Ssam break; 431162017Ssam case 1: 432162017Ssam printf("mandatory"); 433162017Ssam break; 434162017Ssam case 2: 435162017Ssam printf("slowreceiver"); 436162017Ssam break; 437162017Ssam case 32: 438162017Ssam printf("change_l"); 439162017Ssam if (*(option +2) < 10){ 440162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 441162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 442162017Ssam } 443162017Ssam break; 444162017Ssam case 33: 445162017Ssam printf("confirm_l"); 446162017Ssam if (*(option +2) < 10){ 447162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 448162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 449162017Ssam } 450162017Ssam break; 451162017Ssam case 34: 452162017Ssam printf("change_r"); 453162017Ssam if (*(option +2) < 10){ 454162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 455162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 456162017Ssam } 457162017Ssam break; 458162017Ssam case 35: 459162017Ssam printf("confirm_r"); 460162017Ssam if (*(option +2) < 10){ 461162017Ssam printf(" %s", dccp_feature_nums[*(option +2)]); 462162017Ssam for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i)); 463162017Ssam } 464162017Ssam break; 465162017Ssam case 36: 466162017Ssam printf("initcookie 0x"); 467162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 468162017Ssam break; 469162017Ssam case 37: 470162017Ssam printf("ndp_count"); 471162017Ssam for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i)); 472162017Ssam break; 473162017Ssam case 38: 474162017Ssam printf("ack_vector0 0x"); 475162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 476162017Ssam break; 477162017Ssam case 39: 478162017Ssam printf("ack_vector1 0x"); 479162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 480162017Ssam break; 481162017Ssam case 40: 482162017Ssam printf("data_dropped 0x"); 483162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 484162017Ssam break; 485162017Ssam case 41: 486162017Ssam ts = (u_int32_t *)(option + 2); 487162017Ssam printf("timestamp %u", (u_int32_t)ntohl(*ts)); 488162017Ssam break; 489162017Ssam case 42: 490162017Ssam ts = (u_int32_t *)(option + 2); 491162017Ssam printf("timestamp_echo %u", (u_int32_t)ntohl(*ts)); 492162017Ssam break; 493162017Ssam case 43: 494162017Ssam printf("elapsed_time "); 495162017Ssam if (optlen == 6){ 496162017Ssam ts = (u_int32_t *)(option + 2); 497162017Ssam printf("%u", (u_int32_t)ntohl(*ts)); 498162017Ssam } else { 499162017Ssam var16 = (u_int16_t *)(option + 2); 500162017Ssam printf("%u", ntohs(*var16)); 501162017Ssam } 502162017Ssam break; 503162017Ssam case 44: 504162017Ssam printf("data_checksum "); 505162017Ssam for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); 506162017Ssam break; 507162017Ssam default : 508162017Ssam if (*option >= 128) { 509162017Ssam printf("CCID option %d",*option); 510162017Ssam switch (optlen) { 511162017Ssam case 4: 512162017Ssam var16 = (u_int16_t *)(option + 2); 513162017Ssam printf(" %u",ntohs(*var16)); 514162017Ssam break; 515162017Ssam case 6: 516162017Ssam var32 = (u_int32_t *)(option + 2); 517162017Ssam printf(" %u",(u_int32_t)ntohl(*var32)); 518162017Ssam break; 519162017Ssam default: 520162017Ssam break; 521162017Ssam } 522162017Ssam break; 523162017Ssam } 524162017Ssam 525162017Ssam printf("unknown_opt %d", *option); 526162017Ssam break; 527162017Ssam } 528162017Ssam 529162017Ssam return optlen; 530162017Ssamtrunc: 531162017Ssam printf("[|dccp]"); 532162017Ssam return 0; 533162017Ssam} 534