xref: /minix3/external/bsd/libpcap/dist/pcap-libdlpi.c (revision d56f51ea7d8b9045e5c8e2028422523d3f9a5840)
1*d56f51eaSDavid van Moolenbroek /*	$NetBSD: pcap-libdlpi.c,v 1.2 2014/11/19 19:33:30 christos Exp $	*/
2*d56f51eaSDavid van Moolenbroek 
3*d56f51eaSDavid van Moolenbroek /*
4*d56f51eaSDavid van Moolenbroek  * Copyright (c) 1993, 1994, 1995, 1996, 1997
5*d56f51eaSDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
6*d56f51eaSDavid van Moolenbroek  *
7*d56f51eaSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
8*d56f51eaSDavid van Moolenbroek  * modification, are permitted provided that: (1) source code distributions
9*d56f51eaSDavid van Moolenbroek  * retain the above copyright notice and this paragraph in its entirety, (2)
10*d56f51eaSDavid van Moolenbroek  * distributions including binary code include the above copyright notice and
11*d56f51eaSDavid van Moolenbroek  * this paragraph in its entirety in the documentation or other materials
12*d56f51eaSDavid van Moolenbroek  * provided with the distribution, and (3) all advertising materials mentioning
13*d56f51eaSDavid van Moolenbroek  * features or use of this software display the following acknowledgement:
14*d56f51eaSDavid van Moolenbroek  * ``This product includes software developed by the University of California,
15*d56f51eaSDavid van Moolenbroek  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16*d56f51eaSDavid van Moolenbroek  * the University nor the names of its contributors may be used to endorse
17*d56f51eaSDavid van Moolenbroek  * or promote products derived from this software without specific prior
18*d56f51eaSDavid van Moolenbroek  * written permission.
19*d56f51eaSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20*d56f51eaSDavid van Moolenbroek  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21*d56f51eaSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22*d56f51eaSDavid van Moolenbroek  *
23*d56f51eaSDavid van Moolenbroek  * This code contributed by Sagun Shakya (sagun.shakya@sun.com)
24*d56f51eaSDavid van Moolenbroek  */
25*d56f51eaSDavid van Moolenbroek /*
26*d56f51eaSDavid van Moolenbroek  * Packet capture routines for DLPI using libdlpi under SunOS 5.11.
27*d56f51eaSDavid van Moolenbroek  */
28*d56f51eaSDavid van Moolenbroek 
29*d56f51eaSDavid van Moolenbroek #include <sys/cdefs.h>
30*d56f51eaSDavid van Moolenbroek __RCSID("$NetBSD: pcap-libdlpi.c,v 1.2 2014/11/19 19:33:30 christos Exp $");
31*d56f51eaSDavid van Moolenbroek 
32*d56f51eaSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
33*d56f51eaSDavid van Moolenbroek #include "config.h"
34*d56f51eaSDavid van Moolenbroek #endif
35*d56f51eaSDavid van Moolenbroek 
36*d56f51eaSDavid van Moolenbroek #include <sys/types.h>
37*d56f51eaSDavid van Moolenbroek #include <sys/time.h>
38*d56f51eaSDavid van Moolenbroek #include <sys/bufmod.h>
39*d56f51eaSDavid van Moolenbroek #include <sys/stream.h>
40*d56f51eaSDavid van Moolenbroek #include <libdlpi.h>
41*d56f51eaSDavid van Moolenbroek #include <errno.h>
42*d56f51eaSDavid van Moolenbroek #include <memory.h>
43*d56f51eaSDavid van Moolenbroek #include <stropts.h>
44*d56f51eaSDavid van Moolenbroek #include <stdio.h>
45*d56f51eaSDavid van Moolenbroek #include <stdlib.h>
46*d56f51eaSDavid van Moolenbroek #include <string.h>
47*d56f51eaSDavid van Moolenbroek 
48*d56f51eaSDavid van Moolenbroek #include "pcap-int.h"
49*d56f51eaSDavid van Moolenbroek #include "dlpisubs.h"
50*d56f51eaSDavid van Moolenbroek 
51*d56f51eaSDavid van Moolenbroek /* Forwards. */
52*d56f51eaSDavid van Moolenbroek static int dlpromiscon(pcap_t *, bpf_u_int32);
53*d56f51eaSDavid van Moolenbroek static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *);
54*d56f51eaSDavid van Moolenbroek static int pcap_inject_libdlpi(pcap_t *, const void *, size_t);
55*d56f51eaSDavid van Moolenbroek static void pcap_libdlpi_err(const char *, const char *, int, char *);
56*d56f51eaSDavid van Moolenbroek static void pcap_cleanup_libdlpi(pcap_t *);
57*d56f51eaSDavid van Moolenbroek 
58*d56f51eaSDavid van Moolenbroek /*
59*d56f51eaSDavid van Moolenbroek  * list_interfaces() will list all the network links that are
60*d56f51eaSDavid van Moolenbroek  * available on a system.
61*d56f51eaSDavid van Moolenbroek  */
62*d56f51eaSDavid van Moolenbroek static boolean_t list_interfaces(const char *, void *);
63*d56f51eaSDavid van Moolenbroek 
64*d56f51eaSDavid van Moolenbroek typedef struct linknamelist {
65*d56f51eaSDavid van Moolenbroek 	char	linkname[DLPI_LINKNAME_MAX];
66*d56f51eaSDavid van Moolenbroek 	struct linknamelist *lnl_next;
67*d56f51eaSDavid van Moolenbroek } linknamelist_t;
68*d56f51eaSDavid van Moolenbroek 
69*d56f51eaSDavid van Moolenbroek typedef struct linkwalk {
70*d56f51eaSDavid van Moolenbroek 	linknamelist_t	*lw_list;
71*d56f51eaSDavid van Moolenbroek 	int		lw_err;
72*d56f51eaSDavid van Moolenbroek } linkwalk_t;
73*d56f51eaSDavid van Moolenbroek 
74*d56f51eaSDavid van Moolenbroek /*
75*d56f51eaSDavid van Moolenbroek  * The caller of this function should free the memory allocated
76*d56f51eaSDavid van Moolenbroek  * for each linknamelist_t "entry" allocated.
77*d56f51eaSDavid van Moolenbroek  */
78*d56f51eaSDavid van Moolenbroek static boolean_t
list_interfaces(const char * linkname,void * arg)79*d56f51eaSDavid van Moolenbroek list_interfaces(const char *linkname, void *arg)
80*d56f51eaSDavid van Moolenbroek {
81*d56f51eaSDavid van Moolenbroek 	linkwalk_t	*lwp = arg;
82*d56f51eaSDavid van Moolenbroek 	linknamelist_t	*entry;
83*d56f51eaSDavid van Moolenbroek 
84*d56f51eaSDavid van Moolenbroek 	if ((entry = calloc(1, sizeof(linknamelist_t))) == NULL) {
85*d56f51eaSDavid van Moolenbroek 		lwp->lw_err = ENOMEM;
86*d56f51eaSDavid van Moolenbroek 		return (B_TRUE);
87*d56f51eaSDavid van Moolenbroek 	}
88*d56f51eaSDavid van Moolenbroek 	(void) strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
89*d56f51eaSDavid van Moolenbroek 
90*d56f51eaSDavid van Moolenbroek 	if (lwp->lw_list == NULL) {
91*d56f51eaSDavid van Moolenbroek 		lwp->lw_list = entry;
92*d56f51eaSDavid van Moolenbroek 	} else {
93*d56f51eaSDavid van Moolenbroek 		entry->lnl_next = lwp->lw_list;
94*d56f51eaSDavid van Moolenbroek 		lwp->lw_list = entry;
95*d56f51eaSDavid van Moolenbroek 	}
96*d56f51eaSDavid van Moolenbroek 
97*d56f51eaSDavid van Moolenbroek 	return (B_FALSE);
98*d56f51eaSDavid van Moolenbroek }
99*d56f51eaSDavid van Moolenbroek 
100*d56f51eaSDavid van Moolenbroek static int
pcap_activate_libdlpi(pcap_t * p)101*d56f51eaSDavid van Moolenbroek pcap_activate_libdlpi(pcap_t *p)
102*d56f51eaSDavid van Moolenbroek {
103*d56f51eaSDavid van Moolenbroek 	struct pcap_dlpi *pd = p->priv;
104*d56f51eaSDavid van Moolenbroek 	int status = 0;
105*d56f51eaSDavid van Moolenbroek 	int retv;
106*d56f51eaSDavid van Moolenbroek 	dlpi_handle_t dh;
107*d56f51eaSDavid van Moolenbroek 	dlpi_info_t dlinfo;
108*d56f51eaSDavid van Moolenbroek 
109*d56f51eaSDavid van Moolenbroek 	/*
110*d56f51eaSDavid van Moolenbroek 	 * Enable Solaris raw and passive DLPI extensions;
111*d56f51eaSDavid van Moolenbroek 	 * dlpi_open() will not fail if the underlying link does not support
112*d56f51eaSDavid van Moolenbroek 	 * passive mode. See dlpi(7P) for details.
113*d56f51eaSDavid van Moolenbroek 	 */
114*d56f51eaSDavid van Moolenbroek 	retv = dlpi_open(p->opt.source, &dh, DLPI_RAW|DLPI_PASSIVE);
115*d56f51eaSDavid van Moolenbroek 	if (retv != DLPI_SUCCESS) {
116*d56f51eaSDavid van Moolenbroek 		if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK)
117*d56f51eaSDavid van Moolenbroek 			status = PCAP_ERROR_NO_SUCH_DEVICE;
118*d56f51eaSDavid van Moolenbroek 		else if (retv == DL_SYSERR &&
119*d56f51eaSDavid van Moolenbroek 		    (errno == EPERM || errno == EACCES))
120*d56f51eaSDavid van Moolenbroek 			status = PCAP_ERROR_PERM_DENIED;
121*d56f51eaSDavid van Moolenbroek 		else
122*d56f51eaSDavid van Moolenbroek 			status = PCAP_ERROR;
123*d56f51eaSDavid van Moolenbroek 		pcap_libdlpi_err(p->opt.source, "dlpi_open", retv,
124*d56f51eaSDavid van Moolenbroek 		    p->errbuf);
125*d56f51eaSDavid van Moolenbroek 		return (status);
126*d56f51eaSDavid van Moolenbroek 	}
127*d56f51eaSDavid van Moolenbroek 	pd->dlpi_hd = dh;
128*d56f51eaSDavid van Moolenbroek 
129*d56f51eaSDavid van Moolenbroek 	if (p->opt.rfmon) {
130*d56f51eaSDavid van Moolenbroek 		/*
131*d56f51eaSDavid van Moolenbroek 		 * This device exists, but we don't support monitor mode
132*d56f51eaSDavid van Moolenbroek 		 * any platforms that support DLPI.
133*d56f51eaSDavid van Moolenbroek 		 */
134*d56f51eaSDavid van Moolenbroek 		status = PCAP_ERROR_RFMON_NOTSUP;
135*d56f51eaSDavid van Moolenbroek 		goto bad;
136*d56f51eaSDavid van Moolenbroek 	}
137*d56f51eaSDavid van Moolenbroek 
138*d56f51eaSDavid van Moolenbroek 	/* Bind with DLPI_ANY_SAP. */
139*d56f51eaSDavid van Moolenbroek 	if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
140*d56f51eaSDavid van Moolenbroek 		status = PCAP_ERROR;
141*d56f51eaSDavid van Moolenbroek 		pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf);
142*d56f51eaSDavid van Moolenbroek 		goto bad;
143*d56f51eaSDavid van Moolenbroek 	}
144*d56f51eaSDavid van Moolenbroek 
145*d56f51eaSDavid van Moolenbroek 	/* Enable promiscuous mode. */
146*d56f51eaSDavid van Moolenbroek 	if (p->opt.promisc) {
147*d56f51eaSDavid van Moolenbroek 		retv = dlpromiscon(p, DL_PROMISC_PHYS);
148*d56f51eaSDavid van Moolenbroek 		if (retv < 0) {
149*d56f51eaSDavid van Moolenbroek 			/*
150*d56f51eaSDavid van Moolenbroek 			 * "You don't have permission to capture on
151*d56f51eaSDavid van Moolenbroek 			 * this device" and "you don't have permission
152*d56f51eaSDavid van Moolenbroek 			 * to capture in promiscuous mode on this
153*d56f51eaSDavid van Moolenbroek 			 * device" are different; let the user know,
154*d56f51eaSDavid van Moolenbroek 			 * so if they can't get permission to
155*d56f51eaSDavid van Moolenbroek 			 * capture in promiscuous mode, they can at
156*d56f51eaSDavid van Moolenbroek 			 * least try to capture in non-promiscuous
157*d56f51eaSDavid van Moolenbroek 			 * mode.
158*d56f51eaSDavid van Moolenbroek 			 *
159*d56f51eaSDavid van Moolenbroek 			 * XXX - you might have to capture in
160*d56f51eaSDavid van Moolenbroek 			 * promiscuous mode to see outgoing packets.
161*d56f51eaSDavid van Moolenbroek 			 */
162*d56f51eaSDavid van Moolenbroek 			if (retv == PCAP_ERROR_PERM_DENIED)
163*d56f51eaSDavid van Moolenbroek 				status = PCAP_ERROR_PROMISC_PERM_DENIED;
164*d56f51eaSDavid van Moolenbroek 			else
165*d56f51eaSDavid van Moolenbroek 				status = retv;
166*d56f51eaSDavid van Moolenbroek 			goto bad;
167*d56f51eaSDavid van Moolenbroek 		}
168*d56f51eaSDavid van Moolenbroek 	} else {
169*d56f51eaSDavid van Moolenbroek 		/* Try to enable multicast. */
170*d56f51eaSDavid van Moolenbroek 		retv = dlpromiscon(p, DL_PROMISC_MULTI);
171*d56f51eaSDavid van Moolenbroek 		if (retv < 0) {
172*d56f51eaSDavid van Moolenbroek 			status = retv;
173*d56f51eaSDavid van Moolenbroek 			goto bad;
174*d56f51eaSDavid van Moolenbroek 		}
175*d56f51eaSDavid van Moolenbroek 	}
176*d56f51eaSDavid van Moolenbroek 
177*d56f51eaSDavid van Moolenbroek 	/* Try to enable SAP promiscuity. */
178*d56f51eaSDavid van Moolenbroek 	retv = dlpromiscon(p, DL_PROMISC_SAP);
179*d56f51eaSDavid van Moolenbroek 	if (retv < 0) {
180*d56f51eaSDavid van Moolenbroek 		/*
181*d56f51eaSDavid van Moolenbroek 		 * Not fatal, since the DL_PROMISC_PHYS mode worked.
182*d56f51eaSDavid van Moolenbroek 		 * Report it as a warning, however.
183*d56f51eaSDavid van Moolenbroek 		 */
184*d56f51eaSDavid van Moolenbroek 		if (p->opt.promisc)
185*d56f51eaSDavid van Moolenbroek 			status = PCAP_WARNING;
186*d56f51eaSDavid van Moolenbroek 		else {
187*d56f51eaSDavid van Moolenbroek 			status = retv;
188*d56f51eaSDavid van Moolenbroek 			goto bad;
189*d56f51eaSDavid van Moolenbroek 		}
190*d56f51eaSDavid van Moolenbroek 	}
191*d56f51eaSDavid van Moolenbroek 
192*d56f51eaSDavid van Moolenbroek 	/* Determine link type.  */
193*d56f51eaSDavid van Moolenbroek 	if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
194*d56f51eaSDavid van Moolenbroek 		status = PCAP_ERROR;
195*d56f51eaSDavid van Moolenbroek 		pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf);
196*d56f51eaSDavid van Moolenbroek 		goto bad;
197*d56f51eaSDavid van Moolenbroek 	}
198*d56f51eaSDavid van Moolenbroek 
199*d56f51eaSDavid van Moolenbroek 	if (pcap_process_mactype(p, dlinfo.di_mactype) != 0) {
200*d56f51eaSDavid van Moolenbroek 		status = PCAP_ERROR;
201*d56f51eaSDavid van Moolenbroek 		goto bad;
202*d56f51eaSDavid van Moolenbroek 	}
203*d56f51eaSDavid van Moolenbroek 
204*d56f51eaSDavid van Moolenbroek 	p->fd = dlpi_fd(pd->dlpi_hd);
205*d56f51eaSDavid van Moolenbroek 
206*d56f51eaSDavid van Moolenbroek 	/* Push and configure bufmod. */
207*d56f51eaSDavid van Moolenbroek 	if (pcap_conf_bufmod(p, p->snapshot) != 0) {
208*d56f51eaSDavid van Moolenbroek 		status = PCAP_ERROR;
209*d56f51eaSDavid van Moolenbroek 		goto bad;
210*d56f51eaSDavid van Moolenbroek 	}
211*d56f51eaSDavid van Moolenbroek 
212*d56f51eaSDavid van Moolenbroek 	/*
213*d56f51eaSDavid van Moolenbroek 	 * Flush the read side.
214*d56f51eaSDavid van Moolenbroek 	 */
215*d56f51eaSDavid van Moolenbroek 	if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
216*d56f51eaSDavid van Moolenbroek 		status = PCAP_ERROR;
217*d56f51eaSDavid van Moolenbroek 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
218*d56f51eaSDavid van Moolenbroek 		    pcap_strerror(errno));
219*d56f51eaSDavid van Moolenbroek 		goto bad;
220*d56f51eaSDavid van Moolenbroek 	}
221*d56f51eaSDavid van Moolenbroek 
222*d56f51eaSDavid van Moolenbroek 	/* Allocate data buffer. */
223*d56f51eaSDavid van Moolenbroek 	if (pcap_alloc_databuf(p) != 0) {
224*d56f51eaSDavid van Moolenbroek 		status = PCAP_ERROR;
225*d56f51eaSDavid van Moolenbroek 		goto bad;
226*d56f51eaSDavid van Moolenbroek 	}
227*d56f51eaSDavid van Moolenbroek 
228*d56f51eaSDavid van Moolenbroek 	/*
229*d56f51eaSDavid van Moolenbroek 	 * "p->fd" is a FD for a STREAMS device, so "select()" and
230*d56f51eaSDavid van Moolenbroek 	 * "poll()" should work on it.
231*d56f51eaSDavid van Moolenbroek 	 */
232*d56f51eaSDavid van Moolenbroek 	p->selectable_fd = p->fd;
233*d56f51eaSDavid van Moolenbroek 
234*d56f51eaSDavid van Moolenbroek 	p->read_op = pcap_read_libdlpi;
235*d56f51eaSDavid van Moolenbroek 	p->inject_op = pcap_inject_libdlpi;
236*d56f51eaSDavid van Moolenbroek 	p->setfilter_op = install_bpf_program;	/* No kernel filtering */
237*d56f51eaSDavid van Moolenbroek 	p->setdirection_op = NULL;	/* Not implemented */
238*d56f51eaSDavid van Moolenbroek 	p->set_datalink_op = NULL;	/* Can't change data link type */
239*d56f51eaSDavid van Moolenbroek 	p->getnonblock_op = pcap_getnonblock_fd;
240*d56f51eaSDavid van Moolenbroek 	p->setnonblock_op = pcap_setnonblock_fd;
241*d56f51eaSDavid van Moolenbroek 	p->stats_op = pcap_stats_dlpi;
242*d56f51eaSDavid van Moolenbroek 	p->cleanup_op = pcap_cleanup_libdlpi;
243*d56f51eaSDavid van Moolenbroek 
244*d56f51eaSDavid van Moolenbroek 	return (status);
245*d56f51eaSDavid van Moolenbroek bad:
246*d56f51eaSDavid van Moolenbroek 	pcap_cleanup_libdlpi(p);
247*d56f51eaSDavid van Moolenbroek 	return (status);
248*d56f51eaSDavid van Moolenbroek }
249*d56f51eaSDavid van Moolenbroek 
250*d56f51eaSDavid van Moolenbroek #define STRINGIFY(n)	#n
251*d56f51eaSDavid van Moolenbroek 
252*d56f51eaSDavid van Moolenbroek static int
dlpromiscon(pcap_t * p,bpf_u_int32 level)253*d56f51eaSDavid van Moolenbroek dlpromiscon(pcap_t *p, bpf_u_int32 level)
254*d56f51eaSDavid van Moolenbroek {
255*d56f51eaSDavid van Moolenbroek 	struct pcap_dlpi *pd = p->priv;
256*d56f51eaSDavid van Moolenbroek 	int retv;
257*d56f51eaSDavid van Moolenbroek 	int err;
258*d56f51eaSDavid van Moolenbroek 
259*d56f51eaSDavid van Moolenbroek 	retv = dlpi_promiscon(pd->dlpi_hd, level);
260*d56f51eaSDavid van Moolenbroek 	if (retv != DLPI_SUCCESS) {
261*d56f51eaSDavid van Moolenbroek 		if (retv == DL_SYSERR &&
262*d56f51eaSDavid van Moolenbroek 		    (errno == EPERM || errno == EACCES))
263*d56f51eaSDavid van Moolenbroek 			err = PCAP_ERROR_PERM_DENIED;
264*d56f51eaSDavid van Moolenbroek 		else
265*d56f51eaSDavid van Moolenbroek 			err = PCAP_ERROR;
266*d56f51eaSDavid van Moolenbroek 		pcap_libdlpi_err(p->opt.source, "dlpi_promiscon" STRINGIFY(level),
267*d56f51eaSDavid van Moolenbroek 		    retv, p->errbuf);
268*d56f51eaSDavid van Moolenbroek 		return (err);
269*d56f51eaSDavid van Moolenbroek 	}
270*d56f51eaSDavid van Moolenbroek 	return (0);
271*d56f51eaSDavid van Moolenbroek }
272*d56f51eaSDavid van Moolenbroek 
273*d56f51eaSDavid van Moolenbroek /*
274*d56f51eaSDavid van Moolenbroek  * In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
275*d56f51eaSDavid van Moolenbroek  * network links that are plumbed and are up. dlpi_walk(3DLPI) will find
276*d56f51eaSDavid van Moolenbroek  * additional network links present in the system.
277*d56f51eaSDavid van Moolenbroek  */
278*d56f51eaSDavid van Moolenbroek int
pcap_platform_finddevs(pcap_if_t ** alldevsp,char * errbuf)279*d56f51eaSDavid van Moolenbroek pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
280*d56f51eaSDavid van Moolenbroek {
281*d56f51eaSDavid van Moolenbroek 	int retv = 0;
282*d56f51eaSDavid van Moolenbroek 
283*d56f51eaSDavid van Moolenbroek 	linknamelist_t	*entry, *next;
284*d56f51eaSDavid van Moolenbroek 	linkwalk_t	lw = {NULL, 0};
285*d56f51eaSDavid van Moolenbroek 	int 		save_errno;
286*d56f51eaSDavid van Moolenbroek 
287*d56f51eaSDavid van Moolenbroek 	/* dlpi_walk() for loopback will be added here. */
288*d56f51eaSDavid van Moolenbroek 
289*d56f51eaSDavid van Moolenbroek 	dlpi_walk(list_interfaces, &lw, 0);
290*d56f51eaSDavid van Moolenbroek 
291*d56f51eaSDavid van Moolenbroek 	if (lw.lw_err != 0) {
292*d56f51eaSDavid van Moolenbroek 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
293*d56f51eaSDavid van Moolenbroek 		    "dlpi_walk: %s", pcap_strerror(lw.lw_err));
294*d56f51eaSDavid van Moolenbroek 		retv = -1;
295*d56f51eaSDavid van Moolenbroek 		goto done;
296*d56f51eaSDavid van Moolenbroek 	}
297*d56f51eaSDavid van Moolenbroek 
298*d56f51eaSDavid van Moolenbroek 	/* Add linkname if it does not exist on the list. */
299*d56f51eaSDavid van Moolenbroek 	for (entry = lw.lw_list; entry != NULL; entry = entry->lnl_next) {
300*d56f51eaSDavid van Moolenbroek 		if (pcap_add_if(alldevsp, entry->linkname, 0, NULL, errbuf) < 0)
301*d56f51eaSDavid van Moolenbroek 			retv = -1;
302*d56f51eaSDavid van Moolenbroek 	}
303*d56f51eaSDavid van Moolenbroek done:
304*d56f51eaSDavid van Moolenbroek 	save_errno = errno;
305*d56f51eaSDavid van Moolenbroek 	for (entry = lw.lw_list; entry != NULL; entry = next) {
306*d56f51eaSDavid van Moolenbroek 		next = entry->lnl_next;
307*d56f51eaSDavid van Moolenbroek 		free(entry);
308*d56f51eaSDavid van Moolenbroek 	}
309*d56f51eaSDavid van Moolenbroek 	errno = save_errno;
310*d56f51eaSDavid van Moolenbroek 
311*d56f51eaSDavid van Moolenbroek 	return (retv);
312*d56f51eaSDavid van Moolenbroek }
313*d56f51eaSDavid van Moolenbroek 
314*d56f51eaSDavid van Moolenbroek /*
315*d56f51eaSDavid van Moolenbroek  * Read data received on DLPI handle. Returns -2 if told to terminate, else
316*d56f51eaSDavid van Moolenbroek  * returns the number of packets read.
317*d56f51eaSDavid van Moolenbroek  */
318*d56f51eaSDavid van Moolenbroek static int
pcap_read_libdlpi(pcap_t * p,int count,pcap_handler callback,u_char * user)319*d56f51eaSDavid van Moolenbroek pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
320*d56f51eaSDavid van Moolenbroek {
321*d56f51eaSDavid van Moolenbroek 	struct pcap_dlpi *pd = p->priv;
322*d56f51eaSDavid van Moolenbroek 	int len;
323*d56f51eaSDavid van Moolenbroek 	u_char *bufp;
324*d56f51eaSDavid van Moolenbroek 	size_t msglen;
325*d56f51eaSDavid van Moolenbroek 	int retv;
326*d56f51eaSDavid van Moolenbroek 
327*d56f51eaSDavid van Moolenbroek 	len = p->cc;
328*d56f51eaSDavid van Moolenbroek 	if (len != 0) {
329*d56f51eaSDavid van Moolenbroek 		bufp = p->bp;
330*d56f51eaSDavid van Moolenbroek 		goto process_pkts;
331*d56f51eaSDavid van Moolenbroek 	}
332*d56f51eaSDavid van Moolenbroek 	do {
333*d56f51eaSDavid van Moolenbroek 		/* Has "pcap_breakloop()" been called? */
334*d56f51eaSDavid van Moolenbroek 		if (p->break_loop) {
335*d56f51eaSDavid van Moolenbroek 			/*
336*d56f51eaSDavid van Moolenbroek 			 * Yes - clear the flag that indicates that it has,
337*d56f51eaSDavid van Moolenbroek 			 * and return -2 to indicate that we were told to
338*d56f51eaSDavid van Moolenbroek 			 * break out of the loop.
339*d56f51eaSDavid van Moolenbroek 			 */
340*d56f51eaSDavid van Moolenbroek 			p->break_loop = 0;
341*d56f51eaSDavid van Moolenbroek 			return (-2);
342*d56f51eaSDavid van Moolenbroek 		}
343*d56f51eaSDavid van Moolenbroek 
344*d56f51eaSDavid van Moolenbroek 		msglen = p->bufsize;
345*d56f51eaSDavid van Moolenbroek 		bufp = p->buffer + p->offset;
346*d56f51eaSDavid van Moolenbroek 
347*d56f51eaSDavid van Moolenbroek 		retv = dlpi_recv(pd->dlpi_hd, NULL, NULL, bufp,
348*d56f51eaSDavid van Moolenbroek 		    &msglen, -1, NULL);
349*d56f51eaSDavid van Moolenbroek 		if (retv != DLPI_SUCCESS) {
350*d56f51eaSDavid van Moolenbroek 			/*
351*d56f51eaSDavid van Moolenbroek 			 * This is most likely a call to terminate out of the
352*d56f51eaSDavid van Moolenbroek 			 * loop. So, do not return an error message, instead
353*d56f51eaSDavid van Moolenbroek 			 * check if "pcap_breakloop()" has been called above.
354*d56f51eaSDavid van Moolenbroek 			 */
355*d56f51eaSDavid van Moolenbroek 			if (retv == DL_SYSERR && errno == EINTR) {
356*d56f51eaSDavid van Moolenbroek 				len = 0;
357*d56f51eaSDavid van Moolenbroek 				continue;
358*d56f51eaSDavid van Moolenbroek 			}
359*d56f51eaSDavid van Moolenbroek 			pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd),
360*d56f51eaSDavid van Moolenbroek 			    "dlpi_recv", retv, p->errbuf);
361*d56f51eaSDavid van Moolenbroek 			return (-1);
362*d56f51eaSDavid van Moolenbroek 		}
363*d56f51eaSDavid van Moolenbroek 		len = msglen;
364*d56f51eaSDavid van Moolenbroek 	} while (len == 0);
365*d56f51eaSDavid van Moolenbroek 
366*d56f51eaSDavid van Moolenbroek process_pkts:
367*d56f51eaSDavid van Moolenbroek 	return (pcap_process_pkts(p, callback, user, count, bufp, len));
368*d56f51eaSDavid van Moolenbroek }
369*d56f51eaSDavid van Moolenbroek 
370*d56f51eaSDavid van Moolenbroek static int
pcap_inject_libdlpi(pcap_t * p,const void * buf,size_t size)371*d56f51eaSDavid van Moolenbroek pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size)
372*d56f51eaSDavid van Moolenbroek {
373*d56f51eaSDavid van Moolenbroek 	struct pcap_dlpi *pd = p->priv;
374*d56f51eaSDavid van Moolenbroek 	int retv;
375*d56f51eaSDavid van Moolenbroek 
376*d56f51eaSDavid van Moolenbroek 	retv = dlpi_send(pd->dlpi_hd, NULL, 0, buf, size, NULL);
377*d56f51eaSDavid van Moolenbroek 	if (retv != DLPI_SUCCESS) {
378*d56f51eaSDavid van Moolenbroek 		pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd), "dlpi_send", retv,
379*d56f51eaSDavid van Moolenbroek 		    p->errbuf);
380*d56f51eaSDavid van Moolenbroek 		return (-1);
381*d56f51eaSDavid van Moolenbroek 	}
382*d56f51eaSDavid van Moolenbroek 	/*
383*d56f51eaSDavid van Moolenbroek 	 * dlpi_send(3DLPI) does not provide a way to return the number of
384*d56f51eaSDavid van Moolenbroek 	 * bytes sent on the wire. Based on the fact that DLPI_SUCCESS was
385*d56f51eaSDavid van Moolenbroek 	 * returned we are assuming 'size' bytes were sent.
386*d56f51eaSDavid van Moolenbroek 	 */
387*d56f51eaSDavid van Moolenbroek 	return (size);
388*d56f51eaSDavid van Moolenbroek }
389*d56f51eaSDavid van Moolenbroek 
390*d56f51eaSDavid van Moolenbroek /*
391*d56f51eaSDavid van Moolenbroek  * Close dlpi handle.
392*d56f51eaSDavid van Moolenbroek  */
393*d56f51eaSDavid van Moolenbroek static void
pcap_cleanup_libdlpi(pcap_t * p)394*d56f51eaSDavid van Moolenbroek pcap_cleanup_libdlpi(pcap_t *p)
395*d56f51eaSDavid van Moolenbroek {
396*d56f51eaSDavid van Moolenbroek 	struct pcap_dlpi *pd = p->priv;
397*d56f51eaSDavid van Moolenbroek 
398*d56f51eaSDavid van Moolenbroek 	if (pd->dlpi_hd != NULL) {
399*d56f51eaSDavid van Moolenbroek 		dlpi_close(pd->dlpi_hd);
400*d56f51eaSDavid van Moolenbroek 		pd->dlpi_hd = NULL;
401*d56f51eaSDavid van Moolenbroek 		p->fd = -1;
402*d56f51eaSDavid van Moolenbroek 	}
403*d56f51eaSDavid van Moolenbroek 	pcap_cleanup_live_common(p);
404*d56f51eaSDavid van Moolenbroek }
405*d56f51eaSDavid van Moolenbroek 
406*d56f51eaSDavid van Moolenbroek /*
407*d56f51eaSDavid van Moolenbroek  * Write error message to buffer.
408*d56f51eaSDavid van Moolenbroek  */
409*d56f51eaSDavid van Moolenbroek static void
pcap_libdlpi_err(const char * linkname,const char * func,int err,char * errbuf)410*d56f51eaSDavid van Moolenbroek pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
411*d56f51eaSDavid van Moolenbroek {
412*d56f51eaSDavid van Moolenbroek 	snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
413*d56f51eaSDavid van Moolenbroek 	    func, linkname, dlpi_strerror(err));
414*d56f51eaSDavid van Moolenbroek }
415*d56f51eaSDavid van Moolenbroek 
416*d56f51eaSDavid van Moolenbroek pcap_t *
pcap_create_interface(const char * device,char * ebuf)417*d56f51eaSDavid van Moolenbroek pcap_create_interface(const char *device, char *ebuf)
418*d56f51eaSDavid van Moolenbroek {
419*d56f51eaSDavid van Moolenbroek 	pcap_t *p;
420*d56f51eaSDavid van Moolenbroek 
421*d56f51eaSDavid van Moolenbroek 	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
422*d56f51eaSDavid van Moolenbroek 	if (p == NULL)
423*d56f51eaSDavid van Moolenbroek 		return (NULL);
424*d56f51eaSDavid van Moolenbroek 
425*d56f51eaSDavid van Moolenbroek 	p->activate_op = pcap_activate_libdlpi;
426*d56f51eaSDavid van Moolenbroek 	return (p);
427*d56f51eaSDavid van Moolenbroek }
428