📄 driver_nl80211.c
字号:
static int i802_get_rts(void *priv, int *rts){ struct i802_driver_data *drv = priv; struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); if (ioctl(drv->ioctl_sock, SIOCGIWRTS, &iwr) < 0) { perror("ioctl[SIOCGIWRTS]"); return -1; } *rts = iwr.u.rts.value; return 0;}static int i802_set_frag(void *priv, int frag){ struct i802_driver_data *drv = priv; struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); iwr.u.frag.value = frag; iwr.u.frag.fixed = 1; if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) { perror("ioctl[SIOCSIWFRAG]"); return -1; } return 0;}static int i802_get_frag(void *priv, int *frag){ struct i802_driver_data *drv = priv; struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); if (ioctl(drv->ioctl_sock, SIOCGIWFRAG, &iwr) < 0) { perror("ioctl[SIOCGIWFRAG]"); return -1; } *frag = iwr.u.frag.value; return 0;}static int i802_set_retry(void *priv, int short_retry, int long_retry){ struct i802_driver_data *drv = priv; struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); iwr.u.retry.value = short_retry; iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; if (ioctl(drv->ioctl_sock, SIOCSIWRETRY, &iwr) < 0) { perror("ioctl[SIOCSIWRETRY(short)]"); return -1; } iwr.u.retry.value = long_retry; iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; if (ioctl(drv->ioctl_sock, SIOCSIWRETRY, &iwr) < 0) { perror("ioctl[SIOCSIWRETRY(long)]"); return -1; } return 0;}static int i802_get_retry(void *priv, int *short_retry, int *long_retry){ struct i802_driver_data *drv = priv; struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; if (ioctl(drv->ioctl_sock, SIOCGIWRETRY, &iwr) < 0) { perror("ioctl[SIOCGIWFRAG(short)]"); return -1; } *short_retry = iwr.u.retry.value; iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; if (ioctl(drv->ioctl_sock, SIOCGIWRETRY, &iwr) < 0) { perror("ioctl[SIOCGIWFRAG(long)]"); return -1; } *long_retry = iwr.u.retry.value; return 0;}static int i802_flush(void *priv){ struct i802_driver_data *drv = priv; struct nl_msg *msg; msg = nlmsg_alloc(); if (!msg) return -1; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_DEL_STATION, 0); /* * XXX: FIX! this needs to flush all VLANs too */ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: return -ENOBUFS;}static int get_sta_handler(struct nl_msg *msg, void *arg){ struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct hostap_sta_driver_data *data = arg; struct nlattr *stats[NL80211_STA_INFO_MAX + 1]; static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = { [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 }, [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 }, [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 }, [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 }, [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 }, }; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); /* * TODO: validate the interface and mac address! * Otherwise, there's a race condition as soon as * the kernel starts sending station notifications. */ if (!tb[NL80211_ATTR_STA_INFO]) { wpa_printf(MSG_DEBUG, "sta stats missing!"); return NL_SKIP; } if (nla_parse_nested(stats, NL80211_STA_INFO_MAX, tb[NL80211_ATTR_STA_INFO], stats_policy)) { wpa_printf(MSG_DEBUG, "failed to parse nested attributes!"); return NL_SKIP; } if (stats[NL80211_STA_INFO_INACTIVE_TIME]) data->inactive_msec = nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]); if (stats[NL80211_STA_INFO_RX_BYTES]) data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]); if (stats[NL80211_STA_INFO_TX_BYTES]) data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]); if (stats[NL80211_STA_INFO_RX_PACKETS]) data->rx_packets = nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]); if (stats[NL80211_STA_INFO_TX_PACKETS]) data->tx_packets = nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]); return NL_SKIP;}static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, const u8 *addr){ struct i802_driver_data *drv = priv; struct nl_msg *msg; os_memset(data, 0, sizeof(*data)); msg = nlmsg_alloc(); if (!msg) return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_GET_STATION, 0); NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); return send_and_recv_msgs(drv, msg, get_sta_handler, data); nla_put_failure: return -ENOBUFS;}static int i802_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, int encrypt, const u8 *own_addr){ struct i802_driver_data *drv = priv; struct ieee80211_hdr *hdr; size_t len; u8 *pos; int res;#if 0 /* FIX */ int qos = sta->flags & WLAN_STA_WME;#else int qos = 0;#endif len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 + data_len; hdr = os_zalloc(len); if (hdr == NULL) { printf("malloc() failed for i802_send_data(len=%lu)\n", (unsigned long) len); return -1; } hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); if (encrypt) hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);#if 0 /* To be enabled if qos determination is added above */ if (qos) { hdr->frame_control |= host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4); }#endif memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); pos = (u8 *) (hdr + 1);#if 0 /* To be enabled if qos determination is added above */ if (qos) { /* add an empty QoS header if needed */ pos[0] = 0; pos[1] = 0; pos += 2; }#endif memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); pos += sizeof(rfc1042_header); WPA_PUT_BE16(pos, ETH_P_PAE); pos += 2; memcpy(pos, data, data_len); res = i802_send_frame(drv, (u8 *) hdr, len, encrypt, 0); free(hdr); if (res < 0) { perror("i802_send_eapol: send"); printf("i802_send_eapol - packet len: %lu - failed\n", (unsigned long) len); } return res;}static int i802_sta_add2(const char *ifname, void *priv, struct hostapd_sta_add_params *params){ struct i802_driver_data *drv = priv; struct nl_msg *msg; int ret = -ENOBUFS; msg = nlmsg_alloc(); if (!msg) return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_NEW_STATION, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr); NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid); NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len, params->supp_rates); NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, params->listen_interval);#ifdef CONFIG_IEEE80211N if (params->ht_capabilities) { NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, params->ht_capabilities->length, ¶ms->ht_capabilities->data); }#endif /* CONFIG_IEEE80211N */ ret = send_and_recv_msgs(drv, msg, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_NEW_STATION " "result: %d (%s)", ret, strerror(-ret)); if (ret == -EEXIST) ret = 0; nla_put_failure: return ret;}static int i802_sta_remove(void *priv, const u8 *addr){ struct i802_driver_data *drv = priv; struct nl_msg *msg; int ret; msg = nlmsg_alloc(); if (!msg) return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_DEL_STATION, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); ret = send_and_recv_msgs(drv, msg, NULL, NULL); if (ret == -ENOENT) return 0; return ret; nla_put_failure: return -ENOBUFS;}static int i802_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or, int flags_and){ struct i802_driver_data *drv = priv; struct nl_msg *msg, *flags = NULL; msg = nlmsg_alloc(); if (!msg) return -ENOMEM; flags = nlmsg_alloc(); if (!flags) { nlmsg_free(msg); return -ENOMEM; } genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_STATION, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); if (total_flags & WLAN_STA_AUTHORIZED || !drv->ieee802_1x_active) NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED); if (total_flags & WLAN_STA_WME) NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME); if (total_flags & WLAN_STA_SHORT_PREAMBLE) NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE); if (total_flags & WLAN_STA_MFP) NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP); if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags)) goto nla_put_failure; nlmsg_free(flags); return send_and_recv_msgs(drv, msg, NULL, NULL); nla_put_failure: nlmsg_free(flags); return -ENOBUFS;}static int i802_set_regulatory_domain(void *priv, unsigned int rd){ return -1;}static int i802_set_tx_queue_params(void *priv, int queue, int aifs, int cw_min, int cw_max, int burst_time){ struct i802_driver_data *drv = priv; struct nl_msg *msg; struct nlattr *txq, *params; msg = nlmsg_alloc(); if (!msg) return -1; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_WIPHY, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS); if (!txq) goto nla_put_failure; /* We are only sending parameters for a single TXQ at a time */ params = nla_nest_start(msg, 1); if (!params) goto nla_put_failure; NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, queue); /* Burst time is configured in units of 0.1 msec and TXOP parameter in * 32 usec, so need to convert the value here. */ NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32); NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min); NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max); NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs); nla_nest_end(msg, params); nla_nest_end(msg, txq); if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) return 0; nla_put_failure: return -1;}static void nl80211_remove_iface(struct i802_driver_data *drv, int ifidx){ struct nl_msg *msg; /* stop listening for EAPOL on this interface */ del_ifidx(drv, ifidx); msg = nlmsg_alloc(); if (!msg) goto nla_put_failure; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_DEL_INTERFACE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx); if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) return; nla_put_failure: printf("Failed to remove interface.\n");}static int nl80211_create_iface(struct i802_driver_data *drv, const char *ifname, enum nl80211_iftype iftype, const u8 *addr){ struct nl_msg *msg, *flags = NULL; int ifidx; struct ifreq ifreq; struct iwreq iwr; int ret = -ENOBUFS; msg = nlmsg_alloc(); if (!msg) return -1; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_NEW_INTERFACE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->hapd->conf->iface)); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype); if (iftype == NL80211_IFTYPE_MONITOR) { int err; flags = nlmsg_alloc(); if (!flags) goto nla_put_failure; NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES); err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags); nlmsg_free(flags); if (err) goto nla_put_failure; } ret = send_and_recv_msgs(drv, msg, NULL, NULL); if (ret) { nla_put_failure: printf("Failed to create interface %s.\n", ifname); return ret; } ifidx = if_nametoindex(ifname); if (ifidx <= 0) return -1; /* start listening for EAPOL on this interface */ add_ifidx(drv, ifidx); if (addr) { switch (iftype) { case NL80211_IFTYPE_AP: os_strlcpy(ifreq.ifr_name, ifname, IFNAMSIZ); memcpy(ifreq.ifr_hwaddr.sa_data, addr, ETH_ALEN); ifreq.ifr_hwaddr.sa_family = ARPHRD_ETHER; if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifreq)) { nl80211_remove_iface(drv, ifidx); return -1; } break; case NL80211_IFTYPE_WDS: memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); iwr.u.addr.sa_family = ARPHRD_ETHER; memcpy(iwr.u.addr.sa_data, addr, ETH_ALEN); if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr)) return -1; break; default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -