-static void
-hostapd_wireless_event_wireless_custom(struct wpa_driver_nl80211_data *drv,
- char *custom)
-{
- wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
-
- if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
- char *pos;
- u8 addr[ETH_ALEN];
- pos = strstr(custom, "addr=");
- if (pos == NULL) {
- wpa_printf(MSG_DEBUG,
- "MLME-MICHAELMICFAILURE.indication "
- "without sender address ignored");
- return;
- }
- pos += 5;
- if (hwaddr_aton(pos, addr) == 0) {
- hostapd_michael_mic_failure(drv->hapd, addr);
- } else {
- wpa_printf(MSG_DEBUG,
- "MLME-MICHAELMICFAILURE.indication "
- "with invalid MAC address");
- }
- }
-}
-
-
-static void hostapd_wireless_event_wireless(struct wpa_driver_nl80211_data *drv,
- char *data, int len)
-{
- struct iw_event iwe_buf, *iwe = &iwe_buf;
- char *pos, *end, *custom, *buf;
-
- pos = data;
- end = data + len;
-
- while (pos + IW_EV_LCP_LEN <= end) {
- /* Event data may be unaligned, so make a local, aligned copy
- * before processing. */
- memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
- wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
- iwe->cmd, iwe->len);
- if (iwe->len <= IW_EV_LCP_LEN)
- return;
-
- custom = pos + IW_EV_POINT_LEN;
- if (drv->we_version > 18 &&
- (iwe->cmd == IWEVMICHAELMICFAILURE ||
- iwe->cmd == IWEVCUSTOM)) {
- /* WE-19 removed the pointer from struct iw_point */
- char *dpos = (char *) &iwe_buf.u.data.length;
- int dlen = dpos - (char *) &iwe_buf;
- memcpy(dpos, pos + IW_EV_LCP_LEN,
- sizeof(struct iw_event) - dlen);
- } else {
- memcpy(&iwe_buf, pos, sizeof(struct iw_event));
- custom += IW_EV_POINT_OFF;
- }
-
- switch (iwe->cmd) {
- case IWEVCUSTOM:
- if (custom + iwe->u.data.length > end)
- return;
- buf = malloc(iwe->u.data.length + 1);
- if (buf == NULL)
- return;
- memcpy(buf, custom, iwe->u.data.length);
- buf[iwe->u.data.length] = '\0';
- hostapd_wireless_event_wireless_custom(drv, buf);
- free(buf);
- break;
- }
-
- pos += iwe->len;
- }
-}
-
-
-static void hostapd_wireless_event_rtm_newlink(struct wpa_driver_nl80211_data *drv,
- struct nlmsghdr *h, int len)
-{
- struct ifinfomsg *ifi;
- int attrlen, _nlmsg_len, rta_len;
- struct rtattr *attr;
-
- if (len < (int) sizeof(*ifi))
- return;
-
- ifi = NLMSG_DATA(h);
-
- /* TODO: use ifi->ifi_index to filter out wireless events from other
- * interfaces */
-
- _nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
- attrlen = h->nlmsg_len - _nlmsg_len;
- if (attrlen < 0)
- return;
-
- attr = (struct rtattr *) (((char *) ifi) + _nlmsg_len);
-
- rta_len = RTA_ALIGN(sizeof(struct rtattr));
- while (RTA_OK(attr, attrlen)) {
- if (attr->rta_type == IFLA_WIRELESS) {
- hostapd_wireless_event_wireless(
- drv, ((char *) attr) + rta_len,
- attr->rta_len - rta_len);
- }
- attr = RTA_NEXT(attr, attrlen);
- }
-}
-
-
-static void hostapd_wireless_event_receive(int sock, void *eloop_ctx,
- void *sock_ctx)
-{
- char buf[256];
- int left;
- struct sockaddr_nl from;
- socklen_t fromlen;
- struct nlmsghdr *h;
- struct wpa_driver_nl80211_data *drv = eloop_ctx;
-
- fromlen = sizeof(from);
- left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
- (struct sockaddr *) &from, &fromlen);
- if (left < 0) {
- if (errno != EINTR && errno != EAGAIN)
- perror("recvfrom(netlink)");
- return;
- }
-
- h = (struct nlmsghdr *) buf;
- while (left >= (int) sizeof(*h)) {
- int len, plen;
-
- len = h->nlmsg_len;
- plen = len - sizeof(*h);
- if (len > left || plen < 0) {
- printf("Malformed netlink message: "
- "len=%d left=%d plen=%d\n",
- len, left, plen);
- break;
- }
-
- switch (h->nlmsg_type) {
- case RTM_NEWLINK:
- hostapd_wireless_event_rtm_newlink(drv, h, plen);
- break;
- }
-
- len = NLMSG_ALIGN(len);
- left -= len;
- h = (struct nlmsghdr *) ((char *) h + len);
- }
-
- if (left > 0) {
- printf("%d extra bytes in the end of netlink message\n", left);
- }
-}
-
-
-static int hostap_get_we_version(struct wpa_driver_nl80211_data *drv)
-{
- struct iw_range *range;
- struct iwreq iwr;
- int minlen;
- size_t buflen;
-
- drv->we_version = 0;
-
- /*
- * Use larger buffer than struct iw_range in order to allow the
- * structure to grow in the future.
- */
- buflen = sizeof(struct iw_range) + 500;
- range = os_zalloc(buflen);
- if (range == NULL)
- return -1;
-
- memset(&iwr, 0, sizeof(iwr));
- os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
- iwr.u.data.pointer = (caddr_t) range;
- iwr.u.data.length = buflen;
-
- minlen = ((char *) &range->enc_capa) - (char *) range +
- sizeof(range->enc_capa);
-
- if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
- perror("ioctl[SIOCGIWRANGE]");
- free(range);
- return -1;
- } else if (iwr.u.data.length >= minlen &&
- range->we_version_compiled >= 18) {
- wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
- "WE(source)=%d enc_capa=0x%x",
- range->we_version_compiled,
- range->we_version_source,
- range->enc_capa);
- drv->we_version = range->we_version_compiled;
- }
-
- free(range);
- return 0;
-}
-
-
-static int i802_wireless_event_init(struct wpa_driver_nl80211_data *drv)
-{
- int s;
- struct sockaddr_nl local;
-
- hostap_get_we_version(drv);
-
- drv->wext_sock = -1;
-
- s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (s < 0) {
- perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
- return -1;
- }
-
- memset(&local, 0, sizeof(local));
- local.nl_family = AF_NETLINK;
- local.nl_groups = RTMGRP_LINK;
- if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
- perror("bind(netlink)");
- close(s);
- return -1;
- }
-
- eloop_register_read_sock(s, hostapd_wireless_event_receive, drv,
- NULL);
- drv->wext_sock = s;
-
- return 0;
-}
-
-
-static void i802_wireless_event_deinit(struct wpa_driver_nl80211_data *drv)
-{
- if (drv->wext_sock < 0)
- return;
- eloop_unregister_read_sock(drv->wext_sock);
- close(drv->wext_sock);
-}
-
-