diff --git a/include/netutils/netlib.h b/include/netutils/netlib.h index ffd45b442..bcdba7938 100644 --- a/include/netutils/netlib.h +++ b/include/netutils/netlib.h @@ -124,6 +124,9 @@ int netlib_get_ipv6addr(FAR const char *ifname, FAR struct in6_addr *addr); int netlib_set_ipv6addr(FAR const char *ifname, FAR const struct in6_addr *addr); int netlib_set_dripv6addr(FAR const char *ifname, FAR const struct in6_addr *addr); int netlib_set_ipv6netmask(FAR const char *ifname, FAR const struct in6_addr *addr); + +uint8_t netlib_ipv6netmask2prefix(FAR const uint16_t *mask); +void netlib_prefix2ipv6netmask(uint8_t preflen, FAR struct in6_addr *netmask); #endif /* ICMPv6 Autoconfiguration */ diff --git a/netutils/netlib/Makefile b/netutils/netlib/Makefile index da981fcc9..618c3dc5c 100644 --- a/netutils/netlib/Makefile +++ b/netutils/netlib/Makefile @@ -53,6 +53,7 @@ endif 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 ifeq ($(CONFIG_NET_ICMPv6_AUTOCONF),y) CSRCS += netlib_autoconfig.c endif diff --git a/netutils/netlib/netlib_ipv6netmask2prefix.c b/netutils/netlib/netlib_ipv6netmask2prefix.c new file mode 100644 index 000000000..9bc9e6423 --- /dev/null +++ b/netutils/netlib/netlib_ipv6netmask2prefix.c @@ -0,0 +1,188 @@ +/**************************************************************************** + * netutils/netlib/netlib_ipv6netmask2prefix.c + * + * Copyright (C) 2015 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#ifdef CONFIG_NET_IPv6 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_nibblemap[16] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0: No bits, 1-7: Should not happen */ + 1, 1, 1, 1, /* 8: 1 bit, 9-b: Should not happen */ + 2, 2, 3, 4 /* c: 2 bits, d: Should not happen, e: 3 bits, f: 4 bits */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netlib_msbits4 + * + * Description: + * Count the number of leading '1' bits in an 4-bit nibble + * + ****************************************************************************/ + +static inline uint8_t netlib_msbits4(uint8_t nibble) +{ + /* Return the number of leading zeroes: 0-4) */ + + return g_nibblemap[nibble]; +} + +/**************************************************************************** + * Name: netlib_msbits8 + * + * Description: + * Count the number of leading '1' bits in an 8-bit byte + * + ****************************************************************************/ + +static uint8_t netlib_msbits8(uint8_t byval) +{ + uint8_t ones; + + /* Check the MS nibble */ + + ones = netlib_msbits4(byval >> 4); + if (ones == 4) + { + /* All ones, try the LS nibble */ + + ones += netlib_msbits4(byval & 0x0f); + } + + /* Return the number of leading ones (0-8) */ + + return ones; +} + +/**************************************************************************** + * Name: netlib_msbits16 + * + * Description: + * Count the number of leading '1' bits in a 16-bit half-workd + * + ****************************************************************************/ + +static inline uint8_t netlib_msbits16(uint16_t hword) +{ + uint8_t ones; + + /* Look at the MS byte of the 16-bit value */ + + ones = netlib_msbits8((uint8_t)(hword >> 8)); + if (ones == 8) + { + /* All '1's, try the LS byte */ + + ones += netlib_msbits8((uint8_t)(hword & 0xff)); + } + + /* Return the number of leading ones (0-15) */ + + return ones; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netlib_ipv6netmask2prefix + * + * Description: + * Convert a 128-bit netmask to a prefix length. The Nuttx IPv6 + * networking uses 128-bit network masks internally. This function + * converts the IPv6 netmask to a prefix length. + * + * The prefix length is the number of MS '1' bits on in the netmask. + * This, of course, assumes that all MS bits are '1' and all LS bits are + * '0' with no intermixed 1's and 0's. This function searches from the MS + * bit until the first '0' is found (this does not necessary mean that + * there might not be additional '1' bits following the firs '0', but that + * will be a malformed netmask. + * + * Parameters: + * mask Points to an IPv6 netmask in the form of uint16_t[8] + * + * Return: + * The prefix length, range 0-128 on success; This function will not + * fail. + * + ****************************************************************************/ + +uint8_t netlib_ipv6netmask2prefix(FAR const uint16_t *mask) +{ + uint8_t preflen; + int i; + + /* Count the leading all '1' 16-bit groups */ + + for (i = 0, preflen = 0; i < 8 && mask[i] == 0xffff; i++, preflen += 16); + + /* Now i either, (1) indexes past the end of the mask, or (2) is the index + * to the first half-word that is not equal to 0xffff. + */ + + if (i < 8) + { + preflen += netlib_msbits16(ntohs(mask[i])); + } + + /* Return the prefix length */ + + return preflen; +} + +#endif /* CONFIG_NET_IPv6 */ diff --git a/netutils/netlib/netlib_prefix2ipv6netmask.c b/netutils/netlib/netlib_prefix2ipv6netmask.c new file mode 100644 index 000000000..c877ae0f5 --- /dev/null +++ b/netutils/netlib/netlib_prefix2ipv6netmask.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * apps/netutils/netlib/netlib_prefix2ipv6netmask.c + * + * Copyright (C) 2015 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#ifdef CONFIG_NET_IPv6 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: netlib_prefix2ipv6netmask + * + * Description: + * Convert a IPv6 prefix length to a network mask. The prefix length + * specifies the number of MS bits under mask (0-128) + * + * Parameters: + * preflen - Determines the width of the netmask (in bits). Range 0-128 + * netmask - The location to return the netmask. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void netlib_prefix2ipv6netmask(uint8_t preflen, FAR struct in6_addr *netmask) +{ + FAR uint16_t *mask = netmask->s6_addr16; + unsigned int bit; + unsigned int i; + + /* Set the network mask. preflen is the number of MS bits under the mask. + * + * Eg. preflen = 38 + * NETMASK: ffff ffff fc00 0000 0000 0000 0000 0000 + * bit: 1 1..1 + * 1 1..3 3..4 4..6 6..7 8..9 9..1 1..2 + * 0..5 6..1 2..7 8..3 4..9 0..5 6..1 2..7 + * preflen: 1 1..1 + * 1 1..3 3..4 4..6 6..8 8..9 9..1 1..2 + * 1..6 7..2 3..8 9..4 5..0 1..6 7..2 3..8 + */ + + for (i = 0; i < 7; i++) + { + /* bit = {0, 16, 32, 48, 64, 80, 96, 112} */ + + bit = i << 4; + + if (preflen > bit) + { + /* Eg. preflen = 38, bit = {0, 16, 32} */ + + if (preflen > (bit + 16)) + { + /* Eg. preflen = 38, bit = {0, 16} */ + + mask[i] = 0xffff; + } + else + { + /* Eg. preflen = 38, bit = {32} + * bit - preflen = 6 + * make = 0xffff << (16-6) + * = 0xfc00 + */ + + mask[i] = 0xffff << (16 - (bit - preflen)); + } + } + else + { + /* Eg. preflen=38, bit= {48, 64, 80, 112} */ + + mask[i] = 0x0000; + } + } +} + +#endif /* CONFIG_NET_IPv6 */ diff --git a/nshlib/nsh_netcmds.c b/nshlib/nsh_netcmds.c index 5d4195cb3..bda6012e8 100644 --- a/nshlib/nsh_netcmds.c +++ b/nshlib/nsh_netcmds.c @@ -469,6 +469,7 @@ static int ifconfig_callback(FAR struct net_driver_s *dev, void *arg) #endif #ifdef CONFIG_NET_IPv6 char addrstr[INET6_ADDRSTRLEN]; + uint8_t preflen; #endif uint8_t iff; const char *status; @@ -504,12 +505,18 @@ static int ifconfig_callback(FAR struct net_driver_s *dev, void *arg) #endif #ifdef CONFIG_NET_IPv4 + /* Show the IPv4 address */ + addr.s_addr = dev->d_ipaddr; nsh_output(vtbl, "\tinet addr:%s ", inet_ntoa(addr)); + /* Show the IPv4 default router address */ + addr.s_addr = dev->d_draddr; nsh_output(vtbl, "DRaddr:%s ", inet_ntoa(addr)); + /* Show the IPv4 network mask */ + addr.s_addr = dev->d_netmask; nsh_output(vtbl, "Mask:%s\n", inet_ntoa(addr)); @@ -520,22 +527,25 @@ static int ifconfig_callback(FAR struct net_driver_s *dev, void *arg) #endif #ifdef CONFIG_NET_IPv6 + /* Convert the 128 network mask to a human friendly prefix length */ + + preflen = netlib_ipv6netmask2prefix(dev->d_ipv6netmask); + + /* Show the assigned IPv6 address */ + if (inet_ntop(AF_INET6, dev->d_ipv6addr, addrstr, INET6_ADDRSTRLEN)) { - nsh_output(vtbl, "\tinet6 addr:%s\n", addrstr); + nsh_output(vtbl, "\tinet6 addr:%s/%d\n", addrstr, preflen); } + /* REVISIT: Show the IPv6 default router address */ + if (inet_ntop(AF_INET6, dev->d_ipv6draddr, addrstr, INET6_ADDRSTRLEN)) { - nsh_output(vtbl, "\tinet6 DRaddr:%s\n", addrstr); + nsh_output(vtbl, "\tinet6 DRaddr:%s/%d\n", addrstr, preflen); } - if (inet_ntop(AF_INET6, dev->d_ipv6netmask, addrstr, INET6_ADDRSTRLEN)) - { - nsh_output(vtbl, "\tinet6 Mask:%s\n", addrstr); - } - -#if defined(CONFIG_NSH_DHCPC) || defined(CONFIG_NSH_DNS) +#if defined(CONFIG_NSH_DHCPCv6) || defined(CONFIG_NSH_DNS) # warning Missing logic #endif #endif