]> git.sur5r.net Git - freertos/blob - Demo/Common/ethernet/lwIP/core/netif.c
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@82 1d2547de-c912-0410-9cb9...
[freertos] / Demo / Common / ethernet / lwIP / core / netif.c
1 /**\r
2  * @file\r
3  *\r
4  * lwIP network interface abstraction\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 \r
47 struct netif *netif_list = NULL;\r
48 struct netif *netif_default = NULL;\r
49 \r
50 /**\r
51  * Add a network interface to the list of lwIP netifs.\r
52  *\r
53  * @param netif a pre-allocated netif structure\r
54  * @param ipaddr IP address for the new netif\r
55  * @param netmask network mask for the new netif\r
56  * @param gw default gateway IP address for the new netif\r
57  * @param state opaque data passed to the new netif\r
58  * @param init callback function that initializes the interface\r
59  * @param input callback function that is called to pass\r
60  * ingress packets up in the protocol layer stack.\r
61  *\r
62  * @return netif, or NULL if failed.\r
63  */\r
64 struct netif *\r
65 netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,\r
66   struct ip_addr *gw,\r
67   void *state,\r
68   err_t (* init)(struct netif *netif),\r
69   err_t (* input)(struct pbuf *p, struct netif *netif))\r
70 {\r
71   static s16_t netifnum = 0;\r
72 \r
73   /* reset new interface configuration state */\r
74   netif->ip_addr.addr = 0;\r
75   netif->netmask.addr = 0;\r
76   netif->gw.addr = 0;\r
77   netif->flags = 0;\r
78 #if LWIP_DHCP\r
79   /* netif not under DHCP control by default */\r
80   netif->dhcp = NULL;\r
81 #endif\r
82   /* remember netif specific state information data */\r
83   netif->state = state;\r
84   netif->num = netifnum++;\r
85   netif->input = input;\r
86 \r
87   netif_set_addr(netif, ipaddr, netmask, gw);\r
88 \r
89   /* call user specified initialization function for netif */\r
90   if (init(netif) != ERR_OK) {\r
91     return NULL;\r
92   }\r
93 \r
94   /* add this netif to the list */\r
95   netif->next = netif_list;\r
96   netif_list = netif;\r
97   snmp_inc_iflist();\r
98 \r
99   LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",\r
100     netif->name[0], netif->name[1]));\r
101   ip_addr_debug_print(NETIF_DEBUG, ipaddr);\r
102   LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));\r
103   ip_addr_debug_print(NETIF_DEBUG, netmask);\r
104   LWIP_DEBUGF(NETIF_DEBUG, (" gw "));\r
105   ip_addr_debug_print(NETIF_DEBUG, gw);\r
106   LWIP_DEBUGF(NETIF_DEBUG, ("\n"));\r
107   return netif;\r
108 }\r
109 \r
110 void\r
111 netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask,\r
112     struct ip_addr *gw)\r
113 {\r
114   netif_set_ipaddr(netif, ipaddr);\r
115   netif_set_netmask(netif, netmask);\r
116   netif_set_gw(netif, gw);\r
117 }\r
118 \r
119 void netif_remove(struct netif * netif)\r
120 {\r
121   if ( netif == NULL ) return;\r
122 \r
123   snmp_delete_ipaddridx_tree(netif);\r
124 \r
125   /*  is it the first netif? */\r
126   if (netif_list == netif) {\r
127     netif_list = netif->next;\r
128     snmp_dec_iflist();\r
129   }\r
130   else {\r
131     /*  look for netif further down the list */\r
132     struct netif * tmpNetif;\r
133     for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {\r
134       if (tmpNetif->next == netif) {\r
135         tmpNetif->next = netif->next;\r
136         snmp_dec_iflist();\r
137         break;\r
138       }\r
139     }\r
140     if (tmpNetif == NULL)\r
141       return; /*  we didn't find any netif today */\r
142   }\r
143   /* this netif is default? */\r
144   if (netif_default == netif)\r
145     /* reset default netif */\r
146     netif_default = NULL;\r
147   LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );\r
148 }\r
149 \r
150 struct netif *\r
151 netif_find(char *name)\r
152 {\r
153   struct netif *netif;\r
154   u8_t num;\r
155 \r
156   if (name == NULL) {\r
157     return NULL;\r
158   }\r
159 \r
160   num = name[2] - '0';\r
161 \r
162   for(netif = netif_list; netif != NULL; netif = netif->next) {\r
163     if (num == netif->num &&\r
164        name[0] == netif->name[0] &&\r
165        name[1] == netif->name[1]) {\r
166       LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));\r
167       return netif;\r
168     }\r
169   }\r
170   LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));\r
171   return NULL;\r
172 }\r
173 \r
174 void\r
175 netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)\r
176 {\r
177   /* TODO: Handling of obsolete pcbs */\r
178   /* See:  http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */\r
179 #if LWIP_TCP\r
180   struct tcp_pcb *pcb;\r
181   struct tcp_pcb_listen *lpcb;\r
182 \r
183   /* address is actually being changed? */\r
184   if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)\r
185   {\r
186     /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */\r
187     LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));\r
188     pcb = tcp_active_pcbs;\r
189     while (pcb != NULL) {\r
190       /* PCB bound to current local interface address? */\r
191       if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {\r
192         /* this connection must be aborted */\r
193         struct tcp_pcb *next = pcb->next;\r
194         LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));\r
195         tcp_abort(pcb);\r
196         pcb = next;\r
197       } else {\r
198         pcb = pcb->next;\r
199       }\r
200     }\r
201     for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {\r
202       /* PCB bound to current local interface address? */\r
203       if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {\r
204         /* The PCB is listening to the old ipaddr and\r
205          * is set to listen to the new one instead */\r
206         ip_addr_set(&(lpcb->local_ip), ipaddr);\r
207       }\r
208     }\r
209   }\r
210 #endif\r
211   snmp_delete_ipaddridx_tree(netif);\r
212   snmp_delete_iprteidx_tree(0,netif);\r
213   /* set new IP address to netif */\r
214   ip_addr_set(&(netif->ip_addr), ipaddr);\r
215   snmp_insert_ipaddridx_tree(netif);\r
216   snmp_insert_iprteidx_tree(0,netif);\r
217 \r
218 #if 0 /* only allowed for Ethernet interfaces TODO: how can we check? */\r
219   /** For Ethernet network interfaces, we would like to send a\r
220    *  "gratuitous ARP"; this is an ARP packet sent by a node in order\r
221    *  to spontaneously cause other nodes to update an entry in their\r
222    *  ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6.\r
223    */ \r
224   etharp_query(netif, ipaddr, NULL);\r
225 #endif\r
226   LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",\r
227     netif->name[0], netif->name[1],\r
228     ip4_addr1(&netif->ip_addr),\r
229     ip4_addr2(&netif->ip_addr),\r
230     ip4_addr3(&netif->ip_addr),\r
231     ip4_addr4(&netif->ip_addr)));\r
232 }\r
233 \r
234 void\r
235 netif_set_gw(struct netif *netif, struct ip_addr *gw)\r
236 {\r
237   ip_addr_set(&(netif->gw), gw);\r
238   LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",\r
239     netif->name[0], netif->name[1],\r
240     ip4_addr1(&netif->gw),\r
241     ip4_addr2(&netif->gw),\r
242     ip4_addr3(&netif->gw),\r
243     ip4_addr4(&netif->gw)));\r
244 }\r
245 \r
246 void\r
247 netif_set_netmask(struct netif *netif, struct ip_addr *netmask)\r
248 {\r
249   snmp_delete_iprteidx_tree(0, netif);\r
250   /* set new netmask to netif */\r
251   ip_addr_set(&(netif->netmask), netmask);\r
252   snmp_insert_iprteidx_tree(0, netif);\r
253   LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",\r
254     netif->name[0], netif->name[1],\r
255     ip4_addr1(&netif->netmask),\r
256     ip4_addr2(&netif->netmask),\r
257     ip4_addr3(&netif->netmask),\r
258     ip4_addr4(&netif->netmask)));\r
259 }\r
260 \r
261 void\r
262 netif_set_default(struct netif *netif)\r
263 {\r
264   if (netif == NULL)\r
265   {\r
266     /* remove default route */\r
267     snmp_delete_iprteidx_tree(1, netif);\r
268   }\r
269   else\r
270   {\r
271     /* install default route */\r
272     snmp_insert_iprteidx_tree(1, netif);\r
273   }\r
274   netif_default = netif;\r
275   LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",\r
276            netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));\r
277 }\r
278 \r
279 /**\r
280  * Bring an interface up, available for processing\r
281  * traffic.\r
282  * \r
283  * @note: Enabling DHCP on a down interface will make it come\r
284  * up once configured.\r
285  * \r
286  * @see dhcp_start()\r
287  */ \r
288 void netif_set_up(struct netif *netif)\r
289 {\r
290   netif->flags |= NETIF_FLAG_UP;\r
291 #if LWIP_SNMP\r
292   snmp_get_sysuptime(&netif->ts);\r
293 #endif\r
294 }\r
295 \r
296 /**\r
297  * Ask if an interface is up\r
298  */ \r
299 u8_t netif_is_up(struct netif *netif)\r
300 {\r
301   return (netif->flags & NETIF_FLAG_UP)?1:0;\r
302 }\r
303 \r
304 /**\r
305  * Bring an interface down, disabling any traffic processing.\r
306  *\r
307  * @note: Enabling DHCP on a down interface will make it come\r
308  * up once configured.\r
309  * \r
310  * @see dhcp_start()\r
311  */ \r
312 void netif_set_down(struct netif *netif)\r
313 {\r
314   netif->flags &= ~NETIF_FLAG_UP;\r
315 #if LWIP_SNMP\r
316   snmp_get_sysuptime(&netif->ts);\r
317 #endif\r
318 }\r
319 \r
320 void\r
321 netif_init(void)\r
322 {\r
323   netif_list = netif_default = NULL;\r
324 }\r
325 \r