aboutsummaryrefslogtreecommitdiffstats
path: root/pcap-snoop.c
diff options
context:
space:
mode:
authorguy <guy>2008-04-04 19:37:44 +0000
committerguy <guy>2008-04-04 19:37:44 +0000
commitd9b420231a4428234f666eb6c44a4dea6f1f2d71 (patch)
tree83275824f39128a3f3ce9860b5cd8ed99b5a216f /pcap-snoop.c
parent19d1a629c7adea3d04f53c69d08cc4ce9e1693b0 (diff)
From Paolo Abeni and me: split pcap_open_live() into a "get a pcap_t
handle" routine, an 'activate a pcap_t handle" routine, and some "set the properties of the pcap_t handle" routines, so that, for example, the buffer size can be set on a BPF device before the device is bound to an interface. Add additional routines to set monitor mode, and make at least an initial attempt at supporting that on Linux, *BSD, and Mac OS X 10.4 and 10.5. (Very much "initial" for Linux, which is a twisty little maze of wireless drivers, many different.) Have a "timeout" member of the pcap_md structure on all platforms, use that on Windows instead of the "timeout" member of the pcap_t structure, and get rid of the "timeout" member of that structure.
Diffstat (limited to 'pcap-snoop.c')
-rw-r--r--pcap-snoop.c111
1 files changed, 58 insertions, 53 deletions
diff --git a/pcap-snoop.c b/pcap-snoop.c
index e4545c4..bbcf140 100644
--- a/pcap-snoop.c
+++ b/pcap-snoop.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.55 2005-05-03 18:54:00 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.56 2008-04-04 19:37:45 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -194,9 +194,8 @@ pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
}
/* XXX can't disable promiscuous */
-pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+static int
+pcap_activate_snoop(pcap_t *p)
{
int fd;
struct sockaddr_raw sr;
@@ -204,34 +203,34 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
u_int v;
int ll_hdrlen;
int snooplen;
- pcap_t *p;
struct ifreq ifr;
- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- return (NULL);
+ if (p->opt.rfmon) {
+ /*
+ * No monitor mode on Irix (no Wi-Fi devices on
+ * hardware supported by Irix).
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
}
- memset(p, 0, sizeof(*p));
+
fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
if (fd < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
pcap_strerror(errno));
goto bad;
}
p->fd = fd;
memset(&sr, 0, sizeof(sr));
sr.sr_family = AF_RAW;
- (void)strncpy(sr.sr_ifname, device, sizeof(sr.sr_ifname));
+ (void)strncpy(sr.sr_ifname, p->opt.source, sizeof(sr.sr_ifname));
if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
pcap_strerror(errno));
goto bad;
}
memset(&sf, 0, sizeof(sf));
if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
pcap_strerror(errno));
goto bad;
}
@@ -240,19 +239,19 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/*
* XXX hack - map device name to link layer type
*/
- if (strncmp("et", device, 2) == 0 || /* Challenge 10 Mbit */
- strncmp("ec", device, 2) == 0 || /* Indigo/Indy 10 Mbit,
- O2 10/100 */
- strncmp("ef", device, 2) == 0 || /* O200/2000 10/100 Mbit */
- strncmp("eg", device, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */
- strncmp("gfe", device, 3) == 0 || /* GIO 100 Mbit */
- strncmp("fxp", device, 3) == 0 || /* Challenge VME Enet */
- strncmp("ep", device, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */
- strncmp("vfe", device, 3) == 0 || /* Challenge VME 100Mbit */
- strncmp("fa", device, 2) == 0 ||
- strncmp("qaa", device, 3) == 0 ||
- strncmp("cip", device, 3) == 0 ||
- strncmp("el", device, 2) == 0) {
+ if (strncmp("et", p->opt.source, 2) == 0 || /* Challenge 10 Mbit */
+ strncmp("ec", p->opt.source, 2) == 0 || /* Indigo/Indy 10 Mbit,
+ O2 10/100 */
+ strncmp("ef", p->opt.source, 2) == 0 || /* O200/2000 10/100 Mbit */
+ strncmp("eg", p->opt.source, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */
+ strncmp("gfe", p->opt.source, 3) == 0 || /* GIO 100 Mbit */
+ strncmp("fxp", p->opt.source, 3) == 0 || /* Challenge VME Enet */
+ strncmp("ep", p->opt.source, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */
+ strncmp("vfe", p->opt.source, 3) == 0 || /* Challenge VME 100Mbit */
+ strncmp("fa", p->opt.source, 2) == 0 ||
+ strncmp("qaa", p->opt.source, 3) == 0 ||
+ strncmp("cip", p->opt.source, 3) == 0 ||
+ strncmp("el", p->opt.source, 2) == 0) {
p->linktype = DLT_EN10MB;
p->offset = RAW_HDRPAD(sizeof(struct ether_header));
ll_hdrlen = sizeof(struct ether_header);
@@ -285,26 +284,26 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->dlt_list[1] = DLT_DOCSIS;
p->dlt_count = 2;
}
- } else if (strncmp("ipg", device, 3) == 0 ||
- strncmp("rns", device, 3) == 0 || /* O2/200/2000 FDDI */
- strncmp("xpi", device, 3) == 0) {
+ } else if (strncmp("ipg", p->opt.source, 3) == 0 ||
+ strncmp("rns", p->opt.source, 3) == 0 || /* O2/200/2000 FDDI */
+ strncmp("xpi", p->opt.source, 3) == 0) {
p->linktype = DLT_FDDI;
p->offset = 3; /* XXX yeah? */
ll_hdrlen = 13;
- } else if (strncmp("ppp", device, 3) == 0) {
+ } else if (strncmp("ppp", p->opt.source, 3) == 0) {
p->linktype = DLT_RAW;
ll_hdrlen = 0; /* DLT_RAW meaning "no PPP header, just the IP packet"? */
- } else if (strncmp("qfa", device, 3) == 0) {
+ } else if (strncmp("qfa", p->opt.source, 3) == 0) {
p->linktype = DLT_IP_OVER_FC;
ll_hdrlen = 24;
- } else if (strncmp("pl", device, 2) == 0) {
+ } else if (strncmp("pl", p->opt.source, 2) == 0) {
p->linktype = DLT_RAW;
ll_hdrlen = 0; /* Cray UNICOS/mp pseudo link */
- } else if (strncmp("lo", device, 2) == 0) {
+ } else if (strncmp("lo", p->opt.source, 2) == 0) {
p->linktype = DLT_NULL;
ll_hdrlen = 4;
} else {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snoop: unknown physical layer type");
goto bad;
}
@@ -315,9 +314,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* the MTU first and, if that succeeds, trim the snap length
* to be no greater than the MTU.
*/
- (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
pcap_strerror(errno));
goto bad;
}
@@ -338,8 +337,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#ifndef ifr_mtu
#define ifr_mtu ifr_metric
#endif
- if (snaplen > ifr.ifr_mtu + ll_hdrlen)
- snaplen = ifr.ifr_mtu + ll_hdrlen;
+ if (p->snapshot > ifr.ifr_mtu + ll_hdrlen)
+ p->snapshot = ifr.ifr_mtu + ll_hdrlen;
#endif
/*
@@ -347,18 +346,17 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* payload bytes to capture - it doesn't count link-layer
* header bytes.
*/
- snooplen = snaplen - ll_hdrlen;
+ snooplen = p->snapshot - ll_hdrlen;
if (snooplen < 0)
snooplen = 0;
if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
pcap_strerror(errno));
goto bad;
}
- p->snapshot = snaplen;
v = 1;
if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
pcap_strerror(errno));
goto bad;
}
@@ -366,7 +364,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->bufsize = 4096; /* XXX */
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
goto bad;
}
@@ -386,16 +384,23 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->stats_op = pcap_stats_snoop;
p->close_op = pcap_close_common;
- return (p);
+ return (0);
bad:
(void)close(fd);
- /*
- * Get rid of any link-layer type list we allocated.
- */
- if (p->dlt_list != NULL)
- free(p->dlt_list);
- free(p);
- return (NULL);
+ return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_snoop;
+ return (p);
}
int