diff options
author | Guy Harris <guy@alum.mit.edu> | 2017-12-11 12:56:12 -0800 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2017-12-11 12:56:12 -0800 |
commit | b086a6586a86ede9e58e8edba23ba70720274fca (patch) | |
tree | 1db4d39b6fc466f1763e012ddd354935f92bd283 /pcap-netmap.c | |
parent | b98a97f74e9bf0a35c2e955f56c1a63812828860 (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.c | 49 |
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__ */ } |