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