1 Subject: a patch to make trafshow 3.1 IPv6 ready
2 From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
3 Date: Wed, 21 Mar 2001 04:46:17 +0900
4 Sender: itojun@itojun.org
5 Message-Id: <20010320194618.019727E73@starfruit.itojun.org>
7 the following patch makes trafshow 3.1 IPv6 ready.
8 there are a lot of internal changes, also i did not check
9 if it is compilable on systems with 4.3BSD-like sockaddr (without
10 sa_len). let me know if it makes sense to you.
12 note: (1) color does not work for IPv6. (2) pcap_lookupnet() is
13 skipped as the function does not work with IPv6-only machines.
14 basically, libpcap is to be blamed.
20 ===================================================================
21 RCS file: /cvsroot/apps/trafshow/addrtoname.c,v
22 retrieving revision 1.1.1.1
23 retrieving revision 1.2
24 diff -u -r1.1.1.1 -r1.2
25 --- addrtoname.c 2001/03/20 01:48:18 1.1.1.1
26 +++ addrtoname.c 2001/03/20 19:37:56 1.2
28 static u_int32_t f_localnet;
29 static u_int32_t netmask;
33 + struct in6_addr addr;
35 + struct h6namemem *nxt;
38 +struct h6namemem h6nametable[HASHNAMESIZE];
42 + struct sockaddr *sa;
44 + static char buf[NI_MAXHOST];
45 +#ifdef NI_WITHSCOPEID
46 + const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
48 + const int niflags = NI_NUMERICHOST;
51 + if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0,
59 * A faster replacement for inet_ntoa().
67 +extern char * getname6();
71 + struct sockaddr *sa;
74 + if (sa->sa_family == AF_INET)
75 + return getname((u_char *)&((struct sockaddr_in *)sa)->sin_addr);
76 + else /* sa->sa_family == AF_INET6 */
77 + return getname6(&((struct sockaddr_in6 *)sa)->sin6_addr);
82 + struct in6_addr *addr;
84 + register struct h6namemem *p;
85 + register struct hostent *hp = NULL;
88 + char buf[INET6_ADDRSTRLEN];
89 + static int oldtimer;
90 + static sigfunc oldalarm;
92 + bcopy(addr, temp, sizeof(temp));
93 + temp[0] ^= temp[1] ^ temp[2] ^ temp[3];
95 + p = &h6nametable[temp[0] & (HASHNAMESIZE-1)];
96 + for (; p->nxt; p = p->nxt) {
97 + if (bcmp(&p->addr, addr, sizeof(*addr)) == 0)
101 + p->nxt = (struct h6namemem *)calloc(1, sizeof (*p));
104 + * Only print names when:
105 + * (1) -n was not given.
106 + * (2) Address is foreign and -f was given. If -f was not
107 + * present, f_netmask and f_local are 0 and the second
108 + * test will succeed.
109 + * (3) The host portion is not 0 (i.e., a network address).
110 + * (4) The host portion is not broadcast.
112 + if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(addr) &&
113 + !IN6_IS_ADDR_LINKLOCAL(addr)) {
114 + oldtimer = alarm(dns_timeout);
115 + oldalarm = signal(SIGALRM, nohostname);
116 +#ifdef HAVE_SIGINTERRUPT
117 + if (!setjmp(getname_env))
119 + hp = gethostbyaddr((char *)&addr, sizeof(*addr), AF_INET6);
120 + (void)signal(SIGALRM, oldalarm);
121 + if (oldtimer < 1) oldtimer = 1;
122 + (void)alarm(oldtimer);
125 + if (Nflag && (cp = index(hp->h_name, '.')) != NULL) *cp = '\0';
127 + } else cp = inet_ntop(AF_INET6, addr, buf, sizeof(buf));
129 + p->name = (char *)malloc((unsigned)(strlen(cp) + 1));
130 + return strcpy(p->name, cp);
136 * Return a name for the IP address pointed to by ap. This address
138 ===================================================================
139 RCS file: /cvsroot/apps/trafshow/color.c,v
140 retrieving revision 1.1.1.1
141 retrieving revision 1.2
142 diff -u -r1.1.1.1 -r1.2
143 --- color.c 2001/03/20 01:48:18 1.1.1.1
144 +++ color.c 2001/03/20 19:37:56 1.2
145 @@ -386,15 +386,19 @@
146 register struct m_entry *m;
148 for (m = color_mask, i = 0; m != NULL, i < n_masks; m++, i++) {
149 - if ((e->src.s_addr & m->sm.s_addr) ^ m->src.s_addr)
150 + if (e->src.ss_family != AF_INET || e->dst.ss_family != AF_INET)
152 - if ((e->dst.s_addr & m->dm.s_addr) ^ m->dst.s_addr)
153 + if ((((struct sockaddr_in *)&e->src)->sin_addr.s_addr & m->sm.s_addr) ^ m->src.s_addr)
155 + if ((((struct sockaddr_in *)&e->dst)->sin_addr.s_addr & m->dm.s_addr) ^ m->dst.s_addr)
157 if (m->proto && e->proto != m->proto)
159 - if (m->sport && e->sport != m->sport)
161 + ((struct sockaddr_in *)&e->src)->sin_port == m->sport)
163 - if (m->dport && e->dport != m->dport)
165 + ((struct sockaddr_in *)&e->dst)->sin_port == m->dport)
168 attron(COLOR_PAIR(m->pair));
170 ===================================================================
171 RCS file: /cvsroot/apps/trafshow/display.c,v
172 retrieving revision 1.1.1.1
173 retrieving revision 1.2
174 diff -u -r1.1.1.1 -r1.2
175 --- display.c 2001/03/20 01:48:18 1.1.1.1
176 +++ display.c 2001/03/20 19:37:56 1.2
178 #include <netinet/ip_icmp.h>
179 #include <netinet/udp.h>
180 #include <netinet/tcp.h>
182 +#include <netinet/ip6.h>
183 +#include <netinet/icmp6.h>
189 #ifdef TIME_WITH_SYS_TIME
194 #include "trafshow.h"
197 * Pretty print an Internet address (net address + port).
200 -inet_print(in, port, proto)
202 - u_short port, proto;
203 +inet_print(sa, proto)
204 + struct sockaddr *sa;
210 "rtrsolicit", "timeexceed", "paramprobl", "stampreqst",
211 "stampreply", "inforeqst", "inforeply", "maskreqst",
215 + struct protoent *p;
217 + in = ((struct sockaddr_in *)sa)->sin_addr;
218 + port = ((struct sockaddr_in *)sa)->sin_port;
220 - if (l_nflag) cp = intoa(in.s_addr);
221 - else cp = ipaddr_string(&in);
225 + cp = saddr_string(sa);
226 (void) sprintf(aline, "%-*.*s", addr_size, addr_size, cp);
229 @@ -146,10 +159,16 @@
230 cp = udpport_string(port);
231 else if (proto == IPPROTO_ICMP && port <= ICMP_MAXTYPE)
232 cp = icmp_type[port];
233 - else cp = "unknown";
234 + else if ((p = getprotobynumber(proto)) != NULL)
240 + plen = sprintf(pline, "..%.10s", cp);
242 + plen = sprintf(pline, "..%10u", proto);
244 - plen = sprintf(pline, "..%.10s", cp);
246 if ((cp = strchr(aline, ' ')) != NULL)
248 else alen = addr_size;
251 proto = etherproto_string(entries[i].eh.ether_type);
253 - addstr(inet_print(entries[i].src, entries[i].sport, entries[i].proto));
254 + addstr(inet_print(&entries[i].src, entries[i].proto));
256 - addstr(inet_print(entries[i].dst, entries[i].dport, entries[i].proto));
257 + addstr(inet_print(&entries[i].dst, entries[i].proto));
259 proto = getprotoname(entries[i].proto);
260 if (proto == NULL) proto = "unknown";
266 +ipaddr_compar(s1, s2)
267 + struct sockaddr *s1, *s2;
270 + if (s1->sa_family != s2->sa_family)
272 + if (s1->sa_family == AF_INET) {
273 + struct sockaddr_in *sin1, *sin2;
275 + sin1 = (struct sockaddr_in *)s1;
276 + sin2 = (struct sockaddr_in *)s2;
277 + if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr)
279 + if (sin1->sin_port != sin2->sin_port)
284 + if (s1->sa_family == AF_INET6) {
285 + struct sockaddr_in6 *sin1, *sin2;
287 + sin1 = (struct sockaddr_in6 *)s1;
288 + sin2 = (struct sockaddr_in6 *)s2;
289 + if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr, &sin2->sin6_addr))
291 + if (sin1->sin6_port != sin2->sin6_port)
293 + if (sin1->sin6_scope_id != sin2->sin6_scope_id)
303 * Add new entry or add bytes to existed record.
306 j = page * page_size;
307 for (i = 0; i < n_entry; i++) {
308 if (memcmp(&e->eh, &entries[i].eh, sizeof(e->eh)) == 0 &&
309 - e->src.s_addr == entries[i].src.s_addr &&
310 - e->sport == entries[i].sport &&
311 - e->dst.s_addr == entries[i].dst.s_addr &&
312 - e->dport == entries[i].dport &&
313 + ipaddr_compar(&e->src, &e->src) &&
314 + ipaddr_compar(&e->dst, &e->dst) &&
315 e->proto == entries[i].proto) {
316 entries[i].bytes += e->bytes;
317 if (i >= j && i < j + page_size)
318 @@ -310,20 +364,51 @@
322 -display(eh, ip, length)
323 +display(eh, top, length)
324 struct ether_header *eh;
325 - register struct ip *ip;
331 + struct ip6_hdr *ip6;
334 int hlen, not_ip = 0;
337 + in_port_t sport, dport;
338 + struct sockaddr_in *sin;
340 + struct sockaddr_in6 *sin6;
345 - if ((u_char *)(ip + 1) > snapend) {
346 + ip = (struct ip *)top;
347 + switch (ip->ip_v) {
350 + minlen = sizeof(*ip);
351 + iplen = ntohs(ip->ip_len);
356 + ip6 = (struct ip6_hdr *)top;
357 + minlen = sizeof(*ip6);
358 + iplen = ntohs(ip6->ip6_plen) + sizeof(*ip6);
366 + if ((u_char *)top + minlen > snapend) {
367 if (!eflag) return; /* not ip proto? discard silently */
369 - } else if (length < sizeof(*ip)) {
370 + } else if (length < minlen) {
372 mvprintw(LINES-1, err_pos, "\
373 truncated-ip: discard %d bytes", length);
374 @@ -331,15 +416,15 @@
378 - } else if (ip->ip_v != IPVERSION) {
379 + } else if (af == 0) {
381 mvprintw(LINES-1, err_pos, "\
382 -ip ver != %d: discard %d bytes", IPVERSION, length);
383 +unsupported ip ver: discard %d bytes", length);
388 - } else if ((iplen = ntohs(ip->ip_len)) < 1) {
389 + } else if (iplen < 1) {
390 if (!eflag) return; /* empty ip packet? discard silently */
392 } else if (length < iplen) {
395 else memset(&te.eh, 0, sizeof(te.eh));
397 - te.sport = te.dport = 0;
400 - if (!not_ip) { /* parse ip packet */
401 + if (ip) { /* parse ip packet */
404 * If this is fragment zero, hand it to the next higher level
409 - te.sport = ntohs(((struct tcphdr *)cp)->th_sport);
410 - te.dport = ntohs(((struct tcphdr *)cp)->th_dport);
411 + sport = ntohs(((struct tcphdr *)cp)->th_sport);
412 + dport = ntohs(((struct tcphdr *)cp)->th_dport);
413 } else if (ip->ip_p == IPPROTO_UDP) {
414 if (cp + sizeof(struct udphdr) > snapend ||
415 iplen - hlen < sizeof(struct udphdr)) {
420 - te.sport = ntohs(((struct udphdr *)cp)->uh_sport);
421 - te.dport = ntohs(((struct udphdr *)cp)->uh_dport);
422 + sport = ntohs(((struct udphdr *)cp)->uh_sport);
423 + dport = ntohs(((struct udphdr *)cp)->uh_dport);
424 } else if (ip->ip_p == IPPROTO_ICMP) {
425 if (cp + sizeof(struct icmp) > snapend ||
426 iplen - hlen < sizeof(struct icmp)) {
427 @@ -396,15 +481,90 @@
431 - te.sport = ((struct icmp *)cp)->icmp_type;
432 + sport = ((struct icmp *)cp)->icmp_type;
435 - te.src.s_addr = ip->ip_src.s_addr;
436 - te.dst.s_addr = ip->ip_dst.s_addr;
437 + sin = (struct sockaddr_in *)&te.src;
438 + memset(sin, 0, sizeof(*sin));
439 + sin->sin_family = AF_INET;
440 + sin->sin_len = sizeof(*sin);
441 + sin->sin_addr.s_addr = ip->ip_src.s_addr;
442 + sin->sin_port = sport;
443 + sin = (struct sockaddr_in *)&te.dst;
444 + memset(sin, 0, sizeof(*sin));
445 + sin->sin_family = AF_INET;
446 + sin->sin_len = sizeof(*sin);
447 + sin->sin_addr.s_addr = ip->ip_dst.s_addr;
448 + sin->sin_port = dport;
451 - } else { /* other than ip protocol packets */
452 - te.src.s_addr = te.dst.s_addr = 0;
456 + /* XXX should chase header chain */
457 + cp = (u_char *)(ip6 + 1);
458 + hlen = sizeof(*ip6);
459 + switch (ip6->ip6_nxt) {
461 + if (cp + sizeof(struct tcphdr) > snapend ||
462 + iplen - hlen < sizeof(struct tcphdr)) {
463 + mvprintw(LINES-1, err_pos, "\
464 +truncated-tcp: wrong ip hdrlen");
466 + goto refresh_screen;
468 + sport = ntohs(((struct tcphdr *)cp)->th_sport);
469 + dport = ntohs(((struct tcphdr *)cp)->th_dport);
472 + if (cp + sizeof(struct udphdr) > snapend ||
473 + iplen - hlen < sizeof(struct udphdr)) {
474 + mvprintw(LINES-1, err_pos, "\
475 +truncated-udp: wrong ip hdrlen");
477 + goto refresh_screen;
479 + sport = ntohs(((struct udphdr *)cp)->uh_sport);
480 + dport = ntohs(((struct udphdr *)cp)->uh_dport);
482 + case IPPROTO_ICMPV6:
483 + if (cp + sizeof(struct icmp6_hdr) > snapend ||
484 + iplen - hlen < sizeof(struct icmp6_hdr)) {
485 + mvprintw(LINES-1, err_pos, "\
486 +truncated-icmp6: wrong ip hdrlen");
488 + goto refresh_screen;
490 + sport = ((struct icmp6_hdr *)cp)->icmp6_type;
493 + sin6 = (struct sockaddr_in6 *)&te.src;
494 + memset(sin6, 0, sizeof(*sin6));
495 + sin6->sin6_family = AF_INET6;
496 + sin6->sin6_len = sizeof(*sin6);
497 + sin6->sin6_addr = ip6->ip6_src;
498 + sin6->sin6_port = sport;
499 + sin6 = (struct sockaddr_in6 *)&te.dst;
500 + memset(sin6, 0, sizeof(*sin6));
501 + sin6->sin6_family = AF_INET6;
502 + sin6->sin6_len = sizeof(*sin6);
503 + sin6->sin6_addr = ip6->ip6_dst;
504 + sin6->sin6_port = dport;
505 + te.proto = ip6->ip6_nxt;
509 + else { /* other than ip protocol packets */
510 + sin = (struct sockaddr_in *)&te.src;
511 + sin->sin_family = AF_INET;
512 + sin->sin_len = sizeof(*sin);
513 + sin->sin_addr.s_addr = 0;
514 + sin->sin_port = sport;
515 + sin = (struct sockaddr_in *)&te.src;
516 + sin->sin_family = AF_INET;
517 + sin->sin_len = sizeof(*sin);
518 + sin->sin_addr.s_addr = 0;
519 + sin->sin_port = dport;
524 ===================================================================
525 RCS file: /cvsroot/apps/trafshow/getarptab.c,v
526 retrieving revision 1.1.1.1
527 retrieving revision 1.2
528 diff -u -r1.1.1.1 -r1.2
529 --- getarptab.c 2001/03/20 01:48:21 1.1.1.1
530 +++ getarptab.c 2001/03/20 19:37:56 1.2
535 -#ifdef HAVE_RTF_LLINFO /* BSD systems */
537 #include <sys/param.h>
538 #include <sys/types.h>
539 #include <sys/socket.h>
541 #include <net/route.h>
542 #include <netinet/in.h>
543 #include <netinet/if_ether.h>
545 +#ifdef HAVE_RTF_LLINFO /* BSD systems */
547 #ifdef ETHER_ADDR_LEN
548 #define MAC_ADDR_LEN ETHER_ADDR_LEN
550 ===================================================================
551 RCS file: /cvsroot/apps/trafshow/interfaces.c,v
552 retrieving revision 1.1.1.1
553 retrieving revision 1.2
554 diff -u -r1.1.1.1 -r1.2
555 --- interfaces.c 2001/03/20 01:48:18 1.1.1.1
556 +++ interfaces.c 2001/03/20 19:37:56 1.2
559 u_int caplen = h->caplen;
560 u_int length = h->len;
563 if (caplen < ETHER_HDRLEN) return;
565 snapend = p + caplen;
567 - ntohs(((struct ether_header *)p)->ether_type) == ETHERTYPE_IP)
571 + switch (ntohs(((struct ether_header *)p)->ether_type)) {
574 + case ETHERTYPE_IPV6:
580 display(p, p + ETHER_HDRLEN, length - ETHER_HDRLEN);
583 @@ -135,12 +146,17 @@
587 - if (type == 0x21) { /* IP protocol */
589 + case 0x21: /* IPv4 */
591 + case 0x57: /* IPv6 */
594 p = packetp + SLC_BPFHDR; /* skip bpf pseudo header */
597 display(NULL, p, length - hdrlen);
603 if (caplen < CHDLC_HDRLEN) return;
605 snapend = p + caplen;
606 - if (ntohs(*(u_short *)(p + 2)) == 0x0800) /* IP protocol */
607 + switch (ntohs(*(u_short *)(p + 2))) {
608 + case 0x0800: /* IP protocol */
610 + case 0x86dd: /* IP protocol */
612 display(NULL, p + CHDLC_HDRLEN, length - CHDLC_HDRLEN);
620 memcpy(&family, p, sizeof(family));
621 snapend = p + caplen;
622 - if (family == AF_INET)
628 display(NULL, p + NULL_HDRLEN, length - NULL_HDRLEN);
635 ===================================================================
636 RCS file: /cvsroot/apps/trafshow/trafshow.c,v
637 retrieving revision 1.1.1.1
638 retrieving revision 1.2
639 diff -u -r1.1.1.1 -r1.2
640 --- trafshow.c 2001/03/20 01:48:19 1.1.1.1
641 +++ trafshow.c 2001/03/20 19:37:57 1.2
647 + bpf_u_int32 netmask = 0;
649 bpf_u_int32 localnet, netmask;
651 char *cp, *infile, *expr, ebuf[PCAP_ERRBUF_SIZE];
652 struct bpf_program fcode;
656 ) error(0, "interface %s not an Ethernet", device_name);
659 if (pcap_lookupnet(device_name, &localnet, &netmask, ebuf) < 0)
663 /* Get back to user process after socket has been opened */
666 pcap_setfilter(pd, &fcode) < 0)
667 error(0, pcap_geterr(pd));
670 + init_addrtoname(0, 0);
672 init_addrtoname(localnet, netmask);
678 ===================================================================
679 RCS file: /cvsroot/apps/trafshow/trafshow.h,v
680 retrieving revision 1.1.1.1
681 retrieving revision 1.2
682 diff -u -r1.1.1.1 -r1.2
683 --- trafshow.h 2001/03/20 01:48:19 1.1.1.1
684 +++ trafshow.h 2001/03/20 19:37:57 1.2
686 #define DEFAULT_DNS 2 /* max timeout for gethostbyaddr() */
687 #define SCR_OFFS 2 /* first show line on screen */
688 #define MAX_PAGES 20 /* max pages on screen */
690 +#define DEFAULT_SNAPLEN 88 /* length of saved portion of packet */
692 #define DEFAULT_SNAPLEN 68 /* length of saved portion of packet */
695 #define DEFAULT_COLS 80 /* full screen width */
696 #define ADDR_SIZE 28 /* host..port size */
700 struct ether_header eh;
701 - struct in_addr src; /* source ip address */
702 - u_short sport; /* source port */
703 - struct in_addr dst; /* destination ip address */
704 - u_short dport; /* destination port */
705 + struct sockaddr_storage src; /* source ip address */
706 + struct sockaddr_storage dst; /* destination ip address */
707 u_short proto; /* ip protocol */
708 u_long bytes; /* bytes in ip datagram */
709 u_long obytes; /* old bytes */
711 extern void init_addrtoname(u_int32_t, u_int32_t);
712 extern char *getname(u_char *);
713 extern char *intoa(u_int32_t);
715 +extern char *satoa(struct sockaddr *);
716 +extern char *getnamebysa(struct sockaddr *);
718 extern char *tcpport_string(u_short);
719 extern char *udpport_string(u_short);
720 #define ipaddr_string(p) getname((u_char *)(p))
722 +#define saddr_string(p) getnamebysa(p)
724 extern char *entoa(u_char *);
725 extern char *etheraddr_string(u_char *);
726 extern char *etherproto_string(u_short);