From 3e6705b526309dd9f9547f9481186419af867b23 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 6 Feb 2015 08:11:09 -0600 Subject: [PATCH] IPv6: Separate function that converts prefix lengths to a netmask --- include/nuttx/net/ip.h | 39 +++++++---- net/icmpv6/icmpv6_autoconfig.c | 4 ++ net/icmpv6/icmpv6_ping.c | 6 +- net/icmpv6/icmpv6_rnotify.c | 52 ++------------ net/utils/Make.defs | 2 +- net/utils/net_ipv6_maskcmp.c | 18 +---- net/utils/net_ipv6_pref2mask.c | 122 +++++++++++++++++++++++++++++++++ net/utils/utils.h | 22 +++++- 8 files changed, 184 insertions(+), 81 deletions(-) create mode 100644 net/utils/net_ipv6_pref2mask.c diff --git a/include/nuttx/net/ip.h b/include/nuttx/net/ip.h index fa2b57722aa..897eb80c739 100644 --- a/include/nuttx/net/ip.h +++ b/include/nuttx/net/ip.h @@ -365,28 +365,37 @@ EXTERN const net_ipv6addr_t g_ipv6_llnetmask; /* Netmask for local link addres net_ipv6addr_cmp(addr1, addr2) #endif -/* Compare two IP addresses under a netmask. The mask is used to mask - * out the bits that are to be compared: Buts within the mask much - * match exactly; bits outside if the mask are ignored. +/**************************************************************************** + * Function: net_ipv4addr_maskcmp and net_ipv6addr_maskcmp * - * Example: + * Description: + * Compare two IP addresses under a netmask. The mask is used to mask + * out the bits that are to be compared: Buts within the mask much + * match exactly; bits outside if the mask are ignored. * - * in_addr_t ipaddr1; - * in_addr_t ipaddr2; - * in_addr_t mask; + * IPv4 Example: * - * net_ipaddr(&mask, 255,255,255,0); - * net_ipaddr(&ipaddr1, 192,16,1,2); - * net_ipaddr(&ipaddr2, 192,16,1,3); - * if (net_ipv4addr_maskcmp(ipaddr1, ipaddr2, &mask)) + * net_ipv6addr_t ipaddr1; + * net_ipv6addr_t ipaddr2; + * net_ipv6addr_t mask; + * + * net_ipv6addr(&mask, 255,255,255,0); + * net_ipv6addr(&ipaddr1, 192,16,1,2); + * net_iv6paddr(&ipaddr2, 192,16,1,3); + * if (net_ipv6addr_maskcmp(ipaddr1, ipaddr2, &mask)) * { * printf("They are the same"); * } * - * addr1 The first IP address. - * addr2 The second IP address. - * mask The netmask. - */ + * Parameters: + * addr1 - The first IP address. + * addr2 - The second IP address. + * mask - The netmask. + * + * Returned Value: + * True if the address under the mask are equal + * + ****************************************************************************/ #ifdef CONFIG_NET_IPv4 # define net_ipv4addr_maskcmp(addr1, addr2, mask) \ diff --git a/net/icmpv6/icmpv6_autoconfig.c b/net/icmpv6/icmpv6_autoconfig.c index 4854c094bb9..085775d35fb 100644 --- a/net/icmpv6/icmpv6_autoconfig.c +++ b/net/icmpv6/icmpv6_autoconfig.c @@ -515,6 +515,10 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev) netdev_ifdown(dev); } + /* No off-link communications; No router address. */ + + net_ipv6addr_copy(dev->d_ipv6draddr, g_ipv6_allzeroaddr); + /* Set a netmask for the local link address */ net_ipv6addr_copy(dev->d_ipv6netmask, g_ipv6_llnetmask); diff --git a/net/icmpv6/icmpv6_ping.c b/net/icmpv6/icmpv6_ping.c index 397ac976ec3..8f8ec37c638 100644 --- a/net/icmpv6/icmpv6_ping.c +++ b/net/icmpv6/icmpv6_ping.c @@ -322,9 +322,9 @@ static uint16_t ping_interrupt(FAR struct net_driver_s *dev, FAR void *conn, if (!net_ipv6addr_maskcmp(pstate->png_addr, dev->d_ipv6addr, dev->d_ipv6netmask)) { - /* Destination address was not on the local network served by this - * device. If a timeout occurs, then the most likely reason is - * that the destination address is not reachable. + /* Destination address was not on the local network served by + * this device. If a timeout occurs, then the most likely + * reason is that the destination address is not reachable. */ nlldbg("Not reachable\n"); diff --git a/net/icmpv6/icmpv6_rnotify.c b/net/icmpv6/icmpv6_rnotify.c index d2249d95fc9..4515d1bd00a 100644 --- a/net/icmpv6/icmpv6_rnotify.c +++ b/net/icmpv6/icmpv6_rnotify.c @@ -51,6 +51,7 @@ #include #include "netdev/netdev.h" +#include "utils/utils.h" #include "icmpv6/icmpv6.h" #ifdef CONFIG_NET_ICMPv6_AUTOCONF @@ -89,64 +90,25 @@ static void icmpv6_setaddresses(FAR struct net_driver_s *dev, const net_ipv6addr_t prefix, unsigned int preflen) { - unsigned int bit; unsigned int i; /* Make sure that the network is down before changing any addresses */ netdev_ifdown(dev); - /* 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 - */ + /* Create an address mask from the prefix */ - for (i = 0; i < 7; i++) + if (preflen > 128) { - /* 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} */ - - dev->d_ipv6netmask[i] = 0xffff; - } - else - { - /* Eg. preflen = 38, bit = {32} - * bit - preflen = 6 - * make = 0xffff << (16-6) - * = 0xfc00 - */ - - dev->d_ipv6netmask[i] = 0xffff << (16 - (bit - preflen)); - } - } - else - { - /* Eg. preflen=38, bit= {48, 64, 80, 112} */ - - dev->d_ipv6netmask[i] = 0x0000; - } + preflen = 128; } + net_ipv6_pref2mask(preflen, dev->d_ipv6netmask); + nvdbg("preflen=%d netmask=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", preflen, dev->d_ipv6netmask[0], dev->d_ipv6netmask[1], dev->d_ipv6netmask[2], dev->d_ipv6netmask[3], dev->d_ipv6netmask[4], - dev->d_ipv6netmask[6], dev->d_ipv6netmask[6], dev->d_ipv6netmask[7]); + dev->d_ipv6netmask[5], dev->d_ipv6netmask[6], dev->d_ipv6netmask[7]); /* Copy prefix to the current IPv6 address, applying the mask */ diff --git a/net/utils/Make.defs b/net/utils/Make.defs index 39d2bbf218c..6be4afdfc1f 100644 --- a/net/utils/Make.defs +++ b/net/utils/Make.defs @@ -41,7 +41,7 @@ NET_CSRCS += net_chksum.c # IPv6 utilities ifeq ($(CONFIG_NET_IPv6),y) -NET_CSRCS += net_ipv6_maskcmp.c +NET_CSRCS += net_ipv6_maskcmp.c net_ipv6_pref2mask.c endif # Non-interrupt level support required? diff --git a/net/utils/net_ipv6_maskcmp.c b/net/utils/net_ipv6_maskcmp.c index 897f56dcf0f..95f55d0b5dc 100644 --- a/net/utils/net_ipv6_maskcmp.c +++ b/net/utils/net_ipv6_maskcmp.c @@ -51,27 +51,13 @@ ****************************************************************************/ /**************************************************************************** - * Function: net_timeval2dsec + * Function: net_ipv6addr_maskcmp * * Description: - * Compare two IP addresses under a netmask. The mask is used to mask + * Compare two IPv6 addresses under a netmask. The mask is used to mask * out the bits that are to be compared: Buts within the mask much * match exactly; bits outside if the mask are ignored. * - * Example: - * - * net_ipv6addr_t ipaddr1; - * net_ipv6addr_t ipaddr2; - * net_ipv6addr_t mask; - * - * net_ipv6addr(&mask, 255,255,255,0); - * net_ipv6addr(&ipaddr1, 192,16,1,2); - * net_iv6paddr(&ipaddr2, 192,16,1,3); - * if (net_ipv6addr_maskcmp(ipaddr1, ipaddr2, &mask)) - * { - * printf("They are the same"); - * } - * * Parameters: * addr1 - The first IP address. * addr2 - The second IP address. diff --git a/net/utils/net_ipv6_pref2mask.c b/net/utils/net_ipv6_pref2mask.c new file mode 100644 index 00000000000..6dcb63d8745 --- /dev/null +++ b/net/utils/net_ipv6_pref2mask.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * net/utils/net_ipv6_pref2mask.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 "utils/utils.h" + +#ifdef CONFIG_NET_IPv6 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: net_ipv6_pref2mask + * + * 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 + * mask - The location to return the netmask. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask) +{ + 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/net/utils/utils.h b/net/utils/utils.h index 20aeab7d713..3322f868bf4 100644 --- a/net/utils/utils.h +++ b/net/utils/utils.h @@ -41,6 +41,7 @@ ****************************************************************************/ #include +#include /**************************************************************************** * Pre-processor Definitions @@ -138,6 +139,26 @@ unsigned int net_dsec2tick(int dsec); unsigned int net_timeval2dsec(FAR struct timeval *tv); +/**************************************************************************** + * Function: net_ipv6_pref2mask + * + * 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 + * mask - The location to return the netmask. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask); +#endif + /**************************************************************************** * Name: tcp_chksum, tcp_ipv4_chksum, and tcp_ipv6_chksum * @@ -174,7 +195,6 @@ uint16_t tcp_chksum(FAR struct net_driver_s *dev); # define tcp_chksum(d) tcp_ipv6_chksum(d) #endif - /**************************************************************************** * Name: udp_ipv4_chksum *