Subject: misc/1053: ARCnet support additions for libpcap/tcpdump
To: None <gnats-admin@sun-lamp.cs.berkeley.edu>
From: Ignatios Souvatzis <is@beverly.rhein.de>
List: netbsd-bugs
Date: 05/16/1995 02:50:06
>Number: 1053
>Category: misc
>Synopsis: ARCnet support additions for libpcap/tcpdump
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: misc-bug-people (Misc Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue May 16 02:50:03 1995
>Originator: Ignatios Souvatzis
>Organization:
" private Internet site"
>Release: 1.0A
>Environment:
System: NetBSD beverly 1.0A NetBSD 1.0A (BEVERLY) #120: Tue May 9 13:55:13 MET DST 1995 is@beverly:/usr/src/sys/arch/amiga/compile/BEVERLY amiga
>Description:
tcpdump/libpcap don't support DLT_ARCNET devices.
>How-To-Repeat:
On a system with ARCnet primary interface, try
tcpdump.
On a system with multiple interfaces, one of which is ARCnet, try
tcpdump -i bah0
>Fix:
I developed the following set of diffs. They are supposed to work (and tested
with) RFC1051 IP over ARCnet and should work with RFC1051 ARP over ARCnet,
too, but won't work for RFC1201-style encapsulations (e.g., new IP/ARP/RARP
over ARCnet or IPX). These require bigger changes, at least special code, as
most of tcpdump/libpcap assumes every protocol has only one encapsulation and
all encapsulations have same length.
I might implement those later, when I need to debug the RFC1201 code for the
kernel I didn't write yet.
- Ignatios Souvatzis
diff -u usr.sbin/tcpdump.bak/Makefile usr.sbin/tcpdump/Makefile
--- usr.sbin/tcpdump.bak/Makefile Thu May 11 16:05:20 1995
+++ usr.sbin/tcpdump/Makefile Fri May 12 22:49:49 1995
@@ -30,7 +30,8 @@
DPADD+= ${LIBL} ${LIBPCAP}
SRCS= tcpdump.c addrtoname.c \
- print-ether.c print-ip.c print-arp.c print-tcp.c print-udp.c \
+ print-arc.c print-ether.c \
+ print-ip.c print-arp.c print-tcp.c print-udp.c \
print-atalk.c print-domain.c print-tftp.c print-bootp.c print-nfs.c \
print-icmp.c print-sl.c print-ppp.c print-rip.c \
print-snmp.c print-ntp.c print-null.c print-egp.c print-ospf.c \
diff -u usr.sbin/tcpdump.bak/addrtoname.c usr.sbin/tcpdump/addrtoname.c
--- usr.sbin/tcpdump.bak/addrtoname.c Thu May 11 16:05:39 1995
+++ usr.sbin/tcpdump/addrtoname.c Sat May 13 22:57:03 1995
@@ -35,6 +35,7 @@
#include <net/if.h>
#include <netinet/in.h>
+#include <netinet/if_arc.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
@@ -101,6 +102,15 @@
struct protoidmem protoidtable[HASHNAMESIZE];
+struct arcnamemem {
+ u_char addr;
+ char *name;
+ struct arcnamemem *nxt;
+};
+
+struct arcnamemem arcnametable[HASHNAMESIZE];
+struct arcnamemem arcprototable[HASHNAMESIZE];
+
/*
* A faster replacement for inet_ntoa().
*/
@@ -246,6 +256,42 @@
static char hex[] = "0123456789abcdef";
+char *
+arcaddr_string(ap)
+ register u_char ap;
+{
+ register struct anamemem *tp;
+ register char *cp;
+
+ cp = (char *)malloc(sizeof("00"));
+
+ cp[0] = hex[ap >> 4];
+ cp[1] = hex[ap & 0xf];
+ cp[2] = 0;
+
+ return (cp);
+}
+
+char *
+arcproto_string(port)
+ u_char port;
+{
+ register char *cp0, *cp;
+ register struct arcnamemem *tp;
+
+ for (tp = &arcprototable[port & (HASHNAMESIZE-1)];
+ tp->nxt; tp = tp->nxt)
+ if (tp->addr == port)
+ return (tp->name);
+
+ cp0 = cp = (char *)malloc(sizeof("00"));
+
+ *cp++ = hex[port >> 4 & 0xf];
+ *cp++ = hex[port & 0xf];
+ *cp++ = '\0';
+
+ return (cp0);
+}
/* Find the hash node that corresponds the ether address 'ep'. */
@@ -539,6 +585,38 @@
endservent();
}
+struct arcproto {
+ char *s;
+ u_short p;
+} arcproto_db[] = {
+ {"oldip", 240},
+ {"oldarp", 241},
+ {"ip", 212},
+ {"arp", 213},
+ {"rarp", 214},
+ {"atalk", 221},
+ {"banian", 247},
+ {"ipx", 250},
+ {NULL, 0}
+};
+
+static void
+init_arcprotoarray(void)
+{
+ register int i;
+ register struct arcnamemem *table;
+
+ for (i=0; arcproto_db[i].s; ++i) {
+ int j = arcproto_db[i].p & (HASHNAMESIZE-1);
+ table = &arcprototable[j];
+ while (table->name)
+ table = table->nxt;
+ table->name = arcproto_db[i].s;
+ table->addr = arcproto_db[i].p;
+ table->nxt = (struct arcnamemem *)calloc(1, sizeof(*table));
+ }
+}
+
/*XXX from libbpfc.a */
extern struct eproto {
char *s;
@@ -696,6 +774,7 @@
*/
return;
+ init_arcprotoarray();
init_etherarray();
init_servarray();
init_eprotoarray();
diff -u usr.sbin/tcpdump.bak/interface.h usr.sbin/tcpdump/interface.h
--- usr.sbin/tcpdump.bak/interface.h Thu May 11 16:06:49 1995
+++ usr.sbin/tcpdump/interface.h Fri May 12 22:58:26 1995
@@ -101,6 +101,8 @@
extern void ether_if_print(u_char *, const struct pcap_pkthdr *,
const u_char *);
+extern void arc_if_print(u_char *, const struct pcap_pkthdr *,
+ const u_char *);
extern void fddi_if_print(u_char *, const struct pcap_pkthdr *, const u_char*);
extern void null_if_print(u_char *, const struct pcap_pkthdr *, const u_char*);
extern void ppp_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
@@ -119,6 +121,7 @@
extern void bootp_print(const u_char *, int, u_short, u_short);
extern void decnet_print(const u_char *, int, int);
extern void egp_print(const u_char *, int, const u_char *);
+extern int arc_encap_print(u_short, const u_char *, int, int);
extern int ether_encap_print(u_short, const u_char *, int, int);
extern void ipx_print(const u_char *, int length);
extern void isoclns_print(const u_char *, int, int,
diff -u usr.sbin/tcpdump.bak/os.h usr.sbin/tcpdump/os.h
--- usr.sbin/tcpdump.bak/os.h Thu May 11 16:07:27 1995
+++ usr.sbin/tcpdump/os.h Fri May 12 23:02:11 1995
@@ -34,6 +34,9 @@
#define THA(ap) ((ap)->arp_tha)
#define TPA(ap) ((ap)->arp_tpa)
+#define ADST(ap) ((ap)->arc_dhost)
+#define ASRC(ap) ((ap)->arc_shost)
+
#define EDST(ep) ((ep)->ether_dhost)
#define ESRC(ep) ((ep)->ether_shost)
diff -u usr.sbin/tcpdump.bak/tcpdump.c usr.sbin/tcpdump/tcpdump.c
--- usr.sbin/tcpdump.bak/tcpdump.c Thu May 11 16:10:32 1995
+++ usr.sbin/tcpdump/tcpdump.c Fri May 12 11:09:09 1995
@@ -84,6 +84,7 @@
static struct printer printers[] = {
{ ether_if_print, DLT_EN10MB },
+ { arc_if_print, DLT_ARCNET },
{ sl_if_print, DLT_SLIP },
{ ppp_if_print, DLT_PPP },
{ fddi_if_print, DLT_FDDI },
diff -u lib/libpcap.old/gencode.c lib/libpcap/gencode.c
--- lib/libpcap.old/gencode.c Thu May 11 16:32:19 1995
+++ lib/libpcap/gencode.c Sun May 14 00:19:59 1995
@@ -34,6 +34,7 @@
#include <netinet/in.h>
#include <netinet/if_ether.h>
+#include <netinet/if_arc.h>
#include <memory.h>
#include <pcap.h>
@@ -444,6 +445,7 @@
* is set to -1 for no encapsulation, in which case, IP is assumed.
*/
static u_int off_linktype;
+static u_int size_linktype;
static u_int off_nl;
static int linktype;
#ifdef FDDI
@@ -456,8 +458,15 @@
{
linktype = type;
+ size_linktype = 2; /* for most sane protocols, but... */
switch (type) {
+ case DLT_ARCNET:
+ off_linktype = 2;
+ size_linktype = 1;
+ off_nl = 3;
+ return;
+
case DLT_EN10MB:
off_linktype = 12;
off_nl = 14;
@@ -545,8 +554,22 @@
if (proto == ETHERTYPE_IP)
proto = 0x0021; /* XXX - need ppp.h defs */
break;
+
+ case DLT_ARCNET:
+ switch(proto) { /*
+ * XXX - needs more work;
+ * especially for RFC1201
+ */
+ case ETHERTYPE_IP:
+ proto = ARCTYPE_IP_OLD;
+ break;
+ case ETHERTYPE_ARP:
+ proto = ARCTYPE_IP_OLD;
+ break;
+ }
+ break;
}
- return gen_cmp(off_linktype, BPF_H, (long)proto);
+ return gen_cmp(off_linktype, size_linktype, (long)proto);
}
static struct block *
@@ -592,6 +615,39 @@
}
static struct block *
+gen_ahostop(aaddr, dir)
+ u_char *aaddr;
+ int dir;
+{
+ struct block *b0, *b1;
+
+ switch (dir) {
+
+ case Q_SRC:
+ return gen_bcmp(0, 1, aaddr);
+
+ case Q_DST:
+ return gen_bcmp(1, 1, aaddr);
+
+ case Q_AND:
+ b0 = gen_ahostop(aaddr, Q_SRC);
+ b1 = gen_ahostop(aaddr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_ahostop(aaddr, Q_SRC);
+ b1 = gen_ahostop(aaddr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+ }
+ abort();
+ /* NOTREACHED */
+}
+
+
+static struct block *
gen_ehostop(eaddr, dir)
u_char *eaddr;
int dir;
@@ -821,12 +877,17 @@
case Q_RARP:
if (linktype == DLT_EN10MB)
b0 = gen_ehostop(eaddr, Q_OR);
+
+ else if (linktype == DLT_ARCNET)
+ b0 = gen_ahostop(eaddr, Q_OR);
#ifdef FDDI
else if (linktype == DLT_FDDI)
b0 = gen_fhostop(eaddr, Q_OR);
#endif
+
else
- bpf_error("'gateway' supported only on ethernet or FDDI");
+ bpf_error("'gateway' supported only on ethernet, \
+arcnet or FDDI");
b1 = gen_host(**alist++, 0xffffffffL, proto, Q_OR);
while (*alist) {
@@ -1149,6 +1210,14 @@
case Q_HOST:
if (proto == Q_LINK) {
switch (linktype) {
+#if 0 /* no /etc/arcs yet */
+ case DLT_ARCNET:
+ eaddr = pcap_arc_hostton(name);
+ if (eaddr == NULL)
+ bpf_error("unknown arc host '%s'",
+ name);
+ return gen_ahostop(eaddr, dir);
+#endif
case DLT_EN10MB:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
@@ -1163,7 +1232,7 @@
return gen_fhostop(eaddr, dir);
#endif
default:
- bpf_error("only ethernet/FDDI supports link-level host name");
+ bpf_error("only ether-,arcnet and FDDI support link-level host name");
break;
}
} else if (proto == Q_DECNET) {
@@ -1292,6 +1361,8 @@
struct qual q;
{
if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
+ if (linktype == DLT_ARCNET)
+ return gen_ahostop(eaddr, (int)q.dir);
if (linktype == DLT_EN10MB)
return gen_ehostop(eaddr, (int)q.dir);
#ifdef FDDI
@@ -1667,11 +1738,15 @@
u_long hostmask;
struct block *b0, *b1, *b2;
static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ static u_char abroadcast[] = { 0x0 };
switch (proto) {
case Q_DEFAULT:
case Q_LINK:
+ if (linktype == DLT_ARCNET)
+ return gen_ahostop(abroadcast, Q_DST);
+
if (linktype == DLT_EN10MB)
return gen_ehostop(ebroadcast, Q_DST);
#ifdef FDDI
diff -u lib/libpcap.old/grammar.y lib/libpcap/grammar.y
--- lib/libpcap.old/grammar.y Thu May 11 16:33:24 1995
+++ lib/libpcap/grammar.y Sat May 13 23:54:57 1995
@@ -98,11 +98,12 @@
%token NUM INBOUND OUTBOUND
%token LINK
%token GEQ LEQ NEQ
-%token ID EID HID
+%token ID AID EID HID
%token LSH RSH
%token LEN
%type <s> ID
+%type <e> AID
%type <e> EID
%type <h> HID
%type <i> NUM
@@ -157,6 +158,7 @@
}
}
| EID { $$.b = gen_ecode($1, $$.q = $<blk>0.q); }
+ | AID { $$.b = gen_ecode($1, $$.q = $<blk>0.q); }
| not id { gen_not($2.b); $$ = $2; }
;
not: '!' { $$ = $<blk>0; }
diff -u lib/libpcap.old/nametoaddr.c lib/libpcap/nametoaddr.c
--- lib/libpcap.old/nametoaddr.c Thu May 11 16:33:35 1995
+++ lib/libpcap/nametoaddr.c Sun May 14 00:16:22 1995
@@ -263,6 +263,26 @@
return(addr);
}
+u_char *
+pcap_arc_aton(const char *s)
+{
+ register u_char *ep;
+ register u_int d;
+
+ ep = (u_char *)malloc(1);
+
+ if (*s)
+ ++s;
+
+ d = xdtoi(*s++);
+ if (isxdigit(*s)) {
+ d <<= 4;
+ d |= xdtoi(*s);
+ }
+ *ep = d;
+ return (ep);
+}
+
/*
* Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
* ethernet address. Assumes 's' is well formed.
diff -u lib/libpcap.old/pcap-namedb.h lib/libpcap/pcap-namedb.h
--- lib/libpcap.old/pcap-namedb.h Thu May 11 16:34:52 1995
+++ lib/libpcap/pcap-namedb.h Sun May 14 00:17:52 1995
@@ -56,6 +56,8 @@
u_char *pcap_ether_hostton(const char*);
u_char *pcap_ether_aton(const char *);
+u_char *pcap_arc_aton(const char *);
+
u_long **pcap_nametoaddr(const char *);
u_long pcap_nametonetaddr(const char *);
diff -u lib/libpcap.old/scanner.l lib/libpcap/scanner.l
--- lib/libpcap.old/scanner.l Thu May 11 16:36:06 1995
+++ lib/libpcap/scanner.l Sat May 13 23:52:28 1995
@@ -81,6 +81,7 @@
src return SRC;
link|ether|ppp|slip return LINK;
+arc return LINK;
fddi return LINK;
arp return ARP;
rarp return RARP;
@@ -129,6 +130,8 @@
}
{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext);
return EID; }
+:{B} { yylval.e = pcap_arc_aton((char *)yytext);
+ return AID; }
{B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); }
[A-Za-z][-_.A-Za-z0-9]* { yylval.s = sdup((char *)yytext); return ID; }
"\\"[^ !()\n\t]+ { yylval.s = sdup((char *)yytext + 1); return ID; }
>Audit-Trail:
>Unformatted:
Ignatios Souvatzis