BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file
3 * lwIP network interface abstraction
4 *
5 * @defgroup netif Network interface (NETIF)
6 * @ingroup callbackstyle_api
7 *
8 * @defgroup netif_ip4 IPv4 address handling
9 * @ingroup netif
10 *
11 * @defgroup netif_ip6 IPv6 address handling
12 * @ingroup netif
13 *
14 * @defgroup netif_cd Client data handling
15 * Store data (void*) on a netif for application usage.
16 * @see @ref LWIP_NUM_NETIF_CLIENT_DATA
17 * @ingroup netif
18 */
19  
20 /*
21 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
22 * All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without modification,
25 * are permitted provided that the following conditions are met:
26 *
27 * 1. Redistributions of source code must retain the above copyright notice,
28 * this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright notice,
30 * this list of conditions and the following disclaimer in the documentation
31 * and/or other materials provided with the distribution.
32 * 3. The name of the author may not be used to endorse or promote products
33 * derived from this software without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
37 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
38 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
40 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
43 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
44 * OF SUCH DAMAGE.
45 *
46 * This file is part of the lwIP TCP/IP stack.
47 *
48 * Author: Adam Dunkels <adam@sics.se>
49 */
50  
51 #include "lwip/opt.h"
52  
53 #include <string.h> /* memset */
54 #include <stdlib.h> /* atoi */
55  
56 #include "lwip/def.h"
57 #include "lwip/ip_addr.h"
58 #include "lwip/ip6_addr.h"
59 #include "lwip/netif.h"
60 #include "lwip/priv/tcp_priv.h"
61 #include "lwip/udp.h"
62 #include "lwip/raw.h"
63 #include "lwip/snmp.h"
64 #include "lwip/igmp.h"
65 #include "lwip/etharp.h"
66 #include "lwip/stats.h"
67 #include "lwip/sys.h"
68 #include "lwip/ip.h"
69 #if ENABLE_LOOPBACK
70 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
71 #include "lwip/tcpip.h"
72 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
73 #endif /* ENABLE_LOOPBACK */
74  
75 #include "netif/ethernet.h"
76  
77 #if LWIP_AUTOIP
78 #include "lwip/autoip.h"
79 #endif /* LWIP_AUTOIP */
80 #if LWIP_DHCP
81 #include "lwip/dhcp.h"
82 #endif /* LWIP_DHCP */
83 #if LWIP_IPV6_DHCP6
84 #include "lwip/dhcp6.h"
85 #endif /* LWIP_IPV6_DHCP6 */
86 #if LWIP_IPV6_MLD
87 #include "lwip/mld6.h"
88 #endif /* LWIP_IPV6_MLD */
89 #if LWIP_IPV6
90 #include "lwip/nd6.h"
91 #endif
92  
93 #if LWIP_NETIF_STATUS_CALLBACK
94 #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
95 #else
96 #define NETIF_STATUS_CALLBACK(n)
97 #endif /* LWIP_NETIF_STATUS_CALLBACK */
98  
99 #if LWIP_NETIF_LINK_CALLBACK
100 #define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0)
101 #else
102 #define NETIF_LINK_CALLBACK(n)
103 #endif /* LWIP_NETIF_LINK_CALLBACK */
104  
105 #if LWIP_NETIF_EXT_STATUS_CALLBACK
106 static netif_ext_callback_t *ext_callback;
107 #endif
108  
109 #if !LWIP_SINGLE_NETIF
110 struct netif *netif_list;
111 #endif /* !LWIP_SINGLE_NETIF */
112 struct netif *netif_default;
113  
114 #define netif_index_to_num(index) ((index) - 1)
115 static u8_t netif_num;
116  
117 #if LWIP_NUM_NETIF_CLIENT_DATA > 0
118 static u8_t netif_client_id;
119 #endif
120  
121 #define NETIF_REPORT_TYPE_IPV4 0x01
122 #define NETIF_REPORT_TYPE_IPV6 0x02
123 static void netif_issue_reports(struct netif *netif, u8_t report_type);
124  
125 #if LWIP_IPV6
126 static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr);
127 #endif /* LWIP_IPV6 */
128  
129 #if LWIP_HAVE_LOOPIF
130 #if LWIP_IPV4
131 static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr);
132 #endif
133 #if LWIP_IPV6
134 static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr);
135 #endif
136  
137  
138 static struct netif loop_netif;
139  
140 /**
141 * Initialize a lwip network interface structure for a loopback interface
142 *
143 * @param netif the lwip network interface structure for this loopif
144 * @return ERR_OK if the loopif is initialized
145 * ERR_MEM if private data couldn't be allocated
146 */
147 static err_t
148 netif_loopif_init(struct netif *netif)
149 {
150 /* initialize the snmp variables and counters inside the struct netif
151 * ifSpeed: no assumption can be made!
152 */
153 MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0);
154  
155 netif->name[0] = 'l';
156 netif->name[1] = 'o';
157 #if LWIP_IPV4
158 netif->output = netif_loop_output_ipv4;
159 #endif
160 #if LWIP_IPV6
161 netif->output_ip6 = netif_loop_output_ipv6;
162 #endif
163 #if LWIP_LOOPIF_MULTICAST
164 netif_set_flags(netif, NETIF_FLAG_IGMP);
165 #endif
166 return ERR_OK;
167 }
168 #endif /* LWIP_HAVE_LOOPIF */
169  
170 void
171 netif_init(void)
172 {
173 #if LWIP_HAVE_LOOPIF
174 #if LWIP_IPV4
175 #define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw,
176 ip4_addr_t loop_ipaddr, loop_netmask, loop_gw;
177 IP4_ADDR(&loop_gw, 127, 0, 0, 1);
178 IP4_ADDR(&loop_ipaddr, 127, 0, 0, 1);
179 IP4_ADDR(&loop_netmask, 255, 0, 0, 0);
180 #else /* LWIP_IPV4 */
181 #define LOOPIF_ADDRINIT
182 #endif /* LWIP_IPV4 */
183  
184 #if NO_SYS
185 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input);
186 #else /* NO_SYS */
187 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input);
188 #endif /* NO_SYS */
189  
190 #if LWIP_IPV6
191 IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
192 loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
193 #endif /* LWIP_IPV6 */
194  
195 netif_set_link_up(&loop_netif);
196 netif_set_up(&loop_netif);
197  
198 #endif /* LWIP_HAVE_LOOPIF */
199 }
200  
201 /**
202 * @ingroup lwip_nosys
203 * Forwards a received packet for input processing with
204 * ethernet_input() or ip_input() depending on netif flags.
205 * Don't call directly, pass to netif_add() and call
206 * netif->input().
207 * Only works if the netif driver correctly sets
208 * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag!
209 */
210 err_t
211 netif_input(struct pbuf *p, struct netif *inp)
212 {
213 #if LWIP_ETHERNET
214 if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
215 return ethernet_input(p, inp);
216 } else
217 #endif /* LWIP_ETHERNET */
218 return ip_input(p, inp);
219 }
220  
221 /**
222 * @ingroup netif
223 * Add a network interface to the list of lwIP netifs.
224 *
225 * Same as @ref netif_add but without IPv4 addresses
226 */
227 struct netif *
228 netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input)
229 {
230 return netif_add(netif,
231 #if LWIP_IPV4
232 NULL, NULL, NULL,
233 #endif /* LWIP_IPV4*/
234 state, init, input);
235 }
236  
237 /**
238 * @ingroup netif
239 * Add a network interface to the list of lwIP netifs.
240 *
241 * @param netif a pre-allocated netif structure
242 * @param ipaddr IP address for the new netif
243 * @param netmask network mask for the new netif
244 * @param gw default gateway IP address for the new netif
245 * @param state opaque data passed to the new netif
246 * @param init callback function that initializes the interface
247 * @param input callback function that is called to pass
248 * ingress packets up in the protocol layer stack.\n
249 * It is recommended to use a function that passes the input directly
250 * to the stack (netif_input(), NO_SYS=1 mode) or via sending a
251 * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n
252 * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET
253 * to decide whether to forward to ethernet_input() or ip_input().
254 * In other words, the functions only work when the netif
255 * driver is implemented correctly!\n
256 * Most members of struct netif should be be initialized by the
257 * netif init function = netif driver (init parameter of this function).\n
258 * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after
259 * setting the MAC address in struct netif.hwaddr
260 * (IPv6 requires a link-local address).
261 *
262 * @return netif, or NULL if failed.
263 */
264 struct netif *
265 netif_add(struct netif *netif,
266 #if LWIP_IPV4
267 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
268 #endif /* LWIP_IPV4 */
269 void *state, netif_init_fn init, netif_input_fn input)
270 {
271 #if LWIP_IPV6
272 s8_t i;
273 #endif
274  
275 #if LWIP_SINGLE_NETIF
276 if (netif_default != NULL) {
277 LWIP_ASSERT("single netif already set", 0);
278 return NULL;
279 }
280 #endif
281  
282 LWIP_ASSERT("No init function given", init != NULL);
283  
284 #if LWIP_IPV4
285 if (ipaddr == NULL) {
286 ipaddr = ip_2_ip4(IP4_ADDR_ANY);
287 }
288 if (netmask == NULL) {
289 netmask = ip_2_ip4(IP4_ADDR_ANY);
290 }
291 if (gw == NULL) {
292 gw = ip_2_ip4(IP4_ADDR_ANY);
293 }
294  
295 /* reset new interface configuration state */
296 ip_addr_set_zero_ip4(&netif->ip_addr);
297 ip_addr_set_zero_ip4(&netif->netmask);
298 ip_addr_set_zero_ip4(&netif->gw);
299 #endif /* LWIP_IPV4 */
300 #if LWIP_IPV6
301 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
302 ip_addr_set_zero_ip6(&netif->ip6_addr[i]);
303 netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
304 #if LWIP_IPV6_ADDRESS_LIFETIMES
305 netif->ip6_addr_valid_life[i] = IP6_ADDR_LIFE_STATIC;
306 netif->ip6_addr_pref_life[i] = IP6_ADDR_LIFE_STATIC;
307 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
308 }
309 netif->output_ip6 = netif_null_output_ip6;
310 #endif /* LWIP_IPV6 */
311 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL);
312 netif->flags = 0;
313 #ifdef netif_get_client_data
314 memset(netif->client_data, 0, sizeof(netif->client_data));
315 #endif /* LWIP_NUM_NETIF_CLIENT_DATA */
316 #if LWIP_IPV6_AUTOCONFIG
317 /* IPv6 address autoconfiguration not enabled by default */
318 netif->ip6_autoconfig_enabled = 0;
319 #endif /* LWIP_IPV6_AUTOCONFIG */
320 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
321 netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
322 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
323 #if LWIP_NETIF_STATUS_CALLBACK
324 netif->status_callback = NULL;
325 #endif /* LWIP_NETIF_STATUS_CALLBACK */
326 #if LWIP_NETIF_LINK_CALLBACK
327 netif->link_callback = NULL;
328 #endif /* LWIP_NETIF_LINK_CALLBACK */
329 #if LWIP_IGMP
330 netif->igmp_mac_filter = NULL;
331 #endif /* LWIP_IGMP */
332 #if LWIP_IPV6 && LWIP_IPV6_MLD
333 netif->mld_mac_filter = NULL;
334 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
335 #if ENABLE_LOOPBACK
336 netif->loop_first = NULL;
337 netif->loop_last = NULL;
338 #endif /* ENABLE_LOOPBACK */
339  
340 /* remember netif specific state information data */
341 netif->state = state;
342 netif->num = netif_num;
343 netif->input = input;
344  
345 NETIF_RESET_HINTS(netif);
346 #if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
347 netif->loop_cnt_current = 0;
348 #endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
349  
350 #if LWIP_IPV4
351 netif_set_addr(netif, ipaddr, netmask, gw);
352 #endif /* LWIP_IPV4 */
353  
354 /* call user specified initialization function for netif */
355 if (init(netif) != ERR_OK) {
356 return NULL;
357 }
358  
359 #if !LWIP_SINGLE_NETIF
360 /* Assign a unique netif number in the range [0..254], so that (num+1) can
361 serve as an interface index that fits in a u8_t.
362 We assume that the new netif has not yet been added to the list here.
363 This algorithm is O(n^2), but that should be OK for lwIP.
364 */
365 {
366 struct netif *netif2;
367 int num_netifs;
368 do {
369 if (netif->num == 255) {
370 netif->num = 0;
371 }
372 num_netifs = 0;
373 for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) {
374 num_netifs++;
375 LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255);
376 if (netif2->num == netif->num) {
377 netif->num++;
378 break;
379 }
380 }
381 } while (netif2 != NULL);
382 }
383 if (netif->num == 254) {
384 netif_num = 0;
385 } else {
386 netif_num = (u8_t)(netif->num + 1);
387 }
388  
389 /* add this netif to the list */
390 netif->next = netif_list;
391 netif_list = netif;
392 #endif /* "LWIP_SINGLE_NETIF */
393 mib2_netif_added(netif);
394  
395 #if LWIP_IGMP
396 /* start IGMP processing */
397 if (netif->flags & NETIF_FLAG_IGMP) {
398 igmp_start(netif);
399 }
400 #endif /* LWIP_IGMP */
401  
402 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP",
403 netif->name[0], netif->name[1]));
404 #if LWIP_IPV4
405 LWIP_DEBUGF(NETIF_DEBUG, (" addr "));
406 ip4_addr_debug_print(NETIF_DEBUG, ipaddr);
407 LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
408 ip4_addr_debug_print(NETIF_DEBUG, netmask);
409 LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
410 ip4_addr_debug_print(NETIF_DEBUG, gw);
411 #endif /* LWIP_IPV4 */
412 LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
413  
414 netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_ADDED, NULL);
415  
416 return netif;
417 }
418  
419 #if LWIP_IPV4
420 /**
421 * @ingroup netif_ip4
422 * Change IP address configuration for a network interface (including netmask
423 * and default gateway).
424 *
425 * @param netif the network interface to change
426 * @param ipaddr the new IP address
427 * @param netmask the new netmask
428 * @param gw the new default gateway
429 */
430 void
431 netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
432 const ip4_addr_t *gw)
433 {
434 #if LWIP_NETIF_EXT_STATUS_CALLBACK
435 u8_t something_changed = 0;
436  
437 if ((ip4_addr_cmp(ipaddr, netif_ip4_addr(netif)) == 0) ||
438 (ip4_addr_cmp(gw, netif_ip4_gw(netif)) == 0) ||
439 (ip4_addr_cmp(netmask, netif_ip4_netmask(netif)) == 0)) {
440 something_changed = 1;
441 }
442 #endif
443  
444 if (ip4_addr_isany(ipaddr)) {
445 /* when removing an address, we have to remove it *before* changing netmask/gw
446 to ensure that tcp RST segment can be sent correctly */
447 netif_set_ipaddr(netif, ipaddr);
448 netif_set_netmask(netif, netmask);
449 netif_set_gw(netif, gw);
450 } else {
451 netif_set_netmask(netif, netmask);
452 netif_set_gw(netif, gw);
453 /* set ipaddr last to ensure netmask/gw have been set when status callback is called */
454 netif_set_ipaddr(netif, ipaddr);
455 }
456  
457 #if LWIP_NETIF_EXT_STATUS_CALLBACK
458 if (something_changed != 0) {
459 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_SETTINGS_CHANGED, NULL);
460 }
461 #endif
462 }
463 #endif /* LWIP_IPV4*/
464  
465 /**
466 * @ingroup netif
467 * Remove a network interface from the list of lwIP netifs.
468 *
469 * @param netif the network interface to remove
470 */
471 void
472 netif_remove(struct netif *netif)
473 {
474 #if LWIP_IPV6
475 int i;
476 #endif
477  
478 if (netif == NULL) {
479 return;
480 }
481  
482 netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_REMOVED, NULL);
483  
484 #if LWIP_IPV4
485 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
486 #if LWIP_TCP
487 tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
488 #endif /* LWIP_TCP */
489 #if LWIP_UDP
490 udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
491 #endif /* LWIP_UDP */
492 #if LWIP_RAW
493 raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
494 #endif /* LWIP_RAW */
495 }
496  
497 #if LWIP_IGMP
498 /* stop IGMP processing */
499 if (netif->flags & NETIF_FLAG_IGMP) {
500 igmp_stop(netif);
501 }
502 #endif /* LWIP_IGMP */
503 #endif /* LWIP_IPV4*/
504  
505 #if LWIP_IPV6
506 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
507 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
508 #if LWIP_TCP
509 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
510 #endif /* LWIP_TCP */
511 #if LWIP_UDP
512 udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
513 #endif /* LWIP_UDP */
514 #if LWIP_RAW
515 raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
516 #endif /* LWIP_RAW */
517 }
518 }
519 #if LWIP_IPV6_MLD
520 /* stop MLD processing */
521 mld6_stop(netif);
522 #endif /* LWIP_IPV6_MLD */
523 #endif /* LWIP_IPV6 */
524 if (netif_is_up(netif)) {
525 /* set netif down before removing (call callback function) */
526 netif_set_down(netif);
527 }
528  
529 mib2_remove_ip4(netif);
530  
531 /* this netif is default? */
532 if (netif_default == netif) {
533 /* reset default netif */
534 netif_set_default(NULL);
535 }
536 #if !LWIP_SINGLE_NETIF
537 /* is it the first netif? */
538 if (netif_list == netif) {
539 netif_list = netif->next;
540 } else {
541 /* look for netif further down the list */
542 struct netif *tmp_netif;
543 for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) {
544 if (tmp_netif->next == netif) {
545 tmp_netif->next = netif->next;
546 break;
547 }
548 }
549 if (tmp_netif == NULL) {
550 return; /* netif is not on the list */
551 }
552 }
553 #endif /* !LWIP_SINGLE_NETIF */
554 mib2_netif_removed(netif);
555 #if LWIP_NETIF_REMOVE_CALLBACK
556 if (netif->remove_callback) {
557 netif->remove_callback(netif);
558 }
559 #endif /* LWIP_NETIF_REMOVE_CALLBACK */
560 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
561 }
562  
563 #if LWIP_IPV4
564 /**
565 * @ingroup netif_ip4
566 * Change the IP address of a network interface
567 *
568 * @param netif the network interface to change
569 * @param ipaddr the new IP address
570 *
571 * @note call netif_set_addr() if you also want to change netmask and
572 * default gateway
573 */
574 void
575 netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
576 {
577 ip_addr_t new_addr;
578 *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4);
579 IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4);
580  
581 /* address is actually being changed? */
582 if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) {
583 ip_addr_t old_addr;
584 ip_addr_copy(old_addr, *netif_ip_addr4(netif));
585  
586 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
587 #if LWIP_TCP
588 tcp_netif_ip_addr_changed(&old_addr, &new_addr);
589 #endif /* LWIP_TCP */
590 #if LWIP_UDP
591 udp_netif_ip_addr_changed(&old_addr, &new_addr);
592 #endif /* LWIP_UDP */
593 #if LWIP_RAW
594 raw_netif_ip_addr_changed(&old_addr, &new_addr);
595 #endif /* LWIP_RAW */
596  
597 mib2_remove_ip4(netif);
598 mib2_remove_route_ip4(0, netif);
599 /* set new IP address to netif */
600 ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr);
601 IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4);
602 mib2_add_ip4(netif);
603 mib2_add_route_ip4(0, netif);
604  
605 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4);
606  
607 NETIF_STATUS_CALLBACK(netif);
608 #if LWIP_NETIF_EXT_STATUS_CALLBACK
609 {
610 netif_ext_callback_args_t args;
611 args.ipv4_changed.old_address = &old_addr;
612 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_ADDRESS_CHANGED, &args);
613 }
614 #endif
615 }
616  
617 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
618 netif->name[0], netif->name[1],
619 ip4_addr1_16(netif_ip4_addr(netif)),
620 ip4_addr2_16(netif_ip4_addr(netif)),
621 ip4_addr3_16(netif_ip4_addr(netif)),
622 ip4_addr4_16(netif_ip4_addr(netif))));
623 }
624  
625 /**
626 * @ingroup netif_ip4
627 * Change the default gateway for a network interface
628 *
629 * @param netif the network interface to change
630 * @param gw the new default gateway
631 *
632 * @note call netif_set_addr() if you also want to change ip address and netmask
633 */
634 void
635 netif_set_gw(struct netif *netif, const ip4_addr_t *gw)
636 {
637 const ip4_addr_t *safe_gw = gw ? gw : IP4_ADDR_ANY4;
638 #if LWIP_NETIF_EXT_STATUS_CALLBACK
639 netif_ext_callback_args_t args;
640 ip_addr_t old_addr;
641 ip_addr_copy(old_addr, *netif_ip_gw4(netif));
642 args.ipv4_gw_changed.old_address = &old_addr;
643 #endif
644  
645 /* address is actually being changed? */
646 if (ip4_addr_cmp(safe_gw, netif_ip4_gw(netif)) == 0) {
647 ip4_addr_set(ip_2_ip4(&netif->gw), gw);
648 IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4);
649 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
650 netif->name[0], netif->name[1],
651 ip4_addr1_16(netif_ip4_gw(netif)),
652 ip4_addr2_16(netif_ip4_gw(netif)),
653 ip4_addr3_16(netif_ip4_gw(netif)),
654 ip4_addr4_16(netif_ip4_gw(netif))));
655  
656 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_GATEWAY_CHANGED, &args);
657 }
658 }
659  
660 void netif_set_pretend_tcp (struct netif *netif, u8_t pretend)
661 {
662 if (pretend) {
663 netif->flags |= NETIF_FLAG_PRETEND_TCP;
664 } else {
665 netif->flags &= ~NETIF_FLAG_PRETEND_TCP;
666 }
667 }
668  
669 /**
670 * @ingroup netif_ip4
671 * Change the netmask of a network interface
672 *
673 * @param netif the network interface to change
674 * @param netmask the new netmask
675 *
676 * @note call netif_set_addr() if you also want to change ip address and
677 * default gateway
678 */
679 void
680 netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask)
681 {
682 const ip4_addr_t *safe_netmask = netmask ? netmask : IP4_ADDR_ANY4;
683 #if LWIP_NETIF_EXT_STATUS_CALLBACK
684 netif_ext_callback_args_t args;
685 ip_addr_t old_addr;
686 ip_addr_copy(old_addr, *netif_ip_netmask4(netif));
687 args.ipv4_nm_changed.old_address = &old_addr;
688 #endif
689  
690 /* address is actually being changed? */
691 if (ip4_addr_cmp(safe_netmask, netif_ip4_netmask(netif)) == 0) {
692 mib2_remove_route_ip4(0, netif);
693 /* set new netmask to netif */
694 ip4_addr_set(ip_2_ip4(&netif->netmask), netmask);
695 IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4);
696 mib2_add_route_ip4(0, netif);
697 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
698 netif->name[0], netif->name[1],
699 ip4_addr1_16(netif_ip4_netmask(netif)),
700 ip4_addr2_16(netif_ip4_netmask(netif)),
701 ip4_addr3_16(netif_ip4_netmask(netif)),
702 ip4_addr4_16(netif_ip4_netmask(netif))));
703  
704 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_NETMASK_CHANGED, &args);
705 }
706 }
707 #endif /* LWIP_IPV4 */
708  
709 int netif_is_named (struct netif *netif, const char name[3])
710 {
711 u8_t num = name[2] - '0';
712  
713 return (!memcmp(netif->name, name, 2) && netif->num == num);
714 }
715  
716 /**
717 * @ingroup netif
718 * Set a network interface as the default network interface
719 * (used to output all packets for which no specific route is found)
720 *
721 * @param netif the default network interface
722 */
723 void
724 netif_set_default(struct netif *netif)
725 {
726 if (netif == NULL) {
727 /* remove default route */
728 mib2_remove_route_ip4(1, netif);
729 } else {
730 /* install default route */
731 mib2_add_route_ip4(1, netif);
732 }
733 netif_default = netif;
734 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
735 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
736 }
737  
738 /**
739 * @ingroup netif
740 * Bring an interface up, available for processing
741 * traffic.
742 */
743 void
744 netif_set_up(struct netif *netif)
745 {
746 if (!(netif->flags & NETIF_FLAG_UP)) {
747 netif_set_flags(netif, NETIF_FLAG_UP);
748  
749 MIB2_COPY_SYSUPTIME_TO(&netif->ts);
750  
751 NETIF_STATUS_CALLBACK(netif);
752  
753 #if LWIP_NETIF_EXT_STATUS_CALLBACK
754 {
755 netif_ext_callback_args_t args;
756 args.status_changed.state = 1;
757 netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args);
758 }
759 #endif
760  
761 if (netif->flags & NETIF_FLAG_LINK_UP) {
762 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6);
763 }
764 }
765 }
766  
767 /** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change
768 */
769 static void
770 netif_issue_reports(struct netif *netif, u8_t report_type)
771 {
772 #if LWIP_IPV4
773 if ((report_type & NETIF_REPORT_TYPE_IPV4) &&
774 !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
775 #if LWIP_ARP
776 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
777 if (netif->flags & (NETIF_FLAG_ETHARP)) {
778 etharp_gratuitous(netif);
779 }
780 #endif /* LWIP_ARP */
781  
782 #if LWIP_IGMP
783 /* resend IGMP memberships */
784 if (netif->flags & NETIF_FLAG_IGMP) {
785 igmp_report_groups(netif);
786 }
787 #endif /* LWIP_IGMP */
788 }
789 #endif /* LWIP_IPV4 */
790  
791 #if LWIP_IPV6
792 if (report_type & NETIF_REPORT_TYPE_IPV6) {
793 #if LWIP_IPV6_MLD
794 /* send mld memberships */
795 mld6_report_groups(netif);
796 #endif /* LWIP_IPV6_MLD */
797 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
798 /* Send Router Solicitation messages. */
799 netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
800 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
801 }
802 #endif /* LWIP_IPV6 */
803 }
804  
805 /**
806 * @ingroup netif
807 * Bring an interface down, disabling any traffic processing.
808 */
809 void
810 netif_set_down(struct netif *netif)
811 {
812 if (netif->flags & NETIF_FLAG_UP) {
813 #if LWIP_NETIF_EXT_STATUS_CALLBACK
814 {
815 netif_ext_callback_args_t args;
816 args.status_changed.state = 0;
817 netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args);
818 }
819 #endif
820  
821 netif_clear_flags(netif, NETIF_FLAG_UP);
822 MIB2_COPY_SYSUPTIME_TO(&netif->ts);
823  
824 #if LWIP_IPV4 && LWIP_ARP
825 if (netif->flags & NETIF_FLAG_ETHARP) {
826 etharp_cleanup_netif(netif);
827 }
828 #endif /* LWIP_IPV4 && LWIP_ARP */
829  
830 #if LWIP_IPV6
831 nd6_cleanup_netif(netif);
832 #endif /* LWIP_IPV6 */
833  
834 NETIF_STATUS_CALLBACK(netif);
835 }
836 }
837  
838 #if LWIP_NETIF_STATUS_CALLBACK
839 /**
840 * @ingroup netif
841 * Set callback to be called when interface is brought up/down or address is changed while up
842 */
843 void
844 netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
845 {
846 if (netif) {
847 netif->status_callback = status_callback;
848 }
849 }
850 #endif /* LWIP_NETIF_STATUS_CALLBACK */
851  
852 #if LWIP_NETIF_REMOVE_CALLBACK
853 /**
854 * @ingroup netif
855 * Set callback to be called when the interface has been removed
856 */
857 void
858 netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback)
859 {
860 if (netif) {
861 netif->remove_callback = remove_callback;
862 }
863 }
864 #endif /* LWIP_NETIF_REMOVE_CALLBACK */
865  
866 /**
867 * @ingroup netif
868 * Called by a driver when its link goes up
869 */
870 void
871 netif_set_link_up(struct netif *netif)
872 {
873 if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
874 netif_set_flags(netif, NETIF_FLAG_LINK_UP);
875  
876 #if LWIP_DHCP
877 dhcp_network_changed(netif);
878 #endif /* LWIP_DHCP */
879  
880 #if LWIP_AUTOIP
881 autoip_network_changed(netif);
882 #endif /* LWIP_AUTOIP */
883  
884 if (netif->flags & NETIF_FLAG_UP) {
885 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6);
886 }
887 NETIF_LINK_CALLBACK(netif);
888 #if LWIP_NETIF_EXT_STATUS_CALLBACK
889 {
890 netif_ext_callback_args_t args;
891 args.link_changed.state = 1;
892 netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args);
893 }
894 #endif
895 }
896 }
897  
898 /**
899 * @ingroup netif
900 * Called by a driver when its link goes down
901 */
902 void
903 netif_set_link_down(struct netif *netif )
904 {
905 if (netif->flags & NETIF_FLAG_LINK_UP) {
906 netif_clear_flags(netif, NETIF_FLAG_LINK_UP);
907 NETIF_LINK_CALLBACK(netif);
908 #if LWIP_NETIF_EXT_STATUS_CALLBACK
909 {
910 netif_ext_callback_args_t args;
911 args.link_changed.state = 0;
912 netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args);
913 }
914 #endif
915 }
916 }
917  
918 #if LWIP_NETIF_LINK_CALLBACK
919 /**
920 * @ingroup netif
921 * Set callback to be called when link is brought up/down
922 */
923 void
924 netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
925 {
926 if (netif) {
927 netif->link_callback = link_callback;
928 }
929 }
930 #endif /* LWIP_NETIF_LINK_CALLBACK */
931  
932 #if ENABLE_LOOPBACK
933 /**
934 * @ingroup netif
935 * Send an IP packet to be received on the same netif (loopif-like).
936 * The pbuf is simply copied and handed back to netif->input.
937 * In multithreaded mode, this is done directly since netif->input must put
938 * the packet on a queue.
939 * In callback mode, the packet is put on an internal queue and is fed to
940 * netif->input by netif_poll().
941 *
942 * @param netif the lwip network interface structure
943 * @param p the (IP) packet to 'send'
944 * @return ERR_OK if the packet has been sent
945 * ERR_MEM if the pbuf used to copy the packet couldn't be allocated
946 */
947 err_t
948 netif_loop_output(struct netif *netif, struct pbuf *p)
949 {
950 struct pbuf *r;
951 err_t err;
952 struct pbuf *last;
953 #if LWIP_LOOPBACK_MAX_PBUFS
954 u16_t clen = 0;
955 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
956 /* If we have a loopif, SNMP counters are adjusted for it,
957 * if not they are adjusted for 'netif'. */
958 #if MIB2_STATS
959 #if LWIP_HAVE_LOOPIF
960 struct netif *stats_if = &loop_netif;
961 #else /* LWIP_HAVE_LOOPIF */
962 struct netif *stats_if = netif;
963 #endif /* LWIP_HAVE_LOOPIF */
964 #endif /* MIB2_STATS */
965 SYS_ARCH_DECL_PROTECT(lev);
966  
967 /* Allocate a new pbuf */
968 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
969 if (r == NULL) {
970 LINK_STATS_INC(link.memerr);
971 LINK_STATS_INC(link.drop);
972 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
973 return ERR_MEM;
974 }
975 #if LWIP_LOOPBACK_MAX_PBUFS
976 clen = pbuf_clen(r);
977 /* check for overflow or too many pbuf on queue */
978 if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
979 ((netif->loop_cnt_current + clen) > LWIP_MIN(LWIP_LOOPBACK_MAX_PBUFS, 0xFFFF))) {
980 pbuf_free(r);
981 LINK_STATS_INC(link.memerr);
982 LINK_STATS_INC(link.drop);
983 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
984 return ERR_MEM;
985 }
986 netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current + clen);
987 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
988  
989 /* Copy the whole pbuf queue p into the single pbuf r */
990 if ((err = pbuf_copy(r, p)) != ERR_OK) {
991 pbuf_free(r);
992 LINK_STATS_INC(link.memerr);
993 LINK_STATS_INC(link.drop);
994 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
995 return err;
996 }
997  
998 /* Put the packet on a linked list which gets emptied through calling
999 netif_poll(). */
1000  
1001 /* let last point to the last pbuf in chain r */
1002 for (last = r; last->next != NULL; last = last->next) {
1003 /* nothing to do here, just get to the last pbuf */
1004 }
1005  
1006 SYS_ARCH_PROTECT(lev);
1007 if (netif->loop_first != NULL) {
1008 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
1009 netif->loop_last->next = r;
1010 netif->loop_last = last;
1011 } else {
1012 netif->loop_first = r;
1013 netif->loop_last = last;
1014 }
1015 SYS_ARCH_UNPROTECT(lev);
1016  
1017 LINK_STATS_INC(link.xmit);
1018 MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len);
1019 MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts);
1020  
1021 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
1022 /* For multithreading environment, schedule a call to netif_poll */
1023 tcpip_try_callback((tcpip_callback_fn)netif_poll, netif);
1024 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
1025  
1026 return ERR_OK;
1027 }
1028  
1029 #if LWIP_HAVE_LOOPIF
1030 #if LWIP_IPV4
1031 static err_t
1032 netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr)
1033 {
1034 LWIP_UNUSED_ARG(addr);
1035 return netif_loop_output(netif, p);
1036 }
1037 #endif /* LWIP_IPV4 */
1038  
1039 #if LWIP_IPV6
1040 static err_t
1041 netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr)
1042 {
1043 LWIP_UNUSED_ARG(addr);
1044 return netif_loop_output(netif, p);
1045 }
1046 #endif /* LWIP_IPV6 */
1047 #endif /* LWIP_HAVE_LOOPIF */
1048  
1049  
1050 /**
1051 * Call netif_poll() in the main loop of your application. This is to prevent
1052 * reentering non-reentrant functions like tcp_input(). Packets passed to
1053 * netif_loop_output() are put on a list that is passed to netif->input() by
1054 * netif_poll().
1055 */
1056 void
1057 netif_poll(struct netif *netif)
1058 {
1059 /* If we have a loopif, SNMP counters are adjusted for it,
1060 * if not they are adjusted for 'netif'. */
1061 #if MIB2_STATS
1062 #if LWIP_HAVE_LOOPIF
1063 struct netif *stats_if = &loop_netif;
1064 #else /* LWIP_HAVE_LOOPIF */
1065 struct netif *stats_if = netif;
1066 #endif /* LWIP_HAVE_LOOPIF */
1067 #endif /* MIB2_STATS */
1068 SYS_ARCH_DECL_PROTECT(lev);
1069  
1070 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
1071 SYS_ARCH_PROTECT(lev);
1072 while (netif->loop_first != NULL) {
1073 struct pbuf *in, *in_end;
1074 #if LWIP_LOOPBACK_MAX_PBUFS
1075 u8_t clen = 1;
1076 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
1077  
1078 in = in_end = netif->loop_first;
1079 while (in_end->len != in_end->tot_len) {
1080 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
1081 in_end = in_end->next;
1082 #if LWIP_LOOPBACK_MAX_PBUFS
1083 clen++;
1084 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
1085 }
1086 #if LWIP_LOOPBACK_MAX_PBUFS
1087 /* adjust the number of pbufs on queue */
1088 LWIP_ASSERT("netif->loop_cnt_current underflow",
1089 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
1090 netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current - clen);
1091 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
1092  
1093 /* 'in_end' now points to the last pbuf from 'in' */
1094 if (in_end == netif->loop_last) {
1095 /* this was the last pbuf in the list */
1096 netif->loop_first = netif->loop_last = NULL;
1097 } else {
1098 /* pop the pbuf off the list */
1099 netif->loop_first = in_end->next;
1100 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
1101 }
1102 /* De-queue the pbuf from its successors on the 'loop_' list. */
1103 in_end->next = NULL;
1104 SYS_ARCH_UNPROTECT(lev);
1105  
1106 in->if_idx = netif_get_index(netif);
1107  
1108 LINK_STATS_INC(link.recv);
1109 MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
1110 MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
1111 /* loopback packets are always IP packets! */
1112 if (ip_input(in, netif) != ERR_OK) {
1113 pbuf_free(in);
1114 }
1115 SYS_ARCH_PROTECT(lev);
1116 }
1117 SYS_ARCH_UNPROTECT(lev);
1118 }
1119  
1120 #if !LWIP_NETIF_LOOPBACK_MULTITHREADING
1121 /**
1122 * Calls netif_poll() for every netif on the netif_list.
1123 */
1124 void
1125 netif_poll_all(void)
1126 {
1127 struct netif *netif;
1128 /* loop through netifs */
1129 NETIF_FOREACH(netif) {
1130 netif_poll(netif);
1131 }
1132 }
1133 #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
1134 #endif /* ENABLE_LOOPBACK */
1135  
1136 #if LWIP_NUM_NETIF_CLIENT_DATA > 0
1137 /**
1138 * @ingroup netif_cd
1139 * Allocate an index to store data in client_data member of struct netif.
1140 * Returned value is an index in mentioned array.
1141 * @see LWIP_NUM_NETIF_CLIENT_DATA
1142 */
1143 u8_t
1144 netif_alloc_client_data_id(void)
1145 {
1146 u8_t result = netif_client_id;
1147 netif_client_id++;
1148  
1149 #if LWIP_NUM_NETIF_CLIENT_DATA > 256
1150 #error LWIP_NUM_NETIF_CLIENT_DATA must be <= 256
1151 #endif
1152 LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA);
1153 return (u8_t)(result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX);
1154 }
1155 #endif
1156  
1157 #if LWIP_IPV6
1158 /**
1159 * @ingroup netif_ip6
1160 * Change an IPv6 address of a network interface
1161 *
1162 * @param netif the network interface to change
1163 * @param addr_idx index of the IPv6 address
1164 * @param addr6 the new IPv6 address
1165 *
1166 * @note call netif_ip6_addr_set_state() to set the address valid/temptative
1167 */
1168 void
1169 netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6)
1170 {
1171 LWIP_ASSERT("addr6 != NULL", addr6 != NULL);
1172 netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1],
1173 addr6->addr[2], addr6->addr[3]);
1174 }
1175  
1176 /*
1177 * Change an IPv6 address of a network interface (internal version taking 4 * u32_t)
1178 *
1179 * @param netif the network interface to change
1180 * @param addr_idx index of the IPv6 address
1181 * @param i0 word0 of the new IPv6 address
1182 * @param i1 word1 of the new IPv6 address
1183 * @param i2 word2 of the new IPv6 address
1184 * @param i3 word3 of the new IPv6 address
1185 */
1186 void
1187 netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3)
1188 {
1189 ip_addr_t old_addr;
1190 ip_addr_t new_ipaddr;
1191 LWIP_ASSERT("netif != NULL", netif != NULL);
1192 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES);
1193  
1194 ip6_addr_copy(*ip_2_ip6(&old_addr), *netif_ip6_addr(netif, addr_idx));
1195 IP_SET_TYPE_VAL(old_addr, IPADDR_TYPE_V6);
1196  
1197 /* address is actually being changed? */
1198 if ((ip_2_ip6(&old_addr)->addr[0] != i0) || (ip_2_ip6(&old_addr)->addr[1] != i1) ||
1199 (ip_2_ip6(&old_addr)->addr[2] != i2) || (ip_2_ip6(&old_addr)->addr[3] != i3)) {
1200 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n"));
1201  
1202 IP_ADDR6(&new_ipaddr, i0, i1, i2, i3);
1203 ip6_addr_assign_zone(ip_2_ip6(&new_ipaddr), IP6_UNICAST, netif);
1204  
1205 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) {
1206 #if LWIP_TCP
1207 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1208 #endif /* LWIP_TCP */
1209 #if LWIP_UDP
1210 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1211 #endif /* LWIP_UDP */
1212 #if LWIP_RAW
1213 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1214 #endif /* LWIP_RAW */
1215 }
1216 /* @todo: remove/readd mib2 ip6 entries? */
1217  
1218 ip_addr_copy(netif->ip6_addr[addr_idx], new_ipaddr);
1219  
1220 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) {
1221 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6);
1222 NETIF_STATUS_CALLBACK(netif);
1223 }
1224  
1225 #if LWIP_NETIF_EXT_STATUS_CALLBACK
1226 {
1227 netif_ext_callback_args_t args;
1228 args.ipv6_set.addr_index = addr_idx;
1229 args.ipv6_set.old_address = &old_addr;
1230 netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_SET, &args);
1231 }
1232 #endif
1233 }
1234  
1235 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n",
1236 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)),
1237 netif_ip6_addr_state(netif, addr_idx)));
1238 }
1239  
1240 /**
1241 * @ingroup netif_ip6
1242 * Change the state of an IPv6 address of a network interface
1243 * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE
1244 * includes the number of checks done, see ip6_addr.h)
1245 *
1246 * @param netif the network interface to change
1247 * @param addr_idx index of the IPv6 address
1248 * @param state the new IPv6 address state
1249 */
1250 void
1251 netif_ip6_addr_set_state(struct netif *netif, s8_t addr_idx, u8_t state)
1252 {
1253 u8_t old_state;
1254 LWIP_ASSERT("netif != NULL", netif != NULL);
1255 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES);
1256  
1257 old_state = netif_ip6_addr_state(netif, addr_idx);
1258 /* state is actually being changed? */
1259 if (old_state != state) {
1260 u8_t old_valid = old_state & IP6_ADDR_VALID;
1261 u8_t new_valid = state & IP6_ADDR_VALID;
1262 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
1263  
1264 #if LWIP_IPV6_MLD
1265 /* Reevaluate solicited-node multicast group membership. */
1266 if (netif->flags & NETIF_FLAG_MLD6) {
1267 nd6_adjust_mld_membership(netif, addr_idx, state);
1268 }
1269 #endif /* LWIP_IPV6_MLD */
1270  
1271 if (old_valid && !new_valid) {
1272 /* address about to be removed by setting invalid */
1273 #if LWIP_TCP
1274 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1275 #endif /* LWIP_TCP */
1276 #if LWIP_UDP
1277 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1278 #endif /* LWIP_UDP */
1279 #if LWIP_RAW
1280 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1281 #endif /* LWIP_RAW */
1282 /* @todo: remove mib2 ip6 entries? */
1283 }
1284 netif->ip6_addr_state[addr_idx] = state;
1285  
1286 if (!old_valid && new_valid) {
1287 /* address added by setting valid */
1288 /* This is a good moment to check that the address is properly zoned. */
1289 IP6_ADDR_ZONECHECK_NETIF(netif_ip6_addr(netif, addr_idx), netif);
1290 /* @todo: add mib2 ip6 entries? */
1291 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6);
1292 }
1293 if ((old_state & ~IP6_ADDR_TENTATIVE_COUNT_MASK) !=
1294 (state & ~IP6_ADDR_TENTATIVE_COUNT_MASK)) {
1295 /* address state has changed -> call the callback function */
1296 NETIF_STATUS_CALLBACK(netif);
1297 }
1298 }
1299  
1300 #if LWIP_NETIF_EXT_STATUS_CALLBACK
1301 {
1302 netif_ext_callback_args_t args;
1303 args.ipv6_addr_state_changed.addr_index = addr_idx;
1304 args.ipv6_addr_state_changed.address = netif_ip_addr6(netif, addr_idx);
1305 netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_ADDR_STATE_CHANGED, &args);
1306 }
1307 #endif
1308  
1309 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n",
1310 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)),
1311 netif_ip6_addr_state(netif, addr_idx)));
1312 }
1313  
1314 /**
1315 * Checks if a specific local address is present on the netif and returns its
1316 * index. Depending on its state, it may or may not be assigned to the
1317 * interface (as per RFC terminology).
1318 *
1319 * The given address may or may not be zoned (i.e., have a zone index other
1320 * than IP6_NO_ZONE). If the address is zoned, it must have the correct zone
1321 * for the given netif, or no match will be found.
1322 *
1323 * @param netif the netif to check
1324 * @param ip6addr the IPv6 address to find
1325 * @return >= 0: address found, this is its index
1326 * -1: address not found on this netif
1327 */
1328 s8_t
1329 netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr)
1330 {
1331 s8_t i;
1332  
1333 #if LWIP_IPV6_SCOPES
1334 if (ip6_addr_has_zone(ip6addr) && !ip6_addr_test_zone(ip6addr, netif)) {
1335 return -1; /* wrong zone, no match */
1336 }
1337 #endif /* LWIP_IPV6_SCOPES */
1338  
1339 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1340 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
1341 ip6_addr_cmp_zoneless(netif_ip6_addr(netif, i), ip6addr)) {
1342 return i;
1343 }
1344 }
1345 return -1;
1346 }
1347  
1348 /**
1349 * @ingroup netif_ip6
1350 * Create a link-local IPv6 address on a netif (stored in slot 0)
1351 *
1352 * @param netif the netif to create the address on
1353 * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion)
1354 * if == 0, use hwaddr directly as interface ID
1355 */
1356 void
1357 netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
1358 {
1359 u8_t i, addr_index;
1360  
1361 /* Link-local prefix. */
1362 ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul);
1363 ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0;
1364  
1365 /* Generate interface ID. */
1366 if (from_mac_48bit) {
1367 /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
1368 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
1369 ((u32_t)(netif->hwaddr[1]) << 16) |
1370 ((u32_t)(netif->hwaddr[2]) << 8) |
1371 (0xff));
1372 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((u32_t)(0xfeul << 24) |
1373 ((u32_t)(netif->hwaddr[3]) << 16) |
1374 ((u32_t)(netif->hwaddr[4]) << 8) |
1375 (netif->hwaddr[5]));
1376 } else {
1377 /* Use hwaddr directly as interface ID. */
1378 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0;
1379 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0;
1380  
1381 addr_index = 3;
1382 for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) {
1383 if (i == 4) {
1384 addr_index--;
1385 }
1386 ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03));
1387 }
1388 }
1389  
1390 /* Set a link-local zone. Even though the zone is implied by the owning
1391 * netif, setting the zone anyway has two important conceptual advantages:
1392 * 1) it avoids the need for a ton of exceptions in internal code, allowing
1393 * e.g. ip6_addr_cmp() to be used on local addresses;
1394 * 2) the properly zoned address is visible externally, e.g. when any outside
1395 * code enumerates available addresses or uses one to bind a socket.
1396 * Any external code unaware of address scoping is likely to just ignore the
1397 * zone field, so this should not create any compatibility problems. */
1398 ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[0]), IP6_UNICAST, netif);
1399  
1400 /* Set address state. */
1401 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1402 /* Will perform duplicate address detection (DAD). */
1403 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE);
1404 #else
1405 /* Consider address valid. */
1406 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
1407 #endif /* LWIP_IPV6_AUTOCONFIG */
1408 }
1409  
1410 /**
1411 * @ingroup netif_ip6
1412 * This function allows for the easy addition of a new IPv6 address to an interface.
1413 * It takes care of finding an empty slot and then sets the address tentative
1414 * (to make sure that all the subsequent processing happens).
1415 *
1416 * @param netif netif to add the address on
1417 * @param ip6addr address to add
1418 * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here
1419 */
1420 err_t
1421 netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx)
1422 {
1423 s8_t i;
1424  
1425 i = netif_get_ip6_addr_match(netif, ip6addr);
1426 if (i >= 0) {
1427 /* Address already added */
1428 if (chosen_idx != NULL) {
1429 *chosen_idx = i;
1430 }
1431 return ERR_OK;
1432 }
1433  
1434 /* Find a free slot. The first one is reserved for link-local addresses. */
1435 for (i = ip6_addr_islinklocal(ip6addr) ? 0 : 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1436 if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
1437 ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
1438 ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[i]), IP6_UNICAST, netif);
1439 netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
1440 if (chosen_idx != NULL) {
1441 *chosen_idx = i;
1442 }
1443 return ERR_OK;
1444 }
1445 }
1446  
1447 if (chosen_idx != NULL) {
1448 *chosen_idx = -1;
1449 }
1450 return ERR_VAL;
1451 }
1452  
1453 /** Dummy IPv6 output function for netifs not supporting IPv6
1454 */
1455 static err_t
1456 netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr)
1457 {
1458 LWIP_UNUSED_ARG(netif);
1459 LWIP_UNUSED_ARG(p);
1460 LWIP_UNUSED_ARG(ipaddr);
1461  
1462 return ERR_IF;
1463 }
1464 #endif /* LWIP_IPV6 */
1465  
1466 /**
1467 * @ingroup netif
1468 * Return the interface index for the netif with name
1469 * or NETIF_NO_INDEX if not found/on error
1470 *
1471 * @param name the name of the netif
1472 */
1473 u8_t
1474 netif_name_to_index(const char *name)
1475 {
1476 struct netif *netif = netif_find(name);
1477 if (netif != NULL) {
1478 return netif_get_index(netif);
1479 }
1480 /* No name found, return invalid index */
1481 return NETIF_NO_INDEX;
1482 }
1483  
1484 /**
1485 * @ingroup netif
1486 * Return the interface name for the netif matching index
1487 * or NULL if not found/on error
1488 *
1489 * @param idx the interface index of the netif
1490 * @param name char buffer of at least NETIF_NAMESIZE bytes
1491 */
1492 char *
1493 netif_index_to_name(u8_t idx, char *name)
1494 {
1495 struct netif *netif = netif_get_by_index(idx);
1496  
1497 if (netif != NULL) {
1498 name[0] = netif->name[0];
1499 name[1] = netif->name[1];
1500 lwip_itoa(&name[2], NETIF_NAMESIZE - 2, netif_index_to_num(idx));
1501 return name;
1502 }
1503 return NULL;
1504 }
1505  
1506 /**
1507 * @ingroup netif
1508 * Return the interface for the netif index
1509 *
1510 * @param idx index of netif to find
1511 */
1512 struct netif *
1513 netif_get_by_index(u8_t idx)
1514 {
1515 struct netif *netif;
1516  
1517 if (idx != NETIF_NO_INDEX) {
1518 NETIF_FOREACH(netif) {
1519 if (idx == netif_get_index(netif)) {
1520 return netif; /* found! */
1521 }
1522 }
1523 }
1524  
1525 return NULL;
1526 }
1527  
1528 /**
1529 * @ingroup netif
1530 * Find a network interface by searching for its name
1531 *
1532 * @param name the name of the netif (like netif->name) plus concatenated number
1533 * in ascii representation (e.g. 'en0')
1534 */
1535 struct netif *
1536 netif_find(const char *name)
1537 {
1538 struct netif *netif;
1539 u8_t num;
1540  
1541 if (name == NULL) {
1542 return NULL;
1543 }
1544  
1545 num = (u8_t)atoi(&name[2]);
1546  
1547 NETIF_FOREACH(netif) {
1548 if (num == netif->num &&
1549 name[0] == netif->name[0] &&
1550 name[1] == netif->name[1]) {
1551 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));
1552 return netif;
1553 }
1554 }
1555 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
1556 return NULL;
1557 }
1558  
1559 #if LWIP_NETIF_EXT_STATUS_CALLBACK
1560 /**
1561 * @ingroup netif
1562 * Add extended netif events listener
1563 * @param callback pointer to listener structure
1564 * @param fn callback function
1565 */
1566 void netif_add_ext_callback(netif_ext_callback_t *callback, netif_ext_callback_fn fn)
1567 {
1568 LWIP_ASSERT("callback must be != NULL", callback != NULL);
1569 LWIP_ASSERT("fn must be != NULL", fn != NULL);
1570  
1571 callback->callback_fn = fn;
1572 callback->next = ext_callback;
1573 ext_callback = callback;
1574 }
1575  
1576 /**
1577 * Invoke extended netif status event
1578 * @param netif netif that is affected by change
1579 * @param reason change reason
1580 * @param args depends on reason, see reason description
1581 */
1582 void netif_invoke_ext_callback(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args)
1583 {
1584 netif_ext_callback_t *callback = ext_callback;
1585  
1586 LWIP_ASSERT("netif must be != NULL", netif != NULL);
1587  
1588 while (callback != NULL) {
1589 callback->callback_fn(netif, reason, args);
1590 callback = callback->next;
1591 }
1592 }
1593 #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */