From eeb143415a507aa7ce723f8964f1ac0aef6f392a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 10 Apr 2017 13:28:32 -0600 Subject: [PATCH] wireless/wapi: Quick port of Wapi wireless services. No build support yet. This also depends on features not supported by NuttX. This is a work in progress. --- include/wireless/wapi.h | 647 ++++++++++++ wireless/wapi/.gitignore | 6 + wireless/wapi/LICENSE | 23 + wireless/wapi/README | 42 + wireless/wapi/examples/ifadd.c | 118 +++ wireless/wapi/examples/ifdel.c | 62 ++ wireless/wapi/examples/sample-get.c | 35 + wireless/wapi/examples/sample-set.c | 36 + wireless/wapi/examples/sample.c | 410 ++++++++ wireless/wapi/src/network.c | 425 ++++++++ wireless/wapi/src/util.c | 235 +++++ wireless/wapi/src/util.h | 75 ++ wireless/wapi/src/wireless.c | 1498 +++++++++++++++++++++++++++ 13 files changed, 3612 insertions(+) create mode 100644 include/wireless/wapi.h create mode 100644 wireless/wapi/.gitignore create mode 100644 wireless/wapi/LICENSE create mode 100644 wireless/wapi/README create mode 100644 wireless/wapi/examples/ifadd.c create mode 100644 wireless/wapi/examples/ifdel.c create mode 100644 wireless/wapi/examples/sample-get.c create mode 100644 wireless/wapi/examples/sample-set.c create mode 100644 wireless/wapi/examples/sample.c create mode 100644 wireless/wapi/src/network.c create mode 100644 wireless/wapi/src/util.c create mode 100644 wireless/wapi/src/util.h create mode 100644 wireless/wapi/src/wireless.c diff --git a/include/wireless/wapi.h b/include/wireless/wapi.h new file mode 100644 index 000000000..c808f1883 --- /dev/null +++ b/include/wireless/wapi.h @@ -0,0 +1,647 @@ +/**************************************************************************** + * apps/include/wireless/wapi.h + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_INCLUDE_WIRELESS_WAPI_H +#define __APPS_INCLUDE_WIRELESS_WAPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Maximum allowed ESSID size. */ + +#define WAPI_ESSID_MAX_SIZE IW_ESSID_MAX_SIZE + +/* Path to /proc/net/wireless. (Requires procfs mounted.) */ + +#define WAPI_PROC_NET_WIRELESS "/proc/net/wireless" + +/* Path to /proc/net/route. (Requires procfs mounted.) */ + +#define WAPI_PROC_NET_ROUTE "/proc/net/route" + +/* Buffer size while reading lines from PROC_NET_ files. */ + +#define WAPI_PROC_LINE_SIZE 1024 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Generic linked list (dummy) decleration. (No definition!) */ + +typedef struct wapi_list_t wapi_list_t; + +/* Frequency flags. */ + +typedef enum +{ + WAPI_FREQ_AUTO = IW_FREQ_AUTO, + WAPI_FREQ_FIXED = IW_FREQ_FIXED +} wapi_freq_flag_t; + +/* Route target types. */ + +typedef enum +{ + WAPI_ROUTE_TARGET_NET, /* The target is a network. */ + WAPI_ROUTE_TARGET_HOST /* The target is a host. */ +} wapi_route_target_t; + +/* ESSID flags. */ + +typedef enum +{ + WAPI_ESSID_ON, + WAPI_ESSID_OFF +} wapi_essid_flag_t; + +/* Supported operation modes. */ + +typedef enum +{ + WAPI_MODE_AUTO = IW_MODE_AUTO, /* Driver decides. */ + WAPI_MODE_ADHOC = IW_MODE_ADHOC, /* Single cell network. */ + WAPI_MODE_MANAGED = IW_MODE_INFRA, /* Multi cell network, roaming, ... */ + WAPI_MODE_MASTER = IW_MODE_MASTER, /* Synchronisation master or access point. */ + WAPI_MODE_REPEAT = IW_MODE_REPEAT, /* Wireless repeater, forwarder. */ + WAPI_MODE_SECOND = IW_MODE_SECOND, /* Secondary master/repeater, backup. */ + WAPI_MODE_MONITOR = IW_MODE_MONITOR /* Passive monitor, listen only. */ +} wapi_mode_t; + +/* Bitrate flags. + * + * At the moment, unicast (IW_BITRATE_UNICAST) and broadcast + * (IW_BITRATE_BROADCAST) bitrate flags are not supported. + */ + +typedef enum +{ + WAPI_BITRATE_AUTO, + WAPI_BITRATE_FIXED +} wapi_bitrate_flag_t; + +/* Transmit power (txpower) flags. */ + +typedef enum +{ + WAPI_TXPOWER_DBM, /* Value is in dBm. */ + WAPI_TXPOWER_MWATT, /* Value is in mW. */ + WAPI_TXPOWER_RELATIVE /* Value is in arbitrary units. */ +} wapi_txpower_flag_t; + +/* Linked list container for strings. */ + +typedef struct wapi_string_t +{ + FAR struct wapi_string_t *next; + FAR char *data; +} wapi_string_t; + +/* Linked list container for scan results. */ + +typedef struct wapi_scan_info_t +{ + FAR struct wapi_scan_info_t *next; + struct ether_addr ap; + int has_essid; + char essid[WAPI_ESSID_MAX_SIZE + 1]; + wapi_essid_flag_t essid_flag; + int has_freq; + double freq; + int has_mode; + wapi_mode_t mode; + int has_bitrate; + int bitrate; +} wapi_scan_info_t; + +/* Linked list container for routing table rows. */ + +typedef struct wapi_route_info_t +{ + FAR struct wapi_route_info_t *next; + FAR char *ifname; + struct in_addr dest; + struct in_addr gw; + + unsigned int flags;/* See RTF_* in net/route.h for available values. */ + unsigned int refcnt; + unsigned int use; + unsigned int metric; + struct in_addr netmask; + unsigned int mtu; + unsigned int window; + unsigned int irtt; +} wapi_route_info_t; + +/* A generic linked list container. For functions taking wapi_list_t type of + * argument, caller is resposible for releasing allocated memory. + */ + +struct wapi_list_t +{ + union wapi_list_head_t + { + FAR wapi_string_t *string; + FAR wapi_scan_info_t *scan; + FAR wapi_route_info_t *route; + } head; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + + #ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Frequency flag names. */ + +EXTERN FAR const char *g_wapi_freq_flags[]; + +/* ESSID flag names. */ + +EXTERN FAR const char *g_wapi_essid_flags[]; + +/* Supported operation mode names. */ + +EXTERN FAR const char *g_wapi_modes[]; + +/* Bitrate flag names. */ + +EXTERN FAR const char *g_wapi_bitrate_flags[]; + +/* Transmit power flag names. */ + +EXTERN FAR const char *g_wapi_txpower_flags[]; + +/**************************************************************************** + * Public Function Prototyppes + ****************************************************************************/ + +/**************************************************************************** + * Name: wapi_get_ifup + * + * Description: + * Gets the interface up status. + * + * Input Parameters: + * is_up Set to 0, if up; 1, otherwise. + * + ****************************************************************************/ + +int wapi_get_ifup(int sock, const char *ifname, int *is_up); + +/**************************************************************************** + * Name: wapi_set_ifup + * + * Description: + * Activates the interface. + * + ****************************************************************************/ + +int wapi_set_ifup(int sock, const char *ifname); + +/**************************************************************************** + * Name: wapi_set_ifdown + * + * Description: + * Shuts down the interface. + * + ****************************************************************************/ + +int wapi_set_ifdown(int sock, const char *ifname); + +/**************************************************************************** + * Name: wapi_get_ip + * + * Description: + * Gets IP address of the given network interface. + * + ****************************************************************************/ + +int wapi_get_ip(int sock, const char *ifname, struct in_addr *addr); + +/**************************************************************************** + * Name: wapi_set_ip + * + * Description: + * Sets IP adress of the given network interface. + * + ****************************************************************************/ + +int wapi_set_ip(int sock, const char *ifname, const struct in_addr *addr); + +/**************************************************************************** + * Name: wapi_get_netmask + * + * Description: + * Gets netmask of the given network interface. + * + ****************************************************************************/ + +int wapi_get_netmask(int sock, const char *ifname, struct in_addr *addr); + +/**************************************************************************** + * Name: wapi_set_netmask + * + * Description: + * Sets netmask of the given network interface. + * + ****************************************************************************/ + +int wapi_set_netmask(int sock, const char *ifname, const struct in_addr *addr); + +/**************************************************************************** + * Name: wapi_get_routes + * + * Description: + * Parses routing table rows from WAPI_PROC_NET_ROUTE. + * + * Input Parameters: + * list - Pushes collected wapi_route_info_t into this list. + * + ****************************************************************************/ + +int wapi_get_routes(wapi_list_t * list); + +/**************************************************************************** + * Name: wapi_add_route_gw + * + * Description: + * Adds gateway for the given target network. + * + ****************************************************************************/ + +int wapi_add_route_gw(int sock, wapi_route_target_t targettype, + FAR const struct in_addr *target, + FAR const struct in_addr *netmask, + FAR const struct in_addr *gw); + +/**************************************************************************** + * Name: wapi_del_route_gw + * + * Description: + * Deletes gateway for the given target network. + * + ****************************************************************************/ + +int wapi_del_route_gw(int sock, wapi_route_target_t targettype, + FAR const struct in_addr *target, + FAR const struct in_addr *netmask, + FAR const struct in_addr *gw); + +/**************************************************************************** + * Name: wapi_get_we_version + * + * Description: + * Gets kernel WE (Wireless Extensions) version. + * + * Input Parameters: + * we_version Set to we_version_compiled of range information. + * + * Returned Value: + * Zero on success. + * + ****************************************************************************/ + +int wapi_get_we_version(int sock, const char *ifname, FAR int *we_version); + +/**************************************************************************** + * Name: wapi_get_freq + * + * Description: + * Gets the operating frequency of the device. + * + ****************************************************************************/ + +int wapi_get_freq(int sock, FAR const char *ifname, FAR double *freq, + FAR wapi_freq_flag_t *flag); + +/**************************************************************************** + * Name: wapi_set_freq + * + * Description: + * Sets the operating frequency of the device. + * + ****************************************************************************/ + +int wapi_set_freq(int sock, FARconst char *ifname, double freq, + wapi_freq_flag_t flag); + +/**************************************************************************** + * Name: wapi_freq2chan + * + * Description: + * Finds corresponding channel for the supplied freq. + * + * Returned Value: + * 0, on success; -2, if not found; otherwise, ioctl() return value. + * + ****************************************************************************/ + +int wapi_freq2chan(int sock, FAR const char *ifname, double freq, + FAR int *chan); + +/**************************************************************************** + * Name: wapi_chan2freq + * + * Description: + * Finds corresponding frequency for the supplied chan. + * + * Returned Value: + * 0, on success; -2, if not found; otherwise, ioctl() return value. + * + ****************************************************************************/ + +int wapi_chan2freq(int sock, FAR const char *ifname, int chan, + FAR double *freq); + +/**************************************************************************** + * Name: wapi_get_essid + * + * Description: + * Gets ESSID of the device. + * + * Input Parameters: + * essid - Used to store the ESSID of the device. Buffer must have + * enough space to store WAPI_ESSID_MAX_SIZE+1 characters. + * + ****************************************************************************/ + +int wapi_get_essid(int sock, FAR const char *ifname, FAR char *essid, + FAR wapi_essid_flag_t *flag); + +/**************************************************************************** + * Name: wapi_set_essid + * + * Description: + * Sets ESSID of the device. + * + * essid At most WAPI_ESSID_MAX_SIZE characters are read. + * + ****************************************************************************/ + +int wapi_set_essid(int sock, FAR const char *ifname, FAR const char *essid, + wapi_essid_flag_t flag); + +/**************************************************************************** + * Name: wapi_get_mode + * + * Description: + * Gets the operating mode of the device. + * + ****************************************************************************/ + +int wapi_get_mode(int sock, FAR const char *ifname, FAR wapi_mode_t *mode); + +/**************************************************************************** + * Name: wapi_set_mode + * + * Description: + * Sets the operating mode of the device. + * + ****************************************************************************/ + +int wapi_set_mode(int sock, FAR const char *ifname, wapi_mode_t mode); + +/**************************************************************************** + * Name: wapi_make_broad_ether + * + * Description: + * Creates an ethernet broadcast address. + * + ****************************************************************************/ + +int wapi_make_broad_ether(FAR struct ether_addr *sa); + +/**************************************************************************** + * Name: wapi_make_null_ether + * + * Description: + * Creates an ethernet NULL address. + * + ****************************************************************************/ + +int wapi_make_null_ether(FAR struct ether_addr *sa); + +/**************************************************************************** + * Name: wapi_get_ap + * + * Description: + * Gets access point address of the device. + * + * Input Parameters: + * ap - Set the to MAC address of the device. (For "any", a broadcast + * ethernet address; for "off", a null ethernet address is used.) + * + ****************************************************************************/ + +int wapi_get_ap(int sock, FAR const char *ifname, FAR struct ether_addr *ap); + +/**************************************************************************** + * Name: wapi_set_ap + * + * Description: + * Sets access point address of the device. + * + ****************************************************************************/ + +int wapi_set_ap(int sock, FAR const char *ifname, + FAR const struct ether_addr *ap); + +/**************************************************************************** + * Name: wapi_get_bitrate + * + * Description: + * Gets bitrate of the device. + * + ****************************************************************************/ + +int wapi_get_bitrate(int sock, FAR const char *ifname, + FAR int *bitrate, FAR wapi_bitrate_flag_t *flag); + +/**************************************************************************** + * Name: wapi_set_bitrate + * + * Description: + * Sets bitrate of the device. + * + ****************************************************************************/ + +int wapi_set_bitrate(int sock, FAR const char *ifname, int bitrate, + wapi_bitrate_flag_t flag); + +/**************************************************************************** + * Name: wapi_dbm2mwatt + * + * Description: + * Converts a value in dBm to a value in milliWatt. + * + ****************************************************************************/ + +int wapi_dbm2mwatt(int dbm); + +/**************************************************************************** + * Name: wapi_mwatt2dbm + * + * Description: + * Converts a value in milliWatt to a value in dBm. + * + ****************************************************************************/ + +int wapi_mwatt2dbm(int mwatt); + +/**************************************************************************** + * Name: wapi_get_txpower + * + * Description: + * Gets txpower of the device. + * + ****************************************************************************/ + +int wapi_get_txpower(int sock, FAR const char *ifname, FAR int *power, + FAR wapi_txpower_flag_t *flag); + +/**************************************************************************** + * Name: wapi_set_txpower + * + * Description: + * Sets txpower of the device. + * + ****************************************************************************/ + +int wapi_set_txpower(int sock, FAR const char *ifname, int power, + wapi_txpower_flag_t flag); + +/**************************************************************************** + * Name: wapi_if_add + * + * Description: + * Creates a virtual interface with name for interface ifname. + * + ****************************************************************************/ + +int wapi_if_add(int sock, FAR const char *ifname, FAR const char *name, + wapi_mode_t mode); + +/**************************************************************************** + * Name: wapi_if_del + * + * Description: + * Deletes a virtual interface with name. + * + ****************************************************************************/ + +int wapi_if_del(int sock, FAR const char *ifname); + +/**************************************************************************** + * Name: wapi_make_socket + * + * Description: + * Creates an AF_INET socket to be used in ioctl() calls. + * + * Returned Value: + * Non-negative on success. + * + ****************************************************************************/ + +int wapi_make_socket(void); + +/**************************************************************************** + * Name: wapi_get_ifnames + * + * Description: + * Parses WAPI_PROC_NET_WIRELESS. + * + * Returned Value: + * list Pushes collected wapi_string_t into this list. + * + ****************************************************************************/ + +int wapi_get_ifnames(FAR wapi_list_t *list); + +/**************************************************************************** + * Name: wapi_scan_init + * + * Description: + * Starts a scan on the given interface. Root privileges are required to start a + * scan. + * + ****************************************************************************/ + +int wapi_scan_init(int sock, const char *ifname); + +/**************************************************************************** + * Name: wapi_scan_stat + * + * Description: + * Checks the status of the scan process. + * + * Returned Value: + * Zero, if data is ready; 1, if data is not ready; negative on failure. + * + ****************************************************************************/ + +int wapi_scan_stat(int sock, FAR const char *ifname); + +/**************************************************************************** + * Name: wapi_scan_coll + * + * Description: + * Collects the results of a scan process. + * + * Input Parameters: + * aps - Pushes collected wapi_scan_info_t into this list. + * + ****************************************************************************/ + +int wapi_scan_coll(int sock, FAR const char *ifname, FAR wapi_list_t *aps); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_INCLUDE_WIRELESS_WAPI_H */ diff --git a/wireless/wapi/.gitignore b/wireless/wapi/.gitignore new file mode 100644 index 000000000..f21c854d1 --- /dev/null +++ b/wireless/wapi/.gitignore @@ -0,0 +1,6 @@ +/.built +/.depend +/Make.dep +/*.src +/*.obj +/*.lst diff --git a/wireless/wapi/LICENSE b/wireless/wapi/LICENSE new file mode 100644 index 000000000..eeb3ddaae --- /dev/null +++ b/wireless/wapi/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2010, Volkan YAZICI +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/wireless/wapi/README b/wireless/wapi/README new file mode 100644 index 000000000..41cafb9c2 --- /dev/null +++ b/wireless/wapi/README @@ -0,0 +1,42 @@ + + `_`_`_`_____`_____`__` + |`|`|`|``_``|``_``|``| + |`|`|`|`````|```__|``| + |_____|__|__|__|``|__| + +WAPI (Wireless API) provides an easy-to-use function set to configure wireless +network interfaces on a GNU/Linux system. One can think WAPI as a lightweight C +API for iwconfig, wlanconfig, ifconfig, and route commands. (But it is not a +thin wrapper for these command line tools.) It is designed to be used in +wireless heteregenous network research projects and supported by BWRC (Berkeley +Wireless Research Center) and WISERLAB (Wireless Information Systems Engineering +Research Laboratory at Özyeğin University). + +For source codes, see http://github.com/vy/wapi. The most recent version of the +documentation is (hopefully) always available at http://vy.github.com/wapi. + +--- L I C E N S E -------------------------------------------------------------- + +Copyright (c) 2010, Volkan YAZICI +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/wireless/wapi/examples/ifadd.c b/wireless/wapi/examples/ifadd.c new file mode 100644 index 000000000..2885949ba --- /dev/null +++ b/wireless/wapi/examples/ifadd.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * apps/wireless/wapi/examples/ifadd.c + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "include/wireless/wapi.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int parse_wapi_mode(FAR const char *s, FAR wapi_mode_t * mode) +{ + int ret = 0; + + if (!strcmp(s, "auto")) + { + *mode = WAPI_MODE_AUTO; + else if (!strcmp(s, "adhoc")) + { + *mode = WAPI_MODE_ADHOC; + } + else if (!strcmp(s, "managed")) + { + *mode = WAPI_MODE_MANAGED; + } + else if (!strcmp(s, "master")) + { + *mode = WAPI_MODE_MASTER; + } + else if (!strcmp(s, "repeat")) + { + *mode = WAPI_MODE_REPEAT; + } + else if (!strcmp(s, "second")) + { + *mode = WAPI_MODE_SECOND; + } + else if (!strcmp(s, "monitor")) + { + *mode = WAPI_MODE_MONITOR; + } + else + { + ret = 1; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +int main(int argc, FAR char *argv[]) +#else +int ifadd_main(int argc, char *argv[]) +#endif +{ + wapi_mode_t mode; + FAR const char *ifname; + FAR const char *name; + int ret; + + if (argc != 4) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + ifname = argv[1]; + name = argv[2]; + + if (parse_wapi_mode(argv[3], &mode)) + { + fprintf(stderr, "Unknown mode: %s!\n", argv[3]); + return EXIT_FAILURE; + } + + ret = wapi_if_add(-1, ifname, name, mode); + fprintf(stderr, "wapi_if_add(): ret: %d\n", ret); + + return ret; +} diff --git a/wireless/wapi/examples/ifdel.c b/wireless/wapi/examples/ifdel.c new file mode 100644 index 000000000..bc32eb9e0 --- /dev/null +++ b/wireless/wapi/examples/ifdel.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * apps/wireless/wapi/examples/ifdel.c + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "include/wireless/wapi.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +int main(int argc, FAR char *argv[]) +#else +int ifdel_main(int argc, char *argv[]) +#endif +{ + int ret; + + if (argc != 2) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + ret = wapi_if_del(-1, argv[1]); + fprintf(stderr, "wapi_if_del(): ret: %d\n", ret); + + return ret; +} diff --git a/wireless/wapi/examples/sample-get.c b/wireless/wapi/examples/sample-get.c new file mode 100644 index 000000000..7508d551e --- /dev/null +++ b/wireless/wapi/examples/sample-get.c @@ -0,0 +1,35 @@ +/**************************************************************************** + * apps/wireless/wapi/examples/sample.c + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "sample.c" diff --git a/wireless/wapi/examples/sample-set.c b/wireless/wapi/examples/sample-set.c new file mode 100644 index 000000000..f7c6bb600 --- /dev/null +++ b/wireless/wapi/examples/sample-set.c @@ -0,0 +1,36 @@ +/**************************************************************************** + * apps/wireless/wapi/examples/sample.c + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#define ENABLE_SET +#include "sample.c" diff --git a/wireless/wapi/examples/sample.c b/wireless/wapi/examples/sample.c new file mode 100644 index 000000000..04b288e6b --- /dev/null +++ b/wireless/wapi/examples/sample.c @@ -0,0 +1,410 @@ +/**************************************************************************** + * apps/wireless/wapi/examples/sample.c + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "include/wireless/wapi.h" + + +/* Gets current configuration of the @a ifname using WAPI accessors and prints + * them in a pretty fashion with their corresponding return values. If a getter + * succeeds, we try to set that property with the same value to test the setters + * as well. + */ + +static void conf(int sock, FAR const char *ifname) +{ + int ret; + struct in_addr addr; + double freq; + wapi_freq_flag_t freq_flag; + char essid[WAPI_ESSID_MAX_SIZE + 1]; + wapi_essid_flag_t essid_flag; + wapi_mode_t mode; + struct ether_addr ap; + int bitrate; + wapi_bitrate_flag_t bitrate_flag; + int txpower; + wapi_txpower_flag_t txpower_flag; + + /* Get ip */ + + bzero(&addr, sizeof(struct in_addr)); + ret = wapi_get_ip(sock, ifname, &addr); + printf("wapi_get_ip(): ret: %d", ret); + if (ret >= 0) + { + printf(", ip: %s", inet_ntoa(addr)); + +#ifdef ENABLE_SET + /* set ip (Make sure sin.sin_family is set to AF_INET.) */ + + ret = wapi_set_ip(sock, ifname, &addr); + printf("\nwapi_set_ip(): ret: %d", ret); +#endif + } + + putchar('\n'); + + /* Get netmask */ + + bzero(&addr, sizeof(struct in_addr)); + ret = wapi_get_netmask(sock, ifname, &addr); + printf("wapi_get_netmask(): ret: %d", ret); + if (ret >= 0) + { + printf(", netmask: %s", inet_ntoa(addr)); + +#ifdef ENABLE_SET + /* set netmask (Make sure sin.sin_family is set to AF_INET.) */ + + ret = wapi_set_netmask(sock, ifname, &addr); + printf("\nwapi_set_netmask(): ret: %d", ret); +#endif + } + + putchar('\n'); + + /* Get freq */ + + ret = wapi_get_freq(sock, ifname, &freq, &freq_flag); + printf("wapi_get_freq(): ret: %d", ret); + if (ret >= 0) + { + int chan; + double tmpfreq; + + printf(", freq: %g, freq_flag: %s", freq, g_wapi_freq_flags[freq_flag]); + + ret = wapi_freq2chan(sock, ifname, freq, &chan); + printf("\nwapi_freq2chan(): ret: %d", ret); + if (ret >= 0) + { + printf(", chan: %d", chan); + } + + ret = wapi_chan2freq(sock, ifname, chan, &tmpfreq); + printf("\nwapi_chan2freq(): ret: %d", ret); + if (ret >= 0) + { + printf(", freq: %g", tmpfreq); + } + +#ifdef ENABLE_SET + /* Set freq */ + + ret = wapi_set_freq(sock, ifname, freq, freq_flag); + printf("\nwapi_set_freq(): ret: %d", ret); +#endif + } + + putchar('\n'); + + /* Get essid */ + + ret = wapi_get_essid(sock, ifname, essid, &essid_flag); + printf("wapi_get_essid(): ret: %d", ret); + if (ret >= 0) + { + printf(", essid: %s, essid_flag: %s", + essid, g_wapi_essid_flags[essid_flag]); + +#ifdef ENABLE_SET + /* Set essid */ + + ret = wapi_set_essid(sock, ifname, essid, essid_flag); + printf("\nwapi_set_essid(): ret: %d", ret); +#endif + } + + putchar('\n'); + + /* Get operating mode */ + + ret = wapi_get_mode(sock, ifname, &mode); + printf("wapi_get_mode(): ret: %d", ret); + if (ret >= 0) + { + printf(", mode: %s", g_wapi_modes[mode]); + +#ifdef ENABLE_SET + /* Set operating mode */ + + ret = wapi_set_mode(sock, ifname, mode); + printf("\nwapi_set_mode(): ret: %d", ret); +#endif + } + + putchar('\n'); + + /* Get ap */ + + ret = wapi_get_ap(sock, ifname, &ap); + printf("wapi_get_ap(): ret: %d", ret); + if (ret >= 0) + { + printf(", ap: %02X:%02X:%02X:%02X:%02X:%02X", + ap.ether_addr_octet[0], ap.ether_addr_octet[1], + ap.ether_addr_octet[2], ap.ether_addr_octet[3], + ap.ether_addr_octet[4], ap.ether_addr_octet[5]); + +#ifdef ENABLE_SET + /* Set ap */ + + ret = wapi_set_ap(sock, ifname, &ap); + printf("\nwapi_set_ap(): ret: %d", ret); +#endif + } + + putchar('\n'); + + /* Get bitrate */ + + ret = wapi_get_bitrate(sock, ifname, &bitrate, &bitrate_flag); + printf("wapi_get_bitrate(): ret: %d", ret); + if (ret >= 0) + { + printf(", bitrate: %d, bitrate_flag: %s", bitrate, + g_wapi_bitrate_flags[bitrate_flag]); + +#ifdef ENABLE_SET + /* Set bitrate */ + + ret = wapi_set_bitrate(sock, ifname, bitrate, bitrate_flag); + printf("\nwapi_set_bitrate(): ret: %d", ret); +#endif + } + + putchar('\n'); + + /* Get txpower */ + + ret = wapi_get_txpower(sock, ifname, &txpower, &txpower_flag); + printf("wapi_get_txpower(): ret: %d", ret); + if (ret >= 0) + { + printf(", txpower: %d, txpower_flag: %s", + txpower, g_wapi_txpower_flags[txpower_flag]); + +#ifdef ENABLE_SET + /* Set txpower */ + + ret = wapi_set_txpower(sock, ifname, txpower, txpower_flag); + printf("\nwapi_set_txpower(): ret: %d", ret); +#endif + } + + putchar('\n'); +} + +/* Scans available APs in the range using given @a ifname interface. (Requires + * root privileges to start a scan.) + */ + +static void scan(int sock, FAR const char *ifname) +{ + int sleepdur = 1; + int sleeptries = 5; + wapi_list_t list; + FAR wapi_scan_info_t *info; + int ret; + + /* Start scan */ + + ret = wapi_scan_init(sock, ifname); + printf("wapi_scan_init(): ret: %d\n", ret); + + /* Wait for completion */ + + do + { + sleep(sleepdur); + ret = wapi_scan_stat(sock, ifname); + printf("wapi_scan_stat(): ret: %d, sleeptries: %d\n", ret, sleeptries); + } + while (--sleeptries > 0 && ret > 0); + + if (ret < 0) + { + return; + } + + /* Collect results */ + + bzero(&list, sizeof(wapi_list_t)); + ret = wapi_scan_coll(sock, ifname, &list); + printf("wapi_scan_coll(): ret: %d\n", ret); + + /* Print found aps */ + + for (info = list.head.scan; info; info = info->next) + { + printf(">> %02x:%02x:%02x:%02x:%02x:%02x %s\n", + info->ap.ether_addr_octet[0], info->ap.ether_addr_octet[1], + info->ap.ether_addr_octet[2], info->ap.ether_addr_octet[3], + info->ap.ether_addr_octet[4], info->ap.ether_addr_octet[5], + (info->has_essid ? info->essid : "")); + } + + /* Free ap list */ + + info = list.head.scan; + while (info) + { + FAR wapi_scan_info_t *temp; + + temp = info->next; + free(info); + info = temp; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +int main(int argc, FAR char *argv[]) +#else +int wapi_main(int argc, char *argv[]) +#endif +{ + FAR const char *ifname; + wapi_list_t list; + int ret; + int sock; + + /* Check command line args */ + + if (argc != 2) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + ifname = argv[1]; + + /* Get ifnames */ + + bzero(&list, sizeof(wapi_list_t)); + ret = wapi_get_ifnames(&list); + printf("wapi_get_ifnames(): ret: %d", ret); + if (ret >= 0) + { + FAR wapi_string_t *str; + + /* Print ifnames */ + + printf(", ifnames:"); + for (str = list.head.string; str; str = str->next) + { + printf(" %s", str->data); + } + + /* Free ifnames */ + + str = list.head.string; + while (str) + { + FAR wapi_string_t *tmp; + + tmp = str->next; + free(str->data); + free(str); + str = tmp; + } + } + + putchar('\n'); + + /* Get routes */ + + bzero(&list, sizeof(wapi_list_t)); + ret = wapi_get_routes(&list); + printf("wapi_get_routes(): ret: %d\n", ret); + if (ret >= 0) + { + wapi_route_info_t *ri; + + /* Print route */ + + for (ri = list.head.route; ri; ri = ri->next) + { + printf(">> dest: %s, gw: %s, netmask: %s\n", + inet_ntoa(ri->dest), inet_ntoa(ri->gw), + inet_ntoa(ri->netmask)); + } + + /* Free routes */ + + ri = list.head.route; + while (ri) + { + FAR wapi_route_info_t *tmpri; + + tmpri = ri->next; + free(ri->ifname); + free(ri); + ri = tmpri; + } + } + + /* Make a comm. sock. */ + + sock = wapi_make_socket(); + printf("wapi_make_socket(): sock: %d\n", sock); + + /* List conf */ + + printf("\nconf\n"); + printf("------------\n"); + conf(sock, ifname); + + /* Scan aps */ + + printf("\nscan\n"); + printf("----\n"); + scan(sock, ifname); + + /* Close comm. sock. */ + + close(sock); + return EXIT_SUCCESS; +} diff --git a/wireless/wapi/src/network.c b/wireless/wapi/src/network.c new file mode 100644 index 000000000..893bf434d --- /dev/null +++ b/wireless/wapi/src/network.c @@ -0,0 +1,425 @@ +/**************************************************************************** + * apps/wireless/wapi/examples/network.c + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "include/wireless/wapi.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int wapi_get_addr(int sock, FAR const char *ifname, int cmd, + FAR struct in_addr *addr) +{ + struct ifreq ifr; + int ret; + + WAPI_VALIDATE_PTR(addr); + + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, cmd, &ifr)) >= 0) + { + struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; + memcpy(addr, &sin->sin_addr, sizeof(struct in_addr)); + } + else + { + WAPI_IOCTL_STRERROR(cmd); + } + + return ret; +} + +static int wapi_set_addr(int sock, FAR const char *ifname, int cmd, + FAR const struct in_addr *addr) +{ + struct sockaddr_in sin; + struct ifreq ifr; + int ret; + + WAPI_VALIDATE_PTR(addr); + + sin.sin_family = AF_INET; + memcpy(&sin.sin_addr, addr, sizeof(struct in_addr)); + memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr_in)); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, cmd, &ifr)) < 0) + { + WAPI_IOCTL_STRERROR(cmd); + } + + return ret; +} + +static int wapi_act_route_gw(int sock, int act, + wapi_route_target_t targettype, + FAR const struct in_addr *target, + FAR const struct in_addr *netmask, + FAR const struct in_addr *gw) +{ + int ret; + struct rtentry rt; + FAR struct sockaddr_in *sin; + + /* Clean out rtentry. */ + + bzero(&rt, sizeof(struct rtentry)); + + /* Set target. */ + + sin = (struct sockaddr_in *)&rt.rt_dst; + sin->sin_family = AF_INET; + memcpy(&sin->sin_addr, target, sizeof(struct in_addr)); + + /* Set netmask. */ + + sin = (struct sockaddr_in *)&rt.rt_genmask; + sin->sin_family = AF_INET; + memcpy(&sin->sin_addr, netmask, sizeof(struct in_addr)); + + /* Set gateway. */ + + sin = (struct sockaddr_in *)&rt.rt_gateway; + sin->sin_family = AF_INET; + memcpy(&sin->sin_addr, gw, sizeof(struct in_addr)); + + /* Set rt_flags. */ + + rt.rt_flags = RTF_UP | RTF_GATEWAY; + if (targettype == WAPI_ROUTE_TARGET_HOST) + { + rt.rt_flags |= RTF_HOST; + } + + if ((ret = ioctl(sock, act, &rt)) < 0) + { + WAPI_IOCTL_STRERROR(act); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wapi_get_ifup + * + * Description: + * Gets the interface up status. + * + * Input Parameters: + * is_up Set to 0, if up; 1, otherwise. + * + ****************************************************************************/ + +int wapi_get_ifup(int sock, FAR const char *ifname, FAR int *is_up) +{ + struct ifreq ifr; + int ret; + + WAPI_VALIDATE_PTR(is_up); + + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIFFLAGS, &ifr)) >= 0) + { + *is_up = (ifr.ifr_flags & IFF_UP) == IFF_UP; + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIFFLAGS); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_set_ifup + * + * Description: + * Activates the interface. + * + ****************************************************************************/ + +int wapi_set_ifup(int sock, FAR const char *ifname) +{ + struct ifreq ifr; + int ret; + + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIFFLAGS, &ifr)) >= 0) + { + ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); + ret = ioctl(sock, SIOCSIFFLAGS, &ifr); + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIFFLAGS); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_set_ifdown + * + * Description: + * Shuts down the interface. + * + ****************************************************************************/ + +int wapi_set_ifdown(int sock, FAR const char *ifname) +{ + struct ifreq ifr; + int ret; + + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIFFLAGS, &ifr)) >= 0) + { + ifr.ifr_flags &= ~IFF_UP; + ret = ioctl(sock, SIOCSIFFLAGS, &ifr); + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIFFLAGS); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_get_ip + * + * Description: + * Gets IP address of the given network interface. + * + ****************************************************************************/ + +int wapi_get_ip(int sock, FAR const char *ifname, FAR struct in_addr *addr) +{ + return wapi_get_addr(sock, ifname, SIOCGIFADDR, addr); +} + +/**************************************************************************** + * Name: wapi_set_ip + * + * Description: + * Sets IP adress of the given network interface. + * + ****************************************************************************/ + +int wapi_set_ip(int sock, FAR const char *ifname, + FAR const struct in_addr *addr) +{ + return wapi_set_addr(sock, ifname, SIOCSIFADDR, addr); +} + +/**************************************************************************** + * Name: wapi_set_netmask + * + * Description: + * Sets netmask of the given network interface. + * + ****************************************************************************/ + +int wapi_get_netmask(int sock, FAR const char *ifname, + FAR struct in_addr *addr) +{ + return wapi_get_addr(sock, ifname, SIOCGIFNETMASK, addr); +} + +/**************************************************************************** + * Name: wapi_set_netmask + * + * Description: + * Sets netmask of the given network interface. + * + ****************************************************************************/ + +int wapi_set_netmask(int sock, FAR const char *ifname, + FAR const struct in_addr *addr) +{ + return wapi_set_addr(sock, ifname, SIOCSIFNETMASK, addr); +} + +/**************************************************************************** + * Name: wapi_get_routes + * + * Description: + * Parses routing table rows from WAPI_PROC_NET_ROUTE. + * + * Input Parameters: + * list - Pushes collected wapi_route_info_t into this list. + * + ****************************************************************************/ + +int wapi_get_routes(FAR wapi_list_t *list) +{ + FAR FILE *fp; + int ret; + size_t bufsiz = WAPI_PROC_LINE_SIZE * sizeof(char); + char buf[WAPI_PROC_LINE_SIZE]; + + WAPI_VALIDATE_PTR(list); + + /* Open file for reading. */ + + fp = fopen(WAPI_PROC_NET_ROUTE, "r"); + if (!fp) + { + WAPI_STRERROR("fopen(\"%s\", \"r\")", WAPI_PROC_NET_ROUTE); + return -1; + } + + /* Skip header line. */ + + if (!fgets(buf, bufsiz, fp)) + { + WAPI_ERROR("Invalid \"%s\" content!\n", WAPI_PROC_NET_ROUTE); + return -1; + } + + /* Read lines. */ + + ret = 0; + while (fgets(buf, bufsiz, fp)) + { + wapi_route_info_t *ri; + char ifname[WAPI_PROC_LINE_SIZE]; + int refcnt, use, metric, mtu, window, irtt; + unsigned int dest, gw, flags, netmask; + + /* Allocate route row buffer. */ + + ri = malloc(sizeof(wapi_route_info_t)); + if (!ri) + { + WAPI_STRERROR("malloc()"); + ret = -1; + break; + } + + /* Read and tokenize fields. */ + + sscanf(buf, "%s\t" /* ifname */ + "%x\t" /* dest */ + "%x\t" /* gw */ + "%x\t" /* flags */ + "%d\t" /* refcnt */ + "%d\t" /* use */ + "%d\t" /* metric */ + "%x\t" /* mask */ + "%d\t" /* mtu */ + "%d\t" /* window */ + "%d\t", /* irtt */ + ifname, &dest, &gw, &flags, &refcnt, &use, &metric, &netmask, &mtu, + &window, &irtt); + + /* Allocate "ifname". */ + + ri->ifname = malloc((strlen(ifname) + 1) * sizeof(char)); + if (!ri->ifname) + { + WAPI_STRERROR("malloc()"); + free(ri); + ret = -1; + break; + } + + /* Copy fields. */ + + sprintf(ri->ifname, "%s", ifname); + ri->dest.s_addr = dest; + ri->gw.s_addr = gw; + ri->flags = flags; + ri->refcnt = refcnt; + ri->use = use; + ri->metric = metric; + ri->netmask.s_addr = netmask; + ri->mtu = mtu; + ri->window = window; + ri->irtt = irtt; + + /* Push parsed node to the list. */ + + ri->next = list->head.route; + list->head.route = ri; + } + + /* Close file. */ + + fclose(fp); + return 0; +} + +/**************************************************************************** + * Name: wapi_add_route_gw + * + * Description: + * Adds gateway for the given target network. + * + ****************************************************************************/ + +int wapi_add_route_gw(int sock, wapi_route_target_t targettype, + FAR const struct in_addr *target, + FAR const struct in_addr *netmask, + FAR const struct in_addr *gw) +{ + return wapi_act_route_gw(sock, SIOCADDRT, targettype, target, netmask, gw); +} + +/**************************************************************************** + * Name: wapi_del_route_gw + * + * Description: + * Deletes gateway for the given target network. + * + ****************************************************************************/ + +int wapi_del_route_gw(int sock, wapi_route_target_t targettype, + FAR const struct in_addr *target, + FAR const struct in_addr *netmask, + FAR const struct in_addr *gw) +{ + return wapi_act_route_gw(sock, SIOCDELRT, targettype, target, netmask, gw); +} diff --git a/wireless/wapi/src/util.c b/wireless/wapi/src/util.c new file mode 100644 index 000000000..4f8729721 --- /dev/null +++ b/wireless/wapi/src/util.c @@ -0,0 +1,235 @@ +/**************************************************************************** + * apps/wireless/wapi/src/util.c + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "include/wireless/wapi.h" +#include "util.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define WAPI_IOCTL_COMMAND_NAMEBUFSIZ 128 /* Is fairly enough to print an + * integer. */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +static char g_ioctl_command_namebuf[WAPI_IOCTL_COMMAND_NAMEBUFSIZ]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wapi_make_socket + * + * Description: + * Creates an AF_INET socket to be used in ioctl() calls. + * + * Returned Value: + * Non-negative on success. + * + ****************************************************************************/ + +int wapi_make_socket(void) +{ + return socket(AF_INET, SOCK_DGRAM, 0); +} + +/**************************************************************************** + * Name: wapi_get_ifnames + * + * Description: + * Parses WAPI_PROC_NET_WIRELESS. + * + * Returned Value: + * list Pushes collected wapi_string_t into this list. + * + ****************************************************************************/ + +int wapi_get_ifnames(FAR wapi_list_t *list) +{ + FILE *fp; + int ret; + size_t tmpsize = WAPI_PROC_LINE_SIZE * sizeof(char); + char tmp[WAPI_PROC_LINE_SIZE]; + + WAPI_VALIDATE_PTR(list); + + /* Open file for reading. */ + + fp = fopen(WAPI_PROC_NET_WIRELESS, "r"); + if (!fp) + { + WAPI_STRERROR("fopen(\"%s\", \"r\")", WAPI_PROC_NET_WIRELESS); + return -1; + } + + /* Skip first two lines. */ + + if (!fgets(tmp, tmpsize, fp) || !fgets(tmp, tmpsize, fp)) + { + WAPI_ERROR("Invalid \"%s\" content!\n", WAPI_PROC_NET_WIRELESS); + return -1; + } + + /* Iterate over available lines. */ + + ret = 0; + while (fgets(tmp, tmpsize, fp)) + { + char *beg; + char *end; + wapi_string_t *string; + + /* Locate the interface name region. */ + + for (beg = tmp; *beg && isspace(*beg); beg++); + for (end = beg; *end && *end != ':'; end++); + + /* Allocate both wapi_string_t and char vector. */ + + string = malloc(sizeof(wapi_string_t)); + if (string) + { + string->data = malloc(end - beg + sizeof(char)); + } + + if (!string || !string->data) + { + WAPI_STRERROR("malloc()"); + ret = -1; + break; + } + + /* Copy region into the buffer. */ + + snprintf(string->data, (end - beg + sizeof(char)), "%s", beg); + + /* Push string into the list. */ + + string->next = list->head.string; + list->head.string = string; + } + + fclose(fp); + return ret; +} + +/**************************************************************************** + * Name: wapi_get_ifnames + * + * Description: + * Return name string for IOCTL command + * + * Returned Value: + * Name string for IOCTL command + * + ****************************************************************************/ + +FAR const char *wapi_ioctl_command_name(int cmd) +{ + switch (cmd) + { + case SIOCADDRT: + return "SIOCADDRT"; + + case SIOCDELRT: + return "SIOCDELRT"; + + case SIOCGIFADDR: + return "SIOCGIFADDR"; + + case SIOCGIWAP: + return "SIOCGIWAP"; + + case SIOCGIWESSID: + return "SIOCGIWESSID"; + + case SIOCGIWFREQ: + return "SIOCGIWFREQ"; + + case SIOCGIWMODE: + return "SIOCGIWMODE"; + + case SIOCGIWRANGE: + return "SIOCGIWRANGE"; + + case SIOCGIWRATE: + return "SIOCGIWRATE"; + + case SIOCGIWSCAN: + return "SIOCGIWSCAN"; + + case SIOCGIWTXPOW: + return "SIOCGIWTXPOW"; + + case SIOCSIFADDR: + return "SIOCSIFADDR"; + + case SIOCSIWAP: + return "SIOCSIWAP"; + + case SIOCSIWESSID: + return "SIOCSIWESSID"; + + case SIOCSIWFREQ: + return "SIOCSIWFREQ"; + + case SIOCSIWMODE: + return "SIOCSIWMODE"; + + case SIOCSIWRATE: + return "SIOCSIWRATE"; + + case SIOCSIWSCAN: + return "SIOCSIWSCAN"; + + case SIOCSIWTXPOW: + return "SIOCSIWTXPOW"; + + default: + snprintf(g_ioctl_command_namebuf, WAPI_IOCTL_COMMAND_NAMEBUFSIZ, + "0x%x", cmd); + return g_ioctl_command_namebuf; + } +} diff --git a/wireless/wapi/src/util.h b/wireless/wapi/src/util.h new file mode 100644 index 000000000..4982e3155 --- /dev/null +++ b/wireless/wapi/src/util.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * apps/wireless/wapi/src/util.h + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_WIRELESS_WAPI_SRC_UTIL_H +#define __APPS_WIRELESS_WAPI_SRC_UTIL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define WAPI_IOCTL_STRERROR(cmd) \ + fprintf( \ + stderr, "%s:%d:%s():ioctl(%s): %s\n", \ + __FILE__, __LINE__, __func__, \ + wapi_ioctl_command_name(cmd), strerror(errno)) + +#define WAPI_STRERROR(fmt, ...) \ + fprintf( \ + stderr, "%s:%d:%s():" fmt ": %s\n", \ + __FILE__, __LINE__, __func__, \ + ## __VA_ARGS__, strerror(errno)) + +#define WAPI_ERROR(fmt, ...) \ + fprintf( \ + stderr, "%s:%d:%s(): " fmt , \ + __FILE__, __LINE__, __func__, ## __VA_ARGS__) + +#define WAPI_VALIDATE_PTR(ptr) \ + if (!ptr) \ + { \ + WAPI_ERROR("Null pointer: %s.\n", #ptr); \ + return -1; \ + } + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +FAR const char *wapi_ioctl_command_name(int cmd); + +#endif /* __APPS_WIRELESS_WAPI_SRC_UTIL_H */ diff --git a/wireless/wapi/src/wireless.c b/wireless/wapi/src/wireless.c new file mode 100644 index 000000000..d2a137c67 --- /dev/null +++ b/wireless/wapi/src/wireless.c @@ -0,0 +1,1498 @@ +/**************************************************************************** + * apps/wireless/wapi/src/wireless.c + * + * Copyright (c) 2010, Volkan YAZICI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "include/wireless/wapi.h" +#include "util.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef LIBNL1 +# define nl_sock nl_handle +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Events & Streams */ + +struct iw_event_stream_s +{ + FAR char *end; /* End of the stream */ + FAR char *current; /* Current event in stream of events */ + FAR char *value; /* Current value in event */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Frequency */ + +FAR const char *g_wapi_freq_flags[] = +{ + "WAPI_FREQ_AUTO", + "WAPI_FREQ_FIXED" +}; + +/* ESSID */ + +FAR const char *g_wapi_essid_flags[] = +{ + "WAPI_ESSID_ON", + "WAPI_ESSID_OFF" +}; + +/* Operating Mode */ + +FAR const char *g_wapi_modes[] = +{ + "WAPI_MODE_AUTO", + "WAPI_MODE_ADHOC", + "WAPI_MODE_MANAGED", + "WAPI_MODE_MASTER", + "WAPI_MODE_REPEAT", + "WAPI_MODE_SECOND", + "WAPI_MODE_MONITOR" +}; + +/* Bit Rate */ + +FAR const char *g_wapi_bitrate_flags[] = +{ + "WAPI_BITRATE_AUTO", + "WAPI_BITRATE_FIXED" +}; + +/* Transmit Power */ + +FAR const char *g_wapi_txpower_flags[] = +{ + "WAPI_TXPOWER_DBM", + "WAPI_TXPOWER_MWATT", + "WAPI_TXPOWER_RELATIVE" +}; + +/* Add/Delete */ + +typedef enum +{ + WAPI_NL80211_CMD_IFADD, + WAPI_NL80211_CMD_IFDEL +} wapi_nl80211_cmd_t; + +typedef struct wapi_nl80211_ifadd_ctx_t +{ + FAR const char *name; + wapi_mode_t mode; +} wapi_nl80211_ifadd_ctx_t; + +typedef struct wapi_nl80211_ifdel_ctx_t +{ +} wapi_nl80211_ifdel_ctx_t; + +typedef struct wapi_nl80211_ctx_t +{ + FAR const char *ifname; + wapi_nl80211_cmd_t cmd; + union + { + wapi_nl80211_ifadd_ctx_t ifadd; + wapi_nl80211_ifdel_ctx_t ifdel; + } u; +} wapi_nl80211_ctx_t; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wapi_freq2float + * + * Description: + * Converts internal representation of frequencies to a floating point. + * + ****************************************************************************/ + +static inline double wapi_freq2float(const struct iw_freq *freq) +{ + return ((double)freq->m) * pow(10, freq->e); +} + +/**************************************************************************** + * Name: wapi_float2freq + * + * Description: + * Converts a floating point the our internal representation of frequencies. + * + ****************************************************************************/ + +static inline void wapi_float2freq(double floatfreq, struct iw_freq *freq) +{ + freq->e = (short)floor(log10(floatfreq)); + if (freq->e > 8) + { + freq->m = ((long)(floor(floatfreq / pow(10, freq->e - 6)))) * 100; + freq->e -= 8; + } + else + { + freq->m = (long)floatfreq; + freq->e = 0; + } +} + +/**************************************************************************** + * Name: wapi_parse_mode + * + * Description: + * + ****************************************************************************/ + +static int wapi_parse_mode(int iw_mode, FAR wapi_mode_t *wapi_mode) +{ + switch (iw_mode) + { + case WAPI_MODE_AUTO: + case WAPI_MODE_ADHOC: + case WAPI_MODE_MANAGED: + case WAPI_MODE_MASTER: + case WAPI_MODE_REPEAT: + case WAPI_MODE_SECOND: + case WAPI_MODE_MONITOR: + *wapi_mode = iw_mode; + return 0; + + default: + WAPI_ERROR("Unknown mode: %d.\n", iw_mode); + return -1; + } +} + +/**************************************************************************** + * Name: wapi_make_ether + * + * Description: + * + ****************************************************************************/ + +static int wapi_make_ether(FAR struct ether_addr *addr, int byte) +{ + WAPI_VALIDATE_PTR(addr); + memset(addr, byte, sizeof(struct ether_addr)); + return 0; +} + +/**************************************************************************** + * Name: iw_event_stream_init + * + * Description: + * + ****************************************************************************/ + +static void iw_event_stream_init(FAR struct iw_event_stream_s *stream, + FAR char *data, size_t len) +{ + memset(stream, 0, sizeof(struct iw_event_stream_s)); + stream->current = data; + stream->end = &data[len]; +} + +/**************************************************************************** + * Name: iw_event_stream_pop + * + * Description: + * + ****************************************************************************/ + +static int iw_event_stream_pop(FAR struct iw_event_stream_s *stream, + FAR struct iw_event *iwe, int we_version) +{ + return iw_extract_event_stream((struct stream_descr *)stream, iwe, + we_version); +} + +/**************************************************************************** + * Name: wapi_scan_event + * + * Description: + * + ****************************************************************************/ + +static int wapi_scan_event(FAR struct iw_event *event, FAR wapi_list_t *list) +{ + FAR wapi_scan_info_t *info; + + /* Get current "wapi_info_t". */ + + info = list->head.scan; + + /* Decode the event. */ + + switch (event->cmd) + { + case SIOCGIWAP: + { + wapi_scan_info_t *temp; + + /* Allocate a new cell. */ + + temp = malloc(sizeof(wapi_scan_info_t)); + if (!temp) + { + WAPI_STRERROR("malloc()"); + return -1; + } + + /* Reset it. */ + + bzero(temp, sizeof(wapi_scan_info_t)); + + /* Save cell identifier. */ + + memcpy(&temp->ap, &event->u.ap_addr.sa_data, sizeof(struct ether_addr)); + + /* Push it to the head of the list. */ + + temp->next = info; + list->head.scan = temp; + + break; + } + + case SIOCGIWFREQ: + info->has_freq = 1; + info->freq = wapi_freq2float(&(event->u.freq)); + break; + + case SIOCGIWMODE: + { + int ret = wapi_parse_mode(event->u.mode, &info->mode); + if (ret >= 0) + { + info->has_mode = 1; + break; + } + else + { + return ret; + } + } + + case SIOCGIWESSID: + info->has_essid = 1; + info->essid_flag = (event->u.data.flags) ? WAPI_ESSID_ON : WAPI_ESSID_OFF; + memset(info->essid, 0, (WAPI_ESSID_MAX_SIZE + 1)); + if ((event->u.essid.pointer) && (event->u.essid.length)) + { + memcpy(info->essid, event->u.essid.pointer, event->u.essid.length); + } + break; + + case SIOCGIWRATE: + /* Scan may return a list of bitrates. As we have space for only a single + * bitrate, we only keep the largest one. + */ + + if (!info->has_bitrate || event->u.bitrate.value > info->bitrate) + { + info->has_bitrate = 1; + info->bitrate = event->u.bitrate.value; + } + break; + } + + return 0; +} + +/**************************************************************************** + * Name: nl_socket_alloc + * + * Description: + * + ****************************************************************************/ + +#ifdef LIBNL1 +static FAR struct nl_handle *nl_socket_alloc(void) +{ + return nl_handle_alloc(); +} +#endif /* LIBNL1 */ + +/**************************************************************************** + * Name: nl_socket_free + * + * Description: + * + ****************************************************************************/ + +#ifdef LIBNL1 +static void nl_socket_free(FAR struct nl_sock *h) +{ + nl_handle_destroy(h); +} +#endif /* LIBNL1 */ + +/**************************************************************************** + * Name: wapi_mode_to_iftype + * + * Description: + * + ****************************************************************************/ + +static int wapi_mode_to_iftype(wapi_mode_t mode, FAR enum nl80211_iftype *type) +{ + int ret = 0; + + switch (mode) + { + case WAPI_MODE_AUTO: + *type = NL80211_IFTYPE_UNSPECIFIED; + break; + + case WAPI_MODE_ADHOC: + *type = NL80211_IFTYPE_ADHOC; + break; + + case WAPI_MODE_MANAGED: + *type = NL80211_IFTYPE_STATION; + break; + + case WAPI_MODE_MASTER: + *type = NL80211_IFTYPE_AP; + break; + + case WAPI_MODE_MONITOR: + *type = NL80211_IFTYPE_MONITOR; + break; + + default: + WAPI_ERROR("No supported nl80211 iftype for mode: %s!\n", + g_wapi_modes[mode]); + ret = -1; + } + + return ret; +} + +/**************************************************************************** + * Name: nl80211_err_handler + * + * Description: + * + ****************************************************************************/ + +static int nl80211_err_handler(FAR struct sockaddr_nl *nla, + FAR struct nlmsgerr *err, FAR void *arg) +{ + int *ret = arg; + *ret = err->error; + return NL_STOP; +} + +/**************************************************************************** + * Name: nl80211_fin_handler + * + * Description: + * + ****************************************************************************/ + +static int nl80211_fin_handler(FAR struct nl_msg *msg, FAR void *arg) +{ + int *ret = arg; + *ret = 0; + return NL_SKIP; +} + +/**************************************************************************** + * Name: nl80211_ack_handler + * + * Description: + * + ****************************************************************************/ + +static int nl80211_ack_handler(FAR struct nl_msg *msg, FAR void *arg) +{ + int *ret = arg; + *ret = 0; + return NL_STOP; +} + +/**************************************************************************** + * Name: nl80211_cmd_handler + * + * Description: + * + ****************************************************************************/ + +static int nl80211_cmd_handler(FAR const wapi_nl80211_ctx_t *ctx) +{ + FAR struct nl_sock *sock; + FAR struct nl_msg *msg; + FAR struct nl_cb *cb; + int family; + int ifidx; + int ret; + + /* Allocate netlink socket. */ + + sock = nl_socket_alloc(); + if (!sock) + { + WAPI_ERROR("Failed to allocate netlink socket!\n"); + return -ENOMEM; + } + + /* Reset "msg" and "cb". */ + + msg = NULL; + cb = NULL; + + /* Connect to generic netlink socket on kernel side. */ + + if (genl_connect(sock)) + { + WAPI_ERROR("Failed to connect to generic netlink!\n"); + ret = -ENOLINK; + goto exit; + } + + /* Ask kernel to resolve family name to family id. */ + + ret = family = genl_ctrl_resolve(sock, "nl80211"); + if (ret < 0) + { + WAPI_ERROR("genl_ctrl_resolve() failed!\n"); + goto exit; + } + + /* Map given network interface name (ifname) to its corresponding index. */ + + ifidx = if_nametoindex(ctx->ifname); + if (!ifidx) + { + WAPI_STRERROR("if_nametoindex(\"%s\")", ctx->ifname); + ret = -errno; + goto exit; + } + + /* Construct a generic netlink by allocating a new message. */ + + msg = nlmsg_alloc(); + if (!msg) + { + WAPI_ERROR("nlmsg_alloc() failed!\n"); + ret = -ENOMEM; + goto exit; + } + + /* Append the requested command to the message. */ + + switch (ctx->cmd) + { + case WAPI_NL80211_CMD_IFADD: + { + enum nl80211_iftype iftype; + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, 0, + NL80211_CMD_NEW_INTERFACE, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx); + + /* Get NL80211_IFTYPE_* for the given WAPI mode. */ + + ret = wapi_mode_to_iftype(ctx->u.ifadd.mode, &iftype); + if (ret < 0) + { + goto exit; + } + + NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ctx->u.ifadd.name); + NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype); + break; + } + + case WAPI_NL80211_CMD_IFDEL: + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, 0, + NL80211_CMD_DEL_INTERFACE, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx); + break; + } + + /* Finalize (send) the message. */ + + ret = nl_send_auto_complete(sock, msg); + if (ret < 0) + { + WAPI_ERROR("nl_send_auto_complete() failed!\n"); + goto exit; + } + + /* Allocate a new callback handle. */ + + cb = nl_cb_alloc(NL_CB_VERBOSE); + if (!cb) + { + WAPI_ERROR("nl_cb_alloc() failed\n"); + ret = -1; + goto exit; + } + + /* Configure callback handlers. */ + + nl_cb_err(cb, NL_CB_CUSTOM, nl80211_err_handler, &ret); + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_fin_handler, &ret); + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl80211_ack_handler, &ret); + + /* Consume netlink replies. */ + + for (ret = 1; ret > 0;) + { + nl_recvmsgs(sock, cb); + } + + if (ret) + { + WAPI_ERROR("nl_recvmsgs() failed!\n"); + } + +exit: + /* Release resources and exit with "ret". */ + + nl_socket_free(sock); + if (msg) + { + nlmsg_free(msg); + } + + if (cb) + { + free(cb); + } + + return ret; + +nla_put_failure: + WAPI_ERROR("nla_put_failure!\n"); + ret = -1; + goto exit; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wapi_get_we_version + * + * Description: + * Gets kernel WE (Wireless Extensions) version. + * + * Input Parameters: + * we_version Set to we_version_compiled of range information. + * + * Returned Value: + * Zero on success. + * + ****************************************************************************/ + +int wapi_get_we_version(int sock, const char *ifname, FAR int *we_version) +{ + struct iwreq wrq; + char buf[sizeof(struct iw_range) * 2]; + int ret; + + WAPI_VALIDATE_PTR(we_version); + + /* Prepare request. */ + + bzero(buf, sizeof(buf)); + wrq.u.data.pointer = buf; + wrq.u.data.length = sizeof(buf); + wrq.u.data.flags = 0; + + /* Get WE version. */ + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWRANGE, &wrq)) >= 0) + { + struct iw_range *range = (struct iw_range *)buf; + *we_version = (int)range->we_version_compiled; + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIWRANGE); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_get_freq + * + * Description: + * Gets the operating frequency of the device. + * + ****************************************************************************/ + +int wapi_get_freq(int sock, FAR const char *ifname, FAR double *freq, + FAR wapi_freq_flag_t *flag); +{ + struct iwreq wrq; + int ret; + + WAPI_VALIDATE_PTR(freq); + WAPI_VALIDATE_PTR(flag); + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWFREQ, &wrq)) >= 0) + { + /* Set flag. */ + + if (IW_FREQ_AUTO == (wrq.u.freq.flags & IW_FREQ_AUTO)) + { + *flag = WAPI_FREQ_AUTO; + } + else if (IW_FREQ_FIXED == (wrq.u.freq.flags & IW_FREQ_FIXED)) + { + *flag = WAPI_FREQ_FIXED; + } + else + { + WAPI_ERROR("Unknown flag: %d.\n", wrq.u.freq.flags); + return -1; + } + + /* Set freq. */ + + *freq = wapi_freq2float(&(wrq.u.freq)); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_set_freq + * + * Description: + * Sets the operating frequency of the device. + * + ****************************************************************************/ + +int wapi_set_freq(int sock, FARconst char *ifname, double freq, + wapi_freq_flag_t flag); +{ + struct iwreq wrq; + int ret; + + /* Set freq. */ + + wapi_float2freq(freq, &(wrq.u.freq)); + + /* Set flag. */ + + switch (flag) + { + case WAPI_FREQ_AUTO: + wrq.u.freq.flags = IW_FREQ_AUTO; + break; + + case WAPI_FREQ_FIXED: + wrq.u.freq.flags = IW_FREQ_FIXED; + break; + } + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + ret = ioctl(sock, SIOCSIWFREQ, &wrq); + if (ret < 0) + { + WAPI_IOCTL_STRERROR(SIOCSIWFREQ); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_freq2chan + * + * Description: + * Finds corresponding channel for the supplied freq. + * + * Returned Value: + * 0, on success; -2, if not found; otherwise, ioctl() return value. + * + ****************************************************************************/ + +int wapi_freq2chan(int sock, FAR const char *ifname, double freq, + FAR int *chan) +{ + struct iwreq wrq; + char buf[sizeof(struct iw_range) * 2]; + int ret; + + WAPI_VALIDATE_PTR(chan); + + /* Prepare request. */ + + bzero(buf, sizeof(buf)); + wrq.u.data.pointer = buf; + wrq.u.data.length = sizeof(buf); + wrq.u.data.flags = 0; + + /* Get range. */ + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWRANGE, &wrq)) >= 0) + { + struct iw_range *range = (struct iw_range *)buf; + int k; + + /* Compare the frequencies as double to ignore differences in encoding. + * Slower, but safer... + */ + + for (k = 0; k < range->num_frequency; k++) + { + if (freq == wapi_freq2float(&(range->freq[k]))) + { + *chan = range->freq[k].i; + return 0; + } + } + + /* Oops! Nothing found. */ + + ret = -2; + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIWRANGE); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_chan2freq + * + * Description: + * Finds corresponding frequency for the supplied chan. + * + * Returned Value: + * 0, on success; -2, if not found; otherwise, ioctl() return value. + * + ****************************************************************************/ + +int wapi_chan2freq(int sock, FAR const char *ifname, int chan, + FAR double *freq) +{ + struct iwreq wrq; + char buf[sizeof(struct iw_range) * 2]; + int ret; + + WAPI_VALIDATE_PTR(freq); + + /* Prepare request. */ + + bzero(buf, sizeof(buf)); + wrq.u.data.pointer = buf; + wrq.u.data.length = sizeof(buf); + wrq.u.data.flags = 0; + + /* Get range. */ + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWRANGE, &wrq)) >= 0) + { + struct iw_range *range = (struct iw_range *)buf; + int k; + + for (k = 0; k < range->num_frequency; k++) + { + if (chan == range->freq[k].i) + { + *freq = wapi_freq2float(&(range->freq[k])); + return 0; + } + } + + /* Oops! Nothing found. */ + + ret = -2; + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIWRANGE); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_get_essid + * + * Description: + * Gets ESSID of the device. + * + * Input Parameters: + * essid - Used to store the ESSID of the device. Buffer must have + * enough space to store WAPI_ESSID_MAX_SIZE+1 characters. + * + ****************************************************************************/ + +int wapi_get_essid(int sock, FAR const char *ifname, FAR char *essid, + FAR wapi_essid_flag_t *flag) +{ + struct iwreq wrq; + int ret; + + WAPI_VALIDATE_PTR(essid); + WAPI_VALIDATE_PTR(flag); + + wrq.u.essid.pointer = essid; + wrq.u.essid.length = WAPI_ESSID_MAX_SIZE + 1; + wrq.u.essid.flags = 0; + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + ret = ioctl(sock, SIOCGIWESSID, &wrq); + if (ret < 0) + { + WAPI_IOCTL_STRERROR(SIOCGIWESSID); + } + else + { + *flag = (wrq.u.essid.flags) ? WAPI_ESSID_ON : WAPI_ESSID_OFF; + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_set_essid + * + * Description: + * Sets ESSID of the device. + * + * essid At most WAPI_ESSID_MAX_SIZE characters are read. + * + ****************************************************************************/ + +int wapi_set_essid(int sock, FAR const char *ifname, FAR const char *essid, + wapi_essid_flag_t flag) +{ + char buf[WAPI_ESSID_MAX_SIZE + 1]; + struct iwreq wrq; + int ret; + + /* Prepare request. */ + + wrq.u.essid.pointer = buf; + wrq.u.essid.length = + snprintf(buf, ((WAPI_ESSID_MAX_SIZE + 1) * sizeof(char)), "%s", essid); + wrq.u.essid.flags = (flag == WAPI_ESSID_ON); + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + ret = ioctl(sock, SIOCSIWESSID, &wrq); + if (ret < 0) + { + WAPI_IOCTL_STRERROR(SIOCSIWESSID); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_get_mode + * + * Description: + * Gets the operating mode of the device. + * + ****************************************************************************/ + +int wapi_get_mode(int sock, FAR const char *ifname, FAR wapi_mode_t *mode) +{ + struct iwreq wrq; + int ret; + + WAPI_VALIDATE_PTR(mode); + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWMODE, &wrq)) >= 0) + { + ret = wapi_parse_mode(wrq.u.mode, mode); + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIWMODE); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_set_mode + * + * Description: + * Sets the operating mode of the device. + * + ****************************************************************************/ + +int wapi_set_mode(int sock, FAR const char *ifname, wapi_mode_t mode) +{ + struct iwreq wrq; + int ret; + + wrq.u.mode = mode; + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + ret = ioctl(sock, SIOCSIWMODE, &wrq); + if (ret < 0) + { + WAPI_IOCTL_STRERROR(SIOCSIWMODE); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_make_broad_ether + * + * Description: + * Creates an ethernet broadcast address. + * + ****************************************************************************/ + +int wapi_make_broad_ether(FAR struct ether_addr *sa) +{ + return wapi_make_ether(sa, 0xFF); +} + +/**************************************************************************** + * Name: wapi_make_null_ether + * + * Description: + * Creates an ethernet NULL address. + * + ****************************************************************************/ + +int wapi_make_null_ether(FAR struct ether_addr *sa) +{ + return wapi_make_ether(sa, 0x00); +} + +/**************************************************************************** + * Name: wapi_get_ap + * + * Description: + * Gets access point address of the device. + * + * Input Parameters: + * ap - Set the to MAC address of the device. (For "any", a broadcast + * ethernet address; for "off", a null ethernet address is used.) + * + ****************************************************************************/ + +int wapi_get_ap(int sock, FAR const char *ifname, FAR struct ether_addr *ap) +{ + struct iwreq wrq; + int ret; + + WAPI_VALIDATE_PTR(ap); + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWAP, &wrq)) >= 0) + { + memcpy(ap, wrq.u.ap_addr.sa_data, sizeof(struct ether_addr)); + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIWAP); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_set_ap + * + * Description: + * Sets access point address of the device. + * + ****************************************************************************/ + +int wapi_set_ap(int sock, FAR const char *ifname, + FAR const struct ether_addr *ap) +{ + struct iwreq wrq; + int ret; + + WAPI_VALIDATE_PTR(ap); + + wrq.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(wrq.u.ap_addr.sa_data, ap, sizeof(struct ether_addr)); + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + + ret = ioctl(sock, SIOCSIWAP, &wrq); + if (ret < 0) + { + WAPI_IOCTL_STRERROR(SIOCSIWAP); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_get_bitrate + * + * Description: + * Gets bitrate of the device. + * + ****************************************************************************/ + +int wapi_get_bitrate(int sock, FAR const char *ifname, + FAR int *bitrate, FAR wapi_bitrate_flag_t *flag) +{ + struct iwreq wrq; + int ret; + + WAPI_VALIDATE_PTR(bitrate); + WAPI_VALIDATE_PTR(flag); + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWRATE, &wrq)) >= 0) + { + /* Check if enabled. */ + if (wrq.u.bitrate.disabled) + { + WAPI_ERROR("Bitrate is disabled.\n"); + return -1; + } + + /* Get bitrate. */ + *bitrate = wrq.u.bitrate.value; + *flag = wrq.u.bitrate.fixed ? WAPI_BITRATE_FIXED : WAPI_BITRATE_AUTO; + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIWRATE); + + return ret; +} + +/**************************************************************************** + * Name: wapi_set_bitrate + * + * Description: + * Sets bitrate of the device. + * + ****************************************************************************/ + +int wapi_set_bitrate(int sock, FAR const char *ifname, int bitrate, + wapi_bitrate_flag_t flag) +{ + struct iwreq wrq; + int ret; + + wrq.u.bitrate.value = bitrate; + wrq.u.bitrate.fixed = (flag == WAPI_BITRATE_FIXED); + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + ret = ioctl(sock, SIOCSIWRATE, &wrq); + if (ret < 0) + { + WAPI_IOCTL_STRERROR(SIOCSIWRATE); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_dbm2mwatt + * + * Description: + * Converts a value in dBm to a value in milliWatt. + * + ****************************************************************************/ + +int wapi_dbm2mwatt(int dbm) +{ + return floor(pow(10, (((double)dbm) / 10))); +} + +/**************************************************************************** + * Name: wapi_mwatt2dbm + * + * Description: + * Converts a value in milliWatt to a value in dBm. + * + ****************************************************************************/ + +int wapi_mwatt2dbm(int mwatt) +{ + return ceil(10 * log10(mwatt)); +} + +/**************************************************************************** + * Name: wapi_get_txpower + * + * Description: + * Gets txpower of the device. + * + ****************************************************************************/ + +int wapi_get_txpower(int sock, FAR const char *ifname, FAR int *power, + FAR wapi_txpower_flag_t *flag) +{ + struct iwreq wrq; + int ret; + + WAPI_VALIDATE_PTR(power); + WAPI_VALIDATE_PTR(flag); + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWTXPOW, &wrq)) >= 0) + { + /* Check if enabled. */ + + if (wrq.u.txpower.disabled) + { + return -1; + } + + /* Get flag. */ + + if (IW_TXPOW_DBM == (wrq.u.txpower.flags & IW_TXPOW_DBM)) + { + *flag = WAPI_TXPOWER_DBM; + } + else if (IW_TXPOW_MWATT == (wrq.u.txpower.flags & IW_TXPOW_MWATT)) + { + *flag = WAPI_TXPOWER_MWATT; + } + else if (IW_TXPOW_RELATIVE == (wrq.u.txpower.flags & IW_TXPOW_RELATIVE)) + { + *flag = WAPI_TXPOWER_RELATIVE; + } + else + { + WAPI_ERROR("Unknown flag: %d.\n", wrq.u.txpower.flags); + return -1; + } + + /* Get power. */ + + *power = wrq.u.txpower.value; + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIWTXPOW); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_set_txpower + * + * Description: + * Sets txpower of the device. + * + ****************************************************************************/ + +int wapi_set_txpower(int sock, FAR const char *ifname, int power, + wapi_txpower_flag_t flag); +{ + struct iwreq wrq; + int ret; + + /* Construct the request. */ + + wrq.u.txpower.value = power; + switch (flag) + { + case WAPI_TXPOWER_DBM: + wrq.u.txpower.flags = IW_TXPOW_DBM; + break; + + case WAPI_TXPOWER_MWATT: + wrq.u.txpower.flags = IW_TXPOW_MWATT; + break; + + case WAPI_TXPOWER_RELATIVE: + wrq.u.txpower.flags = IW_TXPOW_RELATIVE; + break; + } + + /* Issue the set command. */ + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + ret = ioctl(sock, SIOCSIWTXPOW, &wrq); + if (ret < 0) + { + WAPI_IOCTL_STRERROR(SIOCSIWTXPOW); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_scan_init + * + * Description: + * Starts a scan on the given interface. Root privileges are required to start a + * scan. + * + ****************************************************************************/ + +int wapi_scan_init(int sock, const char *ifname) +{ + struct iwreq wrq; + int ret; + + wrq.u.data.pointer = NULL; + wrq.u.data.flags = 0; + wrq.u.data.length = 0; + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + ret = ioctl(sock, SIOCSIWSCAN, &wrq); + if (ret < 0) + { + WAPI_IOCTL_STRERROR(SIOCSIWSCAN); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_scan_stat + * + * Description: + * Checks the status of the scan process. + * + * Returned Value: + * Zero, if data is ready; 1, if data is not ready; negative on failure. + * + ****************************************************************************/ + +int wapi_scan_stat(int sock, FAR const char *ifname) +{ + struct iwreq wrq; + int ret; + char buf; + + wrq.u.data.pointer = &buf; + wrq.u.data.flags = 0; + wrq.u.data.length = 0; + + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWSCAN, &wrq)) < 0) + { + if (errno == E2BIG) + { + /* Data is ready, but not enough space, which is expected. */ + + return 0; + } + else if (errno == EAGAIN) + { + /* Data is not ready. */ + + return 1; + } + + printf("err[%d]: %s\n", errno, strerror(errno)); + } + else + { + WAPI_IOCTL_STRERROR(SIOCGIWSCAN); + } + + return ret; +} + +/**************************************************************************** + * Name: wapi_scan_coll + * + * Description: + * Collects the results of a scan process. + * + * Input Parameters: + * aps - Pushes collected wapi_scan_info_t into this list. + * + ****************************************************************************/ + +int wapi_scan_coll(int sock, FAR const char *ifname, FAR wapi_list_t *aps) +{ + FAR char *buf; + int buflen; + struct iwreq wrq; + int we_version; + int ret; + + WAPI_VALIDATE_PTR(aps); + + /* Get WE version. (Required for event extraction via libiw.) */ + + if ((ret = wapi_get_we_version(sock, ifname, &we_version)) < 0) + { + return ret; + } + + buflen = IW_SCAN_MAX_DATA; + buf = malloc(buflen * sizeof(char)); + if (!buf) + { + WAPI_STRERROR("malloc()"); + return -1; + } + +alloc: + /* Collect results. */ + + wrq.u.data.pointer = buf; + wrq.u.data.length = buflen; + wrq.u.data.flags = 0; + strncpy(wrq.ifr_name, ifname, IFNAMSIZ); + if ((ret = ioctl(sock, SIOCGIWSCAN, &wrq)) < 0 && errno == E2BIG) + { + char *tmp; + + buflen *= 2; + tmp = realloc(buf, buflen); + if (!tmp) + { + WAPI_STRERROR("realloc()"); + free(buf); + return -1; + } + + buf = tmp; + goto alloc; + } + + /* There is still something wrong. It's either EAGAIN or some other ioctl() + * failure. We don't bother, let the user deal with it. + */ + + if (ret < 0) + { + WAPI_IOCTL_STRERROR(SIOCGIWSCAN); + free(buf); + return ret; + } + + /* We have the results, process them. */ + + if (wrq.u.data.length) + { + struct iw_event iwe; + struct iw_event_stream_s stream; + + iw_event_stream_init(&stream, buf, wrq.u.data.length); + do + { + if ((ret = iw_event_stream_pop(&stream, &iwe, we_version)) >= 0) + { + int eventret = wapi_scan_event(&iwe, aps); + if (eventret < 0) + { + ret = eventret; + } + } + else + { + WAPI_ERROR("iw_event_stream_pop() failed!\n"); + } + } + while (ret > 0); + } + + /* Free request buffer. */ + + free(buf); + return ret; +} + +/**************************************************************************** + * Name: wapi_if_add + * + * Description: + * Creates a virtual interface with name for interface ifname. + * + ****************************************************************************/ + +int wapi_if_add(int sock, FAR const char *ifname, FAR const char *name, + wapi_mode_t mode) +{ + wapi_nl80211_ctx_t ctx; + + ctx.ifname = ifname; + ctx.cmd = WAPI_NL80211_CMD_IFADD; + ctx.u.ifadd.name = name; + ctx.u.ifadd.mode = mode; + + return nl80211_cmd_handler(&ctx); +} + +/**************************************************************************** + * Name: wapi_if_del + * + * Description: + * Deletes a virtual interface with name. + * + ****************************************************************************/ + +int wapi_if_del(int sock, FAR const char *ifname) +{ + wapi_nl80211_ctx_t ctx; + + ctx.ifname = ifname; + ctx.cmd = WAPI_NL80211_CMD_IFDEL; + + return nl80211_cmd_handler(&ctx); +}