xref: /aosp_15_r20/external/libpcap/pcap-dag.c (revision 8b26181f966a6af5cf6981a6f474313de533bb28)
1*8b26181fSAndroid Build Coastguard Worker /*
2*8b26181fSAndroid Build Coastguard Worker  * pcap-dag.c: Packet capture interface for Endace DAG cards.
3*8b26181fSAndroid Build Coastguard Worker  *
4*8b26181fSAndroid Build Coastguard Worker  * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
5*8b26181fSAndroid Build Coastguard Worker  * Modifications: Jesper Peterson
6*8b26181fSAndroid Build Coastguard Worker  *                Koryn Grant
7*8b26181fSAndroid Build Coastguard Worker  *                Stephen Donnelly <[email protected]>
8*8b26181fSAndroid Build Coastguard Worker  */
9*8b26181fSAndroid Build Coastguard Worker 
10*8b26181fSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
11*8b26181fSAndroid Build Coastguard Worker #include <config.h>
12*8b26181fSAndroid Build Coastguard Worker #endif
13*8b26181fSAndroid Build Coastguard Worker 
14*8b26181fSAndroid Build Coastguard Worker #include <sys/param.h>			/* optionally get BSD define */
15*8b26181fSAndroid Build Coastguard Worker 
16*8b26181fSAndroid Build Coastguard Worker #include <stdlib.h>
17*8b26181fSAndroid Build Coastguard Worker #include <string.h>
18*8b26181fSAndroid Build Coastguard Worker #include <errno.h>
19*8b26181fSAndroid Build Coastguard Worker 
20*8b26181fSAndroid Build Coastguard Worker #include "pcap-int.h"
21*8b26181fSAndroid Build Coastguard Worker 
22*8b26181fSAndroid Build Coastguard Worker #include <netinet/in.h>
23*8b26181fSAndroid Build Coastguard Worker #include <sys/mman.h>
24*8b26181fSAndroid Build Coastguard Worker #include <sys/socket.h>
25*8b26181fSAndroid Build Coastguard Worker #include <sys/types.h>
26*8b26181fSAndroid Build Coastguard Worker #include <unistd.h>
27*8b26181fSAndroid Build Coastguard Worker 
28*8b26181fSAndroid Build Coastguard Worker struct mbuf;		/* Squelch compiler warnings on some platforms for */
29*8b26181fSAndroid Build Coastguard Worker struct rtentry;		/* declarations in <net/if.h> */
30*8b26181fSAndroid Build Coastguard Worker #include <net/if.h>
31*8b26181fSAndroid Build Coastguard Worker 
32*8b26181fSAndroid Build Coastguard Worker #include "dagnew.h"
33*8b26181fSAndroid Build Coastguard Worker #include "dagapi.h"
34*8b26181fSAndroid Build Coastguard Worker #include "dagpci.h"
35*8b26181fSAndroid Build Coastguard Worker #include "dag_config_api.h"
36*8b26181fSAndroid Build Coastguard Worker 
37*8b26181fSAndroid Build Coastguard Worker #include "pcap-dag.h"
38*8b26181fSAndroid Build Coastguard Worker 
39*8b26181fSAndroid Build Coastguard Worker /*
40*8b26181fSAndroid Build Coastguard Worker  * DAG devices have names beginning with "dag", followed by a number
41*8b26181fSAndroid Build Coastguard Worker  * from 0 to DAG_MAX_BOARDS, then optionally a colon and a stream number
42*8b26181fSAndroid Build Coastguard Worker  * from 0 to DAG_STREAM_MAX.
43*8b26181fSAndroid Build Coastguard Worker  */
44*8b26181fSAndroid Build Coastguard Worker #ifndef DAG_MAX_BOARDS
45*8b26181fSAndroid Build Coastguard Worker #define DAG_MAX_BOARDS 32
46*8b26181fSAndroid Build Coastguard Worker #endif
47*8b26181fSAndroid Build Coastguard Worker 
48*8b26181fSAndroid Build Coastguard Worker 
49*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_AAL5
50*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_AAL5               4
51*8b26181fSAndroid Build Coastguard Worker #endif
52*8b26181fSAndroid Build Coastguard Worker 
53*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_MC_HDLC
54*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_MC_HDLC            5
55*8b26181fSAndroid Build Coastguard Worker #endif
56*8b26181fSAndroid Build Coastguard Worker 
57*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_MC_RAW
58*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_MC_RAW             6
59*8b26181fSAndroid Build Coastguard Worker #endif
60*8b26181fSAndroid Build Coastguard Worker 
61*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_MC_ATM
62*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_MC_ATM             7
63*8b26181fSAndroid Build Coastguard Worker #endif
64*8b26181fSAndroid Build Coastguard Worker 
65*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_MC_RAW_CHANNEL
66*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_MC_RAW_CHANNEL     8
67*8b26181fSAndroid Build Coastguard Worker #endif
68*8b26181fSAndroid Build Coastguard Worker 
69*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_MC_AAL5
70*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_MC_AAL5            9
71*8b26181fSAndroid Build Coastguard Worker #endif
72*8b26181fSAndroid Build Coastguard Worker 
73*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_COLOR_HDLC_POS
74*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_COLOR_HDLC_POS     10
75*8b26181fSAndroid Build Coastguard Worker #endif
76*8b26181fSAndroid Build Coastguard Worker 
77*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_COLOR_ETH
78*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_COLOR_ETH          11
79*8b26181fSAndroid Build Coastguard Worker #endif
80*8b26181fSAndroid Build Coastguard Worker 
81*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_MC_AAL2
82*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_MC_AAL2            12
83*8b26181fSAndroid Build Coastguard Worker #endif
84*8b26181fSAndroid Build Coastguard Worker 
85*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_IP_COUNTER
86*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_IP_COUNTER         13
87*8b26181fSAndroid Build Coastguard Worker #endif
88*8b26181fSAndroid Build Coastguard Worker 
89*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_TCP_FLOW_COUNTER
90*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_TCP_FLOW_COUNTER   14
91*8b26181fSAndroid Build Coastguard Worker #endif
92*8b26181fSAndroid Build Coastguard Worker 
93*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_DSM_COLOR_HDLC_POS
94*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_DSM_COLOR_HDLC_POS 15
95*8b26181fSAndroid Build Coastguard Worker #endif
96*8b26181fSAndroid Build Coastguard Worker 
97*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_DSM_COLOR_ETH
98*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_DSM_COLOR_ETH      16
99*8b26181fSAndroid Build Coastguard Worker #endif
100*8b26181fSAndroid Build Coastguard Worker 
101*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_COLOR_MC_HDLC_POS
102*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_COLOR_MC_HDLC_POS  17
103*8b26181fSAndroid Build Coastguard Worker #endif
104*8b26181fSAndroid Build Coastguard Worker 
105*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_AAL2
106*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_AAL2               18
107*8b26181fSAndroid Build Coastguard Worker #endif
108*8b26181fSAndroid Build Coastguard Worker 
109*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_COLOR_HASH_POS
110*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_COLOR_HASH_POS     19
111*8b26181fSAndroid Build Coastguard Worker #endif
112*8b26181fSAndroid Build Coastguard Worker 
113*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_COLOR_HASH_ETH
114*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_COLOR_HASH_ETH     20
115*8b26181fSAndroid Build Coastguard Worker #endif
116*8b26181fSAndroid Build Coastguard Worker 
117*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_INFINIBAND
118*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_INFINIBAND         21
119*8b26181fSAndroid Build Coastguard Worker #endif
120*8b26181fSAndroid Build Coastguard Worker 
121*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_IPV4
122*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_IPV4               22
123*8b26181fSAndroid Build Coastguard Worker #endif
124*8b26181fSAndroid Build Coastguard Worker 
125*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_IPV6
126*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_IPV6               23
127*8b26181fSAndroid Build Coastguard Worker #endif
128*8b26181fSAndroid Build Coastguard Worker 
129*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_RAW_LINK
130*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_RAW_LINK           24
131*8b26181fSAndroid Build Coastguard Worker #endif
132*8b26181fSAndroid Build Coastguard Worker 
133*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_INFINIBAND_LINK
134*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_INFINIBAND_LINK    25
135*8b26181fSAndroid Build Coastguard Worker #endif
136*8b26181fSAndroid Build Coastguard Worker 
137*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_META
138*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_META               27
139*8b26181fSAndroid Build Coastguard Worker #endif
140*8b26181fSAndroid Build Coastguard Worker 
141*8b26181fSAndroid Build Coastguard Worker #ifndef ERF_TYPE_PAD
142*8b26181fSAndroid Build Coastguard Worker #define ERF_TYPE_PAD                48
143*8b26181fSAndroid Build Coastguard Worker #endif
144*8b26181fSAndroid Build Coastguard Worker 
145*8b26181fSAndroid Build Coastguard Worker #define ATM_CELL_SIZE		52
146*8b26181fSAndroid Build Coastguard Worker #define ATM_HDR_SIZE		4
147*8b26181fSAndroid Build Coastguard Worker 
148*8b26181fSAndroid Build Coastguard Worker /*
149*8b26181fSAndroid Build Coastguard Worker  * A header containing additional MTP information.
150*8b26181fSAndroid Build Coastguard Worker  */
151*8b26181fSAndroid Build Coastguard Worker #define MTP2_SENT_OFFSET		0	/* 1 byte */
152*8b26181fSAndroid Build Coastguard Worker #define MTP2_ANNEX_A_USED_OFFSET	1	/* 1 byte */
153*8b26181fSAndroid Build Coastguard Worker #define MTP2_LINK_NUMBER_OFFSET		2	/* 2 bytes */
154*8b26181fSAndroid Build Coastguard Worker #define MTP2_HDR_LEN			4	/* length of the header */
155*8b26181fSAndroid Build Coastguard Worker 
156*8b26181fSAndroid Build Coastguard Worker #define MTP2_ANNEX_A_NOT_USED      0
157*8b26181fSAndroid Build Coastguard Worker #define MTP2_ANNEX_A_USED          1
158*8b26181fSAndroid Build Coastguard Worker #define MTP2_ANNEX_A_USED_UNKNOWN  2
159*8b26181fSAndroid Build Coastguard Worker 
160*8b26181fSAndroid Build Coastguard Worker /* SunATM pseudo header */
161*8b26181fSAndroid Build Coastguard Worker struct sunatm_hdr {
162*8b26181fSAndroid Build Coastguard Worker 	unsigned char	flags;		/* destination and traffic type */
163*8b26181fSAndroid Build Coastguard Worker 	unsigned char	vpi;		/* VPI */
164*8b26181fSAndroid Build Coastguard Worker 	unsigned short	vci;		/* VCI */
165*8b26181fSAndroid Build Coastguard Worker };
166*8b26181fSAndroid Build Coastguard Worker 
167*8b26181fSAndroid Build Coastguard Worker /*
168*8b26181fSAndroid Build Coastguard Worker  * Private data for capturing on DAG devices.
169*8b26181fSAndroid Build Coastguard Worker  */
170*8b26181fSAndroid Build Coastguard Worker struct pcap_dag {
171*8b26181fSAndroid Build Coastguard Worker 	struct pcap_stat stat;
172*8b26181fSAndroid Build Coastguard Worker 	u_char	*dag_mem_bottom;	/* DAG card current memory bottom pointer */
173*8b26181fSAndroid Build Coastguard Worker 	u_char	*dag_mem_top;	/* DAG card current memory top pointer */
174*8b26181fSAndroid Build Coastguard Worker 	int	dag_fcs_bits;	/* Number of checksum bits from link layer */
175*8b26181fSAndroid Build Coastguard Worker 	int	dag_flags;	/* Flags */
176*8b26181fSAndroid Build Coastguard Worker 	int	dag_stream;	/* DAG stream number */
177*8b26181fSAndroid Build Coastguard Worker 	int	dag_timeout;	/* timeout specified to pcap_open_live.
178*8b26181fSAndroid Build Coastguard Worker 				 * Same as in linux above, introduce
179*8b26181fSAndroid Build Coastguard Worker 				 * generally? */
180*8b26181fSAndroid Build Coastguard Worker 	dag_card_ref_t dag_ref; /* DAG Configuration/Status API card reference */
181*8b26181fSAndroid Build Coastguard Worker 	dag_component_t dag_root;	/* DAG CSAPI Root component */
182*8b26181fSAndroid Build Coastguard Worker 	attr_uuid_t drop_attr;  /* DAG Stream Drop Attribute handle, if available */
183*8b26181fSAndroid Build Coastguard Worker 	struct timeval required_select_timeout;
184*8b26181fSAndroid Build Coastguard Worker 				/* Timeout caller must use in event loops */
185*8b26181fSAndroid Build Coastguard Worker };
186*8b26181fSAndroid Build Coastguard Worker 
187*8b26181fSAndroid Build Coastguard Worker typedef struct pcap_dag_node {
188*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dag_node *next;
189*8b26181fSAndroid Build Coastguard Worker 	pcap_t *p;
190*8b26181fSAndroid Build Coastguard Worker 	pid_t pid;
191*8b26181fSAndroid Build Coastguard Worker } pcap_dag_node_t;
192*8b26181fSAndroid Build Coastguard Worker 
193*8b26181fSAndroid Build Coastguard Worker static pcap_dag_node_t *pcap_dags = NULL;
194*8b26181fSAndroid Build Coastguard Worker static int atexit_handler_installed = 0;
195*8b26181fSAndroid Build Coastguard Worker static const unsigned short endian_test_word = 0x0100;
196*8b26181fSAndroid Build Coastguard Worker 
197*8b26181fSAndroid Build Coastguard Worker #define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word))
198*8b26181fSAndroid Build Coastguard Worker 
199*8b26181fSAndroid Build Coastguard Worker #define MAX_DAG_PACKET 65536
200*8b26181fSAndroid Build Coastguard Worker 
201*8b26181fSAndroid Build Coastguard Worker static unsigned char TempPkt[MAX_DAG_PACKET];
202*8b26181fSAndroid Build Coastguard Worker 
203*8b26181fSAndroid Build Coastguard Worker #ifndef HAVE_DAG_LARGE_STREAMS_API
204*8b26181fSAndroid Build Coastguard Worker #define dag_attach_stream64(a, b, c, d) dag_attach_stream(a, b, c, d)
205*8b26181fSAndroid Build Coastguard Worker #define dag_get_stream_poll64(a, b, c, d, e) dag_get_stream_poll(a, b, c, d, e)
206*8b26181fSAndroid Build Coastguard Worker #define dag_set_stream_poll64(a, b, c, d, e) dag_set_stream_poll(a, b, c, d, e)
207*8b26181fSAndroid Build Coastguard Worker #define dag_size_t uint32_t
208*8b26181fSAndroid Build Coastguard Worker #endif
209*8b26181fSAndroid Build Coastguard Worker 
210*8b26181fSAndroid Build Coastguard Worker static int dag_stats(pcap_t *p, struct pcap_stat *ps);
211*8b26181fSAndroid Build Coastguard Worker static int dag_set_datalink(pcap_t *p, int dlt);
212*8b26181fSAndroid Build Coastguard Worker static int dag_get_datalink(pcap_t *p);
213*8b26181fSAndroid Build Coastguard Worker static int dag_setnonblock(pcap_t *p, int nonblock);
214*8b26181fSAndroid Build Coastguard Worker 
215*8b26181fSAndroid Build Coastguard Worker static void
delete_pcap_dag(const pcap_t * p)216*8b26181fSAndroid Build Coastguard Worker delete_pcap_dag(const pcap_t *p)
217*8b26181fSAndroid Build Coastguard Worker {
218*8b26181fSAndroid Build Coastguard Worker 	pcap_dag_node_t *curr = NULL, *prev = NULL;
219*8b26181fSAndroid Build Coastguard Worker 
220*8b26181fSAndroid Build Coastguard Worker 	for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) {
221*8b26181fSAndroid Build Coastguard Worker 		/* empty */
222*8b26181fSAndroid Build Coastguard Worker 	}
223*8b26181fSAndroid Build Coastguard Worker 
224*8b26181fSAndroid Build Coastguard Worker 	if (curr != NULL && curr->p == p) {
225*8b26181fSAndroid Build Coastguard Worker 		if (prev != NULL) {
226*8b26181fSAndroid Build Coastguard Worker 			prev->next = curr->next;
227*8b26181fSAndroid Build Coastguard Worker 		} else {
228*8b26181fSAndroid Build Coastguard Worker 			pcap_dags = curr->next;
229*8b26181fSAndroid Build Coastguard Worker 		}
230*8b26181fSAndroid Build Coastguard Worker 	}
231*8b26181fSAndroid Build Coastguard Worker }
232*8b26181fSAndroid Build Coastguard Worker 
233*8b26181fSAndroid Build Coastguard Worker /*
234*8b26181fSAndroid Build Coastguard Worker  * Performs a graceful shutdown of the DAG card, frees dynamic memory held
235*8b26181fSAndroid Build Coastguard Worker  * in the pcap_t structure, and closes the file descriptor for the DAG card.
236*8b26181fSAndroid Build Coastguard Worker  */
237*8b26181fSAndroid Build Coastguard Worker 
238*8b26181fSAndroid Build Coastguard Worker static void
dag_platform_cleanup(pcap_t * p)239*8b26181fSAndroid Build Coastguard Worker dag_platform_cleanup(pcap_t *p)
240*8b26181fSAndroid Build Coastguard Worker {
241*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dag *pd = p->priv;
242*8b26181fSAndroid Build Coastguard Worker 
243*8b26181fSAndroid Build Coastguard Worker 	if(dag_stop_stream(p->fd, pd->dag_stream) < 0)
244*8b26181fSAndroid Build Coastguard Worker 		fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
245*8b26181fSAndroid Build Coastguard Worker 
246*8b26181fSAndroid Build Coastguard Worker 	if(dag_detach_stream(p->fd, pd->dag_stream) < 0)
247*8b26181fSAndroid Build Coastguard Worker 		fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
248*8b26181fSAndroid Build Coastguard Worker 
249*8b26181fSAndroid Build Coastguard Worker 	if(pd->dag_ref != NULL) {
250*8b26181fSAndroid Build Coastguard Worker 		dag_config_dispose(pd->dag_ref);
251*8b26181fSAndroid Build Coastguard Worker 		/*
252*8b26181fSAndroid Build Coastguard Worker 		 * Note: we don't need to call close(p->fd) or
253*8b26181fSAndroid Build Coastguard Worker 		 * dag_close(p->fd), as dag_config_dispose(pd->dag_ref)
254*8b26181fSAndroid Build Coastguard Worker 		 * does this.
255*8b26181fSAndroid Build Coastguard Worker 		 *
256*8b26181fSAndroid Build Coastguard Worker 		 * Set p->fd to -1 to make sure that's not done.
257*8b26181fSAndroid Build Coastguard Worker 		 */
258*8b26181fSAndroid Build Coastguard Worker 		p->fd = -1;
259*8b26181fSAndroid Build Coastguard Worker 		pd->dag_ref = NULL;
260*8b26181fSAndroid Build Coastguard Worker 	}
261*8b26181fSAndroid Build Coastguard Worker 	delete_pcap_dag(p);
262*8b26181fSAndroid Build Coastguard Worker 	pcap_cleanup_live_common(p);
263*8b26181fSAndroid Build Coastguard Worker }
264*8b26181fSAndroid Build Coastguard Worker 
265*8b26181fSAndroid Build Coastguard Worker static void
atexit_handler(void)266*8b26181fSAndroid Build Coastguard Worker atexit_handler(void)
267*8b26181fSAndroid Build Coastguard Worker {
268*8b26181fSAndroid Build Coastguard Worker 	while (pcap_dags != NULL) {
269*8b26181fSAndroid Build Coastguard Worker 		if (pcap_dags->pid == getpid()) {
270*8b26181fSAndroid Build Coastguard Worker 			if (pcap_dags->p != NULL)
271*8b26181fSAndroid Build Coastguard Worker 				dag_platform_cleanup(pcap_dags->p);
272*8b26181fSAndroid Build Coastguard Worker 		} else {
273*8b26181fSAndroid Build Coastguard Worker 			delete_pcap_dag(pcap_dags->p);
274*8b26181fSAndroid Build Coastguard Worker 		}
275*8b26181fSAndroid Build Coastguard Worker 	}
276*8b26181fSAndroid Build Coastguard Worker }
277*8b26181fSAndroid Build Coastguard Worker 
278*8b26181fSAndroid Build Coastguard Worker static int
new_pcap_dag(pcap_t * p)279*8b26181fSAndroid Build Coastguard Worker new_pcap_dag(pcap_t *p)
280*8b26181fSAndroid Build Coastguard Worker {
281*8b26181fSAndroid Build Coastguard Worker 	pcap_dag_node_t *node = NULL;
282*8b26181fSAndroid Build Coastguard Worker 
283*8b26181fSAndroid Build Coastguard Worker 	if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) {
284*8b26181fSAndroid Build Coastguard Worker 		return -1;
285*8b26181fSAndroid Build Coastguard Worker 	}
286*8b26181fSAndroid Build Coastguard Worker 
287*8b26181fSAndroid Build Coastguard Worker 	if (!atexit_handler_installed) {
288*8b26181fSAndroid Build Coastguard Worker 		atexit(atexit_handler);
289*8b26181fSAndroid Build Coastguard Worker 		atexit_handler_installed = 1;
290*8b26181fSAndroid Build Coastguard Worker 	}
291*8b26181fSAndroid Build Coastguard Worker 
292*8b26181fSAndroid Build Coastguard Worker 	node->next = pcap_dags;
293*8b26181fSAndroid Build Coastguard Worker 	node->p = p;
294*8b26181fSAndroid Build Coastguard Worker 	node->pid = getpid();
295*8b26181fSAndroid Build Coastguard Worker 
296*8b26181fSAndroid Build Coastguard Worker 	pcap_dags = node;
297*8b26181fSAndroid Build Coastguard Worker 
298*8b26181fSAndroid Build Coastguard Worker 	return 0;
299*8b26181fSAndroid Build Coastguard Worker }
300*8b26181fSAndroid Build Coastguard Worker 
301*8b26181fSAndroid Build Coastguard Worker static unsigned int
dag_erf_ext_header_count(const uint8_t * erf,size_t len)302*8b26181fSAndroid Build Coastguard Worker dag_erf_ext_header_count(const uint8_t *erf, size_t len)
303*8b26181fSAndroid Build Coastguard Worker {
304*8b26181fSAndroid Build Coastguard Worker 	uint32_t hdr_num = 0;
305*8b26181fSAndroid Build Coastguard Worker 	uint8_t  hdr_type;
306*8b26181fSAndroid Build Coastguard Worker 
307*8b26181fSAndroid Build Coastguard Worker 	/* basic sanity checks */
308*8b26181fSAndroid Build Coastguard Worker 	if ( erf == NULL )
309*8b26181fSAndroid Build Coastguard Worker 		return 0;
310*8b26181fSAndroid Build Coastguard Worker 	if ( len < 16 )
311*8b26181fSAndroid Build Coastguard Worker 		return 0;
312*8b26181fSAndroid Build Coastguard Worker 
313*8b26181fSAndroid Build Coastguard Worker 	/* check if we have any extension headers */
314*8b26181fSAndroid Build Coastguard Worker 	if ( (erf[8] & 0x80) == 0x00 )
315*8b26181fSAndroid Build Coastguard Worker 		return 0;
316*8b26181fSAndroid Build Coastguard Worker 
317*8b26181fSAndroid Build Coastguard Worker 	/* loop over the extension headers */
318*8b26181fSAndroid Build Coastguard Worker 	do {
319*8b26181fSAndroid Build Coastguard Worker 
320*8b26181fSAndroid Build Coastguard Worker 		/* sanity check we have enough bytes */
321*8b26181fSAndroid Build Coastguard Worker 		if ( len < (24 + (hdr_num * 8)) )
322*8b26181fSAndroid Build Coastguard Worker 			return hdr_num;
323*8b26181fSAndroid Build Coastguard Worker 
324*8b26181fSAndroid Build Coastguard Worker 		/* get the header type */
325*8b26181fSAndroid Build Coastguard Worker 		hdr_type = erf[(16 + (hdr_num * 8))];
326*8b26181fSAndroid Build Coastguard Worker 		hdr_num++;
327*8b26181fSAndroid Build Coastguard Worker 
328*8b26181fSAndroid Build Coastguard Worker 	} while ( hdr_type & 0x80 );
329*8b26181fSAndroid Build Coastguard Worker 
330*8b26181fSAndroid Build Coastguard Worker 	return hdr_num;
331*8b26181fSAndroid Build Coastguard Worker }
332*8b26181fSAndroid Build Coastguard Worker 
333*8b26181fSAndroid Build Coastguard Worker /*
334*8b26181fSAndroid Build Coastguard Worker  *  Read at most max_packets from the capture stream and call the callback
335*8b26181fSAndroid Build Coastguard Worker  *  for each of them. Returns the number of packets handled, -1 if an
336*8b26181fSAndroid Build Coastguard Worker  *  error occurred, or -2 if we were told to break out of the loop.
337*8b26181fSAndroid Build Coastguard Worker  */
338*8b26181fSAndroid Build Coastguard Worker static int
dag_read(pcap_t * p,int cnt,pcap_handler callback,u_char * user)339*8b26181fSAndroid Build Coastguard Worker dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
340*8b26181fSAndroid Build Coastguard Worker {
341*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dag *pd = p->priv;
342*8b26181fSAndroid Build Coastguard Worker 	unsigned int processed = 0;
343*8b26181fSAndroid Build Coastguard Worker 	unsigned int nonblocking = pd->dag_flags & DAGF_NONBLOCK;
344*8b26181fSAndroid Build Coastguard Worker 	unsigned int num_ext_hdr = 0;
345*8b26181fSAndroid Build Coastguard Worker 	unsigned int ticks_per_second;
346*8b26181fSAndroid Build Coastguard Worker 
347*8b26181fSAndroid Build Coastguard Worker 	/* Get the next bufferful of packets (if necessary). */
348*8b26181fSAndroid Build Coastguard Worker 	while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) {
349*8b26181fSAndroid Build Coastguard Worker 
350*8b26181fSAndroid Build Coastguard Worker 		/*
351*8b26181fSAndroid Build Coastguard Worker 		 * Has "pcap_breakloop()" been called?
352*8b26181fSAndroid Build Coastguard Worker 		 */
353*8b26181fSAndroid Build Coastguard Worker 		if (p->break_loop) {
354*8b26181fSAndroid Build Coastguard Worker 			/*
355*8b26181fSAndroid Build Coastguard Worker 			 * Yes - clear the flag that indicates that
356*8b26181fSAndroid Build Coastguard Worker 			 * it has, and return -2 to indicate that
357*8b26181fSAndroid Build Coastguard Worker 			 * we were told to break out of the loop.
358*8b26181fSAndroid Build Coastguard Worker 			 */
359*8b26181fSAndroid Build Coastguard Worker 			p->break_loop = 0;
360*8b26181fSAndroid Build Coastguard Worker 			return -2;
361*8b26181fSAndroid Build Coastguard Worker 		}
362*8b26181fSAndroid Build Coastguard Worker 
363*8b26181fSAndroid Build Coastguard Worker 		/* dag_advance_stream() will block (unless nonblock is called)
364*8b26181fSAndroid Build Coastguard Worker 		 * until 64kB of data has accumulated.
365*8b26181fSAndroid Build Coastguard Worker 		 * If to_ms is set, it will timeout before 64kB has accumulated.
366*8b26181fSAndroid Build Coastguard Worker 		 * We wait for 64kB because processing a few packets at a time
367*8b26181fSAndroid Build Coastguard Worker 		 * can cause problems at high packet rates (>200kpps) due
368*8b26181fSAndroid Build Coastguard Worker 		 * to inefficiencies.
369*8b26181fSAndroid Build Coastguard Worker 		 * This does mean if to_ms is not specified the capture may 'hang'
370*8b26181fSAndroid Build Coastguard Worker 		 * for long periods if the data rate is extremely slow (<64kB/sec)
371*8b26181fSAndroid Build Coastguard Worker 		 * If non-block is specified it will return immediately. The user
372*8b26181fSAndroid Build Coastguard Worker 		 * is then responsible for efficiency.
373*8b26181fSAndroid Build Coastguard Worker 		 */
374*8b26181fSAndroid Build Coastguard Worker 		if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) {
375*8b26181fSAndroid Build Coastguard Worker 		     return -1;
376*8b26181fSAndroid Build Coastguard Worker 		}
377*8b26181fSAndroid Build Coastguard Worker 
378*8b26181fSAndroid Build Coastguard Worker 		if (nonblocking && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
379*8b26181fSAndroid Build Coastguard Worker 		{
380*8b26181fSAndroid Build Coastguard Worker 			/* Pcap is configured to process only available packets, and there aren't any, return immediately. */
381*8b26181fSAndroid Build Coastguard Worker 			return 0;
382*8b26181fSAndroid Build Coastguard Worker 		}
383*8b26181fSAndroid Build Coastguard Worker 
384*8b26181fSAndroid Build Coastguard Worker 		if(!nonblocking &&
385*8b26181fSAndroid Build Coastguard Worker 		   pd->dag_timeout &&
386*8b26181fSAndroid Build Coastguard Worker 		   (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
387*8b26181fSAndroid Build Coastguard Worker 		{
388*8b26181fSAndroid Build Coastguard Worker 			/* Blocking mode, but timeout set and no data has arrived, return anyway.*/
389*8b26181fSAndroid Build Coastguard Worker 			return 0;
390*8b26181fSAndroid Build Coastguard Worker 		}
391*8b26181fSAndroid Build Coastguard Worker 
392*8b26181fSAndroid Build Coastguard Worker 	}
393*8b26181fSAndroid Build Coastguard Worker 
394*8b26181fSAndroid Build Coastguard Worker 	/*
395*8b26181fSAndroid Build Coastguard Worker 	 * Process the packets.
396*8b26181fSAndroid Build Coastguard Worker 	 *
397*8b26181fSAndroid Build Coastguard Worker 	 * This assumes that a single buffer of packets will have
398*8b26181fSAndroid Build Coastguard Worker 	 * <= INT_MAX packets, so the packet count doesn't overflow.
399*8b26181fSAndroid Build Coastguard Worker 	 */
400*8b26181fSAndroid Build Coastguard Worker 	while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) {
401*8b26181fSAndroid Build Coastguard Worker 
402*8b26181fSAndroid Build Coastguard Worker 		unsigned short packet_len = 0;
403*8b26181fSAndroid Build Coastguard Worker 		int caplen = 0;
404*8b26181fSAndroid Build Coastguard Worker 		struct pcap_pkthdr	pcap_header;
405*8b26181fSAndroid Build Coastguard Worker 
406*8b26181fSAndroid Build Coastguard Worker 		dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom);
407*8b26181fSAndroid Build Coastguard Worker 
408*8b26181fSAndroid Build Coastguard Worker 		u_char *dp = ((u_char *)header); /* + dag_record_size; */
409*8b26181fSAndroid Build Coastguard Worker 		unsigned short rlen;
410*8b26181fSAndroid Build Coastguard Worker 
411*8b26181fSAndroid Build Coastguard Worker 		/*
412*8b26181fSAndroid Build Coastguard Worker 		 * Has "pcap_breakloop()" been called?
413*8b26181fSAndroid Build Coastguard Worker 		 */
414*8b26181fSAndroid Build Coastguard Worker 		if (p->break_loop) {
415*8b26181fSAndroid Build Coastguard Worker 			/*
416*8b26181fSAndroid Build Coastguard Worker 			 * Yes - clear the flag that indicates that
417*8b26181fSAndroid Build Coastguard Worker 			 * it has, and return -2 to indicate that
418*8b26181fSAndroid Build Coastguard Worker 			 * we were told to break out of the loop.
419*8b26181fSAndroid Build Coastguard Worker 			 */
420*8b26181fSAndroid Build Coastguard Worker 			p->break_loop = 0;
421*8b26181fSAndroid Build Coastguard Worker 			return -2;
422*8b26181fSAndroid Build Coastguard Worker 		}
423*8b26181fSAndroid Build Coastguard Worker 
424*8b26181fSAndroid Build Coastguard Worker 		rlen = ntohs(header->rlen);
425*8b26181fSAndroid Build Coastguard Worker 		if (rlen < dag_record_size)
426*8b26181fSAndroid Build Coastguard Worker 		{
427*8b26181fSAndroid Build Coastguard Worker 			pcap_strlcpy(p->errbuf, "dag_read: record too small",
428*8b26181fSAndroid Build Coastguard Worker 			    PCAP_ERRBUF_SIZE);
429*8b26181fSAndroid Build Coastguard Worker 			return -1;
430*8b26181fSAndroid Build Coastguard Worker 		}
431*8b26181fSAndroid Build Coastguard Worker 		pd->dag_mem_bottom += rlen;
432*8b26181fSAndroid Build Coastguard Worker 
433*8b26181fSAndroid Build Coastguard Worker 		/* Count lost packets. */
434*8b26181fSAndroid Build Coastguard Worker 		switch((header->type & 0x7f)) {
435*8b26181fSAndroid Build Coastguard Worker 			/* in these types the color value overwrites the lctr */
436*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_HDLC_POS:
437*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_ETH:
438*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_DSM_COLOR_HDLC_POS:
439*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_DSM_COLOR_ETH:
440*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_MC_HDLC_POS:
441*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_HASH_ETH:
442*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_HASH_POS:
443*8b26181fSAndroid Build Coastguard Worker 			break;
444*8b26181fSAndroid Build Coastguard Worker 
445*8b26181fSAndroid Build Coastguard Worker 		default:
446*8b26181fSAndroid Build Coastguard Worker 			if ( (pd->drop_attr == kNullAttributeUuid) && (header->lctr) ) {
447*8b26181fSAndroid Build Coastguard Worker 				pd->stat.ps_drop += ntohs(header->lctr);
448*8b26181fSAndroid Build Coastguard Worker 			}
449*8b26181fSAndroid Build Coastguard Worker 		}
450*8b26181fSAndroid Build Coastguard Worker 
451*8b26181fSAndroid Build Coastguard Worker 		if ((header->type & 0x7f) == ERF_TYPE_PAD) {
452*8b26181fSAndroid Build Coastguard Worker 			continue;
453*8b26181fSAndroid Build Coastguard Worker 		}
454*8b26181fSAndroid Build Coastguard Worker 
455*8b26181fSAndroid Build Coastguard Worker 		num_ext_hdr = dag_erf_ext_header_count(dp, rlen);
456*8b26181fSAndroid Build Coastguard Worker 
457*8b26181fSAndroid Build Coastguard Worker 		/* ERF encapsulation */
458*8b26181fSAndroid Build Coastguard Worker 		/* The Extensible Record Format is not dropped for this kind of encapsulation,
459*8b26181fSAndroid Build Coastguard Worker 		 * and will be handled as a pseudo header by the decoding application.
460*8b26181fSAndroid Build Coastguard Worker 		 * The information carried in the ERF header and in the optional subheader (if present)
461*8b26181fSAndroid Build Coastguard Worker 		 * could be merged with the libpcap information, to offer a better decoding.
462*8b26181fSAndroid Build Coastguard Worker 		 * The packet length is
463*8b26181fSAndroid Build Coastguard Worker 		 * o the length of the packet on the link (header->wlen),
464*8b26181fSAndroid Build Coastguard Worker 		 * o plus the length of the ERF header (dag_record_size), as the length of the
465*8b26181fSAndroid Build Coastguard Worker 		 *   pseudo header will be adjusted during the decoding,
466*8b26181fSAndroid Build Coastguard Worker 		 * o plus the length of the optional subheader (if present).
467*8b26181fSAndroid Build Coastguard Worker 		 *
468*8b26181fSAndroid Build Coastguard Worker 		 * The capture length is header.rlen and the byte stuffing for alignment will be dropped
469*8b26181fSAndroid Build Coastguard Worker 		 * if the capture length is greater than the packet length.
470*8b26181fSAndroid Build Coastguard Worker 		 */
471*8b26181fSAndroid Build Coastguard Worker 		if (p->linktype == DLT_ERF) {
472*8b26181fSAndroid Build Coastguard Worker 			packet_len = ntohs(header->wlen) + dag_record_size;
473*8b26181fSAndroid Build Coastguard Worker 			caplen = rlen;
474*8b26181fSAndroid Build Coastguard Worker 			switch ((header->type & 0x7f)) {
475*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_AAL5:
476*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_ATM:
477*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_HDLC:
478*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_RAW_CHANNEL:
479*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_RAW:
480*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_AAL2:
481*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_COLOR_MC_HDLC_POS:
482*8b26181fSAndroid Build Coastguard Worker 				packet_len += 4; /* MC header */
483*8b26181fSAndroid Build Coastguard Worker 				break;
484*8b26181fSAndroid Build Coastguard Worker 
485*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_COLOR_HASH_ETH:
486*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_DSM_COLOR_ETH:
487*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_COLOR_ETH:
488*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_ETH:
489*8b26181fSAndroid Build Coastguard Worker 				packet_len += 2; /* ETH header */
490*8b26181fSAndroid Build Coastguard Worker 				break;
491*8b26181fSAndroid Build Coastguard Worker 			} /* switch type */
492*8b26181fSAndroid Build Coastguard Worker 
493*8b26181fSAndroid Build Coastguard Worker 			/* Include ERF extension headers */
494*8b26181fSAndroid Build Coastguard Worker 			packet_len += (8 * num_ext_hdr);
495*8b26181fSAndroid Build Coastguard Worker 
496*8b26181fSAndroid Build Coastguard Worker 			if (caplen > packet_len) {
497*8b26181fSAndroid Build Coastguard Worker 				caplen = packet_len;
498*8b26181fSAndroid Build Coastguard Worker 			}
499*8b26181fSAndroid Build Coastguard Worker 		} else {
500*8b26181fSAndroid Build Coastguard Worker 			/* Other kind of encapsulation according to the header Type */
501*8b26181fSAndroid Build Coastguard Worker 
502*8b26181fSAndroid Build Coastguard Worker 			/* Skip over generic ERF header */
503*8b26181fSAndroid Build Coastguard Worker 			dp += dag_record_size;
504*8b26181fSAndroid Build Coastguard Worker 			/* Skip over extension headers */
505*8b26181fSAndroid Build Coastguard Worker 			dp += 8 * num_ext_hdr;
506*8b26181fSAndroid Build Coastguard Worker 
507*8b26181fSAndroid Build Coastguard Worker 			switch((header->type & 0x7f)) {
508*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_ATM:
509*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_AAL5:
510*8b26181fSAndroid Build Coastguard Worker 				if ((header->type & 0x7f) == ERF_TYPE_AAL5) {
511*8b26181fSAndroid Build Coastguard Worker 					packet_len = ntohs(header->wlen);
512*8b26181fSAndroid Build Coastguard Worker 					caplen = rlen - dag_record_size;
513*8b26181fSAndroid Build Coastguard Worker 				}
514*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_ATM:
515*8b26181fSAndroid Build Coastguard Worker 				if ((header->type & 0x7f) == ERF_TYPE_MC_ATM) {
516*8b26181fSAndroid Build Coastguard Worker 					caplen = packet_len = ATM_CELL_SIZE;
517*8b26181fSAndroid Build Coastguard Worker 					dp+=4;
518*8b26181fSAndroid Build Coastguard Worker 				}
519*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_AAL5:
520*8b26181fSAndroid Build Coastguard Worker 				if ((header->type & 0x7f) == ERF_TYPE_MC_AAL5) {
521*8b26181fSAndroid Build Coastguard Worker 					packet_len = ntohs(header->wlen);
522*8b26181fSAndroid Build Coastguard Worker 					caplen = rlen - dag_record_size - 4;
523*8b26181fSAndroid Build Coastguard Worker 					dp+=4;
524*8b26181fSAndroid Build Coastguard Worker 				}
525*8b26181fSAndroid Build Coastguard Worker 				/* Skip over extension headers */
526*8b26181fSAndroid Build Coastguard Worker 				caplen -= (8 * num_ext_hdr);
527*8b26181fSAndroid Build Coastguard Worker 
528*8b26181fSAndroid Build Coastguard Worker 				if ((header->type & 0x7f) == ERF_TYPE_ATM) {
529*8b26181fSAndroid Build Coastguard Worker 					caplen = packet_len = ATM_CELL_SIZE;
530*8b26181fSAndroid Build Coastguard Worker 				}
531*8b26181fSAndroid Build Coastguard Worker 				if (p->linktype == DLT_SUNATM) {
532*8b26181fSAndroid Build Coastguard Worker 					struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
533*8b26181fSAndroid Build Coastguard Worker 					unsigned long rawatm;
534*8b26181fSAndroid Build Coastguard Worker 
535*8b26181fSAndroid Build Coastguard Worker 					rawatm = ntohl(*((unsigned long *)dp));
536*8b26181fSAndroid Build Coastguard Worker 					sunatm->vci = htons((rawatm >>  4) & 0xffff);
537*8b26181fSAndroid Build Coastguard Worker 					sunatm->vpi = (rawatm >> 20) & 0x00ff;
538*8b26181fSAndroid Build Coastguard Worker 					sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
539*8b26181fSAndroid Build Coastguard Worker 						((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
540*8b26181fSAndroid Build Coastguard Worker 						 ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
541*8b26181fSAndroid Build Coastguard Worker 						  ((dp[ATM_HDR_SIZE] == 0xaa &&
542*8b26181fSAndroid Build Coastguard Worker 						    dp[ATM_HDR_SIZE+1] == 0xaa &&
543*8b26181fSAndroid Build Coastguard Worker 						    dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
544*8b26181fSAndroid Build Coastguard Worker 
545*8b26181fSAndroid Build Coastguard Worker 				} else if (p->linktype == DLT_ATM_RFC1483) {
546*8b26181fSAndroid Build Coastguard Worker 					packet_len -= ATM_HDR_SIZE;
547*8b26181fSAndroid Build Coastguard Worker 					caplen -= ATM_HDR_SIZE;
548*8b26181fSAndroid Build Coastguard Worker 					dp += ATM_HDR_SIZE;
549*8b26181fSAndroid Build Coastguard Worker 				} else
550*8b26181fSAndroid Build Coastguard Worker 					continue;
551*8b26181fSAndroid Build Coastguard Worker 				break;
552*8b26181fSAndroid Build Coastguard Worker 
553*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_COLOR_HASH_ETH:
554*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_DSM_COLOR_ETH:
555*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_COLOR_ETH:
556*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_ETH:
557*8b26181fSAndroid Build Coastguard Worker 				if ((p->linktype != DLT_EN10MB) &&
558*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_DOCSIS))
559*8b26181fSAndroid Build Coastguard Worker 					continue;
560*8b26181fSAndroid Build Coastguard Worker 				packet_len = ntohs(header->wlen);
561*8b26181fSAndroid Build Coastguard Worker 				packet_len -= (pd->dag_fcs_bits >> 3);
562*8b26181fSAndroid Build Coastguard Worker 				caplen = rlen - dag_record_size - 2;
563*8b26181fSAndroid Build Coastguard Worker 				/* Skip over extension headers */
564*8b26181fSAndroid Build Coastguard Worker 				caplen -= (8 * num_ext_hdr);
565*8b26181fSAndroid Build Coastguard Worker 				if (caplen > packet_len) {
566*8b26181fSAndroid Build Coastguard Worker 					caplen = packet_len;
567*8b26181fSAndroid Build Coastguard Worker 				}
568*8b26181fSAndroid Build Coastguard Worker 				dp += 2;
569*8b26181fSAndroid Build Coastguard Worker 				break;
570*8b26181fSAndroid Build Coastguard Worker 
571*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_COLOR_HASH_POS:
572*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_DSM_COLOR_HDLC_POS:
573*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_COLOR_HDLC_POS:
574*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_HDLC_POS:
575*8b26181fSAndroid Build Coastguard Worker 				if ((p->linktype != DLT_CHDLC) &&
576*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_PPP_SERIAL) &&
577*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_FRELAY))
578*8b26181fSAndroid Build Coastguard Worker 					continue;
579*8b26181fSAndroid Build Coastguard Worker 				packet_len = ntohs(header->wlen);
580*8b26181fSAndroid Build Coastguard Worker 				packet_len -= (pd->dag_fcs_bits >> 3);
581*8b26181fSAndroid Build Coastguard Worker 				caplen = rlen - dag_record_size;
582*8b26181fSAndroid Build Coastguard Worker 				/* Skip over extension headers */
583*8b26181fSAndroid Build Coastguard Worker 				caplen -= (8 * num_ext_hdr);
584*8b26181fSAndroid Build Coastguard Worker 				if (caplen > packet_len) {
585*8b26181fSAndroid Build Coastguard Worker 					caplen = packet_len;
586*8b26181fSAndroid Build Coastguard Worker 				}
587*8b26181fSAndroid Build Coastguard Worker 				break;
588*8b26181fSAndroid Build Coastguard Worker 
589*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_COLOR_MC_HDLC_POS:
590*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_HDLC:
591*8b26181fSAndroid Build Coastguard Worker 				if ((p->linktype != DLT_CHDLC) &&
592*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_PPP_SERIAL) &&
593*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_FRELAY) &&
594*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_MTP2) &&
595*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_MTP2_WITH_PHDR) &&
596*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_LAPD))
597*8b26181fSAndroid Build Coastguard Worker 					continue;
598*8b26181fSAndroid Build Coastguard Worker 				packet_len = ntohs(header->wlen);
599*8b26181fSAndroid Build Coastguard Worker 				packet_len -= (pd->dag_fcs_bits >> 3);
600*8b26181fSAndroid Build Coastguard Worker 				caplen = rlen - dag_record_size - 4;
601*8b26181fSAndroid Build Coastguard Worker 				/* Skip over extension headers */
602*8b26181fSAndroid Build Coastguard Worker 				caplen -= (8 * num_ext_hdr);
603*8b26181fSAndroid Build Coastguard Worker 				if (caplen > packet_len) {
604*8b26181fSAndroid Build Coastguard Worker 					caplen = packet_len;
605*8b26181fSAndroid Build Coastguard Worker 				}
606*8b26181fSAndroid Build Coastguard Worker 				/* jump the MC_HDLC_HEADER */
607*8b26181fSAndroid Build Coastguard Worker 				dp += 4;
608*8b26181fSAndroid Build Coastguard Worker #ifdef DLT_MTP2_WITH_PHDR
609*8b26181fSAndroid Build Coastguard Worker 				if (p->linktype == DLT_MTP2_WITH_PHDR) {
610*8b26181fSAndroid Build Coastguard Worker 					/* Add the MTP2 Pseudo Header */
611*8b26181fSAndroid Build Coastguard Worker 					caplen += MTP2_HDR_LEN;
612*8b26181fSAndroid Build Coastguard Worker 					packet_len += MTP2_HDR_LEN;
613*8b26181fSAndroid Build Coastguard Worker 
614*8b26181fSAndroid Build Coastguard Worker 					TempPkt[MTP2_SENT_OFFSET] = 0;
615*8b26181fSAndroid Build Coastguard Worker 					TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
616*8b26181fSAndroid Build Coastguard Worker 					*(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
617*8b26181fSAndroid Build Coastguard Worker 					*(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
618*8b26181fSAndroid Build Coastguard Worker 					memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
619*8b26181fSAndroid Build Coastguard Worker 					dp = TempPkt;
620*8b26181fSAndroid Build Coastguard Worker 				}
621*8b26181fSAndroid Build Coastguard Worker #endif
622*8b26181fSAndroid Build Coastguard Worker 				break;
623*8b26181fSAndroid Build Coastguard Worker 
624*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_IPV4:
625*8b26181fSAndroid Build Coastguard Worker 				if ((p->linktype != DLT_RAW) &&
626*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_IPV4))
627*8b26181fSAndroid Build Coastguard Worker 					continue;
628*8b26181fSAndroid Build Coastguard Worker 				packet_len = ntohs(header->wlen);
629*8b26181fSAndroid Build Coastguard Worker 				caplen = rlen - dag_record_size;
630*8b26181fSAndroid Build Coastguard Worker 				/* Skip over extension headers */
631*8b26181fSAndroid Build Coastguard Worker 				caplen -= (8 * num_ext_hdr);
632*8b26181fSAndroid Build Coastguard Worker 				if (caplen > packet_len) {
633*8b26181fSAndroid Build Coastguard Worker 					caplen = packet_len;
634*8b26181fSAndroid Build Coastguard Worker 				}
635*8b26181fSAndroid Build Coastguard Worker 				break;
636*8b26181fSAndroid Build Coastguard Worker 
637*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_IPV6:
638*8b26181fSAndroid Build Coastguard Worker 				if ((p->linktype != DLT_RAW) &&
639*8b26181fSAndroid Build Coastguard Worker 				    (p->linktype != DLT_IPV6))
640*8b26181fSAndroid Build Coastguard Worker 					continue;
641*8b26181fSAndroid Build Coastguard Worker 				packet_len = ntohs(header->wlen);
642*8b26181fSAndroid Build Coastguard Worker 				caplen = rlen - dag_record_size;
643*8b26181fSAndroid Build Coastguard Worker 				/* Skip over extension headers */
644*8b26181fSAndroid Build Coastguard Worker 				caplen -= (8 * num_ext_hdr);
645*8b26181fSAndroid Build Coastguard Worker 				if (caplen > packet_len) {
646*8b26181fSAndroid Build Coastguard Worker 					caplen = packet_len;
647*8b26181fSAndroid Build Coastguard Worker 				}
648*8b26181fSAndroid Build Coastguard Worker 				break;
649*8b26181fSAndroid Build Coastguard Worker 
650*8b26181fSAndroid Build Coastguard Worker 			/* These types have no matching 'native' DLT, but can be used with DLT_ERF above */
651*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_RAW:
652*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_MC_RAW_CHANNEL:
653*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_IP_COUNTER:
654*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_TCP_FLOW_COUNTER:
655*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_INFINIBAND:
656*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_RAW_LINK:
657*8b26181fSAndroid Build Coastguard Worker 			case ERF_TYPE_INFINIBAND_LINK:
658*8b26181fSAndroid Build Coastguard Worker 			default:
659*8b26181fSAndroid Build Coastguard Worker 				/* Unhandled ERF type.
660*8b26181fSAndroid Build Coastguard Worker 				 * Ignore rather than generating error
661*8b26181fSAndroid Build Coastguard Worker 				 */
662*8b26181fSAndroid Build Coastguard Worker 				continue;
663*8b26181fSAndroid Build Coastguard Worker 			} /* switch type */
664*8b26181fSAndroid Build Coastguard Worker 
665*8b26181fSAndroid Build Coastguard Worker 		} /* ERF encapsulation */
666*8b26181fSAndroid Build Coastguard Worker 
667*8b26181fSAndroid Build Coastguard Worker 		if (caplen > p->snapshot)
668*8b26181fSAndroid Build Coastguard Worker 			caplen = p->snapshot;
669*8b26181fSAndroid Build Coastguard Worker 
670*8b26181fSAndroid Build Coastguard Worker 		/* Run the packet filter if there is one. */
671*8b26181fSAndroid Build Coastguard Worker 		if ((p->fcode.bf_insns == NULL) || pcap_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
672*8b26181fSAndroid Build Coastguard Worker 
673*8b26181fSAndroid Build Coastguard Worker 			/* convert between timestamp formats */
674*8b26181fSAndroid Build Coastguard Worker 			register unsigned long long ts;
675*8b26181fSAndroid Build Coastguard Worker 
676*8b26181fSAndroid Build Coastguard Worker 			if (IS_BIGENDIAN()) {
677*8b26181fSAndroid Build Coastguard Worker 				ts = SWAPLL(header->ts);
678*8b26181fSAndroid Build Coastguard Worker 			} else {
679*8b26181fSAndroid Build Coastguard Worker 				ts = header->ts;
680*8b26181fSAndroid Build Coastguard Worker 			}
681*8b26181fSAndroid Build Coastguard Worker 
682*8b26181fSAndroid Build Coastguard Worker 			switch (p->opt.tstamp_precision) {
683*8b26181fSAndroid Build Coastguard Worker 			case PCAP_TSTAMP_PRECISION_NANO:
684*8b26181fSAndroid Build Coastguard Worker 				ticks_per_second = 1000000000;
685*8b26181fSAndroid Build Coastguard Worker 				break;
686*8b26181fSAndroid Build Coastguard Worker 			case PCAP_TSTAMP_PRECISION_MICRO:
687*8b26181fSAndroid Build Coastguard Worker 			default:
688*8b26181fSAndroid Build Coastguard Worker 				ticks_per_second = 1000000;
689*8b26181fSAndroid Build Coastguard Worker 				break;
690*8b26181fSAndroid Build Coastguard Worker 
691*8b26181fSAndroid Build Coastguard Worker 			}
692*8b26181fSAndroid Build Coastguard Worker 			pcap_header.ts.tv_sec = ts >> 32;
693*8b26181fSAndroid Build Coastguard Worker 			ts = (ts & 0xffffffffULL) * ticks_per_second;
694*8b26181fSAndroid Build Coastguard Worker 			ts += 0x80000000; /* rounding */
695*8b26181fSAndroid Build Coastguard Worker 			pcap_header.ts.tv_usec = ts >> 32;
696*8b26181fSAndroid Build Coastguard Worker 			if (pcap_header.ts.tv_usec >= ticks_per_second) {
697*8b26181fSAndroid Build Coastguard Worker 				pcap_header.ts.tv_usec -= ticks_per_second;
698*8b26181fSAndroid Build Coastguard Worker 				pcap_header.ts.tv_sec++;
699*8b26181fSAndroid Build Coastguard Worker 			}
700*8b26181fSAndroid Build Coastguard Worker 
701*8b26181fSAndroid Build Coastguard Worker 			/* Fill in our own header data */
702*8b26181fSAndroid Build Coastguard Worker 			pcap_header.caplen = caplen;
703*8b26181fSAndroid Build Coastguard Worker 			pcap_header.len = packet_len;
704*8b26181fSAndroid Build Coastguard Worker 
705*8b26181fSAndroid Build Coastguard Worker 			/* Count the packet. */
706*8b26181fSAndroid Build Coastguard Worker 			pd->stat.ps_recv++;
707*8b26181fSAndroid Build Coastguard Worker 
708*8b26181fSAndroid Build Coastguard Worker 			/* Call the user supplied callback function */
709*8b26181fSAndroid Build Coastguard Worker 			callback(user, &pcap_header, dp);
710*8b26181fSAndroid Build Coastguard Worker 
711*8b26181fSAndroid Build Coastguard Worker 			/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
712*8b26181fSAndroid Build Coastguard Worker 			processed++;
713*8b26181fSAndroid Build Coastguard Worker 			if (processed == cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
714*8b26181fSAndroid Build Coastguard Worker 			{
715*8b26181fSAndroid Build Coastguard Worker 				/* Reached the user-specified limit. */
716*8b26181fSAndroid Build Coastguard Worker 				return cnt;
717*8b26181fSAndroid Build Coastguard Worker 			}
718*8b26181fSAndroid Build Coastguard Worker 		}
719*8b26181fSAndroid Build Coastguard Worker 	}
720*8b26181fSAndroid Build Coastguard Worker 
721*8b26181fSAndroid Build Coastguard Worker 	return processed;
722*8b26181fSAndroid Build Coastguard Worker }
723*8b26181fSAndroid Build Coastguard Worker 
724*8b26181fSAndroid Build Coastguard Worker static int
dag_inject(pcap_t * p,const void * buf _U_,int size _U_)725*8b26181fSAndroid Build Coastguard Worker dag_inject(pcap_t *p, const void *buf _U_, int size _U_)
726*8b26181fSAndroid Build Coastguard Worker {
727*8b26181fSAndroid Build Coastguard Worker 	pcap_strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
728*8b26181fSAndroid Build Coastguard Worker 	    PCAP_ERRBUF_SIZE);
729*8b26181fSAndroid Build Coastguard Worker 	return (-1);
730*8b26181fSAndroid Build Coastguard Worker }
731*8b26181fSAndroid Build Coastguard Worker 
732*8b26181fSAndroid Build Coastguard Worker /*
733*8b26181fSAndroid Build Coastguard Worker  *  Get a handle for a live capture from the given DAG device.  Passing a NULL
734*8b26181fSAndroid Build Coastguard Worker  *  device will result in a failure.  The promisc flag is ignored because DAG
735*8b26181fSAndroid Build Coastguard Worker  *  cards are always promiscuous.  The to_ms parameter is used in setting the
736*8b26181fSAndroid Build Coastguard Worker  *  API polling parameters.
737*8b26181fSAndroid Build Coastguard Worker  *
738*8b26181fSAndroid Build Coastguard Worker  *  snaplen is now also ignored, until we get per-stream slen support. Set
739*8b26181fSAndroid Build Coastguard Worker  *  slen with appropriate DAG tool BEFORE pcap_activate().
740*8b26181fSAndroid Build Coastguard Worker  *
741*8b26181fSAndroid Build Coastguard Worker  *  See also pcap(3).
742*8b26181fSAndroid Build Coastguard Worker  */
dag_activate(pcap_t * p)743*8b26181fSAndroid Build Coastguard Worker static int dag_activate(pcap_t* p)
744*8b26181fSAndroid Build Coastguard Worker {
745*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dag *pd = p->priv;
746*8b26181fSAndroid Build Coastguard Worker 	char *s;
747*8b26181fSAndroid Build Coastguard Worker 	int n;
748*8b26181fSAndroid Build Coastguard Worker 	daginf_t* daginf;
749*8b26181fSAndroid Build Coastguard Worker 	char * newDev = NULL;
750*8b26181fSAndroid Build Coastguard Worker 	char * device = p->opt.device;
751*8b26181fSAndroid Build Coastguard Worker 	int ret;
752*8b26181fSAndroid Build Coastguard Worker 	dag_size_t mindata;
753*8b26181fSAndroid Build Coastguard Worker 	struct timeval maxwait;
754*8b26181fSAndroid Build Coastguard Worker 	struct timeval poll;
755*8b26181fSAndroid Build Coastguard Worker 
756*8b26181fSAndroid Build Coastguard Worker 	if (device == NULL) {
757*8b26181fSAndroid Build Coastguard Worker 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
758*8b26181fSAndroid Build Coastguard Worker 		return PCAP_ERROR;
759*8b26181fSAndroid Build Coastguard Worker 	}
760*8b26181fSAndroid Build Coastguard Worker 
761*8b26181fSAndroid Build Coastguard Worker 	/* Initialize some components of the pcap structure. */
762*8b26181fSAndroid Build Coastguard Worker 	newDev = (char *)malloc(strlen(device) + 16);
763*8b26181fSAndroid Build Coastguard Worker 	if (newDev == NULL) {
764*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
765*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
766*8b26181fSAndroid Build Coastguard Worker 		    errno, "Can't allocate string for device name");
767*8b26181fSAndroid Build Coastguard Worker 		goto fail;
768*8b26181fSAndroid Build Coastguard Worker 	}
769*8b26181fSAndroid Build Coastguard Worker 
770*8b26181fSAndroid Build Coastguard Worker 	/* Parse input name to get dag device and stream number if provided */
771*8b26181fSAndroid Build Coastguard Worker 	if (dag_parse_name(device, newDev, strlen(device) + 16, &pd->dag_stream) < 0) {
772*8b26181fSAndroid Build Coastguard Worker 		/*
773*8b26181fSAndroid Build Coastguard Worker 		 * XXX - it'd be nice if this indicated what was wrong
774*8b26181fSAndroid Build Coastguard Worker 		 * with the name.  Does this reliably set errno?
775*8b26181fSAndroid Build Coastguard Worker 		 * Should this return PCAP_ERROR_NO_SUCH_DEVICE in some
776*8b26181fSAndroid Build Coastguard Worker 		 * cases?
777*8b26181fSAndroid Build Coastguard Worker 		 */
778*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
779*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
780*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_parse_name");
781*8b26181fSAndroid Build Coastguard Worker 		goto fail;
782*8b26181fSAndroid Build Coastguard Worker 	}
783*8b26181fSAndroid Build Coastguard Worker 	device = newDev;
784*8b26181fSAndroid Build Coastguard Worker 
785*8b26181fSAndroid Build Coastguard Worker 	if (pd->dag_stream%2) {
786*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
787*8b26181fSAndroid Build Coastguard Worker 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture");
788*8b26181fSAndroid Build Coastguard Worker 		goto fail;
789*8b26181fSAndroid Build Coastguard Worker 	}
790*8b26181fSAndroid Build Coastguard Worker 
791*8b26181fSAndroid Build Coastguard Worker 	/* setup device parameters */
792*8b26181fSAndroid Build Coastguard Worker 	if((pd->dag_ref = dag_config_init((char *)device)) == NULL) {
793*8b26181fSAndroid Build Coastguard Worker 		/*
794*8b26181fSAndroid Build Coastguard Worker 		 * XXX - does this reliably set errno?
795*8b26181fSAndroid Build Coastguard Worker 		 */
796*8b26181fSAndroid Build Coastguard Worker 		if (errno == ENOENT) {
797*8b26181fSAndroid Build Coastguard Worker 			/*
798*8b26181fSAndroid Build Coastguard Worker 			 * There's nothing more to say, so clear
799*8b26181fSAndroid Build Coastguard Worker 			 * the error message.
800*8b26181fSAndroid Build Coastguard Worker 			 */
801*8b26181fSAndroid Build Coastguard Worker 			ret = PCAP_ERROR_NO_SUCH_DEVICE;
802*8b26181fSAndroid Build Coastguard Worker 			p->errbuf[0] = '\0';
803*8b26181fSAndroid Build Coastguard Worker 		} else if (errno == EPERM || errno == EACCES) {
804*8b26181fSAndroid Build Coastguard Worker 			ret = PCAP_ERROR_PERM_DENIED;
805*8b26181fSAndroid Build Coastguard Worker 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
806*8b26181fSAndroid Build Coastguard Worker 			    "Attempt to open %s failed with %s - additional privileges may be required",
807*8b26181fSAndroid Build Coastguard Worker 			    device, (errno == EPERM) ? "EPERM" : "EACCES");
808*8b26181fSAndroid Build Coastguard Worker 		} else {
809*8b26181fSAndroid Build Coastguard Worker 			ret = PCAP_ERROR;
810*8b26181fSAndroid Build Coastguard Worker 			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
811*8b26181fSAndroid Build Coastguard Worker 			    errno, "dag_config_init %s", device);
812*8b26181fSAndroid Build Coastguard Worker 		}
813*8b26181fSAndroid Build Coastguard Worker 		goto fail;
814*8b26181fSAndroid Build Coastguard Worker 	}
815*8b26181fSAndroid Build Coastguard Worker 
816*8b26181fSAndroid Build Coastguard Worker 	if((p->fd = dag_config_get_card_fd(pd->dag_ref)) < 0) {
817*8b26181fSAndroid Build Coastguard Worker 		/*
818*8b26181fSAndroid Build Coastguard Worker 		 * XXX - does this reliably set errno?
819*8b26181fSAndroid Build Coastguard Worker 		 */
820*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
821*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
822*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_config_get_card_fd %s", device);
823*8b26181fSAndroid Build Coastguard Worker 		goto failclose;
824*8b26181fSAndroid Build Coastguard Worker 	}
825*8b26181fSAndroid Build Coastguard Worker 
826*8b26181fSAndroid Build Coastguard Worker 	/* Open requested stream. Can fail if already locked or on error */
827*8b26181fSAndroid Build Coastguard Worker 	if (dag_attach_stream64(p->fd, pd->dag_stream, 0, 0) < 0) {
828*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
829*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
830*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_attach_stream");
831*8b26181fSAndroid Build Coastguard Worker 		goto failclose;
832*8b26181fSAndroid Build Coastguard Worker 	}
833*8b26181fSAndroid Build Coastguard Worker 
834*8b26181fSAndroid Build Coastguard Worker 	/* Try to find Stream Drop attribute */
835*8b26181fSAndroid Build Coastguard Worker 	pd->drop_attr = kNullAttributeUuid;
836*8b26181fSAndroid Build Coastguard Worker 	pd->dag_root = dag_config_get_root_component(pd->dag_ref);
837*8b26181fSAndroid Build Coastguard Worker 	if ( dag_component_get_subcomponent(pd->dag_root, kComponentStreamFeatures, 0) )
838*8b26181fSAndroid Build Coastguard Worker 	{
839*8b26181fSAndroid Build Coastguard Worker 		pd->drop_attr = dag_config_get_indexed_attribute_uuid(pd->dag_ref, kUint32AttributeStreamDropCount, pd->dag_stream/2);
840*8b26181fSAndroid Build Coastguard Worker 	}
841*8b26181fSAndroid Build Coastguard Worker 
842*8b26181fSAndroid Build Coastguard Worker 	/* Set up default poll parameters for stream
843*8b26181fSAndroid Build Coastguard Worker 	 * Can be overridden by pcap_set_nonblock()
844*8b26181fSAndroid Build Coastguard Worker 	 */
845*8b26181fSAndroid Build Coastguard Worker 	if (dag_get_stream_poll64(p->fd, pd->dag_stream,
846*8b26181fSAndroid Build Coastguard Worker 				&mindata, &maxwait, &poll) < 0) {
847*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
848*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
849*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_get_stream_poll");
850*8b26181fSAndroid Build Coastguard Worker 		goto faildetach;
851*8b26181fSAndroid Build Coastguard Worker 	}
852*8b26181fSAndroid Build Coastguard Worker 
853*8b26181fSAndroid Build Coastguard Worker 	/* Use the poll time as the required select timeout for callers
854*8b26181fSAndroid Build Coastguard Worker 	 * who are using select()/etc. in an event loop waiting for
855*8b26181fSAndroid Build Coastguard Worker 	 * packets to arrive.
856*8b26181fSAndroid Build Coastguard Worker 	 */
857*8b26181fSAndroid Build Coastguard Worker 	pd->required_select_timeout = poll;
858*8b26181fSAndroid Build Coastguard Worker 	p->required_select_timeout = &pd->required_select_timeout;
859*8b26181fSAndroid Build Coastguard Worker 
860*8b26181fSAndroid Build Coastguard Worker 	/*
861*8b26181fSAndroid Build Coastguard Worker 	 * Turn a negative snapshot value (invalid), a snapshot value of
862*8b26181fSAndroid Build Coastguard Worker 	 * 0 (unspecified), or a value bigger than the normal maximum
863*8b26181fSAndroid Build Coastguard Worker 	 * value, into the maximum allowed value.
864*8b26181fSAndroid Build Coastguard Worker 	 *
865*8b26181fSAndroid Build Coastguard Worker 	 * If some application really *needs* a bigger snapshot
866*8b26181fSAndroid Build Coastguard Worker 	 * length, we should just increase MAXIMUM_SNAPLEN.
867*8b26181fSAndroid Build Coastguard Worker 	 */
868*8b26181fSAndroid Build Coastguard Worker 	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
869*8b26181fSAndroid Build Coastguard Worker 		p->snapshot = MAXIMUM_SNAPLEN;
870*8b26181fSAndroid Build Coastguard Worker 
871*8b26181fSAndroid Build Coastguard Worker 	if (p->opt.immediate) {
872*8b26181fSAndroid Build Coastguard Worker 		/* Call callback immediately.
873*8b26181fSAndroid Build Coastguard Worker 		 * XXX - is this the right way to p this?
874*8b26181fSAndroid Build Coastguard Worker 		 */
875*8b26181fSAndroid Build Coastguard Worker 		mindata = 0;
876*8b26181fSAndroid Build Coastguard Worker 	} else {
877*8b26181fSAndroid Build Coastguard Worker 		/* Amount of data to collect in Bytes before calling callbacks.
878*8b26181fSAndroid Build Coastguard Worker 		 * Important for efficiency, but can introduce latency
879*8b26181fSAndroid Build Coastguard Worker 		 * at low packet rates if to_ms not set!
880*8b26181fSAndroid Build Coastguard Worker 		 */
881*8b26181fSAndroid Build Coastguard Worker 		mindata = 65536;
882*8b26181fSAndroid Build Coastguard Worker 	}
883*8b26181fSAndroid Build Coastguard Worker 
884*8b26181fSAndroid Build Coastguard Worker 	/* Obey opt.timeout (was to_ms) if supplied. This is a good idea!
885*8b26181fSAndroid Build Coastguard Worker 	 * Recommend 10-100ms. Calls will time out even if no data arrived.
886*8b26181fSAndroid Build Coastguard Worker 	 */
887*8b26181fSAndroid Build Coastguard Worker 	maxwait.tv_sec = p->opt.timeout/1000;
888*8b26181fSAndroid Build Coastguard Worker 	maxwait.tv_usec = (p->opt.timeout%1000) * 1000;
889*8b26181fSAndroid Build Coastguard Worker 
890*8b26181fSAndroid Build Coastguard Worker 	if (dag_set_stream_poll64(p->fd, pd->dag_stream,
891*8b26181fSAndroid Build Coastguard Worker 				mindata, &maxwait, &poll) < 0) {
892*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
893*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
894*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_set_stream_poll");
895*8b26181fSAndroid Build Coastguard Worker 		goto faildetach;
896*8b26181fSAndroid Build Coastguard Worker 	}
897*8b26181fSAndroid Build Coastguard Worker 
898*8b26181fSAndroid Build Coastguard Worker         /* XXX Not calling dag_configure() to set slen; this is unsafe in
899*8b26181fSAndroid Build Coastguard Worker 	 * multi-stream environments as the gpp config is global.
900*8b26181fSAndroid Build Coastguard Worker          * Once the firmware provides 'per-stream slen' this can be supported
901*8b26181fSAndroid Build Coastguard Worker 	 * again via the Config API without side-effects */
902*8b26181fSAndroid Build Coastguard Worker #if 0
903*8b26181fSAndroid Build Coastguard Worker 	/* set the card snap length to the specified snaplen parameter */
904*8b26181fSAndroid Build Coastguard Worker 	/* This is a really bad idea, as different cards have different
905*8b26181fSAndroid Build Coastguard Worker 	 * valid slen ranges. Should fix in Config API. */
906*8b26181fSAndroid Build Coastguard Worker 	if (p->snapshot == 0 || p->snapshot > MAX_DAG_SNAPLEN) {
907*8b26181fSAndroid Build Coastguard Worker 		p->snapshot = MAX_DAG_SNAPLEN;
908*8b26181fSAndroid Build Coastguard Worker 	} else if (snaplen < MIN_DAG_SNAPLEN) {
909*8b26181fSAndroid Build Coastguard Worker 		p->snapshot = MIN_DAG_SNAPLEN;
910*8b26181fSAndroid Build Coastguard Worker 	}
911*8b26181fSAndroid Build Coastguard Worker 	/* snap len has to be a multiple of 4 */
912*8b26181fSAndroid Build Coastguard Worker #endif
913*8b26181fSAndroid Build Coastguard Worker 
914*8b26181fSAndroid Build Coastguard Worker 	if(dag_start_stream(p->fd, pd->dag_stream) < 0) {
915*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
916*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
917*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_start_stream %s", device);
918*8b26181fSAndroid Build Coastguard Worker 		goto faildetach;
919*8b26181fSAndroid Build Coastguard Worker 	}
920*8b26181fSAndroid Build Coastguard Worker 
921*8b26181fSAndroid Build Coastguard Worker 	/*
922*8b26181fSAndroid Build Coastguard Worker 	 * Important! You have to ensure bottom is properly
923*8b26181fSAndroid Build Coastguard Worker 	 * initialized to zero on startup, it won't give you
924*8b26181fSAndroid Build Coastguard Worker 	 * a compiler warning if you make this mistake!
925*8b26181fSAndroid Build Coastguard Worker 	 */
926*8b26181fSAndroid Build Coastguard Worker 	pd->dag_mem_bottom = 0;
927*8b26181fSAndroid Build Coastguard Worker 	pd->dag_mem_top = 0;
928*8b26181fSAndroid Build Coastguard Worker 
929*8b26181fSAndroid Build Coastguard Worker 	/*
930*8b26181fSAndroid Build Coastguard Worker 	 * Find out how many FCS bits we should strip.
931*8b26181fSAndroid Build Coastguard Worker 	 * First, query the card to see if it strips the FCS.
932*8b26181fSAndroid Build Coastguard Worker 	 */
933*8b26181fSAndroid Build Coastguard Worker 	daginf = dag_info(p->fd);
934*8b26181fSAndroid Build Coastguard Worker 	if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code))	{
935*8b26181fSAndroid Build Coastguard Worker 		/* DAG 4.2S and 4.23S already strip the FCS.  Stripping the final word again truncates the packet. */
936*8b26181fSAndroid Build Coastguard Worker 		pd->dag_fcs_bits = 0;
937*8b26181fSAndroid Build Coastguard Worker 
938*8b26181fSAndroid Build Coastguard Worker 		/* Note that no FCS will be supplied. */
939*8b26181fSAndroid Build Coastguard Worker 		p->linktype_ext = LT_FCS_DATALINK_EXT(0);
940*8b26181fSAndroid Build Coastguard Worker 	} else {
941*8b26181fSAndroid Build Coastguard Worker 		/*
942*8b26181fSAndroid Build Coastguard Worker 		 * Start out assuming it's 32 bits.
943*8b26181fSAndroid Build Coastguard Worker 		 */
944*8b26181fSAndroid Build Coastguard Worker 		pd->dag_fcs_bits = 32;
945*8b26181fSAndroid Build Coastguard Worker 
946*8b26181fSAndroid Build Coastguard Worker 		/* Allow an environment variable to override. */
947*8b26181fSAndroid Build Coastguard Worker 		if ((s = getenv("ERF_FCS_BITS")) != NULL) {
948*8b26181fSAndroid Build Coastguard Worker 			if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
949*8b26181fSAndroid Build Coastguard Worker 				pd->dag_fcs_bits = n;
950*8b26181fSAndroid Build Coastguard Worker 			} else {
951*8b26181fSAndroid Build Coastguard Worker 				ret = PCAP_ERROR;
952*8b26181fSAndroid Build Coastguard Worker 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
953*8b26181fSAndroid Build Coastguard Worker 					"pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment", device, n);
954*8b26181fSAndroid Build Coastguard Worker 				goto failstop;
955*8b26181fSAndroid Build Coastguard Worker 			}
956*8b26181fSAndroid Build Coastguard Worker 		}
957*8b26181fSAndroid Build Coastguard Worker 
958*8b26181fSAndroid Build Coastguard Worker 		/*
959*8b26181fSAndroid Build Coastguard Worker 		 * Did the user request that they not be stripped?
960*8b26181fSAndroid Build Coastguard Worker 		 */
961*8b26181fSAndroid Build Coastguard Worker 		if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) {
962*8b26181fSAndroid Build Coastguard Worker 			/* Yes.  Note the number of 16-bit words that will be
963*8b26181fSAndroid Build Coastguard Worker 			   supplied. */
964*8b26181fSAndroid Build Coastguard Worker 			p->linktype_ext = LT_FCS_DATALINK_EXT(pd->dag_fcs_bits/16);
965*8b26181fSAndroid Build Coastguard Worker 
966*8b26181fSAndroid Build Coastguard Worker 			/* And don't strip them. */
967*8b26181fSAndroid Build Coastguard Worker 			pd->dag_fcs_bits = 0;
968*8b26181fSAndroid Build Coastguard Worker 		}
969*8b26181fSAndroid Build Coastguard Worker 	}
970*8b26181fSAndroid Build Coastguard Worker 
971*8b26181fSAndroid Build Coastguard Worker 	pd->dag_timeout	= p->opt.timeout;
972*8b26181fSAndroid Build Coastguard Worker 
973*8b26181fSAndroid Build Coastguard Worker 	p->linktype = -1;
974*8b26181fSAndroid Build Coastguard Worker 	if (dag_get_datalink(p) < 0) {
975*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
976*8b26181fSAndroid Build Coastguard Worker 		goto failstop;
977*8b26181fSAndroid Build Coastguard Worker 	}
978*8b26181fSAndroid Build Coastguard Worker 
979*8b26181fSAndroid Build Coastguard Worker 	p->bufsize = 0;
980*8b26181fSAndroid Build Coastguard Worker 
981*8b26181fSAndroid Build Coastguard Worker 	if (new_pcap_dag(p) < 0) {
982*8b26181fSAndroid Build Coastguard Worker 		ret = PCAP_ERROR;
983*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
984*8b26181fSAndroid Build Coastguard Worker 		    errno, "new_pcap_dag %s", device);
985*8b26181fSAndroid Build Coastguard Worker 		goto failstop;
986*8b26181fSAndroid Build Coastguard Worker 	}
987*8b26181fSAndroid Build Coastguard Worker 
988*8b26181fSAndroid Build Coastguard Worker 	/*
989*8b26181fSAndroid Build Coastguard Worker 	 * "select()" and "poll()" don't work on DAG device descriptors.
990*8b26181fSAndroid Build Coastguard Worker 	 */
991*8b26181fSAndroid Build Coastguard Worker 	p->selectable_fd = -1;
992*8b26181fSAndroid Build Coastguard Worker 
993*8b26181fSAndroid Build Coastguard Worker 	if (newDev != NULL) {
994*8b26181fSAndroid Build Coastguard Worker 		free((char *)newDev);
995*8b26181fSAndroid Build Coastguard Worker 	}
996*8b26181fSAndroid Build Coastguard Worker 
997*8b26181fSAndroid Build Coastguard Worker 	p->read_op = dag_read;
998*8b26181fSAndroid Build Coastguard Worker 	p->inject_op = dag_inject;
999*8b26181fSAndroid Build Coastguard Worker 	p->setfilter_op = install_bpf_program;
1000*8b26181fSAndroid Build Coastguard Worker 	p->setdirection_op = NULL; /* Not implemented.*/
1001*8b26181fSAndroid Build Coastguard Worker 	p->set_datalink_op = dag_set_datalink;
1002*8b26181fSAndroid Build Coastguard Worker 	p->getnonblock_op = pcap_getnonblock_fd;
1003*8b26181fSAndroid Build Coastguard Worker 	p->setnonblock_op = dag_setnonblock;
1004*8b26181fSAndroid Build Coastguard Worker 	p->stats_op = dag_stats;
1005*8b26181fSAndroid Build Coastguard Worker 	p->cleanup_op = dag_platform_cleanup;
1006*8b26181fSAndroid Build Coastguard Worker 	pd->stat.ps_drop = 0;
1007*8b26181fSAndroid Build Coastguard Worker 	pd->stat.ps_recv = 0;
1008*8b26181fSAndroid Build Coastguard Worker 	pd->stat.ps_ifdrop = 0;
1009*8b26181fSAndroid Build Coastguard Worker 	return 0;
1010*8b26181fSAndroid Build Coastguard Worker 
1011*8b26181fSAndroid Build Coastguard Worker failstop:
1012*8b26181fSAndroid Build Coastguard Worker 	if (dag_stop_stream(p->fd, pd->dag_stream) < 0) {
1013*8b26181fSAndroid Build Coastguard Worker 		fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
1014*8b26181fSAndroid Build Coastguard Worker 	}
1015*8b26181fSAndroid Build Coastguard Worker 
1016*8b26181fSAndroid Build Coastguard Worker faildetach:
1017*8b26181fSAndroid Build Coastguard Worker 	if (dag_detach_stream(p->fd, pd->dag_stream) < 0)
1018*8b26181fSAndroid Build Coastguard Worker 		fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
1019*8b26181fSAndroid Build Coastguard Worker 
1020*8b26181fSAndroid Build Coastguard Worker failclose:
1021*8b26181fSAndroid Build Coastguard Worker 	dag_config_dispose(pd->dag_ref);
1022*8b26181fSAndroid Build Coastguard Worker 	/*
1023*8b26181fSAndroid Build Coastguard Worker 	 * Note: we don't need to call close(p->fd) or dag_close(p->fd),
1024*8b26181fSAndroid Build Coastguard Worker 	 * as dag_config_dispose(pd->dag_ref) does this.
1025*8b26181fSAndroid Build Coastguard Worker 	 *
1026*8b26181fSAndroid Build Coastguard Worker 	 * Set p->fd to -1 to make sure that's not done.
1027*8b26181fSAndroid Build Coastguard Worker 	 */
1028*8b26181fSAndroid Build Coastguard Worker 	p->fd = -1;
1029*8b26181fSAndroid Build Coastguard Worker 	pd->dag_ref = NULL;
1030*8b26181fSAndroid Build Coastguard Worker 	delete_pcap_dag(p);
1031*8b26181fSAndroid Build Coastguard Worker 
1032*8b26181fSAndroid Build Coastguard Worker fail:
1033*8b26181fSAndroid Build Coastguard Worker 	pcap_cleanup_live_common(p);
1034*8b26181fSAndroid Build Coastguard Worker 	if (newDev != NULL) {
1035*8b26181fSAndroid Build Coastguard Worker 		free((char *)newDev);
1036*8b26181fSAndroid Build Coastguard Worker 	}
1037*8b26181fSAndroid Build Coastguard Worker 
1038*8b26181fSAndroid Build Coastguard Worker 	return ret;
1039*8b26181fSAndroid Build Coastguard Worker }
1040*8b26181fSAndroid Build Coastguard Worker 
dag_create(const char * device,char * ebuf,int * is_ours)1041*8b26181fSAndroid Build Coastguard Worker pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
1042*8b26181fSAndroid Build Coastguard Worker {
1043*8b26181fSAndroid Build Coastguard Worker 	const char *cp;
1044*8b26181fSAndroid Build Coastguard Worker 	char *cpend;
1045*8b26181fSAndroid Build Coastguard Worker 	long devnum;
1046*8b26181fSAndroid Build Coastguard Worker 	pcap_t *p;
1047*8b26181fSAndroid Build Coastguard Worker 	long stream = 0;
1048*8b26181fSAndroid Build Coastguard Worker 
1049*8b26181fSAndroid Build Coastguard Worker 	/* Does this look like a DAG device? */
1050*8b26181fSAndroid Build Coastguard Worker 	cp = strrchr(device, '/');
1051*8b26181fSAndroid Build Coastguard Worker 	if (cp == NULL)
1052*8b26181fSAndroid Build Coastguard Worker 		cp = device;
1053*8b26181fSAndroid Build Coastguard Worker 	/* Does it begin with "dag"? */
1054*8b26181fSAndroid Build Coastguard Worker 	if (strncmp(cp, "dag", 3) != 0) {
1055*8b26181fSAndroid Build Coastguard Worker 		/* Nope, doesn't begin with "dag" */
1056*8b26181fSAndroid Build Coastguard Worker 		*is_ours = 0;
1057*8b26181fSAndroid Build Coastguard Worker 		return NULL;
1058*8b26181fSAndroid Build Coastguard Worker 	}
1059*8b26181fSAndroid Build Coastguard Worker 	/* Yes - is "dag" followed by a number from 0 to DAG_MAX_BOARDS-1 */
1060*8b26181fSAndroid Build Coastguard Worker 	cp += 3;
1061*8b26181fSAndroid Build Coastguard Worker 	devnum = strtol(cp, &cpend, 10);
1062*8b26181fSAndroid Build Coastguard Worker 	if (*cpend == ':') {
1063*8b26181fSAndroid Build Coastguard Worker 		/* Followed by a stream number. */
1064*8b26181fSAndroid Build Coastguard Worker 		stream = strtol(++cpend, &cpend, 10);
1065*8b26181fSAndroid Build Coastguard Worker 	}
1066*8b26181fSAndroid Build Coastguard Worker 
1067*8b26181fSAndroid Build Coastguard Worker 	if (cpend == cp || *cpend != '\0') {
1068*8b26181fSAndroid Build Coastguard Worker 		/* Not followed by a number. */
1069*8b26181fSAndroid Build Coastguard Worker 		*is_ours = 0;
1070*8b26181fSAndroid Build Coastguard Worker 		return NULL;
1071*8b26181fSAndroid Build Coastguard Worker 	}
1072*8b26181fSAndroid Build Coastguard Worker 
1073*8b26181fSAndroid Build Coastguard Worker 	if (devnum < 0 || devnum >= DAG_MAX_BOARDS) {
1074*8b26181fSAndroid Build Coastguard Worker 		/* Followed by a non-valid number. */
1075*8b26181fSAndroid Build Coastguard Worker 		*is_ours = 0;
1076*8b26181fSAndroid Build Coastguard Worker 		return NULL;
1077*8b26181fSAndroid Build Coastguard Worker 	}
1078*8b26181fSAndroid Build Coastguard Worker 
1079*8b26181fSAndroid Build Coastguard Worker 	if (stream <0 || stream >= DAG_STREAM_MAX) {
1080*8b26181fSAndroid Build Coastguard Worker 		/* Followed by a non-valid stream number. */
1081*8b26181fSAndroid Build Coastguard Worker 		*is_ours = 0;
1082*8b26181fSAndroid Build Coastguard Worker 		return NULL;
1083*8b26181fSAndroid Build Coastguard Worker 	}
1084*8b26181fSAndroid Build Coastguard Worker 
1085*8b26181fSAndroid Build Coastguard Worker 	/* OK, it's probably ours. */
1086*8b26181fSAndroid Build Coastguard Worker 	*is_ours = 1;
1087*8b26181fSAndroid Build Coastguard Worker 
1088*8b26181fSAndroid Build Coastguard Worker 	p = PCAP_CREATE_COMMON(ebuf, struct pcap_dag);
1089*8b26181fSAndroid Build Coastguard Worker 	if (p == NULL)
1090*8b26181fSAndroid Build Coastguard Worker 		return NULL;
1091*8b26181fSAndroid Build Coastguard Worker 
1092*8b26181fSAndroid Build Coastguard Worker 	p->activate_op = dag_activate;
1093*8b26181fSAndroid Build Coastguard Worker 
1094*8b26181fSAndroid Build Coastguard Worker 	/*
1095*8b26181fSAndroid Build Coastguard Worker 	 * We claim that we support microsecond and nanosecond time
1096*8b26181fSAndroid Build Coastguard Worker 	 * stamps.
1097*8b26181fSAndroid Build Coastguard Worker 	 *
1098*8b26181fSAndroid Build Coastguard Worker 	 * XXX Our native precision is 2^-32s, but libpcap doesn't support
1099*8b26181fSAndroid Build Coastguard Worker 	 * power of two precisions yet. We can convert to either MICRO or NANO.
1100*8b26181fSAndroid Build Coastguard Worker 	 */
1101*8b26181fSAndroid Build Coastguard Worker 	p->tstamp_precision_list = malloc(2 * sizeof(u_int));
1102*8b26181fSAndroid Build Coastguard Worker 	if (p->tstamp_precision_list == NULL) {
1103*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1104*8b26181fSAndroid Build Coastguard Worker 		    errno, "malloc");
1105*8b26181fSAndroid Build Coastguard Worker 		pcap_close(p);
1106*8b26181fSAndroid Build Coastguard Worker 		return NULL;
1107*8b26181fSAndroid Build Coastguard Worker 	}
1108*8b26181fSAndroid Build Coastguard Worker 	p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
1109*8b26181fSAndroid Build Coastguard Worker 	p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
1110*8b26181fSAndroid Build Coastguard Worker 	p->tstamp_precision_count = 2;
1111*8b26181fSAndroid Build Coastguard Worker 	return p;
1112*8b26181fSAndroid Build Coastguard Worker }
1113*8b26181fSAndroid Build Coastguard Worker 
1114*8b26181fSAndroid Build Coastguard Worker static int
dag_stats(pcap_t * p,struct pcap_stat * ps)1115*8b26181fSAndroid Build Coastguard Worker dag_stats(pcap_t *p, struct pcap_stat *ps) {
1116*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dag *pd = p->priv;
1117*8b26181fSAndroid Build Coastguard Worker 	uint32_t stream_drop;
1118*8b26181fSAndroid Build Coastguard Worker 	dag_err_t dag_error;
1119*8b26181fSAndroid Build Coastguard Worker 
1120*8b26181fSAndroid Build Coastguard Worker 	/*
1121*8b26181fSAndroid Build Coastguard Worker 	 * Packet records received (ps_recv) are counted in dag_read().
1122*8b26181fSAndroid Build Coastguard Worker 	 * Packet records dropped (ps_drop) are read from Stream Drop attribute if present,
1123*8b26181fSAndroid Build Coastguard Worker 	 * otherwise integrate the ERF Header lctr counts (if available) in dag_read().
1124*8b26181fSAndroid Build Coastguard Worker 	 * We are reporting that no records are dropped by the card/driver (ps_ifdrop).
1125*8b26181fSAndroid Build Coastguard Worker 	 */
1126*8b26181fSAndroid Build Coastguard Worker 
1127*8b26181fSAndroid Build Coastguard Worker 	if(pd->drop_attr != kNullAttributeUuid) {
1128*8b26181fSAndroid Build Coastguard Worker 		/* Note this counter is cleared at start of capture and will wrap at UINT_MAX.
1129*8b26181fSAndroid Build Coastguard Worker 		 * The application is responsible for polling ps_drop frequently enough
1130*8b26181fSAndroid Build Coastguard Worker 		 * to detect each wrap and integrate total drop with a wider counter */
1131*8b26181fSAndroid Build Coastguard Worker 		if ((dag_error = dag_config_get_uint32_attribute_ex(pd->dag_ref, pd->drop_attr, &stream_drop)) == kDagErrNone) {
1132*8b26181fSAndroid Build Coastguard Worker 			pd->stat.ps_drop = stream_drop;
1133*8b26181fSAndroid Build Coastguard Worker 		} else {
1134*8b26181fSAndroid Build Coastguard Worker 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "reading stream drop attribute: %s",
1135*8b26181fSAndroid Build Coastguard Worker 				 dag_config_strerror(dag_error));
1136*8b26181fSAndroid Build Coastguard Worker 			return -1;
1137*8b26181fSAndroid Build Coastguard Worker 		}
1138*8b26181fSAndroid Build Coastguard Worker 	}
1139*8b26181fSAndroid Build Coastguard Worker 
1140*8b26181fSAndroid Build Coastguard Worker 	*ps = pd->stat;
1141*8b26181fSAndroid Build Coastguard Worker 
1142*8b26181fSAndroid Build Coastguard Worker 	return 0;
1143*8b26181fSAndroid Build Coastguard Worker }
1144*8b26181fSAndroid Build Coastguard Worker 
1145*8b26181fSAndroid Build Coastguard Worker /*
1146*8b26181fSAndroid Build Coastguard Worker  * Add all DAG devices.
1147*8b26181fSAndroid Build Coastguard Worker  */
1148*8b26181fSAndroid Build Coastguard Worker int
dag_findalldevs(pcap_if_list_t * devlistp,char * errbuf)1149*8b26181fSAndroid Build Coastguard Worker dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
1150*8b26181fSAndroid Build Coastguard Worker {
1151*8b26181fSAndroid Build Coastguard Worker 	char name[12];	/* XXX - pick a size */
1152*8b26181fSAndroid Build Coastguard Worker 	int c;
1153*8b26181fSAndroid Build Coastguard Worker 	char dagname[DAGNAME_BUFSIZE];
1154*8b26181fSAndroid Build Coastguard Worker 	int dagstream;
1155*8b26181fSAndroid Build Coastguard Worker 	int dagfd;
1156*8b26181fSAndroid Build Coastguard Worker 	dag_card_inf_t *inf;
1157*8b26181fSAndroid Build Coastguard Worker 	char *description;
1158*8b26181fSAndroid Build Coastguard Worker 	int stream, rxstreams;
1159*8b26181fSAndroid Build Coastguard Worker 
1160*8b26181fSAndroid Build Coastguard Worker 	/* Try all the DAGs 0-DAG_MAX_BOARDS */
1161*8b26181fSAndroid Build Coastguard Worker 	for (c = 0; c < DAG_MAX_BOARDS; c++) {
1162*8b26181fSAndroid Build Coastguard Worker 		snprintf(name, 12, "dag%d", c);
1163*8b26181fSAndroid Build Coastguard Worker 		if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
1164*8b26181fSAndroid Build Coastguard Worker 		{
1165*8b26181fSAndroid Build Coastguard Worker 			(void) snprintf(errbuf, PCAP_ERRBUF_SIZE,
1166*8b26181fSAndroid Build Coastguard Worker 			    "dag: device name %s can't be parsed", name);
1167*8b26181fSAndroid Build Coastguard Worker 			return (-1);
1168*8b26181fSAndroid Build Coastguard Worker 		}
1169*8b26181fSAndroid Build Coastguard Worker 		if ( (dagfd = dag_open(dagname)) >= 0 ) {
1170*8b26181fSAndroid Build Coastguard Worker 			description = NULL;
1171*8b26181fSAndroid Build Coastguard Worker 			if ((inf = dag_pciinfo(dagfd)))
1172*8b26181fSAndroid Build Coastguard Worker 				description = dag_device_name(inf->device_code, 1);
1173*8b26181fSAndroid Build Coastguard Worker 			/*
1174*8b26181fSAndroid Build Coastguard Worker 			 * XXX - is there a way to determine whether
1175*8b26181fSAndroid Build Coastguard Worker 			 * the card is plugged into a network or not?
1176*8b26181fSAndroid Build Coastguard Worker 			 * If so, we should check that and set
1177*8b26181fSAndroid Build Coastguard Worker 			 * PCAP_IF_CONNECTION_STATUS_CONNECTED or
1178*8b26181fSAndroid Build Coastguard Worker 			 * PCAP_IF_CONNECTION_STATUS_DISCONNECTED.
1179*8b26181fSAndroid Build Coastguard Worker 			 *
1180*8b26181fSAndroid Build Coastguard Worker 			 * Also, are there notions of "up" and "running"?
1181*8b26181fSAndroid Build Coastguard Worker 			 */
1182*8b26181fSAndroid Build Coastguard Worker 			if (add_dev(devlistp, name, 0, description, errbuf) == NULL) {
1183*8b26181fSAndroid Build Coastguard Worker 				/*
1184*8b26181fSAndroid Build Coastguard Worker 				 * Failure.
1185*8b26181fSAndroid Build Coastguard Worker 				 */
1186*8b26181fSAndroid Build Coastguard Worker 				return (-1);
1187*8b26181fSAndroid Build Coastguard Worker 			}
1188*8b26181fSAndroid Build Coastguard Worker 			rxstreams = dag_rx_get_stream_count(dagfd);
1189*8b26181fSAndroid Build Coastguard Worker 			for(stream=0;stream<DAG_STREAM_MAX;stream+=2) {
1190*8b26181fSAndroid Build Coastguard Worker 				if (0 == dag_attach_stream64(dagfd, stream, 0, 0)) {
1191*8b26181fSAndroid Build Coastguard Worker 					dag_detach_stream(dagfd, stream);
1192*8b26181fSAndroid Build Coastguard Worker 
1193*8b26181fSAndroid Build Coastguard Worker 					snprintf(name,  10, "dag%d:%d", c, stream);
1194*8b26181fSAndroid Build Coastguard Worker 					if (add_dev(devlistp, name, 0, description, errbuf) == NULL) {
1195*8b26181fSAndroid Build Coastguard Worker 						/*
1196*8b26181fSAndroid Build Coastguard Worker 						 * Failure.
1197*8b26181fSAndroid Build Coastguard Worker 						 */
1198*8b26181fSAndroid Build Coastguard Worker 						return (-1);
1199*8b26181fSAndroid Build Coastguard Worker 					}
1200*8b26181fSAndroid Build Coastguard Worker 
1201*8b26181fSAndroid Build Coastguard Worker 					rxstreams--;
1202*8b26181fSAndroid Build Coastguard Worker 					if(rxstreams <= 0) {
1203*8b26181fSAndroid Build Coastguard Worker 						break;
1204*8b26181fSAndroid Build Coastguard Worker 					}
1205*8b26181fSAndroid Build Coastguard Worker 				}
1206*8b26181fSAndroid Build Coastguard Worker 			}
1207*8b26181fSAndroid Build Coastguard Worker 			dag_close(dagfd);
1208*8b26181fSAndroid Build Coastguard Worker 		}
1209*8b26181fSAndroid Build Coastguard Worker 
1210*8b26181fSAndroid Build Coastguard Worker 	}
1211*8b26181fSAndroid Build Coastguard Worker 	return (0);
1212*8b26181fSAndroid Build Coastguard Worker }
1213*8b26181fSAndroid Build Coastguard Worker 
1214*8b26181fSAndroid Build Coastguard Worker static int
dag_set_datalink(pcap_t * p,int dlt)1215*8b26181fSAndroid Build Coastguard Worker dag_set_datalink(pcap_t *p, int dlt)
1216*8b26181fSAndroid Build Coastguard Worker {
1217*8b26181fSAndroid Build Coastguard Worker 	p->linktype = dlt;
1218*8b26181fSAndroid Build Coastguard Worker 
1219*8b26181fSAndroid Build Coastguard Worker 	return (0);
1220*8b26181fSAndroid Build Coastguard Worker }
1221*8b26181fSAndroid Build Coastguard Worker 
1222*8b26181fSAndroid Build Coastguard Worker static int
dag_setnonblock(pcap_t * p,int nonblock)1223*8b26181fSAndroid Build Coastguard Worker dag_setnonblock(pcap_t *p, int nonblock)
1224*8b26181fSAndroid Build Coastguard Worker {
1225*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dag *pd = p->priv;
1226*8b26181fSAndroid Build Coastguard Worker 	dag_size_t mindata;
1227*8b26181fSAndroid Build Coastguard Worker 	struct timeval maxwait;
1228*8b26181fSAndroid Build Coastguard Worker 	struct timeval poll;
1229*8b26181fSAndroid Build Coastguard Worker 
1230*8b26181fSAndroid Build Coastguard Worker 	/*
1231*8b26181fSAndroid Build Coastguard Worker 	 * Set non-blocking mode on the FD.
1232*8b26181fSAndroid Build Coastguard Worker 	 * XXX - is that necessary?  If not, don't bother calling it,
1233*8b26181fSAndroid Build Coastguard Worker 	 * and have a "dag_getnonblock()" function that looks at
1234*8b26181fSAndroid Build Coastguard Worker 	 * "pd->dag_flags".
1235*8b26181fSAndroid Build Coastguard Worker 	 */
1236*8b26181fSAndroid Build Coastguard Worker 	if (pcap_setnonblock_fd(p, nonblock) < 0)
1237*8b26181fSAndroid Build Coastguard Worker 		return (-1);
1238*8b26181fSAndroid Build Coastguard Worker 
1239*8b26181fSAndroid Build Coastguard Worker 	if (dag_get_stream_poll64(p->fd, pd->dag_stream,
1240*8b26181fSAndroid Build Coastguard Worker 				&mindata, &maxwait, &poll) < 0) {
1241*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1242*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_get_stream_poll");
1243*8b26181fSAndroid Build Coastguard Worker 		return -1;
1244*8b26181fSAndroid Build Coastguard Worker 	}
1245*8b26181fSAndroid Build Coastguard Worker 
1246*8b26181fSAndroid Build Coastguard Worker 	/* Amount of data to collect in Bytes before calling callbacks.
1247*8b26181fSAndroid Build Coastguard Worker 	 * Important for efficiency, but can introduce latency
1248*8b26181fSAndroid Build Coastguard Worker 	 * at low packet rates if to_ms not set!
1249*8b26181fSAndroid Build Coastguard Worker 	 */
1250*8b26181fSAndroid Build Coastguard Worker 	if(nonblock)
1251*8b26181fSAndroid Build Coastguard Worker 		mindata = 0;
1252*8b26181fSAndroid Build Coastguard Worker 	else
1253*8b26181fSAndroid Build Coastguard Worker 		mindata = 65536;
1254*8b26181fSAndroid Build Coastguard Worker 
1255*8b26181fSAndroid Build Coastguard Worker 	if (dag_set_stream_poll64(p->fd, pd->dag_stream,
1256*8b26181fSAndroid Build Coastguard Worker 				mindata, &maxwait, &poll) < 0) {
1257*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1258*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_set_stream_poll");
1259*8b26181fSAndroid Build Coastguard Worker 		return -1;
1260*8b26181fSAndroid Build Coastguard Worker 	}
1261*8b26181fSAndroid Build Coastguard Worker 
1262*8b26181fSAndroid Build Coastguard Worker 	if (nonblock) {
1263*8b26181fSAndroid Build Coastguard Worker 		pd->dag_flags |= DAGF_NONBLOCK;
1264*8b26181fSAndroid Build Coastguard Worker 	} else {
1265*8b26181fSAndroid Build Coastguard Worker 		pd->dag_flags &= ~DAGF_NONBLOCK;
1266*8b26181fSAndroid Build Coastguard Worker 	}
1267*8b26181fSAndroid Build Coastguard Worker 	return (0);
1268*8b26181fSAndroid Build Coastguard Worker }
1269*8b26181fSAndroid Build Coastguard Worker 
1270*8b26181fSAndroid Build Coastguard Worker static int
dag_get_datalink(pcap_t * p)1271*8b26181fSAndroid Build Coastguard Worker dag_get_datalink(pcap_t *p)
1272*8b26181fSAndroid Build Coastguard Worker {
1273*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dag *pd = p->priv;
1274*8b26181fSAndroid Build Coastguard Worker 	int index=0, dlt_index=0;
1275*8b26181fSAndroid Build Coastguard Worker 	uint8_t types[255];
1276*8b26181fSAndroid Build Coastguard Worker 
1277*8b26181fSAndroid Build Coastguard Worker 	memset(types, 0, 255);
1278*8b26181fSAndroid Build Coastguard Worker 
1279*8b26181fSAndroid Build Coastguard Worker 	if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) {
1280*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
1281*8b26181fSAndroid Build Coastguard Worker 		    errno, "malloc");
1282*8b26181fSAndroid Build Coastguard Worker 		return (-1);
1283*8b26181fSAndroid Build Coastguard Worker 	}
1284*8b26181fSAndroid Build Coastguard Worker 
1285*8b26181fSAndroid Build Coastguard Worker 	p->linktype = 0;
1286*8b26181fSAndroid Build Coastguard Worker 
1287*8b26181fSAndroid Build Coastguard Worker #ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
1288*8b26181fSAndroid Build Coastguard Worker 	/* Get list of possible ERF types for this card */
1289*8b26181fSAndroid Build Coastguard Worker 	if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) {
1290*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
1291*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_get_stream_erf_types");
1292*8b26181fSAndroid Build Coastguard Worker 		return (-1);
1293*8b26181fSAndroid Build Coastguard Worker 	}
1294*8b26181fSAndroid Build Coastguard Worker 
1295*8b26181fSAndroid Build Coastguard Worker 	while (types[index]) {
1296*8b26181fSAndroid Build Coastguard Worker 
1297*8b26181fSAndroid Build Coastguard Worker #elif defined HAVE_DAG_GET_ERF_TYPES
1298*8b26181fSAndroid Build Coastguard Worker 	/* Get list of possible ERF types for this card */
1299*8b26181fSAndroid Build Coastguard Worker 	if (dag_get_erf_types(p->fd, types, 255) < 0) {
1300*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
1301*8b26181fSAndroid Build Coastguard Worker 		    errno, "dag_get_erf_types");
1302*8b26181fSAndroid Build Coastguard Worker 		return (-1);
1303*8b26181fSAndroid Build Coastguard Worker 	}
1304*8b26181fSAndroid Build Coastguard Worker 
1305*8b26181fSAndroid Build Coastguard Worker 	while (types[index]) {
1306*8b26181fSAndroid Build Coastguard Worker #else
1307*8b26181fSAndroid Build Coastguard Worker 	/* Check the type through a dagapi call. */
1308*8b26181fSAndroid Build Coastguard Worker 	types[index] = dag_linktype(p->fd);
1309*8b26181fSAndroid Build Coastguard Worker 
1310*8b26181fSAndroid Build Coastguard Worker 	{
1311*8b26181fSAndroid Build Coastguard Worker #endif
1312*8b26181fSAndroid Build Coastguard Worker 		switch((types[index] & 0x7f)) {
1313*8b26181fSAndroid Build Coastguard Worker 
1314*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_HDLC_POS:
1315*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_HDLC_POS:
1316*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_DSM_COLOR_HDLC_POS:
1317*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_HASH_POS:
1318*8b26181fSAndroid Build Coastguard Worker 
1319*8b26181fSAndroid Build Coastguard Worker 			if (p->dlt_list != NULL) {
1320*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_CHDLC;
1321*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
1322*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_FRELAY;
1323*8b26181fSAndroid Build Coastguard Worker 			}
1324*8b26181fSAndroid Build Coastguard Worker 			if(!p->linktype)
1325*8b26181fSAndroid Build Coastguard Worker 				p->linktype = DLT_CHDLC;
1326*8b26181fSAndroid Build Coastguard Worker 			break;
1327*8b26181fSAndroid Build Coastguard Worker 
1328*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_ETH:
1329*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_ETH:
1330*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_DSM_COLOR_ETH:
1331*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_HASH_ETH:
1332*8b26181fSAndroid Build Coastguard Worker 			/*
1333*8b26181fSAndroid Build Coastguard Worker 			 * This is (presumably) a real Ethernet capture; give it a
1334*8b26181fSAndroid Build Coastguard Worker 			 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
1335*8b26181fSAndroid Build Coastguard Worker 			 * that an application can let you choose it, in case you're
1336*8b26181fSAndroid Build Coastguard Worker 			 * capturing DOCSIS traffic that a Cisco Cable Modem
1337*8b26181fSAndroid Build Coastguard Worker 			 * Termination System is putting out onto an Ethernet (it
1338*8b26181fSAndroid Build Coastguard Worker 			 * doesn't put an Ethernet header onto the wire, it puts raw
1339*8b26181fSAndroid Build Coastguard Worker 			 * DOCSIS frames out on the wire inside the low-level
1340*8b26181fSAndroid Build Coastguard Worker 			 * Ethernet framing).
1341*8b26181fSAndroid Build Coastguard Worker 			 */
1342*8b26181fSAndroid Build Coastguard Worker 			if (p->dlt_list != NULL) {
1343*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_EN10MB;
1344*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_DOCSIS;
1345*8b26181fSAndroid Build Coastguard Worker 			}
1346*8b26181fSAndroid Build Coastguard Worker 			if(!p->linktype)
1347*8b26181fSAndroid Build Coastguard Worker 				p->linktype = DLT_EN10MB;
1348*8b26181fSAndroid Build Coastguard Worker 			break;
1349*8b26181fSAndroid Build Coastguard Worker 
1350*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_ATM:
1351*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_AAL5:
1352*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_MC_ATM:
1353*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_MC_AAL5:
1354*8b26181fSAndroid Build Coastguard Worker 			if (p->dlt_list != NULL) {
1355*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_ATM_RFC1483;
1356*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_SUNATM;
1357*8b26181fSAndroid Build Coastguard Worker 			}
1358*8b26181fSAndroid Build Coastguard Worker 			if(!p->linktype)
1359*8b26181fSAndroid Build Coastguard Worker 				p->linktype = DLT_ATM_RFC1483;
1360*8b26181fSAndroid Build Coastguard Worker 			break;
1361*8b26181fSAndroid Build Coastguard Worker 
1362*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_COLOR_MC_HDLC_POS:
1363*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_MC_HDLC:
1364*8b26181fSAndroid Build Coastguard Worker 			if (p->dlt_list != NULL) {
1365*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_CHDLC;
1366*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
1367*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_FRELAY;
1368*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_MTP2;
1369*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_MTP2_WITH_PHDR;
1370*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_LAPD;
1371*8b26181fSAndroid Build Coastguard Worker 			}
1372*8b26181fSAndroid Build Coastguard Worker 			if(!p->linktype)
1373*8b26181fSAndroid Build Coastguard Worker 				p->linktype = DLT_CHDLC;
1374*8b26181fSAndroid Build Coastguard Worker 			break;
1375*8b26181fSAndroid Build Coastguard Worker 
1376*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_IPV4:
1377*8b26181fSAndroid Build Coastguard Worker 			if (p->dlt_list != NULL) {
1378*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_RAW;
1379*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_IPV4;
1380*8b26181fSAndroid Build Coastguard Worker 			}
1381*8b26181fSAndroid Build Coastguard Worker 			if(!p->linktype)
1382*8b26181fSAndroid Build Coastguard Worker 				p->linktype = DLT_RAW;
1383*8b26181fSAndroid Build Coastguard Worker 			break;
1384*8b26181fSAndroid Build Coastguard Worker 
1385*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_IPV6:
1386*8b26181fSAndroid Build Coastguard Worker 			if (p->dlt_list != NULL) {
1387*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_RAW;
1388*8b26181fSAndroid Build Coastguard Worker 				p->dlt_list[dlt_index++] = DLT_IPV6;
1389*8b26181fSAndroid Build Coastguard Worker 			}
1390*8b26181fSAndroid Build Coastguard Worker 			if(!p->linktype)
1391*8b26181fSAndroid Build Coastguard Worker 				p->linktype = DLT_RAW;
1392*8b26181fSAndroid Build Coastguard Worker 			break;
1393*8b26181fSAndroid Build Coastguard Worker 
1394*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_LEGACY:
1395*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_MC_RAW:
1396*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_MC_RAW_CHANNEL:
1397*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_IP_COUNTER:
1398*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_TCP_FLOW_COUNTER:
1399*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_INFINIBAND:
1400*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_RAW_LINK:
1401*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_INFINIBAND_LINK:
1402*8b26181fSAndroid Build Coastguard Worker 		case ERF_TYPE_META:
1403*8b26181fSAndroid Build Coastguard Worker 		default:
1404*8b26181fSAndroid Build Coastguard Worker 			/* Libpcap cannot deal with these types yet */
1405*8b26181fSAndroid Build Coastguard Worker 			/* Add no 'native' DLTs, but still covered by DLT_ERF */
1406*8b26181fSAndroid Build Coastguard Worker 			break;
1407*8b26181fSAndroid Build Coastguard Worker 
1408*8b26181fSAndroid Build Coastguard Worker 		} /* switch */
1409*8b26181fSAndroid Build Coastguard Worker 		index++;
1410*8b26181fSAndroid Build Coastguard Worker 	}
1411*8b26181fSAndroid Build Coastguard Worker 
1412*8b26181fSAndroid Build Coastguard Worker 	p->dlt_list[dlt_index++] = DLT_ERF;
1413*8b26181fSAndroid Build Coastguard Worker 
1414*8b26181fSAndroid Build Coastguard Worker 	p->dlt_count = dlt_index;
1415*8b26181fSAndroid Build Coastguard Worker 
1416*8b26181fSAndroid Build Coastguard Worker 	if(!p->linktype)
1417*8b26181fSAndroid Build Coastguard Worker 		p->linktype = DLT_ERF;
1418*8b26181fSAndroid Build Coastguard Worker 
1419*8b26181fSAndroid Build Coastguard Worker 	return p->linktype;
1420*8b26181fSAndroid Build Coastguard Worker }
1421*8b26181fSAndroid Build Coastguard Worker 
1422*8b26181fSAndroid Build Coastguard Worker #ifdef DAG_ONLY
1423*8b26181fSAndroid Build Coastguard Worker /*
1424*8b26181fSAndroid Build Coastguard Worker  * This libpcap build supports only DAG cards, not regular network
1425*8b26181fSAndroid Build Coastguard Worker  * interfaces.
1426*8b26181fSAndroid Build Coastguard Worker  */
1427*8b26181fSAndroid Build Coastguard Worker 
1428*8b26181fSAndroid Build Coastguard Worker /*
1429*8b26181fSAndroid Build Coastguard Worker  * There are no regular interfaces, just DAG interfaces.
1430*8b26181fSAndroid Build Coastguard Worker  */
1431*8b26181fSAndroid Build Coastguard Worker int
1432*8b26181fSAndroid Build Coastguard Worker pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf)
1433*8b26181fSAndroid Build Coastguard Worker {
1434*8b26181fSAndroid Build Coastguard Worker 	return (0);
1435*8b26181fSAndroid Build Coastguard Worker }
1436*8b26181fSAndroid Build Coastguard Worker 
1437*8b26181fSAndroid Build Coastguard Worker /*
1438*8b26181fSAndroid Build Coastguard Worker  * Attempts to open a regular interface fail.
1439*8b26181fSAndroid Build Coastguard Worker  */
1440*8b26181fSAndroid Build Coastguard Worker pcap_t *
1441*8b26181fSAndroid Build Coastguard Worker pcap_create_interface(const char *device, char *errbuf)
1442*8b26181fSAndroid Build Coastguard Worker {
1443*8b26181fSAndroid Build Coastguard Worker 	snprintf(errbuf, PCAP_ERRBUF_SIZE,
1444*8b26181fSAndroid Build Coastguard Worker 	    "This version of libpcap only supports DAG cards");
1445*8b26181fSAndroid Build Coastguard Worker 	return NULL;
1446*8b26181fSAndroid Build Coastguard Worker }
1447*8b26181fSAndroid Build Coastguard Worker 
1448*8b26181fSAndroid Build Coastguard Worker /*
1449*8b26181fSAndroid Build Coastguard Worker  * Libpcap version string.
1450*8b26181fSAndroid Build Coastguard Worker  */
1451*8b26181fSAndroid Build Coastguard Worker const char *
1452*8b26181fSAndroid Build Coastguard Worker pcap_lib_version(void)
1453*8b26181fSAndroid Build Coastguard Worker {
1454*8b26181fSAndroid Build Coastguard Worker 	return (PCAP_VERSION_STRING " (DAG-only)");
1455*8b26181fSAndroid Build Coastguard Worker }
1456*8b26181fSAndroid Build Coastguard Worker #endif
1457