1 /**
2  * @file
3  * netif API (to be used from TCPIP thread)
4  */
5 
6 /*
7  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without modification,
11  * are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  *    this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  *    this list of conditions and the following disclaimer in the documentation
17  *    and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30  * OF SUCH DAMAGE.
31  *
32  * This file is part of the lwIP TCP/IP stack.
33  *
34  * Author: Adam Dunkels <adam@sics.se>
35  *
36  */
37 #ifndef LWIP_HDR_NETIF_H
38 #define LWIP_HDR_NETIF_H
39 
40 #include "lwip/opt.h"
41 
42 #define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
43 
44 #include "lwip/err.h"
45 
46 #include "lwip/ip_addr.h"
47 
48 #include "lwip/def.h"
49 #include "lwip/pbuf.h"
50 #include "lwip/stats.h"
51 
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55 
56 /* Throughout this file, IP addresses are expected to be in
57  * the same byte order as in IP_PCB. */
58 
59 /** Must be the maximum of all used hardware address lengths
60     across all types of interfaces in use.
61     This does not have to be changed, normally. */
62 #ifndef NETIF_MAX_HWADDR_LEN
63 #define NETIF_MAX_HWADDR_LEN 6U
64 #endif
65 
66 /**
67  * @defgroup netif_flags Flags
68  * @ingroup netif
69  * @{
70  */
71 
72 /** Whether the network interface is 'up'. This is
73  * a software flag used to control whether this network
74  * interface is enabled and processes traffic.
75  * It must be set by the startup code before this netif can be used
76  * (also for dhcp/autoip).
77  */
78 #define NETIF_FLAG_UP           0x01U
79 /** If set, the netif has broadcast capability.
80  * Set by the netif driver in its init function. */
81 #define NETIF_FLAG_BROADCAST    0x02U
82 /** If set, the interface has an active link
83  *  (set by the network interface driver).
84  * Either set by the netif driver in its init function (if the link
85  * is up at that time) or at a later point once the link comes up
86  * (if link detection is supported by the hardware). */
87 #define NETIF_FLAG_LINK_UP      0x04U
88 /** If set, the netif is an ethernet device using ARP.
89  * Set by the netif driver in its init function.
90  * Used to check input packet types and use of DHCP. */
91 #define NETIF_FLAG_ETHARP       0x08U
92 /** If set, the netif is an ethernet device. It might not use
93  * ARP or TCP/IP if it is used for PPPoE only.
94  */
95 #define NETIF_FLAG_ETHERNET     0x10U
96 /** If set, the netif has IGMP capability.
97  * Set by the netif driver in its init function. */
98 #define NETIF_FLAG_IGMP         0x20U
99 /** If set, the netif has MLD6 capability.
100  * Set by the netif driver in its init function. */
101 #define NETIF_FLAG_MLD6         0x40U
102 
103 /**
104  * @}
105  */
106 
107 enum lwip_internal_netif_client_data_index
108 {
109 #if LWIP_DHCP
110    LWIP_NETIF_CLIENT_DATA_INDEX_DHCP,
111 #endif
112 #if LWIP_AUTOIP
113    LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP,
114 #endif
115 #if LWIP_IGMP
116    LWIP_NETIF_CLIENT_DATA_INDEX_IGMP,
117 #endif
118 #if LWIP_IPV6_MLD
119    LWIP_NETIF_CLIENT_DATA_INDEX_MLD6,
120 #endif
121    LWIP_NETIF_CLIENT_DATA_INDEX_MAX
122 };
123 
124 #if LWIP_CHECKSUM_CTRL_PER_NETIF
125 #define NETIF_CHECKSUM_GEN_IP       0x0001
126 #define NETIF_CHECKSUM_GEN_UDP      0x0002
127 #define NETIF_CHECKSUM_GEN_TCP      0x0004
128 #define NETIF_CHECKSUM_GEN_ICMP     0x0008
129 #define NETIF_CHECKSUM_GEN_ICMP6    0x0010
130 #define NETIF_CHECKSUM_CHECK_IP     0x0100
131 #define NETIF_CHECKSUM_CHECK_UDP    0x0200
132 #define NETIF_CHECKSUM_CHECK_TCP    0x0400
133 #define NETIF_CHECKSUM_CHECK_ICMP   0x0800
134 #define NETIF_CHECKSUM_CHECK_ICMP6  0x1000
135 #define NETIF_CHECKSUM_ENABLE_ALL   0xFFFF
136 #define NETIF_CHECKSUM_DISABLE_ALL  0x0000
137 #endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
138 
139 struct netif;
140 
141 /** MAC Filter Actions, these are passed to a netif's igmp_mac_filter or
142  * mld_mac_filter callback function. */
143 enum netif_mac_filter_action {
144   /** Delete a filter entry */
145   NETIF_DEL_MAC_FILTER = 0,
146   /** Add a filter entry */
147   NETIF_ADD_MAC_FILTER = 1
148 };
149 
150 /** Function prototype for netif init functions. Set up flags and output/linkoutput
151  * callback functions in this function.
152  *
153  * @param netif The netif to initialize
154  */
155 typedef err_t (*netif_init_fn)(struct netif *netif);
156 /** Function prototype for netif->input functions. This function is saved as 'input'
157  * callback function in the netif struct. Call it when a packet has been received.
158  *
159  * @param p The received packet, copied into a pbuf
160  * @param inp The netif which received the packet
161  */
162 typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
163 
164 #ifdef LWIP_NETIF_DRV
165 typedef err_t (*netif_drv_fn)(struct netif *inp, u32_t event);
166 #endif
167 
168 #if LWIP_IPV4
169 /** Function prototype for netif->output functions. Called by lwIP when a packet
170  * shall be sent. For ethernet netif, set this to 'etharp_output' and set
171  * 'linkoutput'.
172  *
173  * @param netif The netif which shall send a packet
174  * @param p The packet to send (p->payload points to IP header)
175  * @param ipaddr The IP address to which the packet shall be sent
176  */
177 typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p,
178        const ip4_addr_t *ipaddr);
179 #endif /* LWIP_IPV4*/
180 
181 #if LWIP_IPV6
182 /** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet
183  * shall be sent. For ethernet netif, set this to 'ethip6_output' and set
184  * 'linkoutput'.
185  *
186  * @param netif The netif which shall send a packet
187  * @param p The packet to send (p->payload points to IP header)
188  * @param ipaddr The IPv6 address to which the packet shall be sent
189  */
190 typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p,
191        const ip6_addr_t *ipaddr);
192 #endif /* LWIP_IPV6 */
193 
194 /** Function prototype for netif->linkoutput functions. Only used for ethernet
195  * netifs. This function is called by ARP when a packet shall be sent.
196  *
197  * @param netif The netif which shall send a packet
198  * @param p The packet to send (raw ethernet packet)
199  */
200 typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p);
201 /** Function prototype for netif status- or link-callback functions. */
202 typedef void (*netif_status_callback_fn)(struct netif *netif);
203 #if LWIP_IPV4 && LWIP_IGMP
204 /** Function prototype for netif igmp_mac_filter functions */
205 typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
206        const ip4_addr_t *group, enum netif_mac_filter_action action);
207 #endif /* LWIP_IPV4 && LWIP_IGMP */
208 #if LWIP_IPV6 && LWIP_IPV6_MLD
209 /** Function prototype for netif mld_mac_filter functions */
210 typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif,
211        const ip6_addr_t *group, enum netif_mac_filter_action action);
212 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
213 
214 #if LWIP_DHCP || LWIP_AUTOIP || LWIP_IGMP || LWIP_IPV6_MLD || (LWIP_NUM_NETIF_CLIENT_DATA > 0)
215 u8_t netif_alloc_client_data_id(void);
216 /** @ingroup netif_cd
217  * Set client data. Obtain ID from netif_alloc_client_data_id().
218  */
219 #define netif_set_client_data(netif, id, data) netif_get_client_data(netif, id) = (data)
220 /** @ingroup netif_cd
221  * Get client data. Obtain ID from netif_alloc_client_data_id().
222  */
223 #define netif_get_client_data(netif, id)       (netif)->client_data[(id)]
224 #endif /* LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0) */
225 
226 /** Generic data structure used for all lwIP network interfaces.
227  *  The following fields should be filled in by the initialization
228  *  function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
229 struct netif {
230   /** pointer to next in linked list */
231   struct netif *next;
232 
233 #if LWIP_IPV4
234   /** IP address configuration in network byte order */
235   ip_addr_t ip_addr;
236   ip_addr_t netmask;
237   ip_addr_t gw;
238 #endif /* LWIP_IPV4 */
239 #if LWIP_IPV6
240   /** Array of IPv6 addresses for this netif. */
241   ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES];
242   /** The state of each IPv6 address (Tentative, Preferred, etc).
243    * @see ip6_addr.h */
244   u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES];
245 #endif /* LWIP_IPV6 */
246   /** This function is called by the network device driver
247    *  to pass a packet up the TCP/IP stack. */
248   netif_input_fn input;
249 #if LWIP_IPV4
250   /** This function is called by the IP module when it wants
251    *  to send a packet on the interface. This function typically
252    *  first resolves the hardware address, then sends the packet.
253    *  For ethernet physical layer, this is usually etharp_output() */
254   netif_output_fn output;
255 #endif /* LWIP_IPV4 */
256   /** This function is called by ethernet_output() when it wants
257    *  to send a packet on the interface. This function outputs
258    *  the pbuf as-is on the link medium. */
259   netif_linkoutput_fn linkoutput;
260 #if LWIP_IPV6
261   /** This function is called by the IPv6 module when it wants
262    *  to send a packet on the interface. This function typically
263    *  first resolves the hardware address, then sends the packet.
264    *  For ethernet physical layer, this is usually ethip6_output() */
265   netif_output_ip6_fn output_ip6;
266 #endif /* LWIP_IPV6 */
267 #if LWIP_NETIF_STATUS_CALLBACK
268   /** This function is called when the netif state is set to up or down
269    */
270   netif_status_callback_fn status_callback;
271 #endif /* LWIP_NETIF_STATUS_CALLBACK */
272 #if LWIP_NETIF_LINK_CALLBACK
273   /** This function is called when the netif link is set to up or down
274    */
275   netif_status_callback_fn link_callback;
276 #endif /* LWIP_NETIF_LINK_CALLBACK */
277 #if LWIP_NETIF_REMOVE_CALLBACK
278   /** This function is called when the netif has been removed */
279   netif_status_callback_fn remove_callback;
280 #endif /* LWIP_NETIF_REMOVE_CALLBACK */
281   /** This field can be set by the device driver and could point
282    *  to state information for the device. */
283   void *state;
284 #ifdef netif_get_client_data
285   void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA];
286 #endif
287 #if LWIP_IPV6_AUTOCONFIG
288   /** is this netif enabled for IPv6 autoconfiguration */
289   u8_t ip6_autoconfig_enabled;
290 #endif /* LWIP_IPV6_AUTOCONFIG */
291 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
292   /** Number of Router Solicitation messages that remain to be sent. */
293   u8_t rs_count;
294 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
295 #if LWIP_NETIF_HOSTNAME
296   /* the hostname for this netif, NULL is a valid value */
297   const char*  hostname;
298 #endif /* LWIP_NETIF_HOSTNAME */
299 #if LWIP_CHECKSUM_CTRL_PER_NETIF
300   u16_t chksum_flags;
301 #endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/
302   /** maximum transfer unit (in bytes) */
303   u16_t mtu;
304   /** number of bytes used in hwaddr */
305   u8_t hwaddr_len;
306   /** link level hardware address of this interface */
307   u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
308   /** flags (@see @ref netif_flags) */
309   u8_t flags;
310   /** descriptive abbreviation */
311   char name[2];
312   /** number of this interface */
313   u8_t num;
314 #ifdef CELLULAR_SUPPORT
315   ip_addr_t dns_srv[DNS_MAX_SERVERS];
316 #endif
317 #if MIB2_STATS
318   /** link type (from "snmp_ifType" enum from snmp_mib2.h) */
319   u8_t link_type;
320   /** (estimate) link speed */
321   u32_t link_speed;
322   /** timestamp at last change made (up/down) */
323   u32_t ts;
324   /** counters */
325   struct stats_mib2_netif_ctrs mib2_counters;
326 #endif /* MIB2_STATS */
327 #if LWIP_IPV4 && LWIP_IGMP
328   /** This function could be called to add or delete an entry in the multicast
329       filter table of the ethernet MAC.*/
330   netif_igmp_mac_filter_fn igmp_mac_filter;
331 #endif /* LWIP_IPV4 && LWIP_IGMP */
332 #if LWIP_IPV6 && LWIP_IPV6_MLD
333   /** This function could be called to add or delete an entry in the IPv6 multicast
334       filter table of the ethernet MAC. */
335   netif_mld_mac_filter_fn mld_mac_filter;
336 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
337 #if LWIP_NETIF_HWADDRHINT
338   u8_t *addr_hint;
339 #endif /* LWIP_NETIF_HWADDRHINT */
340 #if ENABLE_LOOPBACK
341   /* List of packets to be queued for ourselves. */
342   struct pbuf *loop_first;
343   struct pbuf *loop_last;
344 #if LWIP_LOOPBACK_MAX_PBUFS
345   u16_t loop_cnt_current;
346 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
347 #endif /* ENABLE_LOOPBACK */
348 };
349 
350 #if LWIP_CHECKSUM_CTRL_PER_NETIF
351 #define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \
352   (netif)->chksum_flags = chksumflags; } while(0)
353 #define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0))
354 #else /* LWIP_CHECKSUM_CTRL_PER_NETIF */
355 #define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags)
356 #define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
357 #endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
358 
359 /** The list of network interfaces. */
360 extern struct netif *netif_list;
361 /** The default network interface. */
362 extern struct netif *netif_default;
363 
364 void netif_init(void);
365 
366 struct netif *netif_add(struct netif *netif,
367 #if LWIP_IPV4
368                         const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
369 #endif /* LWIP_IPV4 */
370                         void *state, netif_init_fn init, netif_input_fn input);
371 #if LWIP_IPV4
372 void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
373                     const ip4_addr_t *gw);
374 #endif /* LWIP_IPV4 */
375 void netif_remove(struct netif * netif);
376 
377 /* Returns a network interface given its name. The name is of the form
378    "et0", where the first two letters are the "name" field in the
379    netif structure, and the digit is in the num field in the same
380    structure. */
381 struct netif *netif_find(const char *name);
382 
383 void netif_set_default(struct netif *netif);
384 
385 #if LWIP_IPV4
386 void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr);
387 void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask);
388 void netif_set_gw(struct netif *netif, const ip4_addr_t *gw);
389 /** @ingroup netif_ip4 */
390 #define netif_ip4_addr(netif)    ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr)))
391 /** @ingroup netif_ip4 */
392 #define netif_ip4_netmask(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->netmask)))
393 /** @ingroup netif_ip4 */
394 #define netif_ip4_gw(netif)      ((const ip4_addr_t*)ip_2_ip4(&((netif)->gw)))
395 /** @ingroup netif_ip4 */
396 #define netif_ip_addr4(netif)    ((const ip_addr_t*)&((netif)->ip_addr))
397 /** @ingroup netif_ip4 */
398 #define netif_ip_netmask4(netif) ((const ip_addr_t*)&((netif)->netmask))
399 /** @ingroup netif_ip4 */
400 #define netif_ip_gw4(netif)      ((const ip_addr_t*)&((netif)->gw))
401 #endif /* LWIP_IPV4 */
402 
403 void netif_set_up(struct netif *netif);
404 void netif_set_down(struct netif *netif);
405 /** @ingroup netif
406  * Ask if an interface is up
407  */
408 #define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0)
409 
410 #if LWIP_NETIF_STATUS_CALLBACK
411 void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback);
412 #endif /* LWIP_NETIF_STATUS_CALLBACK */
413 #if LWIP_NETIF_REMOVE_CALLBACK
414 void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback);
415 #endif /* LWIP_NETIF_REMOVE_CALLBACK */
416 
417 void netif_set_link_up(struct netif *netif);
418 void netif_set_link_down(struct netif *netif);
419 /** Ask if a link is up */
420 #define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0)
421 
422 #if LWIP_NETIF_LINK_CALLBACK
423 void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback);
424 #endif /* LWIP_NETIF_LINK_CALLBACK */
425 
426 #if LWIP_NETIF_HOSTNAME
427 /** @ingroup netif */
428 #define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0)
429 /** @ingroup netif */
430 #define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL)
431 #endif /* LWIP_NETIF_HOSTNAME */
432 
433 #if LWIP_IGMP
434 /** @ingroup netif */
435 #define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0)
436 #define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL)
437 #endif /* LWIP_IGMP */
438 
439 #if LWIP_IPV6 && LWIP_IPV6_MLD
440 /** @ingroup netif */
441 #define netif_set_mld_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->mld_mac_filter = function; }}while(0)
442 #define netif_get_mld_mac_filter(netif) (((netif) != NULL) ? ((netif)->mld_mac_filter) : NULL)
443 #define netif_mld_mac_filter(netif, addr, action) do { if((netif) && (netif)->mld_mac_filter) { (netif)->mld_mac_filter((netif), (addr), (action)); }}while(0)
444 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
445 
446 #if ENABLE_LOOPBACK
447 err_t netif_loop_output(struct netif *netif, struct pbuf *p);
448 void netif_poll(struct netif *netif);
449 #if !LWIP_NETIF_LOOPBACK_MULTITHREADING
450 void netif_poll_all(void);
451 #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
452 #endif /* ENABLE_LOOPBACK */
453 
454 err_t netif_input(struct pbuf *p, struct netif *inp);
455 
456 #if LWIP_IPV6
457 /** @ingroup netif_ip6 */
458 #define netif_ip_addr6(netif, i)  ((const ip_addr_t*)(&((netif)->ip6_addr[i])))
459 /** @ingroup netif_ip6 */
460 #define netif_ip6_addr(netif, i)  ((const ip6_addr_t*)ip_2_ip6(&((netif)->ip6_addr[i])))
461 void netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6);
462 void netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3);
463 #define netif_ip6_addr_state(netif, i)  ((netif)->ip6_addr_state[i])
464 void netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state);
465 s8_t netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr);
466 #ifdef CELLULAR_SUPPORT
467 void netif_create_ip6_linklocal_address_from_if_id(struct netif *netif, u8_t *if_id);
468 #endif /* CELLULAR_SUPPORT */
469 void netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit);
470 err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx);
471 #define netif_set_ip6_autoconfig_enabled(netif, action) do { if(netif) { (netif)->ip6_autoconfig_enabled = (action); }}while(0)
472 #endif /* LWIP_IPV6 */
473 
474 #if LWIP_NETIF_HWADDRHINT
475 #define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint))
476 #else /* LWIP_NETIF_HWADDRHINT */
477 #define NETIF_SET_HWADDRHINT(netif, hint)
478 #endif /* LWIP_NETIF_HWADDRHINT */
479 
480 struct netif* netif_find_by_index(int index);
481 /* Interface indexes always start at 1 per RFC 3493, section 4, num starts at 0 (internal index is 0..254)*/
482 #define netif_get_index(netif)      ((u8_t)((netif)->num + 1))
483 #define NETIF_NO_INDEX              (0)
484 
485 /** The list of network interfaces. */
486 extern struct netif *netif_list;
487 #define NETIF_FOREACH(netif) for ((netif) = netif_list; (netif) != NULL; (netif) = (netif)->next)
488 
489 #if LWIP_XR_EXT
490 #include <lwip/netif_ext.h>
491 #endif
492 
493 #ifdef __cplusplus
494 }
495 #endif
496 
497 #endif /* LWIP_HDR_NETIF_H */
498