Free (GPLv2) TCP/IP stack developed by TASS Belgium
Dependents: lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more
pico_slaacv4.c
00001 /********************************************************************* 00002 PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved. 00003 See LICENSE and COPYING for usage. 00004 00005 Authors: Bogdan Lupu 00006 *********************************************************************/ 00007 #include "pico_slaacv4.h" 00008 #include "pico_arp.h" 00009 #include "pico_constants.h" 00010 #include "pico_stack.h" 00011 00012 #ifdef PICO_SUPPORT_SLAACV4 00013 00014 #define SLAACV4_NETWORK ((long_be(0xa9fe0000))) 00015 #define SLAACV4_NETMASK ((long_be(0xFFFF0000))) 00016 #define SLAACV4_MINRANGE (0x00000100) /* In host order */ 00017 #define SLAACV4_MAXRANGE (0x0000FDFF) /* In host order */ 00018 00019 #define SLAACV4_CREATE_IPV4(seed) ((long_be((seed % SLAACV4_MAXRANGE) + SLAACV4_MINRANGE) & ~SLAACV4_NETMASK) | SLAACV4_NETWORK) 00020 00021 #define PROBE_WAIT 1 /* delay between two tries during claim */ 00022 #define PROBE_NB 3 /* number of probe packets during claim */ 00023 /* #define PROBE_MIN 1 */ 00024 /* #define PROBE_MAX 2 */ 00025 #define ANNOUNCE_WAIT 2 /* delay before start announcing */ 00026 #define ANNOUNCE_NB 2 /* number of announcement packets */ 00027 #define ANNOUNCE_INTERVAL 2 /* time between announcement packets */ 00028 #define MAX_CONFLICTS 10 /* max conflicts before rate limiting */ 00029 #define RATE_LIMIT_INTERVAL 60 /* time between successive attempts */ 00030 #define DEFEND_INTERVAL 10 /* minimum interval between defensive ARP */ 00031 00032 enum slaacv4_state { 00033 SLAACV4_RESET = 0, 00034 SLAACV4_CLAIMING, 00035 SLAACV4_CLAIMED, 00036 SLAACV4_ANNOUNCING, 00037 SLAACV4_ERROR 00038 }; 00039 00040 struct slaacv4_cookie { 00041 enum slaacv4_state state; 00042 uint8_t probe_try_nb; 00043 uint8_t conflict_nb; 00044 uint8_t announce_nb; 00045 struct pico_ip4 ip; 00046 struct pico_device *device; 00047 struct pico_timer *timer; 00048 void (*cb)(struct pico_ip4 *ip, uint8_t code); 00049 }; 00050 00051 static struct slaacv4_cookie slaacv4_local; 00052 00053 static uint32_t pico_slaacv4_getip(struct pico_device *dev, uint8_t rand) 00054 { 00055 uint32_t seed = 0; 00056 if (dev->eth != NULL) 00057 { 00058 seed = pico_hash((const uint8_t *)dev->eth->mac.addr, PICO_SIZE_ETH); 00059 } 00060 00061 if (rand) 00062 { 00063 seed += pico_rand(); 00064 } 00065 00066 return SLAACV4_CREATE_IPV4(seed); 00067 } 00068 00069 static void pico_slaacv4_init_cookie(struct pico_ip4 *ip, struct pico_device *dev, struct slaacv4_cookie *ck, void (*cb)(struct pico_ip4 *ip, uint8_t code)) 00070 { 00071 ck->state = SLAACV4_RESET; 00072 ck->probe_try_nb = 0; 00073 ck->conflict_nb = 0; 00074 ck->announce_nb = 0; 00075 ck->cb = cb; 00076 ck->device = dev; 00077 ck->ip.addr = ip->addr; 00078 ck->timer = NULL; 00079 } 00080 00081 static void pico_slaacv4_cancel_timers(struct slaacv4_cookie *tmp) 00082 { 00083 pico_timer_cancel(tmp->timer); 00084 00085 tmp->timer = NULL; 00086 } 00087 00088 static void pico_slaacv4_send_announce_timer(pico_time now, void *arg) 00089 { 00090 struct slaacv4_cookie *tmp = (struct slaacv4_cookie *)arg; 00091 struct pico_ip4 netmask = { 0 }; 00092 netmask.addr = long_be(0xFFFF0000); 00093 00094 (void)now; 00095 00096 if (tmp->announce_nb < ANNOUNCE_NB) 00097 { 00098 pico_arp_request(tmp->device, &tmp->ip, PICO_ARP_ANNOUNCE); 00099 tmp->announce_nb++; 00100 tmp->timer = pico_timer_add(ANNOUNCE_INTERVAL * 1000, pico_slaacv4_send_announce_timer, arg); 00101 } 00102 else 00103 { 00104 tmp->state = SLAACV4_CLAIMED; 00105 pico_ipv4_link_add(tmp->device, tmp->ip, netmask); 00106 if (tmp->cb != NULL) 00107 tmp->cb(&tmp->ip, PICO_SLAACV4_SUCCESS); 00108 } 00109 } 00110 00111 static void pico_slaacv4_send_probe_timer(pico_time now, void *arg) 00112 { 00113 struct slaacv4_cookie *tmp = (struct slaacv4_cookie *)arg; 00114 (void)now; 00115 00116 if (tmp->probe_try_nb < PROBE_NB) 00117 { 00118 pico_arp_request(tmp->device, &tmp->ip, PICO_ARP_PROBE); 00119 tmp->probe_try_nb++; 00120 tmp->timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, tmp); 00121 } 00122 else 00123 { 00124 tmp->state = SLAACV4_ANNOUNCING; 00125 tmp->timer = pico_timer_add(ANNOUNCE_WAIT * 1000, pico_slaacv4_send_announce_timer, arg); 00126 } 00127 } 00128 00129 00130 00131 static void pico_slaacv4_receive_ipconflict(void) 00132 { 00133 struct slaacv4_cookie *tmp = &slaacv4_local; 00134 00135 tmp->conflict_nb++; 00136 pico_slaacv4_cancel_timers(tmp); 00137 00138 if(tmp->state == SLAACV4_CLAIMED) 00139 { 00140 pico_ipv4_link_del(tmp->device, tmp->ip); 00141 } 00142 00143 if (tmp->conflict_nb < MAX_CONFLICTS) 00144 { 00145 tmp->state = SLAACV4_CLAIMING; 00146 tmp->probe_try_nb = 0; 00147 tmp->announce_nb = 0; 00148 tmp->ip.addr = long_be(pico_slaacv4_getip(tmp->device, (uint8_t)1)); 00149 pico_arp_register_ipconflict(&tmp->ip, &tmp->device->eth->mac, pico_slaacv4_receive_ipconflict); 00150 pico_arp_request(tmp->device, &tmp->ip, PICO_ARP_PROBE); 00151 tmp->probe_try_nb++; 00152 tmp->timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, tmp); 00153 } 00154 else 00155 { 00156 if (tmp->cb != NULL) 00157 { 00158 tmp->cb(&tmp->ip, PICO_SLAACV4_ERROR); 00159 } 00160 00161 tmp->state = SLAACV4_ERROR; 00162 } 00163 00164 } 00165 00166 int pico_slaacv4_claimip(struct pico_device *dev, void (*cb)(struct pico_ip4 *ip, uint8_t code)) 00167 { 00168 struct pico_ip4 ip; 00169 00170 if (!dev->eth) { 00171 pico_err = PICO_ERR_EPROTONOSUPPORT; 00172 return -1; 00173 } 00174 00175 ip.addr = pico_slaacv4_getip(dev, 0); 00176 00177 pico_slaacv4_init_cookie(&ip, dev, &slaacv4_local, cb); 00178 pico_arp_register_ipconflict(&ip, &dev->eth->mac, pico_slaacv4_receive_ipconflict); 00179 pico_arp_request(dev, &ip, PICO_ARP_PROBE); 00180 slaacv4_local.state = SLAACV4_CLAIMING; 00181 slaacv4_local.probe_try_nb++; 00182 slaacv4_local.timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, &slaacv4_local); 00183 00184 return 0; 00185 } 00186 00187 void pico_slaacv4_unregisterip(void) 00188 { 00189 struct slaacv4_cookie *tmp = &slaacv4_local; 00190 struct pico_ip4 empty = { 00191 .addr = 0x00000000 00192 }; 00193 00194 if (tmp->state == SLAACV4_CLAIMED) 00195 { 00196 pico_ipv4_link_del(tmp->device, tmp->ip); 00197 } 00198 00199 pico_slaacv4_cancel_timers(tmp); 00200 pico_slaacv4_init_cookie(&empty, NULL, tmp, NULL); 00201 pico_arp_register_ipconflict(&tmp->ip, NULL, NULL); 00202 00203 } 00204 00205 #endif
Generated on Tue Jul 12 2022 15:59:22 by 1.7.2