static void _print_udp(int family, u_char *p, int length) { struct udp_hdr *udp; char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN]; if (family == AF_INET6) { struct ip6_hdr *ip6 = (struct ip6_hdr *)p; udp = (struct udp_hdr *)(p + IP6_HDR_LEN); ip6_ntop(&ip6->ip6_src, src, sizeof(src)); ip6_ntop(&ip6->ip6_dst, dst, sizeof(dst)); } else { struct ip_hdr *ip; ip = (struct ip_hdr *)p; udp = (struct udp_hdr *)(p + (ip->ip_hl * 4)); ip_ntop(&ip->ip_src, src, sizeof(src)); ip_ntop(&ip->ip_dst, dst, sizeof(dst)); } /* XXX - truncation? */ printf("%s.%d > %s.%d:", src, ntohs(udp->uh_sport), dst, ntohs(udp->uh_dport)); printf(" udp %d", ntohs(udp->uh_ulen) - UDP_HDR_LEN); }
char * addr_ntop(const struct addr *src, char *dst, size_t size) { if (src->addr_type == ADDR_TYPE_IP && size >= 20) { if (ip_ntop(&src->addr_ip, dst, size) != NULL) { if (src->addr_bits != IP_ADDR_BITS) sprintf(dst + strlen(dst), "/%d", src->addr_bits); return (dst); } } else if (src->addr_type == ADDR_TYPE_IP6 && size >= 42) { if (ip6_ntop(&src->addr_ip6, dst, size) != NULL) { if (src->addr_bits != IP6_ADDR_BITS) sprintf(dst + strlen(dst), "/%d", src->addr_bits); return (dst); } } else if (src->addr_type == ADDR_TYPE_ETH && size >= 18) { if (src->addr_bits == ETH_ADDR_BITS) return (eth_ntop(&src->addr_eth, dst, size)); } errno = EINVAL; return (NULL); }
void _print_tcp(int family, unsigned char *p, int length) { struct tcp_hdr *tcp; u_short sport, dport, win, urp; u_long seq, ack; int len, tcp_hl; register char ch; char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN]; if (family == AF_INET6) { struct ip6_hdr *ip6 = (struct ip6_hdr *)p; tcp = (struct tcp_hdr *)(p + IP6_HDR_LEN); len = length; ip6_ntop(&ip6->ip6_src, src, sizeof(src)); ip6_ntop(&ip6->ip6_dst, dst, sizeof(dst)); } else { struct ip_hdr *ip; ip = (struct ip_hdr *)p; tcp = (struct tcp_hdr *)(p + (ip->ip_hl * 4)); len = length - (ip->ip_hl * 4); ip_ntop(&ip->ip_src, src, sizeof(src)); ip_ntop(&ip->ip_dst, dst, sizeof(dst)); } if (len < TCP_HDR_LEN) { printf("truncated-tcp %d", len); return; } sport = ntohs(tcp->th_sport); dport = ntohs(tcp->th_dport); seq = ntohl(tcp->th_seq); ack = ntohl(tcp->th_ack); win = ntohs(tcp->th_win); urp = ntohs(tcp->th_urp); tcp_hl = tcp->th_off * 4; printf("%s.%d > %s.%d: ", src, sport, dst, dport); if (tcp->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_PUSH)) { if (tcp->th_flags & TH_SYN) putchar('S'); if (tcp->th_flags & TH_FIN) putchar('F'); if (tcp->th_flags & TH_RST) putchar('R'); if (tcp->th_flags & TH_PUSH) putchar('P'); } else putchar('.'); if (tcp_hl > len) { printf(" [bad hdr length]"); return; } len -= tcp_hl; if (len > 0 || tcp->th_flags & (TH_SYN | TH_FIN | TH_RST)) printf(" %lu:%lu(%d)", seq, seq + len, len); if (tcp->th_flags & TH_ACK) printf(" ack %lu", ack); printf(" win %d", win); if (tcp->th_flags & TH_URG) printf(" urg %d", urp); /* Handle options. */ if ((tcp_hl -= TCP_HDR_LEN) > 0) { register const u_char *cp; register int i, opt, len, datalen; cp = (const u_char *)tcp + TCP_HDR_LEN; putchar(' '); ch = '<'; while (tcp_hl > 0) { putchar(ch); opt = *cp++; if (TCP_OPT_TYPEONLY(opt)) { len = 1; } else { len = *cp++; /* total including type, len */ if (len < 2 || len > tcp_hl) goto bad; --tcp_hl; /* account for length byte */ } --tcp_hl; /* account for type byte */ datalen = 0; /* Bail if "l" bytes of data are not left or were not captured */ #define LENCHECK(l) { if ((l) > tcp_hl) goto bad; } switch (opt) { case TCP_OPT_MSS: printf("mss"); datalen = 2; LENCHECK(datalen); printf(" %u", EXTRACT_16BITS(cp)); break; case TCP_OPT_EOL: printf("eol"); break; case TCP_OPT_NOP: printf("nop"); break; case TCP_OPT_WSCALE: printf("wscale"); datalen = 1; LENCHECK(datalen); printf(" %u", *cp); break; case TCP_OPT_SACKOK: printf("sackOK"); if (len != 2) printf("[len %d]", len); break; case TCP_OPT_SACK: datalen = len - 2; if ((datalen % 8) != 0 || !(tcp->th_flags & TH_ACK)) { printf("malformed sack "); printf("[len %d] ", datalen); break; } printf("sack %d ", datalen / 8); break; case TCP_OPT_ECHO: printf("echo"); datalen = 4; LENCHECK(datalen); printf(" %u", EXTRACT_32BITS(cp)); break; case TCP_OPT_ECHOREPLY: printf("echoreply"); datalen = 4; LENCHECK(datalen); printf(" %u", EXTRACT_32BITS(cp)); break; case TCP_OPT_TIMESTAMP: printf("timestamp"); datalen = 8; LENCHECK(4); printf(" %u", EXTRACT_32BITS(cp)); LENCHECK(datalen); printf(" %u", EXTRACT_32BITS(cp + 4)); break; case TCP_OPT_CC: printf("cc"); datalen = 4; LENCHECK(datalen); printf(" %u", EXTRACT_32BITS(cp)); break; case TCP_OPT_CCNEW: printf("ccnew"); datalen = 4; LENCHECK(datalen); printf(" %u", EXTRACT_32BITS(cp)); break; case TCP_OPT_CCECHO: printf("ccecho"); datalen = 4; LENCHECK(datalen); printf(" %u", EXTRACT_32BITS(cp)); break; default: printf("opt-%d:", opt); datalen = len - 2; for (i = 0; i < datalen; ++i) { LENCHECK(i); printf("%02x", cp[i]); } break; } /* Account for data printed */ cp += datalen; tcp_hl -= datalen; /* Check specification against observed length */ ++datalen; /* option octet */ if (!TCP_OPT_TYPEONLY(opt)) ++datalen; /* size octet */ if (datalen != len) printf("[len %d]", len); ch = ','; if (opt == TCP_OPT_EOL) break; } putchar('>'); } return; bad: fputs("[bad opt]", stdout); if (ch != '\0') putchar('>'); return; }