02a9eae8165a3c63fe55ee4f22676716d5a3bb07
[olsrd.git] / src / interfaces.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2003 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
7  * olsr.org is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsr.org is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include "defs.h"
24 #include "interfaces.h"
25 #include "ifnet.h"
26 #include "scheduler.h"
27
28 /**
29  *Do initialization of various data needed for
30  *network interface management.
31  *This function also tries to set up the given interfaces.
32  *
33  *@return the number of interfaces configured
34  */
35 int
36 ifinit()
37 {
38   struct if_name *tmp_if;
39
40
41   /* Initial values */
42   ifnet = NULL;
43   nbinterf = 0;
44
45   /*
46    *Initializing addrsock struct to be
47    *used on all the sockets
48    */
49   if(ipversion == AF_INET)
50     {
51       /* IP version 4 */
52       memset(&addrsock, 0, sizeof (addrsock));
53       addrsock.sin_family = AF_INET;
54       addrsock.sin_port = olsr_udp_port;
55       (addrsock.sin_addr).s_addr = INADDR_ANY;
56     }
57   else
58     {
59       /* IP version 6 */
60       memset(&addrsock6, 0, sizeof (addrsock6));
61       addrsock6.sin6_family = AF_INET6;
62       addrsock6.sin6_port = olsr_udp_port;
63       //(addrsock6.sin6_addr).s_addr = IN6ADDR_ANY_INIT;
64     }
65
66   olsr_printf(1, "\n ---- Interface configuration ---- \n\n");
67   /* Run trough all interfaces immedeatly */
68   for(tmp_if = if_names; tmp_if != NULL; tmp_if = tmp_if->next)
69     {
70       chk_if_up(tmp_if, 1);     
71     }
72   
73   /* register network interface update function with scheduler */
74   olsr_register_scheduler_event(&check_interface_updates, 5.0, 0, NULL);
75
76   return nbinterf;
77 }
78
79
80
81 /**
82  *Find the local interface with a given address.
83  *
84  *@param addr the address to check.
85  *
86  *@return the interface struct representing the interface
87  *that matched the address.
88  */
89
90 struct interface *
91 if_ifwithaddr(union olsr_ip_addr *addr)
92 {
93   struct interface *ifp;
94
95   for (ifp = ifnet; ifp; ifp = ifp->int_next)
96     {
97       if(ipversion == AF_INET)
98         {
99           /* IPv4 */
100           //printf("Checking: %s == ", inet_ntoa(((struct sockaddr_in *)&ifp->int_addr)->sin_addr));
101           //printf("%s\n", olsr_ip_to_string(addr));
102
103           if (COMP_IP(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr, addr))
104               return ifp;
105         }
106       else
107         {
108           /* IPv6 */
109           //printf("Checking %s ", olsr_ip_to_string((union olsr_ip_addr *)&ifp->int6_addr.sin6_addr));
110           //printf("== %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in6 *)addr)->sin6_addr));
111           if (COMP_IP(&ifp->int6_addr.sin6_addr, addr))
112             return ifp;
113         }
114     }
115   return NULL;
116 }
117
118
119
120 /**
121  *Find the interface with a given number.
122  *
123  *@param nr the number of the interface to find.
124  *
125  *@return return the interface struct representing the interface
126  *that matched the number.
127  */
128 struct interface *
129 if_ifwithsock(int fd)
130 {
131   struct interface *ifp;
132   ifp = ifnet;
133
134   while (ifp) 
135     {
136       if (ifp->olsr_socket == fd)
137         return ifp;
138       ifp = ifp->int_next;
139     }
140   
141   return (ifp);
142 }
143
144 #ifndef WIN32
145 /*
146  *From net-tools lib/interface.c
147  *
148  */
149
150 int
151 get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
152 {
153   char addr6[40], devname[IFNAMSIZ];
154   char addr6p[8][5];
155   int plen, scope, dad_status, if_idx;
156   FILE *f;
157   struct sockaddr_in6 tmp_sockaddr6;
158
159   if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) 
160     {
161       while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
162                     addr6p[0], addr6p[1], addr6p[2], addr6p[3],
163                     addr6p[4], addr6p[5], addr6p[6], addr6p[7],
164                     &if_idx, &plen, &scope, &dad_status, devname) != EOF) 
165         {
166           if (!strcmp(devname, ifname)) 
167             {
168               sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
169                       addr6p[0], addr6p[1], addr6p[2], addr6p[3],
170                       addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
171               if(debug_level > 1)
172                 {
173                   olsr_printf(1, "\tinet6 addr: %s\n", addr6);
174                   olsr_printf(3, "\tScope:");
175                 }
176               if(scope == scope_in)
177                 {
178                   olsr_printf(3, "IPv6 addr:\n");
179                   inet_pton(AF_INET6,addr6,&tmp_sockaddr6);
180                   memcpy(&saddr6->sin6_addr, &tmp_sockaddr6, sizeof(struct in6_addr));    
181                   fclose(f);
182                   return 1;
183                 }
184             }
185         }
186       fclose(f);
187     }
188   
189   return 0;
190 }
191 #endif
192
193
194
195
196
197 /**
198  *Create a new interf_name struct using a given
199  *name and insert it into the interface list.
200  *
201  *@param name the name of the interface.
202  *
203  *@return nada
204  */
205 void
206 queue_if(char *name)
207 {
208
209   struct if_name *interf_n;
210
211   //printf("Adding interface %s\n", name);
212
213   /* check if the inerfaces already exists */
214   interf_n = if_names;
215   while(interf_n != NULL)
216     {
217       if(memcmp(interf_n->name, name, strlen(name)) == 0)
218         {
219           fprintf(stderr, "Duplicate interfaces defined... not adding %s\n", name);
220           return;
221         }
222       interf_n = interf_n->next;
223     }
224
225   interf_n = olsr_malloc(sizeof(struct if_name), "queue interface");
226
227   /* strlen () does not return length including terminating /0 */
228   interf_n->name = olsr_malloc(strlen(name) + 1, "queue interface name");
229   interf_n->configured = 0;
230   interf_n->interf = NULL;
231   interf_n->index = queued_ifs++;
232
233   strcpy(interf_n->name, name);
234   interf_n->next = if_names;
235   if_names = interf_n;
236
237 }
238
239
240
241
242 /**
243  *Add an ifchange function. These functions are called on all (non-initial)
244  *changes in the interface set.
245  *
246  *@param
247  *
248  *@return
249  */
250 int
251 add_ifchgf(int (*f)(struct interface *, int))
252 {
253
254   struct ifchgf *new_ifchgf;
255
256   new_ifchgf = olsr_malloc(sizeof(struct ifchgf), "Add ifchgfunction");
257
258   new_ifchgf->next = ifchgf_list;
259   new_ifchgf->function = f;
260
261   ifchgf_list = new_ifchgf;
262
263   return 1;
264 }
265
266
267
268 /*
269  * Remove an ifchange function
270  */
271 int
272 del_ifchgf(int (*f)(struct interface *, int))
273 {
274   struct ifchgf *tmp_ifchgf, *prev;
275
276   tmp_ifchgf = ifchgf_list;
277   prev = NULL;
278
279   while(tmp_ifchgf)
280     {
281       if(tmp_ifchgf->function == f)
282         {
283           /* Remove entry */
284           if(prev == NULL)
285             {
286               ifchgf_list = tmp_ifchgf->next;
287               free(tmp_ifchgf);
288             }
289           else
290             {
291               prev->next = tmp_ifchgf->next;
292               free(tmp_ifchgf);
293             }
294           return 1;
295         }
296       prev = tmp_ifchgf;
297       tmp_ifchgf = tmp_ifchgf->next;
298     }
299
300   return 0;
301 }