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>
54#include <net/net.h>
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
105struct netif *netif_list;
106struct netif *netif_default;
107
108static u8_t netif_num;
109
110#if LWIP_NUM_NETIF_CLIENT_DATA > 0
111static u8_t netif_client_id;
112#endif
113
114#define NETIF_REPORT_TYPE_IPV4  0x01
115#define NETIF_REPORT_TYPE_IPV6  0x02
116static void netif_issue_reports(struct netif* netif, u8_t report_type);
117
118#if LWIP_IPV6
119static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr);
120#endif /* LWIP_IPV6 */
121
122#if LWIP_HAVE_LOOPIF
123#if LWIP_IPV4
124static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr);
125#endif
126#if LWIP_IPV6
127static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr);
128#endif
129
130
131static struct netif loop_netif;
132
133/**
134 * Initialize a lwip network interface structure for a loopback interface
135 *
136 * @param netif the lwip network interface structure for this loopif
137 * @return ERR_OK if the loopif is initialized
138 *         ERR_MEM if private data couldn't be allocated
139 */
140static err_t
141netif_loopif_init(struct netif *netif)
142{
143  /* initialize the snmp variables and counters inside the struct netif
144   * ifSpeed: no assumption can be made!
145   */
146  MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0);
147
148  netif->name[0] = 'l';
149  netif->name[1] = 'o';
150#if LWIP_IPV4
151  netif->output = netif_loop_output_ipv4;
152#endif
153#if LWIP_IPV6
154  netif->output_ip6 = netif_loop_output_ipv6;
155#endif
156#if LWIP_LOOPIF_MULTICAST
157  netif->flags |= NETIF_FLAG_IGMP;
158#endif
159  return ERR_OK;
160}
161#endif /* LWIP_HAVE_LOOPIF */
162
163void
164netif_init(void)
165{
166#if LWIP_HAVE_LOOPIF
167#if LWIP_IPV4
168#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw,
169  ip4_addr_t loop_ipaddr, loop_netmask, loop_gw;
170  IP4_ADDR(&loop_gw, 127,0,0,1);
171  IP4_ADDR(&loop_ipaddr, 127,0,0,1);
172  IP4_ADDR(&loop_netmask, 255,0,0,0);
173#else /* LWIP_IPV4 */
174#define LOOPIF_ADDRINIT
175#endif /* LWIP_IPV4 */
176
177#if NO_SYS
178  netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input);
179#else  /* NO_SYS */
180  netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input);
181#endif /* NO_SYS */
182
183#if LWIP_IPV6
184  IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
185  loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
186#endif /* LWIP_IPV6 */
187
188  netif_set_link_up(&loop_netif);
189  netif_set_up(&loop_netif);
190
191#endif /* LWIP_HAVE_LOOPIF */
192}
193
194/**
195 * @ingroup lwip_nosys
196 * Forwards a received packet for input processing with
197 * ethernet_input() or ip_input() depending on netif flags.
198 * Don't call directly, pass to netif_add() and call
199 * netif->input().
200 * Only works if the netif driver correctly sets
201 * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag!
202 */
203err_t
204netif_input(struct pbuf *p, struct netif *inp)
205{
206#if LWIP_ETHERNET
207  if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
208    return ethernet_input(p, inp);
209  } else
210#endif /* LWIP_ETHERNET */
211  return ip_input(p, inp);
212}
213
214/**
215 * @ingroup netif
216 * Add a network interface to the list of lwIP netifs.
217 *
218 * @param netif a pre-allocated netif structure
219 * @param ipaddr IP address for the new netif
220 * @param netmask network mask for the new netif
221 * @param gw default gateway IP address for the new netif
222 * @param state opaque data passed to the new netif
223 * @param init callback function that initializes the interface
224 * @param input callback function that is called to pass
225 * ingress packets up in the protocol layer stack.\n
226 * It is recommended to use a function that passes the input directly
227 * to the stack (netif_input(), NO_SYS=1 mode) or via sending a
228 * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n
229 * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET
230 * to decide whether to forward to ethernet_input() or ip_input().
231 * In other words, the functions only work when the netif
232 * driver is implemented correctly!\n
233 * Most members of struct netif should be be initialized by the
234 * netif init function = netif driver (init parameter of this function).\n
235 * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after
236 * setting the MAC address in struct netif.hwaddr
237 * (IPv6 requires a link-local address).
238 *
239 * @return netif, or NULL if failed.
240 */
241struct netif *
242netif_add(struct netif *netif,
243#if LWIP_IPV4
244          const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
245#endif /* LWIP_IPV4 */
246          void *state, netif_init_fn init, netif_input_fn input)
247{
248#if LWIP_IPV6
249  s8_t i;
250#endif
251
252  LWIP_ASSERT("No init function given", init != NULL);
253
254  /* reset new interface configuration state */
255#if LWIP_IPV4
256  ip_addr_set_zero_ip4(&netif->ip_addr);
257  ip_addr_set_zero_ip4(&netif->netmask);
258  ip_addr_set_zero_ip4(&netif->gw);
259#endif /* LWIP_IPV4 */
260#if LWIP_IPV6
261  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
262    ip_addr_set_zero_ip6(&netif->ip6_addr[i]);
263    netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
264  }
265  netif->output_ip6 = netif_null_output_ip6;
266#endif /* LWIP_IPV6 */
267  NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL);
268  netif->flags = 0;
269#ifdef netif_get_client_data
270  memset(netif->client_data, 0, sizeof(netif->client_data));
271#endif /* LWIP_NUM_NETIF_CLIENT_DATA */
272#if LWIP_IPV6_AUTOCONFIG
273  /* IPv6 address autoconfiguration not enabled by default */
274  netif->ip6_autoconfig_enabled = 0;
275#endif /* LWIP_IPV6_AUTOCONFIG */
276#if LWIP_IPV6_SEND_ROUTER_SOLICIT
277  netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
278#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
279#if LWIP_NETIF_STATUS_CALLBACK
280  netif->status_callback = NULL;
281#endif /* LWIP_NETIF_STATUS_CALLBACK */
282#if LWIP_NETIF_LINK_CALLBACK
283  netif->link_callback = NULL;
284#endif /* LWIP_NETIF_LINK_CALLBACK */
285#if LWIP_IGMP
286  netif->igmp_mac_filter = NULL;
287#endif /* LWIP_IGMP */
288#if LWIP_IPV6 && LWIP_IPV6_MLD
289  netif->mld_mac_filter = NULL;
290#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
291#if ENABLE_LOOPBACK
292  netif->loop_first = NULL;
293  netif->loop_last = NULL;
294#endif /* ENABLE_LOOPBACK */
295
296  /* remember netif specific state information data */
297  netif->state = state;
298  netif->num = netif_num++;
299  netif->input = input;
300
301  NETIF_SET_HWADDRHINT(netif, NULL);
302#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
303  netif->loop_cnt_current = 0;
304#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
305
306#if LWIP_IPV4
307  netif_set_addr(netif, ipaddr, netmask, gw);
308#endif /* LWIP_IPV4 */
309
310  /* call user specified initialization function for netif */
311  if (init(netif) != ERR_OK) {
312    return NULL;
313  }
314
315  /* add this netif to the list */
316  netif->next = netif_list;
317  netif_list = netif;
318  mib2_netif_added(netif);
319
320#if LWIP_IGMP
321  /* start IGMP processing */
322  if (netif->flags & NETIF_FLAG_IGMP) {
323    igmp_start(netif);
324  }
325#endif /* LWIP_IGMP */
326
327  LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP",
328    netif->name[0], netif->name[1]));
329#if LWIP_IPV4
330  LWIP_DEBUGF(NETIF_DEBUG, (" addr "));
331  ip4_addr_debug_print(NETIF_DEBUG, ipaddr);
332  LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
333  ip4_addr_debug_print(NETIF_DEBUG, netmask);
334  LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
335  ip4_addr_debug_print(NETIF_DEBUG, gw);
336#endif /* LWIP_IPV4 */
337  LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
338  return netif;
339}
340
341#if LWIP_IPV4
342/**
343 * @ingroup netif_ip4
344 * Change IP address configuration for a network interface (including netmask
345 * and default gateway).
346 *
347 * @param netif the network interface to change
348 * @param ipaddr the new IP address
349 * @param netmask the new netmask
350 * @param gw the new default gateway
351 */
352void
353netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
354    const ip4_addr_t *gw)
355{
356  if (ip4_addr_isany(ipaddr)) {
357    /* when removing an address, we have to remove it *before* changing netmask/gw
358       to ensure that tcp RST segment can be sent correctly */
359    netif_set_ipaddr(netif, ipaddr);
360    netif_set_netmask(netif, netmask);
361    netif_set_gw(netif, gw);
362  } else {
363    netif_set_netmask(netif, netmask);
364    netif_set_gw(netif, gw);
365    /* set ipaddr last to ensure netmask/gw have been set when status callback is called */
366    netif_set_ipaddr(netif, ipaddr);
367  }
368}
369#endif /* LWIP_IPV4*/
370
371/**
372 * @ingroup netif
373 * Remove a network interface from the list of lwIP netifs.
374 *
375 * @param netif the network interface to remove
376 */
377void
378netif_remove(struct netif *netif)
379{
380#if LWIP_IPV6
381  int i;
382#endif
383
384  if (netif == NULL) {
385    return;
386  }
387
388#if LWIP_IPV4
389  if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
390#if LWIP_TCP
391    tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
392#endif /* LWIP_TCP */
393#if LWIP_UDP
394    udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
395#endif /* LWIP_UDP */
396#if LWIP_RAW
397    raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
398#endif /* LWIP_RAW */
399  }
400
401#if LWIP_IGMP
402  /* stop IGMP processing */
403  if (netif->flags & NETIF_FLAG_IGMP) {
404    igmp_stop(netif);
405  }
406#endif /* LWIP_IGMP */
407#endif /* LWIP_IPV4*/
408
409#if LWIP_IPV6
410  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
411    if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
412#if LWIP_TCP
413      tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
414#endif /* LWIP_TCP */
415#if LWIP_UDP
416      udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
417#endif /* LWIP_UDP */
418#if LWIP_RAW
419      raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
420#endif /* LWIP_RAW */
421    }
422  }
423#if LWIP_IPV6_MLD
424  /* stop MLD processing */
425  mld6_stop(netif);
426#endif /* LWIP_IPV6_MLD */
427#endif /* LWIP_IPV6 */
428  if (netif_is_up(netif)) {
429    /* set netif down before removing (call callback function) */
430    netif_set_down(netif);
431  }
432
433  mib2_remove_ip4(netif);
434
435  /* this netif is default? */
436  if (netif_default == netif) {
437    /* reset default netif */
438    netif_set_default(NULL);
439  }
440  /*  is it the first netif? */
441  if (netif_list == netif) {
442    netif_list = netif->next;
443  } else {
444    /*  look for netif further down the list */
445    struct netif * tmp_netif;
446    for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) {
447      if (tmp_netif->next == netif) {
448        tmp_netif->next = netif->next;
449        break;
450      }
451    }
452    if (tmp_netif == NULL) {
453      return; /* netif is not on the list */
454    }
455  }
456  mib2_netif_removed(netif);
457#if LWIP_NETIF_REMOVE_CALLBACK
458  if (netif->remove_callback) {
459    netif->remove_callback(netif);
460  }
461#endif /* LWIP_NETIF_REMOVE_CALLBACK */
462  LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
463}
464
465/**
466 * @ingroup netif
467 * Find a network interface by searching for its name
468 *
469 * @param name the name of the netif (like netif->name) plus concatenated number
470 * in ascii representation (e.g. 'en0')
471 */
472struct netif *
473netif_find(const char *name)
474{
475  struct netif *netif;
476  u8_t num;
477
478  if (name == NULL) {
479    return NULL;
480  }
481
482  num = (u8_t)(name[2] - '0');
483
484  for (netif = netif_list; netif != NULL; netif = netif->next) {
485    if (num == netif->num &&
486       name[0] == netif->name[0] &&
487       name[1] == netif->name[1]) {
488      LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));
489      return netif;
490    }
491  }
492  LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
493  return NULL;
494}
495
496#if LWIP_IPV4
497/**
498 * @ingroup netif_ip4
499 * Change the IP address of a network interface
500 *
501 * @param netif the network interface to change
502 * @param ipaddr the new IP address
503 *
504 * @note call netif_set_addr() if you also want to change netmask and
505 * default gateway
506 */
507void
508netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
509{
510  ip_addr_t new_addr;
511  *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4);
512  IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4);
513
514  /* address is actually being changed? */
515  if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) {
516    LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
517#if LWIP_TCP
518    tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
519#endif /* LWIP_TCP */
520#if LWIP_UDP
521    udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
522#endif /* LWIP_UDP */
523#if LWIP_RAW
524    raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
525#endif /* LWIP_RAW */
526
527    mib2_remove_ip4(netif);
528    mib2_remove_route_ip4(0, netif);
529    /* set new IP address to netif */
530    ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr);
531    IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4);
532    mib2_add_ip4(netif);
533    mib2_add_route_ip4(0, netif);
534
535    netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4);
536
537    NETIF_STATUS_CALLBACK(netif);
538  }
539
540  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",
541    netif->name[0], netif->name[1],
542    ip4_addr1_16(netif_ip4_addr(netif)),
543    ip4_addr2_16(netif_ip4_addr(netif)),
544    ip4_addr3_16(netif_ip4_addr(netif)),
545    ip4_addr4_16(netif_ip4_addr(netif))));
546}
547
548/**
549 * @ingroup netif_ip4
550 * Change the default gateway for a network interface
551 *
552 * @param netif the network interface to change
553 * @param gw the new default gateway
554 *
555 * @note call netif_set_addr() if you also want to change ip address and netmask
556 */
557void
558netif_set_gw(struct netif *netif, const ip4_addr_t *gw)
559{
560  ip4_addr_set(ip_2_ip4(&netif->gw), gw);
561  IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4);
562  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",
563    netif->name[0], netif->name[1],
564    ip4_addr1_16(netif_ip4_gw(netif)),
565    ip4_addr2_16(netif_ip4_gw(netif)),
566    ip4_addr3_16(netif_ip4_gw(netif)),
567    ip4_addr4_16(netif_ip4_gw(netif))));
568}
569
570/**
571 * @ingroup netif_ip4
572 * Change the netmask of a network interface
573 *
574 * @param netif the network interface to change
575 * @param netmask the new netmask
576 *
577 * @note call netif_set_addr() if you also want to change ip address and
578 * default gateway
579 */
580void
581netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask)
582{
583  mib2_remove_route_ip4(0, netif);
584  /* set new netmask to netif */
585  ip4_addr_set(ip_2_ip4(&netif->netmask), netmask);
586  IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4);
587  mib2_add_route_ip4(0, netif);
588  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",
589    netif->name[0], netif->name[1],
590    ip4_addr1_16(netif_ip4_netmask(netif)),
591    ip4_addr2_16(netif_ip4_netmask(netif)),
592    ip4_addr3_16(netif_ip4_netmask(netif)),
593    ip4_addr4_16(netif_ip4_netmask(netif))));
594}
595#endif /* LWIP_IPV4 */
596
597/**
598 * @ingroup netif
599 * Set a network interface as the default network interface
600 * (used to output all packets for which no specific route is found)
601 *
602 * @param netif the default network interface
603 */
604void
605netif_set_default(struct netif *netif)
606{
607  if (netif == NULL) {
608    /* remove default route */
609    mib2_remove_route_ip4(1, netif);
610  } else {
611    /* install default route */
612    mib2_add_route_ip4(1, netif);
613  }
614  netif_default = netif;
615  LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
616           netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
617}
618
619/**
620 * @ingroup netif
621 * Bring an interface up, available for processing
622 * traffic.
623 */
624void
625netif_set_up(struct netif *netif)
626{
627  if (!(netif->flags & NETIF_FLAG_UP)) {
628    netif->flags |= NETIF_FLAG_UP;
629
630    MIB2_COPY_SYSUPTIME_TO(&netif->ts);
631
632    NETIF_STATUS_CALLBACK(netif);
633
634    if (netif->flags & NETIF_FLAG_LINK_UP) {
635      netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6);
636    }
637  }
638}
639
640/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change
641 */
642static void
643netif_issue_reports(struct netif* netif, u8_t report_type)
644{
645#if LWIP_IPV4
646  if ((report_type & NETIF_REPORT_TYPE_IPV4) &&
647      !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
648#if LWIP_ARP
649    /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
650    if (netif->flags & (NETIF_FLAG_ETHARP)) {
651      etharp_gratuitous(netif);
652    }
653#endif /* LWIP_ARP */
654
655#if LWIP_IGMP
656    /* resend IGMP memberships */
657    if (netif->flags & NETIF_FLAG_IGMP) {
658      igmp_report_groups(netif);
659    }
660#endif /* LWIP_IGMP */
661  }
662#endif /* LWIP_IPV4 */
663
664#if LWIP_IPV6
665  if (report_type & NETIF_REPORT_TYPE_IPV6) {
666#if LWIP_IPV6_MLD
667    /* send mld memberships */
668    mld6_report_groups(netif);
669#endif /* LWIP_IPV6_MLD */
670#if LWIP_IPV6_SEND_ROUTER_SOLICIT
671    /* Send Router Solicitation messages. */
672    netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
673#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
674  }
675#endif /* LWIP_IPV6 */
676}
677
678/**
679 * @ingroup netif
680 * Bring an interface down, disabling any traffic processing.
681 */
682void
683netif_set_down(struct netif *netif)
684{
685  if (netif->flags & NETIF_FLAG_UP) {
686    netif->flags &= ~NETIF_FLAG_UP;
687    MIB2_COPY_SYSUPTIME_TO(&netif->ts);
688
689#if LWIP_IPV4 && LWIP_ARP
690    if (netif->flags & NETIF_FLAG_ETHARP) {
691      etharp_cleanup_netif(netif);
692    }
693#endif /* LWIP_IPV4 && LWIP_ARP */
694
695#if LWIP_IPV6
696    nd6_cleanup_netif(netif);
697#endif /* LWIP_IPV6 */
698
699    NETIF_STATUS_CALLBACK(netif);
700  }
701}
702
703#if LWIP_NETIF_STATUS_CALLBACK
704/**
705 * @ingroup netif
706 * Set callback to be called when interface is brought up/down or address is changed while up
707 */
708void
709netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
710{
711  if (netif) {
712    netif->status_callback = status_callback;
713  }
714}
715#endif /* LWIP_NETIF_STATUS_CALLBACK */
716
717#if LWIP_NETIF_REMOVE_CALLBACK
718/**
719 * @ingroup netif
720 * Set callback to be called when the interface has been removed
721 */
722void
723netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback)
724{
725  if (netif) {
726    netif->remove_callback = remove_callback;
727  }
728}
729#endif /* LWIP_NETIF_REMOVE_CALLBACK */
730
731/**
732 * @ingroup netif
733 * Called by a driver when its link goes up
734 */
735void
736netif_set_link_up(struct netif *netif)
737{
738  if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
739    netif->flags |= NETIF_FLAG_LINK_UP;
740
741#if LWIP_DHCP
742    dhcp_network_changed(netif);
743#endif /* LWIP_DHCP */
744
745#if LWIP_AUTOIP
746    autoip_network_changed(netif);
747#endif /* LWIP_AUTOIP */
748
749    if (netif->flags & NETIF_FLAG_UP) {
750      netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6);
751    }
752    NETIF_LINK_CALLBACK(netif);
753  }
754}
755
756/**
757 * @ingroup netif
758 * Called by a driver when its link goes down
759 */
760void
761netif_set_link_down(struct netif *netif )
762{
763  if (netif->flags & NETIF_FLAG_LINK_UP) {
764    netif->flags &= ~NETIF_FLAG_LINK_UP;
765    NETIF_LINK_CALLBACK(netif);
766  }
767}
768
769#if LWIP_NETIF_LINK_CALLBACK
770/**
771 * @ingroup netif
772 * Set callback to be called when link is brought up/down
773 */
774void
775netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
776{
777  if (netif) {
778    netif->link_callback = link_callback;
779  }
780}
781#endif /* LWIP_NETIF_LINK_CALLBACK */
782
783#if ENABLE_LOOPBACK
784/**
785 * @ingroup netif
786 * Send an IP packet to be received on the same netif (loopif-like).
787 * The pbuf is simply copied and handed back to netif->input.
788 * In multithreaded mode, this is done directly since netif->input must put
789 * the packet on a queue.
790 * In callback mode, the packet is put on an internal queue and is fed to
791 * netif->input by netif_poll().
792 *
793 * @param netif the lwip network interface structure
794 * @param p the (IP) packet to 'send'
795 * @return ERR_OK if the packet has been sent
796 *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
797 */
798err_t
799netif_loop_output(struct netif *netif, struct pbuf *p)
800{
801  struct pbuf *r;
802  err_t err;
803  struct pbuf *last;
804#if LWIP_LOOPBACK_MAX_PBUFS
805  u16_t clen = 0;
806#endif /* LWIP_LOOPBACK_MAX_PBUFS */
807  /* If we have a loopif, SNMP counters are adjusted for it,
808   * if not they are adjusted for 'netif'. */
809#if MIB2_STATS
810#if LWIP_HAVE_LOOPIF
811  struct netif *stats_if = &loop_netif;
812#else /* LWIP_HAVE_LOOPIF */
813  struct netif *stats_if = netif;
814#endif /* LWIP_HAVE_LOOPIF */
815#endif /* MIB2_STATS */
816  SYS_ARCH_DECL_PROTECT(lev);
817
818  /* Allocate a new pbuf */
819  r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
820  if (r == NULL) {
821    LINK_STATS_INC(link.memerr);
822    LINK_STATS_INC(link.drop);
823    MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
824    return ERR_MEM;
825  }
826#if LWIP_LOOPBACK_MAX_PBUFS
827  clen = pbuf_clen(r);
828  /* check for overflow or too many pbuf on queue */
829  if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
830     ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
831    pbuf_free(r);
832    LINK_STATS_INC(link.memerr);
833    LINK_STATS_INC(link.drop);
834    MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
835    return ERR_MEM;
836  }
837  netif->loop_cnt_current += clen;
838#endif /* LWIP_LOOPBACK_MAX_PBUFS */
839
840  /* Copy the whole pbuf queue p into the single pbuf r */
841  if ((err = pbuf_copy(r, p)) != ERR_OK) {
842    pbuf_free(r);
843    LINK_STATS_INC(link.memerr);
844    LINK_STATS_INC(link.drop);
845    MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
846    return err;
847  }
848
849  /* Put the packet on a linked list which gets emptied through calling
850     netif_poll(). */
851
852  /* let last point to the last pbuf in chain r */
853  for (last = r; last->next != NULL; last = last->next);
854
855  SYS_ARCH_PROTECT(lev);
856  if (netif->loop_first != NULL) {
857    LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
858    netif->loop_last->next = r;
859    netif->loop_last = last;
860  } else {
861    netif->loop_first = r;
862    netif->loop_last = last;
863  }
864  SYS_ARCH_UNPROTECT(lev);
865
866  LINK_STATS_INC(link.xmit);
867  MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len);
868  MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts);
869
870#if LWIP_NETIF_LOOPBACK_MULTITHREADING
871  /* For multithreading environment, schedule a call to netif_poll */
872  tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0);
873#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
874  net_if_trigger_loopback();
875
876  return ERR_OK;
877}
878
879#if LWIP_HAVE_LOOPIF
880#if LWIP_IPV4
881static err_t
882netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr)
883{
884  LWIP_UNUSED_ARG(addr);
885  return netif_loop_output(netif, p);
886}
887#endif /* LWIP_IPV4 */
888
889#if LWIP_IPV6
890static err_t
891netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr)
892{
893  LWIP_UNUSED_ARG(addr);
894  return netif_loop_output(netif, p);
895}
896#endif /* LWIP_IPV6 */
897#endif /* LWIP_HAVE_LOOPIF */
898
899
900/**
901 * Call netif_poll() in the main loop of your application. This is to prevent
902 * reentering non-reentrant functions like tcp_input(). Packets passed to
903 * netif_loop_output() are put on a list that is passed to netif->input() by
904 * netif_poll().
905 */
906void
907netif_poll(struct netif *netif)
908{
909  /* If we have a loopif, SNMP counters are adjusted for it,
910   * if not they are adjusted for 'netif'. */
911#if MIB2_STATS
912#if LWIP_HAVE_LOOPIF
913  struct netif *stats_if = &loop_netif;
914#else /* LWIP_HAVE_LOOPIF */
915  struct netif *stats_if = netif;
916#endif /* LWIP_HAVE_LOOPIF */
917#endif /* MIB2_STATS */
918  SYS_ARCH_DECL_PROTECT(lev);
919
920  /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
921  SYS_ARCH_PROTECT(lev);
922  while (netif->loop_first != NULL) {
923    struct pbuf *in, *in_end;
924#if LWIP_LOOPBACK_MAX_PBUFS
925    u8_t clen = 1;
926#endif /* LWIP_LOOPBACK_MAX_PBUFS */
927
928    in = in_end = netif->loop_first;
929    while (in_end->len != in_end->tot_len) {
930      LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
931      in_end = in_end->next;
932#if LWIP_LOOPBACK_MAX_PBUFS
933      clen++;
934#endif /* LWIP_LOOPBACK_MAX_PBUFS */
935    }
936#if LWIP_LOOPBACK_MAX_PBUFS
937    /* adjust the number of pbufs on queue */
938    LWIP_ASSERT("netif->loop_cnt_current underflow",
939      ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
940    netif->loop_cnt_current -= clen;
941#endif /* LWIP_LOOPBACK_MAX_PBUFS */
942
943    /* 'in_end' now points to the last pbuf from 'in' */
944    if (in_end == netif->loop_last) {
945      /* this was the last pbuf in the list */
946      netif->loop_first = netif->loop_last = NULL;
947    } else {
948      /* pop the pbuf off the list */
949      netif->loop_first = in_end->next;
950      LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
951    }
952    /* De-queue the pbuf from its successors on the 'loop_' list. */
953    in_end->next = NULL;
954    SYS_ARCH_UNPROTECT(lev);
955
956    LINK_STATS_INC(link.recv);
957    MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
958    MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
959    /* loopback packets are always IP packets! */
960    if (ip_input(in, netif) != ERR_OK) {
961      pbuf_free(in);
962    }
963    SYS_ARCH_PROTECT(lev);
964  }
965  SYS_ARCH_UNPROTECT(lev);
966}
967
968#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
969/**
970 * Calls netif_poll() for every netif on the netif_list.
971 */
972void
973netif_poll_all(void)
974{
975  struct netif *netif = netif_list;
976  /* loop through netifs */
977  while (netif != NULL) {
978    netif_poll(netif);
979    /* proceed to next network interface */
980    netif = netif->next;
981  }
982}
983#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
984#endif /* ENABLE_LOOPBACK */
985
986#if LWIP_NUM_NETIF_CLIENT_DATA > 0
987/**
988 * @ingroup netif_cd
989 * Allocate an index to store data in client_data member of struct netif.
990 * Returned value is an index in mentioned array.
991 * @see LWIP_NUM_NETIF_CLIENT_DATA
992 */
993u8_t
994netif_alloc_client_data_id(void)
995{
996  u8_t result = netif_client_id;
997  netif_client_id++;
998
999  LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA);
1000  return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX;
1001}
1002#endif
1003
1004#if LWIP_IPV6
1005/**
1006 * @ingroup netif_ip6
1007 * Change an IPv6 address of a network interface
1008 *
1009 * @param netif the network interface to change
1010 * @param addr_idx index of the IPv6 address
1011 * @param addr6 the new IPv6 address
1012 *
1013 * @note call netif_ip6_addr_set_state() to set the address valid/temptative
1014 */
1015void
1016netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6)
1017{
1018  LWIP_ASSERT("addr6 != NULL", addr6 != NULL);
1019  netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1],
1020    addr6->addr[2], addr6->addr[3]);
1021}
1022
1023/*
1024 * Change an IPv6 address of a network interface (internal version taking 4 * u32_t)
1025 *
1026 * @param netif the network interface to change
1027 * @param addr_idx index of the IPv6 address
1028 * @param i0 word0 of the new IPv6 address
1029 * @param i1 word1 of the new IPv6 address
1030 * @param i2 word2 of the new IPv6 address
1031 * @param i3 word3 of the new IPv6 address
1032 */
1033void
1034netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3)
1035{
1036  const ip6_addr_t *old_addr;
1037  LWIP_ASSERT("netif != NULL", netif != NULL);
1038  LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES);
1039
1040  old_addr = netif_ip6_addr(netif, addr_idx);
1041  /* address is actually being changed? */
1042  if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) ||
1043      (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) {
1044    LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n"));
1045
1046    if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) {
1047#if LWIP_TCP || LWIP_UDP
1048      ip_addr_t new_ipaddr;
1049      IP_ADDR6(&new_ipaddr, i0, i1, i2, i3);
1050#endif /* LWIP_TCP || LWIP_UDP */
1051#if LWIP_TCP
1052      tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1053#endif /* LWIP_TCP */
1054#if LWIP_UDP
1055      udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1056#endif /* LWIP_UDP */
1057#if LWIP_RAW
1058      raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1059#endif /* LWIP_RAW */
1060    }
1061    /* @todo: remove/readd mib2 ip6 entries? */
1062
1063    IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3);
1064    IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6);
1065
1066    if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) {
1067      netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6);
1068      NETIF_STATUS_CALLBACK(netif);
1069    }
1070  }
1071
1072  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",
1073    addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)),
1074    netif_ip6_addr_state(netif, addr_idx)));
1075}
1076
1077/**
1078 * @ingroup netif_ip6
1079 * Change the state of an IPv6 address of a network interface
1080 * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE
1081 * includes the number of checks done, see ip6_addr.h)
1082 *
1083 * @param netif the network interface to change
1084 * @param addr_idx index of the IPv6 address
1085 * @param state the new IPv6 address state
1086 */
1087void
1088netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
1089{
1090  u8_t old_state;
1091  LWIP_ASSERT("netif != NULL", netif != NULL);
1092  LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES);
1093
1094  old_state = netif_ip6_addr_state(netif, addr_idx);
1095  /* state is actually being changed? */
1096  if (old_state != state) {
1097    u8_t old_valid = old_state & IP6_ADDR_VALID;
1098    u8_t new_valid = state & IP6_ADDR_VALID;
1099    LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
1100
1101#if LWIP_IPV6_MLD
1102    /* Reevaluate solicited-node multicast group membership. */
1103    if (netif->flags & NETIF_FLAG_MLD6) {
1104      nd6_adjust_mld_membership(netif, addr_idx, state);
1105    }
1106#endif /* LWIP_IPV6_MLD */
1107
1108    if (old_valid && !new_valid) {
1109      /* address about to be removed by setting invalid */
1110#if LWIP_TCP
1111      tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1112#endif /* LWIP_TCP */
1113#if LWIP_UDP
1114      udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1115#endif /* LWIP_UDP */
1116#if LWIP_RAW
1117      raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1118#endif /* LWIP_RAW */
1119      /* @todo: remove mib2 ip6 entries? */
1120    }
1121    netif->ip6_addr_state[addr_idx] = state;
1122
1123    if (!old_valid && new_valid) {
1124      /* address added by setting valid */
1125      /* @todo: add mib2 ip6 entries? */
1126      netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6);
1127    }
1128    if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) {
1129      /* address state has changed (valid flag changed or switched between
1130         preferred and deprecated) -> call the callback function */
1131      NETIF_STATUS_CALLBACK(netif);
1132    }
1133  }
1134
1135  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",
1136    addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)),
1137    netif_ip6_addr_state(netif, addr_idx)));
1138}
1139
1140/**
1141 * Checks if a specific address is assigned to the netif and returns its
1142 * index.
1143 *
1144 * @param netif the netif to check
1145 * @param ip6addr the IPv6 address to find
1146 * @return >= 0: address found, this is its index
1147 *         -1: address not found on this netif
1148 */
1149s8_t
1150netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr)
1151{
1152  s8_t i;
1153  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1154    if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
1155        ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) {
1156      return i;
1157    }
1158  }
1159  return -1;
1160}
1161
1162/**
1163 * @ingroup netif_ip6
1164 * Create a link-local IPv6 address on a netif (stored in slot 0)
1165 *
1166 * @param netif the netif to create the address on
1167 * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion)
1168 *                       if == 0, use hwaddr directly as interface ID
1169 */
1170void
1171netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
1172{
1173  u8_t i, addr_index;
1174
1175  /* Link-local prefix. */
1176  ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul);
1177  ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0;
1178
1179  /* Generate interface ID. */
1180  if (from_mac_48bit) {
1181    /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
1182    ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
1183        ((u32_t)(netif->hwaddr[1]) << 16) |
1184        ((u32_t)(netif->hwaddr[2]) << 8) |
1185        (0xff));
1186    ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) |
1187        ((u32_t)(netif->hwaddr[3]) << 16) |
1188        ((u32_t)(netif->hwaddr[4]) << 8) |
1189        (netif->hwaddr[5]));
1190  } else {
1191    /* Use hwaddr directly as interface ID. */
1192    ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0;
1193    ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0;
1194
1195    addr_index = 3;
1196    for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) {
1197      if (i == 4) {
1198        addr_index--;
1199      }
1200      ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03));
1201    }
1202  }
1203
1204  /* Set address state. */
1205#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1206  /* Will perform duplicate address detection (DAD). */
1207  netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE);
1208#else
1209  /* Consider address valid. */
1210  netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
1211#endif /* LWIP_IPV6_AUTOCONFIG */
1212}
1213
1214/**
1215 * @ingroup netif_ip6
1216 * This function allows for the easy addition of a new IPv6 address to an interface.
1217 * It takes care of finding an empty slot and then sets the address tentative
1218 * (to make sure that all the subsequent processing happens).
1219 *
1220 * @param netif netif to add the address on
1221 * @param ip6addr address to add
1222 * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here
1223 */
1224err_t
1225netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx)
1226{
1227  s8_t i;
1228
1229  i = netif_get_ip6_addr_match(netif, ip6addr);
1230  if (i >= 0) {
1231    /* Address already added */
1232    if (chosen_idx != NULL) {
1233      *chosen_idx = i;
1234    }
1235    return ERR_OK;
1236  }
1237
1238  /* Find a free slot -- musn't be the first one (reserved for link local) */
1239  for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1240    if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
1241      ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
1242      netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
1243      if (chosen_idx != NULL) {
1244        *chosen_idx = i;
1245      }
1246      return ERR_OK;
1247    }
1248  }
1249
1250  if (chosen_idx != NULL) {
1251    *chosen_idx = -1;
1252  }
1253  return ERR_VAL;
1254}
1255
1256/** Dummy IPv6 output function for netifs not supporting IPv6
1257 */
1258static err_t
1259netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr)
1260{
1261  LWIP_UNUSED_ARG(netif);
1262  LWIP_UNUSED_ARG(p);
1263  LWIP_UNUSED_ARG(ipaddr);
1264
1265  return ERR_IF;
1266}
1267#endif /* LWIP_IPV6 */
1268