driver_wired.c 15 KB

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