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