diff --git a/examples/ostest/Makefile b/examples/ostest/Makefile index 5006623fd..f533364c6 100644 --- a/examples/ostest/Makefile +++ b/examples/ostest/Makefile @@ -72,19 +72,24 @@ endif ifneq ($(CONFIG_DISABLE_PTHREAD),y) CSRCS += cancel.c cond.c mutex.c sem.c semtimed.c barrier.c timedwait.c CSRCS += pthread_rwlock.c +CSRCS += pthread_rwlock_cancel.c + +ifeq ($(CONFIG_PTHREAD_CLEANUP),y) +CSRCS += pthread_cleanup.c +endif ifneq ($(CONFIG_PTHREAD_MUTEX_UNSAFE),y) CSRCS += robust.c endif -ifeq ($(CONFIG_FS_NAMED_SEMAPHORES),y) -CSRCS += nsem.c -endif - ifeq ($(CONFIG_PTHREAD_MUTEX_TYPES),y) CSRCS += rmutex.c endif +ifeq ($(CONFIG_FS_NAMED_SEMAPHORES),y) +CSRCS += nsem.c +endif + ifneq ($(CONFIG_RR_INTERVAL),0) CSRCS += roundrobin.c endif diff --git a/examples/ostest/ostest.h b/examples/ostest/ostest.h index 7cd9458ed..b271d3f79 100644 --- a/examples/ostest/ostest.h +++ b/examples/ostest/ostest.h @@ -145,7 +145,7 @@ int waitpid_test(void); void mutex_test(void); -/* rmutex.c ******************************************************************/ +/* rmutex.c *****************************************************************/ void recursive_mutex_test(void); @@ -187,7 +187,7 @@ void robust_test(void); void timedwait_test(void); -/* sigprocmask.c ****************************************************************/ +/* sigprocmask.c ************************************************************/ void sigprocmask_test(void); @@ -208,7 +208,7 @@ void sigev_thread_test(void); void rr_test(void); -/* sporadic.c *************************************************************/ +/* sporadic.c ***************************************************************/ void sporadic_test(void); @@ -216,10 +216,18 @@ void sporadic_test(void); void tls_test(void); -/* pthread_rwlock.c ****************************************************************/ +/* pthread_rwlock.c *********************************************************/ void pthread_rwlock_test(void); +/* pthread_rwlock_cancel.c **************************************************/ + +void pthread_rwlock_cancel_test(void); + +/* pthread_cleanup.c ********************************************************/ + +void pthread_cleanup_test(void); + /* barrier.c ****************************************************************/ void barrier_test(void); diff --git a/examples/ostest/ostest_main.c b/examples/ostest/ostest_main.c index d623d8482..4cfe61cd7 100644 --- a/examples/ostest/ostest_main.c +++ b/examples/ostest/ostest_main.c @@ -430,15 +430,25 @@ static int user_main(int argc, char *argv[]) printf("\nuser_main: pthread_rwlock test\n"); pthread_rwlock_test(); check_test_memory_usage(); -#endif /* !CONFIG_DISABLE_PTHREAD */ -#ifndef CONFIG_DISABLE_PTHREAD + printf("\nuser_main: pthread_rwlock_cancel test\n"); + pthread_rwlock_cancel_test(); + check_test_memory_usage(); + +#ifdef CONFIG_PTHREAD_CLEANUP + /* Verify pthread cancellation cleanup handlers */ + + printf("\nuser_main: pthread_cleanup test\n"); + pthread_cleanup_test(); + check_test_memory_usage(); +#endif + /* Verify pthreads and condition variable timed waits */ printf("\nuser_main: timed wait test\n"); timedwait_test(); check_test_memory_usage(); -#endif +#endif /* !CONFIG_DISABLE_PTHREAD */ #if !defined(CONFIG_DISABLE_MQUEUE) && !defined(CONFIG_DISABLE_PTHREAD) /* Verify pthreads and message queues */ diff --git a/examples/ostest/pthread_cleanup.c b/examples/ostest/pthread_cleanup.c new file mode 100644 index 000000000..54650823f --- /dev/null +++ b/examples/ostest/pthread_cleanup.c @@ -0,0 +1,164 @@ +/**************************************************************************** + * examples/ostest/pthread_cleanup.c + * + * Copyright (C) 2017 Haltian Ltd. All rights reserved. + * Author: Juha Niskanen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct sync_s +{ + pthread_cond_t cond; + pthread_mutex_t lock; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void cleanup(FAR void * data) +{ + FAR struct sync_s *sync = (FAR struct sync_s *) data; + int status; + + /* Note: pthread_cond_wait() will release the mutex while it waits on + * condition value. So a EPERM error is not a failure. + */ + + status = pthread_mutex_unlock(&sync->lock); + if (status == EPERM) + { + printf("pthread_cleanup: thread did not have mutex locked: %d\n", status); + } + else if (status != 0) + { + printf("pthread_cleanup: ERROR pthread_mutex_unlock in cleanup handler. " + "Status: %d\n", status); + } +} + +static void *cleanup_thread(FAR void * data) +{ + FAR struct sync_s *sync = (FAR struct sync_s *) data; + int status; + + status = pthread_mutex_lock(&sync->lock); + if (status != 0) + { + printf("pthread_cleanup: ERROR pthread_mutex_lock, status=%d\n", status); + return NULL; + } + + pthread_cleanup_push(&cleanup, sync); + + while(1) + { + status = pthread_cond_wait(&sync->cond, &sync->lock); + if (status != 0) + { + printf("pthread_cleanup: ERROR wait returned. Status: %d\n", status); + } + } + + pthread_cleanup_pop(1); + return NULL; +} + +static void test_cleanup(void) +{ + pthread_t thread1; + int status; + void *result; + struct sync_s sync = { + PTHREAD_COND_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER + }; + + status = pthread_create(&thread1, NULL, cleanup_thread, &sync); + if (status != 0) + { + printf("pthread_cleanup: ERROR pthread_create, status=%d\n", status); + return; + } + + usleep(500 * 1000); + + status = pthread_cancel(thread1); + if (status != 0) + { + printf("pthread_cleanup: ERROR pthread_cancel, status=%d\n", status); + } + + status = pthread_join(thread1, &result); + if (status != 0) + { + printf("pthread_cleanup: ERROR pthread_join, status=%d\n", status); + } + else if (result != PTHREAD_CANCELED) + { + printf("pthread_cleanup: ERROR pthread_join returned wrong result: %p\n", result); + } + + /* Do some operations on lock in order to check if it is in usable state. */ + + status = pthread_mutex_trylock(&sync.lock); + if (status != 0) + { + printf("pthread_cleanup: ERROR pthread_mutex_trylock, status=%d\n", status); + } + + status = pthread_mutex_unlock(&sync.lock); + if (status != 0) + { + printf("pthread_cleanup: ERROR pthread_mutex_unlock, status=%d\n", status); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void pthread_cleanup_test(void) +{ + printf("pthread_cleanup: Starting test\n"); + test_cleanup(); +} diff --git a/examples/ostest/pthread_rwlock.c b/examples/ostest/pthread_rwlock.c index a53242899..22ad446e8 100644 --- a/examples/ostest/pthread_rwlock.c +++ b/examples/ostest/pthread_rwlock.c @@ -1,5 +1,5 @@ /**************************************************************************** - * apps/examples/pthread_rwlock.c + * examples/ostest/pthread_rwlock.c * * Copyright (C) 2017 Mark Schulte. All rights reserved. * Author: Mark Schulte @@ -423,14 +423,15 @@ void pthread_rwlock_test(void) status = pthread_rwlock_trywrlock(&rw_lock); if (status != EBUSY) { - printf("pthread_rwlock: ""ERROR able to acquire to write locks\n"); + printf("pthread_rwlock: " + "ERROR able to acquire write lock when write lock already acquired\n"); } status = pthread_rwlock_tryrdlock(&rw_lock); if (status != EBUSY) { printf("pthread_rwlock: " - "ERROR able to acquire read lock when read lock already acquired\n"); + "ERROR able to acquire read lock when write lock already acquired\n"); } status = pthread_rwlock_unlock(&rw_lock); diff --git a/examples/ostest/pthread_rwlock_cancel.c b/examples/ostest/pthread_rwlock_cancel.c new file mode 100644 index 000000000..ced4075d9 --- /dev/null +++ b/examples/ostest/pthread_rwlock_cancel.c @@ -0,0 +1,252 @@ +/**************************************************************************** + * examples/ostest/pthread_rwlock_cancel.c + * + * Copyright (C) 2017 Haltian Ltd. All rights reserved. + * Author: Juha Niskanen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct sync_s +{ + pthread_rwlock_t *read_lock; + pthread_rwlock_t *write_lock; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void * timeout_thread1(FAR void * data) +{ + FAR struct sync_s * sync = (FAR struct sync_s *) data; + struct timespec time; + int status; + + while(1) + { + (void)clock_gettime(CLOCK_REALTIME, &time); + time.tv_sec += 1; + + status = pthread_rwlock_timedrdlock(sync->write_lock, &time); + if (status != ETIMEDOUT) + { + printf("pthread_rwlock_cancel: ERROR Acquired held write_lock. Status: %d\n", status); + } + } + + return NULL; +} + +static void * timeout_thread2(FAR void * data) +{ + FAR struct sync_s * sync = (FAR struct sync_s *) data; + struct timespec time; + int status; + + while (1) + { + (void)clock_gettime(CLOCK_REALTIME, &time); + time.tv_sec += 1; + + status = pthread_rwlock_timedrdlock(sync->read_lock, &time); + if (status != 0) + { + printf("pthread_rwlock_cancel: Failed to acquire read_lock. Status: %d\n", status); + } + + sched_yield(); /* Not a cancellation point. */ + + if (status == 0) + { + status = pthread_rwlock_unlock(sync->read_lock); + if (status != 0) + { + printf("pthread_rwlock_cancel: Failed to release read_lock. Status: %d\n", status); + } + } + + (void)clock_gettime(CLOCK_REALTIME, &time); + time.tv_sec += 1; + + status = pthread_rwlock_timedwrlock(sync->read_lock, &time); + if (status != ETIMEDOUT) + { + printf("pthread_rwlock_cancel: " + "ERROR Acquired held read_lock for writing. Status: %d\n", status); + } + } + + return NULL; +} + +static void test_timeout(void) +{ + pthread_rwlock_t read_lock; + pthread_rwlock_t write_lock; + struct sync_s sync; + pthread_t thread1, thread2; + int status, i; + + status = pthread_rwlock_init(&read_lock, NULL); + if (status != 0) + { + printf("pthread_rwlock_cancel: ERROR pthread_rwlock_init(read_lock), status=%d\n", + status); + } + + status = pthread_rwlock_init(&write_lock, NULL); + if (status != 0) + { + printf("pthread_rwlock_cancel: ERROR pthread_rwlock_init(write_lock), status=%d\n", + status); + } + + status = pthread_rwlock_rdlock(&read_lock); + if (status != 0) + { + printf("pthread_rwlock_cancel: ERROR pthread_rwlock_rdlock, status=%d\n", + status); + } + + status = pthread_rwlock_wrlock(&write_lock); + if (status != 0) + { + printf("pthread_rwlock_cancel: ERROR pthread_rwlock_wrlock, status=%d\n", + status); + } + + sync.read_lock = &read_lock; + sync.write_lock = &write_lock; + + status = pthread_create(&thread1, NULL, timeout_thread1, &sync); + if (status != 0) + { + printf("pthread_rwlock_cancel: ERROR pthread_create, status=%d\n", status); + } + + status = pthread_create(&thread2, NULL, timeout_thread2, &sync); + if (status != 0) + { + printf("pthread_rwlock_cancel: ERROR pthread_create, status=%d\n", status); + } + + for (i = 0; i < 10; i++) + { + usleep(300 * 1000); /* Give threads few seconds to run */ + } + + status = pthread_cancel(thread1); + if (status != 0) + { + printf("pthread_rwlock_cancel: ERROR pthread_cancel, status=%d\n", status); + } + + status = pthread_cancel(thread2); + if (status != 0) + { + printf("pthread_rwlock_cancel: ERROR pthread_cancel, status=%d\n", status); + } + + (void) pthread_join(thread1, NULL); + (void) pthread_join(thread2, NULL); + + /* Do some operations on locks in order to check if they are still in + * usable state after deferred cancellation. */ + +#ifdef CONFIG_PTHREAD_CLEANUP +#ifdef CONFIG_CANCELLATION_POINTS + status = pthread_rwlock_trywrlock(&write_lock); + if (status != EBUSY) + { + printf("pthread_rwlock_cancel: " + "ERROR able to acquire write lock when write lock already acquired, " + "status=%d\n", status); + } + + status = pthread_rwlock_tryrdlock(&write_lock); + if (status != EBUSY) + { + printf("pthread_rwlock_cancel: " + "ERROR able to acquire read lock when write lock already acquired, " + "status=%d\n", status); + } + + status = pthread_rwlock_unlock(&read_lock); + if (status != 0) + { + printf("pthread_rwlock_cancel: " + "ERROR pthread_rwlock_unlock, status=%d\n", status); + } + + status = pthread_rwlock_unlock(&write_lock); + if (status != 0) + { + printf("pthread_rwlock_cancel: " + "ERROR pthread_rwlock_unlock, status=%d\n", status); + } + + status = pthread_rwlock_rdlock(&read_lock); + if (status != 0) + { + printf("pthread_rwlock_cancel: " + "ERROR pthread_rwlock_rdlock, status=%d\n", status); + } + + status = pthread_rwlock_wrlock(&write_lock); + if (status != 0) + { + printf("pthread_rwlock_cancel: " + "ERROR pthread_rwlock_wrlock, status=%d\n", status); + } +#endif /* CONFIG_CANCELLATION_POINTS */ +#endif /* CONFIG_PTHREAD_CLEANUP */ +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void pthread_rwlock_cancel_test(void) +{ + printf("pthread_rwlock_cancel: Starting test\n"); + test_timeout(); +} diff --git a/include/wireless/wapi.h b/include/wireless/wapi.h new file mode 100644 index 000000000..d97bb58fc --- /dev/null +++ b/include/wireless/wapi.h @@ -0,0 +1,630 @@ +/**************************************************************************** + * 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. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ROUTE +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); +#endif + +/**************************************************************************** + * Name: wapi_del_route_gw + * + * Description: + * Deletes gateway for the given target network. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ROUTE +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); +#endif + +/**************************************************************************** + * 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, FAR const 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_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/nshlib/nsh_envcmds.c b/nshlib/nsh_envcmds.c index b323d9538..4d80e465c 100644 --- a/nshlib/nsh_envcmds.c +++ b/nshlib/nsh_envcmds.c @@ -316,15 +316,22 @@ int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { FAR char *value; int ret = OK; +#ifndef CONFIG_DISABLE_ENVIRON int ndx = 1; +#endif #ifndef CONFIG_NSH_DISABLESCRIPT FAR char *popt; const char opts[] = NSH_NP_SET_OPTIONS; int op; +#ifndef CONFIG_DISABLE_ENVIRON /* Support set [{+|-}{e|x|xe|ex}] [ ] */ if (argc == 2 || argc == 4) +#else + /* Support set [{+|-}{e|x|xe|ex}] */ + +#endif { if (strlen(argv[1]) < 2) { @@ -362,17 +369,20 @@ int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) } } +#ifndef CONFIG_DISABLE_ENVIRON if (ret == OK) { ndx = 2; } +#endif } } } -# ifndef CONFIG_DISABLE_ENVIRON + +#ifndef CONFIG_DISABLE_ENVIRON if (ret == OK && (argc == 3 || argc == 4)) -# endif #endif +#endif /* CONFIG_NSH_DISABLESCRIPT */ #ifndef CONFIG_DISABLE_ENVIRON { /* Trim whitespace from the value */ diff --git a/wireless/.gitignore b/wireless/.gitignore new file mode 100644 index 000000000..99f41601f --- /dev/null +++ b/wireless/.gitignore @@ -0,0 +1,2 @@ +/Kconfig + diff --git a/wireless/Make.defs b/wireless/Make.defs new file mode 100644 index 000000000..6f5bcf9f7 --- /dev/null +++ b/wireless/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# apps/wireless/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2017 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. 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. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +include $(wildcard wireless/*/Make.defs) diff --git a/wireless/Makefile b/wireless/Makefile new file mode 100644 index 000000000..363f15cd6 --- /dev/null +++ b/wireless/Makefile @@ -0,0 +1,38 @@ +############################################################################ +# apps/wireless/Makefile +# +# Copyright (C) 2017 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. 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. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +MENUDESC = "Wireless Libraries and NSH Add-Ons" + +include $(APPDIR)/Directory.mk 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/Kconfig b/wireless/wapi/Kconfig new file mode 100644 index 000000000..4e8b7edcc --- /dev/null +++ b/wireless/wapi/Kconfig @@ -0,0 +1,44 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menuconfig WIRELESS_WAPI + bool "IEEE802.11 Configuration Library" + default n + depends on NET && DRIVERS_WIRELESS && EXPERIMENTAL + ---help--- + Wapi is a tool by Volkan YAZICI that can + be used to manage 802.11 network. + +if WIRELESS_WAPI + +config WIRELESS_WAPI_CMDTOOL + bool "IEEE802.11 Command Line Tool" + default n + ---help--- + By default, Wapi is build as only a library. If this option is + selected than a simple command line tool that can be ran from NSH + will also be generated. + +config WIRELESS_WAPI_ENABLE_SET + bool "Enable Setting Options" + default n + +config WIRELESS_WAPI_PROGNAME + string "Program Name" + default "wapi" + depends on BUILD_KERNEL + ---help--- + This is the name of the program that will be use when the NSH ELF + program is installed. + +config WIRELESS_WAPI_STACKSIZE + int "Stack Size (bytes)" + default 2048 + +config WIRELESS_WAPI_PRIORITY + int "Command Priority" + default 100 + +endif 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/Make.defs b/wireless/wapi/Make.defs new file mode 100644 index 000000000..f8cf01b20 --- /dev/null +++ b/wireless/wapi/Make.defs @@ -0,0 +1,40 @@ +############################################################################ +# apps/wireless/wapi/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2017 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. 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. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_WIRELESS_WAPI),y) +CONFIGURED_APPS += wireless/wapi +endif + diff --git a/wireless/wapi/Makefile b/wireless/wapi/Makefile new file mode 100644 index 000000000..02297248f --- /dev/null +++ b/wireless/wapi/Makefile @@ -0,0 +1,149 @@ +############################################################################ +# apps/wireless/wapi/Makefile +# +# Copyright (C) 2017 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. 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. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +# TODO, this makefile should run make under the app dirs, instead of +# sourcing the Make.defs! + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# LM-75 Temperature Sensor Application + +CONFIG_WIRELESS_WAPI_PRIORITY ?= 100 +CONFIG_WIRELESS_WAPI_STACKSIZE ?= 2048 + +APPNAME = temp +PRIORITY = $(CONFIG_WIRELESS_WAPI_PRIORITY) +STACKSIZE = $(CONFIG_WIRELESS_WAPI_STACKSIZE) + +ASRCS = +CSRCS = +MAINSRC = + +VPATH = . + +include $(APPDIR)/wireless/wapi/src/Make.defs + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) +MAINOBJ = $(MAINSRC:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) $(MAINSRC) +OBJS = $(AOBJS) $(COBJS) + +ifneq ($(CONFIG_BUILD_KERNEL),y) + OBJS += $(MAINOBJ) +endif + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + BIN = ..\..\libapps$(LIBEXT) +else +ifeq ($(WINTOOL),y) + BIN = ..\\..\\libapps$(LIBEXT) +else + BIN = ../../libapps$(LIBEXT) +endif +endif + +ifeq ($(WINTOOL),y) + INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}" +else + INSTALL_DIR = $(BIN_DIR) +endif + +CONFIG_WAPI_PROGNAME ?= lm75$(EXEEXT) +PROGNAME = $(CONFIG_WAPI_PROGNAME) + +ROOTDEPPATH = --dep-path . + +# Common build + +all: .built +.PHONY: context depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + $(call ARCHIVE, $(BIN), $(OBJS)) + $(Q) touch .built + +ifeq ($(CONFIG_BUILD_KERNEL),y) +$(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJS) $(MAINOBJ) + @echo "LD: $(PROGNAME)" + $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS) + $(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME) + +install: $(BIN_DIR)$(DELIM)$(PROGNAME) + +else +install: + +endif + +# Register application + +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) +$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),lm75_main) + +context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat +else +context: +endif + +# Create dependencies + +.depend: Makefile $(SRCS) + $(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep + $(Q) touch $@ + +depend: .depend + +clean: + $(call DELFILE, .built) + $(call CLEAN) + +distclean: clean + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep +.PHONY: preconfig +preconfig: 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/src/Make.defs b/wireless/wapi/src/Make.defs new file mode 100644 index 000000000..95100bb1c --- /dev/null +++ b/wireless/wapi/src/Make.defs @@ -0,0 +1,49 @@ +############################################################################ +# apps/wireless/src/Make.defs +# +# Copyright (C) 2017 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. 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. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_WIRELESS_WAPI),y) + +CSRCS = network.c util.c wireless.c + +ifeq ($(CONFIG_WIRELESS_WAPI_CMDTOOL),y) +MAINSRC = wapi.c +endif + +DEPPATH += --dep-path src +VPATH += :src +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(APPDIR)/wireless/wapi/src} + +endif + diff --git a/wireless/wapi/src/network.c b/wireless/wapi/src/network.c new file mode 100644 index 000000000..170510ade --- /dev/null +++ b/wireless/wapi/src/network.c @@ -0,0 +1,434 @@ +/**************************************************************************** + * 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 + +#include "util.h" +#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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&ifr))) < 0) + { + WAPI_IOCTL_STRERROR(cmd); + } + + return ret; +} + +#ifdef CONFIG_NET_ROUTE +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, (unsigned long)((uintptr_t)&rt))) < 0) + { + WAPI_IOCTL_STRERROR(act); + } + + return ret; +} +#endif + +/**************************************************************************** + * 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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&ifr))) >= 0) + { + ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); + ret = ioctl(sock, SIOCSIFFLAGS, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&ifr))) >= 0) + { + ifr.ifr_flags &= ~IFF_UP; + ret = ioctl(sock, SIOCSIFFLAGS, (unsigned long)((uintptr_t)&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; + size_t bufsiz = WAPI_PROC_LINE_SIZE * sizeof(char); + char buf[WAPI_PROC_LINE_SIZE]; + int ret; + + 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 ret; +} + +/**************************************************************************** + * Name: wapi_add_route_gw + * + * Description: + * Adds gateway for the given target network. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ROUTE +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); +} +#endif + +/**************************************************************************** + * Name: wapi_del_route_gw + * + * Description: + * Deletes gateway for the given target network. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ROUTE +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); +} +#endif diff --git a/wireless/wapi/src/util.c b/wireless/wapi/src/util.c new file mode 100644 index 000000000..8b9379e46 --- /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 "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/wapi.c b/wireless/wapi/src/wapi.c new file mode 100644 index 000000000..c7a13ee3f --- /dev/null +++ b/wireless/wapi/src/wapi.c @@ -0,0 +1,410 @@ +/**************************************************************************** + * apps/wireless/wapi/src/wapi.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" + + +/* 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 CONFIG_WIRELESS_WAPI_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 CONFIG_WIRELESS_WAPI_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 CONFIG_WIRELESS_WAPI_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 CONFIG_WIRELESS_WAPI_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 CONFIG_WIRELESS_WAPI_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 CONFIG_WIRELESS_WAPI_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 CONFIG_WIRELESS_WAPI_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 CONFIG_WIRELESS_WAPI_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/wireless.c b/wireless/wapi/src/wireless.c new file mode 100644 index 000000000..8ee1bdc83 --- /dev/null +++ b/wireless/wapi/src/wireless.c @@ -0,0 +1,1152 @@ +/**************************************************************************** + * 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 "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" +}; + +/**************************************************************************** + * 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; +} + +/**************************************************************************** + * 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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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, (unsigned long)((uintptr_t)&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; +}