aboutsummaryrefslogtreecommitdiff
path: root/pcap-netmap.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2017-12-11 12:56:12 -0800
committerGuy Harris <guy@alum.mit.edu>2017-12-11 12:56:12 -0800
commitb086a6586a86ede9e58e8edba23ba70720274fca (patch)
tree1db4d39b6fc466f1763e012ddd354935f92bd283 /pcap-netmap.c
parentb98a97f74e9bf0a35c2e955f56c1a63812828860 (diff)
Check for FreeBSD, not Linux, when checking for IFF_PPROMISC and ifr_flagshigh.
Note that we should be checking for FreeBSD *and* DragonFly BSD (perhaps we should be checkign for IFF_PPROMISC and ifr_flagshigh). Add comments explaining what we're doing.
Diffstat (limited to 'pcap-netmap.c')
-rw-r--r--pcap-netmap.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/pcap-netmap.c b/pcap-netmap.c
index 61c820cc..245c8eaa 100644
--- a/pcap-netmap.c
+++ b/pcap-netmap.c
@@ -43,12 +43,15 @@
#include "pcap-int.h"
#include "pcap-netmap.h"
-#if defined (linux)
-/* On FreeBSD we use IFF_PPROMISC which is in ifr_flagshigh.
- * remap to IFF_PROMISC on linux
- */
-#define IFF_PPROMISC IFF_PROMISC
-#endif /* linux */
+#ifndef __FreeBSD__
+ /*
+ * On FreeBSD we use IFF_PPROMISC which is in ifr_flagshigh.
+ * Remap to IFF_PROMISC on other platforms.
+ *
+ * XXX - DragonFly BSD?
+ */
+ #define IFF_PPROMISC IFF_PROMISC
+#endif /* __FreeBSD__ */
struct pcap_netmap {
struct nm_desc *d; /* pointer returned by nm_open() */
@@ -142,8 +145,25 @@ pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags)
strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name));
switch (what) {
case SIOCSIFFLAGS:
+ /*
+ * The flags we pass in are 32-bit and unsigned.
+ *
+ * On most if not all UN*Xes, ifr_flags is 16-bit and
+ * signed, and the result of assigning a longer
+ * unsigned value to a shorter signed value is
+ * implementation-defined (even if, in practice, it'll
+ * do what's intended on all platforms we support
+ * result of assigning a 32-bit unsigned value).
+ * So we mask out the upper 16 bits.
+ */
ifr.ifr_flags = *if_flags & 0xffff;
#ifdef __FreeBSD__
+ /*
+ * In FreeBSD, we need to set the high-order flags,
+ * as we're using IFF_PPROMISC, which is in those bits.
+ *
+ * XXX - DragonFly BSD?
+ */
ifr.ifr_flagshigh = *if_flags >> 16;
#endif /* __FreeBSD__ */
break;
@@ -152,8 +172,25 @@ pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags)
if (!error) {
switch (what) {
case SIOCGIFFLAGS:
+ /*
+ * The flags we return are 32-bit.
+ *
+ * On most if not all UN*Xes, ifr_flags is
+ * 16-bit and signed, and will get sign-
+ * extended, so that the upper 16 bits of
+ * those flags will be forced on. So we
+ * mask out the upper 16 bits of the
+ * sign-extended value.
+ */
*if_flags = ifr.ifr_flags & 0xffff;
#ifdef __FreeBSD__
+ /*
+ * In FreeBSD, we need to return the
+ * high-order flags, as we're using
+ * IFF_PPROMISC, which is in those bits.
+ *
+ * XXX - DragonFly BSD?
+ */
*if_flags |= (ifr.ifr_flagshigh << 16);
#endif /* __FreeBSD__ */
}