autoip.c

Go to the documentation of this file.
00001 /*##############################################################################
00002 
00003 nIP - nano IP stack
00004 
00005 File        : autoip.c
00006 
00007 Description : Implementation of Dynamic Configuration of IPv4 Link-Local
00008               Addresses (according to RFC 3927)
00009 
00010 Copyright notice:
00011 
00012 Copyright (C) 2005 -
00013 Andreas Dittrich, dittrich@informatik.hu-berlin.de
00014 Jon Kowal, kowal@informatik.hu-berlin.de
00015 
00016 This program is free software; you can redistribute it and/or
00017 modify it under the terms of the GNU General Public License
00018 as published by the Free Software Foundation; either version 2
00019 of the License, or (at your option) any later version.
00020 
00021 This program is distributed in the hope that it will be useful,
00022 but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00024 GNU General Public License for more details.
00025 
00026 You should have received a copy of the GNU General Public License
00027 along with this program; if not, write to the Free Software
00028 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00029 
00030 ##############################################################################*/
00031 
00032 #include "dispatcher.h"
00033 #include "inet.h"
00034 #include "net/autoip.h"
00035 #include "net/arp.h"
00036 #include "net/net_if.h"
00037 #include "net/ip.h"
00038 #include "os_core.h"
00039 
00040 #if ( NIP_AUTOIP_ENABLE == 1 )
00041 
00042 
00043 #if NIP_NET_IF_COUNT > 1
00044         struct nip_autoip_conf nip_autoip_conf[ NIP_NET_IF_COUNT ] ;
00045         #define NIP_AUTOIP_CONF( if_id ) nip_autoip_conf[if_id]
00046 #else
00047         struct nip_autoip_conf nip_autoip_conf;
00048         #define NIP_AUTOIP_CONF( if_id ) nip_autoip_conf
00049 #endif
00050 
00051 /** Enable Dynamic Configuration of IPv4 Link-Local Addresses for given
00052  * interface.
00053  */
00054 void nip_autoip_start( nip_net_if_id_t net_if )
00055 {
00056         NIP_AUTOIP_CONF(net_if).state = NIP_AUTOIP_STAT_INIT;
00057         NIP_AUTOIP_CONF(net_if).t     = nip_tickcount() + NIP_AUTOIP_PROBE_WAIT;
00058 }
00059 
00060 
00061 /** Function to be called by dispatcher to check AutoIP state
00062  */
00063 void nip_autoip_disp_check( void )
00064 {
00065         // use different mechanisms to access autoip configuration for the single and
00066         // the multi interface cases to minimize use of program memory in either case
00067 #if NIP_NET_IF_COUNT > 1
00068         struct nip_autoip_conf *conf   = & NIP_AUTOIP_CONF( NIP_CURR_IF );
00069         #define CONF_ATTR(attr) conf-> attr
00070 #else
00071         #define CONF_ATTR(attr) nip_autoip_conf.attr
00072 #endif
00073         nip_time_t             tc = nip_tickcount();
00074         nip_net_if_t           *net_if   = & nip_net_if_list[ NIP_CURR_IF ];
00075         uint8_t                *addr_ptr = &net_if->phy_conf.hw_addr[ net_if->phy_conf.hw_addr_size-4];
00076 
00077         // Don't perform any checks, if AutoIP is disabled. Also double check, that
00078         // we're not interfering with any other IP-setting instance (e.g. DHCP).
00079         if ( CONF_ATTR(state) == NIP_AUTOIP_STAT_DISABLED
00080           || (net_if->ip_conf.state == NIP_IP_CONF_STAT_CONFIGURED
00081              && memcmp( net_if->ip_conf.addr, CONF_ATTR(addr), 4 ) != 0)
00082                 )
00083         {
00084                 return;
00085         }
00086 
00087         // Upon conflict choose new IP address
00088         if ( CONF_ATTR(state) == NIP_AUTOIP_STAT_CONFLICT )
00089         {
00090                 if ( CONF_ATTR(conflict_cnt) < 255 )
00091                         CONF_ATTR(conflict_cnt)++;
00092                 else
00093                         CONF_ATTR(addr)[2]++;
00094 
00095                 CONF_ATTR(addr)[3] += addr_ptr[0]+addr_ptr[3];
00096 
00097                 // set new timeout for next probe
00098                 if ( CONF_ATTR(conflict_cnt) > NIP_AUTOIP_MAX_CONFLICTS )
00099                         CONF_ATTR(t) += NIP_AUTOIP_RATE_LIMIT_INTERVAL;
00100 
00101                 // reset probe mechanism
00102                 CONF_ATTR(cnt)          = 0;
00103                 CONF_ATTR(state)        = NIP_AUTOIP_STAT_PROBE;
00104                 net_if->ip_conf.state   = NIP_IP_CONF_STAT_UNCONFIGURED;
00105         }
00106 
00107         // all states except CONFLICT which is handled above are time triggered
00108         if ( tc >= CONF_ATTR(t) )
00109         {
00110                 switch ( CONF_ATTR( state ) )
00111                 {
00112                         case NIP_AUTOIP_STAT_INIT:
00113                                 CONF_ATTR(conflict_cnt) = 0;
00114                                 // select IP address based on hardware address
00115                                 CONF_ATTR(addr)[0] = 169;
00116                                 CONF_ATTR(addr)[1] = 254;
00117                                 CONF_ATTR(addr)[2] = addr_ptr[0]+addr_ptr[1];
00118                                 CONF_ATTR(addr)[3] = addr_ptr[2]+addr_ptr[3];
00119 
00120                                 // send probes
00121                                 CONF_ATTR(cnt)          = 0;
00122                                 CONF_ATTR(state)        = NIP_AUTOIP_STAT_PROBE;
00123                                 goto probe;
00124 
00125                         case NIP_AUTOIP_STAT_PROBE:
00126                                 goto probe;
00127 
00128                         case NIP_AUTOIP_STAT_ANNOUNCE:
00129                                 goto announce;
00130 
00131                         default:
00132                                 // don't do anything if autoip is UP or DISABLED
00133                                 // just wait for conflicts
00134                                 break;
00135                 }
00136         }
00137 
00138         return;
00139 
00140 probe:
00141 
00142         // check counter and switch to ANNOUNCE state if PROBE_NUM has been
00143         // reached.
00144         if ( ++CONF_ATTR(cnt) < NIP_AUTOIP_PROBE_NUM )
00145         {
00146                 // set timeout for next probe
00147                 CONF_ATTR(t) = tc + NIP_AUTOIP_PROBE_MAX;
00148         }
00149         else
00150         {
00151                 // announce new address
00152                 CONF_ATTR(cnt)   = 0;
00153                 CONF_ATTR(t)     = tc + NIP_AUTOIP_ANNOUNCE_WAIT;
00154                 CONF_ATTR(state) = NIP_AUTOIP_STAT_ANNOUNCE;
00155         }
00156 
00157         // clear IP address and send ARP Probe
00158         nip_memset( net_if->ip_conf.addr, 0, 4 );
00159         NIP_CURR_CMD = &nip_arp_disp_probe_announcement;
00160 
00161         return;
00162 
00163 announce:
00164 
00165         // check announcement counter
00166         if ( ++CONF_ATTR(cnt) < NIP_AUTOIP_ANNOUNCE_NUM )
00167         {
00168                 CONF_ATTR(t) = tc + NIP_AUTOIP_ANNOUNCE_INTERVAL;
00169         }
00170         else
00171         {
00172                 CONF_ATTR(cnt)   = 0;
00173                 CONF_ATTR(state) = NIP_AUTOIP_STAT_UP;
00174         }
00175 
00176         // set IP address and send ARP announcement
00177         nip_ip_addr_set( NIP_CURR_IF, CONF_ATTR(addr) );
00178         NIP_CURR_CMD = &nip_arp_disp_probe_announcement;
00179 
00180         return;
00181 }
00182 
00183 /** Check incoming ARP packet for conflict with current link-local configuration
00184  */
00185 void nip_autoip_arpcheck( nip_net_if_id_t if_id, struct ARP_PACKET *arp )
00186 {
00187 //      nip_net_if_t    *net_if = &nip_net_if_list[ if_id ];
00188 #if NIP_NET_IF_COUNT > 1
00189         struct nip_autoip_conf *conf   = & NIP_AUTOIP_CONF( NIP_CURR_IF );
00190         #define CONF_ATTR(attr) conf-> attr
00191 #else
00192         #define CONF_ATTR(attr) nip_autoip_conf.attr
00193 #endif
00194 
00195         // if sender address matches own address -> conflict
00196         if ( nip_memcmp( arp->spa, CONF_ATTR(addr), 4 ) == 0 )
00197         {
00198                 NIP_AUTOIP_CONF(if_id).state = NIP_AUTOIP_STAT_CONFLICT;
00199                 nip_disp_notify_if( if_id, NIP_DISP_IF_AUTOIP );
00200         }
00201 
00202 }
00203 
00204 
00205 #endif // NIP_AUTOIP_ENABLE

Generated on Thu Jul 10 01:09:29 2008 for NIP by  doxygen 1.5.5