Home | History | Annotate | Download | only in drivers
      1 /*
      2  * Wired Ethernet driver interface
      3  * Copyright (c) 2005-2009, Jouni Malinen <j (at) w1.fi>
      4  * Copyright (c) 2004, Gunter Burchardt <tira (at) isx.de>
      5  *
      6  * This software may be distributed under the terms of the BSD license.
      7  * See README for more details.
      8  */
      9 
     10 #include "includes.h"
     11 #include <sys/ioctl.h>
     12 #include <net/if.h>
     13 #ifdef __linux__
     14 #include <netpacket/packet.h>
     15 #include <net/if_arp.h>
     16 #include <net/if.h>
     17 #endif /* __linux__ */
     18 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
     19 #include <net/if_dl.h>
     20 #include <net/if_media.h>
     21 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */
     22 #ifdef __sun__
     23 #include <sys/sockio.h>
     24 #endif /* __sun__ */
     25 
     26 #include "common.h"
     27 #include "eloop.h"
     28 #include "driver.h"
     29 
     30 #ifdef _MSC_VER
     31 #pragma pack(push, 1)
     32 #endif /* _MSC_VER */
     33 
     34 struct ieee8023_hdr {
     35 	u8 dest[6];
     36 	u8 src[6];
     37 	u16 ethertype;
     38 } STRUCT_PACKED;
     39 
     40 #ifdef _MSC_VER
     41 #pragma pack(pop)
     42 #endif /* _MSC_VER */
     43 
     44 static const u8 pae_group_addr[ETH_ALEN] =
     45 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
     46 
     47 
     48 struct wpa_driver_wired_data {
     49 	char ifname[IFNAMSIZ + 1];
     50 	void *ctx;
     51 
     52 	int sock; /* raw packet socket for driver access */
     53 	int dhcp_sock; /* socket for dhcp packets */
     54 	int use_pae_group_addr;
     55 
     56 	int pf_sock;
     57 	int membership, multi, iff_allmulti, iff_up;
     58 };
     59 
     60 
     61 /* TODO: detecting new devices should eventually be changed from using DHCP
     62  * snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
     63  * based on ebtables, etc. */
     64 
     65 struct dhcp_message {
     66 	u_int8_t op;
     67 	u_int8_t htype;
     68 	u_int8_t hlen;
     69 	u_int8_t hops;
     70 	u_int32_t xid;
     71 	u_int16_t secs;
     72 	u_int16_t flags;
     73 	u_int32_t ciaddr;
     74 	u_int32_t yiaddr;
     75 	u_int32_t siaddr;
     76 	u_int32_t giaddr;
     77 	u_int8_t chaddr[16];
     78 	u_int8_t sname[64];
     79 	u_int8_t file[128];
     80 	u_int32_t cookie;
     81 	u_int8_t options[308]; /* 312 - cookie */
     82 };
     83 
     84 
     85 static int wired_multicast_membership(int sock, int ifindex,
     86 				      const u8 *addr, int add)
     87 {
     88 #ifdef __linux__
     89 	struct packet_mreq mreq;
     90 
     91 	if (sock < 0)
     92 		return -1;
     93 
     94 	os_memset(&mreq, 0, sizeof(mreq));
     95 	mreq.mr_ifindex = ifindex;
     96 	mreq.mr_type = PACKET_MR_MULTICAST;
     97 	mreq.mr_alen = ETH_ALEN;
     98 	os_memcpy(mreq.mr_address, addr, ETH_ALEN);
     99 
    100 	if (setsockopt(sock, SOL_PACKET,
    101 		       add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
    102 		       &mreq, sizeof(mreq)) < 0) {
    103 		wpa_printf(MSG_ERROR, "setsockopt: %s", strerror(errno));
    104 		return -1;
    105 	}
    106 	return 0;
    107 #else /* __linux__ */
    108 	return -1;
    109 #endif /* __linux__ */
    110 }
    111 
    112 
    113 #ifdef __linux__
    114 static void handle_data(void *ctx, unsigned char *buf, size_t len)
    115 {
    116 #ifdef HOSTAPD
    117 	struct ieee8023_hdr *hdr;
    118 	u8 *pos, *sa;
    119 	size_t left;
    120 	union wpa_event_data event;
    121 
    122 	/* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
    123 	 * 2 byte ethertype */
    124 	if (len < 14) {
    125 		wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)",
    126 			   (unsigned long) len);
    127 		return;
    128 	}
    129 
    130 	hdr = (struct ieee8023_hdr *) buf;
    131 
    132 	switch (ntohs(hdr->ethertype)) {
    133 		case ETH_P_PAE:
    134 			wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
    135 			sa = hdr->src;
    136 			os_memset(&event, 0, sizeof(event));
    137 			event.new_sta.addr = sa;
    138 			wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
    139 
    140 			pos = (u8 *) (hdr + 1);
    141 			left = len - sizeof(*hdr);
    142 			drv_event_eapol_rx(ctx, sa, pos, left);
    143 		break;
    144 
    145 	default:
    146 		wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
    147 			   ntohs(hdr->ethertype));
    148 		break;
    149 	}
    150 #endif /* HOSTAPD */
    151 }
    152 
    153 
    154 static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
    155 {
    156 	int len;
    157 	unsigned char buf[3000];
    158 
    159 	len = recv(sock, buf, sizeof(buf), 0);
    160 	if (len < 0) {
    161 		wpa_printf(MSG_ERROR, "recv: %s", strerror(errno));
    162 		return;
    163 	}
    164 
    165 	handle_data(eloop_ctx, buf, len);
    166 }
    167 
    168 
    169 static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx)
    170 {
    171 	int len;
    172 	unsigned char buf[3000];
    173 	struct dhcp_message *msg;
    174 	u8 *mac_address;
    175 	union wpa_event_data event;
    176 
    177 	len = recv(sock, buf, sizeof(buf), 0);
    178 	if (len < 0) {
    179 		wpa_printf(MSG_ERROR, "recv: %s", strerror(errno));
    180 		return;
    181 	}
    182 
    183 	/* must contain at least dhcp_message->chaddr */
    184 	if (len < 44) {
    185 		wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len);
    186 		return;
    187 	}
    188 
    189 	msg = (struct dhcp_message *) buf;
    190 	mac_address = (u8 *) &(msg->chaddr);
    191 
    192 	wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR,
    193 		   MAC2STR(mac_address));
    194 
    195 	os_memset(&event, 0, sizeof(event));
    196 	event.new_sta.addr = mac_address;
    197 	wpa_supplicant_event(eloop_ctx, EVENT_NEW_STA, &event);
    198 }
    199 #endif /* __linux__ */
    200 
    201 
    202 static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
    203 {
    204 #ifdef __linux__
    205 	struct ifreq ifr;
    206 	struct sockaddr_ll addr;
    207 	struct sockaddr_in addr2;
    208 	int n = 1;
    209 
    210 	drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
    211 	if (drv->sock < 0) {
    212 		wpa_printf(MSG_ERROR, "socket[PF_PACKET,SOCK_RAW]: %s",
    213 			   strerror(errno));
    214 		return -1;
    215 	}
    216 
    217 	if (eloop_register_read_sock(drv->sock, handle_read, drv->ctx, NULL)) {
    218 		wpa_printf(MSG_INFO, "Could not register read socket");
    219 		return -1;
    220 	}
    221 
    222 	os_memset(&ifr, 0, sizeof(ifr));
    223 	os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
    224 	if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
    225 		wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s",
    226 			   strerror(errno));
    227 		return -1;
    228 	}
    229 
    230 	os_memset(&addr, 0, sizeof(addr));
    231 	addr.sll_family = AF_PACKET;
    232 	addr.sll_ifindex = ifr.ifr_ifindex;
    233 	wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
    234 		   addr.sll_ifindex);
    235 
    236 	if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    237 		wpa_printf(MSG_ERROR, "bind: %s", strerror(errno));
    238 		return -1;
    239 	}
    240 
    241 	/* filter multicast address */
    242 	if (wired_multicast_membership(drv->sock, ifr.ifr_ifindex,
    243 				       pae_group_addr, 1) < 0) {
    244 		wpa_printf(MSG_ERROR, "wired: Failed to add multicast group "
    245 			   "membership");
    246 		return -1;
    247 	}
    248 
    249 	os_memset(&ifr, 0, sizeof(ifr));
    250 	os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
    251 	if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
    252 		wpa_printf(MSG_ERROR, "ioctl(SIOCGIFHWADDR): %s",
    253 			   strerror(errno));
    254 		return -1;
    255 	}
    256 
    257 	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
    258 		wpa_printf(MSG_INFO, "Invalid HW-addr family 0x%04x",
    259 			   ifr.ifr_hwaddr.sa_family);
    260 		return -1;
    261 	}
    262 	os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    263 
    264 	/* setup dhcp listen socket for sta detection */
    265 	if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
    266 		wpa_printf(MSG_ERROR, "socket call failed for dhcp: %s",
    267 			   strerror(errno));
    268 		return -1;
    269 	}
    270 
    271 	if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, drv->ctx,
    272 				     NULL)) {
    273 		wpa_printf(MSG_INFO, "Could not register read socket");
    274 		return -1;
    275 	}
    276 
    277 	os_memset(&addr2, 0, sizeof(addr2));
    278 	addr2.sin_family = AF_INET;
    279 	addr2.sin_port = htons(67);
    280 	addr2.sin_addr.s_addr = INADDR_ANY;
    281 
    282 	if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n,
    283 		       sizeof(n)) == -1) {
    284 		wpa_printf(MSG_ERROR, "setsockopt[SOL_SOCKET,SO_REUSEADDR]: %s",
    285 			   strerror(errno));
    286 		return -1;
    287 	}
    288 	if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n,
    289 		       sizeof(n)) == -1) {
    290 		wpa_printf(MSG_ERROR, "setsockopt[SOL_SOCKET,SO_BROADCAST]: %s",
    291 			   strerror(errno));
    292 		return -1;
    293 	}
    294 
    295 	os_memset(&ifr, 0, sizeof(ifr));
    296 	os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->ifname, IFNAMSIZ);
    297 	if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
    298 		       (char *) &ifr, sizeof(ifr)) < 0) {
    299 		wpa_printf(MSG_ERROR,
    300 			   "setsockopt[SOL_SOCKET,SO_BINDTODEVICE]: %s",
    301 			   strerror(errno));
    302 		return -1;
    303 	}
    304 
    305 	if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2,
    306 		 sizeof(struct sockaddr)) == -1) {
    307 		wpa_printf(MSG_ERROR, "bind: %s", strerror(errno));
    308 		return -1;
    309 	}
    310 
    311 	return 0;
    312 #else /* __linux__ */
    313 	return -1;
    314 #endif /* __linux__ */
    315 }
    316 
    317 
    318 static int wired_send_eapol(void *priv, const u8 *addr,
    319 			    const u8 *data, size_t data_len, int encrypt,
    320 			    const u8 *own_addr, u32 flags)
    321 {
    322 	struct wpa_driver_wired_data *drv = priv;
    323 	struct ieee8023_hdr *hdr;
    324 	size_t len;
    325 	u8 *pos;
    326 	int res;
    327 
    328 	len = sizeof(*hdr) + data_len;
    329 	hdr = os_zalloc(len);
    330 	if (hdr == NULL) {
    331 		wpa_printf(MSG_INFO,
    332 			   "malloc() failed for wired_send_eapol(len=%lu)",
    333 			   (unsigned long) len);
    334 		return -1;
    335 	}
    336 
    337 	os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
    338 		  ETH_ALEN);
    339 	os_memcpy(hdr->src, own_addr, ETH_ALEN);
    340 	hdr->ethertype = htons(ETH_P_PAE);
    341 
    342 	pos = (u8 *) (hdr + 1);
    343 	os_memcpy(pos, data, data_len);
    344 
    345 	res = send(drv->sock, (u8 *) hdr, len, 0);
    346 	os_free(hdr);
    347 
    348 	if (res < 0) {
    349 		wpa_printf(MSG_ERROR,
    350 			   "wired_send_eapol - packet len: %lu - failed: send: %s",
    351 			   (unsigned long) len, strerror(errno));
    352 	}
    353 
    354 	return res;
    355 }
    356 
    357 
    358 static void * wired_driver_hapd_init(struct hostapd_data *hapd,
    359 				     struct wpa_init_params *params)
    360 {
    361 	struct wpa_driver_wired_data *drv;
    362 
    363 	drv = os_zalloc(sizeof(struct wpa_driver_wired_data));
    364 	if (drv == NULL) {
    365 		wpa_printf(MSG_INFO,
    366 			   "Could not allocate memory for wired driver data");
    367 		return NULL;
    368 	}
    369 
    370 	drv->ctx = hapd;
    371 	os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname));
    372 	drv->use_pae_group_addr = params->use_pae_group_addr;
    373 
    374 	if (wired_init_sockets(drv, params->own_addr)) {
    375 		os_free(drv);
    376 		return NULL;
    377 	}
    378 
    379 	return drv;
    380 }
    381 
    382 
    383 static void wired_driver_hapd_deinit(void *priv)
    384 {
    385 	struct wpa_driver_wired_data *drv = priv;
    386 
    387 	if (drv->sock >= 0) {
    388 		eloop_unregister_read_sock(drv->sock);
    389 		close(drv->sock);
    390 	}
    391 
    392 	if (drv->dhcp_sock >= 0) {
    393 		eloop_unregister_read_sock(drv->dhcp_sock);
    394 		close(drv->dhcp_sock);
    395 	}
    396 
    397 	os_free(drv);
    398 }
    399 
    400 
    401 static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid)
    402 {
    403 	ssid[0] = 0;
    404 	return 0;
    405 }
    406 
    407 
    408 static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid)
    409 {
    410 	/* Report PAE group address as the "BSSID" for wired connection. */
    411 	os_memcpy(bssid, pae_group_addr, ETH_ALEN);
    412 	return 0;
    413 }
    414 
    415 
    416 static int wpa_driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa)
    417 {
    418 	os_memset(capa, 0, sizeof(*capa));
    419 	capa->flags = WPA_DRIVER_FLAGS_WIRED;
    420 	return 0;
    421 }
    422 
    423 
    424 static int wpa_driver_wired_get_ifflags(const char *ifname, int *flags)
    425 {
    426 	struct ifreq ifr;
    427 	int s;
    428 
    429 	s = socket(PF_INET, SOCK_DGRAM, 0);
    430 	if (s < 0) {
    431 		wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
    432 		return -1;
    433 	}
    434 
    435 	os_memset(&ifr, 0, sizeof(ifr));
    436 	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
    437 	if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
    438 		wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s",
    439 			   strerror(errno));
    440 		close(s);
    441 		return -1;
    442 	}
    443 	close(s);
    444 	*flags = ifr.ifr_flags & 0xffff;
    445 	return 0;
    446 }
    447 
    448 
    449 static int wpa_driver_wired_set_ifflags(const char *ifname, int flags)
    450 {
    451 	struct ifreq ifr;
    452 	int s;
    453 
    454 	s = socket(PF_INET, SOCK_DGRAM, 0);
    455 	if (s < 0) {
    456 		wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
    457 		return -1;
    458 	}
    459 
    460 	os_memset(&ifr, 0, sizeof(ifr));
    461 	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
    462 	ifr.ifr_flags = flags & 0xffff;
    463 	if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
    464 		wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
    465 			   strerror(errno));
    466 		close(s);
    467 		return -1;
    468 	}
    469 	close(s);
    470 	return 0;
    471 }
    472 
    473 
    474 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
    475 static int wpa_driver_wired_get_ifstatus(const char *ifname, int *status)
    476 {
    477 	struct ifmediareq ifmr;
    478 	int s;
    479 
    480 	s = socket(PF_INET, SOCK_DGRAM, 0);
    481 	if (s < 0) {
    482 		wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
    483 		return -1;
    484 	}
    485 
    486 	os_memset(&ifmr, 0, sizeof(ifmr));
    487 	os_strlcpy(ifmr.ifm_name, ifname, IFNAMSIZ);
    488 	if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) {
    489 		wpa_printf(MSG_ERROR, "ioctl[SIOCGIFMEDIA]: %s",
    490 			   strerror(errno));
    491 		close(s);
    492 		return -1;
    493 	}
    494 	close(s);
    495 	*status = (ifmr.ifm_status & (IFM_ACTIVE | IFM_AVALID)) ==
    496 		(IFM_ACTIVE | IFM_AVALID);
    497 
    498 	return 0;
    499 }
    500 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
    501 
    502 
    503 static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
    504 {
    505 	struct ifreq ifr;
    506 	int s;
    507 
    508 #ifdef __sun__
    509 	return -1;
    510 #endif /* __sun__ */
    511 
    512 	s = socket(PF_INET, SOCK_DGRAM, 0);
    513 	if (s < 0) {
    514 		wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
    515 		return -1;
    516 	}
    517 
    518 	os_memset(&ifr, 0, sizeof(ifr));
    519 	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
    520 #ifdef __linux__
    521 	ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
    522 	os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
    523 #endif /* __linux__ */
    524 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
    525 	{
    526 		struct sockaddr_dl *dlp;
    527 		dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
    528 		dlp->sdl_len = sizeof(struct sockaddr_dl);
    529 		dlp->sdl_family = AF_LINK;
    530 		dlp->sdl_index = 0;
    531 		dlp->sdl_nlen = 0;
    532 		dlp->sdl_alen = ETH_ALEN;
    533 		dlp->sdl_slen = 0;
    534 		os_memcpy(LLADDR(dlp), addr, ETH_ALEN);
    535 	}
    536 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
    537 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
    538 	{
    539 		struct sockaddr *sap;
    540 		sap = (struct sockaddr *) &ifr.ifr_addr;
    541 		sap->sa_len = sizeof(struct sockaddr);
    542 		sap->sa_family = AF_UNSPEC;
    543 		os_memcpy(sap->sa_data, addr, ETH_ALEN);
    544 	}
    545 #endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */
    546 
    547 	if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
    548 		wpa_printf(MSG_ERROR, "ioctl[SIOC{ADD/DEL}MULTI]: %s",
    549 			   strerror(errno));
    550 		close(s);
    551 		return -1;
    552 	}
    553 	close(s);
    554 	return 0;
    555 }
    556 
    557 
    558 static void * wpa_driver_wired_init(void *ctx, const char *ifname)
    559 {
    560 	struct wpa_driver_wired_data *drv;
    561 	int flags;
    562 
    563 	drv = os_zalloc(sizeof(*drv));
    564 	if (drv == NULL)
    565 		return NULL;
    566 	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
    567 	drv->ctx = ctx;
    568 
    569 #ifdef __linux__
    570 	drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
    571 	if (drv->pf_sock < 0)
    572 		wpa_printf(MSG_ERROR, "socket(PF_PACKET): %s", strerror(errno));
    573 #else /* __linux__ */
    574 	drv->pf_sock = -1;
    575 #endif /* __linux__ */
    576 
    577 	if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 &&
    578 	    !(flags & IFF_UP) &&
    579 	    wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) {
    580 		drv->iff_up = 1;
    581 	}
    582 
    583 	if (wired_multicast_membership(drv->pf_sock,
    584 				       if_nametoindex(drv->ifname),
    585 				       pae_group_addr, 1) == 0) {
    586 		wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
    587 			   "packet socket", __func__);
    588 		drv->membership = 1;
    589 	} else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) {
    590 		wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
    591 			   "SIOCADDMULTI", __func__);
    592 		drv->multi = 1;
    593 	} else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) {
    594 		wpa_printf(MSG_INFO, "%s: Could not get interface "
    595 			   "flags", __func__);
    596 		os_free(drv);
    597 		return NULL;
    598 	} else if (flags & IFF_ALLMULTI) {
    599 		wpa_printf(MSG_DEBUG, "%s: Interface is already configured "
    600 			   "for multicast", __func__);
    601 	} else if (wpa_driver_wired_set_ifflags(ifname,
    602 						flags | IFF_ALLMULTI) < 0) {
    603 		wpa_printf(MSG_INFO, "%s: Failed to enable allmulti",
    604 			   __func__);
    605 		os_free(drv);
    606 		return NULL;
    607 	} else {
    608 		wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode",
    609 			   __func__);
    610 		drv->iff_allmulti = 1;
    611 	}
    612 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
    613 	{
    614 		int status;
    615 		wpa_printf(MSG_DEBUG, "%s: waiting for link to become active",
    616 			   __func__);
    617 		while (wpa_driver_wired_get_ifstatus(ifname, &status) == 0 &&
    618 		       status == 0)
    619 			sleep(1);
    620 	}
    621 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
    622 
    623 	return drv;
    624 }
    625 
    626 
    627 static void wpa_driver_wired_deinit(void *priv)
    628 {
    629 	struct wpa_driver_wired_data *drv = priv;
    630 	int flags;
    631 
    632 	if (drv->membership &&
    633 	    wired_multicast_membership(drv->pf_sock,
    634 				       if_nametoindex(drv->ifname),
    635 				       pae_group_addr, 0) < 0) {
    636 		wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
    637 			   "group (PACKET)", __func__);
    638 	}
    639 
    640 	if (drv->multi &&
    641 	    wpa_driver_wired_multi(drv->ifname, pae_group_addr, 0) < 0) {
    642 		wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
    643 			   "group (SIOCDELMULTI)", __func__);
    644 	}
    645 
    646 	if (drv->iff_allmulti &&
    647 	    (wpa_driver_wired_get_ifflags(drv->ifname, &flags) < 0 ||
    648 	     wpa_driver_wired_set_ifflags(drv->ifname,
    649 					  flags & ~IFF_ALLMULTI) < 0)) {
    650 		wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode",
    651 			   __func__);
    652 	}
    653 
    654 	if (drv->iff_up &&
    655 	    wpa_driver_wired_get_ifflags(drv->ifname, &flags) == 0 &&
    656 	    (flags & IFF_UP) &&
    657 	    wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) {
    658 		wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down",
    659 			   __func__);
    660 	}
    661 
    662 	if (drv->pf_sock != -1)
    663 		close(drv->pf_sock);
    664 
    665 	os_free(drv);
    666 }
    667 
    668 
    669 const struct wpa_driver_ops wpa_driver_wired_ops = {
    670 	.name = "wired",
    671 	.desc = "Wired Ethernet driver",
    672 	.hapd_init = wired_driver_hapd_init,
    673 	.hapd_deinit = wired_driver_hapd_deinit,
    674 	.hapd_send_eapol = wired_send_eapol,
    675 	.get_ssid = wpa_driver_wired_get_ssid,
    676 	.get_bssid = wpa_driver_wired_get_bssid,
    677 	.get_capa = wpa_driver_wired_get_capa,
    678 	.init = wpa_driver_wired_init,
    679 	.deinit = wpa_driver_wired_deinit,
    680 };
    681