Annotation of sys/net/bpf.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: bpf.c,v 1.66 2007/07/25 23:11:53 art Exp $ */
2: /* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */
3:
4: /*
5: * Copyright (c) 1990, 1991, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from the Stanford/CMU enet packet filter,
9: * (net/enet.c) distributed as part of 4.3BSD, and code contributed
10: * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
11: * Berkeley Laboratory.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: * @(#)bpf.c 8.2 (Berkeley) 3/28/94
38: */
39:
40: #include "bpfilter.h"
41:
42: #include <sys/param.h>
43: #include <sys/mbuf.h>
44: #include <sys/proc.h>
45: #include <sys/signalvar.h>
46: #include <sys/ioctl.h>
47: #include <sys/conf.h>
48: #include <sys/vnode.h>
49: #include <sys/file.h>
50: #include <sys/socket.h>
51: #include <sys/poll.h>
52: #include <sys/kernel.h>
53: #include <sys/sysctl.h>
54:
55: #include <net/if.h>
56: #include <net/bpf.h>
57: #include <net/bpfdesc.h>
58:
59: #include <netinet/in.h>
60: #include <netinet/if_ether.h>
61:
62: #define BPF_BUFSIZE 32768
63:
64: #define PRINET 26 /* interruptible */
65:
66: /*
67: * The default read buffer size is patchable.
68: */
69: int bpf_bufsize = BPF_BUFSIZE;
70: int bpf_maxbufsize = BPF_MAXBUFSIZE;
71:
72: /*
73: * bpf_iflist is the list of interfaces; each corresponds to an ifnet
74: * bpf_d_list is the list of descriptors
75: */
76: struct bpf_if *bpf_iflist;
77: LIST_HEAD(, bpf_d) bpf_d_list;
78:
79: int bpf_allocbufs(struct bpf_d *);
80: void bpf_freed(struct bpf_d *);
81: void bpf_ifname(struct ifnet *, struct ifreq *);
82: void bpf_mcopy(const void *, void *, size_t);
83: int bpf_movein(struct uio *, u_int, struct mbuf **,
84: struct sockaddr *, struct bpf_insn *);
85: void bpf_attachd(struct bpf_d *, struct bpf_if *);
86: void bpf_detachd(struct bpf_d *);
87: int bpf_setif(struct bpf_d *, struct ifreq *);
88: int bpfpoll(dev_t, int, struct proc *);
89: int bpfkqfilter(dev_t, struct knote *);
90: static __inline void bpf_wakeup(struct bpf_d *);
91: void bpf_catchpacket(struct bpf_d *, u_char *, size_t, size_t,
92: void (*)(const void *, void *, size_t));
93: void bpf_reset_d(struct bpf_d *);
94: int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
95: int bpf_setdlt(struct bpf_d *, u_int);
96:
97: void filt_bpfrdetach(struct knote *);
98: int filt_bpfread(struct knote *, long);
99:
100: struct bpf_d *bpfilter_lookup(int);
101: struct bpf_d *bpfilter_create(int);
102: void bpfilter_destroy(struct bpf_d *);
103:
104: int
105: bpf_movein(struct uio *uio, u_int linktype, struct mbuf **mp,
106: struct sockaddr *sockp, struct bpf_insn *filter)
107: {
108: struct mbuf *m;
109: struct m_tag *mtag;
110: int error;
111: u_int hlen;
112: u_int len;
113: u_int slen;
114:
115: /*
116: * Build a sockaddr based on the data link layer type.
117: * We do this at this level because the ethernet header
118: * is copied directly into the data field of the sockaddr.
119: * In the case of SLIP, there is no header and the packet
120: * is forwarded as is.
121: * Also, we are careful to leave room at the front of the mbuf
122: * for the link level header.
123: */
124: switch (linktype) {
125:
126: case DLT_SLIP:
127: sockp->sa_family = AF_INET;
128: hlen = 0;
129: break;
130:
131: case DLT_PPP:
132: sockp->sa_family = AF_UNSPEC;
133: hlen = 0;
134: break;
135:
136: case DLT_EN10MB:
137: sockp->sa_family = AF_UNSPEC;
138: /* XXX Would MAXLINKHDR be better? */
139: hlen = ETHER_HDR_LEN;
140: break;
141:
142: case DLT_FDDI:
143: sockp->sa_family = AF_UNSPEC;
144: /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
145: hlen = 24;
146: break;
147:
148: case DLT_IEEE802_11:
149: case DLT_IEEE802_11_RADIO:
150: sockp->sa_family = AF_UNSPEC;
151: hlen = 0;
152: break;
153:
154: case DLT_RAW:
155: case DLT_NULL:
156: sockp->sa_family = AF_UNSPEC;
157: hlen = 0;
158: break;
159:
160: case DLT_ATM_RFC1483:
161: /*
162: * en atm driver requires 4-byte atm pseudo header.
163: * though it isn't standard, vpi:vci needs to be
164: * specified anyway.
165: */
166: sockp->sa_family = AF_UNSPEC;
167: hlen = 12; /* XXX 4(ATM_PH) + 3(LLC) + 5(SNAP) */
168: break;
169:
170: default:
171: return (EIO);
172: }
173:
174: len = uio->uio_resid;
175: if (len > MCLBYTES)
176: return (EIO);
177:
178: MGETHDR(m, M_WAIT, MT_DATA);
179: m->m_pkthdr.rcvif = 0;
180: m->m_pkthdr.len = len - hlen;
181:
182: if (len > MHLEN) {
183: MCLGET(m, M_WAIT);
184: if ((m->m_flags & M_EXT) == 0) {
185: error = ENOBUFS;
186: goto bad;
187: }
188: }
189: m->m_len = len;
190: *mp = m;
191:
192: error = uiomove(mtod(m, caddr_t), len, uio);
193: if (error)
194: goto bad;
195:
196: slen = bpf_filter(filter, mtod(m, u_char *), len, len);
197: if (slen < len) {
198: error = EPERM;
199: goto bad;
200: }
201:
202: if (m->m_len < hlen) {
203: error = EPERM;
204: goto bad;
205: }
206: /*
207: * Make room for link header, and copy it to sockaddr
208: */
209: if (hlen != 0) {
210: bcopy(m->m_data, sockp->sa_data, hlen);
211: m->m_len -= hlen;
212: m->m_data += hlen; /* XXX */
213: }
214:
215: /*
216: * Prepend the data link type as a mbuf tag
217: */
218: mtag = m_tag_get(PACKET_TAG_DLT, sizeof(u_int), M_NOWAIT);
219: if (mtag == NULL)
220: return (ENOMEM);
221: *(u_int *)(mtag + 1) = linktype;
222: m_tag_prepend(m, mtag);
223:
224: return (0);
225: bad:
226: m_freem(m);
227: return (error);
228: }
229:
230: /*
231: * Attach file to the bpf interface, i.e. make d listen on bp.
232: * Must be called at splnet.
233: */
234: void
235: bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
236: {
237: /*
238: * Point d at bp, and add d to the interface's list of listeners.
239: * Finally, point the driver's bpf cookie at the interface so
240: * it will divert packets to bpf.
241: */
242: d->bd_bif = bp;
243: d->bd_next = bp->bif_dlist;
244: bp->bif_dlist = d;
245:
246: *bp->bif_driverp = bp;
247: }
248:
249: /*
250: * Detach a file from its interface.
251: */
252: void
253: bpf_detachd(struct bpf_d *d)
254: {
255: struct bpf_d **p;
256: struct bpf_if *bp;
257:
258: bp = d->bd_bif;
259: /*
260: * Check if this descriptor had requested promiscuous mode.
261: * If so, turn it off.
262: */
263: if (d->bd_promisc) {
264: int error;
265:
266: d->bd_promisc = 0;
267: error = ifpromisc(bp->bif_ifp, 0);
268: if (error && !(error == EINVAL || error == ENODEV))
269: /*
270: * Something is really wrong if we were able to put
271: * the driver into promiscuous mode, but can't
272: * take it out.
273: */
274: panic("bpf: ifpromisc failed");
275: }
276: /* Remove d from the interface's descriptor list. */
277: p = &bp->bif_dlist;
278: while (*p != d) {
279: p = &(*p)->bd_next;
280: if (*p == 0)
281: panic("bpf_detachd: descriptor not in list");
282: }
283: *p = (*p)->bd_next;
284: if (bp->bif_dlist == 0)
285: /*
286: * Let the driver know that there are no more listeners.
287: */
288: *d->bd_bif->bif_driverp = 0;
289: d->bd_bif = 0;
290: }
291:
292: /*
293: * Reference count access to descriptor buffers
294: */
295: #define D_GET(d) ((d)->bd_ref++)
296: #define D_PUT(d) bpf_freed(d)
297:
298: /*
299: * bpfilterattach() is called at boot time in new systems. We do
300: * nothing here since old systems will not call this.
301: */
302: /* ARGSUSED */
303: void
304: bpfilterattach(int n)
305: {
306: LIST_INIT(&bpf_d_list);
307: }
308:
309: /*
310: * Open ethernet device. Returns ENXIO for illegal minor device number,
311: * EBUSY if file is open by another process.
312: */
313: /* ARGSUSED */
314: int
315: bpfopen(dev_t dev, int flag, int mode, struct proc *p)
316: {
317: struct bpf_d *d;
318:
319: /* create on demand */
320: if ((d = bpfilter_create(minor(dev))) == NULL)
321: return (EBUSY);
322:
323: /* Mark "free" and do most initialization. */
324: d->bd_bufsize = bpf_bufsize;
325: d->bd_sig = SIGIO;
326:
327: D_GET(d);
328:
329: return (0);
330: }
331:
332: /*
333: * Close the descriptor by detaching it from its interface,
334: * deallocating its buffers, and marking it free.
335: */
336: /* ARGSUSED */
337: int
338: bpfclose(dev_t dev, int flag, int mode, struct proc *p)
339: {
340: struct bpf_d *d;
341: int s;
342:
343: d = bpfilter_lookup(minor(dev));
344: s = splnet();
345: if (d->bd_bif)
346: bpf_detachd(d);
347: bpf_wakeup(d);
348: D_PUT(d);
349: splx(s);
350:
351: return (0);
352: }
353:
354: /*
355: * Rotate the packet buffers in descriptor d. Move the store buffer
356: * into the hold slot, and the free buffer into the store slot.
357: * Zero the length of the new store buffer.
358: */
359: #define ROTATE_BUFFERS(d) \
360: (d)->bd_hbuf = (d)->bd_sbuf; \
361: (d)->bd_hlen = (d)->bd_slen; \
362: (d)->bd_sbuf = (d)->bd_fbuf; \
363: (d)->bd_slen = 0; \
364: (d)->bd_fbuf = 0;
365: /*
366: * bpfread - read next chunk of packets from buffers
367: */
368: int
369: bpfread(dev_t dev, struct uio *uio, int ioflag)
370: {
371: struct bpf_d *d;
372: int error;
373: int s;
374:
375: d = bpfilter_lookup(minor(dev));
376: if (d->bd_bif == 0)
377: return (ENXIO);
378:
379: /*
380: * Restrict application to use a buffer the same size as
381: * as kernel buffers.
382: */
383: if (uio->uio_resid != d->bd_bufsize)
384: return (EINVAL);
385:
386: s = splnet();
387:
388: D_GET(d);
389:
390: /*
391: * bd_rdStart is tagged when we start the read, iff there's a timeout.
392: * we can then figure out when we're done reading.
393: */
394: if (d->bd_rtout != -1 && d->bd_rdStart == 0)
395: d->bd_rdStart = ticks;
396: else
397: d->bd_rdStart = 0;
398:
399: /*
400: * If the hold buffer is empty, then do a timed sleep, which
401: * ends when the timeout expires or when enough packets
402: * have arrived to fill the store buffer.
403: */
404: while (d->bd_hbuf == 0) {
405: if (d->bd_bif == NULL) {
406: /* interface is gone */
407: if (d->bd_slen == 0) {
408: D_PUT(d);
409: splx(s);
410: return (EIO);
411: }
412: ROTATE_BUFFERS(d);
413: break;
414: }
415: if (d->bd_immediate && d->bd_slen != 0) {
416: /*
417: * A packet(s) either arrived since the previous
418: * read or arrived while we were asleep.
419: * Rotate the buffers and return what's here.
420: */
421: ROTATE_BUFFERS(d);
422: break;
423: }
424: if ((d->bd_rtout != -1) ||
425: (d->bd_rdStart + d->bd_rtout) < ticks) {
426: error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf",
427: d->bd_rtout);
428: } else {
429: if (d->bd_rtout == -1) {
430: /* User requested non-blocking I/O */
431: error = EWOULDBLOCK;
432: } else
433: error = 0;
434: }
435: if (error == EINTR || error == ERESTART) {
436: D_PUT(d);
437: splx(s);
438: return (error);
439: }
440: if (error == EWOULDBLOCK) {
441: /*
442: * On a timeout, return what's in the buffer,
443: * which may be nothing. If there is something
444: * in the store buffer, we can rotate the buffers.
445: */
446: if (d->bd_hbuf)
447: /*
448: * We filled up the buffer in between
449: * getting the timeout and arriving
450: * here, so we don't need to rotate.
451: */
452: break;
453:
454: if (d->bd_slen == 0) {
455: D_PUT(d);
456: splx(s);
457: return (0);
458: }
459: ROTATE_BUFFERS(d);
460: break;
461: }
462: }
463: /*
464: * At this point, we know we have something in the hold slot.
465: */
466: splx(s);
467:
468: /*
469: * Move data from hold buffer into user space.
470: * We know the entire buffer is transferred since
471: * we checked above that the read buffer is bpf_bufsize bytes.
472: */
473: error = uiomove(d->bd_hbuf, d->bd_hlen, uio);
474:
475: s = splnet();
476: d->bd_fbuf = d->bd_hbuf;
477: d->bd_hbuf = 0;
478: d->bd_hlen = 0;
479:
480: D_PUT(d);
481: splx(s);
482:
483: return (error);
484: }
485:
486:
487: /*
488: * If there are processes sleeping on this descriptor, wake them up.
489: */
490: static __inline void
491: bpf_wakeup(struct bpf_d *d)
492: {
493: wakeup((caddr_t)d);
494: if (d->bd_async && d->bd_sig)
495: csignal(d->bd_pgid, d->bd_sig,
496: d->bd_siguid, d->bd_sigeuid);
497:
498: selwakeup(&d->bd_sel);
499: /* XXX */
500: d->bd_sel.si_selpid = 0;
501: KNOTE(&d->bd_sel.si_note, 0);
502: }
503:
504: int
505: bpfwrite(dev_t dev, struct uio *uio, int ioflag)
506: {
507: struct bpf_d *d;
508: struct ifnet *ifp;
509: struct mbuf *m;
510: int error, s;
511: struct sockaddr_storage dst;
512:
513: d = bpfilter_lookup(minor(dev));
514: if (d->bd_bif == 0)
515: return (ENXIO);
516:
517: ifp = d->bd_bif->bif_ifp;
518:
519: if ((ifp->if_flags & IFF_UP) == 0)
520: return (ENETDOWN);
521:
522: if (uio->uio_resid == 0)
523: return (0);
524:
525: error = bpf_movein(uio, d->bd_bif->bif_dlt, &m,
526: (struct sockaddr *)&dst, d->bd_wfilter);
527: if (error)
528: return (error);
529:
530: if (m->m_pkthdr.len > ifp->if_mtu) {
531: m_freem(m);
532: return (EMSGSIZE);
533: }
534:
535: if (d->bd_hdrcmplt)
536: dst.ss_family = pseudo_AF_HDRCMPLT;
537:
538: s = splsoftnet();
539: error = (*ifp->if_output)(ifp, m, (struct sockaddr *)&dst,
540: (struct rtentry *)0);
541: splx(s);
542: /*
543: * The driver frees the mbuf.
544: */
545: return (error);
546: }
547:
548: /*
549: * Reset a descriptor by flushing its packet buffer and clearing the
550: * receive and drop counts. Should be called at splnet.
551: */
552: void
553: bpf_reset_d(struct bpf_d *d)
554: {
555: if (d->bd_hbuf) {
556: /* Free the hold buffer. */
557: d->bd_fbuf = d->bd_hbuf;
558: d->bd_hbuf = 0;
559: }
560: d->bd_slen = 0;
561: d->bd_hlen = 0;
562: d->bd_rcount = 0;
563: d->bd_dcount = 0;
564: }
565:
566: /*
567: * FIONREAD Check for read packet available.
568: * BIOCGBLEN Get buffer len [for read()].
569: * BIOCSETF Set ethernet read filter.
570: * BIOCFLUSH Flush read packet buffer.
571: * BIOCPROMISC Put interface into promiscuous mode.
572: * BIOCGDLTLIST Get supported link layer types.
573: * BIOCGDLT Get link layer type.
574: * BIOCSDLT Set link layer type.
575: * BIOCGETIF Get interface name.
576: * BIOCSETIF Set interface.
577: * BIOCSRTIMEOUT Set read timeout.
578: * BIOCGRTIMEOUT Get read timeout.
579: * BIOCGSTATS Get packet stats.
580: * BIOCIMMEDIATE Set immediate mode.
581: * BIOCVERSION Get filter language version.
582: * BIOCGHDRCMPLT Get "header already complete" flag
583: * BIOCSHDRCMPLT Set "header already complete" flag
584: */
585: /* ARGSUSED */
586: int
587: bpfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
588: {
589: struct bpf_d *d;
590: int s, error = 0;
591:
592: d = bpfilter_lookup(minor(dev));
593: if (d->bd_locked && suser(p, 0) != 0) {
594: /* list of allowed ioctls when locked and not root */
595: switch (cmd) {
596: case BIOCGBLEN:
597: case BIOCFLUSH:
598: case BIOCGDLT:
599: case BIOCGDLTLIST:
600: case BIOCGETIF:
601: case BIOCGRTIMEOUT:
602: case BIOCGSTATS:
603: case BIOCVERSION:
604: case BIOCGRSIG:
605: case BIOCGHDRCMPLT:
606: case FIONREAD:
607: case BIOCLOCK:
608: case BIOCSRTIMEOUT:
609: case BIOCIMMEDIATE:
610: case TIOCGPGRP:
611: case BIOCGDIRFILT:
612: break;
613: default:
614: return (EPERM);
615: }
616: }
617:
618: switch (cmd) {
619:
620: default:
621: error = EINVAL;
622: break;
623:
624: /*
625: * Check for read packet available.
626: */
627: case FIONREAD:
628: {
629: int n;
630:
631: s = splnet();
632: n = d->bd_slen;
633: if (d->bd_hbuf)
634: n += d->bd_hlen;
635: splx(s);
636:
637: *(int *)addr = n;
638: break;
639: }
640:
641: /*
642: * Get buffer len [for read()].
643: */
644: case BIOCGBLEN:
645: *(u_int *)addr = d->bd_bufsize;
646: break;
647:
648: /*
649: * Set buffer length.
650: */
651: case BIOCSBLEN:
652: if (d->bd_bif != 0)
653: error = EINVAL;
654: else {
655: u_int size = *(u_int *)addr;
656:
657: if (size > bpf_maxbufsize)
658: *(u_int *)addr = size = bpf_maxbufsize;
659: else if (size < BPF_MINBUFSIZE)
660: *(u_int *)addr = size = BPF_MINBUFSIZE;
661: d->bd_bufsize = size;
662: }
663: break;
664:
665: /*
666: * Set link layer read filter.
667: */
668: case BIOCSETF:
669: error = bpf_setf(d, (struct bpf_program *)addr, 0);
670: break;
671:
672: /*
673: * Set link layer write filter.
674: */
675: case BIOCSETWF:
676: error = bpf_setf(d, (struct bpf_program *)addr, 1);
677: break;
678:
679: /*
680: * Flush read packet buffer.
681: */
682: case BIOCFLUSH:
683: s = splnet();
684: bpf_reset_d(d);
685: splx(s);
686: break;
687:
688: /*
689: * Put interface into promiscuous mode.
690: */
691: case BIOCPROMISC:
692: if (d->bd_bif == 0) {
693: /*
694: * No interface attached yet.
695: */
696: error = EINVAL;
697: break;
698: }
699: s = splnet();
700: if (d->bd_promisc == 0) {
701: error = ifpromisc(d->bd_bif->bif_ifp, 1);
702: if (error == 0)
703: d->bd_promisc = 1;
704: }
705: splx(s);
706: break;
707:
708: /*
709: * Get a list of supported device parameters.
710: */
711: case BIOCGDLTLIST:
712: if (d->bd_bif == NULL)
713: error = EINVAL;
714: else
715: error = bpf_getdltlist(d, (struct bpf_dltlist *)addr);
716: break;
717:
718: /*
719: * Get device parameters.
720: */
721: case BIOCGDLT:
722: if (d->bd_bif == 0)
723: error = EINVAL;
724: else
725: *(u_int *)addr = d->bd_bif->bif_dlt;
726: break;
727:
728: /*
729: * Set device parameters.
730: */
731: case BIOCSDLT:
732: if (d->bd_bif == NULL)
733: error = EINVAL;
734: else
735: error = bpf_setdlt(d, *(u_int *)addr);
736: break;
737:
738: /*
739: * Set interface name.
740: */
741: case BIOCGETIF:
742: if (d->bd_bif == 0)
743: error = EINVAL;
744: else
745: bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr);
746: break;
747:
748: /*
749: * Set interface.
750: */
751: case BIOCSETIF:
752: error = bpf_setif(d, (struct ifreq *)addr);
753: break;
754:
755: /*
756: * Set read timeout.
757: */
758: case BIOCSRTIMEOUT:
759: {
760: struct timeval *tv = (struct timeval *)addr;
761:
762: /* Compute number of ticks. */
763: d->bd_rtout = tv->tv_sec * hz + tv->tv_usec / tick;
764: if (d->bd_rtout == 0 && tv->tv_usec != 0)
765: d->bd_rtout = 1;
766: break;
767: }
768:
769: /*
770: * Get read timeout.
771: */
772: case BIOCGRTIMEOUT:
773: {
774: struct timeval *tv = (struct timeval *)addr;
775:
776: tv->tv_sec = d->bd_rtout / hz;
777: tv->tv_usec = (d->bd_rtout % hz) * tick;
778: break;
779: }
780:
781: /*
782: * Get packet stats.
783: */
784: case BIOCGSTATS:
785: {
786: struct bpf_stat *bs = (struct bpf_stat *)addr;
787:
788: bs->bs_recv = d->bd_rcount;
789: bs->bs_drop = d->bd_dcount;
790: break;
791: }
792:
793: /*
794: * Set immediate mode.
795: */
796: case BIOCIMMEDIATE:
797: d->bd_immediate = *(u_int *)addr;
798: break;
799:
800: case BIOCVERSION:
801: {
802: struct bpf_version *bv = (struct bpf_version *)addr;
803:
804: bv->bv_major = BPF_MAJOR_VERSION;
805: bv->bv_minor = BPF_MINOR_VERSION;
806: break;
807: }
808:
809: case BIOCGHDRCMPLT: /* get "header already complete" flag */
810: *(u_int *)addr = d->bd_hdrcmplt;
811: break;
812:
813: case BIOCSHDRCMPLT: /* set "header already complete" flag */
814: d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0;
815: break;
816:
817: case BIOCLOCK: /* set "locked" flag (no reset) */
818: d->bd_locked = 1;
819: break;
820:
821: case BIOCGFILDROP: /* get "filter-drop" flag */
822: *(u_int *)addr = d->bd_fildrop;
823: break;
824:
825: case BIOCSFILDROP: /* set "filter-drop" flag */
826: d->bd_fildrop = *(u_int *)addr ? 1 : 0;
827: break;
828:
829: case BIOCGDIRFILT: /* get direction filter */
830: *(u_int *)addr = d->bd_dirfilt;
831: break;
832:
833: case BIOCSDIRFILT: /* set direction filter */
834: d->bd_dirfilt = (*(u_int *)addr) &
835: (BPF_DIRECTION_IN|BPF_DIRECTION_OUT);
836: break;
837:
838: case FIONBIO: /* Non-blocking I/O */
839: if (*(int *)addr)
840: d->bd_rtout = -1;
841: else
842: d->bd_rtout = 0;
843: break;
844:
845: case FIOASYNC: /* Send signal on receive packets */
846: d->bd_async = *(int *)addr;
847: break;
848:
849: /*
850: * N.B. ioctl (FIOSETOWN) and fcntl (F_SETOWN) both end up doing
851: * the equivalent of a TIOCSPGRP and hence end up here. *However*
852: * TIOCSPGRP's arg is a process group if it's positive and a process
853: * id if it's negative. This is exactly the opposite of what the
854: * other two functions want! Therefore there is code in ioctl and
855: * fcntl to negate the arg before calling here.
856: */
857: case TIOCSPGRP: /* Process or group to send signals to */
858: d->bd_pgid = *(int *)addr;
859: d->bd_siguid = p->p_cred->p_ruid;
860: d->bd_sigeuid = p->p_ucred->cr_uid;
861: break;
862:
863: case TIOCGPGRP:
864: *(int *)addr = d->bd_pgid;
865: break;
866:
867: case BIOCSRSIG: /* Set receive signal */
868: {
869: u_int sig;
870:
871: sig = *(u_int *)addr;
872:
873: if (sig >= NSIG)
874: error = EINVAL;
875: else
876: d->bd_sig = sig;
877: break;
878: }
879: case BIOCGRSIG:
880: *(u_int *)addr = d->bd_sig;
881: break;
882: }
883: return (error);
884: }
885:
886: /*
887: * Set d's packet filter program to fp. If this file already has a filter,
888: * free it and replace it. Returns EINVAL for bogus requests.
889: */
890: int
891: bpf_setf(struct bpf_d *d, struct bpf_program *fp, int wf)
892: {
893: struct bpf_insn *fcode, *old;
894: u_int flen, size;
895: int s;
896:
897: old = wf ? d->bd_wfilter : d->bd_rfilter;
898: if (fp->bf_insns == 0) {
899: if (fp->bf_len != 0)
900: return (EINVAL);
901: s = splnet();
902: if (wf)
903: d->bd_wfilter = 0;
904: else
905: d->bd_rfilter = 0;
906: bpf_reset_d(d);
907: splx(s);
908: if (old != 0)
909: free((caddr_t)old, M_DEVBUF);
910: return (0);
911: }
912: flen = fp->bf_len;
913: if (flen > BPF_MAXINSNS)
914: return (EINVAL);
915:
916: size = flen * sizeof(*fp->bf_insns);
917: fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK);
918: if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
919: bpf_validate(fcode, (int)flen)) {
920: s = splnet();
921: if (wf)
922: d->bd_wfilter = fcode;
923: else
924: d->bd_rfilter = fcode;
925: bpf_reset_d(d);
926: splx(s);
927: if (old != 0)
928: free((caddr_t)old, M_DEVBUF);
929:
930: return (0);
931: }
932: free((caddr_t)fcode, M_DEVBUF);
933: return (EINVAL);
934: }
935:
936: /*
937: * Detach a file from its current interface (if attached at all) and attach
938: * to the interface indicated by the name stored in ifr.
939: * Return an errno or 0.
940: */
941: int
942: bpf_setif(struct bpf_d *d, struct ifreq *ifr)
943: {
944: struct bpf_if *bp, *candidate = NULL;
945: int s, error;
946:
947: /*
948: * Look through attached interfaces for the named one.
949: */
950: for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
951: struct ifnet *ifp = bp->bif_ifp;
952:
953: if (ifp == 0 ||
954: strcmp(ifp->if_xname, ifr->ifr_name) != 0)
955: continue;
956:
957: /*
958: * We found the requested interface.
959: */
960: if (candidate == NULL || candidate->bif_dlt > bp->bif_dlt)
961: candidate = bp;
962: }
963:
964: if (candidate != NULL) {
965: /*
966: * Allocate the packet buffers if we need to.
967: * If we're already attached to requested interface,
968: * just flush the buffer.
969: */
970: if (d->bd_sbuf == 0) {
971: error = bpf_allocbufs(d);
972: if (error != 0)
973: return (error);
974: }
975: s = splnet();
976: if (candidate != d->bd_bif) {
977: if (d->bd_bif)
978: /*
979: * Detach if attached to something else.
980: */
981: bpf_detachd(d);
982:
983: bpf_attachd(d, candidate);
984: }
985: bpf_reset_d(d);
986: splx(s);
987: return (0);
988: }
989: /* Not found. */
990: return (ENXIO);
991: }
992:
993: /*
994: * Copy the interface name to the ifreq.
995: */
996: void
997: bpf_ifname(struct ifnet *ifp, struct ifreq *ifr)
998: {
999: bcopy(ifp->if_xname, ifr->ifr_name, IFNAMSIZ);
1000: }
1001:
1002: /*
1003: * Support for poll() system call
1004: */
1005: int
1006: bpfpoll(dev_t dev, int events, struct proc *p)
1007: {
1008: struct bpf_d *d;
1009: int s, revents;
1010:
1011: revents = events & (POLLIN | POLLRDNORM);
1012: if (revents == 0)
1013: return (0); /* only support reading */
1014:
1015: /*
1016: * An imitation of the FIONREAD ioctl code.
1017: */
1018: d = bpfilter_lookup(minor(dev));
1019: s = splnet();
1020: if (d->bd_hlen == 0 && (!d->bd_immediate || d->bd_slen == 0)) {
1021: revents = 0; /* no data waiting */
1022: /*
1023: * if there's a timeout, mark the time we started waiting.
1024: */
1025: if (d->bd_rtout != -1 && d->bd_rdStart == 0)
1026: d->bd_rdStart = ticks;
1027: selrecord(p, &d->bd_sel);
1028: }
1029: splx(s);
1030: return (revents);
1031: }
1032:
1033: struct filterops bpfread_filtops =
1034: { 1, NULL, filt_bpfrdetach, filt_bpfread };
1035:
1036: int
1037: bpfkqfilter(dev_t dev, struct knote *kn)
1038: {
1039: struct bpf_d *d;
1040: struct klist *klist;
1041: int s;
1042:
1043: d = bpfilter_lookup(minor(dev));
1044: switch (kn->kn_filter) {
1045: case EVFILT_READ:
1046: klist = &d->bd_sel.si_note;
1047: kn->kn_fop = &bpfread_filtops;
1048: break;
1049: default:
1050: return (1);
1051: }
1052:
1053: kn->kn_hook = (caddr_t)((u_long)dev);
1054:
1055: s = splnet();
1056: SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1057: splx(s);
1058:
1059: return (0);
1060: }
1061:
1062: void
1063: filt_bpfrdetach(struct knote *kn)
1064: {
1065: dev_t dev = (dev_t)((u_long)kn->kn_hook);
1066: struct bpf_d *d;
1067: int s;
1068:
1069: d = bpfilter_lookup(minor(dev));
1070: s = splnet();
1071: SLIST_REMOVE(&d->bd_sel.si_note, kn, knote, kn_selnext);
1072: splx(s);
1073: }
1074:
1075: int
1076: filt_bpfread(struct knote *kn, long hint)
1077: {
1078: dev_t dev = (dev_t)((u_long)kn->kn_hook);
1079: struct bpf_d *d;
1080:
1081: d = bpfilter_lookup(minor(dev));
1082: kn->kn_data = d->bd_hlen;
1083: if (d->bd_immediate)
1084: kn->kn_data += d->bd_slen;
1085: return (kn->kn_data > 0);
1086: }
1087:
1088: /*
1089: * Incoming linkage from device drivers. Process the packet pkt, of length
1090: * pktlen, which is stored in a contiguous buffer. The packet is parsed
1091: * by each process' filter, and if accepted, stashed into the corresponding
1092: * buffer.
1093: */
1094: int
1095: bpf_tap(caddr_t arg, u_char *pkt, u_int pktlen, u_int direction)
1096: {
1097: struct bpf_if *bp;
1098: struct bpf_d *d;
1099: size_t slen;
1100: int drop = 0;
1101:
1102: /*
1103: * Note that the ipl does not have to be raised at this point.
1104: * The only problem that could arise here is that if two different
1105: * interfaces shared any data. This is not the case.
1106: */
1107: bp = (struct bpf_if *)arg;
1108: for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
1109: ++d->bd_rcount;
1110: if ((direction & d->bd_dirfilt) != 0)
1111: slen = 0;
1112: else
1113: slen = bpf_filter(d->bd_rfilter, pkt, pktlen, pktlen);
1114: if (slen != 0) {
1115: bpf_catchpacket(d, pkt, pktlen, slen, bcopy);
1116: if (d->bd_fildrop)
1117: drop++;
1118: }
1119: }
1120:
1121: return (drop);
1122: }
1123:
1124: /*
1125: * Copy data from an mbuf chain into a buffer. This code is derived
1126: * from m_copydata in sys/uipc_mbuf.c.
1127: */
1128: void
1129: bpf_mcopy(const void *src_arg, void *dst_arg, size_t len)
1130: {
1131: const struct mbuf *m;
1132: u_int count;
1133: u_char *dst;
1134:
1135: m = src_arg;
1136: dst = dst_arg;
1137: while (len > 0) {
1138: if (m == 0)
1139: panic("bpf_mcopy");
1140: count = min(m->m_len, len);
1141: bcopy(mtod(m, caddr_t), (caddr_t)dst, count);
1142: m = m->m_next;
1143: dst += count;
1144: len -= count;
1145: }
1146: }
1147:
1148: /*
1149: * Incoming linkage from device drivers, when packet is in an mbuf chain.
1150: */
1151: void
1152: bpf_mtap(caddr_t arg, struct mbuf *m, u_int direction)
1153: {
1154: struct bpf_if *bp = (struct bpf_if *)arg;
1155: struct bpf_d *d;
1156: size_t pktlen, slen;
1157: struct mbuf *m0;
1158:
1159: if (m == NULL)
1160: return;
1161:
1162: pktlen = 0;
1163: for (m0 = m; m0 != 0; m0 = m0->m_next)
1164: pktlen += m0->m_len;
1165:
1166: for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
1167: ++d->bd_rcount;
1168: if ((direction & d->bd_dirfilt) != 0)
1169: slen = 0;
1170: else
1171: slen = bpf_filter(d->bd_rfilter, (u_char *)m,
1172: pktlen, 0);
1173:
1174: if (slen == 0)
1175: continue;
1176:
1177: bpf_catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
1178: if (d->bd_fildrop)
1179: m->m_flags |= M_FILDROP;
1180: }
1181: }
1182:
1183: /*
1184: * Incoming linkage from device drivers, where we have a mbuf chain
1185: * but need to prepend some arbitrary header from a linear buffer.
1186: *
1187: * Con up a minimal dummy header to pacify bpf. Allocate (only) a
1188: * struct m_hdr on the stack. This is safe as bpf only reads from the
1189: * fields in this header that we initialize, and will not try to free
1190: * it or keep a pointer to it.
1191: */
1192: void
1193: bpf_mtap_hdr(caddr_t arg, caddr_t data, u_int dlen, struct mbuf *m,
1194: u_int direction)
1195: {
1196: struct m_hdr mh;
1197:
1198: mh.mh_flags = 0;
1199: mh.mh_next = m;
1200: mh.mh_len = dlen;
1201: mh.mh_data = data;
1202:
1203: bpf_mtap(arg, (struct mbuf *) &mh, direction);
1204: m->m_flags |= mh.mh_flags & M_FILDROP;
1205: }
1206:
1207: /*
1208: * Incoming linkage from device drivers, where we have a mbuf chain
1209: * but need to prepend the address family.
1210: *
1211: * Con up a minimal dummy header to pacify bpf. We allocate (only) a
1212: * struct m_hdr on the stack. This is safe as bpf only reads from the
1213: * fields in this header that we initialize, and will not try to free
1214: * it or keep a pointer to it.
1215: */
1216: void
1217: bpf_mtap_af(caddr_t arg, u_int32_t af, struct mbuf *m, u_int direction)
1218: {
1219: struct m_hdr mh;
1220:
1221: mh.mh_flags = 0;
1222: mh.mh_next = m;
1223: mh.mh_len = 4;
1224: mh.mh_data = (caddr_t)⁡
1225:
1226: bpf_mtap(arg, (struct mbuf *) &mh, direction);
1227: m->m_flags |= mh.mh_flags & M_FILDROP;
1228: }
1229:
1230: /*
1231: * Move the packet data from interface memory (pkt) into the
1232: * store buffer. Return 1 if it's time to wakeup a listener (buffer full),
1233: * otherwise 0. "copy" is the routine called to do the actual data
1234: * transfer. bcopy is passed in to copy contiguous chunks, while
1235: * bpf_mcopy is passed in to copy mbuf chains. In the latter case,
1236: * pkt is really an mbuf.
1237: */
1238: void
1239: bpf_catchpacket(struct bpf_d *d, u_char *pkt, size_t pktlen, size_t snaplen,
1240: void (*cpfn)(const void *, void *, size_t))
1241: {
1242: struct bpf_hdr *hp;
1243: int totlen, curlen;
1244: int hdrlen = d->bd_bif->bif_hdrlen;
1245: struct timeval tv;
1246:
1247: /*
1248: * Figure out how many bytes to move. If the packet is
1249: * greater or equal to the snapshot length, transfer that
1250: * much. Otherwise, transfer the whole packet (unless
1251: * we hit the buffer size limit).
1252: */
1253: totlen = hdrlen + min(snaplen, pktlen);
1254: if (totlen > d->bd_bufsize)
1255: totlen = d->bd_bufsize;
1256:
1257: /*
1258: * Round up the end of the previous packet to the next longword.
1259: */
1260: curlen = BPF_WORDALIGN(d->bd_slen);
1261: if (curlen + totlen > d->bd_bufsize) {
1262: /*
1263: * This packet will overflow the storage buffer.
1264: * Rotate the buffers if we can, then wakeup any
1265: * pending reads.
1266: */
1267: if (d->bd_fbuf == 0) {
1268: /*
1269: * We haven't completed the previous read yet,
1270: * so drop the packet.
1271: */
1272: ++d->bd_dcount;
1273: return;
1274: }
1275: ROTATE_BUFFERS(d);
1276: bpf_wakeup(d);
1277: curlen = 0;
1278: }
1279:
1280: /*
1281: * Append the bpf header.
1282: */
1283: hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
1284: microtime(&tv);
1285: hp->bh_tstamp.tv_sec = tv.tv_sec;
1286: hp->bh_tstamp.tv_usec = tv.tv_usec;
1287: hp->bh_datalen = pktlen;
1288: hp->bh_hdrlen = hdrlen;
1289: /*
1290: * Copy the packet data into the store buffer and update its length.
1291: */
1292: (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen));
1293: d->bd_slen = curlen + totlen;
1294:
1295: if (d->bd_immediate) {
1296: /*
1297: * Immediate mode is set. A packet arrived so any
1298: * reads should be woken up.
1299: */
1300: bpf_wakeup(d);
1301: }
1302:
1303: if (d->bd_rdStart && (d->bd_rtout + d->bd_rdStart < ticks)) {
1304: /*
1305: * we could be selecting on the bpf, and we
1306: * may have timeouts set. We got here by getting
1307: * a packet, so wake up the reader.
1308: */
1309: if (d->bd_fbuf) {
1310: d->bd_rdStart = 0;
1311: ROTATE_BUFFERS(d);
1312: bpf_wakeup(d);
1313: curlen = 0;
1314: }
1315: }
1316: }
1317:
1318: /*
1319: * Initialize all nonzero fields of a descriptor.
1320: */
1321: int
1322: bpf_allocbufs(struct bpf_d *d)
1323: {
1324: d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_NOWAIT);
1325: if (d->bd_fbuf == NULL)
1326: return (ENOBUFS);
1327: d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_NOWAIT);
1328: if (d->bd_sbuf == NULL) {
1329: free(d->bd_fbuf, M_DEVBUF);
1330: return (ENOBUFS);
1331: }
1332: d->bd_slen = 0;
1333: d->bd_hlen = 0;
1334: return (0);
1335: }
1336:
1337: /*
1338: * Free buffers currently in use by a descriptor
1339: * when the reference count drops to zero.
1340: */
1341: void
1342: bpf_freed(struct bpf_d *d)
1343: {
1344: if (--d->bd_ref > 0)
1345: return;
1346:
1347: if (d->bd_sbuf != 0) {
1348: free(d->bd_sbuf, M_DEVBUF);
1349: if (d->bd_hbuf != 0)
1350: free(d->bd_hbuf, M_DEVBUF);
1351: if (d->bd_fbuf != 0)
1352: free(d->bd_fbuf, M_DEVBUF);
1353: }
1354: if (d->bd_rfilter)
1355: free((caddr_t)d->bd_rfilter, M_DEVBUF);
1356: if (d->bd_wfilter)
1357: free((caddr_t)d->bd_wfilter, M_DEVBUF);
1358:
1359: bpfilter_destroy(d);
1360: }
1361:
1362: /*
1363: * Attach an interface to bpf. driverp is a pointer to a (struct bpf_if *)
1364: * in the driver's softc; dlt is the link layer type; hdrlen is the fixed
1365: * size of the link header (variable length headers not yet supported).
1366: */
1367: void
1368: bpfattach(caddr_t *driverp, struct ifnet *ifp, u_int dlt, u_int hdrlen)
1369: {
1370: struct bpf_if *bp;
1371: bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT);
1372:
1373: if (bp == 0)
1374: panic("bpfattach");
1375:
1376: bp->bif_dlist = 0;
1377: bp->bif_driverp = (struct bpf_if **)driverp;
1378: bp->bif_ifp = ifp;
1379: bp->bif_dlt = dlt;
1380:
1381: bp->bif_next = bpf_iflist;
1382: bpf_iflist = bp;
1383:
1384: *bp->bif_driverp = NULL;
1385:
1386: /*
1387: * Compute the length of the bpf header. This is not necessarily
1388: * equal to SIZEOF_BPF_HDR because we want to insert spacing such
1389: * that the network layer header begins on a longword boundary (for
1390: * performance reasons and to alleviate alignment restrictions).
1391: */
1392: bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
1393: }
1394:
1395: /* Detach an interface from its attached bpf device. */
1396: void
1397: bpfdetach(struct ifnet *ifp)
1398: {
1399: struct bpf_if *bp, *nbp, **pbp = &bpf_iflist;
1400: struct bpf_d *bd;
1401: int maj;
1402:
1403: for (bp = bpf_iflist; bp; bp = nbp) {
1404: nbp= bp->bif_next;
1405: if (bp->bif_ifp == ifp) {
1406: *pbp = nbp;
1407:
1408: /* Locate the major number. */
1409: for (maj = 0; maj < nchrdev; maj++)
1410: if (cdevsw[maj].d_open == bpfopen)
1411: break;
1412:
1413: for (bd = bp->bif_dlist; bd; bd = bp->bif_dlist) {
1414: struct bpf_d *d;
1415:
1416: /*
1417: * Locate the minor number and nuke the vnode
1418: * for any open instance.
1419: */
1420: LIST_FOREACH(d, &bpf_d_list, bd_list)
1421: if (d == bd) {
1422: vdevgone(maj, d->bd_unit,
1423: d->bd_unit, VCHR);
1424: break;
1425: }
1426: }
1427:
1428: free(bp, M_DEVBUF);
1429: } else
1430: pbp = &bp->bif_next;
1431: }
1432: ifp->if_bpf = NULL;
1433: }
1434:
1435: int
1436: bpf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
1437: size_t newlen)
1438: {
1439: int newval;
1440: int error;
1441:
1442: if (namelen != 1)
1443: return (ENOTDIR);
1444:
1445: switch (name[0]) {
1446: case NET_BPF_BUFSIZE:
1447: newval = bpf_bufsize;
1448: error = sysctl_int(oldp, oldlenp, newp, newlen, &newval);
1449: if (error)
1450: return (error);
1451: if (newval < BPF_MINBUFSIZE || newval > bpf_maxbufsize)
1452: return (EINVAL);
1453: bpf_bufsize = newval;
1454: break;
1455: case NET_BPF_MAXBUFSIZE:
1456: newval = bpf_maxbufsize;
1457: error = sysctl_int(oldp, oldlenp, newp, newlen, &newval);
1458: if (error)
1459: return (error);
1460: if (newval < BPF_MINBUFSIZE)
1461: return (EINVAL);
1462: bpf_maxbufsize = newval;
1463: break;
1464: default:
1465: return (EOPNOTSUPP);
1466: }
1467: return (0);
1468: }
1469:
1470: struct bpf_d *
1471: bpfilter_lookup(int unit)
1472: {
1473: struct bpf_d *bd;
1474:
1475: LIST_FOREACH(bd, &bpf_d_list, bd_list)
1476: if (bd->bd_unit == unit)
1477: return (bd);
1478: return (NULL);
1479: }
1480:
1481: struct bpf_d *
1482: bpfilter_create(int unit)
1483: {
1484: struct bpf_d *bd;
1485:
1486: if ((bd = bpfilter_lookup(unit)) != NULL)
1487: return (NULL);
1488: if ((bd = malloc(sizeof(*bd), M_DEVBUF, M_NOWAIT)) != NULL) {
1489: bzero(bd, sizeof(*bd));
1490: bd->bd_unit = unit;
1491: LIST_INSERT_HEAD(&bpf_d_list, bd, bd_list);
1492: }
1493: return (bd);
1494: }
1495:
1496: void
1497: bpfilter_destroy(struct bpf_d *bd)
1498: {
1499: LIST_REMOVE(bd, bd_list);
1500: free(bd, M_DEVBUF);
1501: }
1502:
1503: /*
1504: * Get a list of available data link type of the interface.
1505: */
1506: int
1507: bpf_getdltlist(struct bpf_d *d, struct bpf_dltlist *bfl)
1508: {
1509: int n, error;
1510: struct ifnet *ifp;
1511: struct bpf_if *bp;
1512:
1513: ifp = d->bd_bif->bif_ifp;
1514: n = 0;
1515: error = 0;
1516: for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
1517: if (bp->bif_ifp != ifp)
1518: continue;
1519: if (bfl->bfl_list != NULL) {
1520: if (n >= bfl->bfl_len)
1521: return (ENOMEM);
1522: error = copyout(&bp->bif_dlt,
1523: bfl->bfl_list + n, sizeof(u_int));
1524: if (error)
1525: break;
1526: }
1527: n++;
1528: }
1529:
1530: bfl->bfl_len = n;
1531: return (error);
1532: }
1533:
1534: /*
1535: * Set the data link type of a BPF instance.
1536: */
1537: int
1538: bpf_setdlt(struct bpf_d *d, u_int dlt)
1539: {
1540: int s;
1541: struct ifnet *ifp;
1542: struct bpf_if *bp;
1543:
1544: if (d->bd_bif->bif_dlt == dlt)
1545: return (0);
1546: ifp = d->bd_bif->bif_ifp;
1547: for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
1548: if (bp->bif_ifp == ifp && bp->bif_dlt == dlt)
1549: break;
1550: }
1551: if (bp == NULL)
1552: return (EINVAL);
1553: s = splnet();
1554: bpf_detachd(d);
1555: bpf_attachd(d, bp);
1556: bpf_reset_d(d);
1557: splx(s);
1558: return (0);
1559: }
CVSweb