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