* added -Wwrite-strings
[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.37 2007/11/16 19:12:55 bernd67 Exp $
40  */
41
42 #include "defs.h"
43 #include "interfaces.h"
44 #include "ifnet.h"
45 #include "scheduler.h"
46 #include "olsr.h"
47 #include "net_olsr.h"
48
49 static olsr_u32_t if_property_id;
50
51 /* The interface linked-list */
52 struct interface *ifnet;
53
54 /* Datastructures to use when creating new sockets */
55 struct sockaddr_in addrsock;
56 struct sockaddr_in6 addrsock6;
57
58
59 /* Ifchange functions */
60 struct ifchgf
61 {
62   int (*function)(struct interface *, int);
63   struct ifchgf *next;
64 };
65
66 static struct ifchgf *ifchgf_list;
67
68 /**
69  *Do initialization of various data needed for
70  *network interface management.
71  *This function also tries to set up the given interfaces.
72  *
73  *@return the number of interfaces configured
74  */
75 int
76 ifinit(void)
77 {
78   struct olsr_if *tmp_if;
79
80
81   /* Initial values */
82   ifnet = NULL;
83
84   /*
85    *Initializing addrsock struct to be
86    *used on all the sockets
87    */
88   if(olsr_cnf->ip_version == AF_INET)
89     {
90       /* IP version 4 */
91       memset(&addrsock, 0, sizeof (addrsock));
92       addrsock.sin_family = AF_INET;
93       addrsock.sin_port = htons(OLSRPORT);
94       (addrsock.sin_addr).s_addr = INADDR_ANY;
95     }
96   else
97     {
98       /* IP version 6 */
99       memset(&addrsock6, 0, sizeof (addrsock6));
100       addrsock6.sin6_family = AF_INET6;
101       addrsock6.sin6_port = htons(OLSRPORT);
102       //(addrsock6.sin6_addr).s_addr = IN6ADDR_ANY_INIT;
103     }
104
105   OLSR_PRINTF(1, "\n ---- Interface configuration ---- \n\n");
106     /* Run trough all interfaces immedeatly */
107     for(tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next)
108       {
109         if(!tmp_if->host_emul)
110           {
111             if(!olsr_cnf->host_emul) /* XXX: TEMPORARY! */
112               chk_if_up(tmp_if, 1);     
113           }
114         else
115           add_hemu_if(tmp_if);
116       }
117   
118   /* register network interface update function with scheduler */
119   olsr_register_scheduler_event(&check_interface_updates, NULL, 
120                                 olsr_cnf->nic_chgs_pollrate, 0, NULL);
121
122   return (ifnet == NULL) ? 0 : 1;
123 }
124
125
126 olsr_u32_t
127 get_if_property_id(void)
128 {
129   return if_property_id++;
130 }
131
132 olsr_bool
133 add_if_geninfo(struct interface *ifp, void *data, olsr_u32_t owner_id)
134 {
135   struct if_gen_property *igp;
136
137   if(get_if_geninfo(ifp, owner_id) != NULL)
138     return OLSR_FALSE;
139
140   igp = olsr_malloc(sizeof(struct if_gen_property), __func__);
141
142   igp->owner_id = owner_id;
143   igp->data = data;
144
145   /* queue */
146   igp->next = ifp->gen_properties;
147   ifp->gen_properties = igp;
148
149   return OLSR_TRUE;
150 }
151
152 void *
153 get_if_geninfo(struct interface *ifp, olsr_u32_t owner_id)
154 {
155   struct if_gen_property *igp_list = ifp->gen_properties;
156
157
158   while(igp_list)
159     {
160       if(igp_list->owner_id == owner_id)
161         return igp_list->data;
162
163       igp_list = igp_list->next;
164     }
165
166   return NULL;
167 }
168
169 void *
170 del_if_geninfo(struct interface *ifp, olsr_u32_t owner_id)
171 {
172   void *data = NULL;
173   struct if_gen_property *igp_list = ifp->gen_properties;
174   struct if_gen_property *igp_prev = NULL;
175
176
177   while(igp_list)
178     {
179       if(igp_list->owner_id == owner_id)
180         break;
181
182       igp_prev = igp_list;
183       igp_list = igp_list->next;
184     }
185
186   /* Not found */
187   if(igp_list == NULL)
188     return NULL;
189
190   /* Dequeue */
191   if(igp_prev == NULL)
192     {
193       /* First elem */
194       ifp->gen_properties = igp_list->next;
195     }
196   else
197     {
198       igp_prev->next = igp_list->next;
199     }
200   data = igp_list->data;
201   free(igp_list);
202
203   return data;
204 }
205
206
207 void
208 run_ifchg_cbs(struct interface *ifp, int flag)
209 {
210   struct ifchgf *tmp_ifchgf_list = ifchgf_list;
211
212   while(tmp_ifchgf_list != NULL)
213     {
214       tmp_ifchgf_list->function(ifp, flag);
215       tmp_ifchgf_list = tmp_ifchgf_list->next;
216     }
217 }
218
219
220 /**
221  *Find the local interface with a given address.
222  *
223  *@param addr the address to check.
224  *
225  *@return the interface struct representing the interface
226  *that matched the address.
227  */
228
229 struct interface *
230 if_ifwithaddr(const union olsr_ip_addr *addr)
231 {
232   struct interface *ifp;
233
234   if(!addr)
235     return NULL;
236
237   for (ifp = ifnet; ifp; ifp = ifp->int_next)
238     {
239       if(olsr_cnf->ip_version == AF_INET)
240         {
241           /* IPv4 */
242           //printf("Checking: %s == ", inet_ntoa(((struct sockaddr_in *)&ifp->int_addr)->sin_addr));
243           //printf("%s\n", olsr_ip_to_string(addr));
244
245           if (((struct sockaddr_in *)&ifp->int_addr)->sin_addr.s_addr == addr->v4.s_addr)
246               return ifp;
247         }
248       else
249         {
250           /* IPv6 */
251           //printf("Checking %s ", olsr_ip_to_string((union olsr_ip_addr *)&ifp->int6_addr.sin6_addr));
252           //printf("== %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in6 *)addr)->sin6_addr));
253           if (ip6equal(&ifp->int6_addr.sin6_addr, &addr->v6))
254             return ifp;
255         }
256     }
257   return NULL;
258 }
259
260
261
262 /**
263  *Find the interface with a given number.
264  *
265  *@param nr the number of the interface to find.
266  *
267  *@return return the interface struct representing the interface
268  *that matched the number.
269  */
270 struct interface *
271 if_ifwithsock(int fd)
272 {
273   struct interface *ifp;
274   ifp = ifnet;
275
276   while (ifp) 
277     {
278       if (ifp->olsr_socket == fd)
279         return ifp;
280       ifp = ifp->int_next;
281     }
282   
283   return NULL;
284 }
285
286
287 /**
288  *Find the interface with a given label.
289  *
290  *@param if_name the label of the interface to find.
291  *
292  *@return return the interface struct representing the interface
293  *that matched the label.
294  */
295 struct interface *
296 if_ifwithname(const char *if_name)
297 {
298   struct interface *ifp;
299   ifp = ifnet;
300
301   while (ifp) 
302     {
303       /* good ol' strcmp should be sufficcient here */
304       if (!strcmp(ifp->int_name, if_name))
305         return ifp;
306       ifp = ifp->int_next;
307     }
308   
309   return NULL;
310 }
311
312
313 /**
314  *Find the interface with a given interface index.
315  *
316  *@param iif_index of the interface to find.
317  *
318  *@return return the interface struct representing the interface
319  *that matched the iif_index.
320  */
321 struct interface *
322 if_ifwithindex(const int if_index)
323 {
324   struct interface *ifp = ifnet;
325   while (ifp) 
326     {
327       if (ifp->if_index == if_index)
328         return ifp;
329       ifp = ifp->int_next;
330     }
331   return NULL;
332 }
333
334
335 /**
336  *Get an interface name for a given interface index
337  *
338  *@param iif_index of the interface to find.
339  *
340  *@return "" or interface name.
341  */
342 const char *
343 if_ifwithindex_name(const int if_index)
344 {
345   const struct interface * const ifp = if_ifwithindex(if_index);
346   return ifp == NULL ? "void" : ifp->int_name;
347 }
348
349
350 /**
351  *Create a new interf_name struct using a given
352  *name and insert it into the interface list.
353  *
354  *@param name the name of the interface.
355  *
356  *@return nada
357  */
358 struct olsr_if *
359 queue_if(const char *name, int hemu)
360 {
361   struct olsr_if *interf_n = olsr_cnf->interfaces;
362
363   //printf("Adding interface %s\n", name);
364
365   /* check if the inerfaces already exists */
366   while(interf_n != NULL)
367     {
368       if(memcmp(interf_n->name, name, strlen(name)) == 0)
369         {
370           fprintf(stderr, "Duplicate interfaces defined... not adding %s\n", name);
371           return NULL;
372         }
373       interf_n = interf_n->next;
374     }
375
376   interf_n = olsr_malloc(sizeof(struct olsr_if), "queue interface");
377
378   /* strlen () does not return length including terminating /0 */
379   interf_n->name = olsr_malloc(strlen(name) + 1, "queue interface name");
380   interf_n->cnf = NULL;
381   interf_n->interf = NULL;
382   interf_n->configured = 0;
383
384   interf_n->host_emul = hemu ? OLSR_TRUE : OLSR_FALSE;
385
386   strncpy(interf_n->name, name, strlen(name) + 1);
387   interf_n->next = olsr_cnf->interfaces;
388   olsr_cnf->interfaces = interf_n;
389
390   return interf_n;
391 }
392
393
394
395 /**
396  *Add an ifchange function. These functions are called on all (non-initial)
397  *changes in the interface set.
398  *
399  *@param
400  *
401  *@return
402  */
403 int
404 add_ifchgf(int (*f)(struct interface *, int))
405 {
406
407   struct ifchgf *new_ifchgf;
408
409   new_ifchgf = olsr_malloc(sizeof(struct ifchgf), "Add ifchgfunction");
410
411   new_ifchgf->next = ifchgf_list;
412   new_ifchgf->function = f;
413
414   ifchgf_list = new_ifchgf;
415
416   return 1;
417 }
418
419
420
421 /*
422  * Remove an ifchange function
423  */
424 int
425 del_ifchgf(int (*f)(struct interface *, int))
426 {
427   struct ifchgf *tmp_ifchgf, *prev;
428
429   tmp_ifchgf = ifchgf_list;
430   prev = NULL;
431
432   while(tmp_ifchgf)
433     {
434       if(tmp_ifchgf->function == f)
435         {
436           /* Remove entry */
437           if(prev == NULL)
438             {
439               ifchgf_list = tmp_ifchgf->next;
440               free(tmp_ifchgf);
441             }
442           else
443             {
444               prev->next = tmp_ifchgf->next;
445               free(tmp_ifchgf);
446             }
447           return 1;
448         }
449       prev = tmp_ifchgf;
450       tmp_ifchgf = tmp_ifchgf->next;
451     }
452
453   return 0;
454 }