Exemple #1
0
/* Based on ieee80211_listnodes() from ifconfig. */
struct config_ssid *
all_matching_network(struct config_interfaces * config) {
        struct ieee80211_nodereq_all na;
        struct ieee80211_nodereq nr[512];
        struct ifreq 	ifr;
        char 		name     [IEEE80211_NWID_LEN];
        int 		i        , s, len, res;
        int8_t 		rssi;
        struct config_ssid *ret = 0;

        /* Open socket and scan for wlans. */
        memset(&ifr, 0, sizeof(ifr));
        strlcpy(ifr.ifr_name, config->if_name, sizeof(ifr.ifr_name));
        s = open_socket(AF_INET);
        if (s < 0)
            return NULL;
        if (ioctl(s, SIOCS80211SCAN, (caddr_t) & ifr) != 0) {
            /* Interface not available; invoking ifconfig to bring it up. */
            printf("error scanning: %s\n", strerror(errno));
            close(s);
            char 		command  [50];
            snprintf(command, sizeof(command), "ifconfig %s up\n", config->if_name);
            printf("%s\n", command);
            system(command);
            printf("try bringing up interface\n");
            return NULL;
        }
        memset(&na, 0, sizeof(na));
        memset(&nr, 0, sizeof(nr));
        na.na_node = nr;
        na.na_size = sizeof(nr);
        strlcpy(na.na_ifname, config->if_name, sizeof(na.na_ifname));
        res = ioctl(s, SIOCG80211ALLNODES, &na);
        close(s);
        if (res) {
            printf("error retrieving nodes: %s\n", strerror(errno));
            return NULL;
        }
        if (!na.na_nodes) {
            printf("no access points found\n");
            return NULL;
        }
        /* Sort nodes in order of signal strength. */
        qsort(nr, na.na_nodes, sizeof(*nr), rssicmp);
        struct config_ssid *cur = config->ssids;
        while (cur) {
            for (i = 0; i < na.na_nodes; i++) {
                len = nr[i].nr_nwid_len > IEEE80211_NWID_LEN ? IEEE80211_NWID_LEN : nr[i].nr_nwid_len;
                snprintf(name, IEEE80211_NWID_LEN, "%.*s", len, nr[i].nr_nwid);
                rssi = nr[i].nr_rssi;
                printf("checking this one: %s and this one: %s, has rssi of %d\n", cur->ssid_name, name, rssi);
                if (strcmp(cur->ssid_name, name) == 0) {
                    printf("this one found\n");
                    /*
                     * get data we need from scan; BSSID, signal
                     * strength, auth mode.
                     */
                    struct ether_addr ea;
                    memcpy(&ea.ether_addr_octet, nr[i].nr_bssid, sizeof(ea.ether_addr_octet));
                    /* convert BSSID from binary to ASCII. */
                    strlcpy(cur->ssid_bssid, ether_ntoa(&ea), sizeof(cur->ssid_bssid));
                    /* Get signal strength. */
                    if (nr[i].nr_max_rssi)
                        cur->ssid_rssi = IEEE80211_NODEREQ_RSSI(&nr[i]);
                    else
                        cur->ssid_rssi = nr[i].nr_rssi;
                    printf("signal strength is: %d\n", cur->ssid_rssi);
                    if (nr[i].nr_capinfo) {
                        if ((nr[i].nr_rsnakms & IEEE80211_WPA_AKM_8021X) || (nr[i].nr_rsnakms & IEEE80211_WPA_AKM_SHA256_8021X))
                            strlcpy(cur->ssid_auth, "802.1x", sizeof(cur->ssid_auth));
                            
                        /*
                         * CCMP is WPA2 and TKIP is WPA1. The
                         * code to connect to either auth is
                         * exactly the same, they just uses
                         * different cipher. For the purposes
                         * of this program, I am
                         * consolidating them.
                         */    
                        else if ((nr[i].nr_rsnciphers & IEEE80211_WPA_CIPHER_CCMP) || (nr[i].nr_rsnciphers & IEEE80211_WPA_CIPHER_TKIP))
                            strlcpy(cur->ssid_auth, "wpa", sizeof(cur->ssid_auth));
                        /*
                         * Check if a password has been set
                         * for this access point. If there
                         * is, we use WEP.
                         */
                        else {
                            if (cur->ssid_pass[0] == '\0')
                                strlcpy(cur->ssid_auth, "none", sizeof(cur->ssid_auth));
                            else
                                strlcpy(cur->ssid_auth, "wep", sizeof(cur->ssid_auth));
						/*
						 * Unable to check for a WEP
						 * cipher with a nodereq.
						 */
                        }
                    } else
                        strlcpy(cur->ssid_auth, "none", sizeof(cur->ssid_auth));
                        /* No auth on access point. */
                    printf("%s mode found\n", cur->ssid_auth);
                    struct config_ssid *cpy = malloc(sizeof(struct config_ssid));
                    memcpy(cpy, cur, sizeof(struct config_ssid));
                    cpy->next = 0;
                    if (ret)
                        ret->next = cpy;
                    else {
                        ret = cpy;
                        ret->next = 0;
                    }
                }
            }
        cur = cur->next;
        }
        return ret;
}
static int get_wireless_info(const char *interface, wireless_info_t *info) {
        memset(info, 0, sizeof(wireless_info_t));

#ifdef LINUX
        int skfd = iw_sockets_open();
        if (skfd < 0) {
                perror("iw_sockets_open");
                return 0;
        }

        wireless_config wcfg;
        if (iw_get_basic_config(skfd, interface, &wcfg) < 0) {
            close(skfd);
            return 0;
        }

        if (wcfg.has_essid && wcfg.essid_on) {
                info->flags |= WIRELESS_INFO_FLAG_HAS_ESSID;
                strncpy(&info->essid[0], wcfg.essid, IW_ESSID_MAX_SIZE);
                info->essid[IW_ESSID_MAX_SIZE] = '\0';
        }

        /* If the function iw_get_stats does not return proper stats, the
           wifi is considered as down.
           Since ad-hoc network does not have theses stats, we need to return
           here for this mode. */
        if (wcfg.mode == 1) {
                close(skfd);
                return 1;
        }

        /* Wireless quality is a relative value in a driver-specific range.
           Signal and noise level can be either relative or absolute values
           in dBm. Furthermore, noise and quality can be expressed directly
           in dBm or in RCPI (802.11k), which we convert to dBm. When those
           values are expressed directly in dBm, they range from -192 to 63,
           and since the values are packed into 8 bits, we need to perform
           8-bit arithmetic on them. Assume absolute values if everything
           else fails (driver bug). */

        iwrange range;
        if (iw_get_range_info(skfd, interface, &range) < 0) {
                close(skfd);
                return 0;
        }

        iwstats stats;
        if (iw_get_stats(skfd, interface, &stats, &range, 1) < 0) {
                close(skfd);
                return 0;
        }

        if (stats.qual.level != 0 || (stats.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI))) {
                if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) {
                        info->quality = stats.qual.qual;
                        info->quality_max = range.max_qual.qual;
                        info->quality_average = range.avg_qual.qual;
                        info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY;
                }

                if (stats.qual.updated & IW_QUAL_RCPI) {
                        if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
                                info->signal_level = stats.qual.level / 2.0 - 110 + 0.5;
                                info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
                        }
                        if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
                                info->noise_level = stats.qual.noise / 2.0 - 110 + 0.5;
                                info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
                        }
                }
                else {
                        if ((stats.qual.updated & IW_QUAL_DBM) || stats.qual.level > range.max_qual.level) {
                                if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
                                        info->signal_level = stats.qual.level;
                                        if (info->signal_level > 63)
                                                info->signal_level -= 256;
                                        info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
                                }
                                if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
                                        info->noise_level = stats.qual.noise;
                                        if (info->noise_level > 63)
                                                info->noise_level -= 256;
                                        info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
                                }
                        }
                        else {
                                if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
                                        info->signal_level = stats.qual.level;
                                        info->signal_level_max = range.max_qual.level;
                                        info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
                                }
                                if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
                                        info->noise_level = stats.qual.noise;
                                        info->noise_level_max = range.max_qual.noise;
                                        info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
                                }
                        }
                }
        }
        else {
                if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) {
                        info->quality = stats.qual.qual;
                        info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY;
                }
                if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
                        info->quality = stats.qual.level;
                        info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
                }
                if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
                        info->quality = stats.qual.noise;
                        info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
                }
        }

        struct iwreq wrq;
        if (iw_get_ext(skfd, interface, SIOCGIWRATE, &wrq) >= 0)
                info->bitrate = wrq.u.bitrate.value;

        close(skfd);
        return 1;
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
        int s, len, inwid;
        uint8_t buf[24 * 1024], *cp;
        struct ieee80211req na;
        char network_id[IEEE80211_NWID_LEN + 1];

        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
                return (0);

        memset(&na, 0, sizeof(na));
        strlcpy(na.i_name, interface, sizeof(na.i_name));
        na.i_type = IEEE80211_IOC_SSID;
        na.i_data = &info->essid[0];
        na.i_len = IEEE80211_NWID_LEN + 1;
        if ((inwid = ioctl(s, SIOCG80211, (caddr_t)&na)) == -1) {
                close(s);
                return (0);
        }
        if (inwid == 0) {
                if (na.i_len <= IEEE80211_NWID_LEN)
                        len = na.i_len + 1;
                else
                        len = IEEE80211_NWID_LEN + 1;
                info->essid[len -1] = '\0';
        } else {
                close(s);
                return (0);
        }
        info->flags |= WIRELESS_INFO_FLAG_HAS_ESSID;

        memset(&na, 0, sizeof(na));
        strlcpy(na.i_name, interface, sizeof(na.i_name));
        na.i_type = IEEE80211_IOC_SCAN_RESULTS;
        na.i_data = buf;
        na.i_len = sizeof(buf);

        if (ioctl(s, SIOCG80211, (caddr_t)&na) == -1) {
                printf("fail\n");
                close(s);
                return (0);
        }

        close(s);
        len = na.i_len;
        cp = buf;
        struct ieee80211req_scan_result *sr;
        uint8_t *vp;
        sr = (struct ieee80211req_scan_result *)cp;
        vp = (u_int8_t *)(sr + 1);
        strlcpy(network_id, (const char *)vp, sr->isr_ssid_len + 1);
        if (!strcmp(network_id, &info->essid[0])) {
                info->signal_level = sr->isr_rssi;
                info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
                info->noise_level = sr->isr_noise;
                info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
                info->quality = sr->isr_intval;
                info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY;
        }

        return 1;
#endif
#ifdef __OpenBSD__
	struct ifreq ifr;
	struct ieee80211_bssid bssid;
	struct ieee80211_nwid nwid;
	struct ieee80211_nodereq nr;

	struct ether_addr ea;

        int s, len, ibssid, inwid;
	u_int8_t zero_bssid[IEEE80211_ADDR_LEN];

	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
		return (0);

        memset(&ifr, 0, sizeof(ifr));
        ifr.ifr_data = (caddr_t)&nwid;
	(void)strlcpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
        inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr);

	memset(&bssid, 0, sizeof(bssid));
	strlcpy(bssid.i_name, interface, sizeof(bssid.i_name));
	ibssid = ioctl(s, SIOCG80211BSSID, &bssid);

	if (ibssid != 0 || inwid != 0) {
		close(s);
		return 0;
	}

	/* NWID */
	{
		if (nwid.i_len <= IEEE80211_NWID_LEN)
			len = nwid.i_len + 1;
		else
			len = IEEE80211_NWID_LEN + 1;

		strncpy(&info->essid[0], nwid.i_nwid, len);
		info->essid[IW_ESSID_MAX_SIZE] = '\0';
		info->flags |= WIRELESS_INFO_FLAG_HAS_ESSID;
	}

	/* Signal strength */
	{
		memset(&zero_bssid, 0, sizeof(zero_bssid));
		if (ibssid == 0 && memcmp(bssid.i_bssid, zero_bssid, IEEE80211_ADDR_LEN) != 0) {
			memcpy(&ea.ether_addr_octet, bssid.i_bssid, sizeof(ea.ether_addr_octet));

			bzero(&nr, sizeof(nr));
			bcopy(bssid.i_bssid, &nr.nr_macaddr, sizeof(nr.nr_macaddr));
			strlcpy(nr.nr_ifname, interface, sizeof(nr.nr_ifname));

			if (ioctl(s, SIOCG80211NODE, &nr) == 0 && nr.nr_rssi) {
				if (nr.nr_max_rssi)
					info->signal_level_max = IEEE80211_NODEREQ_RSSI(&nr);
				else
					info->signal_level = nr.nr_rssi;

		                info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
			}
		}
	}

	close(s);
	return 1;
#endif
	return 0;
}