From 9791e829f598f99187dbc13e558898e0eb0037d1 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 3 Feb 2015 15:40:56 -0600 Subject: [PATCH] ICMPv6: This completes coding of the ICMPv6 auto-configuration feature. It is not yet functional --- net/icmpv6/icmpv6.h | 11 ++- net/icmpv6/icmpv6_autoconfig.c | 48 +++++++++---- net/icmpv6/icmpv6_input.c | 2 +- net/netdev/netdev.h | 5 ++ net/netdev/netdev_ioctl.c | 120 ++++++++++++++++----------------- 5 files changed, 106 insertions(+), 80 deletions(-) diff --git a/net/icmpv6/icmpv6.h b/net/icmpv6/icmpv6.h index 2a9a094f29..67a6be6241 100644 --- a/net/icmpv6/icmpv6.h +++ b/net/icmpv6/icmpv6.h @@ -93,10 +93,6 @@ struct icmpv6_rnotify_s { #ifdef CONFIG_NET_MULTILINK FAR struct icmpv6_notify_s *rn_flink; /* Supports singly linked list */ -#endif - net_ipv6addr_t rn_prefix; /* Waited for router prefix */ - uint8_t rn_preflen; /* Prefix length (# valid leading bits) */ -#ifdef CONFIG_NET_MULTILINK char rn_ifname[IFNAMSIZ]; /* Device name */ #endif sem_t rn_sem; /* Will wake up the waiter */ @@ -431,6 +427,9 @@ int icmpv6_rwait(FAR struct icmpv6_rnotify_s *notify, * wake-up any threads that may be waiting for this particular Router * Advertisement. * + * NOTE: On success the network has the new address applied and is in + * the down state. + * * Assumptions: * This function is called from the MAC device driver indirectly through * icmpv6_icmpv6in() will execute with the network locked. @@ -438,8 +437,8 @@ int icmpv6_rwait(FAR struct icmpv6_rnotify_s *notify, ****************************************************************************/ #ifdef CONFIG_NET_ICMPv6_AUTOCONF -void icmpv6_rnotify(FAR struct net_driver_s *dev, const net_ipv6addr_t prefix, - unsigned int preflen); +void icmpv6_rnotify(FAR struct net_driver_s *dev, const net_ipv6addr_t draddr, + const net_ipv6addr_t prefix, unsigned int preflen); #else # define icmpv6_rnotify(d,p,l) #endif diff --git a/net/icmpv6/icmpv6_autoconfig.c b/net/icmpv6/icmpv6_autoconfig.c index ed7577d086..747651e3d8 100644 --- a/net/icmpv6/icmpv6_autoconfig.c +++ b/net/icmpv6/icmpv6_autoconfig.c @@ -52,6 +52,7 @@ #include #include "devif/devif.h" +#include "netdev/netdev.h" #include "icmpv6/icmpv6.h" /**************************************************************************** @@ -327,7 +328,7 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev) ndbg("ERROR: Only Ethernet is supported\n"); return -ENOSYS; -#else +#else /* CONFIG_NET_ETHERNET */ struct icmpv6_rnotify_s notify; net_ipv6addr_t lladdr; net_lock_t save; @@ -348,6 +349,11 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev) return -ENOSYS; } #endif + /* The interface should be in the down state */ + + save = net_lock(); + netdev_ifdown(dev); + net_unlock(save); /* IPv6 Stateless Autoconfiguration * Reference: http://www.tcpipguide.com/free/t_IPv6AutoconfiguratinoandRenumbering.htm @@ -378,6 +384,10 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev) memset(&lladdr[1], 0, 4* sizeof(uint16_t)); /* 64 more zeroes */ memcpy(&lladdr[5], dev->d_mac.ether_addr_octet, sizeof(struct ether_addr)); /* 48-bit Ethernet address */ + nvdbg("lladdr=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + lladdr[0], lladdr[1], lladdr[2], lladdr[3], + lladdr[4], lladdr[6], lladdr[6], lladdr[7]); + #ifdef CONFIG_NET_ICMPv6_NEIGHBOR /* 2. Link-Local Address Uniqueness Test: The node tests to ensure that * the address it generated isn't for some reason already in use on the @@ -410,6 +420,11 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev) net_ipv6addr_copy(dev->d_ipv6addr, lladdr); + /* Bring the interface up with the new, temporary IP address */ + + save = net_lock(); + netdev_ifup(dev); + /* 4. Router Contact: The node next attempts to contact a local router for * more information on continuing the configuration. This is done either * by listening for Router Advertisement messages sent periodically by @@ -417,7 +432,6 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev) * for information on what to do next. */ - save = net_lock(); for (retries = 0; retries < CONFIG_ICMPv6_AUTOCONF_MAXTRIES; retries++) { /* Set up the Router Advertisement BEFORE we send the Router @@ -447,17 +461,22 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev) break; } - nvdbg("Timed out... retrying\n"); + nvdbg("Timed out... retrying %d\n", retries + 1); } - net_unlock(save); - - /* Check for failures */ + /* Check for failures. Note: On successful return, the network will be + * in the down state, but not in the event of failures. + */ if (ret < 0) { ndbg("ERROR: Failed to get the router advertisement: %d (retries=%d)\n", ret, retries); + + /* Take the network down and return the failure */ + + netdev_ifdown(dev); + net_unlock(save); return ret; } @@ -466,20 +485,23 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev) * network "stateful" auto-configuration is in use, and tell it the * address of a DHCP server to use. Alternately, it will tell the host * how to determine its global Internet address. - */ -#warning Missing logic - - /* 6. Global Address Configuration: Assuming that stateless auto- + * + * 6. Global Address Configuration: Assuming that stateless auto- * configuration is in use on the network, the host will configure * itself with its globally-unique Internet address. This address is * generally formed from a network prefix provided to the host by the * router, combined with the device's identifier as generated in the * first step. */ -#warning Missing logic - return ret; -#endif + /* On success, the new address was already set (in icmpv_rnotify()). We + * need only to bring the network back to the up state and return success. + */ + + netdev_ifup(dev); + net_unlock(save); + return OK; +#endif /* CONFIG_NET_ETHERNET */ } #endif /* CONFIG_NET_ICMPv6_AUTOCONF */ diff --git a/net/icmpv6/icmpv6_input.c b/net/icmpv6/icmpv6_input.c index e3dc4d24b4..8aeaddfe80 100644 --- a/net/icmpv6/icmpv6_input.c +++ b/net/icmpv6/icmpv6_input.c @@ -321,7 +321,7 @@ void icmpv6_input(FAR struct net_driver_s *dev) { /* Yes.. Notify any waiting threads */ - icmpv6_rnotify(dev, opt->prefix, opt->preflen); + icmpv6_rnotify(dev, icmp->srcipaddr, opt->prefix, opt->preflen); goto icmpv_send_nothing; } diff --git a/net/netdev/netdev.h b/net/netdev/netdev.h index 28dbf83f1c..d0083723bb 100644 --- a/net/netdev/netdev.h +++ b/net/netdev/netdev.h @@ -85,6 +85,11 @@ void netdev_semtake(void); void netdev_semgive(void); #endif +/* netdev_ioctl.c ************************************************************/ + +void netdev_ifup(FAR struct net_driver_s *dev); +void netdev_ifdown(FAR struct net_driver_s *dev); + /* netdev_findbyname.c *******************************************************/ #if CONFIG_NSOCKET_DESCRIPTORS > 0 diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index 7a61897dc7..5eae3b8164 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -1,7 +1,7 @@ /**************************************************************************** * net/netdev/netdev_ioctl.c * - * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2012, 2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -315,58 +315,6 @@ static void ioctl_setipv6addr(FAR net_ipv6addr_t outaddr, } #endif -/**************************************************************************** - * Name: ioctl_ifup / ioctl_ifdown - * - * Description: - * Bring the interface up/down - * - ****************************************************************************/ - -static void ioctl_ifup(FAR struct net_driver_s *dev) -{ - /* Make sure that the device supports the d_ifup() method */ - - if (dev->d_ifup) - { - /* Is the interface already up? */ - - if ((dev->d_flags & IFF_UP) == 0) - { - /* No, bring the interface up now */ - - if (dev->d_ifup(dev) == OK) - { - /* Mark the interface as up */ - - dev->d_flags |= IFF_UP; - } - } - } -} - -static void ioctl_ifdown(FAR struct net_driver_s *dev) -{ - /* Make sure that the device supports the d_ifdown() method */ - - if (dev->d_ifdown) - { - /* Is the interface already down? */ - - if ((dev->d_flags & IFF_UP) != 0) - { - /* No, take the interface down now */ - - if (dev->d_ifdown(dev) == OK) - { - /* Mark the interface as down */ - - dev->d_flags &= ~IFF_UP; - } - } - } -} - /**************************************************************************** * Name: netdev_ifrdev * @@ -445,9 +393,9 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd, dev = netdev_ifrdev(req); if (dev) { - ioctl_ifdown(dev); + netdev_ifdown(dev); ioctl_setipv4addr(&dev->d_ipaddr, &req->ifr_addr); - ioctl_ifup(dev); + netdev_ifup(dev); ret = OK; } } @@ -538,9 +486,9 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd, { FAR struct lifreq *lreq = (FAR struct lifreq *)req; - ioctl_ifdown(dev); + netdev_ifdown(dev); ioctl_setipv6addr(dev->d_ipv6addr, &lreq->lifr_addr); - ioctl_ifup(dev); + netdev_ifup(dev); ret = OK; } } @@ -650,7 +598,7 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd, { /* Yes.. bring the interface up */ - ioctl_ifup(dev); + netdev_ifup(dev); } /* Is this a request to take the interface down? */ @@ -659,7 +607,7 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd, { /* Yes.. take the interface down */ - ioctl_ifdown(dev); + netdev_ifdown(dev); } } @@ -713,7 +661,7 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd, dev = netdev_ifrdev(req); if (dev) { - ioctl_ifdown(dev); + netdev_ifdown(dev); #ifdef CONFIG_NET_IPv4 dev->d_ipaddr = 0; #endif @@ -1051,4 +999,56 @@ errout: return ERROR; } +/**************************************************************************** + * Name: netdev_ifup / netdev_ifdown + * + * Description: + * Bring the interface up/down + * + ****************************************************************************/ + +void netdev_ifup(FAR struct net_driver_s *dev) +{ + /* Make sure that the device supports the d_ifup() method */ + + if (dev->d_ifup) + { + /* Is the interface already up? */ + + if ((dev->d_flags & IFF_UP) == 0) + { + /* No, bring the interface up now */ + + if (dev->d_ifup(dev) == OK) + { + /* Mark the interface as up */ + + dev->d_flags |= IFF_UP; + } + } + } +} + +void netdev_ifdown(FAR struct net_driver_s *dev) +{ + /* Make sure that the device supports the d_ifdown() method */ + + if (dev->d_ifdown) + { + /* Is the interface already down? */ + + if ((dev->d_flags & IFF_UP) != 0) + { + /* No, take the interface down now */ + + if (dev->d_ifdown(dev) == OK) + { + /* Mark the interface as down */ + + dev->d_flags &= ~IFF_UP; + } + } + } +} + #endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */