diff --git a/examples/README.txt b/examples/README.txt index 98535fc79..9da9b0f64 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -87,8 +87,8 @@ examples/alarm CONFIG_EXAMPLES_ALARM_DEVPATH - RTC device path (/dev/rtc0) ONFIG_EXAMPLES_ALARM_SIGNO - Alarm signal -examples/ap102 -^^^^^^^^^^^^^^ +examples/apa102 +^^^^^^^^^^^^^^^ Rainbow example for APA102 LED Strip. diff --git a/include/netutils/netlib.h b/include/netutils/netlib.h index 558b9c4c5..51d3a94d2 100644 --- a/include/netutils/netlib.h +++ b/include/netutils/netlib.h @@ -152,6 +152,7 @@ int netlib_set_dripv4addr(FAR const char *ifname, FAR const struct in_addr *addr int netlib_get_dripv4addr(FAR const char *ifname, FAR struct in_addr *addr); int netlib_set_ipv4netmask(FAR const char *ifname, FAR const struct in_addr *addr); int netlib_get_ipv4netmask(FAR const char *ifname, FAR struct in_addr *addr); +int netlib_ipv4adaptor(in_addr_t destipaddr, FAR in_addr_t *srcipaddr); #endif #ifdef CONFIG_NET_IPv6 @@ -162,6 +163,8 @@ int netlib_set_ipv6netmask(FAR const char *ifname, FAR const struct in6_addr *ad uint8_t netlib_ipv6netmask2prefix(FAR const uint16_t *mask); void netlib_prefix2ipv6netmask(uint8_t preflen, FAR struct in6_addr *netmask); +int netlib_ipv6adaptor(FAR const struct in6_addr *destipaddr, + FAR struct in6_addr *srcipaddr); #endif #ifdef CONFIG_NETDEV_WIRELESS_IOCTL diff --git a/netutils/netlib/Makefile b/netutils/netlib/Makefile index 962e76e19..6cf90a49d 100644 --- a/netutils/netlib/Makefile +++ b/netutils/netlib/Makefile @@ -49,6 +49,7 @@ ifeq ($(CONFIG_NET_IPv4),y) CSRCS += netlib_setipv4addr.c netlib_getipv4addr.c CSRCS += netlib_setdripv4addr.c netlib_setipv4netmask.c CSRCS += netlib_getdripv4addr.c netlib_getipv4netmask.c +CSRCS += netlib_ipv4adaptor.c ifeq ($(CONFIG_NET_ARP),y) CSRCS += netlib_getarp.c netlib_setarp.c netlib_delarp.c endif @@ -61,6 +62,7 @@ ifeq ($(CONFIG_NET_IPv6),y) CSRCS += netlib_setipv6addr.c netlib_getipv6addr.c CSRCS += netlib_setdripv6addr.c netlib_setipv6netmask.c CSRCS += netlib_prefix2ipv6netmask.c netlib_ipv6netmask2prefix.c +CSRCS += netlib_ipv6adaptor.c ifeq ($(CONFIG_NET_ICMPv6_AUTOCONF),y) CSRCS += netlib_autoconfig.c endif diff --git a/netutils/netlib/netlib_ipv4adaptor.c b/netutils/netlib/netlib_ipv4adaptor.c new file mode 100644 index 000000000..40cf6c367 --- /dev/null +++ b/netutils/netlib/netlib_ipv4adaptor.c @@ -0,0 +1,170 @@ +/**************************************************************************** + * netutils/netlib/netlib_ipv4adaptor.c + * + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "netutils/netlib.h" + +#ifdef CONFIG_NET_IPv4 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netlib_ipv4adaptor + ****************************************************************************/ + +int netlib_ipv4adaptor(in_addr_t destipaddr, FAR in_addr_t *srcipaddr) +{ + FAR struct ifreq *ifr; + struct ifconf ifc; + int nintf; + int ret; + int sd; + int i; + + /* REVISIT: Should check the routing table to see if there is a route + * for the destipaddr before finding the device that provides the sub-net. + */ + + /* Find the size of the buffer we need to hold the interface descriptions */ + + ifc.ifc_req = NULL; + ifc.ifc_len = 0; + + sd = socket(AF_INET, NETLIB_SOCK_IOCTL, 0); + if (sd < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: socket() failed: %d\n", ret); + return ret; + } + + ret = ioctl(sd, SIOCGIFCONF, (unsigned long)((uintptr_t)&ifc)); + if (ret < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: ioctl(SIOCGIFCONF) failed: %d\n", ret); + goto errout_with_sd; + } + + /* Allocate the buffer to hold the interface descriptions */ + + ifr = (FAR struct ifreq *)malloc(ifc.ifc_len); + if (ifr == NULL) + { + fprintf(stderr, "ERROR: Failed to allocate IFC buffer\n"); + ret = -ENOMEM; + goto errout_with_sd; + } + + /* Get the interface descriptions */ + + ifc.ifc_req = ifr; + + ret = ioctl(sd, SIOCGIFCONF, (unsigned long)((uintptr_t)&ifc)); + if (ret < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: ioctl(SIOCGIFCONF) failed: %d\n", ret); + goto errout_with_ifr; + } + + /* Find an interface that supports the subnet needed by the provided + * IPv4 address. + */ + + nintf = ifc.ifc_len / sizeof(struct ifreq); + ret = -EHOSTUNREACH; + + for (i = 0; i < nintf; i++) + { + FAR struct ifreq *req = &ifr[i]; + FAR struct sockaddr_in *addr = + (FAR struct sockaddr_in *)&req->ifr_addr; + struct ifreq maskreq; + FAR struct sockaddr_in *netmask; + + /* Get the network mask */ + + strncpy(maskreq.ifr_name, ifr->ifr_name, IFNAMSIZ); + + ret = ioctl(sd, SIOCGIFNETMASK, (unsigned long)((uintptr_t)&maskreq)); + if (ret < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: ioctl(SIOCGIFNETMASK) failed: %d\n", + ret); + goto errout_with_ifr; + } + + netmask = (FAR struct sockaddr_in *)&maskreq.ifr_addr; + + /* Does this device provide the sub-net? */ + + if (net_ipv4addr_maskcmp(addr->sin_addr.s_addr, destipaddr, + netmask->sin_addr.s_addr)) + { + /* Yes.. return the IP address assigned to this adaptor */ + + *srcipaddr = addr->sin_addr.s_addr; + ret = OK; + break; + } + } + +errout_with_ifr: + free(ifr); + +errout_with_sd: + close(sd); + return ret; +} + +#endif /* CONFIG_NET_IPv4 */ diff --git a/netutils/netlib/netlib_ipv6adaptor.c b/netutils/netlib/netlib_ipv6adaptor.c new file mode 100644 index 000000000..5c558c809 --- /dev/null +++ b/netutils/netlib/netlib_ipv6adaptor.c @@ -0,0 +1,174 @@ +/**************************************************************************** + * netutils/netlib/netlib_ipv6adaptor.c + * + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "netutils/netlib.h" + +#ifdef CONFIG_NET_IPv6 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netlib_ipv6adaptor + ****************************************************************************/ + +int netlib_ipv6adaptor(FAR const struct in6_addr *destipaddr, + FAR struct in6_addr *srcipaddr) +{ + FAR struct lifreq *lifr; + struct lifconf lifc; + int nintf; + int ret; + int sd; + int i; + + /* REVISIT: Should check the routing table to see if there is a route + * for the destipaddr before finding the device that provides the sub-net. + */ + + /* Find the size of the buffer we need to hold the interface descriptions */ + + lifc.lifc_req = NULL; + lifc.lifc_len = 0; + + sd = socket(AF_INET6, NETLIB_SOCK_IOCTL, 0); + if (sd < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: socket() failed: %d\n", ret); + return ret; + } + + ret = ioctl(sd, SIOCGLIFCONF, (unsigned long)((uintptr_t)&lifc)); + if (ret < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: ioctl(SIOCGLIFCONF) failed: %d\n", ret); + goto errout_with_sd; + } + + /* Allocate the buffer to hold the interface descriptions */ + + lifr = (FAR struct lifreq *)malloc(lifc.lifc_len); + if (lifr == NULL) + { + fprintf(stderr, "ERROR: Failed to allocate LIFC buffer\n"); + ret = -ENOMEM; + goto errout_with_sd; + } + + /* Get the interface descriptions */ + + lifc.lifc_req = lifr; + + ret = ioctl(sd, SIOCGLIFCONF, (unsigned long)((uintptr_t)&lifc)); + if (ret < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: ioctl(SIOCGLIFCONF) failed: %d\n", ret); + goto errout_with_ifr; + } + + /* Find an interface that supports the subnet needed by the provided + * IPv6 address. + */ + + nintf = lifc.lifc_len / sizeof(struct lifreq); + ret = -EHOSTUNREACH; + + for (i = 0; i < nintf; i++) + { + FAR struct lifreq *req = &lifr[i]; + FAR struct sockaddr_in6 *addr = + (FAR struct sockaddr_in6 *)&req->lifr_addr; + struct lifreq maskreq; + FAR struct sockaddr_in6 *netmask; + int status; + + /* Get the network mask */ + + strncpy(maskreq.lifr_name, lifr->lifr_name, IFNAMSIZ); + + status = ioctl(sd, SIOCGLIFNETMASK, (unsigned long)((uintptr_t)&maskreq)); + if (status < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: ioctl(SIOCGLIFNETMASK) failed: %d\n", + ret); + goto errout_with_ifr; + } + + netmask = (FAR struct sockaddr_in6 *)&maskreq.lifr_addr; + + /* Does this device provide the sub-net? */ + + if (net_ipv6addr_maskcmp(addr->sin6_addr.s6_addr16, + destipaddr->s6_addr16, + netmask->sin6_addr.s6_addr16)) + { + /* Yes.. return the IP address assigned to this adaptor */ + + net_ipv6addr_copy(srcipaddr->s6_addr16, + addr->sin6_addr.s6_addr16); + ret = OK; + break; + } + } + +errout_with_ifr: + free(lifr); + +errout_with_sd: + close(sd); + return ret; +} + +#endif /* CONFIG_NET_IPv6 */