driver_wired.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*
  2. * WPA Supplicant - wired Ethernet driver interface
  3. * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
  4. * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Alternatively, this software may be distributed under the terms of BSD
  11. * license.
  12. *
  13. * See README and COPYING for more details.
  14. */
  15. #include "includes.h"
  16. #include <sys/ioctl.h>
  17. #include <net/if.h>
  18. #ifdef __linux__
  19. #include <netpacket/packet.h>
  20. #include <net/if_arp.h>
  21. #include <net/if.h>
  22. #endif /* __linux__ */
  23. #if defined(__FreeBSD__) || defined(__DragonFly__)
  24. #include <net/if_dl.h>
  25. #endif /* defined(__FreeBSD__) || defined(__DragonFly__) */
  26. #include "common.h"
  27. #include "driver.h"
  28. #ifdef HOSTAPD
  29. #include "eloop.h"
  30. #include "../../hostapd/hostapd_defs.h"
  31. #include "../../hostapd/sta_info.h"
  32. #endif /* HOSTAPD */
  33. static const u8 pae_group_addr[ETH_ALEN] =
  34. { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
  35. struct wpa_driver_wired_data {
  36. #ifdef HOSTAPD
  37. struct hostapd_data *hapd;
  38. char iface[IFNAMSIZ + 1];
  39. int sock; /* raw packet socket for driver access */
  40. int dhcp_sock; /* socket for dhcp packets */
  41. int use_pae_group_addr;
  42. #else /* HOSTAPD */
  43. void *ctx;
  44. int pf_sock;
  45. char ifname[IFNAMSIZ + 1];
  46. int membership, multi, iff_allmulti, iff_up;
  47. #endif /* HOSTAPD */
  48. };
  49. #ifdef HOSTAPD
  50. /* TODO: detecting new devices should eventually be changed from using DHCP
  51. * snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
  52. * based on ebtables, etc. */
  53. struct dhcp_message {
  54. u_int8_t op;
  55. u_int8_t htype;
  56. u_int8_t hlen;
  57. u_int8_t hops;
  58. u_int32_t xid;
  59. u_int16_t secs;
  60. u_int16_t flags;
  61. u_int32_t ciaddr;
  62. u_int32_t yiaddr;
  63. u_int32_t siaddr;
  64. u_int32_t giaddr;
  65. u_int8_t chaddr[16];
  66. u_int8_t sname[64];
  67. u_int8_t file[128];
  68. u_int32_t cookie;
  69. u_int8_t options[308]; /* 312 - cookie */
  70. };
  71. static void wired_possible_new_sta(struct hostapd_data *hapd, u8 *addr)
  72. {
  73. struct sta_info *sta;
  74. sta = ap_get_sta(hapd, addr);
  75. if (sta)
  76. return;
  77. wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
  78. " - adding a new STA", MAC2STR(addr));
  79. sta = ap_sta_add(hapd, addr);
  80. if (sta) {
  81. hostapd_new_assoc_sta(hapd, sta, 0);
  82. } else {
  83. wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
  84. MAC2STR(addr));
  85. }
  86. }
  87. static void handle_data(struct hostapd_data *hapd, unsigned char *buf,
  88. size_t len)
  89. {
  90. struct ieee8023_hdr *hdr;
  91. u8 *pos, *sa;
  92. size_t left;
  93. /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
  94. * 2 byte ethertype */
  95. if (len < 14) {
  96. wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)",
  97. (unsigned long) len);
  98. return;
  99. }
  100. hdr = (struct ieee8023_hdr *) buf;
  101. switch (ntohs(hdr->ethertype)) {
  102. case ETH_P_PAE:
  103. wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
  104. sa = hdr->src;
  105. wired_possible_new_sta(hapd, sa);
  106. pos = (u8 *) (hdr + 1);
  107. left = len - sizeof(*hdr);
  108. hostapd_eapol_receive(hapd, sa, pos, left);
  109. break;
  110. default:
  111. wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
  112. ntohs(hdr->ethertype));
  113. break;
  114. }
  115. }
  116. static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
  117. {
  118. struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
  119. int len;
  120. unsigned char buf[3000];
  121. len = recv(sock, buf, sizeof(buf), 0);
  122. if (len < 0) {
  123. perror("recv");
  124. return;
  125. }
  126. handle_data(hapd, buf, len);
  127. }
  128. static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx)
  129. {
  130. struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
  131. int len;
  132. unsigned char buf[3000];
  133. struct dhcp_message *msg;
  134. u8 *mac_address;
  135. len = recv(sock, buf, sizeof(buf), 0);
  136. if (len < 0) {
  137. perror("recv");
  138. return;
  139. }
  140. /* must contain at least dhcp_message->chaddr */
  141. if (len < 44) {
  142. wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len);
  143. return;
  144. }
  145. msg = (struct dhcp_message *) buf;
  146. mac_address = (u8 *) &(msg->chaddr);
  147. wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR,
  148. MAC2STR(mac_address));
  149. wired_possible_new_sta(hapd, mac_address);
  150. }
  151. static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
  152. {
  153. struct hostapd_data *hapd = drv->hapd;
  154. struct ifreq ifr;
  155. struct sockaddr_ll addr;
  156. struct sockaddr_in addr2;
  157. struct packet_mreq mreq;
  158. int n = 1;
  159. drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
  160. if (drv->sock < 0) {
  161. perror("socket[PF_PACKET,SOCK_RAW]");
  162. return -1;
  163. }
  164. if (eloop_register_read_sock(drv->sock, handle_read, hapd, NULL)) {
  165. printf("Could not register read socket\n");
  166. return -1;
  167. }
  168. memset(&ifr, 0, sizeof(ifr));
  169. os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
  170. if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
  171. perror("ioctl(SIOCGIFINDEX)");
  172. return -1;
  173. }
  174. memset(&addr, 0, sizeof(addr));
  175. addr.sll_family = AF_PACKET;
  176. addr.sll_ifindex = ifr.ifr_ifindex;
  177. wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
  178. addr.sll_ifindex);
  179. if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  180. perror("bind");
  181. return -1;
  182. }
  183. /* filter multicast address */
  184. memset(&mreq, 0, sizeof(mreq));
  185. mreq.mr_ifindex = ifr.ifr_ifindex;
  186. mreq.mr_type = PACKET_MR_MULTICAST;
  187. mreq.mr_alen = 6;
  188. memcpy(mreq.mr_address, pae_group_addr, mreq.mr_alen);
  189. if (setsockopt(drv->sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
  190. sizeof(mreq)) < 0) {
  191. perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]");
  192. return -1;
  193. }
  194. memset(&ifr, 0, sizeof(ifr));
  195. os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
  196. if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
  197. perror("ioctl(SIOCGIFHWADDR)");
  198. return -1;
  199. }
  200. if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
  201. printf("Invalid HW-addr family 0x%04x\n",
  202. ifr.ifr_hwaddr.sa_family);
  203. return -1;
  204. }
  205. memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
  206. /* setup dhcp listen socket for sta detection */
  207. if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  208. perror("socket call failed for dhcp");
  209. return -1;
  210. }
  211. if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, hapd, NULL))
  212. {
  213. printf("Could not register read socket\n");
  214. return -1;
  215. }
  216. memset(&addr2, 0, sizeof(addr2));
  217. addr2.sin_family = AF_INET;
  218. addr2.sin_port = htons(67);
  219. addr2.sin_addr.s_addr = INADDR_ANY;
  220. if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n,
  221. sizeof(n)) == -1) {
  222. perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
  223. return -1;
  224. }
  225. if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n,
  226. sizeof(n)) == -1) {
  227. perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
  228. return -1;
  229. }
  230. memset(&ifr, 0, sizeof(ifr));
  231. os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->iface, IFNAMSIZ);
  232. if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
  233. (char *) &ifr, sizeof(ifr)) < 0) {
  234. perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
  235. return -1;
  236. }
  237. if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2,
  238. sizeof(struct sockaddr)) == -1) {
  239. perror("bind");
  240. return -1;
  241. }
  242. return 0;
  243. }
  244. static int wired_send_eapol(void *priv, const u8 *addr,
  245. const u8 *data, size_t data_len, int encrypt,
  246. const u8 *own_addr)
  247. {
  248. struct wpa_driver_wired_data *drv = priv;
  249. struct ieee8023_hdr *hdr;
  250. size_t len;
  251. u8 *pos;
  252. int res;
  253. len = sizeof(*hdr) + data_len;
  254. hdr = os_zalloc(len);
  255. if (hdr == NULL) {
  256. printf("malloc() failed for wired_send_eapol(len=%lu)\n",
  257. (unsigned long) len);
  258. return -1;
  259. }
  260. memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
  261. ETH_ALEN);
  262. memcpy(hdr->src, own_addr, ETH_ALEN);
  263. hdr->ethertype = htons(ETH_P_PAE);
  264. pos = (u8 *) (hdr + 1);
  265. memcpy(pos, data, data_len);
  266. res = send(drv->sock, (u8 *) hdr, len, 0);
  267. free(hdr);
  268. if (res < 0) {
  269. perror("wired_send_eapol: send");
  270. printf("wired_send_eapol - packet len: %lu - failed\n",
  271. (unsigned long) len);
  272. }
  273. return res;
  274. }
  275. static void * wired_driver_hapd_init(struct hostapd_data *hapd,
  276. struct wpa_init_params *params)
  277. {
  278. struct wpa_driver_wired_data *drv;
  279. drv = os_zalloc(sizeof(struct wpa_driver_wired_data));
  280. if (drv == NULL) {
  281. printf("Could not allocate memory for wired driver data\n");
  282. return NULL;
  283. }
  284. drv->hapd = hapd;
  285. os_strlcpy(drv->iface, params->ifname, sizeof(drv->iface));
  286. drv->use_pae_group_addr = params->use_pae_group_addr;
  287. if (wired_init_sockets(drv, params->own_addr)) {
  288. free(drv);
  289. return NULL;
  290. }
  291. return drv;
  292. }
  293. static void wired_driver_hapd_deinit(void *priv)
  294. {
  295. struct wpa_driver_wired_data *drv = priv;
  296. if (drv->sock >= 0)
  297. close(drv->sock);
  298. if (drv->dhcp_sock >= 0)
  299. close(drv->dhcp_sock);
  300. free(drv);
  301. }
  302. #else /* HOSTAPD */
  303. static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid)
  304. {
  305. ssid[0] = 0;
  306. return 0;
  307. }
  308. static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid)
  309. {
  310. /* Report PAE group address as the "BSSID" for wired connection. */
  311. os_memcpy(bssid, pae_group_addr, ETH_ALEN);
  312. return 0;
  313. }
  314. static int wpa_driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa)
  315. {
  316. os_memset(capa, 0, sizeof(*capa));
  317. capa->flags = WPA_DRIVER_FLAGS_WIRED;
  318. return 0;
  319. }
  320. static int wpa_driver_wired_get_ifflags(const char *ifname, int *flags)
  321. {
  322. struct ifreq ifr;
  323. int s;
  324. s = socket(PF_INET, SOCK_DGRAM, 0);
  325. if (s < 0) {
  326. perror("socket");
  327. return -1;
  328. }
  329. os_memset(&ifr, 0, sizeof(ifr));
  330. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  331. if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
  332. perror("ioctl[SIOCGIFFLAGS]");
  333. close(s);
  334. return -1;
  335. }
  336. close(s);
  337. *flags = ifr.ifr_flags & 0xffff;
  338. return 0;
  339. }
  340. static int wpa_driver_wired_set_ifflags(const char *ifname, int flags)
  341. {
  342. struct ifreq ifr;
  343. int s;
  344. s = socket(PF_INET, SOCK_DGRAM, 0);
  345. if (s < 0) {
  346. perror("socket");
  347. return -1;
  348. }
  349. os_memset(&ifr, 0, sizeof(ifr));
  350. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  351. ifr.ifr_flags = flags & 0xffff;
  352. if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
  353. perror("ioctl[SIOCSIFFLAGS]");
  354. close(s);
  355. return -1;
  356. }
  357. close(s);
  358. return 0;
  359. }
  360. static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
  361. {
  362. struct ifreq ifr;
  363. int s;
  364. s = socket(PF_INET, SOCK_DGRAM, 0);
  365. if (s < 0) {
  366. perror("socket");
  367. return -1;
  368. }
  369. os_memset(&ifr, 0, sizeof(ifr));
  370. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  371. #ifdef __linux__
  372. ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
  373. os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
  374. #endif /* __linux__ */
  375. #if defined(__FreeBSD__) || defined(__DragonFly__)
  376. {
  377. struct sockaddr_dl *dlp;
  378. dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
  379. dlp->sdl_len = sizeof(struct sockaddr_dl);
  380. dlp->sdl_family = AF_LINK;
  381. dlp->sdl_index = 0;
  382. dlp->sdl_nlen = 0;
  383. dlp->sdl_alen = ETH_ALEN;
  384. dlp->sdl_slen = 0;
  385. os_memcpy(LLADDR(dlp), addr, ETH_ALEN);
  386. }
  387. #endif /* defined(__FreeBSD__) || defined(__DragonFly__) */
  388. #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
  389. {
  390. struct sockaddr *sap;
  391. sap = (struct sockaddr *) &ifr.ifr_addr;
  392. sap->sa_len = sizeof(struct sockaddr);
  393. sap->sa_family = AF_UNSPEC;
  394. os_memcpy(sap->sa_data, addr, ETH_ALEN);
  395. }
  396. #endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */
  397. if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
  398. perror("ioctl[SIOC{ADD/DEL}MULTI]");
  399. close(s);
  400. return -1;
  401. }
  402. close(s);
  403. return 0;
  404. }
  405. static int wpa_driver_wired_membership(struct wpa_driver_wired_data *drv,
  406. const u8 *addr, int add)
  407. {
  408. #ifdef __linux__
  409. struct packet_mreq mreq;
  410. if (drv->pf_sock == -1)
  411. return -1;
  412. os_memset(&mreq, 0, sizeof(mreq));
  413. mreq.mr_ifindex = if_nametoindex(drv->ifname);
  414. mreq.mr_type = PACKET_MR_MULTICAST;
  415. mreq.mr_alen = ETH_ALEN;
  416. os_memcpy(mreq.mr_address, addr, ETH_ALEN);
  417. if (setsockopt(drv->pf_sock, SOL_PACKET,
  418. add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
  419. &mreq, sizeof(mreq)) < 0) {
  420. perror("setsockopt");
  421. return -1;
  422. }
  423. return 0;
  424. #else /* __linux__ */
  425. return -1;
  426. #endif /* __linux__ */
  427. }
  428. static void * wpa_driver_wired_init(void *ctx, const char *ifname)
  429. {
  430. struct wpa_driver_wired_data *drv;
  431. int flags;
  432. drv = os_zalloc(sizeof(*drv));
  433. if (drv == NULL)
  434. return NULL;
  435. os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
  436. drv->ctx = ctx;
  437. #ifdef __linux__
  438. drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
  439. if (drv->pf_sock < 0)
  440. perror("socket(PF_PACKET)");
  441. #else /* __linux__ */
  442. drv->pf_sock = -1;
  443. #endif /* __linux__ */
  444. if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 &&
  445. !(flags & IFF_UP) &&
  446. wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) {
  447. drv->iff_up = 1;
  448. }
  449. if (wpa_driver_wired_membership(drv, pae_group_addr, 1) == 0) {
  450. wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
  451. "packet socket", __func__);
  452. drv->membership = 1;
  453. } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) {
  454. wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
  455. "SIOCADDMULTI", __func__);
  456. drv->multi = 1;
  457. } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) {
  458. wpa_printf(MSG_INFO, "%s: Could not get interface "
  459. "flags", __func__);
  460. os_free(drv);
  461. return NULL;
  462. } else if (flags & IFF_ALLMULTI) {
  463. wpa_printf(MSG_DEBUG, "%s: Interface is already configured "
  464. "for multicast", __func__);
  465. } else if (wpa_driver_wired_set_ifflags(ifname,
  466. flags | IFF_ALLMULTI) < 0) {
  467. wpa_printf(MSG_INFO, "%s: Failed to enable allmulti",
  468. __func__);
  469. os_free(drv);
  470. return NULL;
  471. } else {
  472. wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode",
  473. __func__);
  474. drv->iff_allmulti = 1;
  475. }
  476. return drv;
  477. }
  478. static void wpa_driver_wired_deinit(void *priv)
  479. {
  480. struct wpa_driver_wired_data *drv = priv;
  481. int flags;
  482. if (drv->membership &&
  483. wpa_driver_wired_membership(drv, pae_group_addr, 0) < 0) {
  484. wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
  485. "group (PACKET)", __func__);
  486. }
  487. if (drv->multi &&
  488. wpa_driver_wired_multi(drv->ifname, pae_group_addr, 0) < 0) {
  489. wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
  490. "group (SIOCDELMULTI)", __func__);
  491. }
  492. if (drv->iff_allmulti &&
  493. (wpa_driver_wired_get_ifflags(drv->ifname, &flags) < 0 ||
  494. wpa_driver_wired_set_ifflags(drv->ifname,
  495. flags & ~IFF_ALLMULTI) < 0)) {
  496. wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode",
  497. __func__);
  498. }
  499. if (drv->iff_up &&
  500. wpa_driver_wired_get_ifflags(drv->ifname, &flags) == 0 &&
  501. (flags & IFF_UP) &&
  502. wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) {
  503. wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down",
  504. __func__);
  505. }
  506. if (drv->pf_sock != -1)
  507. close(drv->pf_sock);
  508. os_free(drv);
  509. }
  510. #endif /* HOSTAPD */
  511. const struct wpa_driver_ops wpa_driver_wired_ops = {
  512. .name = "wired",
  513. .desc = "Wired Ethernet driver",
  514. #ifdef HOSTAPD
  515. .hapd_init = wired_driver_hapd_init,
  516. .hapd_deinit = wired_driver_hapd_deinit,
  517. .hapd_send_eapol = wired_send_eapol,
  518. #else /* HOSTAPD */
  519. .get_ssid = wpa_driver_wired_get_ssid,
  520. .get_bssid = wpa_driver_wired_get_bssid,
  521. .get_capa = wpa_driver_wired_get_capa,
  522. .init = wpa_driver_wired_init,
  523. .deinit = wpa_driver_wired_deinit,
  524. #endif /* HOSTAPD */
  525. };