Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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