117683Spst/*
239291Sfenner * Copyright (c) 1993, 1994, 1995, 1996, 1997
317683Spst *	The Regents of the University of California.  All rights reserved.
417683Spst *
517683Spst * Redistribution and use in source and binary forms, with or without
617683Spst * modification, are permitted provided that: (1) source code distributions
717683Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817683Spst * distributions including binary code include the above copyright notice and
917683Spst * this paragraph in its entirety in the documentation or other materials
1017683Spst * provided with the distribution, and (3) all advertising materials mentioning
1117683Spst * features or use of this software display the following acknowledgement:
1217683Spst * ``This product includes software developed by the University of California,
1317683Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417683Spst * the University nor the names of its contributors may be used to endorse
1517683Spst * or promote products derived from this software without specific prior
1617683Spst * written permission.
1717683Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817683Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917683Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2017683Spst */
2117683Spst#ifndef lint
22127664Sbmsstatic const char rcsid[] _U_ =
23214518Srpaulo    "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.59 2008-12-02 16:25:14 guy Exp $ (LBL)";
2417683Spst#endif
2517683Spst
2675107Sfenner#ifdef HAVE_CONFIG_H
2775107Sfenner#include "config.h"
2875107Sfenner#endif
2975107Sfenner
3017683Spst#include <sys/param.h>
3117683Spst#include <sys/file.h>
3217683Spst#include <sys/ioctl.h>
3317683Spst#include <sys/socket.h>
3417683Spst#include <sys/time.h>
3517683Spst
3617683Spst#include <net/raw.h>
3717683Spst#include <net/if.h>
3817683Spst
3917683Spst#include <netinet/in.h>
4017683Spst#include <netinet/in_systm.h>
4117683Spst#include <netinet/ip.h>
4217683Spst#include <netinet/if_ether.h>
4317683Spst#include <netinet/ip_var.h>
4417683Spst#include <netinet/udp.h>
4517683Spst#include <netinet/udp_var.h>
4617683Spst#include <netinet/tcp.h>
4717683Spst#include <netinet/tcpip.h>
4817683Spst
4917683Spst#include <errno.h>
5017683Spst#include <stdio.h>
5117683Spst#include <stdlib.h>
5217683Spst#include <string.h>
5317683Spst#include <unistd.h>
5417683Spst
5517683Spst#include "pcap-int.h"
5617683Spst
5717683Spst#ifdef HAVE_OS_PROTO_H
5817683Spst#include "os-proto.h"
5917683Spst#endif
6017683Spst
61127664Sbmsstatic int
62127664Sbmspcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
6317683Spst{
6417683Spst	int cc;
6517683Spst	register struct snoopheader *sh;
66146768Ssam	register u_int datalen;
67146768Ssam	register u_int caplen;
6817683Spst	register u_char *cp;
6917683Spst
7017683Spstagain:
71127664Sbms	/*
72127664Sbms	 * Has "pcap_breakloop()" been called?
73127664Sbms	 */
74127664Sbms	if (p->break_loop) {
75127664Sbms		/*
76127664Sbms		 * Yes - clear the flag that indicates that it
77127664Sbms		 * has, and return -2 to indicate that we were
78127664Sbms		 * told to break out of the loop.
79127664Sbms		 */
80127664Sbms		p->break_loop = 0;
81127664Sbms		return (-2);
82127664Sbms	}
8317683Spst	cc = read(p->fd, (char *)p->buffer, p->bufsize);
8417683Spst	if (cc < 0) {
8517683Spst		/* Don't choke when we get ptraced */
8617683Spst		switch (errno) {
8717683Spst
8817683Spst		case EINTR:
89127664Sbms			goto again;
9017683Spst
9117683Spst		case EWOULDBLOCK:
9217683Spst			return (0);			/* XXX */
9317683Spst		}
9475107Sfenner		snprintf(p->errbuf, sizeof(p->errbuf),
9575107Sfenner		    "read: %s", pcap_strerror(errno));
9617683Spst		return (-1);
9717683Spst	}
9817683Spst	sh = (struct snoopheader *)p->buffer;
9917683Spst	datalen = sh->snoop_packetlen;
100146768Ssam
101146768Ssam	/*
102146768Ssam	 * XXX - Sigh, snoop_packetlen is a 16 bit quantity.  If we
103240725Skevlo	 * got a short length, but read a full sized snoop packet,
104146768Ssam	 * assume we overflowed and add back the 64K...
105146768Ssam	 */
106146768Ssam	if (cc == (p->snapshot + sizeof(struct snoopheader)) &&
107146768Ssam	    (datalen < p->snapshot))
108146768Ssam		datalen += (64 * 1024);
109146768Ssam
11017683Spst	caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
11117683Spst	cp = (u_char *)(sh + 1) + p->offset;		/* XXX */
11217683Spst
113127664Sbms	/*
114127664Sbms	 * XXX unfortunately snoop loopback isn't exactly like
115127664Sbms	 * BSD's.  The address family is encoded in the first 2
116127664Sbms	 * bytes rather than the first 4 bytes!  Luckily the last
117127664Sbms	 * two snoop loopback bytes are zeroed.
118127664Sbms	 */
119127664Sbms	if (p->linktype == DLT_NULL && *((short *)(cp + 2)) == 0) {
120127664Sbms		u_int *uip = (u_int *)cp;
121127664Sbms		*uip >>= 16;
122127664Sbms	}
123127664Sbms
12417683Spst	if (p->fcode.bf_insns == NULL ||
12517683Spst	    bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
12617683Spst		struct pcap_pkthdr h;
12717683Spst		++p->md.stat.ps_recv;
128127664Sbms		h.ts.tv_sec = sh->snoop_timestamp.tv_sec;
129127664Sbms		h.ts.tv_usec = sh->snoop_timestamp.tv_usec;
13017683Spst		h.len = datalen;
13117683Spst		h.caplen = caplen;
13217683Spst		(*callback)(user, &h, cp);
13317683Spst		return (1);
13417683Spst	}
13517683Spst	return (0);
13617683Spst}
13717683Spst
138127664Sbmsstatic int
139146768Ssampcap_inject_snoop(pcap_t *p, const void *buf, size_t size)
140146768Ssam{
141146768Ssam	int ret;
142146768Ssam
143146768Ssam	/*
144146768Ssam	 * XXX - libnet overwrites the source address with what I
145146768Ssam	 * presume is the interface's address; is that required?
146146768Ssam	 */
147146768Ssam	ret = write(p->fd, buf, size);
148146768Ssam	if (ret == -1) {
149146768Ssam		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
150146768Ssam		    pcap_strerror(errno));
151146768Ssam		return (-1);
152146768Ssam	}
153146768Ssam	return (ret);
154146768Ssam}
155146768Ssam
156146768Ssamstatic int
157127664Sbmspcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
15817683Spst{
15917683Spst	register struct rawstats *rs;
16017683Spst	struct rawstats rawstats;
16117683Spst
16217683Spst	rs = &rawstats;
16375107Sfenner	memset(rs, 0, sizeof(*rs));
16417683Spst	if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
16575107Sfenner		snprintf(p->errbuf, sizeof(p->errbuf),
16675107Sfenner		    "SIOCRAWSTATS: %s", pcap_strerror(errno));
16717683Spst		return (-1);
16817683Spst	}
16917683Spst
17098530Sfenner	/*
17198530Sfenner	 * "ifdrops" are those dropped by the network interface
17298530Sfenner	 * due to resource shortages or hardware errors.
17398530Sfenner	 *
17498530Sfenner	 * "sbdrops" are those dropped due to socket buffer limits.
17598530Sfenner	 *
17698530Sfenner	 * As filter is done in userland, "sbdrops" counts packets
17798530Sfenner	 * regardless of whether they would've passed the filter.
17898530Sfenner	 *
17998530Sfenner	 * XXX - does this count *all* Snoop or Drain sockets,
18098530Sfenner	 * rather than just this socket?  If not, why does it have
18198530Sfenner	 * both Snoop and Drain statistics?
18298530Sfenner	 */
18317683Spst	p->md.stat.ps_drop =
18417683Spst	    rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops +
18517683Spst	    rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops;
18617683Spst
18798530Sfenner	/*
18898530Sfenner	 * "ps_recv" counts only packets that passed the filter.
18998530Sfenner	 * As filtering is done in userland, this does not include
19098530Sfenner	 * packets dropped because we ran out of buffer space.
19198530Sfenner	 */
19217683Spst	*ps = p->md.stat;
19317683Spst	return (0);
19417683Spst}
19517683Spst
19617683Spst/* XXX can't disable promiscuous */
197190225Srpaulostatic int
198190225Srpaulopcap_activate_snoop(pcap_t *p)
19917683Spst{
20017683Spst	int fd;
20117683Spst	struct sockaddr_raw sr;
20217683Spst	struct snoopfilter sf;
20317683Spst	u_int v;
20475107Sfenner	int ll_hdrlen;
20575107Sfenner	int snooplen;
20675107Sfenner	struct ifreq ifr;
20717683Spst
20817683Spst	fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
20917683Spst	if (fd < 0) {
210190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
21175107Sfenner		    pcap_strerror(errno));
21217683Spst		goto bad;
21317683Spst	}
21417683Spst	p->fd = fd;
21575107Sfenner	memset(&sr, 0, sizeof(sr));
21617683Spst	sr.sr_family = AF_RAW;
217190225Srpaulo	(void)strncpy(sr.sr_ifname, p->opt.source, sizeof(sr.sr_ifname));
21817683Spst	if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
219190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
22075107Sfenner		    pcap_strerror(errno));
22117683Spst		goto bad;
22217683Spst	}
22375107Sfenner	memset(&sf, 0, sizeof(sf));
22417683Spst	if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
225190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
22675107Sfenner		    pcap_strerror(errno));
22717683Spst		goto bad;
22817683Spst	}
229214518Srpaulo	if (p->opt.buffer_size != 0)
230214518Srpaulo		v = p->opt.buffer_size;
231190225Srpaulo	else
232190225Srpaulo		v = 64 * 1024;	/* default to 64K buffer size */
23317683Spst	(void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v));
23417683Spst	/*
23517683Spst	 * XXX hack - map device name to link layer type
23617683Spst	 */
237190225Srpaulo	if (strncmp("et", p->opt.source, 2) == 0 ||	/* Challenge 10 Mbit */
238190225Srpaulo	    strncmp("ec", p->opt.source, 2) == 0 ||	/* Indigo/Indy 10 Mbit,
239190225Srpaulo							   O2 10/100 */
240190225Srpaulo	    strncmp("ef", p->opt.source, 2) == 0 ||	/* O200/2000 10/100 Mbit */
241190225Srpaulo	    strncmp("eg", p->opt.source, 2) == 0 ||	/* Octane/O2xxx/O3xxx Gigabit */
242190225Srpaulo	    strncmp("gfe", p->opt.source, 3) == 0 ||	/* GIO 100 Mbit */
243190225Srpaulo	    strncmp("fxp", p->opt.source, 3) == 0 ||	/* Challenge VME Enet */
244190225Srpaulo	    strncmp("ep", p->opt.source, 2) == 0 ||	/* Challenge 8x10 Mbit EPLEX */
245190225Srpaulo	    strncmp("vfe", p->opt.source, 3) == 0 ||	/* Challenge VME 100Mbit */
246190225Srpaulo	    strncmp("fa", p->opt.source, 2) == 0 ||
247190225Srpaulo	    strncmp("qaa", p->opt.source, 3) == 0 ||
248190225Srpaulo	    strncmp("cip", p->opt.source, 3) == 0 ||
249190225Srpaulo	    strncmp("el", p->opt.source, 2) == 0) {
25017683Spst		p->linktype = DLT_EN10MB;
25117683Spst		p->offset = RAW_HDRPAD(sizeof(struct ether_header));
25275107Sfenner		ll_hdrlen = sizeof(struct ether_header);
253146768Ssam		/*
254146768Ssam		 * This is (presumably) a real Ethernet capture; give it a
255146768Ssam		 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
256146768Ssam		 * that an application can let you choose it, in case you're
257146768Ssam		 * capturing DOCSIS traffic that a Cisco Cable Modem
258146768Ssam		 * Termination System is putting out onto an Ethernet (it
259146768Ssam		 * doesn't put an Ethernet header onto the wire, it puts raw
260146768Ssam		 * DOCSIS frames out on the wire inside the low-level
261146768Ssam		 * Ethernet framing).
262146768Ssam		 *
263146768Ssam		 * XXX - are there any sorts of "fake Ethernet" that have
264146768Ssam		 * Ethernet link-layer headers but that *shouldn't offer
265146768Ssam		 * DLT_DOCSIS as a Cisco CMTS won't put traffic onto it
266146768Ssam		 * or get traffic bridged onto it?  "el" is for ATM LANE
267146768Ssam		 * Ethernet devices, so that might be the case for them;
268146768Ssam		 * the same applies for "qaa" classical IP devices.  If
269146768Ssam		 * "fa" devices are for FORE SPANS, that'd apply to them
270146768Ssam		 * as well; what are "cip" devices - some other ATM
271146768Ssam		 * Classical IP devices?
272146768Ssam		 */
273146768Ssam		p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
274146768Ssam		/*
275146768Ssam		 * If that fails, just leave the list empty.
276146768Ssam		 */
277146768Ssam		if (p->dlt_list != NULL) {
278146768Ssam			p->dlt_list[0] = DLT_EN10MB;
279146768Ssam			p->dlt_list[1] = DLT_DOCSIS;
280146768Ssam			p->dlt_count = 2;
281146768Ssam		}
282190225Srpaulo	} else if (strncmp("ipg", p->opt.source, 3) == 0 ||
283190225Srpaulo		   strncmp("rns", p->opt.source, 3) == 0 ||	/* O2/200/2000 FDDI */
284190225Srpaulo		   strncmp("xpi", p->opt.source, 3) == 0) {
28517683Spst		p->linktype = DLT_FDDI;
28617683Spst		p->offset = 3;				/* XXX yeah? */
28775107Sfenner		ll_hdrlen = 13;
288190225Srpaulo	} else if (strncmp("ppp", p->opt.source, 3) == 0) {
28939291Sfenner		p->linktype = DLT_RAW;
29075107Sfenner		ll_hdrlen = 0;	/* DLT_RAW meaning "no PPP header, just the IP packet"? */
291190225Srpaulo	} else if (strncmp("qfa", p->opt.source, 3) == 0) {
292127664Sbms		p->linktype = DLT_IP_OVER_FC;
293127664Sbms		ll_hdrlen = 24;
294190225Srpaulo	} else if (strncmp("pl", p->opt.source, 2) == 0) {
295127664Sbms		p->linktype = DLT_RAW;
296127664Sbms		ll_hdrlen = 0;	/* Cray UNICOS/mp pseudo link */
297190225Srpaulo	} else if (strncmp("lo", p->opt.source, 2) == 0) {
29817683Spst		p->linktype = DLT_NULL;
299127664Sbms		ll_hdrlen = 4;
30017683Spst	} else {
301190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
30275107Sfenner		    "snoop: unknown physical layer type");
30317683Spst		goto bad;
30417683Spst	}
305190225Srpaulo
306190225Srpaulo	if (p->opt.rfmon) {
307190225Srpaulo		/*
308190225Srpaulo		 * No monitor mode on Irix (no Wi-Fi devices on
309190225Srpaulo		 * hardware supported by Irix).
310190225Srpaulo		 */
311190225Srpaulo		return (PCAP_ERROR_RFMON_NOTSUP);
312190225Srpaulo	}
313190225Srpaulo
31475107Sfenner#ifdef SIOCGIFMTU
31575107Sfenner	/*
31675107Sfenner	 * XXX - IRIX appears to give you an error if you try to set the
31775107Sfenner	 * capture length to be greater than the MTU, so let's try to get
31875107Sfenner	 * the MTU first and, if that succeeds, trim the snap length
31975107Sfenner	 * to be no greater than the MTU.
32075107Sfenner	 */
321190225Srpaulo	(void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
32275107Sfenner	if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
323190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
32475107Sfenner		    pcap_strerror(errno));
32575107Sfenner		goto bad;
32675107Sfenner	}
32775107Sfenner	/*
32875107Sfenner	 * OK, we got it.
32975107Sfenner	 *
33075107Sfenner	 * XXX - some versions of IRIX 6.5 define "ifr_mtu" and have an
33175107Sfenner	 * "ifru_metric" member of the "ifr_ifru" union in an "ifreq"
33275107Sfenner	 * structure, others don't.
33375107Sfenner	 *
33475107Sfenner	 * I've no idea what's going on, so, if "ifr_mtu" isn't defined,
33575107Sfenner	 * we define it as "ifr_metric", as using that field appears to
33675107Sfenner	 * work on the versions that lack "ifr_mtu" (and, on those that
33775107Sfenner	 * don't lack it, "ifru_metric" and "ifru_mtu" are both "int"
33875107Sfenner	 * members of the "ifr_ifru" union, which suggests that they
33975107Sfenner	 * may be interchangeable in this case).
34075107Sfenner	 */
34175107Sfenner#ifndef ifr_mtu
34275107Sfenner#define ifr_mtu	ifr_metric
34375107Sfenner#endif
344190225Srpaulo	if (p->snapshot > ifr.ifr_mtu + ll_hdrlen)
345190225Srpaulo		p->snapshot = ifr.ifr_mtu + ll_hdrlen;
34675107Sfenner#endif
34717683Spst
34875107Sfenner	/*
34975107Sfenner	 * The argument to SIOCSNOOPLEN is the number of link-layer
35075107Sfenner	 * payload bytes to capture - it doesn't count link-layer
35175107Sfenner	 * header bytes.
35275107Sfenner	 */
353190225Srpaulo	snooplen = p->snapshot - ll_hdrlen;
35475107Sfenner	if (snooplen < 0)
35575107Sfenner		snooplen = 0;
35675107Sfenner	if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) {
357190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
35875107Sfenner		    pcap_strerror(errno));
35975107Sfenner		goto bad;
36075107Sfenner	}
36175107Sfenner	v = 1;
36275107Sfenner	if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
363190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
36475107Sfenner		    pcap_strerror(errno));
36575107Sfenner		goto bad;
36675107Sfenner	}
36775107Sfenner
36817683Spst	p->bufsize = 4096;				/* XXX */
36917683Spst	p->buffer = (u_char *)malloc(p->bufsize);
37017683Spst	if (p->buffer == NULL) {
371190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
37275107Sfenner		    pcap_strerror(errno));
37317683Spst		goto bad;
37417683Spst	}
37517683Spst
376127664Sbms	/*
377127664Sbms	 * "p->fd" is a socket, so "select()" should work on it.
378127664Sbms	 */
379127664Sbms	p->selectable_fd = p->fd;
380127664Sbms
381127664Sbms	p->read_op = pcap_read_snoop;
382146768Ssam	p->inject_op = pcap_inject_snoop;
383127664Sbms	p->setfilter_op = install_bpf_program;	/* no kernel filtering */
384147894Ssam	p->setdirection_op = NULL;	/* Not implemented. */
385127664Sbms	p->set_datalink_op = NULL;	/* can't change data link type */
386127664Sbms	p->getnonblock_op = pcap_getnonblock_fd;
387127664Sbms	p->setnonblock_op = pcap_setnonblock_fd;
388127664Sbms	p->stats_op = pcap_stats_snoop;
389127664Sbms
390190225Srpaulo	return (0);
39117683Spst bad:
392214518Srpaulo	pcap_cleanup_live_common(p);
393190225Srpaulo	return (PCAP_ERROR);
39417683Spst}
39517683Spst
396190225Srpaulopcap_t *
397251129Sdelphijpcap_create_interface(const char *device, char *ebuf)
398190225Srpaulo{
399190225Srpaulo	pcap_t *p;
400190225Srpaulo
401190225Srpaulo	p = pcap_create_common(device, ebuf);
402190225Srpaulo	if (p == NULL)
403190225Srpaulo		return (NULL);
404190225Srpaulo
405190225Srpaulo	p->activate_op = pcap_activate_snoop;
406190225Srpaulo	return (p);
407190225Srpaulo}
408190225Srpaulo
40917683Spstint
410127664Sbmspcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
41117683Spst{
41217683Spst	return (0);
41317683Spst}
414