00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "includes.h"
00017 #include <sys/ioctl.h>
00018 #include <net/if.h>
00019 #ifdef __linux__
00020 #include <netpacket/packet.h>
00021 #include <net/if_arp.h>
00022 #include <net/if.h>
00023 #endif
00024 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
00025 #include <net/if_dl.h>
00026 #endif
00027
00028 #include "common.h"
00029 #include "eloop.h"
00030 #include "driver.h"
00031
00032 #ifdef _MSC_VER
00033 #pragma pack(push, 1)
00034 #endif
00035
00036 struct ieee8023_hdr {
00037 u8 dest[6];
00038 u8 src[6];
00039 u16 ethertype;
00040 } STRUCT_PACKED;
00041
00042 #ifdef _MSC_VER
00043 #pragma pack(pop)
00044 #endif
00045
00046 static const u8 pae_group_addr[ETH_ALEN] =
00047 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
00048
00049
00050 struct wpa_driver_wired_data {
00051 char ifname[IFNAMSIZ + 1];
00052 void *ctx;
00053
00054 int sock;
00055 int dhcp_sock;
00056 int use_pae_group_addr;
00057
00058 int pf_sock;
00059 int membership, multi, iff_allmulti, iff_up;
00060 };
00061
00062
00063
00064
00065
00066
00067 struct dhcp_message {
00068 u_int8_t op;
00069 u_int8_t htype;
00070 u_int8_t hlen;
00071 u_int8_t hops;
00072 u_int32_t xid;
00073 u_int16_t secs;
00074 u_int16_t flags;
00075 u_int32_t ciaddr;
00076 u_int32_t yiaddr;
00077 u_int32_t siaddr;
00078 u_int32_t giaddr;
00079 u_int8_t chaddr[16];
00080 u_int8_t sname[64];
00081 u_int8_t file[128];
00082 u_int32_t cookie;
00083 u_int8_t options[308];
00084 };
00085
00086
00087 static int wired_multicast_membership(int sock, int ifindex,
00088 const u8 *addr, int add)
00089 {
00090 #ifdef __linux__
00091 struct packet_mreq mreq;
00092
00093 if (sock < 0)
00094 return -1;
00095
00096 os_memset(&mreq, 0, sizeof(mreq));
00097 mreq.mr_ifindex = ifindex;
00098 mreq.mr_type = PACKET_MR_MULTICAST;
00099 mreq.mr_alen = ETH_ALEN;
00100 os_memcpy(mreq.mr_address, addr, ETH_ALEN);
00101
00102 if (setsockopt(sock, SOL_PACKET,
00103 add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
00104 &mreq, sizeof(mreq)) < 0) {
00105 perror("setsockopt");
00106 return -1;
00107 }
00108 return 0;
00109 #else
00110 return -1;
00111 #endif
00112 }
00113
00114
00115 #ifdef __linux__
00116 static void handle_data(void *ctx, unsigned char *buf, size_t len)
00117 {
00118 #ifdef HOSTAPD
00119 struct ieee8023_hdr *hdr;
00120 u8 *pos, *sa;
00121 size_t left;
00122 union wpa_event_data event;
00123
00124
00125
00126 if (len < 14) {
00127 wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)",
00128 (unsigned long) len);
00129 return;
00130 }
00131
00132 hdr = (struct ieee8023_hdr *) buf;
00133
00134 switch (ntohs(hdr->ethertype)) {
00135 case ETH_P_PAE:
00136 wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
00137 sa = hdr->src;
00138 os_memset(&event, 0, sizeof(event));
00139 event.new_sta.addr = sa;
00140 wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
00141
00142 pos = (u8 *) (hdr + 1);
00143 left = len - sizeof(*hdr);
00144 drv_event_eapol_rx(ctx, sa, pos, left);
00145 break;
00146
00147 default:
00148 wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
00149 ntohs(hdr->ethertype));
00150 break;
00151 }
00152 #endif
00153 }
00154
00155
00156 static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
00157 {
00158 int len;
00159 unsigned char buf[3000];
00160
00161 len = recv(sock, buf, sizeof(buf), 0);
00162 if (len < 0) {
00163 perror("recv");
00164 return;
00165 }
00166
00167 handle_data(eloop_ctx, buf, len);
00168 }
00169
00170
00171 static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx)
00172 {
00173 int len;
00174 unsigned char buf[3000];
00175 struct dhcp_message *msg;
00176 u8 *mac_address;
00177 union wpa_event_data event;
00178
00179 len = recv(sock, buf, sizeof(buf), 0);
00180 if (len < 0) {
00181 perror("recv");
00182 return;
00183 }
00184
00185
00186 if (len < 44) {
00187 wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len);
00188 return;
00189 }
00190
00191 msg = (struct dhcp_message *) buf;
00192 mac_address = (u8 *) &(msg->chaddr);
00193
00194 wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR,
00195 MAC2STR(mac_address));
00196
00197 os_memset(&event, 0, sizeof(event));
00198 event.new_sta.addr = mac_address;
00199 wpa_supplicant_event(eloop_ctx, EVENT_NEW_STA, &event);
00200 }
00201 #endif
00202
00203
00204 static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
00205 {
00206 #ifdef __linux__
00207 struct ifreq ifr;
00208 struct sockaddr_ll addr;
00209 struct sockaddr_in addr2;
00210 int n = 1;
00211
00212 drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
00213 if (drv->sock < 0) {
00214 perror("socket[PF_PACKET,SOCK_RAW]");
00215 return -1;
00216 }
00217
00218 if (eloop_register_read_sock(drv->sock, handle_read, drv->ctx, NULL)) {
00219 printf("Could not register read socket\n");
00220 return -1;
00221 }
00222
00223 os_memset(&ifr, 0, sizeof(ifr));
00224 os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
00225 if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
00226 perror("ioctl(SIOCGIFINDEX)");
00227 return -1;
00228 }
00229
00230 os_memset(&addr, 0, sizeof(addr));
00231 addr.sll_family = AF_PACKET;
00232 addr.sll_ifindex = ifr.ifr_ifindex;
00233 wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
00234 addr.sll_ifindex);
00235
00236 if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00237 perror("bind");
00238 return -1;
00239 }
00240
00241
00242 if (wired_multicast_membership(drv->sock, ifr.ifr_ifindex,
00243 pae_group_addr, 1) < 0) {
00244 wpa_printf(MSG_ERROR, "wired: Failed to add multicast group "
00245 "membership");
00246 return -1;
00247 }
00248
00249 os_memset(&ifr, 0, sizeof(ifr));
00250 os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
00251 if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
00252 perror("ioctl(SIOCGIFHWADDR)");
00253 return -1;
00254 }
00255
00256 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
00257 printf("Invalid HW-addr family 0x%04x\n",
00258 ifr.ifr_hwaddr.sa_family);
00259 return -1;
00260 }
00261 os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
00262
00263
00264 if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
00265 perror("socket call failed for dhcp");
00266 return -1;
00267 }
00268
00269 if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, drv->ctx,
00270 NULL)) {
00271 printf("Could not register read socket\n");
00272 return -1;
00273 }
00274
00275 os_memset(&addr2, 0, sizeof(addr2));
00276 addr2.sin_family = AF_INET;
00277 addr2.sin_port = htons(67);
00278 addr2.sin_addr.s_addr = INADDR_ANY;
00279
00280 if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n,
00281 sizeof(n)) == -1) {
00282 perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
00283 return -1;
00284 }
00285 if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n,
00286 sizeof(n)) == -1) {
00287 perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
00288 return -1;
00289 }
00290
00291 os_memset(&ifr, 0, sizeof(ifr));
00292 os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->ifname, IFNAMSIZ);
00293 if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
00294 (char *) &ifr, sizeof(ifr)) < 0) {
00295 perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
00296 return -1;
00297 }
00298
00299 if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2,
00300 sizeof(struct sockaddr)) == -1) {
00301 perror("bind");
00302 return -1;
00303 }
00304
00305 return 0;
00306 #else
00307 return -1;
00308 #endif
00309 }
00310
00311
00312 static int wired_send_eapol(void *priv, const u8 *addr,
00313 const u8 *data, size_t data_len, int encrypt,
00314 const u8 *own_addr)
00315 {
00316 struct wpa_driver_wired_data *drv = priv;
00317 struct ieee8023_hdr *hdr;
00318 size_t len;
00319 u8 *pos;
00320 int res;
00321
00322 len = sizeof(*hdr) + data_len;
00323 hdr = os_zalloc(len);
00324 if (hdr == NULL) {
00325 printf("malloc() failed for wired_send_eapol(len=%lu)\n",
00326 (unsigned long) len);
00327 return -1;
00328 }
00329
00330 os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
00331 ETH_ALEN);
00332 os_memcpy(hdr->src, own_addr, ETH_ALEN);
00333 hdr->ethertype = htons(ETH_P_PAE);
00334
00335 pos = (u8 *) (hdr + 1);
00336 os_memcpy(pos, data, data_len);
00337
00338 res = send(drv->sock, (u8 *) hdr, len, 0);
00339 os_free(hdr);
00340
00341 if (res < 0) {
00342 perror("wired_send_eapol: send");
00343 printf("wired_send_eapol - packet len: %lu - failed\n",
00344 (unsigned long) len);
00345 }
00346
00347 return res;
00348 }
00349
00350
00351 static void * wired_driver_hapd_init(struct hostapd_data *hapd,
00352 struct wpa_init_params *params)
00353 {
00354 struct wpa_driver_wired_data *drv;
00355
00356 drv = os_zalloc(sizeof(struct wpa_driver_wired_data));
00357 if (drv == NULL) {
00358 printf("Could not allocate memory for wired driver data\n");
00359 return NULL;
00360 }
00361
00362 drv->ctx = hapd;
00363 os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname));
00364 drv->use_pae_group_addr = params->use_pae_group_addr;
00365
00366 if (wired_init_sockets(drv, params->own_addr)) {
00367 os_free(drv);
00368 return NULL;
00369 }
00370
00371 return drv;
00372 }
00373
00374
00375 static void wired_driver_hapd_deinit(void *priv)
00376 {
00377 struct wpa_driver_wired_data *drv = priv;
00378
00379 if (drv->sock >= 0)
00380 close(drv->sock);
00381
00382 if (drv->dhcp_sock >= 0)
00383 close(drv->dhcp_sock);
00384
00385 os_free(drv);
00386 }
00387
00388
00389 static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid)
00390 {
00391 ssid[0] = 0;
00392 return 0;
00393 }
00394
00395
00396 static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid)
00397 {
00398
00399 os_memcpy(bssid, pae_group_addr, ETH_ALEN);
00400 return 0;
00401 }
00402
00403
00404 static int wpa_driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa)
00405 {
00406 os_memset(capa, 0, sizeof(*capa));
00407 capa->flags = WPA_DRIVER_FLAGS_WIRED;
00408 return 0;
00409 }
00410
00411
00412 static int wpa_driver_wired_get_ifflags(const char *ifname, int *flags)
00413 {
00414 struct ifreq ifr;
00415 int s;
00416
00417 s = socket(PF_INET, SOCK_DGRAM, 0);
00418 if (s < 0) {
00419 perror("socket");
00420 return -1;
00421 }
00422
00423 os_memset(&ifr, 0, sizeof(ifr));
00424 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
00425 if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
00426 perror("ioctl[SIOCGIFFLAGS]");
00427 close(s);
00428 return -1;
00429 }
00430 close(s);
00431 *flags = ifr.ifr_flags & 0xffff;
00432 return 0;
00433 }
00434
00435
00436 static int wpa_driver_wired_set_ifflags(const char *ifname, int flags)
00437 {
00438 struct ifreq ifr;
00439 int s;
00440
00441 s = socket(PF_INET, SOCK_DGRAM, 0);
00442 if (s < 0) {
00443 perror("socket");
00444 return -1;
00445 }
00446
00447 os_memset(&ifr, 0, sizeof(ifr));
00448 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
00449 ifr.ifr_flags = flags & 0xffff;
00450 if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
00451 perror("ioctl[SIOCSIFFLAGS]");
00452 close(s);
00453 return -1;
00454 }
00455 close(s);
00456 return 0;
00457 }
00458
00459
00460 static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
00461 {
00462 struct ifreq ifr;
00463 int s;
00464
00465 s = socket(PF_INET, SOCK_DGRAM, 0);
00466 if (s < 0) {
00467 perror("socket");
00468 return -1;
00469 }
00470
00471 os_memset(&ifr, 0, sizeof(ifr));
00472 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
00473 #ifdef __linux__
00474 ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
00475 os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
00476 #endif
00477 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
00478 {
00479 struct sockaddr_dl *dlp;
00480 dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
00481 dlp->sdl_len = sizeof(struct sockaddr_dl);
00482 dlp->sdl_family = AF_LINK;
00483 dlp->sdl_index = 0;
00484 dlp->sdl_nlen = 0;
00485 dlp->sdl_alen = ETH_ALEN;
00486 dlp->sdl_slen = 0;
00487 os_memcpy(LLADDR(dlp), addr, ETH_ALEN);
00488 }
00489 #endif
00490 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
00491 {
00492 struct sockaddr *sap;
00493 sap = (struct sockaddr *) &ifr.ifr_addr;
00494 sap->sa_len = sizeof(struct sockaddr);
00495 sap->sa_family = AF_UNSPEC;
00496 os_memcpy(sap->sa_data, addr, ETH_ALEN);
00497 }
00498 #endif
00499
00500 if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
00501 perror("ioctl[SIOC{ADD/DEL}MULTI]");
00502 close(s);
00503 return -1;
00504 }
00505 close(s);
00506 return 0;
00507 }
00508
00509
00510 static void * wpa_driver_wired_init(void *ctx, const char *ifname)
00511 {
00512 struct wpa_driver_wired_data *drv;
00513 int flags;
00514
00515 drv = os_zalloc(sizeof(*drv));
00516 if (drv == NULL)
00517 return NULL;
00518 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
00519 drv->ctx = ctx;
00520
00521 #ifdef __linux__
00522 drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
00523 if (drv->pf_sock < 0)
00524 perror("socket(PF_PACKET)");
00525 #else
00526 drv->pf_sock = -1;
00527 #endif
00528
00529 if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 &&
00530 !(flags & IFF_UP) &&
00531 wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) {
00532 drv->iff_up = 1;
00533 }
00534
00535 if (wired_multicast_membership(drv->pf_sock,
00536 if_nametoindex(drv->ifname),
00537 pae_group_addr, 1) == 0) {
00538 wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
00539 "packet socket", __func__);
00540 drv->membership = 1;
00541 } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) {
00542 wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
00543 "SIOCADDMULTI", __func__);
00544 drv->multi = 1;
00545 } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) {
00546 wpa_printf(MSG_INFO, "%s: Could not get interface "
00547 "flags", __func__);
00548 os_free(drv);
00549 return NULL;
00550 } else if (flags & IFF_ALLMULTI) {
00551 wpa_printf(MSG_DEBUG, "%s: Interface is already configured "
00552 "for multicast", __func__);
00553 } else if (wpa_driver_wired_set_ifflags(ifname,
00554 flags | IFF_ALLMULTI) < 0) {
00555 wpa_printf(MSG_INFO, "%s: Failed to enable allmulti",
00556 __func__);
00557 os_free(drv);
00558 return NULL;
00559 } else {
00560 wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode",
00561 __func__);
00562 drv->iff_allmulti = 1;
00563 }
00564
00565 return drv;
00566 }
00567
00568
00569 static void wpa_driver_wired_deinit(void *priv)
00570 {
00571 struct wpa_driver_wired_data *drv = priv;
00572 int flags;
00573
00574 if (drv->membership &&
00575 wired_multicast_membership(drv->pf_sock,
00576 if_nametoindex(drv->ifname),
00577 pae_group_addr, 0) < 0) {
00578 wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
00579 "group (PACKET)", __func__);
00580 }
00581
00582 if (drv->multi &&
00583 wpa_driver_wired_multi(drv->ifname, pae_group_addr, 0) < 0) {
00584 wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
00585 "group (SIOCDELMULTI)", __func__);
00586 }
00587
00588 if (drv->iff_allmulti &&
00589 (wpa_driver_wired_get_ifflags(drv->ifname, &flags) < 0 ||
00590 wpa_driver_wired_set_ifflags(drv->ifname,
00591 flags & ~IFF_ALLMULTI) < 0)) {
00592 wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode",
00593 __func__);
00594 }
00595
00596 if (drv->iff_up &&
00597 wpa_driver_wired_get_ifflags(drv->ifname, &flags) == 0 &&
00598 (flags & IFF_UP) &&
00599 wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) {
00600 wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down",
00601 __func__);
00602 }
00603
00604 if (drv->pf_sock != -1)
00605 close(drv->pf_sock);
00606
00607 os_free(drv);
00608 }
00609
00610
00611 const struct wpa_driver_ops wpa_driver_wired_ops = {
00612 .name = "wired",
00613 .desc = "Wired Ethernet driver",
00614 .hapd_init = wired_driver_hapd_init,
00615 .hapd_deinit = wired_driver_hapd_deinit,
00616 .hapd_send_eapol = wired_send_eapol,
00617 .get_ssid = wpa_driver_wired_get_ssid,
00618 .get_bssid = wpa_driver_wired_get_bssid,
00619 .get_capa = wpa_driver_wired_get_capa,
00620 .init = wpa_driver_wired_init,
00621 .deinit = wpa_driver_wired_deinit,
00622 };