int nl80211_create_monitor_interface(struct nl80211_data* ctx) { if (ctx->monitor_ifidx < 0) { // create monitor ctx->monitor_ifidx = nl80211_create_iface_once(ctx, NULL, NULL); if (ctx->monitor_ifidx == -EOPNOTSUPP) { /* * This is backward compatibility for a few versions of * the kernel only that didn't advertise the right * attributes for the only driver that then supported * AP mode w/o monitor -- ath6kl. */ fprintf(stderr, "nl80211: Driver does not support monitor interface type - try to run without it\n"); } } else { fprintf(stderr, "nl80211: re-use monitor '%s' index: %d\n",ctx->monitor_name, ctx->monitor_ifidx); } if (ctx->monitor_ifidx < 0) return -1; // interface up! if (linux_set_iface_flags(ctx->cfg->ioctl_sock, ctx->monitor_name, 1)) goto error; // create socket on monitor interface { struct sockaddr_ll ll; int optval; socklen_t optlen; memset(&ll, 0, sizeof(ll)); ll.sll_family = AF_PACKET; ll.sll_ifindex = ctx->monitor_ifidx; ctx->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (ctx->monitor_sock < 0) { fprintf(stderr, "nl80211: socket[PF_PACKET,SOCK_RAW] failed: %s\n", strerror(errno)); goto error; } if (add_monitor_filter(ctx->monitor_sock)) { fprintf(stderr, "Failed to set socket filter for monitor interface; do filtering in user space\n"); /* This works, but will cost in performance. */ } if (bind(ctx->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) { fprintf(stderr, "nl80211: monitor socket bind failed: %s\n", strerror(errno)); goto error; } optlen = sizeof(optval); optval = 20; if (setsockopt(ctx->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) { fprintf(stderr, "nl80211: Failed to set socket priority: %s\n", strerror(errno)); goto error; } if (eloop_register_read_sock(ctx->monitor_sock, handle_monitor_read, ctx, NULL)) { fprintf(stderr, "nl80211: Could not register monitor read socket\n"); goto error; } } return 0; error: nl80211_remove_monitor_interface(ctx); return -1; }
int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) { char buf[IFNAMSIZ]; struct sockaddr_ll ll; int optval; socklen_t optlen; if (drv->monitor_ifidx >= 0) { drv->monitor_refcount++; wpa_printf(MSG_DEBUG, "nl80211: Re-use existing monitor interface: refcount=%d", drv->monitor_refcount); return 0; } if (os_strncmp(drv->first_bss->ifname, "p2p-", 4) == 0) { /* * P2P interface name is of the format p2p-%s-%d. For monitor * interface name corresponding to P2P GO, replace "p2p-" with * "mon-" to retain the same interface name length and to * indicate that it is a monitor interface. */ snprintf(buf, IFNAMSIZ, "mon-%s", drv->first_bss->ifname + 4); } else { /* Non-P2P interface with AP functionality. */ snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss->ifname); } buf[IFNAMSIZ - 1] = '\0'; drv->monitor_ifidx = nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL, 0, NULL, NULL, 0); if (drv->monitor_ifidx == -EOPNOTSUPP) { /* * This is backward compatibility for a few versions of * the kernel only that didn't advertise the right * attributes for the only driver that then supported * AP mode w/o monitor -- ath6kl. */ wpa_printf(MSG_DEBUG, "nl80211: Driver does not support " "monitor interface type - try to run without it"); drv->device_ap_sme = 1; } if (drv->monitor_ifidx < 0) return -1; if (linux_set_iface_flags(drv->global->ioctl_sock, buf, 1)) goto error; 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) { wpa_printf(MSG_ERROR, "nl80211: socket[PF_PACKET,SOCK_RAW] failed: %s", strerror(errno)); goto error; } if (add_monitor_filter(drv->monitor_sock)) { wpa_printf(MSG_INFO, "Failed to set socket filter for monitor " "interface; do filtering in user space"); /* This works, but will cost in performance. */ } if (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) { wpa_printf(MSG_ERROR, "nl80211: monitor socket bind failed: %s", strerror(errno)); goto error; } optlen = sizeof(optval); optval = 20; if (setsockopt (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) { wpa_printf(MSG_ERROR, "nl80211: Failed to set socket priority: %s", strerror(errno)); goto error; } if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read, drv, NULL)) { wpa_printf(MSG_INFO, "nl80211: Could not register monitor read socket"); goto error; } drv->monitor_refcount++; return 0; error: nl80211_remove_monitor_interface(drv); return -1; }