/* * Print ntp requests */ void ntp_print(register const u_char *cp, u_int length) { register const struct ntpdata *bp; int mode, version, leapind; bp = (struct ntpdata *)cp; TCHECK(bp->status); version = (int)(bp->status & VERSIONMASK) >> 3; printf("NTPv%d", version); mode = bp->status & MODEMASK; if (!vflag) { printf (", %s, length %u", tok2str(ntp_mode_values, "Unknown mode", mode), length); return; } printf (", length %u\n\t%s", length, tok2str(ntp_mode_values, "Unknown mode", mode)); leapind = bp->status & LEAPMASK; printf (", Leap indicator: %s (%u)", tok2str(ntp_leapind_values, "Unknown", leapind), leapind); TCHECK(bp->stratum); printf(", Stratum %u (%s)", bp->stratum, tok2str(ntp_stratum_values, (bp->stratum >=2 && bp->stratum<=15) ? "secondary reference" : "reserved", bp->stratum)); TCHECK(bp->ppoll); printf(", poll %u (%us)", bp->ppoll, 1 << bp->ppoll); /* Can't TCHECK bp->precision bitfield so bp->distance + 0 instead */ TCHECK2(bp->root_delay, 0); printf(", precision %d", bp->precision); TCHECK(bp->root_delay); fputs("\n\tRoot Delay: ", stdout); p_sfix(&bp->root_delay); TCHECK(bp->root_dispersion); fputs(", Root dispersion: ", stdout); p_sfix(&bp->root_dispersion); TCHECK(bp->refid); fputs(", Reference-ID: ", stdout); /* Interpretation depends on stratum */ switch (bp->stratum) { case UNSPECIFIED: printf("(unspec)"); break; case PRIM_REF: if (fn_printn((u_char *)&(bp->refid), 4, snapend)) goto trunc; break; case INFO_QUERY: printf("%s INFO_QUERY", ipaddr_string(&(bp->refid))); /* this doesn't have more content */ return; case INFO_REPLY: printf("%s INFO_REPLY", ipaddr_string(&(bp->refid))); /* this is too complex to be worth printing */ return; default: printf("%s", ipaddr_string(&(bp->refid))); break; } TCHECK(bp->ref_timestamp); fputs("\n\t Reference Timestamp: ", stdout); p_ntp_time(&(bp->ref_timestamp)); TCHECK(bp->org_timestamp); fputs("\n\t Originator Timestamp: ", stdout); p_ntp_time(&(bp->org_timestamp)); TCHECK(bp->rec_timestamp); fputs("\n\t Receive Timestamp: ", stdout); p_ntp_time(&(bp->rec_timestamp)); TCHECK(bp->xmt_timestamp); fputs("\n\t Transmit Timestamp: ", stdout); p_ntp_time(&(bp->xmt_timestamp)); fputs("\n\t Originator - Receive Timestamp: ", stdout); p_ntp_delta(&(bp->org_timestamp), &(bp->rec_timestamp)); fputs("\n\t Originator - Transmit Timestamp: ", stdout); p_ntp_delta(&(bp->org_timestamp), &(bp->xmt_timestamp)); if ( (sizeof(struct ntpdata) - length) == 16) { /* Optional: key-id */ TCHECK(bp->key_id); printf("\n\tKey id: %u", bp->key_id); } else if ( (sizeof(struct ntpdata) - length) == 0) { /* Optional: key-id + authentication */ TCHECK(bp->key_id); printf("\n\tKey id: %u", bp->key_id); TCHECK2(bp->message_digest, sizeof (bp->message_digest)); printf("\n\tAuthentication: %08x%08x%08x%08x", EXTRACT_32BITS(bp->message_digest), EXTRACT_32BITS(bp->message_digest + 4), EXTRACT_32BITS(bp->message_digest + 8), EXTRACT_32BITS(bp->message_digest + 12)); } return; trunc: fputs(" [|ntp]", stdout); }
void tcp_print(register const u_char *bp, register u_int length, register const u_char *bp2, int fragmented) { register const struct tcphdr *tp; register const struct ip *ip; register u_char flags; register u_int hlen; register char ch; u_int16_t sport, dport, win, urp; u_int32_t seq, ack, thseq, thack; u_int utoval; int threv; #ifdef INET6 register const struct ip6_hdr *ip6; #endif tp = (struct tcphdr *)bp; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (struct ip6_hdr *)bp2; else ip6 = NULL; #endif /*INET6*/ ch = '\0'; if (!TTEST(tp->th_dport)) { (void)printf("%s > %s: [|tcp]", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); return; } sport = EXTRACT_16BITS(&tp->th_sport); dport = EXTRACT_16BITS(&tp->th_dport); hlen = TH_OFF(tp) * 4; /* * If data present, header length valid, and NFS port used, * assume NFS. * Pass offset of data plus 4 bytes for RPC TCP msg length * to NFS print routines. */ if (!qflag && hlen >= sizeof(*tp) && hlen <= length && (length - hlen) >= 4) { u_char *fraglenp; u_int32_t fraglen; register struct sunrpc_msg *rp; enum sunrpc_msg_type direction; fraglenp = (u_char *)tp + hlen; if (TTEST2(*fraglenp, 4)) { fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF; if (fraglen > (length - hlen) - 4) fraglen = (length - hlen) - 4; rp = (struct sunrpc_msg *)(fraglenp + 4); if (TTEST(rp->rm_direction)) { direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); if (dport == NFS_PORT && direction == SUNRPC_CALL) { nfsreq_print((u_char *)rp, fraglen, (u_char *)ip); return; } if (sport == NFS_PORT && direction == SUNRPC_REPLY) { nfsreply_print((u_char *)rp, fraglen, (u_char *)ip); return; } } } } #ifdef INET6 if (ip6) { if (ip6->ip6_nxt == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ip6addr_string(&ip6->ip6_src), tcpport_string(sport), ip6addr_string(&ip6->ip6_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } else #endif /*INET6*/ { if (ip->ip_p == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ipaddr_string(&ip->ip_src), tcpport_string(sport), ipaddr_string(&ip->ip_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } if (hlen < sizeof(*tp)) { (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]", length - hlen, hlen, (unsigned long)sizeof(*tp)); return; } TCHECK(*tp); seq = EXTRACT_32BITS(&tp->th_seq); ack = EXTRACT_32BITS(&tp->th_ack); win = EXTRACT_16BITS(&tp->th_win); urp = EXTRACT_16BITS(&tp->th_urp); if (qflag) { (void)printf("tcp %d", length - hlen); if (hlen > length) { (void)printf(" [bad hdr length %u - too long, > %u]", hlen, length); } return; } flags = tp->th_flags; printf("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); if (!Sflag && (flags & TH_ACK)) { register struct tcp_seq_hash *th; const void *src, *dst; register int rev; struct tha tha; /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ #ifdef INET6 rev = 0; if (ip6) { src = &ip6->ip6_src; dst = &ip6->ip6_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0) rev = 1; } if (rev) { memcpy(&tha.src, dst, sizeof ip6->ip6_dst); memcpy(&tha.dst, src, sizeof ip6->ip6_src); tha.port = dport << 16 | sport; } else { memcpy(&tha.dst, dst, sizeof ip6->ip6_dst); memcpy(&tha.src, src, sizeof ip6->ip6_src); tha.port = sport << 16 | dport; } } else { /* * Zero out the tha structure; the src and dst * fields are big enough to hold an IPv6 * address, but we only have IPv4 addresses * and thus must clear out the remaining 124 * bits. * * XXX - should we just clear those bytes after * copying the IPv4 addresses, rather than * zeroing out the entire structure and then * overwriting some of the zeroes? * * XXX - this could fail if we see TCP packets * with an IPv6 address with the lower 124 bits * all zero and also see TCP packes with an * IPv4 address with the same 32 bits as the * upper 32 bits of the IPv6 address in question. * Can that happen? Is it likely enough to be * an issue? */ memset(&tha, 0, sizeof(tha)); src = &ip->ip_src; dst = &ip->ip_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (memcmp(src, dst, sizeof ip->ip_dst) > 0) rev = 1; } if (rev) { memcpy(&tha.src, dst, sizeof ip->ip_dst); memcpy(&tha.dst, src, sizeof ip->ip_src); tha.port = dport << 16 | sport; } else { memcpy(&tha.dst, dst, sizeof ip->ip_dst); memcpy(&tha.src, src, sizeof ip->ip_src); tha.port = sport << 16 | dport; } } #else rev = 0; src = &ip->ip_src; dst = &ip->ip_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (memcmp(src, dst, sizeof ip->ip_dst) > 0) rev = 1; } if (rev) { memcpy(&tha.src, dst, sizeof ip->ip_dst); memcpy(&tha.dst, src, sizeof ip->ip_src); tha.port = dport << 16 | sport; } else { memcpy(&tha.dst, dst, sizeof ip->ip_dst); memcpy(&tha.src, src, sizeof ip->ip_src); tha.port = sport << 16 | dport; } #endif threv = rev; for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } else { /*fool gcc*/ thseq = thack = threv = 0; } if (hlen > length) { (void)printf(" [bad hdr length %u - too long, > %u]", hlen, length); return; } if (IP_V(ip) == 4 && vflag && !Kflag && !fragmented) { u_int16_t sum, tcp_sum; if (TTEST2(tp->th_sport, length)) { sum = tcp_cksum(ip, tp, length); (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" (correct)"); } } #ifdef INET6 if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !Kflag && !fragmented) { u_int16_t sum,tcp_sum; if (TTEST2(tp->th_sport, length)) { sum = nextproto6_cksum(ip6, (u_short *)tp, length, IPPROTO_TCP); (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" (correct)"); } } #endif length -= hlen; if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { (void)printf(", seq %u", seq); if (length > 0) { (void)printf(":%u", seq + length); } } if (flags & TH_ACK) { (void)printf(", ack %u", ack); } (void)printf(", win %d", win); if (flags & TH_URG) (void)printf(", urg %d", urp); /* * Handle any options. */ if (hlen > sizeof(*tp)) { register const u_char *cp; register u_int i, opt, datalen; register u_int len; hlen -= sizeof(*tp); cp = (const u_char *)tp + sizeof(*tp); printf(", options ["); while (hlen > 0) { if (ch != '\0') putchar(ch); TCHECK(*cp); opt = *cp++; if (ZEROLENOPT(opt)) len = 1; else { TCHECK(*cp); len = *cp++; /* total including type, len */ if (len < 2 || len > hlen) goto bad; --hlen; /* account for length byte */ } --hlen; /* account for type byte */ datalen = 0; /* Bail if "l" bytes of data are not left or were not captured */ #define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); } printf("%s", tok2str(tcp_option_values, "Unknown Option %u", opt)); switch (opt) { case TCPOPT_MAXSEG: datalen = 2; LENCHECK(datalen); (void)printf(" %u", EXTRACT_16BITS(cp)); break; case TCPOPT_WSCALE: datalen = 1; LENCHECK(datalen); (void)printf(" %u", *cp); break; case TCPOPT_SACK: datalen = len - 2; if (datalen % 8 != 0) { (void)printf("malformed sack"); } else { u_int32_t s, e; (void)printf(" %d ", datalen / 8); for (i = 0; i < datalen; i += 8) { LENCHECK(i + 4); s = EXTRACT_32BITS(cp + i); LENCHECK(i + 8); e = EXTRACT_32BITS(cp + i + 4); if (threv) { s -= thseq; e -= thseq; } else { s -= thack; e -= thack; } (void)printf("{%u:%u}", s, e); } } break; case TCPOPT_CC: case TCPOPT_CCNEW: case TCPOPT_CCECHO: case TCPOPT_ECHO: case TCPOPT_ECHOREPLY: /* * those options share their semantics. * fall through */ datalen = 4; LENCHECK(datalen); (void)printf(" %u", EXTRACT_32BITS(cp)); break; case TCPOPT_TIMESTAMP: datalen = 8; LENCHECK(datalen); (void)printf(" val %u ecr %u", EXTRACT_32BITS(cp), EXTRACT_32BITS(cp + 4)); break; case TCPOPT_SIGNATURE: datalen = TCP_SIGLEN; LENCHECK(datalen); #ifdef HAVE_LIBCRYPTO switch (tcp_verify_signature(ip, tp, bp + TH_OFF(tp) * 4, length, cp)) { case SIGNATURE_VALID: (void)printf("valid"); break; case SIGNATURE_INVALID: (void)printf("invalid"); break; case CANT_CHECK_SIGNATURE: (void)printf("can't check - "); for (i = 0; i < TCP_SIGLEN; ++i) (void)printf("%02x", cp[i]); break; } #else for (i = 0; i < TCP_SIGLEN; ++i) (void)printf("%02x", cp[i]); #endif break; case TCPOPT_AUTH: (void)printf("keyid %d", *cp++); datalen = len - 3; for (i = 0; i < datalen; ++i) { LENCHECK(i); (void)printf("%02x", cp[i]); } break; case TCPOPT_EOL: case TCPOPT_NOP: case TCPOPT_SACKOK: /* * Nothing interesting. * fall through */ break; case TCPOPT_UTO: datalen = 2; LENCHECK(datalen); utoval = EXTRACT_16BITS(cp); (void)printf("0x%x", utoval); if (utoval & 0x0001) utoval = (utoval >> 1) * 60; else utoval >>= 1; (void)printf(" %u", utoval); break; default: datalen = len - 2; for (i = 0; i < datalen; ++i) { LENCHECK(i); (void)printf("%02x", cp[i]); } break; } /* Account for data printed */ cp += datalen; hlen -= datalen; /* Check specification against observed length */ ++datalen; /* option octet */ if (!ZEROLENOPT(opt)) ++datalen; /* size octet */ if (datalen != len) (void)printf("[len %d]", len); ch = ','; if (opt == TCPOPT_EOL) break; } putchar(']'); }
static void ospf_print_ls_type(register u_int ls_type, register const struct in_addr *ls_stateid, register const struct in_addr *ls_router, register const char *fmt) { switch (ls_type) { case LS_TYPE_ROUTER: printf(" rtr %s ", ipaddr_string(ls_router)); break; case LS_TYPE_NETWORK: printf(" net dr %s if %s", ipaddr_string(ls_router), ipaddr_string(ls_stateid)); break; case LS_TYPE_SUM_IP: printf(" sum %s abr %s", ipaddr_string(ls_stateid), ipaddr_string(ls_router)); break; case LS_TYPE_SUM_ABR: printf(" abr %s rtr %s", ipaddr_string(ls_router), ipaddr_string(ls_stateid)); break; case LS_TYPE_ASE: printf(" ase %s asbr %s", ipaddr_string(ls_stateid), ipaddr_string(ls_router)); break; case LS_TYPE_GROUP: printf(" group %s rtr %s", ipaddr_string(ls_stateid), ipaddr_string(ls_router)); break; default: putchar(' '); printf(fmt, ls_type); break; } }
void eigrp_print(register const u_char *pptr, register u_int len) { const struct eigrp_common_header *eigrp_com_header; const struct eigrp_tlv_header *eigrp_tlv_header; const u_char *tptr,*tlv_tptr; u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length; u_int8_t prefix[4]; union { const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm; const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version; const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int; const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext; const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup; const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int; const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext; } tlv_ptr; tptr=pptr; eigrp_com_header = (const struct eigrp_common_header *)pptr; TCHECK(*eigrp_com_header); /* * Sanity checking of the header. */ if (eigrp_com_header->version != EIGRP_VERSION) { printf("EIGRP version %u packet not supported",eigrp_com_header->version); return; } /* in non-verbose mode just lets print the basic Message Type*/ if (vflag < 1) { printf("EIGRP %s, length: %u", tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode), len); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=len-sizeof(struct eigrp_common_header); /* FIXME print other header info */ printf("\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]\n\tseq: 0x%08x, ack: 0x%08x, AS: %u, length: %u", eigrp_com_header->version, tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode), eigrp_com_header->opcode, EXTRACT_16BITS(&eigrp_com_header->checksum), tok2str(eigrp_common_header_flag_values, "none", EXTRACT_32BITS(&eigrp_com_header->flags)), EXTRACT_32BITS(&eigrp_com_header->seq), EXTRACT_32BITS(&eigrp_com_header->ack), EXTRACT_32BITS(&eigrp_com_header->asn), tlen); tptr+=sizeof(const struct eigrp_common_header); while(tlen>0) { /* did we capture enough for fully decoding the object header ? */ TCHECK2(*tptr, sizeof(struct eigrp_tlv_header)); eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr; eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length); eigrp_tlv_type=EXTRACT_16BITS(&eigrp_tlv_header->type); if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) || eigrp_tlv_len > tlen) { print_unknown_data(tptr+sizeof(sizeof(struct eigrp_tlv_header)),"\n\t ",tlen); return; } printf("\n\t %s TLV (0x%04x), length: %u", tok2str(eigrp_tlv_values, "Unknown", eigrp_tlv_type), eigrp_tlv_type, eigrp_tlv_len); tlv_tptr=tptr+sizeof(struct eigrp_tlv_header); tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header); /* did we capture enough for fully decoding the object ? */ TCHECK2(*tptr, eigrp_tlv_len); switch(eigrp_tlv_type) { case EIGRP_TLV_GENERAL_PARM: tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr; printf("\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u", EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime), tlv_ptr.eigrp_tlv_general_parm->k1, tlv_ptr.eigrp_tlv_general_parm->k2, tlv_ptr.eigrp_tlv_general_parm->k3, tlv_ptr.eigrp_tlv_general_parm->k4, tlv_ptr.eigrp_tlv_general_parm->k5); break; case EIGRP_TLV_SW_VERSION: tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr; printf("\n\t IOS version: %u.%u, EIGRP version %u.%u", tlv_ptr.eigrp_tlv_sw_version->ios_major, tlv_ptr.eigrp_tlv_sw_version->ios_minor, tlv_ptr.eigrp_tlv_sw_version->eigrp_major, tlv_ptr.eigrp_tlv_sw_version->eigrp_minor); break; case EIGRP_TLV_IP_INT: tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr; bit_length = tlv_ptr.eigrp_tlv_ip_int->plen; if (bit_length > 32) { printf("\n\t illegal prefix length %u",bit_length); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length); printf("\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(prefix), bit_length); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0) printf("self"); else printf("%s",ipaddr_string(&tlv_ptr.eigrp_tlv_ip_int->nexthop)); printf("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu), tlv_ptr.eigrp_tlv_ip_int->hopcount, tlv_ptr.eigrp_tlv_ip_int->reliability, tlv_ptr.eigrp_tlv_ip_int->load); break; case EIGRP_TLV_IP_EXT: tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr; bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen; if (bit_length > 32) { printf("\n\t illegal prefix length %u",bit_length); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length); printf("\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(prefix), bit_length); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0) printf("self"); else printf("%s",ipaddr_string(&tlv_ptr.eigrp_tlv_ip_ext->nexthop)); printf("\n\t origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", ipaddr_string(tlv_ptr.eigrp_tlv_ip_ext->origin_router), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id), tlv_ptr.eigrp_tlv_ip_ext->flags, EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric)); printf("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu), tlv_ptr.eigrp_tlv_ip_ext->hopcount, tlv_ptr.eigrp_tlv_ip_ext->reliability, tlv_ptr.eigrp_tlv_ip_ext->load); break; case EIGRP_TLV_AT_CABLE_SETUP: tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr; printf("\n\t Cable-range: %u-%u, Router-ID %u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->router_id)); break; case EIGRP_TLV_AT_INT: tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr; printf("\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end)); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0) printf("self"); else printf("%u.%u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2])); printf("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu), tlv_ptr.eigrp_tlv_at_int->hopcount, tlv_ptr.eigrp_tlv_at_int->reliability, tlv_ptr.eigrp_tlv_at_int->load); break; case EIGRP_TLV_AT_EXT: tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr; printf("\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end)); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0) printf("self"); else printf("%u.%u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2])); printf("\n\t origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id), tlv_ptr.eigrp_tlv_at_ext->flags, EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag), EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric)); printf("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu), tlv_ptr.eigrp_tlv_at_ext->hopcount, tlv_ptr.eigrp_tlv_at_ext->reliability, tlv_ptr.eigrp_tlv_at_ext->load); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case EIGRP_TLV_AUTH: case EIGRP_TLV_SEQ: case EIGRP_TLV_MCAST_SEQ: case EIGRP_TLV_IPX_INT: case EIGRP_TLV_IPX_EXT: default: if (vflag <= 1) print_unknown_data(tlv_tptr,"\n\t ",tlv_tlen); break; } /* do we want to see an additionally hexdump ? */ if (vflag > 1) print_unknown_data(tptr+sizeof(sizeof(struct eigrp_tlv_header)),"\n\t ", eigrp_tlv_len-sizeof(struct eigrp_tlv_header)); tptr+=eigrp_tlv_len; tlen-=eigrp_tlv_len; } return; trunc: printf("\n\t\t packet exceeded snapshot"); }
void msdp_print(const unsigned char *sp, u_int length) { unsigned int type, len; TCHECK2(*sp, 3); /* See if we think we're at the beginning of a compound packet */ type = *sp; len = EXTRACT_16BITS(sp + 1); if (len > 1500 || len < 3 || type == 0 || type > MSDP_TYPE_MAX) goto trunc; /* not really truncated, but still not decodable */ (void)printf(" msdp:"); while (length > 0) { TCHECK2(*sp, 3); type = *sp; len = EXTRACT_16BITS(sp + 1); if (len > 1400 || vflag) printf(" [len %u]", len); if (len < 3) goto trunc; sp += 3; length -= 3; switch (type) { case 1: /* IPv4 Source-Active */ case 3: /* IPv4 Source-Active Response */ if (type == 1) (void)printf(" SA"); else (void)printf(" SA-Response"); TCHECK(*sp); (void)printf(" %u entries", *sp); if ((u_int)((*sp * 12) + 8) < len) { (void)printf(" [w/data]"); if (vflag > 1) { (void)printf(" "); ip_print(gndo, sp + *sp * 12 + 8 - 3, len - (*sp * 12 + 8)); } } break; case 2: (void)printf(" SA-Request"); TCHECK2(*sp, 5); (void)printf(" for %s", ipaddr_string(sp + 1)); break; case 4: (void)printf(" Keepalive"); if (len != 3) (void)printf("[len=%d] ", len); break; case 5: (void)printf(" Notification"); break; default: (void)printf(" [type=%d len=%d]", type, len); break; } sp += (len - 3); length -= (len - 3); } return; trunc: (void)printf(" [|msdp]"); }
static void atmarp_print(netdissect_options *ndo, const u_char *bp, u_int length, u_int caplen) { const struct atmarp_pkthdr *ap; u_short pro, hrd, op; ap = (const struct atmarp_pkthdr *)bp; ND_TCHECK(*ap); hrd = ATMHRD(ap); pro = ATMPRO(ap); op = ATMOP(ap); if (!ND_TTEST2(*aar_tpa(ap), ATMTPROTO_LEN(ap))) { ND_PRINT((ndo, "[|ARP]")); ND_DEFAULTPRINT((const u_char *)ap, length); return; } if (!ndo->ndo_eflag) { ND_PRINT((ndo, "ARP, ")); } if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) || ATMSPROTO_LEN(ap) != 4 || ATMTPROTO_LEN(ap) != 4 || ndo->ndo_vflag) { ND_PRINT((ndo, "%s, %s (len %u/%u)", tok2str(arphrd_values, "Unknown Hardware (%u)", hrd), tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro), ATMSPROTO_LEN(ap), ATMTPROTO_LEN(ap))); /* don't know know about the address formats */ if (!ndo->ndo_vflag) { goto out; } } /* print operation */ printf("%s%s ", ndo->ndo_vflag ? ", " : "", tok2str(arpop_values, "Unknown (%u)", op)); switch (op) { case ARPOP_REQUEST: ND_PRINT((ndo, "who-has %s", ipaddr_string(ATMTPA(ap)))); if (ATMTHRD_LEN(ap) != 0) { ND_PRINT((ndo, " (")); atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap), ATMTSLN(ap)); ND_PRINT((ndo, ")")); } ND_PRINT((ndo, "tell %s", ipaddr_string(ATMSPA(ap)))); break; case ARPOP_REPLY: ND_PRINT((ndo, "%s is-at ", ipaddr_string(ATMSPA(ap)))); atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), ATMSSLN(ap)); break; case ARPOP_INVREQUEST: ND_PRINT((ndo, "who-is ")); atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap), ATMTSLN(ap)); ND_PRINT((ndo, " tell ")); atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), ATMSSLN(ap)); break; case ARPOP_INVREPLY: atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), ATMSSLN(ap)); ND_PRINT((ndo, "at %s", ipaddr_string(ATMSPA(ap)))); break; case ARPOP_NAK: ND_PRINT((ndo, "for %s", ipaddr_string(ATMSPA(ap)))); break; default: ND_DEFAULTPRINT((const u_char *)ap, caplen); return; } out: ND_PRINT((ndo, ", length %u", length)); return; trunc: ND_PRINT((ndo, "[|ARP]")); }
static int ldp_tlv_print(netdissect_options *ndo, const u_char *tptr, u_short msg_tlen) { struct ldp_tlv_header { nd_uint16_t type; nd_uint16_t length; }; const struct ldp_tlv_header *ldp_tlv_header; u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; u_char fec_type; u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx; char buf[100]; int i; ldp_tlv_header = (const struct ldp_tlv_header *)tptr; ND_TCHECK_SIZE(ldp_tlv_header); tlv_len=EXTRACT_BE_U_2(ldp_tlv_header->length); if (tlv_len + 4 > msg_tlen) { ND_PRINT("\n\t\t TLV contents go past end of message"); return 0; } tlv_tlen=tlv_len; tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_BE_U_2(ldp_tlv_header->type)); /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", tok2str(ldp_tlv_values, "Unknown", tlv_type), tlv_type, tlv_len, LDP_MASK_U_BIT(EXTRACT_BE_U_2(ldp_tlv_header->type)) ? "continue processing" : "ignore", LDP_MASK_F_BIT(EXTRACT_BE_U_2(ldp_tlv_header->type)) ? "do" : "don't"); tptr+=sizeof(struct ldp_tlv_header); switch(tlv_type) { case LDP_TLV_COMMON_HELLO: TLV_TCHECK(4); ND_PRINT("\n\t Hold Time: %us, Flags: [%s Hello%s]", EXTRACT_BE_U_2(tptr), (EXTRACT_BE_U_2(tptr + 2)&0x8000) ? "Targeted" : "Link", (EXTRACT_BE_U_2(tptr + 2)&0x4000) ? ", Request for targeted Hellos" : ""); break; case LDP_TLV_IPV4_TRANSPORT_ADDR: TLV_TCHECK(4); ND_PRINT("\n\t IPv4 Transport Address: %s", ipaddr_string(ndo, tptr)); break; case LDP_TLV_IPV6_TRANSPORT_ADDR: TLV_TCHECK(16); ND_PRINT("\n\t IPv6 Transport Address: %s", ip6addr_string(ndo, tptr)); break; case LDP_TLV_CONFIG_SEQ_NUMBER: TLV_TCHECK(4); ND_PRINT("\n\t Sequence Number: %u", EXTRACT_BE_U_4(tptr)); break; case LDP_TLV_ADDRESS_LIST: TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); af = EXTRACT_BE_U_2(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; ND_PRINT("\n\t Address Family: %s, addresses", tok2str(af_values, "Unknown (%u)", af)); switch (af) { case AFNUM_INET: while(tlv_tlen >= sizeof(struct in_addr)) { ND_TCHECK_LEN(tptr, sizeof(struct in_addr)); ND_PRINT(" %s", ipaddr_string(ndo, tptr)); tlv_tlen-=sizeof(struct in_addr); tptr+=sizeof(struct in_addr); } break; case AFNUM_INET6: while(tlv_tlen >= sizeof(struct in6_addr)) { ND_TCHECK_LEN(tptr, sizeof(struct in6_addr)); ND_PRINT(" %s", ip6addr_string(ndo, tptr)); tlv_tlen-=sizeof(struct in6_addr); tptr+=sizeof(struct in6_addr); } break; default: /* unknown AF */ break; } break; case LDP_TLV_COMMON_SESSION: TLV_TCHECK(8); ND_PRINT("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", EXTRACT_BE_U_2(tptr), EXTRACT_BE_U_2(tptr + 2), (EXTRACT_BE_U_2(tptr + 6)&0x8000) ? "On Demand" : "Unsolicited", (EXTRACT_BE_U_2(tptr + 6)&0x4000) ? "Enabled" : "Disabled" ); break; case LDP_TLV_FEC: TLV_TCHECK(1); fec_type = EXTRACT_U_1(tptr); ND_PRINT("\n\t %s FEC (0x%02x)", tok2str(ldp_fec_values, "Unknown", fec_type), fec_type); tptr+=1; tlv_tlen-=1; switch(fec_type) { case LDP_FEC_WILDCARD: break; case LDP_FEC_PREFIX: TLV_TCHECK(2); af = EXTRACT_BE_U_2(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; if (af == AFNUM_INET) { i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) ND_PRINT(": IPv4 prefix (invalid length)"); else ND_PRINT(": IPv4 prefix %s", buf); } else if (af == AFNUM_INET6) { i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) ND_PRINT(": IPv6 prefix (invalid length)"); else ND_PRINT(": IPv6 prefix %s", buf); } else ND_PRINT(": Address family %u prefix", af); break; case LDP_FEC_HOSTADDRESS: break; case LDP_FEC_MARTINI_VC: /* * We assume the type was supposed to be one of the MPLS * Pseudowire Types. */ TLV_TCHECK(7); vc_info_len = EXTRACT_U_1(tptr + 2); /* * According to RFC 4908, the VC info Length field can be zero, * in which case not only are there no interface parameters, * there's no VC ID. */ if (vc_info_len == 0) { ND_PRINT(": %s, %scontrol word, group-ID %u, VC-info-length: %u", tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff), EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ", EXTRACT_BE_U_4(tptr + 3), vc_info_len); break; } /* Make sure we have the VC ID as well */ TLV_TCHECK(11); ND_PRINT(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff), EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ", EXTRACT_BE_U_4(tptr + 3), EXTRACT_BE_U_4(tptr + 7), vc_info_len); if (vc_info_len < 4) { /* minimum 4, for the VC ID */ ND_PRINT(" (invalid, < 4"); return(tlv_len+4); /* Type & Length fields not included */ } vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */ /* Skip past the fixed information and the VC ID */ tptr+=11; tlv_tlen-=11; TLV_TCHECK(vc_info_len); while (vc_info_len > 2) { vc_info_tlv_type = EXTRACT_U_1(tptr); vc_info_tlv_len = EXTRACT_U_1(tptr + 1); if (vc_info_tlv_len < 2) break; if (vc_info_len < vc_info_tlv_len) break; ND_PRINT("\n\t\tInterface Parameter: %s (0x%02x), len %u", tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type), vc_info_tlv_type, vc_info_tlv_len); switch(vc_info_tlv_type) { case LDP_FEC_MARTINI_IFPARM_MTU: ND_PRINT(": %u", EXTRACT_BE_U_2(tptr + 2)); break; case LDP_FEC_MARTINI_IFPARM_DESC: ND_PRINT(": "); for (idx = 2; idx < vc_info_tlv_len; idx++) safeputchar(ndo, EXTRACT_U_1(tptr + idx)); break; case LDP_FEC_MARTINI_IFPARM_VCCV: ND_PRINT("\n\t\t Control Channels (0x%02x) = [%s]", EXTRACT_U_1((tptr + 2)), bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", EXTRACT_U_1((tptr + 2)))); ND_PRINT("\n\t\t CV Types (0x%02x) = [%s]", EXTRACT_U_1((tptr + 3)), bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", EXTRACT_U_1((tptr + 3)))); break; default: print_unknown_data(ndo, tptr+2, "\n\t\t ", vc_info_tlv_len-2); break; } vc_info_len -= vc_info_tlv_len; tptr += vc_info_tlv_len; } break; } break; case LDP_TLV_GENERIC_LABEL: TLV_TCHECK(4); ND_PRINT("\n\t Label: %u", EXTRACT_BE_U_4(tptr) & 0xfffff); break; case LDP_TLV_STATUS: TLV_TCHECK(8); ui = EXTRACT_BE_U_4(tptr); tptr+=4; ND_PRINT("\n\t Status: 0x%02x, Flags: [%s and %s forward]", ui&0x3fffffff, ui&0x80000000 ? "Fatal error" : "Advisory Notification", ui&0x40000000 ? "do" : "don't"); ui = EXTRACT_BE_U_4(tptr); tptr+=4; if (ui) ND_PRINT(", causing Message ID: 0x%08x", ui); break; case LDP_TLV_FT_SESSION: TLV_TCHECK(8); ft_flags = EXTRACT_BE_U_2(tptr); ND_PRINT("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", ft_flags&0x8000 ? "" : "No ", ft_flags&0x8 ? "" : "Don't ", ft_flags&0x4 ? "" : "No ", ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", ft_flags&0x1 ? "" : "Don't "); tptr+=4; ui = EXTRACT_BE_U_4(tptr); if (ui) ND_PRINT(", Reconnect Timeout: %ums", ui); tptr+=4; ui = EXTRACT_BE_U_4(tptr); if (ui) ND_PRINT(", Recovery Time: %ums", ui); break; case LDP_TLV_MTU: TLV_TCHECK(2); ND_PRINT("\n\t MTU: %u", EXTRACT_BE_U_2(tptr)); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case LDP_TLV_HOP_COUNT: case LDP_TLV_PATH_VECTOR: case LDP_TLV_ATM_LABEL: case LDP_TLV_FR_LABEL: case LDP_TLV_EXTD_STATUS: case LDP_TLV_RETURNED_PDU: case LDP_TLV_RETURNED_MSG: case LDP_TLV_ATM_SESSION_PARM: case LDP_TLV_FR_SESSION_PARM: case LDP_TLV_LABEL_REQUEST_MSG_ID: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tptr, "\n\t ", tlv_tlen); break; } return(tlv_len+4); /* Type & Length fields not included */ trunc: ND_PRINT("\n\t\t packet exceeded snapshot"); return 0; badtlv: ND_PRINT("\n\t\t TLV contents go past end of TLV"); return(tlv_len+4); /* Type & Length fields not included */ }
/* * Print a single link state advertisement. If truncated return 1, else 0. */ static int ospf6_print_lsa(register const struct lsa6 *lsap) { register const struct rlalink6 *rlp; #if 0 register const struct tos_metric *tosp; #endif register const rtrid_t *ap; #if 0 register const struct aslametric *almp; register const struct mcla *mcp; #endif register const struct llsa *llsap; register const struct lsa6_prefix *lsapp; #if 0 register const u_int32_t *lp; #endif register u_int prefixes; register int bytelen; register u_int length, lsa_length; u_int32_t flags32; const u_int8_t *tptr; if (ospf6_print_lshdr(&lsap->ls_hdr)) return (1); TCHECK(lsap->ls_hdr.ls_length); length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length); /* * The LSA length includes the length of the header; * it must have a value that's at least that length. * If it does, find the length of what follows the * header. */ if (length < sizeof(struct lsa6_hdr)) return (1); lsa_length = length - sizeof(struct lsa6_hdr); tptr = (u_int8_t *)lsap+sizeof(struct lsa6_hdr); switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) { case LS_TYPE_ROUTER | LS_SCOPE_AREA: if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options); TCHECK(lsap->lsa_un.un_rla.rla_options); printf("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options))); printf(", RLA-Flags [%s]", bittok2str(ospf6_rla_flag_values, "none", lsap->lsa_un.un_rla.rla_flags)); rlp = lsap->lsa_un.un_rla.rla_link; while (lsa_length != 0) { if (lsa_length < sizeof (*rlp)) return (1); lsa_length -= sizeof (*rlp); TCHECK(*rlp); switch (rlp->link_type) { case RLA_TYPE_VIRTUAL: printf("\n\t Virtual Link: Neighbor Router-ID %s" "\n\t Neighbor Interface-ID %s, Interface %s", ipaddr_string(&rlp->link_nrtid), ipaddr_string(&rlp->link_nifid), ipaddr_string(&rlp->link_ifid)); break; case RLA_TYPE_ROUTER: printf("\n\t Neighbor Router-ID %s" "\n\t Neighbor Interface-ID %s, Interface %s", ipaddr_string(&rlp->link_nrtid), ipaddr_string(&rlp->link_nifid), ipaddr_string(&rlp->link_ifid)); break; case RLA_TYPE_TRANSIT: printf("\n\t Neighbor Network-ID %s" "\n\t Neighbor Interface-ID %s, Interface %s", ipaddr_string(&rlp->link_nrtid), ipaddr_string(&rlp->link_nifid), ipaddr_string(&rlp->link_ifid)); break; default: printf("\n\t Unknown Router Links Type 0x%02x", rlp->link_type); return (0); } printf(", metric %d", EXTRACT_16BITS(&rlp->link_metric)); rlp++; } break; case LS_TYPE_NETWORK | LS_SCOPE_AREA: if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options); TCHECK(lsap->lsa_un.un_nla.nla_options); printf("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options))); printf("\n\t Connected Routers:"); ap = lsap->lsa_un.un_nla.nla_router; while (lsa_length != 0) { if (lsa_length < sizeof (*ap)) return (1); lsa_length -= sizeof (*ap); TCHECK(*ap); printf("\n\t\t%s", ipaddr_string(ap)); ++ap; } break; case LS_TYPE_INTER_AP | LS_SCOPE_AREA: if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric); TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); printf(", metric %u", EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC); tptr = (u_int8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix; while (lsa_length != 0) { bytelen = ospf6_print_lsaprefix(tptr, lsa_length); if (bytelen < 0) goto trunc; lsa_length -= bytelen; tptr += bytelen; } break; case LS_TYPE_ASE | LS_SCOPE_AS: if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric); TCHECK(lsap->lsa_un.un_asla.asla_metric); flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric); printf("\n\t Flags [%s]", bittok2str(ospf6_asla_flag_values, "none", flags32)); printf(" metric %u", EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) & ASLA_MASK_METRIC); tptr = (u_int8_t *)lsap->lsa_un.un_asla.asla_prefix; lsapp = (struct lsa6_prefix *)tptr; bytelen = ospf6_print_lsaprefix(tptr, lsa_length); if (bytelen < 0) goto trunc; lsa_length -= bytelen; tptr += bytelen; if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { struct in6_addr *fwdaddr6; fwdaddr6 = (struct in6_addr *)tptr; if (lsa_length < sizeof (*fwdaddr6)) return (1); lsa_length -= sizeof (*fwdaddr6); TCHECK(*fwdaddr6); printf(" forward %s", ip6addr_string(fwdaddr6)); tptr += sizeof(*fwdaddr6); } if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { if (lsa_length < sizeof (u_int32_t)) return (1); lsa_length -= sizeof (u_int32_t); TCHECK(*(u_int32_t *)tptr); printf(" tag %s", ipaddr_string((u_int32_t *)tptr)); tptr += sizeof(u_int32_t); } if (lsapp->lsa_p_metric) { if (lsa_length < sizeof (u_int32_t)) return (1); lsa_length -= sizeof (u_int32_t); TCHECK(*(u_int32_t *)tptr); printf(" RefLSID: %s", ipaddr_string((u_int32_t *)tptr)); tptr += sizeof(u_int32_t); } break; case LS_TYPE_LINK: /* Link LSA */ llsap = &lsap->lsa_un.un_llsa; if (lsa_length < sizeof (llsap->llsa_priandopt)) return (1); lsa_length -= sizeof (llsap->llsa_priandopt); TCHECK(llsap->llsa_priandopt); printf("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&llsap->llsa_options))); if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix)) return (1); lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix); prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix); printf("\n\t Priority %d, Link-local address %s, Prefixes %d:", llsap->llsa_priority, ip6addr_string(&llsap->llsa_lladdr), prefixes); tptr = (u_int8_t *)llsap->llsa_prefix; while (prefixes > 0) { bytelen = ospf6_print_lsaprefix(tptr, lsa_length); if (bytelen < 0) goto trunc; prefixes--; lsa_length -= bytelen; tptr += bytelen; } break; case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: /* Intra-Area-Prefix LSA */ if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid); TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); ospf6_print_ls_type( EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype), &lsap->lsa_un.un_intra_ap.intra_ap_lsid); if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix); TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix); printf("\n\t Prefixes %d:", prefixes); tptr = (u_int8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; while (prefixes > 0) { bytelen = ospf6_print_lsaprefix(tptr, lsa_length); if (bytelen < 0) goto trunc; prefixes--; lsa_length -= bytelen; tptr += bytelen; } break; case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL: if (ospf_print_grace_lsa(tptr, lsa_length) == -1) { return 1; } break; case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL: if (ospf_print_te_lsa(tptr, lsa_length) == -1) { return 1; } break; default: if(!print_unknown_data(tptr, "\n\t ", lsa_length)) { return (1); } break; } return (0); trunc: return (1); }
static int ospf6_decode_v3(register const struct ospf6hdr *op, register const u_char *dataend) { register const rtrid_t *ap; register const struct lsr6 *lsrp; register const struct lsa6_hdr *lshp; register const struct lsa6 *lsap; register int i; switch (op->ospf6_type) { case OSPF_TYPE_HELLO: printf("\n\tOptions [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&op->ospf6_hello.hello_options))); TCHECK(op->ospf6_hello.hello_deadint); printf("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u", EXTRACT_16BITS(&op->ospf6_hello.hello_helloint), EXTRACT_16BITS(&op->ospf6_hello.hello_deadint), ipaddr_string(&op->ospf6_hello.hello_ifid), op->ospf6_hello.hello_priority); TCHECK(op->ospf6_hello.hello_dr); if (op->ospf6_hello.hello_dr != 0) printf("\n\t Designated Router %s", ipaddr_string(&op->ospf6_hello.hello_dr)); TCHECK(op->ospf6_hello.hello_bdr); if (op->ospf6_hello.hello_bdr != 0) printf(", Backup Designated Router %s", ipaddr_string(&op->ospf6_hello.hello_bdr)); if (vflag) { printf("\n\t Neighbor List:"); ap = op->ospf6_hello.hello_neighbor; while ((u_char *)ap < dataend) { TCHECK(*ap); printf("\n\t %s", ipaddr_string(ap)); ++ap; } } break; /* HELLO */ case OSPF_TYPE_DD: TCHECK(op->ospf6_db.db_options); printf("\n\tOptions [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&op->ospf6_db.db_options))); TCHECK(op->ospf6_db.db_flags); printf(", DD Flags [%s]", bittok2str(ospf6_dd_flag_values,"none",op->ospf6_db.db_flags)); TCHECK(op->ospf6_db.db_seq); printf(", MTU %u, DD-Sequence 0x%08x", EXTRACT_16BITS(&op->ospf6_db.db_mtu), EXTRACT_32BITS(&op->ospf6_db.db_seq)); /* Print all the LS adv's */ lshp = op->ospf6_db.db_lshdr; while (!ospf6_print_lshdr(lshp)) { ++lshp; } break; case OSPF_TYPE_LS_REQ: if (vflag) { lsrp = op->ospf6_lsr; while ((u_char *)lsrp < dataend) { TCHECK(*lsrp); printf("\n\t Advertising Router %s", ipaddr_string(&lsrp->ls_router)); ospf6_print_ls_type(EXTRACT_16BITS(&lsrp->ls_type), &lsrp->ls_stateid); ++lsrp; } } break; case OSPF_TYPE_LS_UPDATE: if (vflag) { lsap = op->ospf6_lsu.lsu_lsa; TCHECK(op->ospf6_lsu.lsu_count); i = EXTRACT_32BITS(&op->ospf6_lsu.lsu_count); while (i--) { if (ospf6_print_lsa(lsap)) goto trunc; lsap = (struct lsa6 *)((u_char *)lsap + EXTRACT_16BITS(&lsap->ls_hdr.ls_length)); } } break; case OSPF_TYPE_LS_ACK: if (vflag) { lshp = op->ospf6_lsa.lsa_lshdr; while (!ospf6_print_lshdr(lshp)) { ++lshp; } } break; default: break; } return (0); trunc: return (1); }
int main(int argc, char *argv[]) { int tun; in_addr_t remote_ip; char tun_name[IFNAMSIZ]; openlog("tb_userspace", 0, LOG_DAEMON); if (argc != 5) { fprintf(stderr, "Usage: %s tun_name remote_ipv4 local_ipv4 mode\r\n", argv[0]); return 1; } strcpy(tun_name, argv[1]); tun = tun_create(tun_name, IFF_TUN );//| IFF_NO_PI); if (tun < 0) { perror("tun_create"); return 1; } fprintf(stderr, "TUN name is %s\r\n", tun_name); int sockv6, if_bind, tun_mode; sockv6 = socket(AF_INET, SOCK_RAW, IPPROTO_IPV6); if (sockv6 < 0) { perror("v4_socket_create"); return 1; } fprintf(stderr, "IPv4 SOCK_RAW created: %d\r\n", sockv6); struct sockaddr_in localaddr; localaddr.sin_family = AF_INET; localaddr.sin_port = htons(IPPROTO_IPV6); localaddr.sin_addr.s_addr = inet_addr(argv[3]); bzero(&(localaddr.sin_zero), 8); if (localaddr.sin_addr.s_addr != -1) { if_bind = bind(sockv6, (struct sockaddr *)&localaddr, sizeof(struct sockaddr)); if (if_bind < 0) { perror("bind local address"); return 1; } fprintf(stderr, "Bind local IPv4 address %s\r\n", ipaddr_string(localaddr.sin_addr.s_addr)); }/*If local_ipv4(argv[3]) is "any", do not bind local IPv4 address*/ else fprintf(stderr, "Do not bind local IPv4 address, using default.\r\n"); pthread_t ids2t, idt2s; struct Threadargs s2targs, t2sargs; s2targs.sockv6 = sockv6; s2targs.tun = tun; if (!strcmp(argv[4],"sit")) { if (strcmp(argv[2],"any")) { remote_ip = inet_addr(argv[2]); tun_mode = 1; } else { remote_ip = inet_addr("192.88.99.1"); tun_mode = 0; } }/*If remote_ipv4(argv[2]) is "any", use 6to4 mode and set default gateway 192.88.99.1*/ else if (!strcmp(argv[4],"isatap")) { remote_ip = inet_addr(argv[2]); tun_mode = 2; } else { fprintf(stderr, "tunnel mode %s not found.\r\n", argv[4]); return 1; } s2targs.tun_mode = tun_mode; if (remote_ip == INADDR_NONE) { fprintf(stderr, "Bad remote ipv4 address.\r\n"); return 1; } else { t2sargs.remote_ip = remote_ip; s2targs.remote_ip = remote_ip; } fprintf(stderr, "Using remote IPv4 %s\r\n", ipaddr_string(remote_ip)); pthread_create(&ids2t, NULL, (void *)s2t_thread, (void *)&s2targs); t2sargs.sockv6 = sockv6; t2sargs.tun = tun; t2sargs.tun_mode = tun_mode; pthread_create(&idt2s, NULL, (void *)t2s_thread, (void *)&t2sargs); pthread_join(ids2t, NULL); pthread_join(idt2s, NULL); return 0; }
/** * 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; const struct ip6_hdr *ip6; const u_char *cp; u_short sport, dport; u_int hlen; u_int fixed_hdrlen; uint8_t dccph_type; 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) { 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; if (ip6) { ND_PRINT((ndo, "%s.%d > %s.%d: ", ip6addr_string(ndo, &ip6->ip6_src), sport, ip6addr_string(ndo, &ip6->ip6_dst), dport)); } else { ND_PRINT((ndo, "%s.%d > %s.%d: ", ipaddr_string(ndo, &ip->ip_src), sport, ipaddr_string(ndo, &ip->ip_dst), dport)); } ND_PRINT((ndo, "DCCP")); if (ndo->ndo_qflag) { ND_PRINT((ndo, " %d", len - hlen)); if (hlen > len) { ND_PRINT((ndo, " [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)) { uint16_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); else if (IP_V(ip) == 6) sum = dccp6_cksum(ndo, ip6, dh, len); if (sum != 0) ND_PRINT((ndo, "(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum))); else ND_PRINT((ndo, "(correct)")); } if (ndo->ndo_vflag) ND_PRINT((ndo, ")")); ND_PRINT((ndo, " ")); 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((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "%s (service=%d) ", tok2str(dccp_pkt_type_str, "", dccph_type), EXTRACT_32BITS(&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((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "%s (service=%d) ", tok2str(dccp_pkt_type_str, "", dccph_type), EXTRACT_32BITS(&dhr->dccph_resp_service))); break; } case DCCP_PKT_DATA: ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_ACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; } case DCCP_PKT_DATAACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; } case DCCP_PKT_CLOSEREQ: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_CLOSE: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%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((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "%s (code=%s) ", tok2str(dccp_pkt_type_str, "", dccph_type), dccp_reset_code(dhr->dccph_reset_code))); break; } case DCCP_PKT_SYNC: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_SYNCACK: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; default: ND_PRINT((ndo, "%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((ndo, "seq %" PRIu64, dccp_seqno(bp))); /* process options */ if (hlen > fixed_hdrlen){ 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; }
void tcp_print(const u_char *bp, u_int length, const u_char *bp2) { const struct tcphdr *tp; const struct ip *ip; u_char flags; int hlen; char ch; struct tcp_seq_hash *th = NULL; int rev = 0; u_int16_t sport, dport, win, urp; tcp_seq seq, ack; #ifdef INET6 const struct ip6_hdr *ip6; #endif tp = (struct tcphdr *)bp; switch (((struct ip *)bp2)->ip_v) { case 4: ip = (struct ip *)bp2; #ifdef INET6 ip6 = NULL; #endif break; #ifdef INET6 case 6: ip = NULL; ip6 = (struct ip6_hdr *)bp2; break; #endif default: (void)printf("invalid ip version"); return; } ch = '\0'; if (length < sizeof(*tp)) { (void)printf("truncated-tcp %u", length); return; } if (!TTEST(tp->th_dport)) { #ifdef INET6 if (ip6) { (void)printf("%s > %s: [|tcp]", ip6addr_string(&ip6->ip6_src), ip6addr_string(&ip6->ip6_dst)); } else #endif /*INET6*/ { (void)printf("%s > %s: [|tcp]", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); } return; } sport = ntohs(tp->th_sport); dport = ntohs(tp->th_dport); #ifdef INET6 if (ip6) { if (ip6->ip6_nxt == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ip6addr_string(&ip6->ip6_src), tcpport_string(sport), ip6addr_string(&ip6->ip6_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } else #endif /*INET6*/ { if (ip->ip_p == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ipaddr_string(&ip->ip_src), tcpport_string(sport), ipaddr_string(&ip->ip_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } if (!qflag && TTEST(tp->th_seq) && !TTEST(tp->th_ack)) (void)printf("%u ", ntohl(tp->th_seq)); TCHECK(*tp); seq = ntohl(tp->th_seq); ack = ntohl(tp->th_ack); win = ntohs(tp->th_win); urp = ntohs(tp->th_urp); hlen = tp->th_off * 4; if (qflag) { (void)printf("tcp %d", length - tp->th_off * 4); return; } else if (packettype != PT_TCP) { /* * If data present and NFS port used, assume NFS. * Pass offset of data plus 4 bytes for RPC TCP msg length * to NFS print routines. */ u_int len = length - hlen; if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend && dport == NFS_PORT) { nfsreq_print((u_char *)tp + hlen + 4, len, bp2); return; } else if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend && sport == NFS_PORT) { nfsreply_print((u_char *)tp + hlen + 4, len, bp2); return; } } if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH| TH_ECNECHO|TH_CWR)) { if (flags & TH_SYN) putchar('S'); if (flags & TH_FIN) putchar('F'); if (flags & TH_RST) putchar('R'); if (flags & TH_PUSH) putchar('P'); if (flags & TH_CWR) putchar('W'); /* congestion _W_indow reduced (ECN) */ if (flags & TH_ECNECHO) putchar('E'); /* ecn _E_cho sent (ECN) */ } else putchar('.'); if (!Sflag && (flags & TH_ACK)) { struct tha tha; /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ #ifdef INET6 bzero(&tha, sizeof(tha)); rev = 0; if (ip6) { if (sport > dport) { rev = 1; } else if (sport == dport) { int i; for (i = 0; i < 4; i++) { if (((u_int32_t *)(&ip6->ip6_src))[i] > ((u_int32_t *)(&ip6->ip6_dst))[i]) { rev = 1; break; } } } if (rev) { tha.src = ip6->ip6_dst; tha.dst = ip6->ip6_src; tha.port = dport << 16 | sport; } else { tha.dst = ip6->ip6_dst; tha.src = ip6->ip6_src; tha.port = sport << 16 | dport; } } else { if (sport > dport || (sport == dport && ip->ip_src.s_addr > ip->ip_dst.s_addr)) { rev = 1; } if (rev) { *(struct in_addr *)&tha.src = ip->ip_dst; *(struct in_addr *)&tha.dst = ip->ip_src; tha.port = dport << 16 | sport; } else { *(struct in_addr *)&tha.dst = ip->ip_dst; *(struct in_addr *)&tha.src = ip->ip_src; tha.port = sport << 16 | dport; } } #else if (sport < dport || (sport == dport && ip->ip_src.s_addr < ip->ip_dst.s_addr)) { tha.src = ip->ip_src, tha.dst = ip->ip_dst; tha.port = sport << 16 | dport; rev = 0; } else { tha.src = ip->ip_dst, tha.dst = ip->ip_src; tha.port = dport << 16 | sport; rev = 1; } #endif for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (!memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr))) break; if (!th->nxt || flags & TH_SYN) { /* didn't find it or new conversation */ if (th->nxt == NULL) { th->nxt = calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } } hlen = tp->th_off * 4; if (hlen > length) { (void)printf(" [bad hdr length]"); return; } if (ip && ip->ip_v == 4 && vflag) { if (TTEST2(tp->th_sport, length)) { u_int16_t sum, tcp_sum; sum = tcp_cksum(ip, tp, length); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" [bad tcp cksum %x! -> %x]", tcp_sum, in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" [tcp sum ok]"); } } #ifdef INET6 if (ip6 && ip6->ip6_plen && vflag) { if (TTEST2(tp->th_sport, length)) { u_int16_t sum, tcp_sum; sum = tcp6_cksum(ip6, tp, length); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" [bad tcp cksum %x! -> %x]", tcp_sum, in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" [tcp sum ok]"); } } #endif /* OS Fingerprint */ if (oflag && (flags & (TH_SYN|TH_ACK)) == TH_SYN) { struct pf_osfp_enlist *head = NULL; struct pf_osfp_entry *fp; unsigned long left; left = (unsigned long)(snapend - (const u_char *)tp); if (left >= hlen) head = pf_osfp_fingerprint_hdr(ip, ip6, tp); if (head) { int prev = 0; printf(" (src OS:"); SLIST_FOREACH(fp, head, fp_entry) { if (fp->fp_enflags & PF_OSFP_EXPANDED) continue; if (prev) printf(","); printf(" %s", fp->fp_class_nm); if (fp->fp_version_nm[0]) printf(" %s", fp->fp_version_nm); if (fp->fp_subtype_nm[0]) printf(" %s", fp->fp_subtype_nm); prev = 1; } printf(")"); } else { if (left < hlen) printf(" (src OS: short-pkt)"); else printf(" (src OS: unknown)"); } }
/* LCP config options */ static int print_lcp_config_options(netdissect_options *ndo, const u_char *p, int length) { int len, opt; if (length < 2) return 0; ND_TCHECK2(*p, 2); len = p[1]; opt = p[0]; if (length < len) return 0; if (len < 2) { if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX)) ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", lcpconfopts[opt], opt, len)); else ND_PRINT((ndo, "\n\tunknown LCP option 0x%02x", opt)); return 0; } if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX)) ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u", lcpconfopts[opt], opt, len)); else { ND_PRINT((ndo, "\n\tunknown LCP option 0x%02x", opt)); return len; } switch (opt) { case LCPOPT_VEXT: if (len < 6) { ND_PRINT((ndo, " (length bogus, should be >= 6)")); return len; } ND_TCHECK2(*(p + 2), 3); ND_PRINT((ndo, ": Vendor: %s (%u)", tok2str(oui_values,"Unknown",EXTRACT_24BITS(p+2)), EXTRACT_24BITS(p + 2))); #if 0 ND_TCHECK(p[5]); ND_PRINT((ndo, ", kind: 0x%02x", p[5])); ND_PRINT((ndo, ", Value: 0x")); for (i = 0; i < len - 6; i++) { ND_TCHECK(p[6 + i]); ND_PRINT((ndo, "%02x", p[6 + i])); } #endif break; case LCPOPT_MRU: if (len != 4) { ND_PRINT((ndo, " (length bogus, should be = 4)")); return len; } ND_TCHECK2(*(p + 2), 2); ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2))); break; case LCPOPT_ACCM: if (len != 6) { ND_PRINT((ndo, " (length bogus, should be = 6)")); return len; } ND_TCHECK2(*(p + 2), 4); ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2))); break; case LCPOPT_AP: if (len < 4) { ND_PRINT((ndo, " (length bogus, should be >= 4)")); return len; } ND_TCHECK2(*(p + 2), 2); ND_PRINT((ndo, ": %s", tok2str(ppptype2str, "Unknown Auth Proto (0x04x)", EXTRACT_16BITS(p + 2)))); switch (EXTRACT_16BITS(p+2)) { case PPP_CHAP: ND_TCHECK(p[4]); ND_PRINT((ndo, ", %s", tok2str(authalg_values, "Unknown Auth Alg %u", p[4]))); break; case PPP_PAP: /* fall through */ case PPP_EAP: case PPP_SPAP: case PPP_SPAP_OLD: break; default: print_unknown_data(ndo, p, "\n\t", len); } break; case LCPOPT_QP: if (len < 4) { ND_PRINT((ndo, " (length bogus, should be >= 4)")); return 0; } ND_TCHECK2(*(p + 2), 2); if (EXTRACT_16BITS(p+2) == PPP_LQM) ND_PRINT((ndo, ": LQR")); else ND_PRINT((ndo, ": unknown")); break; case LCPOPT_MN: if (len != 6) { ND_PRINT((ndo, " (length bogus, should be = 6)")); return 0; } ND_TCHECK2(*(p + 2), 4); ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2))); break; case LCPOPT_PFC: break; case LCPOPT_ACFC: break; case LCPOPT_LD: if (len != 4) { ND_PRINT((ndo, " (length bogus, should be = 4)")); return 0; } ND_TCHECK2(*(p + 2), 2); ND_PRINT((ndo, ": 0x%04x", EXTRACT_16BITS(p + 2))); break; case LCPOPT_CBACK: if (len < 3) { ND_PRINT((ndo, " (length bogus, should be >= 3)")); return 0; } ND_PRINT((ndo, ": ")); ND_TCHECK(p[2]); ND_PRINT((ndo, ": Callback Operation %s (%u)", tok2str(ppp_callback_values, "Unknown", p[2]), p[2])); break; case LCPOPT_MLMRRU: if (len != 4) { ND_PRINT((ndo, " (length bogus, should be = 4)")); return 0; } ND_TCHECK2(*(p + 2), 2); ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2))); break; case LCPOPT_MLED: if (len < 3) { ND_PRINT((ndo, " (length bogus, should be >= 3)")); return 0; } ND_TCHECK(p[2]); switch (p[2]) { /* class */ case MEDCLASS_NULL: ND_PRINT((ndo, ": Null")); break; case MEDCLASS_LOCAL: ND_PRINT((ndo, ": Local")); /* XXX */ break; case MEDCLASS_IPV4: if (len != 7) { ND_PRINT((ndo, " (length bogus, should be = 7)")); return 0; } ND_TCHECK2(*(p + 3), 4); ND_PRINT((ndo, ": IPv4 %s", ipaddr_string(ndo, p + 3))); break; case MEDCLASS_MAC: if (len != 9) { ND_PRINT((ndo, " (length bogus, should be = 9)")); return 0; } ND_TCHECK(p[8]); ND_PRINT((ndo, ": MAC %02x:%02x:%02x:%02x:%02x:%02x", p[3], p[4], p[5], p[6], p[7], p[8])); break; case MEDCLASS_MNB: ND_PRINT((ndo, ": Magic-Num-Block")); /* XXX */ break; case MEDCLASS_PSNDN: ND_PRINT((ndo, ": PSNDN")); /* XXX */ break; default: ND_PRINT((ndo, ": Unknown class %u", p[2])); break; } break; /* XXX: to be supported */ #if 0 case LCPOPT_DEP6: case LCPOPT_FCSALT: case LCPOPT_SDP: case LCPOPT_NUMMODE: case LCPOPT_DEP12: case LCPOPT_DEP14: case LCPOPT_DEP15: case LCPOPT_DEP16: case LCPOPT_MLSSNHF: case LCPOPT_PROP: case LCPOPT_DCEID: case LCPOPT_MPP: case LCPOPT_LCPAOPT: case LCPOPT_COBS: case LCPOPT_PE: case LCPOPT_MLHF: case LCPOPT_I18N: case LCPOPT_SDLOS: case LCPOPT_PPPMUX: break; #endif default: /* * Unknown option; dump it as raw bytes now if we're * not going to do so below. */ if (ndo->ndo_vflag < 2) print_unknown_data(ndo, &p[2], "\n\t ", len - 2); break; } if (ndo->ndo_vflag > 1) print_unknown_data(ndo, &p[2], "\n\t ", len - 2); /* exclude TLV header */ return len; trunc: ND_PRINT((ndo, "[|lcp]")); return 0; }
/* IPCP config options */ static int print_ipcp_config_options(netdissect_options *ndo, const u_char *p, int length) { int len, opt; u_int compproto, ipcomp_subopttotallen, ipcomp_subopt, ipcomp_suboptlen; if (length < 2) return 0; ND_TCHECK2(*p, 2); len = p[1]; opt = p[0]; if (length < len) return 0; if (len < 2) { ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", tok2str(ipcpopt_values,"unknown",opt), opt, len)); return 0; } ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u", tok2str(ipcpopt_values,"unknown",opt), opt, len)); switch (opt) { case IPCPOPT_2ADDR: /* deprecated */ if (len != 10) { ND_PRINT((ndo, " (length bogus, should be = 10)")); return len; } ND_TCHECK2(*(p + 6), 4); ND_PRINT((ndo, ": src %s, dst %s", ipaddr_string(ndo, p + 2), ipaddr_string(ndo, p + 6))); break; case IPCPOPT_IPCOMP: if (len < 4) { ND_PRINT((ndo, " (length bogus, should be >= 4)")); return 0; } ND_TCHECK2(*(p + 2), 2); compproto = EXTRACT_16BITS(p+2); ND_PRINT((ndo, ": %s (0x%02x):", tok2str(ipcpopt_compproto_values, "Unknown", compproto), compproto)); switch (compproto) { case PPP_VJC: /* XXX: VJ-Comp parameters should be decoded */ break; case IPCPOPT_IPCOMP_HDRCOMP: if (len < IPCPOPT_IPCOMP_MINLEN) { ND_PRINT((ndo, " (length bogus, should be >= %u)", IPCPOPT_IPCOMP_MINLEN)); return 0; } ND_TCHECK2(*(p + 2), IPCPOPT_IPCOMP_MINLEN); ND_PRINT((ndo, "\n\t TCP Space %u, non-TCP Space %u" \ ", maxPeriod %u, maxTime %u, maxHdr %u", EXTRACT_16BITS(p+4), EXTRACT_16BITS(p+6), EXTRACT_16BITS(p+8), EXTRACT_16BITS(p+10), EXTRACT_16BITS(p+12))); /* suboptions present ? */ if (len > IPCPOPT_IPCOMP_MINLEN) { ipcomp_subopttotallen = len - IPCPOPT_IPCOMP_MINLEN; p += IPCPOPT_IPCOMP_MINLEN; ND_PRINT((ndo, "\n\t Suboptions, length %u", ipcomp_subopttotallen)); while (ipcomp_subopttotallen >= 2) { ND_TCHECK2(*p, 2); ipcomp_subopt = *p; ipcomp_suboptlen = *(p+1); /* sanity check */ if (ipcomp_subopt == 0 || ipcomp_suboptlen == 0 ) break; /* XXX: just display the suboptions for now */ ND_PRINT((ndo, "\n\t\t%s Suboption #%u, length %u", tok2str(ipcpopt_compproto_subopt_values, "Unknown", ipcomp_subopt), ipcomp_subopt, ipcomp_suboptlen)); ipcomp_subopttotallen -= ipcomp_suboptlen; p += ipcomp_suboptlen; } } break; default: break; } break; case IPCPOPT_ADDR: /* those options share the same format - fall through */ case IPCPOPT_MOBILE4: case IPCPOPT_PRIDNS: case IPCPOPT_PRINBNS: case IPCPOPT_SECDNS: case IPCPOPT_SECNBNS: if (len != 6) { ND_PRINT((ndo, " (length bogus, should be = 6)")); return 0; } ND_TCHECK2(*(p + 2), 4); ND_PRINT((ndo, ": %s", ipaddr_string(ndo, p + 2))); break; default: /* * Unknown option; dump it as raw bytes now if we're * not going to do so below. */ if (ndo->ndo_vflag < 2) print_unknown_data(ndo, &p[2], "\n\t ", len - 2); break; } if (ndo->ndo_vflag > 1) print_unknown_data(ndo, &p[2], "\n\t ", len - 2); /* exclude TLV header */ return len; trunc: ND_PRINT((ndo, "[|ipcp]")); return 0; }
static void rfc1048_print(netdissect_options *ndo, register const u_char *bp) { register uint16_t tag; register u_int len; register const char *cp; register char c; int first, idx; uint32_t ul; uint16_t us; uint8_t uc, subopt, suboptlen; ND_PRINT((ndo, "\n\t Vendor-rfc1048 Extensions")); /* Step over magic cookie */ ND_PRINT((ndo, "\n\t Magic Cookie 0x%08x", EXTRACT_32BITS(bp))); bp += sizeof(int32_t); /* Loop while we there is a tag left in the buffer */ while (ND_TTEST2(*bp, 1)) { tag = *bp++; if (tag == TAG_PAD && ndo->ndo_vflag < 3) continue; if (tag == TAG_END && ndo->ndo_vflag < 3) return; if (tag == TAG_EXTENDED_OPTION) { ND_TCHECK2(*(bp + 1), 2); tag = EXTRACT_16BITS(bp + 1); /* XXX we don't know yet if the IANA will * preclude overlap of 1-byte and 2-byte spaces. * If not, we need to offset tag after this step. */ cp = tok2str(xtag2str, "?xT%u", tag); } else cp = tok2str(tag2str, "?T%u", tag); c = *cp++; if (tag == TAG_PAD || tag == TAG_END) len = 0; else { /* Get the length; check for truncation */ ND_TCHECK2(*bp, 1); len = *bp++; } ND_PRINT((ndo, "\n\t %s Option %u, length %u%s", cp, tag, len, len > 0 ? ": " : "")); if (tag == TAG_PAD && ndo->ndo_vflag > 2) { u_int ntag = 1; while (ND_TTEST2(*bp, 1) && *bp == TAG_PAD) { bp++; ntag++; } if (ntag > 1) ND_PRINT((ndo, ", occurs %u", ntag)); } if (!ND_TTEST2(*bp, len)) { ND_PRINT((ndo, "[|rfc1048 %u]", len)); return; } if (tag == TAG_DHCP_MESSAGE && len == 1) { uc = *bp++; ND_PRINT((ndo, "%s", tok2str(dhcp_msg_values, "Unknown (%u)", uc))); continue; } if (tag == TAG_PARM_REQUEST) { idx = 0; while (len-- > 0) { uc = *bp++; cp = tok2str(tag2str, "?Option %u", uc); if (idx % 4 == 0) ND_PRINT((ndo, "\n\t ")); else ND_PRINT((ndo, ", ")); ND_PRINT((ndo, "%s", cp + 1)); idx++; } continue; } if (tag == TAG_EXTENDED_REQUEST) { first = 1; while (len > 1) { len -= 2; us = EXTRACT_16BITS(bp); bp += 2; cp = tok2str(xtag2str, "?xT%u", us); if (!first) ND_PRINT((ndo, "+")); ND_PRINT((ndo, "%s", cp + 1)); first = 0; } continue; } /* Print data */ if (c == '?') { /* Base default formats for unknown tags on data size */ if (len & 1) c = 'b'; else if (len & 2) c = 's'; else c = 'l'; } first = 1; switch (c) { case 'a': /* ascii strings */ ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, len, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); bp += len; len = 0; break; case 'i': case 'l': case 'L': /* ip addresses/32-bit words */ while (len >= sizeof(ul)) { if (!first) ND_PRINT((ndo, ",")); ul = EXTRACT_32BITS(bp); if (c == 'i') { ul = htonl(ul); ND_PRINT((ndo, "%s", ipaddr_string(ndo, &ul))); } else if (c == 'L') ND_PRINT((ndo, "%d", ul)); else ND_PRINT((ndo, "%u", ul)); bp += sizeof(ul); len -= sizeof(ul); first = 0; } break; case 'p': /* IP address pairs */ while (len >= 2*sizeof(ul)) { if (!first) ND_PRINT((ndo, ",")); memcpy((char *)&ul, (const char *)bp, sizeof(ul)); ND_PRINT((ndo, "(%s:", ipaddr_string(ndo, &ul))); bp += sizeof(ul); memcpy((char *)&ul, (const char *)bp, sizeof(ul)); ND_PRINT((ndo, "%s)", ipaddr_string(ndo, &ul))); bp += sizeof(ul); len -= 2*sizeof(ul); first = 0; } break; case 's': /* shorts */ while (len >= sizeof(us)) { if (!first) ND_PRINT((ndo, ",")); us = EXTRACT_16BITS(bp); ND_PRINT((ndo, "%u", us)); bp += sizeof(us); len -= sizeof(us); first = 0; } break; case 'B': /* boolean */ while (len > 0) { if (!first) ND_PRINT((ndo, ",")); switch (*bp) { case 0: ND_PRINT((ndo, "N")); break; case 1: ND_PRINT((ndo, "Y")); break; default: ND_PRINT((ndo, "%u?", *bp)); break; } ++bp; --len; first = 0; } break; case 'b': case 'x': default: /* Bytes */ while (len > 0) { if (!first) ND_PRINT((ndo, c == 'x' ? ":" : ".")); if (c == 'x') ND_PRINT((ndo, "%02x", *bp)); else ND_PRINT((ndo, "%u", *bp)); ++bp; --len; first = 0; } break; case '$': /* Guys we can't handle with one of the usual cases */ switch (tag) { case TAG_NETBIOS_NODE: /* this option should be at least 1 byte long */ if (len < 1) { ND_PRINT((ndo, "ERROR: length < 1 bytes")); break; } tag = *bp++; --len; ND_PRINT((ndo, "%s", tok2str(nbo2str, NULL, tag))); break; case TAG_OPT_OVERLOAD: /* this option should be at least 1 byte long */ if (len < 1) { ND_PRINT((ndo, "ERROR: length < 1 bytes")); break; } tag = *bp++; --len; ND_PRINT((ndo, "%s", tok2str(oo2str, NULL, tag))); break; case TAG_CLIENT_FQDN: /* this option should be at least 3 bytes long */ if (len < 3) { ND_PRINT((ndo, "ERROR: length < 3 bytes")); bp += len; len = 0; break; } if (*bp) ND_PRINT((ndo, "[%s] ", client_fqdn_flags(*bp))); bp++; if (*bp || *(bp+1)) ND_PRINT((ndo, "%u/%u ", *bp, *(bp+1))); bp += 2; ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, len - 3, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); bp += len - 3; len = 0; break; case TAG_CLIENT_ID: { int type; /* this option should be at least 1 byte long */ if (len < 1) { ND_PRINT((ndo, "ERROR: length < 1 bytes")); break; } type = *bp++; len--; if (type == 0) { ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, len, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); bp += len; len = 0; break; } else { ND_PRINT((ndo, "%s ", tok2str(arp2str, "hardware-type %u,", type))); while (len > 0) { if (!first) ND_PRINT((ndo, ":")); ND_PRINT((ndo, "%02x", *bp)); ++bp; --len; first = 0; } } break; } case TAG_AGENT_CIRCUIT: while (len >= 2) { subopt = *bp++; suboptlen = *bp++; len -= 2; if (suboptlen > len) { ND_PRINT((ndo, "\n\t %s SubOption %u, length %u: length goes past end of option", tok2str(agent_suboption_values, "Unknown", subopt), subopt, suboptlen)); bp += len; len = 0; break; } ND_PRINT((ndo, "\n\t %s SubOption %u, length %u: ", tok2str(agent_suboption_values, "Unknown", subopt), subopt, suboptlen)); switch (subopt) { case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */ case AGENT_SUBOPTION_REMOTE_ID: case AGENT_SUBOPTION_SUBSCRIBER_ID: if (fn_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) goto trunc; break; default: print_unknown_data(ndo, bp, "\n\t\t", suboptlen); } len -= suboptlen; bp += suboptlen; } break; case TAG_CLASSLESS_STATIC_RT: case TAG_CLASSLESS_STA_RT_MS: { u_int mask_width, significant_octets, i; /* this option should be at least 5 bytes long */ if (len < 5) { ND_PRINT((ndo, "ERROR: length < 5 bytes")); bp += len; len = 0; break; } while (len > 0) { if (!first) ND_PRINT((ndo, ",")); mask_width = *bp++; len--; /* mask_width <= 32 */ if (mask_width > 32) { ND_PRINT((ndo, "[ERROR: Mask width (%d) > 32]", mask_width)); bp += len; len = 0; break; } significant_octets = (mask_width + 7) / 8; /* significant octets + router(4) */ if (len < significant_octets + 4) { ND_PRINT((ndo, "[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4)); bp += len; len = 0; break; } ND_PRINT((ndo, "(")); if (mask_width == 0) ND_PRINT((ndo, "default")); else { for (i = 0; i < significant_octets ; i++) { if (i > 0) ND_PRINT((ndo, ".")); ND_PRINT((ndo, "%d", *bp++)); } for (i = significant_octets ; i < 4 ; i++) ND_PRINT((ndo, ".0")); ND_PRINT((ndo, "/%d", mask_width)); } memcpy((char *)&ul, (const char *)bp, sizeof(ul)); ND_PRINT((ndo, ":%s)", ipaddr_string(ndo, &ul))); bp += sizeof(ul); len -= (significant_octets + 4); first = 0; } break; } case TAG_USER_CLASS: { u_int suboptnumber = 1; first = 1; if (len < 2) { ND_PRINT((ndo, "ERROR: length < 2 bytes")); bp += len; len = 0; break; } while (len > 0) { suboptlen = *bp++; len--; ND_PRINT((ndo, "\n\t ")); ND_PRINT((ndo, "instance#%u: ", suboptnumber)); if (suboptlen == 0) { ND_PRINT((ndo, "ERROR: suboption length must be non-zero")); bp += len; len = 0; break; } if (len < suboptlen) { ND_PRINT((ndo, "ERROR: invalid option")); bp += len; len = 0; break; } ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); ND_PRINT((ndo, ", length %d", suboptlen)); suboptnumber++; len -= suboptlen; bp += suboptlen; } break; } default: ND_PRINT((ndo, "[unknown special tag %u, size %u]", tag, len)); bp += len; len = 0; break; } break; } /* Data left over? */ if (len) { ND_PRINT((ndo, "\n\t trailing data length %u", len)); bp += len; } } return; trunc: ND_PRINT((ndo, "|[rfc1048]")); }
void sctp_print(const u_char *bp, /* beginning of sctp packet */ const u_char *bp2, /* beginning of enclosing */ u_int sctpPacketLength) /* ip packet */ { const struct sctpHeader *sctpPktHdr; const struct ip *ip; #ifdef INET6 const struct ip6_hdr *ip6; #endif const void *endPacketPtr; u_short sourcePort, destPort; int chunkCount; const struct sctpChunkDesc *chunkDescPtr; const void *nextChunk; const char *sep; int isforces = 0; sctpPktHdr = (const struct sctpHeader*) bp; endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength; if( (u_long) endPacketPtr > (u_long) snapend) endPacketPtr = (const void *) snapend; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; #endif /*INET6*/ TCHECK(*sctpPktHdr); if (sctpPacketLength < sizeof(struct sctpHeader)) { (void)printf("truncated-sctp - %ld bytes missing!", (long)sctpPacketLength-sizeof(struct sctpHeader)); return; } /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */ /* is now only as long as the payload */ sourcePort = EXTRACT_16BITS(&sctpPktHdr->source); destPort = EXTRACT_16BITS(&sctpPktHdr->destination); #ifdef INET6 if (ip6) { (void)printf("%s.%d > %s.%d: sctp", ip6addr_string(&ip6->ip6_src), sourcePort, ip6addr_string(&ip6->ip6_dst), destPort); } else #endif /*INET6*/ { (void)printf("%s.%d > %s.%d: sctp", ipaddr_string(&ip->ip_src), sourcePort, ipaddr_string(&ip->ip_dst), destPort); } fflush(stdout); if (isForCES_port(sourcePort)) { printf("[%s]", tok2str(ForCES_channels, NULL, sourcePort)); isforces = 1; } if (isForCES_port(destPort)) { printf("[%s]", tok2str(ForCES_channels, NULL, destPort)); isforces = 1; } if (vflag >= 2) sep = "\n\t"; else sep = " ("; /* cycle through all chunks, printing information on each one */ for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *) ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader)); chunkDescPtr != NULL && ( (const void *) ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc)) <= endPacketPtr); chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++) { u_int16_t chunkLength; const u_char *chunkEnd; u_int16_t align; TCHECK(*chunkDescPtr); chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength); if (chunkLength < sizeof(*chunkDescPtr)) { printf("%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength); break; } TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength); chunkEnd = ((const u_char*)chunkDescPtr + chunkLength); align=chunkLength % 4; if (align != 0) align = 4 - align; nextChunk = (const void *) (chunkEnd + align); printf("%s%d) ", sep, chunkCount+1); switch (chunkDescPtr->chunkID) { case SCTP_DATA : { const struct sctpDataPart *dataHdrPtr; printf("[DATA] "); if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) printf("(U)"); if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) printf("(B)"); if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) printf("(E)"); if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) || ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) || ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ) printf(" "); dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1); printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN)); printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId)); printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence)); printf("[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr->payloadtype)); fflush(stdout); if (isforces) { const u_char *payloadPtr; u_int chunksize = sizeof(struct sctpDataPart)+ sizeof(struct sctpChunkDesc); payloadPtr = (const u_char *) (dataHdrPtr + 1); if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) < sizeof(struct sctpDataPart)+ sizeof(struct sctpChunkDesc)+1) { /* Less than 1 byte of chunk payload */ printf("bogus ForCES chunk length %u]", EXTRACT_16BITS(&chunkDescPtr->chunkLength)); return; } forces_print(payloadPtr, EXTRACT_16BITS(&chunkDescPtr->chunkLength)- chunksize); } else if (vflag >= 2) { /* if verbose output is specified */ /* at the command line */ const u_char *payloadPtr; printf("[Payload"); if (!suppress_default_print) { payloadPtr = (const u_char *) (++dataHdrPtr); printf(":"); if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) < sizeof(struct sctpDataPart)+ sizeof(struct sctpChunkDesc)+1) { /* Less than 1 byte of chunk payload */ printf("bogus chunk length %u]", EXTRACT_16BITS(&chunkDescPtr->chunkLength)); return; } default_print(payloadPtr, EXTRACT_16BITS(&chunkDescPtr->chunkLength) - (sizeof(struct sctpDataPart)+ sizeof(struct sctpChunkDesc))); } else printf("]"); } break; } case SCTP_INITIATION : { const struct sctpInitiation *init; printf("[INIT] "); init=(const struct sctpInitiation*)(chunkDescPtr+1); printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); #if(0) /* ALC you can add code for optional params here */ if( (init+1) < chunkEnd ) printf(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif break; } case SCTP_INITIATION_ACK : { const struct sctpInitiation *init; printf("[INIT ACK] "); init=(const struct sctpInitiation*)(chunkDescPtr+1); printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); #if(0) /* ALC you can add code for optional params here */ if( (init+1) < chunkEnd ) printf(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif break; } case SCTP_SELECTIVE_ACK: { const struct sctpSelectiveAck *sack; const struct sctpSelectiveFrag *frag; int fragNo, tsnNo; const u_char *dupTSN; printf("[SACK] "); sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1); printf("[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN)); printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd)); printf("[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc)); printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns)); /* print gaps */ for (frag = ( (const struct sctpSelectiveFrag *) ((const struct sctpSelectiveAck *) sack+1)), fragNo=0; (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc); frag++, fragNo++) printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ", fragNo+1, EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart), EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd)); /* print duplicate TSNs */ for (dupTSN = (const u_char *)frag, tsnNo=0; (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns); dupTSN += 4, tsnNo++) printf("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, EXTRACT_32BITS(dupTSN)); break; } case SCTP_HEARTBEAT_REQUEST : printf("[HB REQ] "); break; case SCTP_HEARTBEAT_ACK : printf("[HB ACK] "); break; case SCTP_ABORT_ASSOCIATION : printf("[ABORT] "); break; case SCTP_SHUTDOWN : printf("[SHUTDOWN] "); break; case SCTP_SHUTDOWN_ACK : printf("[SHUTDOWN ACK] "); break; case SCTP_OPERATION_ERR : printf("[OP ERR] "); break; case SCTP_COOKIE_ECHO : printf("[COOKIE ECHO] "); break; case SCTP_COOKIE_ACK : printf("[COOKIE ACK] "); break; case SCTP_ECN_ECHO : printf("[ECN ECHO] "); break; case SCTP_ECN_CWR : printf("[ECN CWR] "); break; case SCTP_SHUTDOWN_COMPLETE : printf("[SHUTDOWN COMPLETE] "); break; case SCTP_FORWARD_CUM_TSN : printf("[FOR CUM TSN] "); break; case SCTP_RELIABLE_CNTL : printf("[REL CTRL] "); break; case SCTP_RELIABLE_CNTL_ACK : printf("[REL CTRL ACK] "); break; default : printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID); return; } if (vflag < 2) sep = ", ("; } return; trunc: printf("[|sctp]"); return; }
/* * Print a single PDU. */ static void rpki_rtr_pdu_print (const u_char *tptr, u_int indent) { const rpki_rtr_pdu *pdu_header; u_int pdu_type, pdu_len, hexdump; const u_char *msg; pdu_header = (rpki_rtr_pdu *)tptr; pdu_type = pdu_header->pdu_type; pdu_len = EXTRACT_32BITS(pdu_header->length); hexdump = FALSE; printf("%sRPKI-RTRv%u, %s PDU (%u), length: %u", indent_string(8), pdu_header->version, tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type), pdu_type, pdu_len); switch (pdu_type) { /* * The following PDUs share the message format. */ case RPKI_RTR_SERIAL_NOTIFY_PDU: case RPKI_RTR_SERIAL_QUERY_PDU: case RPKI_RTR_END_OF_DATA_PDU: msg = (const u_char *)(pdu_header + 1); printf("%sCache-Nonce: 0x%04x, Serial: %u", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.cache_nonce), EXTRACT_32BITS(msg)); break; /* * The following PDUs share the message format. */ case RPKI_RTR_RESET_QUERY_PDU: case RPKI_RTR_CACHE_RESET_PDU: /* * Zero payload PDUs. */ break; case RPKI_RTR_CACHE_RESPONSE_PDU: printf("%sCache-Nonce: 0x%04x", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.cache_nonce)); break; case RPKI_RTR_IPV4_PREFIX_PDU: { rpki_rtr_pdu_ipv4_prefix *pdu; pdu = (rpki_rtr_pdu_ipv4_prefix *)tptr; printf("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ipaddr_string(pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags); } break; #ifdef INET6 case RPKI_RTR_IPV6_PREFIX_PDU: { rpki_rtr_pdu_ipv6_prefix *pdu; pdu = (rpki_rtr_pdu_ipv6_prefix *)tptr; printf("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ip6addr_string(pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags); } break; #endif case RPKI_RTR_ERROR_REPORT_PDU: { rpki_rtr_pdu_error_report *pdu; u_int encapsulated_pdu_length, text_length, tlen, error_code; u_char buf[80]; pdu = (rpki_rtr_pdu_error_report *)tptr; encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length); tlen = pdu_len; error_code = EXTRACT_16BITS(pdu->pdu_header.u.error_code); printf("%sError code: %s (%u), Encapsulated PDU length: %u", indent_string(indent+2), tok2str(rpki_rtr_error_codes, "Unknown", error_code), error_code, encapsulated_pdu_length); tptr += sizeof(*pdu); tlen -= sizeof(*pdu); /* * Recurse if there is an encapsulated PDU. */ if (encapsulated_pdu_length && (encapsulated_pdu_length <= tlen)) { printf("%s-----encapsulated PDU-----", indent_string(indent+4)); rpki_rtr_pdu_print(tptr, indent+2); } tptr += encapsulated_pdu_length; tlen -= encapsulated_pdu_length; /* * Extract, trail-zero and print the Error message. */ text_length = 0; if (tlen > 4) { text_length = EXTRACT_32BITS(tptr); tptr += 4; tlen -= 4; } if (text_length && (text_length <= tlen )) { memcpy(buf, tptr, MIN(sizeof(buf)-1, text_length)); buf[text_length] = '\0'; printf("%sError text: %s", indent_string(indent+2), buf); } } break; default: /* * Unknown data, please hexdump. */ hexdump = TRUE; } /* do we also want to see a hex dump ? */ if (vflag > 1 || (vflag && hexdump)) { print_unknown_data(tptr,"\n\t ", pdu_len); } }
void olsr_print (packetbody_t pptr, u_int length, int is_ipv6) { union { __capability const struct olsr_common *common; __capability const struct olsr_msg4 *msg4; __capability const struct olsr_msg6 *msg6; __capability const struct olsr_hello *hello; __capability const struct olsr_hello_link *hello_link; __capability const struct olsr_tc *tc; __capability const struct olsr_hna4 *hna; } ptr; u_int msg_type, msg_len, msg_tlen, hello_len; u_int16_t name_entry_type, name_entry_len; u_int name_entry_padding; u_int8_t link_type, neighbor_type; packetbody_t tptr, msg_data; tptr = pptr; if (length < sizeof(struct olsr_common)) { goto trunc; } if (!PACKET_HAS_SPACE(tptr, sizeof(struct olsr_common))) { goto trunc; } ptr.common = (__capability struct olsr_common *)tptr; length = MIN(length, EXTRACT_16BITS(ptr.common->packet_len)); printf("OLSRv%i, seq 0x%04x, length %u", (is_ipv6 == 0) ? 4 : 6, EXTRACT_16BITS(ptr.common->packet_seq), length); tptr += sizeof(struct olsr_common); /* * In non-verbose mode, just print version. */ if (vflag < 1) { return; } while (tptr < (pptr+length)) { union { __capability struct olsr_msg4 *v4; __capability struct olsr_msg6 *v6; } msgptr; int msg_len_valid = 0; if (!PACKET_HAS_SPACE(tptr, sizeof(struct olsr_msg4))) goto trunc; #if INET6 if (is_ipv6) { msgptr.v6 = (__capability struct olsr_msg6 *) tptr; msg_type = msgptr.v6->msg_type; msg_len = EXTRACT_16BITS(msgptr.v6->msg_len); if ((msg_len >= sizeof (struct olsr_msg6)) && (msg_len <= length)) msg_len_valid = 1; /* infinite loop check */ if (msg_type == 0 || msg_len == 0) { return; } printf("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" "\n\t vtime %.3lfs, msg-seq 0x%04x, length %u%s", tok2str(olsr_msg_values, "Unknown", msg_type), msg_type, ip6addr_string(msgptr.v6->originator), msgptr.v6->ttl, msgptr.v6->hopcount, ME_TO_DOUBLE(msgptr.v6->vtime), EXTRACT_16BITS(msgptr.v6->msg_seq), msg_len, (msg_len_valid == 0) ? " (invalid)" : ""); msg_tlen = msg_len - sizeof(struct olsr_msg6); msg_data = tptr + sizeof(struct olsr_msg6); } else /* (!is_ipv6) */ #endif /* INET6 */ { msgptr.v4 = (__capability struct olsr_msg4 *) tptr; msg_type = msgptr.v4->msg_type; msg_len = EXTRACT_16BITS(msgptr.v4->msg_len); if ((msg_len >= sizeof (struct olsr_msg4)) && (msg_len <= length)) msg_len_valid = 1; /* infinite loop check */ if (msg_type == 0 || msg_len == 0) { return; } printf("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" "\n\t vtime %.3lfs, msg-seq 0x%04x, length %u%s", tok2str(olsr_msg_values, "Unknown", msg_type), msg_type, ipaddr_string(msgptr.v4->originator), msgptr.v4->ttl, msgptr.v4->hopcount, ME_TO_DOUBLE(msgptr.v4->vtime), EXTRACT_16BITS(msgptr.v4->msg_seq), msg_len, (msg_len_valid == 0) ? " (invalid)" : ""); msg_tlen = msg_len - sizeof(struct olsr_msg4); msg_data = tptr + sizeof(struct olsr_msg4); } switch (msg_type) { case OLSR_HELLO_MSG: case OLSR_HELLO_LQ_MSG: if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_hello))) goto trunc; ptr.hello = (__capability struct olsr_hello *)msg_data; printf("\n\t hello-time %.3lfs, MPR willingness %u", ME_TO_DOUBLE(ptr.hello->htime), ptr.hello->will); msg_data += sizeof(struct olsr_hello); msg_tlen -= sizeof(struct olsr_hello); while (msg_tlen >= sizeof(struct olsr_hello_link)) { int hello_len_valid = 0; /* * link-type. */ if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_hello_link))) goto trunc; ptr.hello_link = (__capability struct olsr_hello_link *)msg_data; hello_len = EXTRACT_16BITS(ptr.hello_link->len); link_type = OLSR_EXTRACT_LINK_TYPE(ptr.hello_link->link_code); neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(ptr.hello_link->link_code); if ((hello_len <= msg_tlen) && (hello_len >= sizeof(struct olsr_hello_link))) hello_len_valid = 1; printf("\n\t link-type %s, neighbor-type %s, len %u%s", tok2str(olsr_link_type_values, "Unknown", link_type), tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type), hello_len, (hello_len_valid == 0) ? " (invalid)" : ""); if (hello_len_valid == 0) break; msg_data += sizeof(struct olsr_hello_link); msg_tlen -= sizeof(struct olsr_hello_link); hello_len -= sizeof(struct olsr_hello_link); if (msg_type == OLSR_HELLO_MSG) { olsr_print_neighbor(msg_data, hello_len); } else { #if INET6 if (is_ipv6) olsr_print_lq_neighbor6(msg_data, hello_len); else #endif olsr_print_lq_neighbor4(msg_data, hello_len); } msg_data += hello_len; msg_tlen -= hello_len; } break; case OLSR_TC_MSG: case OLSR_TC_LQ_MSG: if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_tc))) goto trunc; ptr.tc = (__capability struct olsr_tc *)msg_data; printf("\n\t advertised neighbor seq 0x%04x", EXTRACT_16BITS(ptr.tc->ans_seq)); msg_data += sizeof(struct olsr_tc); msg_tlen -= sizeof(struct olsr_tc); if (msg_type == OLSR_TC_MSG) { olsr_print_neighbor(msg_data, msg_tlen); } else { #if INET6 if (is_ipv6) olsr_print_lq_neighbor6(msg_data, msg_tlen); else #endif olsr_print_lq_neighbor4(msg_data, msg_tlen); } break; case OLSR_MID_MSG: { size_t addr_size = sizeof(struct in_addr); #if INET6 if (is_ipv6) addr_size = sizeof(struct in6_addr); #endif while (msg_tlen >= addr_size) { if (!PACKET_HAS_SPACE(msg_data, addr_size)) goto trunc; printf("\n\t interface address %s", #if INET6 is_ipv6 ? ip6addr_string(msg_data) : #endif ipaddr_string(msg_data)); msg_data += addr_size; msg_tlen -= addr_size; } break; } case OLSR_HNA_MSG: printf("\n\t Advertised networks (total %u)", (unsigned int) (msg_tlen / sizeof(struct olsr_hna6))); #if INET6 if (is_ipv6) { int i = 0; while (msg_tlen >= sizeof(struct olsr_hna6)) { __capability struct olsr_hna6 *hna6; if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_hna6))) goto trunc; hna6 = (__capability struct olsr_hna6 *)msg_data; printf("\n\t #%i: %s/%u", i, ip6addr_string(hna6->network), mask62plen (hna6->mask)); msg_data += sizeof(struct olsr_hna6); msg_tlen -= sizeof(struct olsr_hna6); } } else #endif { int col = 0; while (msg_tlen >= sizeof(struct olsr_hna4)) { if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_hna4))) goto trunc; ptr.hna = (__capability struct olsr_hna4 *)msg_data; /* print 4 prefixes per line */ if (col == 0) printf ("\n\t "); else printf (", "); printf("%s/%u", ipaddr_string(ptr.hna->network), mask2plen(EXTRACT_32BITS(ptr.hna->mask))); msg_data += sizeof(struct olsr_hna4); msg_tlen -= sizeof(struct olsr_hna4); col = (col + 1) % 4; } } break; case OLSR_NAMESERVICE_MSG: { u_int name_entries = EXTRACT_16BITS(msg_data+2); u_int addr_size = 4; int name_entries_valid = 0; u_int i; if (is_ipv6) addr_size = 16; if ((name_entries > 0) && ((name_entries * (4 + addr_size)) <= msg_tlen)) name_entries_valid = 1; if (msg_tlen < 4) goto trunc; if (!PACKET_HAS_SPACE(msg_data, 4)) goto trunc; printf("\n\t Version %u, Entries %u%s", EXTRACT_16BITS(msg_data), name_entries, (name_entries_valid == 0) ? " (invalid)" : ""); if (name_entries_valid == 0) break; msg_data += 4; msg_tlen -= 4; for (i = 0; i < name_entries; i++) { int name_entry_len_valid = 0; if (msg_tlen < 4) break; if (!PACKET_HAS_SPACE(msg_data, 4)) goto trunc; name_entry_type = EXTRACT_16BITS(msg_data); name_entry_len = EXTRACT_16BITS(msg_data+2); msg_data += 4; msg_tlen -= 4; if ((name_entry_len > 0) && ((addr_size + name_entry_len) <= msg_tlen)) name_entry_len_valid = 1; printf("\n\t #%u: type %#06x, length %u%s", (unsigned int) i, name_entry_type, name_entry_len, (name_entry_len_valid == 0) ? " (invalid)" : ""); if (name_entry_len_valid == 0) break; /* 32-bit alignment */ name_entry_padding = 0; if (name_entry_len%4 != 0) name_entry_padding = 4-(name_entry_len%4); if (msg_tlen < addr_size + name_entry_len + name_entry_padding) goto trunc; if (!PACKET_HAS_SPACE(msg_data, addr_size + name_entry_len + name_entry_padding)) goto trunc; #if INET6 if (is_ipv6) printf(", address %s, name \"", ip6addr_string(msg_data)); else #endif printf(", address %s, name \"", ipaddr_string(msg_data)); fn_printn(msg_data + addr_size, name_entry_len, NULL); printf("\""); msg_data += addr_size + name_entry_len + name_entry_padding; msg_tlen -= addr_size + name_entry_len + name_entry_padding; } /* for (i = 0; i < name_entries; i++) */ break; } /* case OLSR_NAMESERVICE_MSG */ /* * FIXME those are the defined messages that lack a decoder * you are welcome to contribute code ;-) */ case OLSR_POWERINFO_MSG: default: print_unknown_data(msg_data, "\n\t ", msg_tlen); break; } /* switch (msg_type) */ tptr += msg_len; } /* while (tptr < (pptr+length)) */ return; trunc: printf("[|olsr]"); }
void arp_print(netdissect_options *ndo, const u_char *bp, u_int length, u_int caplen) { const struct arp_pkthdr *ap; u_short pro, hrd, op, linkaddr; ap = (const struct arp_pkthdr *)bp; ND_TCHECK(*ap); hrd = HRD(ap); pro = PRO(ap); op = OP(ap); /* if its ATM then call the ATM ARP printer for Frame-relay ARP most of the fields are similar to Ethernet so overload the Ethernet Printer and set the linkaddr type for linkaddr_string() accordingly */ switch(hrd) { case ARPHRD_ATM2225: atmarp_print(ndo, bp, length, caplen); return; case ARPHRD_FRELAY: linkaddr = LINKADDR_FRELAY; break; default: linkaddr = LINKADDR_ETHER; break; } if (!ND_TTEST2(*ar_tpa(ap), PROTO_LEN(ap))) { ND_PRINT((ndo, "[|ARP]")); ND_DEFAULTPRINT((const u_char *)ap, length); return; } if (!ndo->ndo_eflag) { ND_PRINT((ndo, "ARP, ")); } /* print hardware type/len and proto type/len */ if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) || PROTO_LEN(ap) != 4 || HRD_LEN(ap) == 0 || ndo->ndo_vflag) { ND_PRINT((ndo, "%s (len %u), %s (len %u)", tok2str(arphrd_values, "Unknown Hardware (%u)", hrd), HRD_LEN(ap), tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro), PROTO_LEN(ap))); /* don't know know about the address formats */ if (!ndo->ndo_vflag) { goto out; } } /* print operation */ printf("%s%s ", ndo->ndo_vflag ? ", " : "", tok2str(arpop_values, "Unknown (%u)", op)); switch (op) { case ARPOP_REQUEST: ND_PRINT((ndo, "who-has %s", ipaddr_string(TPA(ap)))); if (memcmp((const char *)ezero, (const char *)THA(ap), HRD_LEN(ap)) != 0) ND_PRINT((ndo, " (%s)", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)))); ND_PRINT((ndo, " tell %s", ipaddr_string(SPA(ap)))); break; case ARPOP_REPLY: ND_PRINT((ndo, "%s is-at %s", ipaddr_string(SPA(ap)), linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap)))); break; case ARPOP_REVREQUEST: ND_PRINT((ndo, "who-is %s tell %s", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap)))); break; case ARPOP_REVREPLY: ND_PRINT((ndo, "%s at %s", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), ipaddr_string(TPA(ap)))); break; case ARPOP_INVREQUEST: ND_PRINT((ndo, "who-is %s tell %s", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap)))); break; case ARPOP_INVREPLY: ND_PRINT((ndo,"%s at %s", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), ipaddr_string(TPA(ap)))); break; default: ND_DEFAULTPRINT((const u_char *)ap, caplen); return; } out: ND_PRINT((ndo, ", length %u", length)); return; trunc: ND_PRINT((ndo, "[|ARP]")); }
static void chdlc_slarp_print(netdissect_options *ndo, const u_char *cp, u_int length) { const struct cisco_slarp *slarp; u_int sec,min,hrs,days; ND_PRINT((ndo, "SLARP (length: %u), ",length)); if (length < SLARP_MIN_LEN) goto trunc; slarp = (const struct cisco_slarp *)cp; ND_TCHECK2(*slarp, SLARP_MIN_LEN); switch (EXTRACT_32BITS(&slarp->code)) { case SLARP_REQUEST: ND_PRINT((ndo, "request")); /* * At least according to William "Chops" Westfield's * message in * * http://www.nethelp.no/net/cisco-hdlc.txt * * the address and mask aren't used in requests - * they're just zero. */ break; case SLARP_REPLY: ND_PRINT((ndo, "reply %s/%s", ipaddr_string(ndo, &slarp->un.addr.addr), ipaddr_string(ndo, &slarp->un.addr.mask))); break; case SLARP_KEEPALIVE: ND_PRINT((ndo, "keepalive: mineseen=0x%08x, yourseen=0x%08x, reliability=0x%04x", EXTRACT_32BITS(&slarp->un.keep.myseq), EXTRACT_32BITS(&slarp->un.keep.yourseq), EXTRACT_16BITS(&slarp->un.keep.rel))); if (length >= SLARP_MAX_LEN) { /* uptime-stamp is optional */ cp += SLARP_MIN_LEN; ND_TCHECK2(*cp, 4); sec = EXTRACT_32BITS(cp) / 1000; min = sec / 60; sec -= min * 60; hrs = min / 60; min -= hrs * 60; days = hrs / 24; hrs -= days * 24; ND_PRINT((ndo, ", link uptime=%ud%uh%um%us",days,hrs,min,sec)); } break; default: ND_PRINT((ndo, "0x%02x unknown", EXTRACT_32BITS(&slarp->code))); if (ndo->ndo_vflag <= 1) print_unknown_data(ndo,cp+4,"\n\t",length-4); break; } if (SLARP_MAX_LEN < length && ndo->ndo_vflag) ND_PRINT((ndo, ", (trailing junk: %d bytes)", length - SLARP_MAX_LEN)); if (ndo->ndo_vflag > 1) print_unknown_data(ndo,cp+4,"\n\t",length-4); return; trunc: ND_PRINT((ndo, "[|slarp]")); }
static int ldp_pdu_print(netdissect_options *ndo, const u_char *pptr) { const struct ldp_common_header *ldp_com_header; const struct ldp_msg_header *ldp_msg_header; const u_char *tptr,*msg_tptr; u_short tlen; u_short pdu_len,msg_len,msg_type,msg_tlen; int hexdump,processed; ldp_com_header = (const struct ldp_common_header *)pptr; ND_TCHECK_SIZE(ldp_com_header); /* * Sanity checking of the header. */ if (EXTRACT_BE_U_2(ldp_com_header->version) != LDP_VERSION) { ND_PRINT("%sLDP version %u packet not supported", (ndo->ndo_vflag < 1) ? "" : "\n\t", EXTRACT_BE_U_2(ldp_com_header->version)); return 0; } pdu_len = EXTRACT_BE_U_2(ldp_com_header->pdu_length); if (pdu_len < sizeof(struct ldp_common_header)-4) { /* length too short */ ND_PRINT("%sLDP, pdu-length: %u (too short, < %u)", (ndo->ndo_vflag < 1) ? "" : "\n\t", pdu_len, (u_int)(sizeof(struct ldp_common_header)-4)); return 0; } /* print the LSR-ID, label-space & length */ ND_PRINT("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", (ndo->ndo_vflag < 1) ? "" : "\n\t", ipaddr_string(ndo, &ldp_com_header->lsr_id), EXTRACT_BE_U_2(ldp_com_header->label_space), pdu_len); /* bail out if non-verbose */ if (ndo->ndo_vflag < 1) return 0; /* ok they seem to want to know everything - lets fully decode it */ tptr = pptr + sizeof(struct ldp_common_header); tlen = pdu_len - (sizeof(struct ldp_common_header)-4); /* Type & Length fields not included */ while(tlen>0) { /* did we capture enough for fully decoding the msg header ? */ ND_TCHECK_LEN(tptr, sizeof(struct ldp_msg_header)); ldp_msg_header = (const struct ldp_msg_header *)tptr; msg_len=EXTRACT_BE_U_2(ldp_msg_header->length); msg_type=LDP_MASK_MSG_TYPE(EXTRACT_BE_U_2(ldp_msg_header->type)); if (msg_len < sizeof(struct ldp_msg_header)-4) { /* length too short */ /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s Message (0x%04x), length: %u (too short, < %u)", tok2str(ldp_msg_values, "Unknown", msg_type), msg_type, msg_len, (u_int)(sizeof(struct ldp_msg_header)-4)); return 0; } /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", tok2str(ldp_msg_values, "Unknown", msg_type), msg_type, msg_len, EXTRACT_BE_U_4(ldp_msg_header->id), LDP_MASK_U_BIT(EXTRACT_BE_U_2(ldp_msg_header->type)) ? "continue processing" : "ignore"); msg_tptr=tptr+sizeof(struct ldp_msg_header); msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */ /* did we capture enough for fully decoding the message ? */ ND_TCHECK_LEN(tptr, msg_len); hexdump=FALSE; switch(msg_type) { case LDP_MSG_NOTIF: case LDP_MSG_HELLO: case LDP_MSG_INIT: case LDP_MSG_KEEPALIVE: case LDP_MSG_ADDRESS: case LDP_MSG_LABEL_MAPPING: case LDP_MSG_ADDRESS_WITHDRAW: case LDP_MSG_LABEL_WITHDRAW: while(msg_tlen >= 4) { processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen); if (processed == 0) break; msg_tlen-=processed; msg_tptr+=processed; } break; /* * FIXME those are the defined messages that lack a decoder * you are welcome to contribute code ;-) */ case LDP_MSG_LABEL_REQUEST: case LDP_MSG_LABEL_RELEASE: case LDP_MSG_LABEL_ABORT_REQUEST: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, msg_tptr, "\n\t ", msg_tlen); break; } /* do we want to see an additionally hexdump ? */ if (ndo->ndo_vflag > 1 || hexdump==TRUE) print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t ", msg_len); tptr += msg_len+4; tlen -= msg_len+4; } return pdu_len+4; trunc: ND_PRINT("\n\t\t packet exceeded snapshot"); return 0; }
void vtp_print (netdissect_options *ndo, const u_char *pptr, u_int length) { int type, len, tlv_len, tlv_value, mgmtd_len; const u_char *tptr; const struct vtp_vlan_ *vtp_vlan; if (length < VTP_HEADER_LEN) goto trunc; tptr = pptr; ND_TCHECK2(*tptr, VTP_HEADER_LEN); type = *(tptr+1); ND_PRINT((ndo, "VTPv%u, Message %s (0x%02x), length %u", *tptr, tok2str(vtp_message_type_values,"Unknown message type", type), type, length)); /* In non-verbose mode, just print version and message type */ if (ndo->ndo_vflag < 1) { return; } /* verbose mode print all fields */ ND_PRINT((ndo, "\n\tDomain name: ")); mgmtd_len = *(tptr + 3); if (mgmtd_len < 1 || mgmtd_len > 32) { ND_PRINT((ndo, " [invalid MgmtD Len %d]", mgmtd_len)); return; } fn_printzp(ndo, tptr + 4, mgmtd_len, NULL); ND_PRINT((ndo, ", %s: %u", tok2str(vtp_header_values, "Unknown", type), *(tptr+2))); tptr += VTP_HEADER_LEN; switch (type) { case VTP_SUMMARY_ADV: /* * SUMMARY ADVERTISEMENT * * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Version | Code | Followers | MgmtD Len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Management Domain Name (zero-padded to 32 bytes) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Configuration revision number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Updater Identity IP address | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Update Timestamp (12 bytes) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | MD5 digest (16 bytes) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ ND_TCHECK2(*tptr, 8); ND_PRINT((ndo, "\n\t Config Rev %x, Updater %s", EXTRACT_32BITS(tptr), ipaddr_string(ndo, tptr+4))); tptr += 8; ND_TCHECK2(*tptr, VTP_UPDATE_TIMESTAMP_LEN); ND_PRINT((ndo, ", Timestamp 0x%08x 0x%08x 0x%08x", EXTRACT_32BITS(tptr), EXTRACT_32BITS(tptr + 4), EXTRACT_32BITS(tptr + 8))); tptr += VTP_UPDATE_TIMESTAMP_LEN; ND_TCHECK2(*tptr, VTP_MD5_DIGEST_LEN); ND_PRINT((ndo, ", MD5 digest: %08x%08x%08x%08x", EXTRACT_32BITS(tptr), EXTRACT_32BITS(tptr + 4), EXTRACT_32BITS(tptr + 8), EXTRACT_32BITS(tptr + 12))); tptr += VTP_MD5_DIGEST_LEN; break; case VTP_SUBSET_ADV: /* * SUBSET ADVERTISEMENT * * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Version | Code | Seq number | MgmtD Len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Management Domain Name (zero-padded to 32 bytes) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Configuration revision number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VLAN info field 1 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ................ | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VLAN info field N | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ ND_TCHECK_32BITS(tptr); ND_PRINT((ndo, ", Config Rev %x", EXTRACT_32BITS(tptr))); /* * VLAN INFORMATION * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | V info len | Status | VLAN type | VLAN name len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ISL vlan id | MTU size | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | 802.10 index (SAID) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VLAN name | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ tptr += 4; while (tptr < (pptr+length)) { ND_TCHECK_8BITS(tptr); len = *tptr; if (len == 0) break; ND_TCHECK2(*tptr, len); vtp_vlan = (const struct vtp_vlan_*)tptr; if (len < VTP_VLAN_INFO_FIXED_PART_LEN) goto trunc; ND_TCHECK(*vtp_vlan); ND_PRINT((ndo, "\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name ", tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status), tok2str(vtp_vlan_type_values,"Unknown",vtp_vlan->type), EXTRACT_16BITS(&vtp_vlan->vlanid), EXTRACT_16BITS(&vtp_vlan->mtu), EXTRACT_32BITS(&vtp_vlan->index))); len -= VTP_VLAN_INFO_FIXED_PART_LEN; tptr += VTP_VLAN_INFO_FIXED_PART_LEN; if (len < 4*((vtp_vlan->name_len + 3)/4)) goto trunc; ND_TCHECK2(*tptr, vtp_vlan->name_len); fn_printzp(ndo, tptr, vtp_vlan->name_len, NULL); /* * Vlan names are aligned to 32-bit boundaries. */ len -= 4*((vtp_vlan->name_len + 3)/4); tptr += 4*((vtp_vlan->name_len + 3)/4); /* TLV information follows */ while (len > 0) { /* * Cisco specs say 2 bytes for type + 2 bytes for length; * see http://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm * However, actual packets on the wire appear to use 1 * byte for the type and 1 byte for the length, so that's * what we do. */ if (len < 2) goto trunc; ND_TCHECK2(*tptr, 2); type = *tptr; tlv_len = *(tptr+1); ND_PRINT((ndo, "\n\t\t%s (0x%04x) TLV", tok2str(vtp_vlan_tlv_values, "Unknown", type), type)); if (len < tlv_len * 2 + 2) { ND_PRINT((ndo, " (TLV goes past the end of the packet)")); return; } ND_TCHECK2(*tptr, tlv_len * 2 +2); /* * We assume the value is a 2-byte integer; the length is * in units of 16-bit words. */ if (tlv_len != 1) { ND_PRINT((ndo, " (invalid TLV length %u != 1)", tlv_len)); return; } else { tlv_value = EXTRACT_16BITS(tptr+2); switch (type) { case VTP_VLAN_STE_HOP_COUNT: ND_PRINT((ndo, ", %u", tlv_value)); break; case VTP_VLAN_PRUNING: ND_PRINT((ndo, ", %s (%u)", tlv_value == 1 ? "Enabled" : "Disabled", tlv_value)); break; case VTP_VLAN_STP_TYPE: ND_PRINT((ndo, ", %s (%u)", tok2str(vtp_stp_type_values, "Unknown", tlv_value), tlv_value)); break; case VTP_VLAN_BRIDGE_TYPE: ND_PRINT((ndo, ", %s (%u)", tlv_value == 1 ? "SRB" : "SRT", tlv_value)); break; case VTP_VLAN_BACKUP_CRF_MODE: ND_PRINT((ndo, ", %s (%u)", tlv_value == 1 ? "Backup" : "Not backup", tlv_value)); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER: case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER: case VTP_VLAN_PARENT_VLAN: case VTP_VLAN_TRANS_BRIDGED_VLAN: case VTP_VLAN_ARP_HOP_COUNT: default: print_unknown_data(ndo, tptr, "\n\t\t ", 2 + tlv_len*2); break; } } len -= 2 + tlv_len*2; tptr += 2 + tlv_len*2; } } break; case VTP_ADV_REQUEST: /* * ADVERTISEMENT REQUEST * * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Version | Code | Reserved | MgmtD Len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Management Domain Name (zero-padded to 32 bytes) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Start value | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ ND_TCHECK2(*tptr, 4); ND_PRINT((ndo, "\n\tStart value: %u", EXTRACT_32BITS(tptr))); break; case VTP_JOIN_MESSAGE: /* FIXME - Could not find message format */ break; default: break; } return; trunc: ND_PRINT((ndo, "[|vtp]")); }
void tcp_print(register const u_char *bp, register u_int length, register const u_char *bp2) { register const struct tcphdr *tp; register const struct ip *ip; register u_char flags; register int hlen; register char ch; u_short sport, dport, win, urp; u_int32_t seq, ack; tp = (struct tcphdr *)bp; ip = (struct ip *)bp2; ch = '\0'; TCHECK(*tp); if (length < sizeof(*tp)) { (void)printf("truncated-tcp %d", length); return; } sport = ntohs(tp->th_sport); dport = ntohs(tp->th_dport); seq = ntohl(tp->th_seq); ack = ntohl(tp->th_ack); win = ntohs(tp->th_win); urp = ntohs(tp->th_urp); (void)printf("%s.%s > %s.%s: ", ipaddr_string(&ip->ip_src), tcpport_string(sport), ipaddr_string(&ip->ip_dst), tcpport_string(dport)); if (qflag) { (void)printf("tcp %d", length - tp->th_off * 4); return; } if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH)) { if (flags & TH_SYN) putchar('S'); if (flags & TH_FIN) putchar('F'); if (flags & TH_RST) putchar('R'); if (flags & TH_PUSH) putchar('P'); } else putchar('.'); if (!Sflag && (flags & TH_ACK)) { register struct tcp_seq_hash *th; register int rev; struct tha tha; /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ if (sport < dport || (sport == dport && ip->ip_src.s_addr < ip->ip_dst.s_addr)) { tha.src = ip->ip_src, tha.dst = ip->ip_dst; tha.port = sport << 16 | dport; rev = 0; } else { tha.src = ip->ip_dst, tha.dst = ip->ip_src; tha.port = dport << 16 | sport; rev = 1; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (!memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr))) break; if (!th->nxt || flags & TH_SYN) { /* didn't find it or new conversation */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } } hlen = tp->th_off * 4; if (hlen > length) { (void)printf(" [bad hdr length]"); return; } length -= hlen; if (length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) (void)printf(" %u:%u(%d)", seq, seq + length, length); if (flags & TH_ACK) (void)printf(" ack %u", ack); (void)printf(" win %d", win); if (flags & TH_URG) (void)printf(" urg %d", urp); /* * Handle any options. */ if ((hlen -= sizeof(*tp)) > 0) { register const u_char *cp; register int i, opt, len, datalen; cp = (const u_char *)tp + sizeof(*tp); putchar(' '); ch = '<'; while (hlen > 0) { putchar(ch); TCHECK(*cp); opt = *cp++; if (ZEROLENOPT(opt)) len = 1; else { TCHECK(*cp); len = *cp++; /* total including type, len */ if (len < 2 || len > hlen) goto bad; --hlen; /* account for length byte */ } --hlen; /* account for type byte */ datalen = 0; /* Bail if "l" bytes of data are not left or were not captured */ #define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); } switch (opt) { case TCPOPT_MAXSEG: (void)printf("mss"); datalen = 2; LENCHECK(datalen); (void)printf(" %u", EXTRACT_16BITS(cp)); break; case TCPOPT_EOL: (void)printf("eol"); break; case TCPOPT_NOP: (void)printf("nop"); break; case TCPOPT_WSCALE: (void)printf("wscale"); datalen = 1; LENCHECK(datalen); (void)printf(" %u", *cp); break; case TCPOPT_SACKOK: (void)printf("sackOK"); break; case TCPOPT_SACK: (void)printf("sack"); datalen = len - 2; for (i = 0; i < datalen; i += 4) { LENCHECK(i + 4); /* block-size@relative-origin */ (void)printf(" %u@%u", EXTRACT_16BITS(cp + i + 2), EXTRACT_16BITS(cp + i)); } if (datalen % 4) (void)printf("[len %d]", len); break; case TCPOPT_ECHO: (void)printf("echo"); datalen = 4; LENCHECK(datalen); (void)printf(" %u", EXTRACT_32BITS(cp)); break; case TCPOPT_ECHOREPLY: (void)printf("echoreply"); datalen = 4; LENCHECK(datalen); (void)printf(" %u", EXTRACT_32BITS(cp)); break; case TCPOPT_TIMESTAMP: (void)printf("timestamp"); datalen = 8; LENCHECK(4); (void)printf(" %u", EXTRACT_32BITS(cp)); LENCHECK(datalen); (void)printf(" %u", EXTRACT_32BITS(cp + 4)); break; case TCPOPT_CC: (void)printf("cc"); datalen = 4; LENCHECK(datalen); (void)printf(" %u", EXTRACT_32BITS(cp)); break; case TCPOPT_CCNEW: (void)printf("ccnew"); datalen = 4; LENCHECK(datalen); (void)printf(" %u", EXTRACT_32BITS(cp)); break; case TCPOPT_CCECHO: (void)printf("ccecho"); datalen = 4; LENCHECK(datalen); (void)printf(" %u", EXTRACT_32BITS(cp)); break; default: (void)printf("opt-%d:", opt); datalen = len - 2; for (i = 0; i < datalen; ++i) { LENCHECK(i); (void)printf("%02x", cp[i]); } break; } /* Account for data printed */ cp += datalen; hlen -= datalen; /* Check specification against observed length */ ++datalen; /* option octet */ if (!ZEROLENOPT(opt)) ++datalen; /* size octet */ if (datalen != len) (void)printf("[len %d]", len); ch = ','; if (opt == TCPOPT_EOL) break; } putchar('>'); } return; bad: fputs("[bad opt]", stdout); if (ch != '\0') putchar('>'); return; trunc: fputs("[|tcp]", stdout); if (ch != '\0') putchar('>'); }
void vrrp_print(netdissect_options *ndo, register const u_char *bp, register u_int len, register const u_char *bp2, int ttl) { int version, type, auth_type = VRRP_AUTH_NONE; /* keep compiler happy */ const char *type_s; ND_TCHECK(bp[0]); version = (bp[0] & 0xf0) >> 4; type = bp[0] & 0x0f; type_s = tok2str(type2str, "unknown type (%u)", type); ND_PRINT((ndo, "VRRPv%u, %s", version, type_s)); if (ttl != 255) ND_PRINT((ndo, ", (ttl %u)", ttl)); if (version < 2 || version > 3 || type != VRRP_TYPE_ADVERTISEMENT) return; ND_TCHECK(bp[2]); ND_PRINT((ndo, ", vrid %u, prio %u", bp[1], bp[2])); ND_TCHECK(bp[5]); if (version == 2) { auth_type = bp[4]; ND_PRINT((ndo, ", authtype %s", tok2str(auth2str, NULL, auth_type))); ND_PRINT((ndo, ", intvl %us, length %u", bp[5], len)); } else { /* version == 3 */ uint16_t intvl = (bp[4] & 0x0f) << 8 | bp[5]; ND_PRINT((ndo, ", intvl %ucs, length %u", intvl, len)); } if (ndo->ndo_vflag) { int naddrs = bp[3]; int i; char c; if (version == 2 && ND_TTEST2(bp[0], len)) { struct cksum_vec vec[1]; vec[0].ptr = bp; vec[0].len = len; if (in_cksum(vec, 1)) ND_PRINT((ndo, ", (bad vrrp cksum %x)", EXTRACT_16BITS(&bp[6]))); } if (version == 3 && ND_TTEST2(bp[0], len)) { uint16_t cksum = nextproto4_cksum(ndo, (const struct ip *)bp2, bp, len, len, IPPROTO_VRRP); if (cksum) ND_PRINT((ndo, ", (bad vrrp cksum %x)", EXTRACT_16BITS(&bp[6]))); } ND_PRINT((ndo, ", addrs")); if (naddrs > 1) ND_PRINT((ndo, "(%d)", naddrs)); ND_PRINT((ndo, ":")); c = ' '; bp += 8; for (i = 0; i < naddrs; i++) { ND_TCHECK(bp[3]); ND_PRINT((ndo, "%c%s", c, ipaddr_string(ndo, bp))); c = ','; bp += 4; } if (version == 2 && auth_type == VRRP_AUTH_SIMPLE) { /* simple text password */ ND_TCHECK(bp[7]); ND_PRINT((ndo, " auth \"")); if (fn_printn(ndo, bp, 8, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); } } return; trunc: ND_PRINT((ndo, "[|vrrp]")); }
u_int juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; struct juniper_ipsec_header { u_int8_t sa_index[2]; u_int8_t ttl; u_int8_t type; u_int8_t spi[4]; u_int8_t src_ip[4]; u_int8_t dst_ip[4]; }; u_int rewrite_len,es_type_bundle; const struct juniper_ipsec_header *ih; l2info.pictype = DLT_JUNIPER_ES; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; ih = (struct juniper_ipsec_header *)p; switch (ih->type) { case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE: case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE: rewrite_len = 0; es_type_bundle = 1; break; case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE: case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE: case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE: rewrite_len = 16; es_type_bundle = 0; default: printf("ES Invalid type %u, length %u", ih->type, l2info.length); return l2info.header_len; } l2info.length-=rewrite_len; p+=rewrite_len; if (eflag) { if (!es_type_bundle) { printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n", EXTRACT_16BITS(&ih->sa_index), ih->ttl, tok2str(juniper_ipsec_type_values,"Unknown",ih->type), ih->type, EXTRACT_32BITS(&ih->spi), ipaddr_string(EXTRACT_32BITS(&ih->src_ip)), ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)), l2info.length); } else { printf("ES SA, index %u, ttl %u type %s (%u), length %u\n", EXTRACT_16BITS(&ih->sa_index), ih->ttl, tok2str(juniper_ipsec_type_values,"Unknown",ih->type), ih->type, l2info.length); } } ip_print(gndo, p, l2info.length); return l2info.header_len; }
void tcp_print(netdissect_options *ndo, const u_char *bp, u_int length, const u_char *bp2, int fragmented) { const struct tcphdr *tp; const struct ip *ip; u_char flags; u_int hlen; char ch; uint16_t sport, dport, win, urp; uint32_t seq, ack, thseq, thack; u_int utoval; uint16_t magic; int rev; const struct ip6_hdr *ip6; ndo->ndo_protocol = "tcp"; tp = (const struct tcphdr *)bp; ip = (const struct ip *)bp2; if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; ch = '\0'; if (!ND_TTEST_2(tp->th_dport)) { if (ip6) { ND_PRINT("%s > %s:", ip6addr_string(ndo, ip6->ip6_src), ip6addr_string(ndo, ip6->ip6_dst)); } else { ND_PRINT("%s > %s:", ipaddr_string(ndo, ip->ip_src), ipaddr_string(ndo, ip->ip_dst)); } nd_print_trunc(ndo); return; } sport = GET_BE_U_2(tp->th_sport); dport = GET_BE_U_2(tp->th_dport); if (ip6) { if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) { ND_PRINT("%s.%s > %s.%s: ", ip6addr_string(ndo, ip6->ip6_src), tcpport_string(ndo, sport), ip6addr_string(ndo, ip6->ip6_dst), tcpport_string(ndo, dport)); } else { ND_PRINT("%s > %s: ", tcpport_string(ndo, sport), tcpport_string(ndo, dport)); } } else { if (GET_U_1(ip->ip_p) == IPPROTO_TCP) { ND_PRINT("%s.%s > %s.%s: ", ipaddr_string(ndo, ip->ip_src), tcpport_string(ndo, sport), ipaddr_string(ndo, ip->ip_dst), tcpport_string(ndo, dport)); } else { ND_PRINT("%s > %s: ", tcpport_string(ndo, sport), tcpport_string(ndo, dport)); } } ND_TCHECK_SIZE(tp); hlen = TH_OFF(tp) * 4; if (hlen < sizeof(*tp)) { ND_PRINT(" tcp %u [bad hdr length %u - too short, < %lu]", length - hlen, hlen, (unsigned long)sizeof(*tp)); return; } seq = GET_BE_U_4(tp->th_seq); ack = GET_BE_U_4(tp->th_ack); win = GET_BE_U_2(tp->th_win); urp = GET_BE_U_2(tp->th_urp); if (ndo->ndo_qflag) { ND_PRINT("tcp %u", length - hlen); if (hlen > length) { ND_PRINT(" [bad hdr length %u - too long, > %u]", hlen, length); } return; } flags = GET_U_1(tp->th_flags); ND_PRINT("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); if (!ndo->ndo_Sflag && (flags & TH_ACK)) { /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ rev = 0; if (ip6) { struct tcp_seq_hash6 *th; struct tcp_seq_hash6 *tcp_seq_hash; const void *src, *dst; struct tha6 tha; tcp_seq_hash = tcp_seq_hash6; src = (const void *)ip6->ip6_src; dst = (const void *)ip6->ip6_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(src, dst, sizeof(ip6->ip6_dst)) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, dst, sizeof(ip6->ip6_dst)); UNALIGNED_MEMCPY(&tha.dst, src, sizeof(ip6->ip6_src)); tha.port = ((u_int)dport) << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, dst, sizeof(ip6->ip6_dst)); UNALIGNED_MEMCPY(&tha.src, src, sizeof(ip6->ip6_src)); tha.port = ((u_int)sport) << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ /* calloc() return used by the 'tcp_seq_hash6' hash table: do not free() */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash6 *) calloc(1, sizeof(*th)); if (th->nxt == NULL) (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } else { struct tcp_seq_hash *th; struct tcp_seq_hash *tcp_seq_hash; struct tha tha; tcp_seq_hash = tcp_seq_hash4; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(ip->ip_src, ip->ip_dst, sizeof(ip->ip_dst)) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, ip->ip_dst, sizeof(ip->ip_dst)); UNALIGNED_MEMCPY(&tha.dst, ip->ip_src, sizeof(ip->ip_src)); tha.port = ((u_int)dport) << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, ip->ip_dst, sizeof(ip->ip_dst)); UNALIGNED_MEMCPY(&tha.src, ip->ip_src, sizeof(ip->ip_src)); tha.port = ((u_int)sport) << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ /* calloc() return used by the 'tcp_seq_hash4' hash table: do not free() */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } } else { /*fool gcc*/ thseq = thack = rev = 0; } if (hlen > length) { ND_PRINT(" [bad hdr length %u - too long, > %u]", hlen, length); return; } if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) { /* Check the checksum, if possible. */ uint16_t sum, tcp_sum; if (IP_V(ip) == 4) { if (ND_TTEST_LEN(tp->th_sport, length)) { sum = tcp_cksum(ndo, ip, tp, length); tcp_sum = GET_BE_U_2(tp->th_sum); ND_PRINT(", cksum 0x%04x", tcp_sum); if (sum != 0) ND_PRINT(" (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum)); else ND_PRINT(" (correct)"); } } else if (IP_V(ip) == 6 && ip6->ip6_plen) { if (ND_TTEST_LEN(tp->th_sport, length)) { sum = tcp6_cksum(ndo, ip6, tp, length); tcp_sum = GET_BE_U_2(tp->th_sum); ND_PRINT(", cksum 0x%04x", tcp_sum); if (sum != 0) ND_PRINT(" (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum)); else ND_PRINT(" (correct)"); } } } length -= hlen; if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { ND_PRINT(", seq %u", seq); if (length > 0) { ND_PRINT(":%u", seq + length); } } if (flags & TH_ACK) { ND_PRINT(", ack %u", ack); } ND_PRINT(", win %u", win); if (flags & TH_URG) ND_PRINT(", urg %u", urp); /* * Handle any options. */ if (hlen > sizeof(*tp)) { const u_char *cp; u_int i, opt, datalen; u_int len; hlen -= sizeof(*tp); cp = (const u_char *)tp + sizeof(*tp); ND_PRINT(", options ["); while (hlen > 0) { if (ch != '\0') ND_PRINT("%c", ch); ND_TCHECK_1(cp); opt = GET_U_1(cp); cp++; if (ZEROLENOPT(opt)) len = 1; else { ND_TCHECK_1(cp); len = GET_U_1(cp); cp++; /* total including type, len */ if (len < 2 || len > hlen) goto bad; --hlen; /* account for length byte */ } --hlen; /* account for type byte */ datalen = 0; /* Bail if "l" bytes of data are not left or were not captured */ #define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK_LEN(cp, l); } ND_PRINT("%s", tok2str(tcp_option_values, "unknown-%u", opt)); switch (opt) { case TCPOPT_MAXSEG: datalen = 2; LENCHECK(datalen); ND_PRINT(" %u", GET_BE_U_2(cp)); break; case TCPOPT_WSCALE: datalen = 1; LENCHECK(datalen); ND_PRINT(" %u", GET_U_1(cp)); break; case TCPOPT_SACK: datalen = len - 2; if (datalen % 8 != 0) { ND_PRINT(" invalid sack"); } else { uint32_t s, e; ND_PRINT(" %u ", datalen / 8); for (i = 0; i < datalen; i += 8) { LENCHECK(i + 4); s = GET_BE_U_4(cp + i); LENCHECK(i + 8); e = GET_BE_U_4(cp + i + 4); if (rev) { s -= thseq; e -= thseq; } else { s -= thack; e -= thack; } ND_PRINT("{%u:%u}", s, e); } } break; case TCPOPT_CC: case TCPOPT_CCNEW: case TCPOPT_CCECHO: case TCPOPT_ECHO: case TCPOPT_ECHOREPLY: /* * those options share their semantics. * fall through */ datalen = 4; LENCHECK(datalen); ND_PRINT(" %u", GET_BE_U_4(cp)); break; case TCPOPT_TIMESTAMP: datalen = 8; LENCHECK(datalen); ND_PRINT(" val %u ecr %u", GET_BE_U_4(cp), GET_BE_U_4(cp + 4)); break; case TCPOPT_SIGNATURE: datalen = TCP_SIGLEN; LENCHECK(datalen); ND_PRINT(" "); #ifdef HAVE_LIBCRYPTO switch (tcp_verify_signature(ndo, ip, tp, bp + TH_OFF(tp) * 4, length, cp)) { case SIGNATURE_VALID: ND_PRINT("valid"); break; case SIGNATURE_INVALID: nd_print_invalid(ndo); break; case CANT_CHECK_SIGNATURE: ND_PRINT("can't check - "); for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); break; } #else for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); #endif break; case TCPOPT_SCPS: datalen = 2; LENCHECK(datalen); ND_PRINT(" cap %02x id %u", GET_U_1(cp), GET_U_1(cp + 1)); break; case TCPOPT_TCPAO: datalen = len - 2; /* RFC 5925 Section 2.2: * "The Length value MUST be greater than or equal to 4." * (This includes the Kind and Length fields already processed * at this point.) */ if (datalen < 2) { nd_print_invalid(ndo); } else { LENCHECK(1); ND_PRINT(" keyid %u", GET_U_1(cp)); LENCHECK(2); ND_PRINT(" rnextkeyid %u", GET_U_1(cp + 1)); if (datalen > 2) { ND_PRINT(" mac 0x"); for (i = 2; i < datalen; i++) { LENCHECK(i + 1); ND_PRINT("%02x", GET_U_1(cp + i)); } } } break; case TCPOPT_EOL: case TCPOPT_NOP: case TCPOPT_SACKOK: /* * Nothing interesting. * fall through */ break; case TCPOPT_UTO: datalen = 2; LENCHECK(datalen); utoval = GET_BE_U_2(cp); ND_PRINT(" 0x%x", utoval); if (utoval & 0x0001) utoval = (utoval >> 1) * 60; else utoval >>= 1; ND_PRINT(" %u", utoval); break; case TCPOPT_MPTCP: datalen = len - 2; LENCHECK(datalen); if (!mptcp_print(ndo, cp-2, len, flags)) goto bad; break; case TCPOPT_FASTOPEN: datalen = len - 2; LENCHECK(datalen); ND_PRINT(" "); print_tcp_fastopen_option(ndo, cp, datalen, FALSE); break; case TCPOPT_EXPERIMENT2: datalen = len - 2; LENCHECK(datalen); if (datalen < 2) goto bad; /* RFC6994 */ magic = GET_BE_U_2(cp); ND_PRINT("-"); switch(magic) { case 0xf989: /* TCP Fast Open RFC 7413 */ print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE); break; default: /* Unknown magic number */ ND_PRINT("%04x", magic); break; } break; default: datalen = len - 2; if (datalen) ND_PRINT(" 0x"); for (i = 0; i < datalen; ++i) { LENCHECK(i + 1); ND_PRINT("%02x", GET_U_1(cp + i)); } break; } /* Account for data printed */ cp += datalen; hlen -= datalen; /* Check specification against observed length */ ++datalen; /* option octet */ if (!ZEROLENOPT(opt)) ++datalen; /* size octet */ if (datalen != len) ND_PRINT("[len %u]", len); ch = ','; if (opt == TCPOPT_EOL) break; } ND_PRINT("]"); }
/* print a reply */ static const u_char * ns_rprint(register const u_char *cp, register const u_char *bp) { register u_int i; register u_short typ, len; register const u_char *rp; if (vflag) { putchar(' '); cp = ns_nprint(cp, bp); } else cp = ns_nskip(cp, bp); if (cp + 10 > snapend) return (snapend); /* print the type/qtype and class (if it's not IN) */ typ = *cp++ << 8; typ |= *cp++; i = *cp++ << 8; i |= *cp++; if (i != C_IN) printf(" %s", tok2str(class2str, "(Class %d)", i)); /* ignore ttl */ cp += 4; len = *cp++ << 8; len |= *cp++; rp = cp + len; printf(" %s", tok2str(type2str, "Type%d", typ)); switch (typ) { case T_A: printf(" %s", ipaddr_string(cp)); break; case T_NS: case T_CNAME: case T_PTR: putchar(' '); (void)ns_nprint(cp, bp); break; case T_MX: putchar(' '); (void)ns_nprint(cp + 2, bp); printf(" %d", EXTRACT_16BITS(cp)); break; case T_TXT: putchar(' '); (void)ns_cprint(cp, bp); break; case T_UNSPECA: /* One long string */ printf(" %.*s", len, cp); break; } return (rp); /* XXX This isn't always right */ }
/* * Print bootp requests */ void bootp_print(netdissect_options *ndo, register const u_char *cp, u_int length) { register const struct bootp *bp; static const u_char vm_cmu[4] = VM_CMU; static const u_char vm_rfc1048[4] = VM_RFC1048; bp = (const struct bootp *)cp; ND_TCHECK(bp->bp_op); ND_PRINT((ndo, "BOOTP/DHCP, %s", tok2str(bootp_op_values, "unknown (0x%02x)", bp->bp_op))); if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) { ND_TCHECK2(bp->bp_chaddr[0], 6); ND_PRINT((ndo, " from %s", etheraddr_string(ndo, bp->bp_chaddr))); } ND_PRINT((ndo, ", length %u", length)); if (!ndo->ndo_vflag) return; ND_TCHECK(bp->bp_secs); /* The usual hardware address type is 1 (10Mb Ethernet) */ if (bp->bp_htype != 1) ND_PRINT((ndo, ", htype %d", bp->bp_htype)); /* The usual length for 10Mb Ethernet address is 6 bytes */ if (bp->bp_htype != 1 || bp->bp_hlen != 6) ND_PRINT((ndo, ", hlen %d", bp->bp_hlen)); /* Only print interesting fields */ if (bp->bp_hops) ND_PRINT((ndo, ", hops %d", bp->bp_hops)); if (EXTRACT_32BITS(&bp->bp_xid)) ND_PRINT((ndo, ", xid 0x%x", EXTRACT_32BITS(&bp->bp_xid))); if (EXTRACT_16BITS(&bp->bp_secs)) ND_PRINT((ndo, ", secs %d", EXTRACT_16BITS(&bp->bp_secs))); ND_PRINT((ndo, ", Flags [%s]", bittok2str(bootp_flag_values, "none", EXTRACT_16BITS(&bp->bp_flags)))); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, " (0x%04x)", EXTRACT_16BITS(&bp->bp_flags))); /* Client's ip address */ ND_TCHECK(bp->bp_ciaddr); if (EXTRACT_32BITS(&bp->bp_ciaddr.s_addr)) ND_PRINT((ndo, "\n\t Client-IP %s", ipaddr_string(ndo, &bp->bp_ciaddr))); /* 'your' ip address (bootp client) */ ND_TCHECK(bp->bp_yiaddr); if (EXTRACT_32BITS(&bp->bp_yiaddr.s_addr)) ND_PRINT((ndo, "\n\t Your-IP %s", ipaddr_string(ndo, &bp->bp_yiaddr))); /* Server's ip address */ ND_TCHECK(bp->bp_siaddr); if (EXTRACT_32BITS(&bp->bp_siaddr.s_addr)) ND_PRINT((ndo, "\n\t Server-IP %s", ipaddr_string(ndo, &bp->bp_siaddr))); /* Gateway's ip address */ ND_TCHECK(bp->bp_giaddr); if (EXTRACT_32BITS(&bp->bp_giaddr.s_addr)) ND_PRINT((ndo, "\n\t Gateway-IP %s", ipaddr_string(ndo, &bp->bp_giaddr))); /* Client's Ethernet address */ if (bp->bp_htype == 1 && bp->bp_hlen == 6) { ND_TCHECK2(bp->bp_chaddr[0], 6); ND_PRINT((ndo, "\n\t Client-Ethernet-Address %s", etheraddr_string(ndo, bp->bp_chaddr))); } ND_TCHECK2(bp->bp_sname[0], 1); /* check first char only */ if (*bp->bp_sname) { ND_PRINT((ndo, "\n\t sname \"")); if (fn_print(ndo, bp->bp_sname, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); ND_PRINT((ndo, "%s", tstr + 1)); return; } ND_PRINT((ndo, "\"")); } ND_TCHECK2(bp->bp_file[0], 1); /* check first char only */ if (*bp->bp_file) { ND_PRINT((ndo, "\n\t file \"")); if (fn_print(ndo, bp->bp_file, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); ND_PRINT((ndo, "%s", tstr + 1)); return; } ND_PRINT((ndo, "\"")); } /* Decode the vendor buffer */ ND_TCHECK(bp->bp_vend[0]); if (memcmp((const char *)bp->bp_vend, vm_rfc1048, sizeof(uint32_t)) == 0) rfc1048_print(ndo, bp->bp_vend); else if (memcmp((const char *)bp->bp_vend, vm_cmu, sizeof(uint32_t)) == 0) cmu_print(ndo, bp->bp_vend); else { uint32_t ul; ul = EXTRACT_32BITS(&bp->bp_vend); if (ul != 0) ND_PRINT((ndo, "\n\t Vendor-#0x%x", ul)); } return; trunc: ND_PRINT((ndo, "%s", tstr)); }
/* * Print a single link state advertisement. If truncated return 1, else 0. */ static int ospf_print_lsa(register const struct lsa *lsap) { register const u_char *ls_end; register const struct rlalink *rlp; register const struct tos_metric *tosp; register const struct in_addr *ap; register const struct aslametric *almp; register const struct mcla *mcp; register const u_int32_t *lp; register int j, k; if (ospf_print_lshdr(&lsap->ls_hdr)) return (1); TCHECK(lsap->ls_hdr.ls_length); ls_end = (u_char *)lsap + ntohs(lsap->ls_hdr.ls_length); switch (lsap->ls_hdr.ls_type) { case LS_TYPE_ROUTER: TCHECK(lsap->lsa_un.un_rla.rla_flags); ospf_print_bits(ospf_rla_flag_bits, lsap->lsa_un.un_rla.rla_flags); TCHECK(lsap->lsa_un.un_rla.rla_count); j = ntohs(lsap->lsa_un.un_rla.rla_count); TCHECK(lsap->lsa_un.un_rla.rla_link); rlp = lsap->lsa_un.un_rla.rla_link; while (j--) { TCHECK(*rlp); printf(" {"); /* } (ctags) */ switch (rlp->link_type) { case RLA_TYPE_VIRTUAL: printf(" virt"); /* Fall through */ case RLA_TYPE_ROUTER: printf(" nbrid %s if %s", ipaddr_string(&rlp->link_id), ipaddr_string(&rlp->link_data)); break; case RLA_TYPE_TRANSIT: printf(" dr %s if %s", ipaddr_string(&rlp->link_id), ipaddr_string(&rlp->link_data)); break; case RLA_TYPE_STUB: printf(" net %s mask %s", ipaddr_string(&rlp->link_id), ipaddr_string(&rlp->link_data)); break; default: /* { (ctags) */ printf(" ??RouterLinksType %d?? }", rlp->link_type); return (0); } printf(" tos 0 metric %d", ntohs(rlp->link_tos0metric)); tosp = (struct tos_metric *) ((sizeof rlp->link_tos0metric) + (u_char *) rlp); for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) { TCHECK(*tosp); printf(" tos %d metric %d", tosp->tos_type, ntohs(tosp->tos_metric)); } /* { (ctags) */ printf(" }"); rlp = (struct rlalink *)((u_char *)(rlp + 1) + ((rlp->link_toscount) * sizeof(*tosp))); } break; case LS_TYPE_NETWORK: TCHECK(lsap->lsa_un.un_nla.nla_mask); printf(" mask %s rtrs", ipaddr_string(&lsap->lsa_un.un_nla.nla_mask)); ap = lsap->lsa_un.un_nla.nla_router; while ((u_char *)ap < ls_end) { TCHECK(*ap); printf(" %s", ipaddr_string(ap)); ++ap; } break; case LS_TYPE_SUM_IP: TCHECK(lsap->lsa_un.un_nla.nla_mask); printf(" mask %s", ipaddr_string(&lsap->lsa_un.un_sla.sla_mask)); /* Fall through */ case LS_TYPE_SUM_ABR: TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); lp = lsap->lsa_un.un_sla.sla_tosmetric; while ((u_char *)lp < ls_end) { register u_int32_t ul; TCHECK(*lp); ul = ntohl(*lp); printf(" tos %d metric %d", (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS, ul & SLA_MASK_METRIC); ++lp; } break; case LS_TYPE_ASE: TCHECK(lsap->lsa_un.un_nla.nla_mask); printf(" mask %s", ipaddr_string(&lsap->lsa_un.un_asla.asla_mask)); TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); almp = lsap->lsa_un.un_asla.asla_metric; while ((u_char *)almp < ls_end) { register u_int32_t ul; TCHECK(almp->asla_tosmetric); ul = ntohl(almp->asla_tosmetric); printf(" type %d tos %d metric %d", (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1, (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS, (ul & ASLA_MASK_METRIC)); TCHECK(almp->asla_forward); if (almp->asla_forward.s_addr) { printf(" forward %s", ipaddr_string(&almp->asla_forward)); } TCHECK(almp->asla_tag); if (almp->asla_tag.s_addr) { printf(" tag %s", ipaddr_string(&almp->asla_tag)); } ++almp; } break; case LS_TYPE_GROUP: /* Multicast extensions as of 23 July 1991 */ mcp = lsap->lsa_un.un_mcla; while ((u_char *)mcp < ls_end) { TCHECK(mcp->mcla_vid); switch (ntohl(mcp->mcla_vtype)) { case MCLA_VERTEX_ROUTER: printf(" rtr rtrid %s", ipaddr_string(&mcp->mcla_vid)); break; case MCLA_VERTEX_NETWORK: printf(" net dr %s", ipaddr_string(&mcp->mcla_vid)); break; default: printf(" ??VertexType %u??", (u_int32_t)ntohl(mcp->mcla_vtype)); break; } ++mcp; } } /* { (ctags) */ fputs(" }", stdout); return (0); trunc: fputs(" }", stdout); return (1); }
static int ospf_decode_v2(register const struct ospfhdr *op, register const u_char *dataend) { register const struct in_addr *ap; register const struct lsr *lsrp; register const struct lsa_hdr *lshp; register const struct lsa *lsap; register u_int32_t lsa_count,lsa_count_max; switch (op->ospf_type) { case OSPF_TYPE_UMD: /* * Rob Coltun's special monitoring packets; * do nothing */ break; case OSPF_TYPE_HELLO: printf("\n\tOptions: [%s]", bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options)); TCHECK(op->ospf_hello.hello_deadint); printf("\n\t Hello Timer: %us, Dead Timer %us, Mask: %s, Priority: %u", EXTRACT_16BITS(&op->ospf_hello.hello_helloint), EXTRACT_32BITS(&op->ospf_hello.hello_deadint), ipaddr_string(&op->ospf_hello.hello_mask), op->ospf_hello.hello_priority); TCHECK(op->ospf_hello.hello_dr); if (op->ospf_hello.hello_dr.s_addr != 0) printf("\n\t Designated Router %s", ipaddr_string(&op->ospf_hello.hello_dr)); TCHECK(op->ospf_hello.hello_bdr); if (op->ospf_hello.hello_bdr.s_addr != 0) printf(", Backup Designated Router %s", ipaddr_string(&op->ospf_hello.hello_bdr)); ap = op->ospf_hello.hello_neighbor; if ((u_char *)ap < dataend) printf("\n\t Neighbor List:"); while ((u_char *)ap < dataend) { TCHECK(*ap); printf("\n\t %s", ipaddr_string(ap)); ++ap; } break; /* HELLO */ case OSPF_TYPE_DD: TCHECK(op->ospf_db.db_options); printf("\n\tOptions: [%s]", bittok2str(ospf_option_values,"none",op->ospf_db.db_options)); TCHECK(op->ospf_db.db_flags); printf(", DD Flags: [%s]", bittok2str(ospf_dd_flag_values,"none",op->ospf_db.db_flags)); if (vflag) { /* Print all the LS adv's */ lshp = op->ospf_db.db_lshdr; while (ospf_print_lshdr(lshp) != -1) { ++lshp; } } break; case OSPF_TYPE_LS_REQ: lsrp = op->ospf_lsr; while ((u_char *)lsrp < dataend) { TCHECK(*lsrp); printf("\n\t Advertising Router: %s, %s LSA (%u)", ipaddr_string(&lsrp->ls_router), tok2str(lsa_values,"unknown",EXTRACT_32BITS(lsrp->ls_type)), EXTRACT_32BITS(&lsrp->ls_type)); switch (EXTRACT_32BITS(lsrp->ls_type)) { /* the LSA header for opaque LSAs was slightly changed */ case LS_TYPE_OPAQUE_LL: case LS_TYPE_OPAQUE_AL: case LS_TYPE_OPAQUE_DW: printf(", Opaque-Type: %s LSA (%u), Opaque-ID: %u", tok2str(lsa_opaque_values, "unknown",lsrp->un_ls_stateid.opaque_field.opaque_type), lsrp->un_ls_stateid.opaque_field.opaque_type, EXTRACT_24BITS(&lsrp->un_ls_stateid.opaque_field.opaque_id)); break; default: printf(", LSA-ID: %s", ipaddr_string(&lsrp->un_ls_stateid.ls_stateid)); break; } ++lsrp; } break; case OSPF_TYPE_LS_UPDATE: lsap = op->ospf_lsu.lsu_lsa; TCHECK(op->ospf_lsu.lsu_count); lsa_count_max = EXTRACT_32BITS(&op->ospf_lsu.lsu_count); printf(", %d LSA%s",lsa_count_max, lsa_count_max > 1 ? "s" : ""); for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) { printf("\n\t LSA #%u",lsa_count); lsap = (const struct lsa *)ospf_print_lsa(lsap); if (lsap == NULL) goto trunc; } break; case OSPF_TYPE_LS_ACK: lshp = op->ospf_lsa.lsa_lshdr; while (ospf_print_lshdr(lshp) != -1) { ++lshp; } break; default: printf("v2 type (%d)", op->ospf_type); break; } return (0); trunc: return (1); }