This fixes a number of things (including it not compiling under 1.1.x. After you apply this patch, read the README.linux in the tcpdump directory. diff -u --recursive --new-file tcpdump/libpcap-0.0/pcap-linux.c tcpdump-3.0/libpcap-0.0/pcap-linux.c --- tcpdump/libpcap-0.0/pcap-linux.c Tue Jul 12 16:30:32 1994 +++ tcpdump-3.0/libpcap-0.0/pcap-linux.c Thu Jul 21 16:26:50 1994 @@ -32,6 +32,21 @@ #include "pcap-int.h" static char snoop_device[255]; +struct ifreq ifr_orig; + +void restore_interface() +{ + int fd; + + fd = socket(PF_INET, SOCK_PACKET, htons(0x0003)); + if (fd < 0) { + printf("Warning: could not restore interface to normal.\n"); + return; + } + + if (ioctl(fd, SIOCSIFFLAGS, &ifr_orig)<0) + printf("Warning: could not restore interface to normal.\n"); +} int pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { @@ -39,9 +54,20 @@ register int caplen; struct sockaddr from; int from_len; + char *buf; + int bufsize; + + if (p->linktype == DLT_SLIP) { + buf = (char *)p->buffer+16; + bufsize = p->bufsize - 16; + memset(p->buffer,0,16); + } else { + buf = (char *)p->buffer; + bufsize = p->bufsize; + } do { - datalen = recvfrom(p->fd,(char *)p->buffer,p->bufsize,0,&from,&from_len); + datalen = recvfrom(p->fd,buf,bufsize,0,&from,&from_len); if (datalen < 0) { switch (errno) { @@ -54,7 +80,11 @@ } while (strcmp(snoop_device,from.sa_data)); /* go until we find something from the right interface */ + if (p->linktype == DLT_SLIP) + datalen+=16; + caplen = (datalen > p->bufsize) ? datalen : p->bufsize; + if (caplen > p->snapshot) caplen = p->snapshot; @@ -63,7 +93,11 @@ struct pcap_pkthdr h; ++p->md.stat.ps_recv; - gettimeofday(&h.ts,0); +#ifdef SIOCGSTAMP + if (ioctl(p->fd,SIOCGSTAMP,&h.ts)<0) /* ask for the timestamp */ +#endif + gettimeofday(&h.ts,0); + h.len = datalen; h.caplen = caplen; (*callback)(user, &h, (char *)p->buffer); @@ -113,17 +147,20 @@ goto bad; } - strcpy(ifr.ifr_name, device); /* interface we're gonna use */ - if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0 ) { /* get flags */ - sprintf(ebuf, "socket ioctl get: %s", pcap_strerror(errno)); - goto bad; - } - if (promisc) + if (p->linktype != DLT_SLIP && promisc) { + strcpy(ifr.ifr_name, device); /* interface we're gonna use */ + if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0 ) { /* get flags */ + sprintf(ebuf, "socket ioctl get: %s", pcap_strerror(errno)); + goto bad; + } + ifr_orig = ifr; + atexit(restore_interface); ifr.ifr_flags |= IFF_PROMISC; /* set promiscuous mode */ - if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0 ) { /* set flags */ - sprintf(ebuf, "socket ioctl set: %s", pcap_strerror(errno)); - goto bad; + if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0 ) { /* set flags */ + sprintf(ebuf, "socket ioctl set: %s", pcap_strerror(errno)); + goto bad; + } } strcpy(snoop_device,device); diff -u --recursive --new-file tcpdump/linux-include/linux/if_arp.h tcpdump-3.0/linux-include/linux/if_arp.h --- tcpdump/linux-include/linux/if_arp.h Wed Dec 31 19:00:00 1969 +++ tcpdump-3.0/linux-include/linux/if_arp.h Wed Jul 20 20:07:31 1994 @@ -0,0 +1,45 @@ +/* @(#)if_arp.h 1.5 88/08/19 SMI; from UCB 7.1 1/24/86 */ +/* + * Copyright (c) 1986 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#ifndef _net_if_arp_h +#define _net_if_arp_h + +/* + * Address Resolution Protocol. + * + * See RFC 826 for protocol description. ARP packets are variable + * in size; the arphdr structure defines the fixed-length portion. + * Protocol type values are the same as those for 10 Mb/s Ethernet. + * It is followed by the variable-sized fields ar_sha, arp_spa, + * arp_tha and arp_tpa in that order, according to the lengths + * specified. Field names used correspond to RFC 826. + */ +struct arphdr { + u_short ar_hrd; /* format of hardware address */ +#define ARPHRD_ETHER 1 /* ethernet hardware address */ + u_short ar_pro; /* format of protocol address */ + u_char ar_hln; /* length of hardware address */ + u_char ar_pln; /* length of protocol address */ + u_short ar_op; /* one of: */ +#define ARPOP_REQUEST 1 /* request to resolve address */ +#define ARPOP_REPLY 2 /* response to previous request */ +#define REVARP_REQUEST 3 /* Reverse ARP request */ +#define REVARP_REPLY 4 /* Reverse ARP reply */ + /* + * The remaining fields are variable in size, + * according to the sizes above, and are defined + * as appropriate for specific hardware/protocol + * combinations. (E.g., see .) + */ +#ifdef notdef + u_char ar_sha[]; /* sender hardware address */ + u_char ar_spa[]; /* sender protocol address */ + u_char ar_tha[]; /* target hardware address */ + u_char ar_tpa[]; /* target protocol address */ +#endif notdef +}; +#endif diff -u --recursive --new-file tcpdump/linux-include/net/slip.h tcpdump-3.0/linux-include/net/slip.h --- tcpdump/linux-include/net/slip.h Thu Jul 7 16:25:46 1994 +++ tcpdump-3.0/linux-include/net/slip.h Wed Jul 20 20:07:30 1994 @@ -1,5 +1,5 @@ /* linux does not give us the link level header */ -#define SLIP_HDRLEN 0 +#define SLIP_HDRLEN 16 #define SLX_DIR 0 #define SLX_CHDR 1 diff -u --recursive --new-file tcpdump/tcpdump-3.0/README.linux tcpdump-3.0/tcpdump-3.0/README.linux --- tcpdump/tcpdump-3.0/README.linux Tue Jul 12 16:36:06 1994 +++ tcpdump-3.0/tcpdump-3.0/README.linux Thu Jul 21 16:52:47 1994 @@ -9,15 +9,14 @@ contained the needed definitions. 2) This program compiles using gcc 2.5.8, flex 2.4.6, bison 1.22, whatever include files came with Slackware 1.2.0 (presumably the ones - that go with gcc 2.5.8), and kernel version 1.0.8 - 3) The slip level of the kernel doesn't return the "low level" header, so - I had to slightly hack the pr-slip.c file to fix that annoyance. + that go with gcc 2.5.8), and kernel version 1.0.8 (and 1.1.33) + 3) The kernel keeps track of the exact time a packet was received. + the newer kernels provide a way to get to this, so I put in a modification + to ask for it.... If it the newer interface doesn't exist (ie old kernel) + it will revert back to using gettimeofday(). + 4) I put in a hook so that it can clean up after itself (ie turn off promisc + mode if it turned it on. Things to do: 1) The kernel keeps track of interface statistics... I took the easy way out and didn't ask for them. - 2) The kernel keeps track of the exact time a packet was received... I - wanted to keep this as portable between kernel versions as possible, so - I did not modify the kernel to return that information. I don't know - how much of a difference it really makes... I just used gettimeofday() - when it recieved the packet at the software level. diff -u --recursive --new-file tcpdump/tcpdump-3.0/print-sl.c tcpdump-3.0/tcpdump-3.0/print-sl.c --- tcpdump/tcpdump-3.0/print-sl.c Thu Jul 7 16:27:32 1994 +++ tcpdump-3.0/tcpdump-3.0/print-sl.c Thu Jul 21 16:48:28 1994 @@ -88,13 +88,8 @@ ip = (struct ip *)(p + SLIP_HDRLEN); -#if SLIP_HDRLEN > 0 -/* for some reason, linux doesn't give us the link level information.... - its probably a kernel oversite and may be fixed by some future version -*/ if (eflag) sliplink_print(p, ip, length); -#endif ip_print((u_char *)ip, length);