Home | History | Annotate | Download | only in libpcap
      1 /*
      2  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that: (1) source code distributions
      7  * retain the above copyright notice and this paragraph in its entirety, (2)
      8  * distributions including binary code include the above copyright notice and
      9  * this paragraph in its entirety in the documentation or other materials
     10  * provided with the distribution, and (3) all advertising materials mentioning
     11  * features or use of this software display the following acknowledgement:
     12  * ``This product includes software developed by the University of California,
     13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     14  * the University nor the names of its contributors may be used to endorse
     15  * or promote products derived from this software without specific prior
     16  * written permission.
     17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     20  */
     21 
     22 #ifdef HAVE_CONFIG_H
     23 #include "config.h"
     24 #endif
     25 
     26 #include <sys/types.h>
     27 #include <sys/time.h>
     28 #include <sys/timeb.h>
     29 #include <sys/file.h>
     30 #include <sys/ioctl.h>
     31 #include <sys/socket.h>
     32 
     33 #include <net/if.h>
     34 #include <net/nit.h>
     35 
     36 #include <netinet/in.h>
     37 #include <netinet/in_systm.h>
     38 #include <netinet/ip.h>
     39 #include <netinet/if_ether.h>
     40 #include <netinet/ip_var.h>
     41 #include <netinet/udp.h>
     42 #include <netinet/udp_var.h>
     43 #include <netinet/tcp.h>
     44 #include <netinet/tcpip.h>
     45 
     46 #include <ctype.h>
     47 #include <errno.h>
     48 #include <stdio.h>
     49 
     50 #include "pcap-int.h"
     51 
     52 #ifdef HAVE_OS_PROTO_H
     53 #include "os-proto.h"
     54 #endif
     55 
     56 /*
     57  * The chunk size for NIT.  This is the amount of buffering
     58  * done for read calls.
     59  */
     60 #define CHUNKSIZE (2*1024)
     61 
     62 /*
     63  * The total buffer space used by NIT.
     64  */
     65 #define BUFSPACE (4*CHUNKSIZE)
     66 
     67 /* Forwards */
     68 static int nit_setflags(int, int, int, char *);
     69 
     70 /*
     71  * Private data for capturing on NIT devices.
     72  */
     73 struct pcap_nit {
     74 	struct pcap_stat stat;
     75 };
     76 
     77 static int
     78 pcap_stats_nit(pcap_t *p, struct pcap_stat *ps)
     79 {
     80 	struct pcap_nit *pn = p->priv;
     81 
     82 	/*
     83 	 * "ps_recv" counts packets handed to the filter, not packets
     84 	 * that passed the filter.  As filtering is done in userland,
     85 	 * this does not include packets dropped because we ran out
     86 	 * of buffer space.
     87 	 *
     88 	 * "ps_drop" presumably counts packets dropped by the socket
     89 	 * because of flow control requirements or resource exhaustion;
     90 	 * it doesn't count packets dropped by the interface driver.
     91 	 * As filtering is done in userland, it counts packets regardless
     92 	 * of whether they would've passed the filter.
     93 	 *
     94 	 * These statistics don't include packets not yet read from the
     95 	 * kernel by libpcap or packets not yet read from libpcap by the
     96 	 * application.
     97 	 */
     98 	*ps = pn->stat;
     99 	return (0);
    100 }
    101 
    102 static int
    103 pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    104 {
    105 	struct pcap_nit *pn = p->priv;
    106 	register int cc, n;
    107 	register u_char *bp, *cp, *ep;
    108 	register struct nit_hdr *nh;
    109 	register int caplen;
    110 
    111 	cc = p->cc;
    112 	if (cc == 0) {
    113 		cc = read(p->fd, (char *)p->buffer, p->bufsize);
    114 		if (cc < 0) {
    115 			if (errno == EWOULDBLOCK)
    116 				return (0);
    117 			pcap_snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
    118 				pcap_strerror(errno));
    119 			return (-1);
    120 		}
    121 		bp = (u_char *)p->buffer;
    122 	} else
    123 		bp = p->bp;
    124 
    125 	/*
    126 	 * Loop through each packet.  The increment expression
    127 	 * rounds up to the next int boundary past the end of
    128 	 * the previous packet.
    129 	 */
    130 	n = 0;
    131 	ep = bp + cc;
    132 	while (bp < ep) {
    133 		/*
    134 		 * Has "pcap_breakloop()" been called?
    135 		 * If so, return immediately - if we haven't read any
    136 		 * packets, clear the flag and return -2 to indicate
    137 		 * that we were told to break out of the loop, otherwise
    138 		 * leave the flag set, so that the *next* call will break
    139 		 * out of the loop without having read any packets, and
    140 		 * return the number of packets we've processed so far.
    141 		 */
    142 		if (p->break_loop) {
    143 			if (n == 0) {
    144 				p->break_loop = 0;
    145 				return (-2);
    146 			} else {
    147 				p->cc = ep - bp;
    148 				p->bp = bp;
    149 				return (n);
    150 			}
    151 		}
    152 
    153 		nh = (struct nit_hdr *)bp;
    154 		cp = bp + sizeof(*nh);
    155 
    156 		switch (nh->nh_state) {
    157 
    158 		case NIT_CATCH:
    159 			break;
    160 
    161 		case NIT_NOMBUF:
    162 		case NIT_NOCLUSTER:
    163 		case NIT_NOSPACE:
    164 			pn->stat.ps_drop = nh->nh_dropped;
    165 			continue;
    166 
    167 		case NIT_SEQNO:
    168 			continue;
    169 
    170 		default:
    171 			pcap_snprintf(p->errbuf, sizeof(p->errbuf),
    172 			    "bad nit state %d", nh->nh_state);
    173 			return (-1);
    174 		}
    175 		++pn->stat.ps_recv;
    176 		bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
    177 		    sizeof(int) - 1) & ~(sizeof(int) - 1));
    178 
    179 		caplen = nh->nh_wirelen;
    180 		if (caplen > p->snapshot)
    181 			caplen = p->snapshot;
    182 		if (bpf_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) {
    183 			struct pcap_pkthdr h;
    184 			h.ts = nh->nh_timestamp;
    185 			h.len = nh->nh_wirelen;
    186 			h.caplen = caplen;
    187 			(*callback)(user, &h, cp);
    188 			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
    189 				p->cc = ep - bp;
    190 				p->bp = bp;
    191 				return (n);
    192 			}
    193 		}
    194 	}
    195 	p->cc = 0;
    196 	return (n);
    197 }
    198 
    199 static int
    200 pcap_inject_nit(pcap_t *p, const void *buf, size_t size)
    201 {
    202 	struct sockaddr sa;
    203 	int ret;
    204 
    205 	memset(&sa, 0, sizeof(sa));
    206 	strncpy(sa.sa_data, device, sizeof(sa.sa_data));
    207 	ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa));
    208 	if (ret == -1) {
    209 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
    210 		    pcap_strerror(errno));
    211 		return (-1);
    212 	}
    213 	return (ret);
    214 }
    215 
    216 static int
    217 nit_setflags(pcap_t *p)
    218 {
    219 	struct nit_ioc nioc;
    220 
    221 	memset(&nioc, 0, sizeof(nioc));
    222 	nioc.nioc_typetomatch = NT_ALLTYPES;
    223 	nioc.nioc_snaplen = p->snapshot;
    224 	nioc.nioc_bufalign = sizeof(int);
    225 	nioc.nioc_bufoffset = 0;
    226 
    227 	if (p->opt.buffer_size != 0)
    228 		nioc.nioc_bufspace = p->opt.buffer_size;
    229 	else {
    230 		/* Default buffer size */
    231 		nioc.nioc_bufspace = BUFSPACE;
    232 	}
    233 
    234 	if (p->opt.immediate) {
    235 		/*
    236 		 * XXX - will this cause packets to be delivered immediately?
    237 		 * XXX - given that this is for SunOS prior to 4.0, do
    238 		 * we care?
    239 		 */
    240 		nioc.nioc_chunksize = 0;
    241 	} else
    242 		nioc.nioc_chunksize = CHUNKSIZE;
    243 	if (p->opt.timeout != 0) {
    244 		nioc.nioc_flags |= NF_TIMEOUT;
    245 		nioc.nioc_timeout.tv_sec = p->opt.timeout / 1000;
    246 		nioc.nioc_timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
    247 	}
    248 	if (p->opt.promisc)
    249 		nioc.nioc_flags |= NF_PROMISC;
    250 
    251 	if (ioctl(p->fd, SIOCSNIT, &nioc) < 0) {
    252 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s",
    253 		    pcap_strerror(errno));
    254 		return (-1);
    255 	}
    256 	return (0);
    257 }
    258 
    259 static int
    260 pcap_activate_nit(pcap_t *p)
    261 {
    262 	int fd;
    263 	struct sockaddr_nit snit;
    264 
    265 	if (p->opt.rfmon) {
    266 		/*
    267 		 * No monitor mode on SunOS 3.x or earlier (no
    268 		 * Wi-Fi *devices* for the hardware that supported
    269 		 * them!).
    270 		 */
    271 		return (PCAP_ERROR_RFMON_NOTSUP);
    272 	}
    273 
    274 	if (p->snapshot < 96)
    275 		/*
    276 		 * NIT requires a snapshot length of at least 96.
    277 		 */
    278 		p->snapshot = 96;
    279 
    280 	memset(p, 0, sizeof(*p));
    281 	p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
    282 	if (fd < 0) {
    283 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    284 		    "socket: %s", pcap_strerror(errno));
    285 		goto bad;
    286 	}
    287 	snit.snit_family = AF_NIT;
    288 	(void)strncpy(snit.snit_ifname, p->opt.device, NITIFSIZ);
    289 
    290 	if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
    291 		/*
    292 		 * XXX - there's probably a particular bind error that
    293 		 * means "there's no such device" and a particular bind
    294 		 * error that means "that device doesn't support NIT";
    295 		 * they might be the same error, if they both end up
    296 		 * meaning "NIT doesn't know about that device".
    297 		 */
    298 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    299 		    "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
    300 		goto bad;
    301 	}
    302 	if (nit_setflags(p) < 0)
    303 		goto bad;
    304 
    305 	/*
    306 	 * NIT supports only ethernets.
    307 	 */
    308 	p->linktype = DLT_EN10MB;
    309 
    310 	p->bufsize = BUFSPACE;
    311 	p->buffer = malloc(p->bufsize);
    312 	if (p->buffer == NULL) {
    313 		strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
    314 		goto bad;
    315 	}
    316 
    317 	/*
    318 	 * "p->fd" is a socket, so "select()" should work on it.
    319 	 */
    320 	p->selectable_fd = p->fd;
    321 
    322 	/*
    323 	 * This is (presumably) a real Ethernet capture; give it a
    324 	 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
    325 	 * that an application can let you choose it, in case you're
    326 	 * capturing DOCSIS traffic that a Cisco Cable Modem
    327 	 * Termination System is putting out onto an Ethernet (it
    328 	 * doesn't put an Ethernet header onto the wire, it puts raw
    329 	 * DOCSIS frames out on the wire inside the low-level
    330 	 * Ethernet framing).
    331 	 */
    332 	p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
    333 	/*
    334 	 * If that fails, just leave the list empty.
    335 	 */
    336 	if (p->dlt_list != NULL) {
    337 		p->dlt_list[0] = DLT_EN10MB;
    338 		p->dlt_list[1] = DLT_DOCSIS;
    339 		p->dlt_count = 2;
    340 	}
    341 
    342 	p->read_op = pcap_read_nit;
    343 	p->inject_op = pcap_inject_nit;
    344 	p->setfilter_op = install_bpf_program;	/* no kernel filtering */
    345 	p->setdirection_op = NULL;	/* Not implemented. */
    346 	p->set_datalink_op = NULL;	/* can't change data link type */
    347 	p->getnonblock_op = pcap_getnonblock_fd;
    348 	p->setnonblock_op = pcap_setnonblock_fd;
    349 	p->stats_op = pcap_stats_nit;
    350 
    351 	return (0);
    352  bad:
    353 	pcap_cleanup_live_common(p);
    354 	return (PCAP_ERROR);
    355 }
    356 
    357 pcap_t *
    358 pcap_create_interface(const char *device _U_, char *ebuf)
    359 {
    360 	pcap_t *p;
    361 
    362 	p = pcap_create_common(ebuf, sizeof (struct pcap_nit));
    363 	if (p == NULL)
    364 		return (NULL);
    365 
    366 	p->activate_op = pcap_activate_nit;
    367 	return (p);
    368 }
    369 
    370 /*
    371  * XXX - there's probably a particular bind error that means "that device
    372  * doesn't support NIT"; if so, we should try a bind and use that.
    373  */
    374 static int
    375 can_be_bound(const char *name _U_)
    376 {
    377 	return (1);
    378 }
    379 
    380 int
    381 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
    382 {
    383 	return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
    384 }
    385