--- hostapd/driver_nl80211.c | 112 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 6 deletions(-) --- hostap.orig/hostapd/driver_nl80211.c 2007-12-12 17:29:39.000000000 +0100 +++ hostap/hostapd/driver_nl80211.c 2007-12-12 17:29:42.000000000 +0100 @@ -139,6 +139,11 @@ struct i802_driver_data { int sock; /* raw packet socket for driver access */ int ioctl_sock; /* socket for ioctl() use */ int wext_sock; /* socket for wireless events */ + int eapol_sock; /* socket for EAPOL frames */ + + int default_if_indices[16]; + int *if_indices; + int num_if_indices; int we_version; struct nl_handle *nl_handle; @@ -146,6 +151,59 @@ struct i802_driver_data { struct genl_family *nl80211; }; +static void add_ifidx(struct i802_driver_data *drv, int ifidx) +{ + int i; + int *old; + + for (i = 0; i < drv->num_if_indices; i++) { + if (drv->if_indices[i] == 0) { + drv->if_indices[i] = ifidx; + return; + } + } + + if (drv->if_indices != drv->default_if_indices) + old = drv->if_indices; + else + old = NULL; + + drv->if_indices = realloc(old, sizeof(int) * (drv->num_if_indices + 1)); + if (!drv->if_indices) { + if (!old) + drv->if_indices = drv->default_if_indices; + else + drv->if_indices = old; + wpa_printf(MSG_ERROR, "Failed to reallocate memory for interfaces\n"); + wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d\n", ifidx); + return; + } + drv->if_indices[drv->num_if_indices] = ifidx; + drv->num_if_indices++; +} + +static void del_ifidx(struct i802_driver_data *drv, int ifidx) +{ + int i; + + for (i = 0; i < drv->num_if_indices; i++) { + if (drv->if_indices[i] == ifidx) { + drv->if_indices[i] = 0; + break; + } + } +} + +static int have_ifidx(struct i802_driver_data *drv, int ifidx) +{ + int i; + + for (i = 0; i < drv->num_if_indices; i++) + if (drv->if_indices[i] == ifidx) + return 1; + + return 0; +} #define HAPD_DECL struct hostapd_data *hapd = iface->bss[0] @@ -848,6 +906,9 @@ static void nl80211_remove_iface(struct { struct nl_msg *msg; + /* stop listening for EAPOL on this interface */ + del_ifidx(drv, ifidx); + msg = nlmsg_alloc(); if (!msg) goto nla_put_failure; @@ -896,6 +957,9 @@ static int nl80211_create_iface(struct i ifidx = if_nametoindex(ifname); + /* start listening for EAPOL on this interface */ + add_ifidx(drv, ifidx); + if (ifidx <= 0) return -1; @@ -997,12 +1061,6 @@ static int i802_set_ieee8021x(const char "driver.\n", ifname, enabled ? "enable" : "disable"); return -1; } - if (hostap_ioctl_prism2param_iface(ifname, drv, - PRISM2_PARAM_EAPOL, enabled)) { - printf("%s: Could not %s EAPOL support in kernel " - "driver.\n", ifname, enabled ? "enable" : "disable"); - return -1; - } return 0; } @@ -1575,6 +1633,27 @@ static void handle_read(int sock, void * } +static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) +{ + struct i802_driver_data *drv = eloop_ctx; + struct hostapd_data *hapd = drv->hapd; + struct sockaddr_ll lladdr; + unsigned char buf[3000]; + int len; + socklen_t fromlen = sizeof(lladdr); + + len = recvfrom(sock, buf, sizeof(buf), 0, + (struct sockaddr *)&lladdr, &fromlen); + if (len < 0) { + perror("recv"); + return; + } + + if (have_ifidx(drv, lladdr.sll_ifindex)) + ieee802_1x_receive(hapd, lladdr.sll_addr, buf, len); +} + + static int i802_init_sockets(struct i802_driver_data *drv, u8 *bssid) { struct hostapd_data *hapd = drv->hapd; @@ -1591,6 +1670,9 @@ static int i802_init_sockets(struct i802 return -1; } + /* start listening for EAPOL on the default AP interface */ + add_ifidx(drv, if_nametoindex(drv->iface)); + if (hostapd_set_iface_flags(drv, drv->iface, 0)) return -1; @@ -1687,6 +1769,17 @@ static int i802_init_sockets(struct i802 return -1; } + drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); + if (drv->eapol_sock < 0) { + perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)"); + return -1; + } + + if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL)) { + printf("Could not register read socket for eapol\n"); + return -1; + } + memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) { @@ -2031,6 +2124,9 @@ static void *i802_init_bssid(struct host drv->hapd = hapd; memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); + drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int); + drv->if_indices = drv->default_if_indices; + if (i802_init_sockets(drv, bssid)) goto failed; @@ -2063,6 +2159,10 @@ static void i802_deinit(void *priv) } if (drv->ioctl_sock >= 0) close(drv->ioctl_sock); + if (drv->eapol_sock >= 0) { + eloop_unregister_read_sock(drv->eapol_sock); + close(drv->eapol_sock); + } genl_family_put(drv->nl80211); nl_cache_free(drv->nl_cache);