summaryrefslogtreecommitdiffstats
path: root/contrib/libpcap/pcap-linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpcap/pcap-linux.c')
-rw-r--r--contrib/libpcap/pcap-linux.c140
1 files changed, 116 insertions, 24 deletions
diff --git a/contrib/libpcap/pcap-linux.c b/contrib/libpcap/pcap-linux.c
index fe56d05..d01899a 100644
--- a/contrib/libpcap/pcap-linux.c
+++ b/contrib/libpcap/pcap-linux.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996
+ * Copyright (c) 1996, 1997
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] =
- "@(#) $Header: pcap-linux.c,v 1.4 96/12/10 23:15:00 leres Exp $ (LBL)";
+ "@(#) $Header: pcap-linux.c,v 1.15 97/10/02 22:39:37 leres Exp $ (LBL)";
#endif
#include <sys/param.h>
@@ -29,10 +29,17 @@ static const char rcsid[] =
#include <sys/time.h>
#include <net/if.h>
+#ifdef HAVE_NET_IF_ARP_H
+#include <net/if_arp.h>
+#else
+#include <linux/if_arp.h>
+#endif
+#include <linux/if_ether.h>
#include <netinet/in.h>
#include <errno.h>
+#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -67,12 +74,12 @@ pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
struct sockaddr from;
int fromlen;
- bp = (char *)p->buffer;
+ bp = p->buffer + p->offset;
bufsize = p->bufsize;
if (p->md.pad > 0) {
+ memset(bp, 0, p->md.pad);
bp += p->md.pad;
bufsize -= p->md.pad;
- memset(p->buffer, 0, p->md.pad);
}
again:
@@ -96,7 +103,7 @@ again:
/* If we need have leading zero bytes, adjust count */
cc += p->md.pad;
- bp = p->buffer;
+ bp = p->buffer + p->offset;
/* If we need to step over leading junk, adjust count and pointer */
cc -= p->md.skip;
@@ -136,46 +143,131 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
register int fd, broadcast;
register pcap_t *p;
struct ifreq ifr;
+ struct sockaddr sa;
p = (pcap_t *)malloc(sizeof(*p));
if (p == NULL) {
sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
return (NULL);
}
- memset((char *)p, 0, sizeof(*p));
+ memset(p, 0, sizeof(*p));
fd = -1;
- /* XXX hack - map device name to link layer type */
+ fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
+ if (fd < 0) {
+ sprintf(ebuf, "socket: %s", pcap_strerror(errno));
+ goto bad;
+ }
+ p->fd = fd;
+
+ /* Bind to the interface name */
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_family = AF_INET;
+ (void)strncpy(sa.sa_data, device, sizeof(sa.sa_data));
+ if (bind(p->fd, &sa, sizeof(sa))) {
+ sprintf(ebuf, "bind: %s: %s", device, pcap_strerror(errno));
+ goto bad;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(p->fd, SIOCGIFHWADDR, &ifr) < 0 ) {
+ sprintf(ebuf, "SIOCGIFHWADDR: %s", pcap_strerror(errno));
+ goto bad;
+ }
broadcast = 0;
- if (strncmp("eth", device, 3) == 0) {
+ switch (ifr.ifr_hwaddr.sa_family) {
+
+ case ARPHRD_ETHER:
+ case ARPHRD_METRICOM:
p->linktype = DLT_EN10MB;
+ p->offset = 2;
+ ++broadcast;
+ break;
+
+ case ARPHRD_EETHER:
+ p->linktype = DLT_EN3MB;
+ ++broadcast;
+ break;
+
+ case ARPHRD_AX25:
+ p->linktype = DLT_AX25;
++broadcast;
- } else if (strncmp("sl", device, 2) == 0) {
- p->linktype = DLT_SLIP;
- p->md.pad = 16;
- } else if (strncmp("ppp", device, 3) == 0) {
- p->linktype = DLT_PPP;
- p->md.pad = 4;
- } else if (strncmp("lo", device, 2) == 0) {
+ break;
+
+ case ARPHRD_PRONET:
+ p->linktype = DLT_PRONET;
+ break;
+
+ case ARPHRD_CHAOS:
+ p->linktype = DLT_CHAOS;
+ break;
+
+ case ARPHRD_IEEE802:
+ p->linktype = DLT_IEEE802;
+ ++broadcast;
+ break;
+
+ case ARPHRD_ARCNET:
+ p->linktype = DLT_ARCNET;
+ ++broadcast;
+ break;
+
+ case ARPHRD_SLIP:
+ case ARPHRD_CSLIP:
+ case ARPHRD_SLIP6:
+ case ARPHRD_CSLIP6:
+ case ARPHRD_PPP:
+ p->linktype = DLT_RAW;
+ break;
+
+ case ARPHRD_LOOPBACK:
p->linktype = DLT_NULL;
p->md.pad = 2;
p->md.skip = 12;
- } else {
- sprintf(ebuf, "linux: unknown physical layer type");
+ break;
+
+#ifdef ARPHRD_FDDI
+ /* Not all versions of the kernel has this define */
+ case ARPHRD_FDDI:
+ p->linktype = DLT_FDDI;
+ ++broadcast;
+ break;
+#endif
+
+#ifdef notdef
+ case ARPHRD_LOCALTLK:
+ case ARPHRD_NETROM:
+ case ARPHRD_APPLETLK:
+ case ARPHRD_DLCI:
+ case ARPHRD_RSRVD:
+ case ARPHRD_ADAPT:
+ case ARPHRD_TUNNEL:
+ case ARPHRD_TUNNEL6:
+ case ARPHRD_FRAD:
+ case ARPHRD_SKIP:
+ /* XXX currently do not know what to do with these... */
+ abort();
+#endif
+
+ default:
+ sprintf(ebuf, "unknown physical layer type 0x%x",
+ ifr.ifr_hwaddr.sa_family);
goto bad;
}
- /* Linux is full of magic numbers */
- fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
- if (fd < 0) {
- sprintf(ebuf, "linux socket: %s", pcap_strerror(errno));
+ /* Base the buffer size on the interface MTU */
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(p->fd, SIOCGIFMTU, &ifr) < 0 ) {
+ sprintf(ebuf, "SIOCGIFMTU: %s", pcap_strerror(errno));
goto bad;
}
- p->fd = fd;
+ /* Leave room for link header (which is never large under linux...) */
+ p->bufsize = ifr.ifr_mtu + 64;
- p->bufsize = 4096; /* XXX */
- p->buffer = (u_char *)malloc(p->bufsize);
+ p->buffer = (u_char *)malloc(p->bufsize + p->offset);
if (p->buffer == NULL) {
sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
goto bad;
OpenPOWER on IntegriCloud