Changeset View
Changeset View
Standalone View
Standalone View
sys/net/bpf.c
Show First 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | static void catchpacket(struct bpf_d *, u_char *, u_int, u_int, | ||||
void (*)(struct bpf_d *, caddr_t, u_int, void *, u_int), | void (*)(struct bpf_d *, caddr_t, u_int, void *, u_int), | ||||
struct bintime *); | struct bintime *); | ||||
static void reset_d(struct bpf_d *); | static void reset_d(struct bpf_d *); | ||||
static int bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd); | static int bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd); | ||||
static int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *); | static int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *); | ||||
static int bpf_setdlt(struct bpf_d *, u_int); | static int bpf_setdlt(struct bpf_d *, u_int); | ||||
static void filt_bpfdetach(struct knote *); | static void filt_bpfdetach(struct knote *); | ||||
static int filt_bpfread(struct knote *, long); | static int filt_bpfread(struct knote *, long); | ||||
static int filt_bpfwrite(struct knote *, long); | |||||
static void bpf_drvinit(void *); | static void bpf_drvinit(void *); | ||||
static int bpf_stats_sysctl(SYSCTL_HANDLER_ARGS); | static int bpf_stats_sysctl(SYSCTL_HANDLER_ARGS); | ||||
SYSCTL_NODE(_net, OID_AUTO, bpf, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | SYSCTL_NODE(_net, OID_AUTO, bpf, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | ||||
"bpf sysctl"); | "bpf sysctl"); | ||||
int bpf_maxinsns = BPF_MAXINSNS; | int bpf_maxinsns = BPF_MAXINSNS; | ||||
SYSCTL_INT(_net_bpf, OID_AUTO, maxinsns, CTLFLAG_RW, | SYSCTL_INT(_net_bpf, OID_AUTO, maxinsns, CTLFLAG_RW, | ||||
&bpf_maxinsns, 0, "Maximum bpf program instructions"); | &bpf_maxinsns, 0, "Maximum bpf program instructions"); | ||||
Show All 28 Lines | |||||
}; | }; | ||||
static struct filterops bpfread_filtops = { | static struct filterops bpfread_filtops = { | ||||
.f_isfd = 1, | .f_isfd = 1, | ||||
.f_detach = filt_bpfdetach, | .f_detach = filt_bpfdetach, | ||||
.f_event = filt_bpfread, | .f_event = filt_bpfread, | ||||
}; | }; | ||||
static struct filterops bpfwrite_filtops = { | |||||
.f_isfd = 1, | |||||
.f_detach = filt_bpfdetach, | |||||
.f_event = filt_bpfwrite, | |||||
}; | |||||
/* | /* | ||||
* LOCKING MODEL USED BY BPF | * LOCKING MODEL USED BY BPF | ||||
* | * | ||||
* Locks: | * Locks: | ||||
* 1) global lock (BPF_LOCK). Sx, used to protect some global counters, | * 1) global lock (BPF_LOCK). Sx, used to protect some global counters, | ||||
* every bpf_iflist changes, serializes ioctl access to bpf descriptors. | * every bpf_iflist changes, serializes ioctl access to bpf descriptors. | ||||
* 2) Descriptor lock. Mutex, used to protect BPF buffers and various | * 2) Descriptor lock. Mutex, used to protect BPF buffers and various | ||||
* structure fields used by bpf_*tap* code. | * structure fields used by bpf_*tap* code. | ||||
▲ Show 20 Lines • Show All 1,885 Lines • ▼ Show 20 Lines | |||||
* Support for kevent() system call. Register EVFILT_READ filters and | * Support for kevent() system call. Register EVFILT_READ filters and | ||||
* reject all others. | * reject all others. | ||||
*/ | */ | ||||
int | int | ||||
bpfkqfilter(struct cdev *dev, struct knote *kn) | bpfkqfilter(struct cdev *dev, struct knote *kn) | ||||
{ | { | ||||
struct bpf_d *d; | struct bpf_d *d; | ||||
if (devfs_get_cdevpriv((void **)&d) != 0 || | if (devfs_get_cdevpriv((void **)&d) != 0) | ||||
kn->kn_filter != EVFILT_READ) | |||||
return (1); | return (1); | ||||
switch (kn->kn_filter) { | |||||
case EVFILT_READ: | |||||
kn->kn_fop = &bpfread_filtops; | |||||
break; | |||||
case EVFILT_WRITE: | |||||
kn->kn_fop = &bpfwrite_filtops; | |||||
break; | |||||
default: | |||||
return (1); | |||||
} | |||||
/* | /* | ||||
* Refresh PID associated with this descriptor. | * Refresh PID associated with this descriptor. | ||||
*/ | */ | ||||
BPFD_LOCK(d); | BPFD_LOCK(d); | ||||
BPF_PID_REFRESH_CUR(d); | BPF_PID_REFRESH_CUR(d); | ||||
kn->kn_fop = &bpfread_filtops; | |||||
kn->kn_hook = d; | kn->kn_hook = d; | ||||
knlist_add(&d->bd_sel.si_note, kn, 1); | knlist_add(&d->bd_sel.si_note, kn, 1); | ||||
BPFD_UNLOCK(d); | BPFD_UNLOCK(d); | ||||
return (0); | return (0); | ||||
ae: I'd prefer a bit less code duplication:
```
struct filterops *ops;
...
switch (kn… | |||||
} | } | ||||
static void | static void | ||||
filt_bpfdetach(struct knote *kn) | filt_bpfdetach(struct knote *kn) | ||||
{ | { | ||||
struct bpf_d *d = (struct bpf_d *)kn->kn_hook; | struct bpf_d *d = (struct bpf_d *)kn->kn_hook; | ||||
knlist_remove(&d->bd_sel.si_note, kn, 0); | knlist_remove(&d->bd_sel.si_note, kn, 0); | ||||
Show All 16 Lines | if (!d->bd_hbuf_in_use && d->bd_hbuf) | ||||
kn->kn_data += d->bd_hlen; | kn->kn_data += d->bd_hlen; | ||||
} else if (d->bd_rtout > 0 && d->bd_state == BPF_IDLE) { | } else if (d->bd_rtout > 0 && d->bd_state == BPF_IDLE) { | ||||
callout_reset(&d->bd_callout, d->bd_rtout, | callout_reset(&d->bd_callout, d->bd_rtout, | ||||
bpf_timed_out, d); | bpf_timed_out, d); | ||||
d->bd_state = BPF_WAITING; | d->bd_state = BPF_WAITING; | ||||
} | } | ||||
return (ready); | return (ready); | ||||
} | |||||
static int | |||||
filt_bpfwrite(struct knote *kn, long hint) | |||||
{ | |||||
struct bpf_d *d = (struct bpf_d *)kn->kn_hook; | |||||
BPFD_LOCK_ASSERT(d); | |||||
kn->kn_data = d->bd_bif->bif_ifp->if_mtu; | |||||
return (1); | |||||
} | } | ||||
#define BPF_TSTAMP_NONE 0 | #define BPF_TSTAMP_NONE 0 | ||||
#define BPF_TSTAMP_FAST 1 | #define BPF_TSTAMP_FAST 1 | ||||
#define BPF_TSTAMP_NORMAL 2 | #define BPF_TSTAMP_NORMAL 2 | ||||
#define BPF_TSTAMP_EXTERN 3 | #define BPF_TSTAMP_EXTERN 3 | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 897 Lines • Show Last 20 Lines |
I'd prefer a bit less code duplication:
Also it seems you need to modify kqueue(2).