xref: /aosp_15_r20/external/libpcap/pcap-libdlpi.c (revision 8b26181f966a6af5cf6981a6f474313de533bb28)
1*8b26181fSAndroid Build Coastguard Worker /*
2*8b26181fSAndroid Build Coastguard Worker  * Copyright (c) 1993, 1994, 1995, 1996, 1997
3*8b26181fSAndroid Build Coastguard Worker  *	The Regents of the University of California.  All rights reserved.
4*8b26181fSAndroid Build Coastguard Worker  *
5*8b26181fSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*8b26181fSAndroid Build Coastguard Worker  * modification, are permitted provided that: (1) source code distributions
7*8b26181fSAndroid Build Coastguard Worker  * retain the above copyright notice and this paragraph in its entirety, (2)
8*8b26181fSAndroid Build Coastguard Worker  * distributions including binary code include the above copyright notice and
9*8b26181fSAndroid Build Coastguard Worker  * this paragraph in its entirety in the documentation or other materials
10*8b26181fSAndroid Build Coastguard Worker  * provided with the distribution, and (3) all advertising materials mentioning
11*8b26181fSAndroid Build Coastguard Worker  * features or use of this software display the following acknowledgement:
12*8b26181fSAndroid Build Coastguard Worker  * ``This product includes software developed by the University of California,
13*8b26181fSAndroid Build Coastguard Worker  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*8b26181fSAndroid Build Coastguard Worker  * the University nor the names of its contributors may be used to endorse
15*8b26181fSAndroid Build Coastguard Worker  * or promote products derived from this software without specific prior
16*8b26181fSAndroid Build Coastguard Worker  * written permission.
17*8b26181fSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*8b26181fSAndroid Build Coastguard Worker  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*8b26181fSAndroid Build Coastguard Worker  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*8b26181fSAndroid Build Coastguard Worker  *
21*8b26181fSAndroid Build Coastguard Worker  * This code contributed by Sagun Shakya ([email protected])
22*8b26181fSAndroid Build Coastguard Worker  */
23*8b26181fSAndroid Build Coastguard Worker /*
24*8b26181fSAndroid Build Coastguard Worker  * Packet capture routines for DLPI using libdlpi under SunOS 5.11.
25*8b26181fSAndroid Build Coastguard Worker  */
26*8b26181fSAndroid Build Coastguard Worker 
27*8b26181fSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
28*8b26181fSAndroid Build Coastguard Worker #include <config.h>
29*8b26181fSAndroid Build Coastguard Worker #endif
30*8b26181fSAndroid Build Coastguard Worker 
31*8b26181fSAndroid Build Coastguard Worker #include <sys/types.h>
32*8b26181fSAndroid Build Coastguard Worker #include <sys/time.h>
33*8b26181fSAndroid Build Coastguard Worker #include <sys/bufmod.h>
34*8b26181fSAndroid Build Coastguard Worker #include <sys/stream.h>
35*8b26181fSAndroid Build Coastguard Worker #include <libdlpi.h>
36*8b26181fSAndroid Build Coastguard Worker #include <errno.h>
37*8b26181fSAndroid Build Coastguard Worker #include <memory.h>
38*8b26181fSAndroid Build Coastguard Worker #include <stropts.h>
39*8b26181fSAndroid Build Coastguard Worker #include <stdio.h>
40*8b26181fSAndroid Build Coastguard Worker #include <stdlib.h>
41*8b26181fSAndroid Build Coastguard Worker #include <string.h>
42*8b26181fSAndroid Build Coastguard Worker 
43*8b26181fSAndroid Build Coastguard Worker #include "pcap-int.h"
44*8b26181fSAndroid Build Coastguard Worker #include "dlpisubs.h"
45*8b26181fSAndroid Build Coastguard Worker 
46*8b26181fSAndroid Build Coastguard Worker /* Forwards. */
47*8b26181fSAndroid Build Coastguard Worker static int dlpromiscon(pcap_t *, bpf_u_int32);
48*8b26181fSAndroid Build Coastguard Worker static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *);
49*8b26181fSAndroid Build Coastguard Worker static int pcap_inject_libdlpi(pcap_t *, const void *, int);
50*8b26181fSAndroid Build Coastguard Worker static void pcap_libdlpi_err(const char *, const char *, int, char *);
51*8b26181fSAndroid Build Coastguard Worker static void pcap_cleanup_libdlpi(pcap_t *);
52*8b26181fSAndroid Build Coastguard Worker 
53*8b26181fSAndroid Build Coastguard Worker /*
54*8b26181fSAndroid Build Coastguard Worker  * list_interfaces() will list all the network links that are
55*8b26181fSAndroid Build Coastguard Worker  * available on a system.
56*8b26181fSAndroid Build Coastguard Worker  */
57*8b26181fSAndroid Build Coastguard Worker static boolean_t list_interfaces(const char *, void *);
58*8b26181fSAndroid Build Coastguard Worker 
59*8b26181fSAndroid Build Coastguard Worker typedef struct linknamelist {
60*8b26181fSAndroid Build Coastguard Worker 	char	linkname[DLPI_LINKNAME_MAX];
61*8b26181fSAndroid Build Coastguard Worker 	struct linknamelist *lnl_next;
62*8b26181fSAndroid Build Coastguard Worker } linknamelist_t;
63*8b26181fSAndroid Build Coastguard Worker 
64*8b26181fSAndroid Build Coastguard Worker typedef struct linkwalk {
65*8b26181fSAndroid Build Coastguard Worker 	linknamelist_t	*lw_list;
66*8b26181fSAndroid Build Coastguard Worker 	int		lw_err;
67*8b26181fSAndroid Build Coastguard Worker } linkwalk_t;
68*8b26181fSAndroid Build Coastguard Worker 
69*8b26181fSAndroid Build Coastguard Worker /*
70*8b26181fSAndroid Build Coastguard Worker  * The caller of this function should free the memory allocated
71*8b26181fSAndroid Build Coastguard Worker  * for each linknamelist_t "entry" allocated.
72*8b26181fSAndroid Build Coastguard Worker  */
73*8b26181fSAndroid Build Coastguard Worker static boolean_t
list_interfaces(const char * linkname,void * arg)74*8b26181fSAndroid Build Coastguard Worker list_interfaces(const char *linkname, void *arg)
75*8b26181fSAndroid Build Coastguard Worker {
76*8b26181fSAndroid Build Coastguard Worker 	linkwalk_t	*lwp = arg;
77*8b26181fSAndroid Build Coastguard Worker 	linknamelist_t	*entry;
78*8b26181fSAndroid Build Coastguard Worker 
79*8b26181fSAndroid Build Coastguard Worker 	if ((entry = calloc(1, sizeof(linknamelist_t))) == NULL) {
80*8b26181fSAndroid Build Coastguard Worker 		lwp->lw_err = ENOMEM;
81*8b26181fSAndroid Build Coastguard Worker 		return (B_TRUE);
82*8b26181fSAndroid Build Coastguard Worker 	}
83*8b26181fSAndroid Build Coastguard Worker 	(void) pcap_strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
84*8b26181fSAndroid Build Coastguard Worker 
85*8b26181fSAndroid Build Coastguard Worker 	if (lwp->lw_list == NULL) {
86*8b26181fSAndroid Build Coastguard Worker 		lwp->lw_list = entry;
87*8b26181fSAndroid Build Coastguard Worker 	} else {
88*8b26181fSAndroid Build Coastguard Worker 		entry->lnl_next = lwp->lw_list;
89*8b26181fSAndroid Build Coastguard Worker 		lwp->lw_list = entry;
90*8b26181fSAndroid Build Coastguard Worker 	}
91*8b26181fSAndroid Build Coastguard Worker 
92*8b26181fSAndroid Build Coastguard Worker 	return (B_FALSE);
93*8b26181fSAndroid Build Coastguard Worker }
94*8b26181fSAndroid Build Coastguard Worker 
95*8b26181fSAndroid Build Coastguard Worker static int
pcap_activate_libdlpi(pcap_t * p)96*8b26181fSAndroid Build Coastguard Worker pcap_activate_libdlpi(pcap_t *p)
97*8b26181fSAndroid Build Coastguard Worker {
98*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dlpi *pd = p->priv;
99*8b26181fSAndroid Build Coastguard Worker 	int status = 0;
100*8b26181fSAndroid Build Coastguard Worker 	int retv;
101*8b26181fSAndroid Build Coastguard Worker 	dlpi_handle_t dh;
102*8b26181fSAndroid Build Coastguard Worker 	dlpi_info_t dlinfo;
103*8b26181fSAndroid Build Coastguard Worker 
104*8b26181fSAndroid Build Coastguard Worker 	/*
105*8b26181fSAndroid Build Coastguard Worker 	 * Enable Solaris raw and passive DLPI extensions;
106*8b26181fSAndroid Build Coastguard Worker 	 * dlpi_open() will not fail if the underlying link does not support
107*8b26181fSAndroid Build Coastguard Worker 	 * passive mode. See dlpi(7P) for details.
108*8b26181fSAndroid Build Coastguard Worker 	 */
109*8b26181fSAndroid Build Coastguard Worker 	retv = dlpi_open(p->opt.device, &dh, DLPI_RAW|DLPI_PASSIVE);
110*8b26181fSAndroid Build Coastguard Worker 	if (retv != DLPI_SUCCESS) {
111*8b26181fSAndroid Build Coastguard Worker 		if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK) {
112*8b26181fSAndroid Build Coastguard Worker 			/*
113*8b26181fSAndroid Build Coastguard Worker 			 * There's nothing more to say, so clear the
114*8b26181fSAndroid Build Coastguard Worker 			 * error message.
115*8b26181fSAndroid Build Coastguard Worker 			 */
116*8b26181fSAndroid Build Coastguard Worker 			status = PCAP_ERROR_NO_SUCH_DEVICE;
117*8b26181fSAndroid Build Coastguard Worker 			p->errbuf[0] = '\0';
118*8b26181fSAndroid Build Coastguard Worker 		} else if (retv == DL_SYSERR &&
119*8b26181fSAndroid Build Coastguard Worker 		    (errno == EPERM || errno == EACCES)) {
120*8b26181fSAndroid Build Coastguard Worker 			status = PCAP_ERROR_PERM_DENIED;
121*8b26181fSAndroid Build Coastguard Worker 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
122*8b26181fSAndroid Build Coastguard Worker 			    "Attempt to open DLPI device failed with %s - root privilege may be required",
123*8b26181fSAndroid Build Coastguard Worker 			    (errno == EPERM) ? "EPERM" : "EACCES");
124*8b26181fSAndroid Build Coastguard Worker 		} else {
125*8b26181fSAndroid Build Coastguard Worker 			status = PCAP_ERROR;
126*8b26181fSAndroid Build Coastguard Worker 			pcap_libdlpi_err(p->opt.device, "dlpi_open", retv,
127*8b26181fSAndroid Build Coastguard Worker 			    p->errbuf);
128*8b26181fSAndroid Build Coastguard Worker 		}
129*8b26181fSAndroid Build Coastguard Worker 		return (status);
130*8b26181fSAndroid Build Coastguard Worker 	}
131*8b26181fSAndroid Build Coastguard Worker 	pd->dlpi_hd = dh;
132*8b26181fSAndroid Build Coastguard Worker 
133*8b26181fSAndroid Build Coastguard Worker 	if (p->opt.rfmon) {
134*8b26181fSAndroid Build Coastguard Worker 		/*
135*8b26181fSAndroid Build Coastguard Worker 		 * This device exists, but we don't support monitor mode
136*8b26181fSAndroid Build Coastguard Worker 		 * any platforms that support DLPI.
137*8b26181fSAndroid Build Coastguard Worker 		 */
138*8b26181fSAndroid Build Coastguard Worker 		status = PCAP_ERROR_RFMON_NOTSUP;
139*8b26181fSAndroid Build Coastguard Worker 		goto bad;
140*8b26181fSAndroid Build Coastguard Worker 	}
141*8b26181fSAndroid Build Coastguard Worker 
142*8b26181fSAndroid Build Coastguard Worker 	/* Bind with DLPI_ANY_SAP. */
143*8b26181fSAndroid Build Coastguard Worker 	if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
144*8b26181fSAndroid Build Coastguard Worker 		status = PCAP_ERROR;
145*8b26181fSAndroid Build Coastguard Worker 		pcap_libdlpi_err(p->opt.device, "dlpi_bind", retv, p->errbuf);
146*8b26181fSAndroid Build Coastguard Worker 		goto bad;
147*8b26181fSAndroid Build Coastguard Worker 	}
148*8b26181fSAndroid Build Coastguard Worker 
149*8b26181fSAndroid Build Coastguard Worker 	/*
150*8b26181fSAndroid Build Coastguard Worker 	 * Turn a negative snapshot value (invalid), a snapshot value of
151*8b26181fSAndroid Build Coastguard Worker 	 * 0 (unspecified), or a value bigger than the normal maximum
152*8b26181fSAndroid Build Coastguard Worker 	 * value, into the maximum allowed value.
153*8b26181fSAndroid Build Coastguard Worker 	 *
154*8b26181fSAndroid Build Coastguard Worker 	 * If some application really *needs* a bigger snapshot
155*8b26181fSAndroid Build Coastguard Worker 	 * length, we should just increase MAXIMUM_SNAPLEN.
156*8b26181fSAndroid Build Coastguard Worker 	 */
157*8b26181fSAndroid Build Coastguard Worker 	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
158*8b26181fSAndroid Build Coastguard Worker 		p->snapshot = MAXIMUM_SNAPLEN;
159*8b26181fSAndroid Build Coastguard Worker 
160*8b26181fSAndroid Build Coastguard Worker 	/* Enable promiscuous mode. */
161*8b26181fSAndroid Build Coastguard Worker 	if (p->opt.promisc) {
162*8b26181fSAndroid Build Coastguard Worker 		retv = dlpromiscon(p, DL_PROMISC_PHYS);
163*8b26181fSAndroid Build Coastguard Worker 		if (retv < 0) {
164*8b26181fSAndroid Build Coastguard Worker 			/*
165*8b26181fSAndroid Build Coastguard Worker 			 * "You don't have permission to capture on
166*8b26181fSAndroid Build Coastguard Worker 			 * this device" and "you don't have permission
167*8b26181fSAndroid Build Coastguard Worker 			 * to capture in promiscuous mode on this
168*8b26181fSAndroid Build Coastguard Worker 			 * device" are different; let the user know,
169*8b26181fSAndroid Build Coastguard Worker 			 * so if they can't get permission to
170*8b26181fSAndroid Build Coastguard Worker 			 * capture in promiscuous mode, they can at
171*8b26181fSAndroid Build Coastguard Worker 			 * least try to capture in non-promiscuous
172*8b26181fSAndroid Build Coastguard Worker 			 * mode.
173*8b26181fSAndroid Build Coastguard Worker 			 *
174*8b26181fSAndroid Build Coastguard Worker 			 * XXX - you might have to capture in
175*8b26181fSAndroid Build Coastguard Worker 			 * promiscuous mode to see outgoing packets.
176*8b26181fSAndroid Build Coastguard Worker 			 */
177*8b26181fSAndroid Build Coastguard Worker 			if (retv == PCAP_ERROR_PERM_DENIED)
178*8b26181fSAndroid Build Coastguard Worker 				status = PCAP_ERROR_PROMISC_PERM_DENIED;
179*8b26181fSAndroid Build Coastguard Worker 			else
180*8b26181fSAndroid Build Coastguard Worker 				status = retv;
181*8b26181fSAndroid Build Coastguard Worker 			goto bad;
182*8b26181fSAndroid Build Coastguard Worker 		}
183*8b26181fSAndroid Build Coastguard Worker 	} else {
184*8b26181fSAndroid Build Coastguard Worker 		/* Try to enable multicast. */
185*8b26181fSAndroid Build Coastguard Worker 		retv = dlpromiscon(p, DL_PROMISC_MULTI);
186*8b26181fSAndroid Build Coastguard Worker 		if (retv < 0) {
187*8b26181fSAndroid Build Coastguard Worker 			status = retv;
188*8b26181fSAndroid Build Coastguard Worker 			goto bad;
189*8b26181fSAndroid Build Coastguard Worker 		}
190*8b26181fSAndroid Build Coastguard Worker 	}
191*8b26181fSAndroid Build Coastguard Worker 
192*8b26181fSAndroid Build Coastguard Worker 	/* Try to enable SAP promiscuity. */
193*8b26181fSAndroid Build Coastguard Worker 	retv = dlpromiscon(p, DL_PROMISC_SAP);
194*8b26181fSAndroid Build Coastguard Worker 	if (retv < 0) {
195*8b26181fSAndroid Build Coastguard Worker 		/*
196*8b26181fSAndroid Build Coastguard Worker 		 * Not fatal, since the DL_PROMISC_PHYS mode worked.
197*8b26181fSAndroid Build Coastguard Worker 		 * Report it as a warning, however.
198*8b26181fSAndroid Build Coastguard Worker 		 */
199*8b26181fSAndroid Build Coastguard Worker 		if (p->opt.promisc)
200*8b26181fSAndroid Build Coastguard Worker 			status = PCAP_WARNING;
201*8b26181fSAndroid Build Coastguard Worker 		else {
202*8b26181fSAndroid Build Coastguard Worker 			status = retv;
203*8b26181fSAndroid Build Coastguard Worker 			goto bad;
204*8b26181fSAndroid Build Coastguard Worker 		}
205*8b26181fSAndroid Build Coastguard Worker 	}
206*8b26181fSAndroid Build Coastguard Worker 
207*8b26181fSAndroid Build Coastguard Worker 	/* Determine link type.  */
208*8b26181fSAndroid Build Coastguard Worker 	if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
209*8b26181fSAndroid Build Coastguard Worker 		status = PCAP_ERROR;
210*8b26181fSAndroid Build Coastguard Worker 		pcap_libdlpi_err(p->opt.device, "dlpi_info", retv, p->errbuf);
211*8b26181fSAndroid Build Coastguard Worker 		goto bad;
212*8b26181fSAndroid Build Coastguard Worker 	}
213*8b26181fSAndroid Build Coastguard Worker 
214*8b26181fSAndroid Build Coastguard Worker 	if (pcap_process_mactype(p, dlinfo.di_mactype) != 0) {
215*8b26181fSAndroid Build Coastguard Worker 		status = PCAP_ERROR;
216*8b26181fSAndroid Build Coastguard Worker 		goto bad;
217*8b26181fSAndroid Build Coastguard Worker 	}
218*8b26181fSAndroid Build Coastguard Worker 
219*8b26181fSAndroid Build Coastguard Worker 	p->fd = dlpi_fd(pd->dlpi_hd);
220*8b26181fSAndroid Build Coastguard Worker 
221*8b26181fSAndroid Build Coastguard Worker 	/* Push and configure bufmod. */
222*8b26181fSAndroid Build Coastguard Worker 	if (pcap_conf_bufmod(p, p->snapshot) != 0) {
223*8b26181fSAndroid Build Coastguard Worker 		status = PCAP_ERROR;
224*8b26181fSAndroid Build Coastguard Worker 		goto bad;
225*8b26181fSAndroid Build Coastguard Worker 	}
226*8b26181fSAndroid Build Coastguard Worker 
227*8b26181fSAndroid Build Coastguard Worker 	/*
228*8b26181fSAndroid Build Coastguard Worker 	 * Flush the read side.
229*8b26181fSAndroid Build Coastguard Worker 	 */
230*8b26181fSAndroid Build Coastguard Worker 	if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
231*8b26181fSAndroid Build Coastguard Worker 		status = PCAP_ERROR;
232*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
233*8b26181fSAndroid Build Coastguard Worker 		    errno, "FLUSHR");
234*8b26181fSAndroid Build Coastguard Worker 		goto bad;
235*8b26181fSAndroid Build Coastguard Worker 	}
236*8b26181fSAndroid Build Coastguard Worker 
237*8b26181fSAndroid Build Coastguard Worker 	/* Allocate data buffer. */
238*8b26181fSAndroid Build Coastguard Worker 	if (pcap_alloc_databuf(p) != 0) {
239*8b26181fSAndroid Build Coastguard Worker 		status = PCAP_ERROR;
240*8b26181fSAndroid Build Coastguard Worker 		goto bad;
241*8b26181fSAndroid Build Coastguard Worker 	}
242*8b26181fSAndroid Build Coastguard Worker 
243*8b26181fSAndroid Build Coastguard Worker 	/*
244*8b26181fSAndroid Build Coastguard Worker 	 * "p->fd" is a FD for a STREAMS device, so "select()" and
245*8b26181fSAndroid Build Coastguard Worker 	 * "poll()" should work on it.
246*8b26181fSAndroid Build Coastguard Worker 	 */
247*8b26181fSAndroid Build Coastguard Worker 	p->selectable_fd = p->fd;
248*8b26181fSAndroid Build Coastguard Worker 
249*8b26181fSAndroid Build Coastguard Worker 	p->read_op = pcap_read_libdlpi;
250*8b26181fSAndroid Build Coastguard Worker 	p->inject_op = pcap_inject_libdlpi;
251*8b26181fSAndroid Build Coastguard Worker 	p->setfilter_op = install_bpf_program;	/* No kernel filtering */
252*8b26181fSAndroid Build Coastguard Worker 	p->setdirection_op = NULL;	/* Not implemented */
253*8b26181fSAndroid Build Coastguard Worker 	p->set_datalink_op = NULL;	/* Can't change data link type */
254*8b26181fSAndroid Build Coastguard Worker 	p->getnonblock_op = pcap_getnonblock_fd;
255*8b26181fSAndroid Build Coastguard Worker 	p->setnonblock_op = pcap_setnonblock_fd;
256*8b26181fSAndroid Build Coastguard Worker 	p->stats_op = pcap_stats_dlpi;
257*8b26181fSAndroid Build Coastguard Worker 	p->cleanup_op = pcap_cleanup_libdlpi;
258*8b26181fSAndroid Build Coastguard Worker 
259*8b26181fSAndroid Build Coastguard Worker 	return (status);
260*8b26181fSAndroid Build Coastguard Worker bad:
261*8b26181fSAndroid Build Coastguard Worker 	pcap_cleanup_libdlpi(p);
262*8b26181fSAndroid Build Coastguard Worker 	return (status);
263*8b26181fSAndroid Build Coastguard Worker }
264*8b26181fSAndroid Build Coastguard Worker 
265*8b26181fSAndroid Build Coastguard Worker #define STRINGIFY(n)	#n
266*8b26181fSAndroid Build Coastguard Worker 
267*8b26181fSAndroid Build Coastguard Worker static int
dlpromiscon(pcap_t * p,bpf_u_int32 level)268*8b26181fSAndroid Build Coastguard Worker dlpromiscon(pcap_t *p, bpf_u_int32 level)
269*8b26181fSAndroid Build Coastguard Worker {
270*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dlpi *pd = p->priv;
271*8b26181fSAndroid Build Coastguard Worker 	int retv;
272*8b26181fSAndroid Build Coastguard Worker 	int err;
273*8b26181fSAndroid Build Coastguard Worker 
274*8b26181fSAndroid Build Coastguard Worker 	retv = dlpi_promiscon(pd->dlpi_hd, level);
275*8b26181fSAndroid Build Coastguard Worker 	if (retv != DLPI_SUCCESS) {
276*8b26181fSAndroid Build Coastguard Worker 		if (retv == DL_SYSERR &&
277*8b26181fSAndroid Build Coastguard Worker 		    (errno == EPERM || errno == EACCES)) {
278*8b26181fSAndroid Build Coastguard Worker 			if (level == DL_PROMISC_PHYS) {
279*8b26181fSAndroid Build Coastguard Worker 				err = PCAP_ERROR_PROMISC_PERM_DENIED;
280*8b26181fSAndroid Build Coastguard Worker 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
281*8b26181fSAndroid Build Coastguard Worker 				    "Attempt to set promiscuous mode failed with %s - root privilege may be required",
282*8b26181fSAndroid Build Coastguard Worker 				    (errno == EPERM) ? "EPERM" : "EACCES");
283*8b26181fSAndroid Build Coastguard Worker 			} else {
284*8b26181fSAndroid Build Coastguard Worker 				err = PCAP_ERROR_PERM_DENIED;
285*8b26181fSAndroid Build Coastguard Worker 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
286*8b26181fSAndroid Build Coastguard Worker 				    "Attempt to set %s mode failed with %s - root privilege may be required",
287*8b26181fSAndroid Build Coastguard Worker 				    (level == DL_PROMISC_MULTI) ? "multicast" : "SAP promiscuous",
288*8b26181fSAndroid Build Coastguard Worker 				    (errno == EPERM) ? "EPERM" : "EACCES");
289*8b26181fSAndroid Build Coastguard Worker 			}
290*8b26181fSAndroid Build Coastguard Worker 		} else {
291*8b26181fSAndroid Build Coastguard Worker 			err = PCAP_ERROR;
292*8b26181fSAndroid Build Coastguard Worker 			pcap_libdlpi_err(p->opt.device,
293*8b26181fSAndroid Build Coastguard Worker 			    "dlpi_promiscon" STRINGIFY(level),
294*8b26181fSAndroid Build Coastguard Worker 			    retv, p->errbuf);
295*8b26181fSAndroid Build Coastguard Worker 		}
296*8b26181fSAndroid Build Coastguard Worker 		return (err);
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 /*
302*8b26181fSAndroid Build Coastguard Worker  * Presumably everything returned by dlpi_walk() is a DLPI device,
303*8b26181fSAndroid Build Coastguard Worker  * so there's no work to be done here to check whether name refers
304*8b26181fSAndroid Build Coastguard Worker  * to a DLPI device.
305*8b26181fSAndroid Build Coastguard Worker  */
306*8b26181fSAndroid Build Coastguard Worker static int
is_dlpi_interface(const char * name _U_)307*8b26181fSAndroid Build Coastguard Worker is_dlpi_interface(const char *name _U_)
308*8b26181fSAndroid Build Coastguard Worker {
309*8b26181fSAndroid Build Coastguard Worker 	return (1);
310*8b26181fSAndroid Build Coastguard Worker }
311*8b26181fSAndroid Build Coastguard Worker 
312*8b26181fSAndroid Build Coastguard Worker static int
get_if_flags(const char * name _U_,bpf_u_int32 * flags _U_,char * errbuf _U_)313*8b26181fSAndroid Build Coastguard Worker get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
314*8b26181fSAndroid Build Coastguard Worker {
315*8b26181fSAndroid Build Coastguard Worker 	/*
316*8b26181fSAndroid Build Coastguard Worker 	 * Nothing we can do other than mark loopback devices as "the
317*8b26181fSAndroid Build Coastguard Worker 	 * connected/disconnected status doesn't apply".
318*8b26181fSAndroid Build Coastguard Worker 	 *
319*8b26181fSAndroid Build Coastguard Worker 	 * XXX - on Solaris, can we do what the dladm command does,
320*8b26181fSAndroid Build Coastguard Worker 	 * i.e. get a connected/disconnected indication from a kstat?
321*8b26181fSAndroid Build Coastguard Worker 	 * (Note that you can also get the link speed, and possibly
322*8b26181fSAndroid Build Coastguard Worker 	 * other information, from a kstat as well.)
323*8b26181fSAndroid Build Coastguard Worker 	 */
324*8b26181fSAndroid Build Coastguard Worker 	if (*flags & PCAP_IF_LOOPBACK) {
325*8b26181fSAndroid Build Coastguard Worker 		/*
326*8b26181fSAndroid Build Coastguard Worker 		 * Loopback devices aren't wireless, and "connected"/
327*8b26181fSAndroid Build Coastguard Worker 		 * "disconnected" doesn't apply to them.
328*8b26181fSAndroid Build Coastguard Worker 		 */
329*8b26181fSAndroid Build Coastguard Worker 		*flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
330*8b26181fSAndroid Build Coastguard Worker 		return (0);
331*8b26181fSAndroid Build Coastguard Worker 	}
332*8b26181fSAndroid Build Coastguard Worker 	return (0);
333*8b26181fSAndroid Build Coastguard Worker }
334*8b26181fSAndroid Build Coastguard Worker 
335*8b26181fSAndroid Build Coastguard Worker /*
336*8b26181fSAndroid Build Coastguard Worker  * In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
337*8b26181fSAndroid Build Coastguard Worker  * network links that are plumbed and are up. dlpi_walk(3DLPI) will find
338*8b26181fSAndroid Build Coastguard Worker  * additional network links present in the system.
339*8b26181fSAndroid Build Coastguard Worker  */
340*8b26181fSAndroid Build Coastguard Worker int
pcap_platform_finddevs(pcap_if_list_t * devlistp,char * errbuf)341*8b26181fSAndroid Build Coastguard Worker pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
342*8b26181fSAndroid Build Coastguard Worker {
343*8b26181fSAndroid Build Coastguard Worker 	int retv = 0;
344*8b26181fSAndroid Build Coastguard Worker 
345*8b26181fSAndroid Build Coastguard Worker 	linknamelist_t	*entry, *next;
346*8b26181fSAndroid Build Coastguard Worker 	linkwalk_t	lw = {NULL, 0};
347*8b26181fSAndroid Build Coastguard Worker 	int		save_errno;
348*8b26181fSAndroid Build Coastguard Worker 
349*8b26181fSAndroid Build Coastguard Worker 	/*
350*8b26181fSAndroid Build Coastguard Worker 	 * Get the list of regular interfaces first.
351*8b26181fSAndroid Build Coastguard Worker 	 */
352*8b26181fSAndroid Build Coastguard Worker 	if (pcap_findalldevs_interfaces(devlistp, errbuf,
353*8b26181fSAndroid Build Coastguard Worker 	    is_dlpi_interface, get_if_flags) == -1)
354*8b26181fSAndroid Build Coastguard Worker 		return (-1);	/* failure */
355*8b26181fSAndroid Build Coastguard Worker 
356*8b26181fSAndroid Build Coastguard Worker 	/* dlpi_walk() for loopback will be added here. */
357*8b26181fSAndroid Build Coastguard Worker 
358*8b26181fSAndroid Build Coastguard Worker 	/*
359*8b26181fSAndroid Build Coastguard Worker 	 * Find all DLPI devices in the current zone.
360*8b26181fSAndroid Build Coastguard Worker 	 *
361*8b26181fSAndroid Build Coastguard Worker 	 * XXX - will pcap_findalldevs_interfaces() find any devices
362*8b26181fSAndroid Build Coastguard Worker 	 * outside the current zone?  If not, the only reason to call
363*8b26181fSAndroid Build Coastguard Worker 	 * it would be to get the interface addresses.
364*8b26181fSAndroid Build Coastguard Worker 	 */
365*8b26181fSAndroid Build Coastguard Worker 	dlpi_walk(list_interfaces, &lw, 0);
366*8b26181fSAndroid Build Coastguard Worker 
367*8b26181fSAndroid Build Coastguard Worker 	if (lw.lw_err != 0) {
368*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
369*8b26181fSAndroid Build Coastguard Worker 		    lw.lw_err, "dlpi_walk");
370*8b26181fSAndroid Build Coastguard Worker 		retv = -1;
371*8b26181fSAndroid Build Coastguard Worker 		goto done;
372*8b26181fSAndroid Build Coastguard Worker 	}
373*8b26181fSAndroid Build Coastguard Worker 
374*8b26181fSAndroid Build Coastguard Worker 	/* Add linkname if it does not exist on the list. */
375*8b26181fSAndroid Build Coastguard Worker 	for (entry = lw.lw_list; entry != NULL; entry = entry->lnl_next) {
376*8b26181fSAndroid Build Coastguard Worker 		/*
377*8b26181fSAndroid Build Coastguard Worker 		 * If it isn't already in the list of devices, try to
378*8b26181fSAndroid Build Coastguard Worker 		 * add it.
379*8b26181fSAndroid Build Coastguard Worker 		 */
380*8b26181fSAndroid Build Coastguard Worker 		if (find_or_add_dev(devlistp, entry->linkname, 0, get_if_flags,
381*8b26181fSAndroid Build Coastguard Worker 		    NULL, errbuf) == NULL)
382*8b26181fSAndroid Build Coastguard Worker 			retv = -1;
383*8b26181fSAndroid Build Coastguard Worker 	}
384*8b26181fSAndroid Build Coastguard Worker done:
385*8b26181fSAndroid Build Coastguard Worker 	save_errno = errno;
386*8b26181fSAndroid Build Coastguard Worker 	for (entry = lw.lw_list; entry != NULL; entry = next) {
387*8b26181fSAndroid Build Coastguard Worker 		next = entry->lnl_next;
388*8b26181fSAndroid Build Coastguard Worker 		free(entry);
389*8b26181fSAndroid Build Coastguard Worker 	}
390*8b26181fSAndroid Build Coastguard Worker 	errno = save_errno;
391*8b26181fSAndroid Build Coastguard Worker 
392*8b26181fSAndroid Build Coastguard Worker 	return (retv);
393*8b26181fSAndroid Build Coastguard Worker }
394*8b26181fSAndroid Build Coastguard Worker 
395*8b26181fSAndroid Build Coastguard Worker /*
396*8b26181fSAndroid Build Coastguard Worker  * Read data received on DLPI handle. Returns -2 if told to terminate, else
397*8b26181fSAndroid Build Coastguard Worker  * returns the number of packets read.
398*8b26181fSAndroid Build Coastguard Worker  */
399*8b26181fSAndroid Build Coastguard Worker static int
pcap_read_libdlpi(pcap_t * p,int count,pcap_handler callback,u_char * user)400*8b26181fSAndroid Build Coastguard Worker pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
401*8b26181fSAndroid Build Coastguard Worker {
402*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dlpi *pd = p->priv;
403*8b26181fSAndroid Build Coastguard Worker 	int len;
404*8b26181fSAndroid Build Coastguard Worker 	u_char *bufp;
405*8b26181fSAndroid Build Coastguard Worker 	size_t msglen;
406*8b26181fSAndroid Build Coastguard Worker 	int retv;
407*8b26181fSAndroid Build Coastguard Worker 
408*8b26181fSAndroid Build Coastguard Worker 	len = p->cc;
409*8b26181fSAndroid Build Coastguard Worker 	if (len != 0) {
410*8b26181fSAndroid Build Coastguard Worker 		bufp = p->bp;
411*8b26181fSAndroid Build Coastguard Worker 		goto process_pkts;
412*8b26181fSAndroid Build Coastguard Worker 	}
413*8b26181fSAndroid Build Coastguard Worker 	do {
414*8b26181fSAndroid Build Coastguard Worker 		/* Has "pcap_breakloop()" been called? */
415*8b26181fSAndroid Build Coastguard Worker 		if (p->break_loop) {
416*8b26181fSAndroid Build Coastguard Worker 			/*
417*8b26181fSAndroid Build Coastguard Worker 			 * Yes - clear the flag that indicates that it has,
418*8b26181fSAndroid Build Coastguard Worker 			 * and return -2 to indicate that we were told to
419*8b26181fSAndroid Build Coastguard Worker 			 * break out of the loop.
420*8b26181fSAndroid Build Coastguard Worker 			 */
421*8b26181fSAndroid Build Coastguard Worker 			p->break_loop = 0;
422*8b26181fSAndroid Build Coastguard Worker 			return (-2);
423*8b26181fSAndroid Build Coastguard Worker 		}
424*8b26181fSAndroid Build Coastguard Worker 
425*8b26181fSAndroid Build Coastguard Worker 		msglen = p->bufsize;
426*8b26181fSAndroid Build Coastguard Worker 		bufp = (u_char *)p->buffer + p->offset;
427*8b26181fSAndroid Build Coastguard Worker 
428*8b26181fSAndroid Build Coastguard Worker 		retv = dlpi_recv(pd->dlpi_hd, NULL, NULL, bufp,
429*8b26181fSAndroid Build Coastguard Worker 		    &msglen, -1, NULL);
430*8b26181fSAndroid Build Coastguard Worker 		if (retv != DLPI_SUCCESS) {
431*8b26181fSAndroid Build Coastguard Worker 			/*
432*8b26181fSAndroid Build Coastguard Worker 			 * This is most likely a call to terminate out of the
433*8b26181fSAndroid Build Coastguard Worker 			 * loop. So, do not return an error message, instead
434*8b26181fSAndroid Build Coastguard Worker 			 * check if "pcap_breakloop()" has been called above.
435*8b26181fSAndroid Build Coastguard Worker 			 */
436*8b26181fSAndroid Build Coastguard Worker 			if (retv == DL_SYSERR && errno == EINTR) {
437*8b26181fSAndroid Build Coastguard Worker 				len = 0;
438*8b26181fSAndroid Build Coastguard Worker 				continue;
439*8b26181fSAndroid Build Coastguard Worker 			}
440*8b26181fSAndroid Build Coastguard Worker 			pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd),
441*8b26181fSAndroid Build Coastguard Worker 			    "dlpi_recv", retv, p->errbuf);
442*8b26181fSAndroid Build Coastguard Worker 			return (-1);
443*8b26181fSAndroid Build Coastguard Worker 		}
444*8b26181fSAndroid Build Coastguard Worker 		len = msglen;
445*8b26181fSAndroid Build Coastguard Worker 	} while (len == 0);
446*8b26181fSAndroid Build Coastguard Worker 
447*8b26181fSAndroid Build Coastguard Worker process_pkts:
448*8b26181fSAndroid Build Coastguard Worker 	return (pcap_process_pkts(p, callback, user, count, bufp, len));
449*8b26181fSAndroid Build Coastguard Worker }
450*8b26181fSAndroid Build Coastguard Worker 
451*8b26181fSAndroid Build Coastguard Worker static int
pcap_inject_libdlpi(pcap_t * p,const void * buf,int size)452*8b26181fSAndroid Build Coastguard Worker pcap_inject_libdlpi(pcap_t *p, const void *buf, int size)
453*8b26181fSAndroid Build Coastguard Worker {
454*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dlpi *pd = p->priv;
455*8b26181fSAndroid Build Coastguard Worker 	int retv;
456*8b26181fSAndroid Build Coastguard Worker 
457*8b26181fSAndroid Build Coastguard Worker 	retv = dlpi_send(pd->dlpi_hd, NULL, 0, buf, size, NULL);
458*8b26181fSAndroid Build Coastguard Worker 	if (retv != DLPI_SUCCESS) {
459*8b26181fSAndroid Build Coastguard Worker 		pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd), "dlpi_send", retv,
460*8b26181fSAndroid Build Coastguard Worker 		    p->errbuf);
461*8b26181fSAndroid Build Coastguard Worker 		return (-1);
462*8b26181fSAndroid Build Coastguard Worker 	}
463*8b26181fSAndroid Build Coastguard Worker 	/*
464*8b26181fSAndroid Build Coastguard Worker 	 * dlpi_send(3DLPI) does not provide a way to return the number of
465*8b26181fSAndroid Build Coastguard Worker 	 * bytes sent on the wire. Based on the fact that DLPI_SUCCESS was
466*8b26181fSAndroid Build Coastguard Worker 	 * returned we are assuming 'size' bytes were sent.
467*8b26181fSAndroid Build Coastguard Worker 	 */
468*8b26181fSAndroid Build Coastguard Worker 	return (size);
469*8b26181fSAndroid Build Coastguard Worker }
470*8b26181fSAndroid Build Coastguard Worker 
471*8b26181fSAndroid Build Coastguard Worker /*
472*8b26181fSAndroid Build Coastguard Worker  * Close dlpi handle.
473*8b26181fSAndroid Build Coastguard Worker  */
474*8b26181fSAndroid Build Coastguard Worker static void
pcap_cleanup_libdlpi(pcap_t * p)475*8b26181fSAndroid Build Coastguard Worker pcap_cleanup_libdlpi(pcap_t *p)
476*8b26181fSAndroid Build Coastguard Worker {
477*8b26181fSAndroid Build Coastguard Worker 	struct pcap_dlpi *pd = p->priv;
478*8b26181fSAndroid Build Coastguard Worker 
479*8b26181fSAndroid Build Coastguard Worker 	if (pd->dlpi_hd != NULL) {
480*8b26181fSAndroid Build Coastguard Worker 		dlpi_close(pd->dlpi_hd);
481*8b26181fSAndroid Build Coastguard Worker 		pd->dlpi_hd = NULL;
482*8b26181fSAndroid Build Coastguard Worker 		p->fd = -1;
483*8b26181fSAndroid Build Coastguard Worker 	}
484*8b26181fSAndroid Build Coastguard Worker 	pcap_cleanup_live_common(p);
485*8b26181fSAndroid Build Coastguard Worker }
486*8b26181fSAndroid Build Coastguard Worker 
487*8b26181fSAndroid Build Coastguard Worker /*
488*8b26181fSAndroid Build Coastguard Worker  * Write error message to buffer.
489*8b26181fSAndroid Build Coastguard Worker  */
490*8b26181fSAndroid Build Coastguard Worker static void
pcap_libdlpi_err(const char * linkname,const char * func,int err,char * errbuf)491*8b26181fSAndroid Build Coastguard Worker pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
492*8b26181fSAndroid Build Coastguard Worker {
493*8b26181fSAndroid Build Coastguard Worker 	snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
494*8b26181fSAndroid Build Coastguard Worker 	    func, linkname, dlpi_strerror(err));
495*8b26181fSAndroid Build Coastguard Worker }
496*8b26181fSAndroid Build Coastguard Worker 
497*8b26181fSAndroid Build Coastguard Worker pcap_t *
pcap_create_interface(const char * device _U_,char * ebuf)498*8b26181fSAndroid Build Coastguard Worker pcap_create_interface(const char *device _U_, char *ebuf)
499*8b26181fSAndroid Build Coastguard Worker {
500*8b26181fSAndroid Build Coastguard Worker 	pcap_t *p;
501*8b26181fSAndroid Build Coastguard Worker 
502*8b26181fSAndroid Build Coastguard Worker 	p = PCAP_CREATE_COMMON(ebuf, struct pcap_dlpi);
503*8b26181fSAndroid Build Coastguard Worker 	if (p == NULL)
504*8b26181fSAndroid Build Coastguard Worker 		return (NULL);
505*8b26181fSAndroid Build Coastguard Worker 
506*8b26181fSAndroid Build Coastguard Worker 	p->activate_op = pcap_activate_libdlpi;
507*8b26181fSAndroid Build Coastguard Worker 	return (p);
508*8b26181fSAndroid Build Coastguard Worker }
509*8b26181fSAndroid Build Coastguard Worker 
510*8b26181fSAndroid Build Coastguard Worker /*
511*8b26181fSAndroid Build Coastguard Worker  * Libpcap version string.
512*8b26181fSAndroid Build Coastguard Worker  */
513*8b26181fSAndroid Build Coastguard Worker const char *
pcap_lib_version(void)514*8b26181fSAndroid Build Coastguard Worker pcap_lib_version(void)
515*8b26181fSAndroid Build Coastguard Worker {
516*8b26181fSAndroid Build Coastguard Worker 	return (PCAP_VERSION_STRING);
517*8b26181fSAndroid Build Coastguard Worker }
518