Programming interface MAC filter without enabling PROMISC on an interface from user space.

Tom Judge tom at tomjudge.com
Mon Jan 14 08:38:59 PST 2008


Bruce M. Simpson wrote:
> Tom Judge wrote:
>> Hi,
>>
>> I have just started experimenting with OpenLLDP and come across a 
>> little bit of a nasty.  When it opens the interface, it puts it into 
>> PROMISC mode,  which I don't really want to happen.  Is there any way 
>> to add the LLDP MAC address (01-80-C2-00-00-0E) to the interface mac 
>> filter from user space, so that the interface does not have to be set 
>> to PROMISC?
> 
> There *is* an API for this but it's not integrated into pcap or bpf; see 
> SIOCADDMULTI and SIOCDELMULTI. There are some issues with doing that 
> portably, Windows and Linux do things somewhat differently in this space.
> 
> Really we could do with a KPI for this so that the references are 
> properly refcounted. If you have other link layer multicast listeners 
> it's not guaranteed that the stack will correctly restore the hash 
> filters at the driver level if it has to enable ALLMULTI mode.
> 
> You almost certainly don't want to set PROMISC if you are ever going to 
> do any kind of IP forwarding, although I believe I fixed that historic 
> bug whereby the IP layer kept seeing its own packets about a year ago.
> 
> later
> BMS


Hi Bruce,

Thanks for the response.  I have a quick grep of the src tree to find an 
example of this being used and only found the following from 
wpa_supplicant and I have a few questions:

	* I am presuming that this will do what I want, am I correct?

	* If I was only ever to add the address to an interface an never delete 
it would this cause any problems?  I.e. when lldpd ends, or is restarted 
and tries to add the address again?

	* Alternatively is there a way to query the filter to ask what 
addresses it is currently programmed for?


At this stage I am not looking for portability, I just want a working 
solution for a FreeBSD only shop.

Thanks again

Tom


 From contrib/wpa_supplicant/driver_wired.c:

static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, 
int add)
{
     struct ifreq ifr;
     int s;

     s = socket(PF_INET, SOCK_DGRAM, 0);
     if (s < 0) {
         perror("socket");
         return -1;
     }

     memset(&ifr, 0, sizeof(ifr));
     strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
     ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
     memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);

     if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
         perror("ioctl[SIOC{ADD/DEL}MULTI]");
         close(s);
         return -1;
     }
     close(s);
     return 0;
}



More information about the freebsd-net mailing list