]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/ethernet/lwIP_130/src/core/netif.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / Common / ethernet / lwIP_130 / src / core / netif.c
1 /**\r
2  * @file\r
3  * lwIP network interface abstraction\r
4  *\r
5  */\r
6 \r
7 /*\r
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
9  * All rights reserved.\r
10  *\r
11  * Redistribution and use in source and binary forms, with or without modification,\r
12  * are permitted provided that the following conditions are met:\r
13  *\r
14  * 1. Redistributions of source code must retain the above copyright notice,\r
15  *    this list of conditions and the following disclaimer.\r
16  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
17  *    this list of conditions and the following disclaimer in the documentation\r
18  *    and/or other materials provided with the distribution.\r
19  * 3. The name of the author may not be used to endorse or promote products\r
20  *    derived from this software without specific prior written permission.\r
21  *\r
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\r
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
31  * OF SUCH DAMAGE.\r
32  *\r
33  * This file is part of the lwIP TCP/IP stack.\r
34  *\r
35  * Author: Adam Dunkels <adam@sics.se>\r
36  *\r
37  */\r
38 \r
39 #include "lwip/opt.h"\r
40 \r
41 #include "lwip/def.h"\r
42 #include "lwip/ip_addr.h"\r
43 #include "lwip/netif.h"\r
44 #include "lwip/tcp.h"\r
45 #include "lwip/snmp.h"\r
46 #include "lwip/igmp.h"\r
47 #include "netif/etharp.h"\r
48 \r
49 #if LWIP_NETIF_STATUS_CALLBACK\r
50 #define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }\r
51 #else\r
52 #define NETIF_STATUS_CALLBACK(n) { /* NOP */ }\r
53 #endif /* LWIP_NETIF_STATUS_CALLBACK */\r
54 \r
55 #if LWIP_NETIF_LINK_CALLBACK\r
56 #define NETIF_LINK_CALLBACK(n) { if (n->link_callback) (n->link_callback)(n); }\r
57 #else\r
58 #define NETIF_LINK_CALLBACK(n) { /* NOP */ }\r
59 #endif /* LWIP_NETIF_LINK_CALLBACK */\r
60 \r
61 struct netif *netif_list;\r
62 struct netif *netif_default;\r
63 \r
64 /**\r
65  * Add a network interface to the list of lwIP netifs.\r
66  *\r
67  * @param netif a pre-allocated netif structure\r
68  * @param ipaddr IP address for the new netif\r
69  * @param netmask network mask for the new netif\r
70  * @param gw default gateway IP address for the new netif\r
71  * @param state opaque data passed to the new netif\r
72  * @param init callback function that initializes the interface\r
73  * @param input callback function that is called to pass\r
74  * ingress packets up in the protocol layer stack.\r
75  *\r
76  * @return netif, or NULL if failed.\r
77  */\r
78 struct netif *\r
79 netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,\r
80   struct ip_addr *gw,\r
81   void *state,\r
82   err_t (* init)(struct netif *netif),\r
83   err_t (* input)(struct pbuf *p, struct netif *netif))\r
84 {\r
85   static u8_t netifnum = 0;\r
86 \r
87   /* reset new interface configuration state */\r
88   netif->ip_addr.addr = 0;\r
89   netif->netmask.addr = 0;\r
90   netif->gw.addr = 0;\r
91   netif->flags = 0;\r
92 #if LWIP_DHCP\r
93   /* netif not under DHCP control by default */\r
94   netif->dhcp = NULL;\r
95 #endif /* LWIP_DHCP */\r
96 #if LWIP_AUTOIP\r
97   /* netif not under AutoIP control by default */\r
98   netif->autoip = NULL;\r
99 #endif /* LWIP_AUTOIP */\r
100 #if LWIP_NETIF_STATUS_CALLBACK\r
101   netif->status_callback = NULL;\r
102 #endif /* LWIP_NETIF_STATUS_CALLBACK */\r
103 #if LWIP_NETIF_LINK_CALLBACK\r
104   netif->link_callback = NULL;\r
105 #endif /* LWIP_NETIF_LINK_CALLBACK */\r
106 #if LWIP_IGMP\r
107   netif->igmp_mac_filter = NULL;\r
108 #endif /* LWIP_IGMP */\r
109 \r
110   /* remember netif specific state information data */\r
111   netif->state = state;\r
112   netif->num = netifnum++;\r
113   netif->input = input;\r
114 #if LWIP_NETIF_HWADDRHINT\r
115   netif->addr_hint = NULL;\r
116 #endif /* LWIP_NETIF_HWADDRHINT*/\r
117 \r
118   netif_set_addr(netif, ipaddr, netmask, gw);\r
119 \r
120   /* call user specified initialization function for netif */\r
121   if (init(netif) != ERR_OK) {\r
122     return NULL;\r
123   }\r
124 \r
125   /* add this netif to the list */\r
126   netif->next = netif_list;\r
127   netif_list = netif;\r
128   snmp_inc_iflist();\r
129 \r
130 #if LWIP_IGMP\r
131   /* start IGMP processing */\r
132   if (netif->flags & NETIF_FLAG_IGMP) {\r
133     igmp_start( netif);\r
134   }\r
135 #endif /* LWIP_IGMP */\r
136 \r
137   LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",\r
138     netif->name[0], netif->name[1]));\r
139   ip_addr_debug_print(NETIF_DEBUG, ipaddr);\r
140   LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));\r
141   ip_addr_debug_print(NETIF_DEBUG, netmask);\r
142   LWIP_DEBUGF(NETIF_DEBUG, (" gw "));\r
143   ip_addr_debug_print(NETIF_DEBUG, gw);\r
144   LWIP_DEBUGF(NETIF_DEBUG, ("\n"));\r
145   return netif;\r
146 }\r
147 \r
148 /**\r
149  * Change IP address configuration for a network interface (including netmask\r
150  * and default gateway).\r
151  *\r
152  * @param netif the network interface to change\r
153  * @param ipaddr the new IP address\r
154  * @param netmask the new netmask\r
155  * @param gw the new default gateway\r
156  */\r
157 void\r
158 netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,\r
159     struct ip_addr *gw)\r
160 {\r
161   netif_set_ipaddr(netif, ipaddr);\r
162   netif_set_netmask(netif, netmask);\r
163   netif_set_gw(netif, gw);\r
164 }\r
165 \r
166 /**\r
167  * Remove a network interface from the list of lwIP netifs.\r
168  *\r
169  * @param netif the network interface to remove\r
170  */\r
171 void netif_remove(struct netif * netif)\r
172 {\r
173   if ( netif == NULL ) return;\r
174 \r
175 #if LWIP_IGMP\r
176   /* stop IGMP processing */\r
177   if (netif->flags & NETIF_FLAG_IGMP) {\r
178     igmp_stop( netif);\r
179   }\r
180 #endif /* LWIP_IGMP */\r
181 \r
182   snmp_delete_ipaddridx_tree(netif);\r
183 \r
184   /*  is it the first netif? */\r
185   if (netif_list == netif) {\r
186     netif_list = netif->next;\r
187     snmp_dec_iflist();\r
188   }\r
189   else {\r
190     /*  look for netif further down the list */\r
191     struct netif * tmpNetif;\r
192     for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {\r
193       if (tmpNetif->next == netif) {\r
194         tmpNetif->next = netif->next;\r
195         snmp_dec_iflist();\r
196         break;\r
197       }\r
198     }\r
199     if (tmpNetif == NULL)\r
200       return; /*  we didn't find any netif today */\r
201   }\r
202   /* this netif is default? */\r
203   if (netif_default == netif)\r
204     /* reset default netif */\r
205     netif_set_default(NULL);\r
206   LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );\r
207 }\r
208 \r
209 /**\r
210  * Find a network interface by searching for its name\r
211  *\r
212  * @param name the name of the netif (like netif->name) plus concatenated number\r
213  * in ascii representation (e.g. 'en0')\r
214  */\r
215 struct netif *\r
216 netif_find(char *name)\r
217 {\r
218   struct netif *netif;\r
219   u8_t num;\r
220 \r
221   if (name == NULL) {\r
222     return NULL;\r
223   }\r
224 \r
225   num = name[2] - '0';\r
226 \r
227   for(netif = netif_list; netif != NULL; netif = netif->next) {\r
228     if (num == netif->num &&\r
229        name[0] == netif->name[0] &&\r
230        name[1] == netif->name[1]) {\r
231       LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));\r
232       return netif;\r
233     }\r
234   }\r
235   LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));\r
236   return NULL;\r
237 }\r
238 \r
239 /**\r
240  * Change the IP address of a network interface\r
241  *\r
242  * @param netif the network interface to change\r
243  * @param ipaddr the new IP address\r
244  *\r
245  * @note call netif_set_addr() if you also want to change netmask and\r
246  * default gateway\r
247  */\r
248 void\r
249 netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)\r
250 {\r
251   /* TODO: Handling of obsolete pcbs */\r
252   /* See:  http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */\r
253 #if LWIP_TCP\r
254   struct tcp_pcb *pcb;\r
255   struct tcp_pcb_listen *lpcb;\r
256 \r
257   /* address is actually being changed? */\r
258   if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)\r
259   {\r
260     /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */\r
261     LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));\r
262     pcb = tcp_active_pcbs;\r
263     while (pcb != NULL) {\r
264       /* PCB bound to current local interface address? */\r
265       if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {\r
266         /* this connection must be aborted */\r
267         struct tcp_pcb *next = pcb->next;\r
268         LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));\r
269         tcp_abort(pcb);\r
270         pcb = next;\r
271       } else {\r
272         pcb = pcb->next;\r
273       }\r
274     }\r
275     for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {\r
276       /* PCB bound to current local interface address? */\r
277       if ((!(ip_addr_isany(&(lpcb->local_ip)))) &&\r
278           (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) {\r
279         /* The PCB is listening to the old ipaddr and\r
280          * is set to listen to the new one instead */\r
281         ip_addr_set(&(lpcb->local_ip), ipaddr);\r
282       }\r
283     }\r
284   }\r
285 #endif\r
286   snmp_delete_ipaddridx_tree(netif);\r
287   snmp_delete_iprteidx_tree(0,netif);\r
288   /* set new IP address to netif */\r
289   ip_addr_set(&(netif->ip_addr), ipaddr);\r
290   snmp_insert_ipaddridx_tree(netif);\r
291   snmp_insert_iprteidx_tree(0,netif);\r
292 \r
293   LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",\r
294     netif->name[0], netif->name[1],\r
295     ip4_addr1(&netif->ip_addr),\r
296     ip4_addr2(&netif->ip_addr),\r
297     ip4_addr3(&netif->ip_addr),\r
298     ip4_addr4(&netif->ip_addr)));\r
299 }\r
300 \r
301 /**\r
302  * Change the default gateway for a network interface\r
303  *\r
304  * @param netif the network interface to change\r
305  * @param gw the new default gateway\r
306  *\r
307  * @note call netif_set_addr() if you also want to change ip address and netmask\r
308  */\r
309 void\r
310 netif_set_gw(struct netif *netif, struct ip_addr *gw)\r
311 {\r
312   ip_addr_set(&(netif->gw), gw);\r
313   LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",\r
314     netif->name[0], netif->name[1],\r
315     ip4_addr1(&netif->gw),\r
316     ip4_addr2(&netif->gw),\r
317     ip4_addr3(&netif->gw),\r
318     ip4_addr4(&netif->gw)));\r
319 }\r
320 \r
321 /**\r
322  * Change the netmask of a network interface\r
323  *\r
324  * @param netif the network interface to change\r
325  * @param netmask the new netmask\r
326  *\r
327  * @note call netif_set_addr() if you also want to change ip address and\r
328  * default gateway\r
329  */\r
330 void\r
331 netif_set_netmask(struct netif *netif, struct ip_addr *netmask)\r
332 {\r
333   snmp_delete_iprteidx_tree(0, netif);\r
334   /* set new netmask to netif */\r
335   ip_addr_set(&(netif->netmask), netmask);\r
336   snmp_insert_iprteidx_tree(0, netif);\r
337   LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",\r
338     netif->name[0], netif->name[1],\r
339     ip4_addr1(&netif->netmask),\r
340     ip4_addr2(&netif->netmask),\r
341     ip4_addr3(&netif->netmask),\r
342     ip4_addr4(&netif->netmask)));\r
343 }\r
344 \r
345 /**\r
346  * Set a network interface as the default network interface\r
347  * (used to output all packets for which no specific route is found)\r
348  *\r
349  * @param netif the default network interface\r
350  */\r
351 void\r
352 netif_set_default(struct netif *netif)\r
353 {\r
354   if (netif == NULL)\r
355   {\r
356     /* remove default route */\r
357     snmp_delete_iprteidx_tree(1, netif);\r
358   }\r
359   else\r
360   {\r
361     /* install default route */\r
362     snmp_insert_iprteidx_tree(1, netif);\r
363   }\r
364   netif_default = netif;\r
365   LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",\r
366            netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));\r
367 }\r
368 \r
369 /**\r
370  * Bring an interface up, available for processing\r
371  * traffic.\r
372  *\r
373  * @note: Enabling DHCP on a down interface will make it come\r
374  * up once configured.\r
375  *\r
376  * @see dhcp_start()\r
377  */\r
378 void netif_set_up(struct netif *netif)\r
379 {\r
380   if ( !(netif->flags & NETIF_FLAG_UP )) {\r
381     netif->flags |= NETIF_FLAG_UP;\r
382 \r
383 #if LWIP_SNMP\r
384     snmp_get_sysuptime(&netif->ts);\r
385 #endif /* LWIP_SNMP */\r
386 \r
387     NETIF_LINK_CALLBACK(netif);\r
388     NETIF_STATUS_CALLBACK(netif);\r
389 \r
390 #if LWIP_ARP\r
391     /** For Ethernet network interfaces, we would like to send a\r
392      *  "gratuitous ARP"; this is an ARP packet sent by a node in order\r
393      *  to spontaneously cause other nodes to update an entry in their\r
394      *  ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6.\r
395      */\r
396     if (netif->flags & NETIF_FLAG_ETHARP) {\r
397       etharp_query(netif, &(netif->ip_addr), NULL);\r
398     }\r
399 #endif /* LWIP_ARP */\r
400 \r
401   }\r
402 }\r
403 \r
404 /**\r
405  * Bring an interface down, disabling any traffic processing.\r
406  *\r
407  * @note: Enabling DHCP on a down interface will make it come\r
408  * up once configured.\r
409  *\r
410  * @see dhcp_start()\r
411  */\r
412 void netif_set_down(struct netif *netif)\r
413 {\r
414   if ( netif->flags & NETIF_FLAG_UP )\r
415     {\r
416       netif->flags &= ~NETIF_FLAG_UP;\r
417 #if LWIP_SNMP\r
418       snmp_get_sysuptime(&netif->ts);\r
419 #endif\r
420 \r
421       NETIF_LINK_CALLBACK(netif);\r
422       NETIF_STATUS_CALLBACK(netif);\r
423     }\r
424 }\r
425 \r
426 /**\r
427  * Ask if an interface is up\r
428  */\r
429 u8_t netif_is_up(struct netif *netif)\r
430 {\r
431   return (netif->flags & NETIF_FLAG_UP)?1:0;\r
432 }\r
433 \r
434 #if LWIP_NETIF_STATUS_CALLBACK\r
435 /**\r
436  * Set callback to be called when interface is brought up/down\r
437  */\r
438 void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif ))\r
439 {\r
440     if ( netif )\r
441         netif->status_callback = status_callback;\r
442 }\r
443 #endif /* LWIP_NETIF_STATUS_CALLBACK */\r
444 \r
445 #if LWIP_NETIF_LINK_CALLBACK\r
446 /**\r
447  * Called by a driver when its link goes up\r
448  */\r
449 void netif_set_link_up(struct netif *netif )\r
450 {\r
451   netif->flags |= NETIF_FLAG_LINK_UP;\r
452 \r
453 #if LWIP_ARP\r
454   /** For Ethernet network interfaces, we would like to send a\r
455    *  "gratuitous ARP"; this is an ARP packet sent by a node in order\r
456    *  to spontaneously cause other nodes to update an entry in their\r
457    *  ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6.\r
458    */\r
459   if (netif->flags & NETIF_FLAG_ETHARP) {\r
460     etharp_query(netif, &(netif->ip_addr), NULL);\r
461   }\r
462 #endif /* LWIP_ARP */\r
463 \r
464 #if LWIP_IGMP\r
465   /* resend IGMP memberships */\r
466   if (netif->flags & NETIF_FLAG_IGMP) {\r
467     igmp_report_groups( netif);\r
468   }\r
469 #endif /* LWIP_IGMP */\r
470 \r
471   NETIF_LINK_CALLBACK(netif);\r
472 }\r
473 \r
474 /**\r
475  * Called by a driver when its link goes down\r
476  */\r
477 void netif_set_link_down(struct netif *netif )\r
478 {\r
479   netif->flags &= ~NETIF_FLAG_LINK_UP;\r
480   NETIF_LINK_CALLBACK(netif);\r
481 }\r
482 \r
483 /**\r
484  * Ask if a link is up\r
485  */\r
486 u8_t netif_is_link_up(struct netif *netif)\r
487 {\r
488   return (netif->flags & NETIF_FLAG_LINK_UP) ? 1 : 0;\r
489 }\r
490 \r
491 /**\r
492  * Set callback to be called when link is brought up/down\r
493  */\r
494 void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif ))\r
495 {\r
496     if ( netif )\r
497         netif->link_callback = link_callback;\r
498 }\r
499 #endif /* LWIP_NETIF_LINK_CALLBACK */\r