123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446 |
- /*
- * mod_print.c
- *
- * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
- *
- * $Id: mod_print.c 2303 2009-05-06 18:48:20Z aturner $
- */
- #include "config.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "mod.h"
- #include "pkt.h"
- #ifndef INET6_ADDRSTRLEN
- #define INET6_ADDRSTRLEN 46
- #endif
- #define EXTRACT_16BITS(p) ((uint16_t)ntohs(*(uint16_t *)(p)))
- #define EXTRACT_32BITS(p) ((uint32_t)ntohl(*(uint32_t *)(p)))
- /* XXX - _print_* routines adapted from tcpdump */
- static void
- _print_icmp(u_char *p, int length)
- {
- struct ip_hdr *ip;
- struct icmp_hdr *icmp;
-
- ip = (struct ip_hdr *)p;
- icmp = (struct icmp_hdr *)(p + (ip->ip_hl * 4));
- /* XXX - truncation? */
- printf("%s > %s:", ip_ntoa(&ip->ip_src), ip_ntoa(&ip->ip_dst));
- printf(" icmp: type %d code %d", icmp->icmp_type, icmp->icmp_code);
- }
- static void
- _print_icmp6(u_char *p, int length)
- {
- struct ip6_hdr *ip6;
- struct icmp_hdr *icmp;
- ip6 = (struct ip6_hdr *)p;
- icmp = (struct icmp_hdr *)(p + IP6_HDR_LEN);
- /* XXX - truncation? */
- printf("%s > %s:", ip6_ntoa(&ip6->ip6_src), ip6_ntoa(&ip6->ip6_dst));
- printf(" icmp: type %hhu code %hhu", icmp->icmp_type, icmp->icmp_code);
- }
- 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;
- }
- 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);
- }
- static void
- _print_frag6(u_char *p, int length)
- {
- struct ip6_hdr *ip6;
- struct ip6_ext_hdr *ext;
- int off;
- ip6 = (struct ip6_hdr *)p;
- ext = (struct ip6_ext_hdr *)(p + IP6_HDR_LEN);
- off = htons(ext->ext_data.fragment.offlg & IP6_OFF_MASK);
- printf("%s > %s:", ip6_ntoa(&ip6->ip6_src), ip6_ntoa(&ip6->ip6_dst));
- printf(" fragment: next %hhu offset %d%s ident 0x%08x",
- ext->ext_nxt, off,
- (ext->ext_data.fragment.offlg & IP6_MORE_FRAG) ? " MF" : "",
- htonl(ext->ext_data.fragment.ident));
- }
- static void
- _print_ip(u_char *p, int length)
- {
- struct ip_hdr *ip;
- u_int ip_off, ip_hl, ip_len;
-
- ip = (struct ip_hdr *)p;
-
- if (length < IP_HDR_LEN) {
- printf("truncated-ip %d", length);
- return;
- }
- ip_hl = ip->ip_hl * 4;
- ip_len = ntohs(ip->ip_len);
-
- if (length < ip_len) {
- printf("truncated-ip - %d bytes missing!", ip_len - length);
- return;
- }
- ip_off = ntohs(ip->ip_off);
-
- /* Handle first fragment. */
- if ((ip_off & IP_OFFMASK) == 0) {
- switch (ip->ip_p) {
- case IP_PROTO_TCP:
- _print_tcp(AF_INET, p, ip_len);
- break;
- case IP_PROTO_UDP:
- _print_udp(AF_INET, p, ip_len);
- break;
- case IP_PROTO_ICMP:
- _print_icmp(p, ip_len);
- break;
- default:
- printf("%s > %s:", ip_ntoa(&ip->ip_src),
- ip_ntoa(&ip->ip_dst));
- printf(" ip-proto-%d %d", ip->ip_p, ip_len);
- break;
- }
- }
- /* Handle more frags. */
- if (ip_off & (IP_MF|IP_OFFMASK)) {
- if (ip_off & IP_OFFMASK)
- printf("%s > %s:", ip_ntoa(&ip->ip_src),
- ip_ntoa(&ip->ip_dst));
- printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), ip_len - ip_hl,
- (ip_off & IP_OFFMASK) << 3, (ip_off & IP_MF) ? "+" : "");
- } else if (ip_off & IP_DF)
- printf(" (DF)");
-
- if (ip->ip_tos)
- printf(" [tos 0x%x]", ip->ip_tos);
- if (ip->ip_ttl <= 1)
- printf(" [ttl %d]", ip->ip_ttl);
- }
- static void
- _print_ip6(u_char *p, int length)
- {
- struct ip6_hdr *ip6;
- int plen;
- ip6 = (struct ip6_hdr *)p;
- if (length < IP6_HDR_LEN) {
- printf("truncated-ip6 %d", length);
- return;
- }
- plen = htons(ip6->ip6_plen);
- switch (ip6->ip6_nxt) {
- case IP_PROTO_TCP:
- _print_tcp(AF_INET6, p, plen);
- break;
- case IP_PROTO_UDP:
- _print_udp(AF_INET6, p, plen);
- break;
- case IP_PROTO_ICMPV6:
- _print_icmp6(p, plen);
- break;
- case IP_PROTO_FRAGMENT:
- _print_frag6(p, plen);
- break;
- default:
- printf("%s > %s:", ip6_ntoa(&ip6->ip6_src),
- ip6_ntoa(&ip6->ip6_dst));
- printf(" ip-proto-%hhu ttl %hhu payload len %hu", ip6->ip6_nxt,
- ip6->ip6_hlim, plen);
- break;
- }
- if (ip6->ip6_hlim <= 1)
- printf(" [ttl %d]", ip6->ip6_hlim);
- }
- static void
- _print_eth(struct eth_hdr* e, int length)
- {
- char d[20], s[20];
- eth_ntop(&e->eth_dst, &d[0], sizeof(d));
- eth_ntop(&e->eth_src, &s[0], sizeof(s));
- printf("%s > %s type 0x%04hx length %d", d, s, htons(e->eth_type), length);
- }
- static char *
- timerntoa(struct timeval *tv)
- {
- static char buf[128];
- uint64_t usec;
- usec = (tv->tv_sec * 1000000) + tv->tv_usec;
-
- snprintf(buf, sizeof(buf), "%d.%03d ms",
- (int)(usec / 1000), (int)(usec % 1000));
-
- return (buf);
- }
- int
- print_apply(void *d, struct pktq *pktq)
- {
- struct pkt *pkt;
- TAILQ_FOREACH(pkt, pktq, pkt_next) {
- uint16_t eth_type = htons(pkt->pkt_eth->eth_type);
- if (eth_type == ETH_TYPE_IP)
- _print_ip(pkt->pkt_eth_data, pkt->pkt_end - pkt->pkt_eth_data);
- else if (eth_type == ETH_TYPE_IPV6)
- _print_ip6(pkt->pkt_eth_data, pkt->pkt_end - pkt->pkt_eth_data);
- else
- _print_eth(pkt->pkt_eth, pkt->pkt_end - pkt->pkt_data);
- if (timerisset(&pkt->pkt_ts))
- printf(" [delay %s]", timerntoa(&pkt->pkt_ts));
- printf("\n");
- }
- return (0);
- }
- struct mod mod_print = {
- "print", /* name */
- "print", /* usage */
- NULL, /* init */
- print_apply, /* apply */
- NULL /* close */
- };
|