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