Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}