Added a small abstraction layer for the if geninfo stuff. Functions add_if_geninfo...
[olsrd.git] / src / interfaces.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: interfaces.c,v 1.19 2005/03/06 12:38:09 kattemat Exp $
40  */
41
42 #include "defs.h"
43 #include "interfaces.h"
44 #include "ifnet.h"
45 #include "scheduler.h"
46 #include "olsr.h"
47
48 static olsr_u32_t if_property_id;
49
50 /* Ifchange functions */
51 struct ifchgf
52 {
53   int (*function)(struct interface *, int);
54   struct ifchgf *next;
55 };
56
57 static olsr_u32_t
58 get_if_property_id(void);
59
60 static struct ifchgf *ifchgf_list;
61
62 /**
63  *Do initialization of various data needed for
64  *network interface management.
65  *This function also tries to set up the given interfaces.
66  *
67  *@return the number of interfaces configured
68  */
69 int
70 ifinit()
71 {
72   struct olsr_if *tmp_if;
73
74
75   /* Initial values */
76   ifnet = NULL;
77
78   /*
79    *Initializing addrsock struct to be
80    *used on all the sockets
81    */
82   if(olsr_cnf->ip_version == AF_INET)
83     {
84       /* IP version 4 */
85       memset(&addrsock, 0, sizeof (addrsock));
86       addrsock.sin_family = AF_INET;
87       addrsock.sin_port = olsr_udp_port;
88       (addrsock.sin_addr).s_addr = INADDR_ANY;
89     }
90   else
91     {
92       /* IP version 6 */
93       memset(&addrsock6, 0, sizeof (addrsock6));
94       addrsock6.sin6_family = AF_INET6;
95       addrsock6.sin6_port = olsr_udp_port;
96       //(addrsock6.sin6_addr).s_addr = IN6ADDR_ANY_INIT;
97     }
98
99   OLSR_PRINTF(1, "\n ---- Interface configuration ---- \n\n")
100   /* Run trough all interfaces immedeatly */
101   for(tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next)
102     {
103       chk_if_up(tmp_if, 1);     
104     }
105   
106   /* register network interface update function with scheduler */
107   olsr_register_scheduler_event(&check_interface_updates, NULL, 5.0, 0, NULL);
108
109   return (ifnet == NULL) ? 0 : 1;
110 }
111
112
113 static olsr_u32_t
114 get_if_property_id()
115 {
116   return if_property_id++;
117 }
118
119 olsr_u32_t
120 add_if_geninfo(struct interface *ifp, void *data)
121 {
122   struct if_gen_property *igp = olsr_malloc(sizeof(struct if_gen_property), __func__);
123
124   igp->owner_id = get_if_property_id();
125   igp->data = data;
126
127   /* queue */
128   igp->next = ifp->gen_properties;
129   ifp->gen_properties = igp;
130
131   return igp->owner_id;
132 }
133
134 void *
135 get_if_geninfo(struct interface *ifp, olsr_u32_t owner_id)
136 {
137   struct if_gen_property *igp_list = ifp->gen_properties;
138
139
140   while(igp_list)
141     {
142       if(igp_list->owner_id == owner_id)
143         return igp_list->data;
144
145       igp_list = igp_list->next;
146     }
147
148   return NULL;
149 }
150
151 void *
152 del_if_geninfo(struct interface *ifp, olsr_u32_t owner_id)
153 {
154   void *data = NULL;
155   struct if_gen_property *igp_list = ifp->gen_properties;
156   struct if_gen_property *igp_prev = NULL;
157
158
159   while(igp_list)
160     {
161       if(igp_list->owner_id == owner_id)
162         break;
163
164       igp_prev = igp_list;
165       igp_list = igp_list->next;
166     }
167
168   /* Not found */
169   if(igp_list == NULL)
170     return NULL;
171
172   /* Dequeue */
173   if(igp_prev == NULL)
174     {
175       /* First elem */
176       ifp->gen_properties = igp_list->next;
177     }
178   else
179     {
180       igp_prev->next = igp_list->next;
181     }
182   data = igp_list->data;
183   free(igp_list);
184
185   return data;
186 }
187
188
189 void
190 run_ifchg_cbs(struct interface *ifp, int flag)
191 {
192   struct ifchgf *tmp_ifchgf_list = ifchgf_list;
193
194   while(tmp_ifchgf_list != NULL)
195     {
196       tmp_ifchgf_list->function(ifp, flag);
197       tmp_ifchgf_list = tmp_ifchgf_list->next;
198     }
199 }
200
201
202 /**
203  *Find the local interface with a given address.
204  *
205  *@param addr the address to check.
206  *
207  *@return the interface struct representing the interface
208  *that matched the address.
209  */
210
211 struct interface *
212 if_ifwithaddr(union olsr_ip_addr *addr)
213 {
214   struct interface *ifp;
215
216   if(!addr)
217     return NULL;
218
219   for (ifp = ifnet; ifp; ifp = ifp->int_next)
220     {
221       if(olsr_cnf->ip_version == AF_INET)
222         {
223           /* IPv4 */
224           //printf("Checking: %s == ", inet_ntoa(((struct sockaddr_in *)&ifp->int_addr)->sin_addr));
225           //printf("%s\n", olsr_ip_to_string(addr));
226
227           if (COMP_IP(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr, addr))
228               return ifp;
229         }
230       else
231         {
232           /* IPv6 */
233           //printf("Checking %s ", olsr_ip_to_string((union olsr_ip_addr *)&ifp->int6_addr.sin6_addr));
234           //printf("== %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in6 *)addr)->sin6_addr));
235           if (COMP_IP(&ifp->int6_addr.sin6_addr, addr))
236             return ifp;
237         }
238     }
239   return NULL;
240 }
241
242
243
244 /**
245  *Find the interface with a given number.
246  *
247  *@param nr the number of the interface to find.
248  *
249  *@return return the interface struct representing the interface
250  *that matched the number.
251  */
252 struct interface *
253 if_ifwithsock(int fd)
254 {
255   struct interface *ifp;
256   ifp = ifnet;
257
258   while (ifp) 
259     {
260       if (ifp->olsr_socket == fd)
261         return ifp;
262       ifp = ifp->int_next;
263     }
264   
265   return NULL;
266 }
267
268
269 /**
270  *Find the interface with a given label.
271  *
272  *@param if_name the label of the interface to find.
273  *
274  *@return return the interface struct representing the interface
275  *that matched the label.
276  */
277 struct interface *
278 if_ifwithname(const char *if_name)
279 {
280   struct interface *ifp;
281   ifp = ifnet;
282
283   while (ifp) 
284     {
285       /* good ol' strcmp should be sufficcient here */
286       if (!strcmp(ifp->int_name, if_name))
287         return ifp;
288       ifp = ifp->int_next;
289     }
290   
291   return NULL;
292 }
293
294
295 /**
296  *Create a new interf_name struct using a given
297  *name and insert it into the interface list.
298  *
299  *@param name the name of the interface.
300  *
301  *@return nada
302  */
303 void
304 queue_if(char *name)
305 {
306
307   struct olsr_if *interf_n = olsr_cnf->interfaces;
308
309   //printf("Adding interface %s\n", name);
310
311   /* check if the inerfaces already exists */
312   while(interf_n != NULL)
313     {
314       if(memcmp(interf_n->name, name, strlen(name)) == 0)
315         {
316           fprintf(stderr, "Duplicate interfaces defined... not adding %s\n", name);
317           return;
318         }
319       interf_n = interf_n->next;
320     }
321
322   interf_n = olsr_malloc(sizeof(struct olsr_if), "queue interface");
323
324   /* strlen () does not return length including terminating /0 */
325   interf_n->name = olsr_malloc(strlen(name) + 1, "queue interface name");
326   interf_n->cnf = NULL;
327   interf_n->interf = NULL;
328   interf_n->configured = 0;
329   interf_n->index = olsr_cnf->ifcnt++;
330
331   strcpy(interf_n->name, name);
332   interf_n->next = olsr_cnf->interfaces;
333   olsr_cnf->interfaces = interf_n;
334
335 }
336
337
338
339 /**
340  *Add an ifchange function. These functions are called on all (non-initial)
341  *changes in the interface set.
342  *
343  *@param
344  *
345  *@return
346  */
347 int
348 add_ifchgf(int (*f)(struct interface *, int))
349 {
350
351   struct ifchgf *new_ifchgf;
352
353   new_ifchgf = olsr_malloc(sizeof(struct ifchgf), "Add ifchgfunction");
354
355   new_ifchgf->next = ifchgf_list;
356   new_ifchgf->function = f;
357
358   ifchgf_list = new_ifchgf;
359
360   return 1;
361 }
362
363
364
365 /*
366  * Remove an ifchange function
367  */
368 int
369 del_ifchgf(int (*f)(struct interface *, int))
370 {
371   struct ifchgf *tmp_ifchgf, *prev;
372
373   tmp_ifchgf = ifchgf_list;
374   prev = NULL;
375
376   while(tmp_ifchgf)
377     {
378       if(tmp_ifchgf->function == f)
379         {
380           /* Remove entry */
381           if(prev == NULL)
382             {
383               ifchgf_list = tmp_ifchgf->next;
384               free(tmp_ifchgf);
385             }
386           else
387             {
388               prev->next = tmp_ifchgf->next;
389               free(tmp_ifchgf);
390             }
391           return 1;
392         }
393       prev = tmp_ifchgf;
394       tmp_ifchgf = tmp_ifchgf->next;
395     }
396
397   return 0;
398 }