/** * dccp_print - show dccp packet * @bp - beginning of dccp packet * @data2 - beginning of enclosing * @len - length of ip packet */ void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, u_int len) { const struct dccp_hdr *dh; const struct ip *ip; const struct ip6_hdr *ip6; const u_char *cp; u_short sport, dport; u_int hlen; u_int fixed_hdrlen; uint8_t dccph_type; ndo->ndo_protocol = "dccp"; dh = (const struct dccp_hdr *)bp; ip = (const struct ip *)data2; if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)data2; else ip6 = NULL; /* make sure we have enough data to look at the X bit */ cp = (const u_char *)(dh + 1); if (cp > ndo->ndo_snapend) goto trunc; if (len < sizeof(struct dccp_hdr)) { ND_PRINT("truncated-dccp - %u bytes missing!", (u_int)sizeof(struct dccp_hdr) - len); return; } /* get the length of the generic header */ fixed_hdrlen = dccp_basic_hdr_len(ndo, dh); if (len < fixed_hdrlen) { ND_PRINT("truncated-dccp - %u bytes missing!", fixed_hdrlen - len); return; } ND_TCHECK_LEN(dh, fixed_hdrlen); sport = GET_BE_U_2(dh->dccph_sport); dport = GET_BE_U_2(dh->dccph_dport); hlen = GET_U_1(dh->dccph_doff) * 4; if (ip6) { ND_PRINT("%s.%u > %s.%u: ", ip6addr_string(ndo, ip6->ip6_src), sport, ip6addr_string(ndo, ip6->ip6_dst), dport); } else { ND_PRINT("%s.%u > %s.%u: ", ipaddr_string(ndo, ip->ip_src), sport, ipaddr_string(ndo, ip->ip_dst), dport); } ND_PRINT("DCCP"); if (ndo->ndo_qflag) { ND_PRINT(" %u", len - hlen); if (hlen > len) { ND_PRINT(" [bad hdr length %u - too long, > %u]", hlen, len); } return; } /* other variables in generic header */ if (ndo->ndo_vflag) { ND_PRINT(" (CCVal %u, CsCov %u, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); } /* checksum calculation */ if (ndo->ndo_vflag && ND_TTEST_LEN(bp, len)) { uint16_t sum = 0, dccp_sum; dccp_sum = GET_BE_U_2(dh->dccph_checksum); ND_PRINT("cksum 0x%04x ", dccp_sum); if (IP_V(ip) == 4) sum = dccp_cksum(ndo, ip, dh, len); else if (IP_V(ip) == 6) sum = dccp6_cksum(ndo, ip6, dh, len); if (sum != 0) ND_PRINT("(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum)); else ND_PRINT("(correct)"); } if (ndo->ndo_vflag) ND_PRINT(")"); ND_PRINT(" "); dccph_type = DCCPH_TYPE(dh); switch (dccph_type) { case DCCP_PKT_REQUEST: { const struct dccp_hdr_request *dhr = (const struct dccp_hdr_request *)(bp + fixed_hdrlen); fixed_hdrlen += 4; if (len < fixed_hdrlen) { ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), fixed_hdrlen - len); return; } ND_TCHECK_SIZE(dhr); ND_PRINT("%s (service=%u) ", tok2str(dccp_pkt_type_str, "", dccph_type), GET_BE_U_4(dhr->dccph_req_service)); break; } case DCCP_PKT_RESPONSE: { const struct dccp_hdr_response *dhr = (const struct dccp_hdr_response *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), fixed_hdrlen - len); return; } ND_TCHECK_SIZE(dhr); ND_PRINT("%s (service=%u) ", tok2str(dccp_pkt_type_str, "", dccph_type), GET_BE_U_4(dhr->dccph_resp_service)); break; } case DCCP_PKT_DATA: ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; case DCCP_PKT_ACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), fixed_hdrlen - len); return; } ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; } case DCCP_PKT_DATAACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), fixed_hdrlen - len); return; } ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; } case DCCP_PKT_CLOSEREQ: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), fixed_hdrlen - len); return; } ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; case DCCP_PKT_CLOSE: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), fixed_hdrlen - len); return; } ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; case DCCP_PKT_RESET: { const struct dccp_hdr_reset *dhr = (const struct dccp_hdr_reset *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), fixed_hdrlen - len); return; } ND_TCHECK_SIZE(dhr); ND_PRINT("%s (code=%s) ", tok2str(dccp_pkt_type_str, "", dccph_type), dccp_reset_code(GET_U_1(dhr->dccph_reset_code))); break; } case DCCP_PKT_SYNC: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), fixed_hdrlen - len); return; } ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; case DCCP_PKT_SYNCACK: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), fixed_hdrlen - len); return; } ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; default: ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "unknown-type-%u", dccph_type)); break; } if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST)) dccp_print_ack_no(ndo, bp); if (ndo->ndo_vflag < 2) return; ND_PRINT("seq %" PRIu64, dccp_seqno(ndo, bp)); /* process options */ if (hlen > fixed_hdrlen){ u_int optlen; cp = bp + fixed_hdrlen; ND_PRINT(" <"); hlen -= fixed_hdrlen; while(1){ optlen = dccp_print_option(ndo, cp, hlen); if (!optlen) break; if (hlen <= optlen) break; hlen -= optlen; cp += optlen; ND_PRINT(", "); } ND_PRINT(">"); } return; trunc: nd_print_trunc(ndo); return; }
/** * dccp_print - show dccp packet * @bp - beginning of dccp packet * @data2 - beginning of enclosing * @len - lenght of ip packet */ void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, u_int len) { const struct dccp_hdr *dh; const struct ip *ip; #ifdef INET6 const struct ip6_hdr *ip6; #endif const u_char *cp; u_short sport, dport; u_int hlen; u_int fixed_hdrlen; dh = (const struct dccp_hdr *)bp; ip = (struct ip *)data2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)data2; else ip6 = NULL; #endif /*INET6*/ /* make sure we have enough data to look at the X bit */ cp = (const u_char *)(dh + 1); if (cp > ndo->ndo_snapend) { ND_PRINT((ndo, "[Invalid packet|dccp]")); return; } if (len < sizeof(struct dccp_hdr)) { ND_PRINT((ndo, "truncated-dccp - %u bytes missing!", len - (u_int)sizeof(struct dccp_hdr))); return; } /* get the length of the generic header */ fixed_hdrlen = dccp_basic_hdr_len(dh); if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp - %u bytes missing!", len - fixed_hdrlen)); return; } ND_TCHECK2(*dh, fixed_hdrlen); sport = EXTRACT_16BITS(&dh->dccph_sport); dport = EXTRACT_16BITS(&dh->dccph_dport); hlen = dh->dccph_doff * 4; #ifdef INET6 if (ip6) { ND_PRINT((ndo, "%s.%d > %s.%d: ", ip6addr_string(ndo, &ip6->ip6_src), sport, ip6addr_string(ndo, &ip6->ip6_dst), dport)); } else #endif /*INET6*/ { ND_PRINT((ndo, "%s.%d > %s.%d: ", ipaddr_string(ndo, &ip->ip_src), sport, ipaddr_string(ndo, &ip->ip_dst), dport)); } if (ndo->ndo_qflag) { ND_PRINT((ndo, " %d", len - hlen)); if (hlen > len) { ND_PRINT((ndo, "dccp [bad hdr length %u - too long, > %u]", hlen, len)); } return; } /* other variables in generic header */ if (ndo->ndo_vflag) { ND_PRINT((ndo, "CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh))); } /* checksum calculation */ if (ndo->ndo_vflag && ND_TTEST2(bp[0], len)) { u_int16_t sum = 0, dccp_sum; dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); ND_PRINT((ndo, "cksum 0x%04x ", dccp_sum)); if (IP_V(ip) == 4) sum = dccp_cksum(ndo, ip, dh, len); #ifdef INET6 else if (IP_V(ip) == 6) sum = dccp6_cksum(ip6, dh, len); #endif if (sum != 0) ND_PRINT((ndo, "(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum))); else ND_PRINT((ndo, "(correct), ")); } switch (DCCPH_TYPE(dh)) { case DCCP_PKT_REQUEST: { struct dccp_hdr_request *dhr = (struct dccp_hdr_request *)(bp + fixed_hdrlen); fixed_hdrlen += 4; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp request - %u bytes missing!", len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "request (service=%d) ", EXTRACT_32BITS(&dhr->dccph_req_service))); break; } case DCCP_PKT_RESPONSE: { struct dccp_hdr_response *dhr = (struct dccp_hdr_response *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp response - %u bytes missing!", len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "response (service=%d) ", EXTRACT_32BITS(&dhr->dccph_resp_service))); break; } case DCCP_PKT_DATA: ND_PRINT((ndo, "data ")); break; case DCCP_PKT_ACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp ack - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "ack ")); break; } case DCCP_PKT_DATAACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp dataack - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "dataack ")); break; } case DCCP_PKT_CLOSEREQ: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp closereq - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "closereq ")); break; case DCCP_PKT_CLOSE: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp close - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "close ")); break; case DCCP_PKT_RESET: { struct dccp_hdr_reset *dhr = (struct dccp_hdr_reset *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp reset - %u bytes missing!", len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "reset (code=%s) ", dccp_reset_code(dhr->dccph_reset_code))); break; } case DCCP_PKT_SYNC: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp sync - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "sync ")); break; case DCCP_PKT_SYNCACK: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp syncack - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "syncack ")); break; default: ND_PRINT((ndo, "invalid ")); break; } if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST)) dccp_print_ack_no(ndo, bp); if (ndo->ndo_vflag < 2) return; ND_PRINT((ndo, "seq %" PRIu64, dccp_seqno(bp))); /* process options */ if (hlen > fixed_hdrlen){ const u_char *cp; u_int optlen; cp = bp + fixed_hdrlen; ND_PRINT((ndo, " <")); hlen -= fixed_hdrlen; while(1){ optlen = dccp_print_option(ndo, cp, hlen); if (!optlen) break; if (hlen <= optlen) break; hlen -= optlen; cp += optlen; ND_PRINT((ndo, ", ")); } ND_PRINT((ndo, ">")); } return; trunc: ND_PRINT((ndo, "%s", tstr)); return; }
/** * dccp_print - show dccp packet * @bp - beginning of dccp packet * @data2 - beginning of enclosing * @len - lenght of ip packet */ void dccp_print(const u_char *bp, const u_char *data2, u_int len) { const struct dccp_hdr *dh; const struct ip *ip; #ifdef INET6 const struct ip6_hdr *ip6; #endif const u_char *cp; u_short sport, dport; u_int hlen; u_int extlen = 0; dh = (const struct dccp_hdr *)bp; ip = (struct ip *)data2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)data2; else ip6 = NULL; #endif /*INET6*/ cp = (const u_char *)(dh + 1); if (cp > snapend) { printf("[Invalid packet|dccp]"); return; } if (len < sizeof(struct dccp_hdr)) { printf("truncated-dccp - %ld bytes missing!", (long)len - sizeof(struct dccp_hdr)); return; } sport = EXTRACT_16BITS(&dh->dccph_sport); dport = EXTRACT_16BITS(&dh->dccph_dport); hlen = dh->dccph_doff * 4; #ifdef INET6 if (ip6) { (void)printf("%s.%d > %s.%d: ", ip6addr_string(&ip6->ip6_src), sport, ip6addr_string(&ip6->ip6_dst), dport); } else #endif /*INET6*/ { (void)printf("%s.%d > %s.%d: ", ipaddr_string(&ip->ip_src), sport, ipaddr_string(&ip->ip_dst), dport); } fflush(stdout); if (qflag) { (void)printf(" %d", len - hlen); if (hlen > len) { (void)printf("dccp [bad hdr length %u - too long, > %u]", hlen, len); } return; } /* other variables in generic header */ if (vflag) { (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); } /* checksum calculation */ if (vflag && TTEST2(bp[0], len)) { u_int16_t sum = 0, dccp_sum; dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); (void)printf("cksum 0x%04x ", dccp_sum); if (IP_V(ip) == 4) sum = dccp_cksum(ip, dh, len); #ifdef INET6 else if (IP_V(ip) == 6) sum = dccp6_cksum(ip6, dh, len); #endif if (sum != 0) (void)printf("(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); else (void)printf("(correct), "); } switch (DCCPH_TYPE(dh)) { case DCCP_PKT_REQUEST: { struct dccp_hdr_request *dhr = (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh)); TCHECK(*dhr); (void)printf("request (service=%d) ", EXTRACT_32BITS(&dhr->dccph_req_service)); extlen += 4; break; } case DCCP_PKT_RESPONSE: { struct dccp_hdr_response *dhr = (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh)); TCHECK(*dhr); (void)printf("response (service=%d) ", EXTRACT_32BITS(&dhr->dccph_resp_service)); extlen += 12; break; } case DCCP_PKT_DATA: (void)printf("data "); break; case DCCP_PKT_ACK: { (void)printf("ack "); extlen += 8; break; } case DCCP_PKT_DATAACK: { (void)printf("dataack "); extlen += 8; break; } case DCCP_PKT_CLOSEREQ: (void)printf("closereq "); extlen += 8; break; case DCCP_PKT_CLOSE: (void)printf("close "); extlen += 8; break; case DCCP_PKT_RESET: { struct dccp_hdr_reset *dhr = (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh)); TCHECK(*dhr); (void)printf("reset (code=%s) ", dccp_reset_code(dhr->dccph_reset_code)); extlen += 12; break; } case DCCP_PKT_SYNC: (void)printf("sync "); extlen += 8; break; case DCCP_PKT_SYNCACK: (void)printf("syncack "); extlen += 8; break; default: (void)printf("invalid "); break; } if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST)) dccp_print_ack_no(bp); if (vflag < 2) return; (void)printf("seq %" PRIu64, dccp_seqno(dh)); /* process options */ if (hlen > dccp_basic_hdr_len(dh) + extlen){ const u_char *cp; u_int optlen; cp = bp + dccp_basic_hdr_len(dh) + extlen; printf(" <"); hlen -= dccp_basic_hdr_len(dh) + extlen; while(1){ TCHECK(*cp); optlen = dccp_print_option(cp); if (!optlen) goto trunc2; if (hlen <= optlen) break; hlen -= optlen; cp += optlen; printf(", "); } printf(">"); } return; trunc: printf("%s", tstr); trunc2: return; }