- struct bpf_program bpf;
- char ifname[IFNAMSIZ];
- pcap_t *pp;
- int err;
- int fd;
-
- assert(__pp == NULL);
-
- if (interface_up(iface) < 0) {
- return (-1);
- }
- if (__get_ether_addr(iface, __lladdr) == -1) {
- return (-1);
- }
- if (if_indextoname(iface, ifname) == NULL) {
- return (-1);
- }
-
- pp = pcap_open_live(ifname, 1500, 0, 0, __pcap_errbuf);
- if (pp == NULL) {
- return (-1);
- }
- err = pcap_set_datalink(pp, DLT_EN10MB);
- if (err == -1) {
- daemon_log(LOG_ERR, "pcap_set_datalink: %s", pcap_geterr(pp));
- pcap_close(pp);
- return (-1);
- }
- err = pcap_setdirection(pp, PCAP_D_IN);
- if (err == -1) {
- daemon_log(LOG_ERR, "pcap_setdirection: %s", pcap_geterr(pp));
- pcap_close(pp);
- return (-1);
- }
-
- fd = pcap_get_selectable_fd(pp);
- if (fd == -1) {
- pcap_close(pp);
- return (-1);
- }
-#if 0
- /* XXX: can we use this with pcap_next_ex() ? */
- err = pcap_setnonblock(pp, 1, __pcap_errbuf);
- if (err == -1) {
- pcap_close(pp);
- return (-1);
- }
-#endif
+ struct bpf_program bpf;
+ char *filter;
+ char ifname[IFNAMSIZ];
+ pcap_t *pp;
+ int err;
+ int fd;
+
+ assert(__pp == NULL);
+
+ if (interface_up(iface) < 0) {
+ return (-1);
+ }
+ if (__get_ether_addr(iface, __lladdr) == -1) {
+ return (-1);
+ }
+ if (if_indextoname(iface, ifname) == NULL) {
+ return (-1);
+ }
+
+ /*
+ * Using a timeout for BPF is fairly portable across BSDs. On most
+ * modern versions, using the timeout/nonblock/poll method results in
+ * fairly sane behavior, with the timeout only coming into play during
+ * the next_ex() call itself (so, for us, that's only when there's
+ * data). On older versions, it may result in a PCAP_TIMEOUT busy-wait
+ * on some versions, though, as the poll() may terminate at the
+ * PCAP_TIMEOUT instead of the poll() timeout.
+ */
+ pp = pcap_open_live(ifname, 1500, 0, PCAP_TIMEOUT, __pcap_errbuf);
+ if (pp == NULL) {
+ return (-1);
+ }
+ err = pcap_set_datalink(pp, DLT_EN10MB);
+ if (err == -1) {
+ daemon_log(LOG_ERR, "pcap_set_datalink: %s", pcap_geterr(pp));
+ pcap_close(pp);
+ return (-1);
+ }
+ err = pcap_setdirection(pp, PCAP_D_IN);
+ if (err == -1) {
+ daemon_log(LOG_ERR, "pcap_setdirection: %s", pcap_geterr(pp));
+ pcap_close(pp);
+ return (-1);
+ }
+
+ fd = pcap_get_selectable_fd(pp);
+ if (fd == -1) {
+ pcap_close(pp);
+ return (-1);
+ }
+
+ /*
+ * Using setnonblock is a portability stop-gap. Using the timeout in
+ * combination with setnonblock will ensure on most BSDs that the
+ * next_ex call returns in a timely fashion.
+ */
+ err = pcap_setnonblock(pp, 1, __pcap_errbuf);
+ if (err == -1) {
+ pcap_close(pp);
+ return (-1);
+ }