1 /*
2 * This code is derived from code formerly in pcap-dlpi.c, originally
3 * contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), University College
4 * London, and subsequently modified by Guy Harris (guy@alum.mit.edu),
5 * Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>,
6 * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
7 */
8
9 /*
10 * This file contains dlpi/libdlpi related common functions used
11 * by pcap-[dlpi,libdlpi].c.
12 */
13
14 #include <config.h>
15
16 #ifndef DL_IPATM
17 #define DL_IPATM 0x12 /* ATM Classical IP interface */
18 #endif
19
20 #ifdef HAVE_SYS_BUFMOD_H
21 /*
22 * Size of a bufmod chunk to pass upstream; that appears to be the
23 * biggest value to which you can set it, and setting it to that value
24 * (which is bigger than what appears to be the Solaris default of 8192)
25 * reduces the number of packet drops.
26 */
27 #define CHUNKSIZE 65536
28
29 /*
30 * Size of the buffer to allocate for packet data we read; it must be
31 * large enough to hold a chunk.
32 */
33 #define PKTBUFSIZE CHUNKSIZE
34
35 #else /* HAVE_SYS_BUFMOD_H */
36
37 /*
38 * Size of the buffer to allocate for packet data we read; this is
39 * what the value used to be - there's no particular reason why it
40 * should be tied to MAXDLBUF, but we'll leave it as this for now.
41 */
42 #define MAXDLBUF 8192
43 #define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32))
44
45 #endif
46
47 #include <sys/types.h>
48 #include <sys/time.h>
49 #ifdef HAVE_SYS_BUFMOD_H
50 #include <sys/bufmod.h>
51 #endif
52 #include <sys/dlpi.h>
53 #include <sys/stream.h>
54
55 #include <errno.h>
56 #include <memory.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stropts.h>
61 #include <unistd.h>
62
63 #include <sys/ioctl.h>
64 #include <sys/socket.h>
65 #include <sys/sockio.h>
66
67 #include <net/if.h>
68
69 #ifdef HAVE_LIBDLPI
70 #include <libdlpi.h>
71 #endif
72
73 #ifdef HAVE_ZONE_H
74 #include <zone.h>
75 #endif
76
77 #include "pcap-int.h"
78 #include "dlpisubs.h"
79
80 #ifdef HAVE_SYS_BUFMOD_H
81 static void pcap_stream_err(const char *, int, char *);
82 #endif
83
84 /*
85 * Get the packet statistics.
86 */
87 int
pcap_stats_dlpi(pcap_t * p,struct pcap_stat * ps)88 pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
89 {
90 struct pcap_dlpi *pd = p->priv;
91
92 /*
93 * "ps_recv" counts packets handed to the filter, not packets
94 * that passed the filter. As filtering is done in userland,
95 * this would not include packets dropped because we ran out
96 * of buffer space; in order to make this more like other
97 * platforms (Linux 2.4 and later, BSDs with BPF), where the
98 * "packets received" count includes packets received but dropped
99 * due to running out of buffer space, and to keep from confusing
100 * applications that, for example, compute packet drop percentages,
101 * we also make it count packets dropped by "bufmod" (otherwise we
102 * might run the risk of the packet drop count being bigger than
103 * the received-packet count).
104 *
105 * "ps_drop" counts packets dropped by "bufmod" because of
106 * flow control requirements or resource exhaustion; it doesn't
107 * count packets dropped by the interface driver, or packets
108 * dropped upstream. As filtering is done in userland, it counts
109 * packets regardless of whether they would've passed the filter.
110 *
111 * These statistics don't include packets not yet read from
112 * the kernel by libpcap, but they may include packets not
113 * yet read from libpcap by the application.
114 */
115 *ps = pd->stat;
116
117 /*
118 * Add in the drop count, as per the above comment.
119 */
120 ps->ps_recv += ps->ps_drop;
121 return (0);
122 }
123
124 /*
125 * Does the processor for which we're compiling this support aligned loads?
126 */
127 #if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
128 (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \
129 (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
130 (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \
131 (defined(__s390__) || defined(__s390x__) || defined(__zarch__))
132 /* Yes, it does. */
133 #else
134 /* No, it doesn't. */
135 #define REQUIRE_ALIGNMENT
136 #endif
137
138 /*
139 * Loop through the packets and call the callback for each packet.
140 * Return the number of packets read.
141 */
142 int
pcap_process_pkts(pcap_t * p,pcap_handler callback,u_char * user,int count,u_char * bufp,int len)143 pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
144 int count, u_char *bufp, int len)
145 {
146 struct pcap_dlpi *pd = p->priv;
147 int n, caplen, origlen;
148 u_char *ep, *pk;
149 struct pcap_pkthdr pkthdr;
150 #ifdef HAVE_SYS_BUFMOD_H
151 struct sb_hdr *sbp;
152 #ifdef REQUIRE_ALIGNMENT
153 struct sb_hdr sbhdr;
154 #endif
155 #endif
156
157 /*
158 * Loop through packets.
159 *
160 * This assumes that a single buffer of packets will have
161 * <= INT_MAX packets, so the packet count doesn't overflow.
162 */
163 ep = bufp + len;
164 n = 0;
165
166 #ifdef HAVE_SYS_BUFMOD_H
167 while (bufp < ep) {
168 /*
169 * Has "pcap_breakloop()" been called?
170 * If so, return immediately - if we haven't read any
171 * packets, clear the flag and return -2 to indicate
172 * that we were told to break out of the loop, otherwise
173 * leave the flag set, so that the *next* call will break
174 * out of the loop without having read any packets, and
175 * return the number of packets we've processed so far.
176 */
177 if (p->break_loop) {
178 if (n == 0) {
179 p->break_loop = 0;
180 return (-2);
181 } else {
182 p->bp = bufp;
183 p->cc = ep - bufp;
184 return (n);
185 }
186 }
187 #ifdef REQUIRE_ALIGNMENT
188 if ((long)bufp & 3) {
189 sbp = &sbhdr;
190 memcpy(sbp, bufp, sizeof(*sbp));
191 } else
192 #endif
193 sbp = (struct sb_hdr *)bufp;
194 pd->stat.ps_drop = sbp->sbh_drops;
195 pk = bufp + sizeof(*sbp);
196 bufp += sbp->sbh_totlen;
197 origlen = sbp->sbh_origlen;
198 caplen = sbp->sbh_msglen;
199 #else
200 origlen = len;
201 caplen = min(p->snapshot, len);
202 pk = bufp;
203 bufp += caplen;
204 #endif
205 ++pd->stat.ps_recv;
206 if (pcapint_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
207 #ifdef HAVE_SYS_BUFMOD_H
208 pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
209 pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
210 #else
211 (void) gettimeofday(&pkthdr.ts, NULL);
212 #endif
213 pkthdr.len = origlen;
214 pkthdr.caplen = caplen;
215 /* Insure caplen does not exceed snapshot */
216 if (pkthdr.caplen > (bpf_u_int32)p->snapshot)
217 pkthdr.caplen = (bpf_u_int32)p->snapshot;
218 (*callback)(user, &pkthdr, pk);
219 if (++n >= count && !PACKET_COUNT_IS_UNLIMITED(count)) {
220 p->cc = ep - bufp;
221 p->bp = bufp;
222 return (n);
223 }
224 }
225 #ifdef HAVE_SYS_BUFMOD_H
226 }
227 #endif
228 p->cc = 0;
229 return (n);
230 }
231
232 /*
233 * Process the mac type. Returns -1 if no matching mac type found, otherwise 0.
234 */
235 int
pcap_process_mactype(pcap_t * p,u_int mactype)236 pcap_process_mactype(pcap_t *p, u_int mactype)
237 {
238 int retv = 0;
239
240 switch (mactype) {
241
242 case DL_CSMACD:
243 case DL_ETHER:
244 p->linktype = DLT_EN10MB;
245 p->offset = 2;
246 /*
247 * This is (presumably) a real Ethernet capture; give it a
248 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
249 * that an application can let you choose it, in case you're
250 * capturing DOCSIS traffic that a Cisco Cable Modem
251 * Termination System is putting out onto an Ethernet (it
252 * doesn't put an Ethernet header onto the wire, it puts raw
253 * DOCSIS frames out on the wire inside the low-level
254 * Ethernet framing).
255 */
256 p->dlt_list = (u_int *)malloc(sizeof(u_int) * 2);
257 if (p->dlt_list == NULL) {
258 pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
259 errno, "malloc");
260 return (-1);
261 }
262 p->dlt_list[0] = DLT_EN10MB;
263 p->dlt_list[1] = DLT_DOCSIS;
264 p->dlt_count = 2;
265 break;
266
267 case DL_FDDI:
268 p->linktype = DLT_FDDI;
269 p->offset = 3;
270 break;
271
272 case DL_TPR:
273 /* XXX - what about DL_TPB? Is that Token Bus? */
274 p->linktype = DLT_IEEE802;
275 p->offset = 2;
276 break;
277
278 #ifdef HAVE_SOLARIS
279 case DL_IPATM:
280 p->linktype = DLT_SUNATM;
281 p->offset = 0; /* works for LANE and LLC encapsulation */
282 break;
283 #endif
284
285 #ifdef DL_IPV4
286 case DL_IPV4:
287 p->linktype = DLT_IPV4;
288 p->offset = 0;
289 break;
290 #endif
291
292 #ifdef DL_IPV6
293 case DL_IPV6:
294 p->linktype = DLT_IPV6;
295 p->offset = 0;
296 break;
297 #endif
298
299 #ifdef DL_IPNET
300 case DL_IPNET:
301 /*
302 * XXX - DL_IPNET devices default to "raw IP" rather than
303 * "IPNET header"; see
304 *
305 * https://seclists.org/tcpdump/2009/q1/202
306 *
307 * We'd have to do DL_IOC_IPNET_INFO to enable getting
308 * the IPNET header.
309 */
310 p->linktype = DLT_RAW;
311 p->offset = 0;
312 break;
313 #endif
314
315 default:
316 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype 0x%x",
317 mactype);
318 retv = -1;
319 }
320
321 return (retv);
322 }
323
324 #ifdef HAVE_SYS_BUFMOD_H
325 /*
326 * Push and configure the buffer module. Returns -1 for error, otherwise 0.
327 */
328 int
pcap_conf_bufmod(pcap_t * p,int snaplen)329 pcap_conf_bufmod(pcap_t *p, int snaplen)
330 {
331 struct timeval to;
332 bpf_u_int32 ss, chunksize;
333
334 /* Non-standard call to get the data nicely buffered. */
335 if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
336 pcap_stream_err("I_PUSH bufmod", errno, p->errbuf);
337 return (-1);
338 }
339
340 ss = snaplen;
341 if (ss > 0 &&
342 strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
343 pcap_stream_err("SBIOCSSNAP", errno, p->errbuf);
344 return (-1);
345 }
346
347 if (p->opt.immediate) {
348 /* Set the timeout to zero, for immediate delivery. */
349 to.tv_sec = 0;
350 to.tv_usec = 0;
351 if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
352 pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
353 return (-1);
354 }
355 } else {
356 /* Set up the bufmod timeout. */
357 if (p->opt.timeout != 0) {
358 to.tv_sec = p->opt.timeout / 1000;
359 to.tv_usec = (p->opt.timeout * 1000) % 1000000;
360 if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
361 pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
362 return (-1);
363 }
364 }
365
366 /* Set the chunk length. */
367 chunksize = CHUNKSIZE;
368 if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
369 != 0) {
370 pcap_stream_err("SBIOCSCHUNKP", errno, p->errbuf);
371 return (-1);
372 }
373 }
374
375 return (0);
376 }
377 #endif /* HAVE_SYS_BUFMOD_H */
378
379 /*
380 * Allocate data buffer. Returns -1 if memory allocation fails, else 0.
381 */
382 int
pcap_alloc_databuf(pcap_t * p)383 pcap_alloc_databuf(pcap_t *p)
384 {
385 p->bufsize = PKTBUFSIZE;
386 p->buffer = malloc(p->bufsize + p->offset);
387 if (p->buffer == NULL) {
388 pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
389 errno, "malloc");
390 return (-1);
391 }
392
393 return (0);
394 }
395
396 /*
397 * Issue a STREAMS I_STR ioctl. Returns -1 on error, otherwise
398 * length of returned data on success.
399 */
400 int
strioctl(int fd,int cmd,int len,char * dp)401 strioctl(int fd, int cmd, int len, char *dp)
402 {
403 struct strioctl str;
404 int retv;
405
406 str.ic_cmd = cmd;
407 str.ic_timout = -1;
408 str.ic_len = len;
409 str.ic_dp = dp;
410 if ((retv = ioctl(fd, I_STR, &str)) < 0)
411 return (retv);
412
413 return (str.ic_len);
414 }
415
416 #ifdef HAVE_SYS_BUFMOD_H
417 /*
418 * Write stream error message to errbuf.
419 */
420 static void
pcap_stream_err(const char * func,int err,char * errbuf)421 pcap_stream_err(const char *func, int err, char *errbuf)
422 {
423 pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, err, "%s", func);
424 }
425 #endif
426
427 int
handle_nonexistent_dlpi_device(const char * ifname,char * errbuf)428 handle_nonexistent_dlpi_device(const char *ifname, char *errbuf)
429 {
430 int fd;
431 int status;
432 #ifdef LIFNAMSIZ
433 struct lifreq lifr;
434 #else
435 struct ifreq ifr;
436 #endif
437
438 #ifdef LIFNAMSIZ
439 if (strlen(ifname) >= sizeof(lifr.lifr_name)) {
440 #else
441 if (strlen(ifname) >= sizeof(ifr.ifr_name)) {
442 #endif
443 /*
444 * The name is too long, so it can't possibly exist.
445 */
446 strlcpy(errbuf, "", PCAP_ERRBUF_SIZE);
447 return (PCAP_ERROR_NO_SUCH_DEVICE);
448 }
449
450 /*
451 * Try to get a socket on which to do an ioctl to get the
452 * interface's flags.
453 */
454 fd = socket(AF_INET, SOCK_DGRAM, 0);
455 if (fd < 0) {
456 /* That failed; report that as the error. */
457 pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
458 errno, "Can't open socket to get interface flags");
459 return (PCAP_ERROR);
460 }
461
462 #ifdef LIFNAMSIZ
463 pcapint_strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
464 status = ioctl(fd, SIOCGLIFFLAGS, (char *)&lifr);
465 #else
466 pcapint_strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
467 status = ioctl(fd, SIOCGIFFLAGS, (char *)&ifr);
468 #endif
469
470 if (status < 0) {
471 if (errno == ENXIO || errno == EINVAL) {
472 /*
473 * macOS, *BSD, and Solaris return one of
474 * those two errors if the device doesn't exist.
475 */
476 strlcpy(errbuf, "", PCAP_ERRBUF_SIZE);
477 close(fd);
478 return (PCAP_ERROR_NO_SUCH_DEVICE);
479 }
480
481 /*
482 * Some other error.
483 */
484 pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
485 "Can't get interface flags");
486 close(fd);
487 return (PCAP_ERROR);
488 }
489
490 /*
491 * The interface exists.
492 */
493 close(fd);
494
495 #ifdef HAVE_ZONE_H
496 /*
497 * If we're not in a global zone, the problem is probably
498 * that the zone we're in doesn't happen to have any
499 * DLPI devices. Exclusive-IP non-global zones have
500 * their own interfaces and have DLPI devices for them:
501 *
502 * https://docs.oracle.com/cd/E37838_01/html/E61040/z.config.ov-6.html#VLZCRgekkb
503 *
504 * https://docs.oracle.com/cd/E19044-01/sol.containers/817-1592/geprv/index.html
505 *
506 * but shared-IP non-global zones don't:
507 *
508 * https://docs.oracle.com/cd/E37838_01/html/E61040/z.config.ov-6.html#VLZCRgekku
509 */
510 if (getzoneid() != GLOBAL_ZONEID) {
511 /*
512 * Not a global zone; note that capturing on network
513 * interfaces is only supported for interfaces
514 * in an exclusive-IP zone.
515 */
516 snprintf(errbuf, PCAP_ERRBUF_SIZE,
517 "Capturing on interfaces in a non-global zone is supported only for interfaces in exclusive-IP zones");
518 return (PCAP_ERROR_CAPTURE_NOTSUP);
519 }
520 #endif /* HAVE_ZONE_H */
521
522 /*
523 * Some other problem; just report it as not having
524 * a DLPI device. We don't report the DLPI device
525 * name, so people don't get confused and think, for
526 * example, that if they can't capture on that interface
527 * on Solaris prior to Solaris 11 the fix is to change
528 * libpcap (or the application that uses it) to look
529 * for something other than "/dev/{ifname}", as the fix
530 * is to use Solaris 11 or some operating system other
531 * than Solaris - you just *can't* capture on that
532 * interface on Solaris prior to Solaris 11, the lack
533 * of a DLPI device for the loopback interface is just
534 * a symptom of that inability.
535 */
536 snprintf(errbuf, PCAP_ERRBUF_SIZE,
537 "Capturing on that interface is not supported - no DLPI device found");
538 return (PCAP_ERROR_CAPTURE_NOTSUP);
539 }
540