18cf6c252SPaul Traina /* 28cf6c252SPaul Traina * Stanford Enetfilter subroutines for tcpdump 38cf6c252SPaul Traina * 48cf6c252SPaul Traina * Based on the MERIT NNstat etherifrt.c and the Ultrix pcap-pf.c 58cf6c252SPaul Traina * subroutines. 68cf6c252SPaul Traina * 78cf6c252SPaul Traina * Rayan Zachariassen, CA*Net 88cf6c252SPaul Traina */ 9dc2c7305SBill Fenner #ifndef lint 10feb4ecdbSBruce M Simpson static const char rcsid[] _U_ = 11a8e07101SRui Paulo "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.9 2006/10/04 18:09:22 guy Exp $"; 12dc2c7305SBill Fenner #endif 13dc2c7305SBill Fenner 14dc2c7305SBill Fenner #ifdef HAVE_CONFIG_H 15dc2c7305SBill Fenner #include "config.h" 16dc2c7305SBill Fenner #endif 178cf6c252SPaul Traina 188cf6c252SPaul Traina #include <sys/types.h> 198cf6c252SPaul Traina #include <sys/time.h> 208cf6c252SPaul Traina #include <sys/file.h> 218cf6c252SPaul Traina #include <sys/ioctl.h> 228cf6c252SPaul Traina #include <sys/socket.h> 238cf6c252SPaul Traina 248cf6c252SPaul Traina #include <net/if.h> 25a8e07101SRui Paulo #include <pcap/bpf.h> 268cf6c252SPaul Traina #include <net/enet.h> 278cf6c252SPaul Traina 288cf6c252SPaul Traina #include <netinet/in.h> 298cf6c252SPaul Traina #include <netinet/if_ether.h> 308cf6c252SPaul Traina 318cf6c252SPaul Traina #include <stdio.h> 328cf6c252SPaul Traina #include <errno.h> 338cf6c252SPaul Traina 348cf6c252SPaul Traina #include "interface.h" 358cf6c252SPaul Traina 368cf6c252SPaul Traina struct packet_header { 378cf6c252SPaul Traina #ifdef IBMRTPC 388cf6c252SPaul Traina struct LengthWords length; 398cf6c252SPaul Traina struct tap_header tap; 408cf6c252SPaul Traina #endif /* IBMRTPC */ 418cf6c252SPaul Traina u_char packet[8] 428cf6c252SPaul Traina }; 438cf6c252SPaul Traina 448cf6c252SPaul Traina extern int errno; 458cf6c252SPaul Traina 468cf6c252SPaul Traina #define BUFSPACE (4*1024) 478cf6c252SPaul Traina 488cf6c252SPaul Traina /* Forwards */ 498cf6c252SPaul Traina static void efReadError(int, char *); 508cf6c252SPaul Traina 518cf6c252SPaul Traina void 528cf6c252SPaul Traina readloop(int cnt, int if_fd, struct bpf_program *fp, printfunc printit) 538cf6c252SPaul Traina { 548cf6c252SPaul Traina #ifdef IBMRTPC 558cf6c252SPaul Traina register struct packet_header *ph; 568cf6c252SPaul Traina register u_char *bp; 578cf6c252SPaul Traina register int inc; 588cf6c252SPaul Traina #else /* !IBMRTPC */ 598cf6c252SPaul Traina static struct timeval tv = { 0 }; 608cf6c252SPaul Traina #endif /* IBMRTPC */ 618cf6c252SPaul Traina register int cc, caplen; 628cf6c252SPaul Traina register struct bpf_insn *fcode = fp->bf_insns; 638cf6c252SPaul Traina union { 648cf6c252SPaul Traina struct packet_header hdr; 658cf6c252SPaul Traina u_char p[BUFSPACE]; 668cf6c252SPaul Traina u_short s; 678cf6c252SPaul Traina } buf; 688cf6c252SPaul Traina 698cf6c252SPaul Traina while (1) { 708cf6c252SPaul Traina if ((cc = read(if_fd, (char *)buf.p, sizeof(buf))) < 0) 718cf6c252SPaul Traina efReadError(if_fd, "reader"); 728cf6c252SPaul Traina 738cf6c252SPaul Traina #ifdef IBMRTPC 748cf6c252SPaul Traina /* 758cf6c252SPaul Traina * Loop through each packet. 768cf6c252SPaul Traina */ 778cf6c252SPaul Traina bp = buf.p; 788cf6c252SPaul Traina while (cc > 0) { 798cf6c252SPaul Traina ph = (struct packet_header *)bp; 808cf6c252SPaul Traina caplen = ph->tap.th_wirelen > snaplen ? snaplen : ph->tap 818cf6c252SPaul Traina .th_wirelen ; 828cf6c252SPaul Traina if (bpf_filter(fcode, (char *)ph->packet, 838cf6c252SPaul Traina ph->tap.th_wirelen, caplen)) { 848cf6c252SPaul Traina if (cnt >= 0 && --cnt < 0) 858cf6c252SPaul Traina goto out; 868cf6c252SPaul Traina (*printit)((char *)ph->packet, 878cf6c252SPaul Traina (struct timeval *)ph->tap.th_timestamp, 888cf6c252SPaul Traina ph->tap.th_wirelen, caplen); 898cf6c252SPaul Traina } 908cf6c252SPaul Traina inc = ph->length.PacketOffset; 918cf6c252SPaul Traina cc -= inc; 928cf6c252SPaul Traina bp += inc; 938cf6c252SPaul Traina } 948cf6c252SPaul Traina #else /* !IBMRTPC */ 958cf6c252SPaul Traina caplen = cc > snaplen ? snaplen : cc ; 968cf6c252SPaul Traina if (bpf_filter(fcode, buf.hdr.packet, cc, caplen)) { 978cf6c252SPaul Traina if (cnt >= 0 && --cnt < 0) 988cf6c252SPaul Traina goto out; 998cf6c252SPaul Traina (*printit)(buf.hdr.packet, &tv, cc, caplen); 1008cf6c252SPaul Traina } 1018cf6c252SPaul Traina #endif /* IBMRTPC */ 1028cf6c252SPaul Traina } 1038cf6c252SPaul Traina out: 1048cf6c252SPaul Traina wrapup(if_fd); 1058cf6c252SPaul Traina } 1068cf6c252SPaul Traina 1078cf6c252SPaul Traina /* Call ONLY if read() has returned an error on packet filter */ 1088cf6c252SPaul Traina static void 1098cf6c252SPaul Traina efReadError(int fid, char *msg) 1108cf6c252SPaul Traina { 1118cf6c252SPaul Traina if (errno == EINVAL) { /* read MAXINT bytes already! */ 1128cf6c252SPaul Traina if (lseek(fid, 0, 0) < 0) { 1138cf6c252SPaul Traina perror("tcpdump: efReadError/lseek"); 1148cf6c252SPaul Traina exit(-1); 1158cf6c252SPaul Traina } 1168cf6c252SPaul Traina else 1178cf6c252SPaul Traina return; 1188cf6c252SPaul Traina } 1198cf6c252SPaul Traina else { 1208cf6c252SPaul Traina (void) fprintf(stderr, "tcpdump: "); 1218cf6c252SPaul Traina perror(msg); 1228cf6c252SPaul Traina exit(-1); 1238cf6c252SPaul Traina } 1248cf6c252SPaul Traina } 1258cf6c252SPaul Traina 1268cf6c252SPaul Traina void 1278cf6c252SPaul Traina wrapup(int fd) 1288cf6c252SPaul Traina { 1298cf6c252SPaul Traina #ifdef IBMRTPC 1308cf6c252SPaul Traina struct enstats es; 1318cf6c252SPaul Traina 1328cf6c252SPaul Traina if (ioctl(fd, EIOSTATS, &es) == -1) { 1338cf6c252SPaul Traina perror("tcpdump: enet ioctl EIOSTATS error"); 1348cf6c252SPaul Traina exit(-1); 1358cf6c252SPaul Traina } 1368cf6c252SPaul Traina 1378cf6c252SPaul Traina fprintf(stderr, "%d packets queued", es.enStat_Rcnt); 1388cf6c252SPaul Traina if (es.enStat_Rdrops > 0) 1398cf6c252SPaul Traina fprintf(stderr, ", %d dropped", es.enStat_Rdrops); 1408cf6c252SPaul Traina if (es.enStat_Reads > 0) 1418cf6c252SPaul Traina fprintf(stderr, ", %d tcpdump %s", es.enStat_Reads, 1428cf6c252SPaul Traina es.enStat_Reads > 1 ? "reads" : "read"); 1438cf6c252SPaul Traina if (es.enStat_MaxRead > 1) 1448cf6c252SPaul Traina fprintf(stderr, ", %d packets in largest read", 1458cf6c252SPaul Traina es.enStat_MaxRead); 1468cf6c252SPaul Traina putc('\n', stderr); 1478cf6c252SPaul Traina #endif /* IBMRTPC */ 1488cf6c252SPaul Traina close(fd); 1498cf6c252SPaul Traina } 1508cf6c252SPaul Traina 1518cf6c252SPaul Traina int 1528cf6c252SPaul Traina initdevice(char *device, int pflag, int *linktype) 1538cf6c252SPaul Traina { 1548cf6c252SPaul Traina struct eniocb ctl; 1558cf6c252SPaul Traina struct enfilter filter; 1568cf6c252SPaul Traina u_int maxwaiting; 1578cf6c252SPaul Traina int if_fd; 1588cf6c252SPaul Traina 1598cf6c252SPaul Traina #ifdef IBMRTPC 1608cf6c252SPaul Traina GETENETDEVICE(0, O_RDONLY, &if_fd); 1618cf6c252SPaul Traina #else /* !IBMRTPC */ 1628cf6c252SPaul Traina if_fd = open("/dev/enet", O_RDONLY, 0); 1638cf6c252SPaul Traina #endif /* IBMRTPC */ 1648cf6c252SPaul Traina 1658cf6c252SPaul Traina if (if_fd == -1) { 1668cf6c252SPaul Traina perror("tcpdump: enet open error"); 1678cf6c252SPaul Traina error( 1688cf6c252SPaul Traina "your system may not be properly configured; see \"man enet(4)\""); 1698cf6c252SPaul Traina exit(-1); 1708cf6c252SPaul Traina } 1718cf6c252SPaul Traina 1728cf6c252SPaul Traina /* Get operating parameters. */ 1738cf6c252SPaul Traina 1748cf6c252SPaul Traina if (ioctl(if_fd, EIOCGETP, (char *)&ctl) == -1) { 1758cf6c252SPaul Traina perror("tcpdump: enet ioctl EIOCGETP error"); 1768cf6c252SPaul Traina exit(-1); 1778cf6c252SPaul Traina } 1788cf6c252SPaul Traina 1798cf6c252SPaul Traina /* Set operating parameters. */ 1808cf6c252SPaul Traina 1818cf6c252SPaul Traina #ifdef IBMRTPC 1828cf6c252SPaul Traina ctl.en_rtout = 1 * ctl.en_hz; 1838cf6c252SPaul Traina ctl.en_tr_etherhead = 1; 1848cf6c252SPaul Traina ctl.en_tap_network = 1; 1858cf6c252SPaul Traina ctl.en_multi_packet = 1; 1868cf6c252SPaul Traina ctl.en_maxlen = BUFSPACE; 1878cf6c252SPaul Traina #else /* !IBMRTPC */ 1888cf6c252SPaul Traina ctl.en_rtout = 64; /* randomly picked value for HZ */ 1898cf6c252SPaul Traina #endif /* IBMRTPC */ 1908cf6c252SPaul Traina if (ioctl(if_fd, EIOCSETP, &ctl) == -1) { 1918cf6c252SPaul Traina perror("tcpdump: enet ioctl EIOCSETP error"); 1928cf6c252SPaul Traina exit(-1); 1938cf6c252SPaul Traina } 1948cf6c252SPaul Traina 1958cf6c252SPaul Traina /* Flush the receive queue, since we've changed 1968cf6c252SPaul Traina the operating parameters and we otherwise might 1978cf6c252SPaul Traina receive data without headers. */ 1988cf6c252SPaul Traina 1998cf6c252SPaul Traina if (ioctl(if_fd, EIOCFLUSH) == -1) { 2008cf6c252SPaul Traina perror("tcpdump: enet ioctl EIOCFLUSH error"); 2018cf6c252SPaul Traina exit(-1); 2028cf6c252SPaul Traina } 2038cf6c252SPaul Traina 2048cf6c252SPaul Traina /* Set the receive queue depth to its maximum. */ 2058cf6c252SPaul Traina 2068cf6c252SPaul Traina maxwaiting = ctl.en_maxwaiting; 2078cf6c252SPaul Traina if (ioctl(if_fd, EIOCSETW, &maxwaiting) == -1) { 2088cf6c252SPaul Traina perror("tcpdump: enet ioctl EIOCSETW error"); 2098cf6c252SPaul Traina exit(-1); 2108cf6c252SPaul Traina } 2118cf6c252SPaul Traina 2128cf6c252SPaul Traina #ifdef IBMRTPC 2138cf6c252SPaul Traina /* Clear statistics. */ 2148cf6c252SPaul Traina 2158cf6c252SPaul Traina if (ioctl(if_fd, EIOCLRSTAT, 0) == -1) { 2168cf6c252SPaul Traina perror("tcpdump: enet ioctl EIOCLRSTAT error"); 2178cf6c252SPaul Traina exit(-1); 2188cf6c252SPaul Traina } 2198cf6c252SPaul Traina #endif /* IBMRTPC */ 2208cf6c252SPaul Traina 2218cf6c252SPaul Traina /* Set the filter (accept all packets). */ 2228cf6c252SPaul Traina 2238cf6c252SPaul Traina filter.enf_Priority = 3; 2248cf6c252SPaul Traina filter.enf_FilterLen = 0; 2258cf6c252SPaul Traina if (ioctl(if_fd, EIOCSETF, &filter) == -1) { 2268cf6c252SPaul Traina perror("tcpdump: enet ioctl EIOCSETF error"); 2278cf6c252SPaul Traina exit(-1); 2288cf6c252SPaul Traina } 2298cf6c252SPaul Traina /* 2308cf6c252SPaul Traina * "enetfilter" supports only ethernets. 2318cf6c252SPaul Traina */ 2328cf6c252SPaul Traina *linktype = DLT_EN10MB; 2338cf6c252SPaul Traina 2348cf6c252SPaul Traina return(if_fd); 2358cf6c252SPaul Traina } 236