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 */
68static int nit_setflags(int, int, int, char *);
69
70/*
71 * Private data for capturing on NIT devices.
72 */
73struct pcap_nit {
74	struct pcap_stat stat;
75};
76
77static int
78pcap_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
102static int
103pcap_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_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
118			    errno, "pcap_read");
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
199static int
200pcap_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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
210		    errno, "send");
211		return (-1);
212	}
213	return (ret);
214}
215
216static int
217nit_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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
253		    errno, "SIOCSNIT");
254		return (-1);
255	}
256	return (0);
257}
258
259static int
260pcap_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	/*
275	 * Turn a negative snapshot value (invalid), a snapshot value of
276	 * 0 (unspecified), or a value bigger than the normal maximum
277	 * value, into the maximum allowed value.
278	 *
279	 * If some application really *needs* a bigger snapshot
280	 * length, we should just increase MAXIMUM_SNAPLEN.
281	 */
282	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
283		p->snapshot = MAXIMUM_SNAPLEN;
284
285	if (p->snapshot < 96)
286		/*
287		 * NIT requires a snapshot length of at least 96.
288		 */
289		p->snapshot = 96;
290
291	memset(p, 0, sizeof(*p));
292	p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
293	if (fd < 0) {
294		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
295		    errno, "socket");
296		goto bad;
297	}
298	snit.snit_family = AF_NIT;
299	(void)strncpy(snit.snit_ifname, p->opt.device, NITIFSIZ);
300
301	if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
302		/*
303		 * XXX - there's probably a particular bind error that
304		 * means "there's no such device" and a particular bind
305		 * error that means "that device doesn't support NIT";
306		 * they might be the same error, if they both end up
307		 * meaning "NIT doesn't know about that device".
308		 */
309		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
310		    errno, "bind: %s", snit.snit_ifname);
311		goto bad;
312	}
313	if (nit_setflags(p) < 0)
314		goto bad;
315
316	/*
317	 * NIT supports only ethernets.
318	 */
319	p->linktype = DLT_EN10MB;
320
321	p->bufsize = BUFSPACE;
322	p->buffer = malloc(p->bufsize);
323	if (p->buffer == NULL) {
324		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
325		    errno, "malloc");
326		goto bad;
327	}
328
329	/*
330	 * "p->fd" is a socket, so "select()" should work on it.
331	 */
332	p->selectable_fd = p->fd;
333
334	/*
335	 * This is (presumably) a real Ethernet capture; give it a
336	 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
337	 * that an application can let you choose it, in case you're
338	 * capturing DOCSIS traffic that a Cisco Cable Modem
339	 * Termination System is putting out onto an Ethernet (it
340	 * doesn't put an Ethernet header onto the wire, it puts raw
341	 * DOCSIS frames out on the wire inside the low-level
342	 * Ethernet framing).
343	 */
344	p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
345	/*
346	 * If that fails, just leave the list empty.
347	 */
348	if (p->dlt_list != NULL) {
349		p->dlt_list[0] = DLT_EN10MB;
350		p->dlt_list[1] = DLT_DOCSIS;
351		p->dlt_count = 2;
352	}
353
354	p->read_op = pcap_read_nit;
355	p->inject_op = pcap_inject_nit;
356	p->setfilter_op = install_bpf_program;	/* no kernel filtering */
357	p->setdirection_op = NULL;	/* Not implemented. */
358	p->set_datalink_op = NULL;	/* can't change data link type */
359	p->getnonblock_op = pcap_getnonblock_fd;
360	p->setnonblock_op = pcap_setnonblock_fd;
361	p->stats_op = pcap_stats_nit;
362
363	return (0);
364 bad:
365	pcap_cleanup_live_common(p);
366	return (PCAP_ERROR);
367}
368
369pcap_t *
370pcap_create_interface(const char *device _U_, char *ebuf)
371{
372	pcap_t *p;
373
374	p = pcap_create_common(ebuf, sizeof (struct pcap_nit));
375	if (p == NULL)
376		return (NULL);
377
378	p->activate_op = pcap_activate_nit;
379	return (p);
380}
381
382/*
383 * XXX - there's probably a particular bind error that means "that device
384 * doesn't support NIT"; if so, we should try a bind and use that.
385 */
386static int
387can_be_bound(const char *name _U_)
388{
389	return (1);
390}
391
392static int
393get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
394{
395	/*
396	 * Nothing we can do.
397	 * XXX - is there a way to find out whether an adapter has
398	 * something plugged into it?
399	 */
400	return (0);
401}
402
403int
404pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
405{
406	return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
407	    get_if_flags));
408}
409
410/*
411 * Libpcap version string.
412 */
413const char *
414pcap_lib_version(void)
415{
416	return (PCAP_VERSION_STRING);
417}
418