1511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * This code is derived from code formerly in pcap-dlpi.c, originally
3511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), University College
4511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * London, and subsequently modified by Guy Harris (guy@alum.mit.edu),
5511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>,
6511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
7511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
8511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
9511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
10511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * This file contains dlpi/libdlpi related common functions used
11511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * by pcap-[dlpi,libdlpi].c.
12511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
13511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
14511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_CONFIG_H
15511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "config.h"
16511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
17511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
18511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef DL_IPATM
19511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define DL_IPATM	0x12	/* ATM Classical IP interface */
20511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
21511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
22511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BUFMOD_H
23511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
24511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Size of a bufmod chunk to pass upstream; that appears to be the
25511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * biggest value to which you can set it, and setting it to that value
26511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * (which is bigger than what appears to be the Solaris default of 8192)
27511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * reduces the number of packet drops.
28511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
29511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define	CHUNKSIZE	65536
30511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
31511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
32511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Size of the buffer to allocate for packet data we read; it must be
33511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * large enough to hold a chunk.
34511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
35511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define	PKTBUFSIZE	CHUNKSIZE
36511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
37511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else /* HAVE_SYS_BUFMOD_H */
38511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
39511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
40511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Size of the buffer to allocate for packet data we read; this is
41511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * what the value used to be - there's no particular reason why it
42511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * should be tied to MAXDLBUF, but we'll leave it as this for now.
43511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
44511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define	MAXDLBUF	8192
45511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define	PKTBUFSIZE	(MAXDLBUF * sizeof(bpf_u_int32))
46511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
47511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
48511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
49511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/types.h>
50511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/time.h>
51511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BUFMOD_H
52511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/bufmod.h>
53511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
54511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/dlpi.h>
55511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/stream.h>
56511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
57511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <errno.h>
58511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <memory.h>
59511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stdio.h>
60511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stdlib.h>
61511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <string.h>
62511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stropts.h>
63511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <unistd.h>
64511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
65511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LIBDLPI
66511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <libdlpi.h>
67511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
68511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
69511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap-int.h"
70511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "dlpisubs.h"
71511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
72511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BUFMOD_H
73511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void pcap_stream_err(const char *, int, char *);
74511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
75511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
76511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
77511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Get the packet statistics.
78511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
79511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint
80511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
81511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
82511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_dlpi *pd = p->priv;
83511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
84511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
85511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "ps_recv" counts packets handed to the filter, not packets
86511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * that passed the filter.  As filtering is done in userland,
87511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * this would not include packets dropped because we ran out
88511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * of buffer space; in order to make this more like other
89511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * platforms (Linux 2.4 and later, BSDs with BPF), where the
90511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "packets received" count includes packets received but dropped
91511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * due to running out of buffer space, and to keep from confusing
92511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * applications that, for example, compute packet drop percentages,
93511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we also make it count packets dropped by "bufmod" (otherwise we
94511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * might run the risk of the packet drop count being bigger than
95511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the received-packet count).
96511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
97511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "ps_drop" counts packets dropped by "bufmod" because of
98511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * flow control requirements or resource exhaustion; it doesn't
99511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * count packets dropped by the interface driver, or packets
100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * dropped upstream.  As filtering is done in userland, it counts
101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * packets regardless of whether they would've passed the filter.
102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * These statistics don't include packets not yet read from
104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the kernel by libpcap, but they may include packets not
105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * yet read from libpcap by the application.
106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	*ps = pd->stat;
108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
109511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Add in the drop count, as per the above comment.
111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ps->ps_recv += ps->ps_drop;
113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (0);
114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Loop through the packets and call the callback for each packet.
118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Return the number of packets read.
119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint
121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int count, u_char *bufp, int len)
123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_dlpi *pd = p->priv;
125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int n, caplen, origlen;
126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_char *ep, *pk;
127511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_pkthdr pkthdr;
128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BUFMOD_H
129511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct sb_hdr *sbp;
130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef LBL_ALIGN
131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct sb_hdr sbhdr;
132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Loop through packets */
136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ep = bufp + len;
137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	n = 0;
138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BUFMOD_H
140511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	while (bufp < ep) {
141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
142511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Has "pcap_breakloop()" been called?
143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If so, return immediately - if we haven't read any
144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * packets, clear the flag and return -2 to indicate
145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * that we were told to break out of the loop, otherwise
146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * leave the flag set, so that the *next* call will break
147511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * out of the loop without having read any packets, and
148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * return the number of packets we've processed so far.
149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (p->break_loop) {
151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (n == 0) {
152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				p->break_loop = 0;
153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return (-2);
154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			} else {
155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				p->bp = bufp;
156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				p->cc = ep - bufp;
157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return (n);
158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
159511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
160511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef LBL_ALIGN
161511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ((long)bufp & 3) {
162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			sbp = &sbhdr;
163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			memcpy(sbp, bufp, sizeof(*sbp));
164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else
165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
166511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			sbp = (struct sb_hdr *)bufp;
167511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pd->stat.ps_drop = sbp->sbh_drops;
168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pk = bufp + sizeof(*sbp);
169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bufp += sbp->sbh_totlen;
170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		origlen = sbp->sbh_origlen;
171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		caplen = sbp->sbh_msglen;
172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		origlen = len;
174511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		caplen = min(p->snapshot, len);
175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pk = bufp;
176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bufp += caplen;
177511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		++pd->stat.ps_recv;
179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
180511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BUFMOD_H
181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
184511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			(void) gettimeofday(&pkthdr.ts, NULL);
185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkthdr.len = origlen;
187511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkthdr.caplen = caplen;
188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* Insure caplen does not exceed snapshot */
189965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes			if (pkthdr.caplen > (bpf_u_int32)p->snapshot)
190965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes				pkthdr.caplen = (bpf_u_int32)p->snapshot;
191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			(*callback)(user, &pkthdr, pk);
192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (++n >= count && !PACKET_COUNT_IS_UNLIMITED(count)) {
193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				p->cc = ep - bufp;
194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				p->bp = bufp;
195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return (n);
196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BUFMOD_H
199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	p->cc = 0;
202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (n);
203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Process the mac type. Returns -1 if no matching mac type found, otherwise 0.
207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint
209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_process_mactype(pcap_t *p, u_int mactype)
210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int retv = 0;
212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (mactype) {
214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DL_CSMACD:
216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DL_ETHER:
217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->linktype = DLT_EN10MB;
218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->offset = 2;
219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * This is (presumably) a real Ethernet capture; give it a
221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * that an application can let you choose it, in case you're
223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * capturing DOCSIS traffic that a Cisco Cable Modem
224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Termination System is putting out onto an Ethernet (it
225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * doesn't put an Ethernet header onto the wire, it puts raw
226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * DOCSIS frames out on the wire inside the low-level
227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Ethernet framing).
228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->dlt_list = (u_int *)malloc(sizeof(u_int) * 2);
230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If that fails, just leave the list empty.
232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (p->dlt_list != NULL) {
234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			p->dlt_list[0] = DLT_EN10MB;
235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			p->dlt_list[1] = DLT_DOCSIS;
236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			p->dlt_count = 2;
237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DL_FDDI:
241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->linktype = DLT_FDDI;
242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->offset = 3;
243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DL_TPR:
246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* XXX - what about DL_TPB?  Is that Token Bus?  */
247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->linktype = DLT_IEEE802;
248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->offset = 2;
249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SOLARIS
252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DL_IPATM:
253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->linktype = DLT_SUNATM;
254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->offset = 0;  /* works for LANE and LLC encapsulation */
255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
258965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes#ifdef DL_IPV4
259965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes	case DL_IPV4:
260965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		p->linktype = DLT_IPV4;
261965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		p->offset = 0;
262965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		break;
263965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes#endif
264965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes
265965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes#ifdef DL_IPV6
266965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes	case DL_IPV6:
267965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		p->linktype = DLT_IPV6;
268965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		p->offset = 0;
269965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		break;
270965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes#endif
271965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes
272965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes#ifdef DL_IPNET
273965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes	case DL_IPNET:
274965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		p->linktype = DLT_IPNET;
275965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		p->offset = 0;
276965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		break;
277965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes#endif
278965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes
279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
280965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype 0x%x",
281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    mactype);
282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		retv = -1;
283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (retv);
286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BUFMOD_H
289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Push and configure the buffer module. Returns -1 for error, otherwise 0.
291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint
293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_conf_bufmod(pcap_t *p, int snaplen)
294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct timeval to;
296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	bpf_u_int32 ss, chunksize;
297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Non-standard call to get the data nicely buffered. */
299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcap_stream_err("I_PUSH bufmod", errno, p->errbuf);
301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);
302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ss = snaplen;
305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ss > 0 &&
306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcap_stream_err("SBIOCSSNAP", errno, p->errbuf);
308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);
309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (p->opt.immediate) {
312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Set the timeout to zero, for immediate delivery. */
313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		to.tv_sec = 0;
314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		to.tv_usec = 0;
315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return (-1);
318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else {
320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Set up the bufmod timeout. */
321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (p->opt.timeout != 0) {
322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			to.tv_sec = p->opt.timeout / 1000;
323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			to.tv_usec = (p->opt.timeout * 1000) % 1000000;
324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return (-1);
327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Set the chunk length. */
331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		chunksize = CHUNKSIZE;
332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    != 0) {
334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pcap_stream_err("SBIOCSCHUNKP", errno, p->errbuf);
335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return (-1);
336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (0);
340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_SYS_BUFMOD_H */
342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Allocate data buffer. Returns -1 if memory allocation fails, else 0.
345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint
347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_alloc_databuf(pcap_t *p)
348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	p->bufsize = PKTBUFSIZE;
350965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes	p->buffer = malloc(p->bufsize + p->offset);
351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (p->buffer == NULL) {
352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);
354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (0);
357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Issue a STREAMS I_STR ioctl. Returns -1 on error, otherwise
361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * length of returned data on success.
362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint
364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstrioctl(int fd, int cmd, int len, char *dp)
365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct strioctl str;
367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int retv;
368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	str.ic_cmd = cmd;
370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	str.ic_timout = -1;
371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	str.ic_len = len;
372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	str.ic_dp = dp;
373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if ((retv = ioctl(fd, I_STR, &str)) < 0)
374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (retv);
375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (str.ic_len);
377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BUFMOD_H
380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Write stream error message to errbuf.
382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void
384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_stream_err(const char *func, int err, char *errbuf)
385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
386965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", func, pcap_strerror(err));
387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
389