📄 driver_nl80211.c
字号:
struct wpa_driver_nl80211_data *drv = eloop_ctx; wpa_printf(MSG_DEBUG, "nl80211: Event message available"); cb = nl_cb_clone(drv->nl_cb); if (!cb) return; nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv); nl_recvmsgs(drv->nl_handle, cb); nl_cb_put(cb);}static int wpa_driver_nl80211_get_ifflags_ifname(struct wpa_driver_nl80211_data *drv, const char *ifname, int *flags){ struct ifreq ifr; os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { perror("ioctl[SIOCGIFFLAGS]"); return -1; } *flags = ifr.ifr_flags & 0xffff; return 0;}/** * wpa_driver_nl80211_get_ifflags - Get interface flags (SIOCGIFFLAGS) * @drv: driver_nl80211 private data * @flags: Pointer to returned flags value * Returns: 0 on success, -1 on failure */static int wpa_driver_nl80211_get_ifflags(struct wpa_driver_nl80211_data *drv, int *flags){ return wpa_driver_nl80211_get_ifflags_ifname(drv, drv->ifname, flags);}static int wpa_driver_nl80211_set_ifflags_ifname( struct wpa_driver_nl80211_data *drv, const char *ifname, int flags){ struct ifreq ifr; os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); ifr.ifr_flags = flags & 0xffff; if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { perror("SIOCSIFFLAGS"); return -1; } return 0;}/** * wpa_driver_nl80211_set_ifflags - Set interface flags (SIOCSIFFLAGS) * @drv: driver_nl80211 private data * @flags: New value for flags * Returns: 0 on success, -1 on failure */static int wpa_driver_nl80211_set_ifflags(struct wpa_driver_nl80211_data *drv, int flags){ return wpa_driver_nl80211_set_ifflags_ifname(drv, drv->ifname, flags);}/** * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain * @priv: driver_nl80211 private data * @alpha2_arg: country to which to switch to * Returns: 0 on success, -1 on failure * * This asks nl80211 to set the regulatory domain for given * country ISO / IEC alpha2. */static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg){ struct wpa_driver_nl80211_data *drv = priv; char alpha2[3]; struct nl_msg *msg; msg = nlmsg_alloc(); if (!msg) goto nla_put_failure; alpha2[0] = alpha2_arg[0]; alpha2[1] = alpha2_arg[1]; alpha2[2] = '\0'; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_REQ_SET_REG, 0); NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2); if (send_and_recv_msgs(drv, msg, NULL, NULL)) return -EINVAL; return 0;nla_put_failure: return -EINVAL;}static int wpa_driver_nl80211_set_probe_req_ie(void *priv, const u8 *ies, size_t ies_len){ struct wpa_driver_nl80211_data *drv = priv; struct nl_msg *msg; int ret = -1; msg = nlmsg_alloc(); if (!msg) return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_MGMT_EXTRA_IE, 0); NLA_PUT_U8(msg, NL80211_ATTR_MGMT_SUBTYPE, 4 /* ProbeReq */); if (ies) NLA_PUT(msg, NL80211_ATTR_IE, ies_len, ies); ret = 0; NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); ret = send_and_recv_msgs(drv, msg, NULL, NULL); return ret;nla_put_failure: return -ENOBUFS;}#ifdef CONFIG_CLIENT_MLMEstatic int nl80211_set_vif(struct wpa_driver_nl80211_data *drv, int drop_unencrypted, int userspace_mlme){#ifdef NL80211_CMD_SET_VIF struct nl_msg *msg; int ret = -1; msg = nlmsg_alloc(); if (!msg) return -ENOMEM; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_VIF, 0); if (drop_unencrypted >= 0) NLA_PUT_U8(msg, NL80211_ATTR_VIF_DROP_UNENCRYPTED, drop_unencrypted); if (userspace_mlme >= 0) NLA_PUT_U8(msg, NL80211_ATTR_VIF_USERSPACE_MLME, userspace_mlme); ret = 0; NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); ret = send_and_recv_msgs(drv, msg, NULL, NULL); return ret;nla_put_failure: return -ENOBUFS;#else /* NL80211_CMD_SET_VIF */ return -1;#endif /* NL80211_CMD_SET_VIF */}static int wpa_driver_nl80211_set_userspace_mlme( struct wpa_driver_nl80211_data *drv, int enabled){ return nl80211_set_vif(drv, -1, enabled);}static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx){ struct nl_msg *msg; 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: wpa_printf(MSG_ERROR, "nl80211: Failed to remove interface.");}static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, const char *ifname, enum nl80211_iftype iftype){ struct nl_msg *msg, *flags = NULL; int ifidx, err; 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->ifname)); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype); if (iftype == NL80211_IFTYPE_MONITOR) { 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: wpa_printf(MSG_ERROR, "nl80211: Failed to create interface %d", ret); return ret; } ifidx = if_nametoindex(ifname); if (ifidx <= 0) return -1; return ifidx;}static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx){ struct wpa_driver_nl80211_data *drv = eloop_ctx; int len; unsigned char buf[3000]; struct ieee80211_radiotap_iterator iter; int ret; int injected = 0, failed = 0, rxflags = 0; struct ieee80211_rx_status rx_status; len = recv(sock, buf, sizeof(buf), 0); if (len < 0) { perror("recv"); return; } if (ieee80211_radiotap_iterator_init(&iter, (void *) buf, len)) { wpa_printf(MSG_DEBUG, "nl80211: received invalid radiotap " "frame"); return; } os_memset(&rx_status, 0, sizeof(rx_status)); while (1) { ret = ieee80211_radiotap_iterator_next(&iter); if (ret == -ENOENT) break; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: received invalid " "radiotap frame (%d)", ret); return; } switch (iter.this_arg_index) { case IEEE80211_RADIOTAP_FLAGS: if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS) len -= 4; break; case IEEE80211_RADIOTAP_RX_FLAGS: rxflags = 1; break; case IEEE80211_RADIOTAP_TX_FLAGS: injected = 1; failed = le_to_host16((*(u16 *) iter.this_arg)) & IEEE80211_RADIOTAP_F_TX_FAIL; break; case IEEE80211_RADIOTAP_DATA_RETRIES: break; case IEEE80211_RADIOTAP_CHANNEL: /* TODO convert from freq/flags to channel number * rx_status.channel = XXX; */ break; case IEEE80211_RADIOTAP_RATE: break; case IEEE80211_RADIOTAP_DB_ANTSIGNAL: rx_status.ssi = *iter.this_arg; break; } } if (rxflags && injected) return; if (!injected) { wpa_supplicant_sta_rx(drv->ctx, buf + iter.max_length, len - iter.max_length, &rx_status); } else if (failed) { /* TX failure callback */ } else { /* TX success (ACK) callback */ }}static int wpa_driver_nl80211_create_monitor_interface( struct wpa_driver_nl80211_data *drv){ char buf[IFNAMSIZ]; struct sockaddr_ll ll; int optval, flags; socklen_t optlen; os_snprintf(buf, IFNAMSIZ, "mon.%s", drv->ifname); buf[IFNAMSIZ - 1] = '\0'; drv->monitor_ifidx = nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR); if (drv->monitor_ifidx < 0) return -1; if (wpa_driver_nl80211_get_ifflags_ifname(drv, buf, &flags) != 0 || wpa_driver_nl80211_set_ifflags_ifname(drv, buf, flags | IFF_UP) != 0) { wpa_printf(MSG_ERROR, "nl80211: Could not set interface '%s' " "UP", buf); goto error; } os_memset(&ll, 0, sizeof(ll)); ll.sll_family = AF_PACKET; ll.sll_ifindex = drv->monitor_ifidx; drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (drv->monitor_sock < 0) { perror("socket[PF_PACKET,SOCK_RAW]"); goto error; } if (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) { perror("monitor socket bind"); goto error; } optlen = sizeof(optval); optval = 20; if (setsockopt (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) { perror("Failed to set socket priority"); goto error; } if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read, drv, NULL)) { wpa_printf(MSG_ERROR, "nl80211: Could not register monitor " "read socket"); goto error; } return 0; error: nl80211_remove_iface(drv, drv->monitor_ifidx); return -1;}#endif /* CONFIG_CLIENT_MLME *//** * wpa_driver_nl80211_init - Initialize nl80211 driver interface * @ctx: context to be used when calling wpa_supplicant functions, * e.g., wpa_supplicant_event() * @ifname: interface name, e.g., wlan0 * Returns: Pointer to private data, %NULL on failure */static void * wpa_driver_nl80211_init(void *ctx, const char *ifname){ int s, ret; struct sockaddr_nl local; struct wpa_driver_nl80211_data *drv; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) return NULL; drv->ctx = ctx; os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); if (drv->nl_cb == NULL) { wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " "callbacks"); goto err1; } drv->nl_handle = nl_handle_alloc_cb(drv->nl_cb); if (drv->nl_handle == NULL) { wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " "callbacks"); goto err2; } if (genl_connect(drv->nl_handle)) { wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " "netlink"); goto err3; } drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle); if (drv->nl_cache == NULL) { wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " "netlink cache"); goto err3; } drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211"); if (drv->nl80211 == NULL) { wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not " "found"); goto err4; } ret = nl_get_multicast_id(drv, "nl80211", "scan"); if (ret >= 0) ret = nl_socket_add_membership(drv->nl_handle, ret); if (ret < 0) { wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " "membership for scan events: %d (%s)", ret, strerror(-ret)); goto err4; } eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle), wpa_driver_nl80211_event_receive, drv, ctx); drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); if (drv->ioctl_sock < 0) { perror("socket(PF_INET,SOCK_DGRAM)"); goto err5; } s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (s < 0) { perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); goto err6; } os_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); goto err6; } eloop_register_read_sock(s, wpa_driver_nl80211_event_receive_wext, drv, ctx); drv->wext_event_sock = s; wpa_driver_nl80211_finish_drv_init(drv); return drv;err6: close(drv->ioctl_sock);err5: genl_family_put(drv->nl80211);err4: nl_cache_free(drv->nl_cache);err3: nl_handle_destroy(drv->nl_handle);err2: nl_cb_put(drv->nl_cb);err1: os_free(drv); return NULL;}static voidwpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv){ int flags; if (wpa_driver_nl80211_get_ifflags(drv, &flags) != 0) printf("Could not get interface '%s' flags\n", drv->ifname);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -