Removed various signed comparision warnings
[olsrd.git] / src / linux / kernel_routes.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: kernel_routes.c,v 1.18 2005/02/27 18:39:43 kattemat Exp $
40  */
41
42
43
44 #include "kernel_routes.h"
45 #include "link_set.h"
46 #include "olsr.h"
47 #include "log.h"
48 #include <net/if.h>
49 #include <sys/ioctl.h>
50 #include <unistd.h>
51
52
53
54 static struct sockaddr_in6 null_addr6; /* Address used as Originator Address IPv6 */
55
56 /**
57  *Insert a route in the kernel routing table
58  *
59  *@param destination the route to add
60  *
61  *@return negative on error
62  */
63 int
64 olsr_ioctl_add_route(struct rt_entry *destination)
65 {
66   struct rtentry kernel_route;
67   int tmp;
68   char dst_str[16], mask_str[16], router_str[16];
69
70   inet_ntop(AF_INET, &destination->rt_dst.v4, dst_str, 16);
71   inet_ntop(AF_INET, &destination->rt_mask.v4, mask_str, 16);
72   inet_ntop(AF_INET, &destination->rt_router.v4, router_str, 16);
73
74   OLSR_PRINTF(1, "(ioctl)Adding route with metric %d to %s/%s via %s/%s.\n",
75               destination->rt_metric, dst_str, mask_str, router_str,
76               destination->rt_if->int_name)
77   
78   memset(&kernel_route, 0, sizeof(struct rtentry));
79
80   ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
81   ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
82   ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
83
84   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = destination->rt_dst.v4;
85   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = destination->rt_mask.v4;
86
87   if(destination->rt_dst.v4 != destination->rt_router.v4)
88     {
89       ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr=destination->rt_router.v4;
90     }
91
92   kernel_route.rt_flags = destination->rt_flags;
93   
94   kernel_route.rt_metric = destination->rt_metric + 1;
95
96   /* 
97    * Thales Internet GW fix
98    */
99
100   if((del_gws) &&
101      (destination->rt_dst.v4 == INADDR_ANY) &&
102      (destination->rt_dst.v4 == INADDR_ANY))
103     {
104       delete_all_inet_gws();
105       del_gws = 0;
106     }
107
108   /*
109    * Set interface
110    */
111   if((kernel_route.rt_dev = malloc(strlen(destination->rt_if->int_name) + 1)) == 0)
112     {
113       fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
114       olsr_exit(__func__, EXIT_FAILURE);
115     }
116
117   strcpy(kernel_route.rt_dev, destination->rt_if->int_name);
118
119   
120   //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
121   
122   /*
123   printf("Adding route:\n\tdest: %s\n", olsr_ip_to_string(&destination->rt_dst));    
124   printf("\trouter: %s\n", olsr_ip_to_string(&destination->rt_router));    
125   printf("\tmask: %s\n", olsr_ip_to_string((union olsr_ip_addr *)&destination->rt_mask));    
126   printf("\tmetric: %d\n", destination->rt_metric);    
127   */
128
129   //printf("\tiface: %s\n", kernel_route.rt_dev);    
130   
131   tmp = ioctl(ioctl_s,SIOCADDRT,&kernel_route);
132   /*  kernel_route.rt_dev=*/
133
134   /*
135    *Send IPC route update message
136    */
137   
138   if(olsr_cnf->open_ipc)
139       {
140         ipc_route_send_rtentry(&destination->rt_dst, 
141                                &destination->rt_router, 
142                                destination->rt_metric, 
143                                1,
144                                destination->rt_if->int_name); /* Send interface name */
145       }
146   
147   
148   if (ifnet && kernel_route.rt_dev)
149     {
150       free(kernel_route.rt_dev);
151     }
152   
153   
154   return tmp;
155 }
156
157
158
159
160 /**
161  *Insert a route in the kernel routing table
162  *
163  *@param destination the route to add
164  *
165  *@return negative on error
166  */
167 int
168 olsr_ioctl_add_route6(struct rt_entry *destination)
169 {
170
171   struct in6_rtmsg kernel_route;
172   int tmp;
173   struct in6_addr zeroaddr;
174
175   OLSR_PRINTF(2, "(ioctl)Adding route: %s(hopc %d)\n", 
176               olsr_ip_to_string(&destination->rt_dst), 
177               destination->rt_metric + 1)
178   
179
180   memset(&zeroaddr, 0, ipsize); /* Use for comparision */
181
182
183   memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
184
185   COPY_IP(&kernel_route.rtmsg_dst, &destination->rt_dst);
186
187   kernel_route.rtmsg_flags = destination->rt_flags;
188   kernel_route.rtmsg_metric = destination->rt_metric;
189   
190   kernel_route.rtmsg_dst_len = destination->rt_mask.v6;
191
192   if(memcmp(&destination->rt_dst, &destination->rt_router, ipsize) != 0)
193     {
194       COPY_IP(&kernel_route.rtmsg_gateway, &destination->rt_router);
195     }
196   else
197     {
198       COPY_IP(&kernel_route.rtmsg_gateway, &destination->rt_dst);
199     }
200
201       /*
202        * set interface
203        */
204   kernel_route.rtmsg_ifindex = destination->rt_if->if_index;
205
206
207   
208   //OLSR_PRINTF(3, "Adding route to %s using gw ", olsr_ip_to_string((union olsr_ip_addr *)&kernel_route.rtmsg_dst))
209   //OLSR_PRINTF(3, "%s\n", olsr_ip_to_string((union olsr_ip_addr *)&kernel_route.rtmsg_gateway))
210
211   if((tmp = ioctl(ioctl_s, SIOCADDRT, &kernel_route)) >= 0)
212     {
213       if(olsr_cnf->open_ipc)
214         {
215           if(memcmp(&destination->rt_router, &null_addr6, ipsize) != 0)
216             ipc_route_send_rtentry(&destination->rt_dst, 
217                                    &destination->rt_router, 
218                                    destination->rt_metric, 
219                                    1,
220                                    destination->rt_if->int_name); /* Send interface name */
221
222         }
223     }
224     return(tmp);
225 }
226
227
228
229 /**
230  *Remove a route from the kernel
231  *
232  *@param destination the route to remove
233  *
234  *@return negative on error
235  */
236 int
237 olsr_ioctl_del_route(struct rt_entry *destination)
238 {
239   struct rtentry kernel_route;
240   int tmp;
241   char dst_str[16], mask_str[16], router_str[16];
242
243   inet_ntop(AF_INET, &destination->rt_dst.v4, dst_str, 16);
244   inet_ntop(AF_INET, &destination->rt_mask.v4, mask_str, 16);
245   inet_ntop(AF_INET, &destination->rt_router.v4, router_str, 16);
246
247   OLSR_PRINTF(1, "(ioctl)Deleting route with metric %d to %s/%s via %s/%s.\n",
248               destination->rt_metric, dst_str, mask_str, router_str,
249               destination->rt_if->int_name)
250   
251   memset(&kernel_route,0,sizeof(struct rtentry));
252
253   ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
254   ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
255   ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
256
257   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = destination->rt_dst.v4;
258   if(destination->rt_dst.v4 != destination->rt_router.v4)
259     ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = destination->rt_router.v4;
260   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = destination->rt_mask.v4;
261
262
263   kernel_route.rt_dev = NULL;
264
265   kernel_route.rt_flags = destination->rt_flags;
266   
267   kernel_route.rt_metric = destination->rt_metric + 1;
268
269   /*
270   printf("Deleteing route:\n\tdest: %s\n", olsr_ip_to_string(&destination->rt_dst));    
271   printf("\trouter: %s\n", olsr_ip_to_string(&destination->rt_router));    
272   printf("\tmask: %s\n", olsr_ip_to_string((union olsr_ip_addr *)&destination->rt_mask));    
273   printf("\tmetric: %d\n", destination->rt_metric);    
274   //printf("\tiface: %s\n", kernel_route.rt_dev);    
275   */
276
277   tmp = ioctl(ioctl_s, SIOCDELRT, &kernel_route);
278
279
280     /*
281      *Send IPC route update message
282      */
283
284   if(olsr_cnf->open_ipc)
285     ipc_route_send_rtentry(&destination->rt_dst, 
286                            NULL, 
287                            destination->rt_metric, 
288                            0,
289                            NULL); /* Send interface name */
290
291   return tmp;
292 }
293
294
295
296
297
298
299 /**
300  *Remove a route from the kernel
301  *
302  *@param destination the route to remove
303  *
304  *@return negative on error
305  */
306 int
307 olsr_ioctl_del_route6(struct rt_entry *destination)
308 {
309
310   struct in6_rtmsg kernel_route;
311   int tmp;
312
313   union olsr_ip_addr tmp_addr = destination->rt_dst;
314
315   OLSR_PRINTF(2, "(ioctl)Deleting route: %s(hopc %d)\n", 
316               olsr_ip_to_string(&destination->rt_dst), 
317               destination->rt_metric)
318
319
320   OLSR_PRINTF(1, "Deleting route: %s\n", olsr_ip_to_string(&tmp_addr))
321
322   memset(&kernel_route,0,sizeof(struct in6_rtmsg));
323
324   kernel_route.rtmsg_dst_len = destination->rt_mask.v6;
325
326   memcpy(&kernel_route.rtmsg_dst, &destination->rt_dst, ipsize);
327
328   memcpy(&kernel_route.rtmsg_gateway, &destination->rt_router, ipsize);
329
330   kernel_route.rtmsg_flags = destination->rt_flags;
331   kernel_route.rtmsg_metric = destination->rt_metric;
332
333
334   tmp = ioctl(ioctl_s, SIOCDELRT,&kernel_route);
335
336
337     /*
338      *Send IPC route update message
339      */
340
341   if(olsr_cnf->open_ipc)
342     ipc_route_send_rtentry(&destination->rt_dst, 
343                            NULL, 
344                            destination->rt_metric, 
345                            0,
346                            NULL); /* Send interface name */
347
348   return tmp;
349 }
350
351
352
353 int
354 delete_all_inet_gws()
355 {
356   struct rtentry kernel_route;
357   
358   int s;
359   char buf[BUFSIZ], *cp, *cplim;
360   struct ifconf ifc;
361   struct ifreq *ifr;
362   
363   OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n")
364   
365   /* Get a socket */
366   if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
367     {
368       olsr_syslog(OLSR_LOG_ERR, "socket: %m");
369       close(s);
370       return -1;
371     }
372   
373   ifc.ifc_len = sizeof (buf);
374   ifc.ifc_buf = buf;
375   if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) 
376     {
377       olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");
378       close(s);
379       return -1;
380     }
381
382   ifr = ifc.ifc_req;
383 #define size(p) (sizeof (p))
384   cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
385   for (cp = buf; cp < cplim;cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) 
386     {
387       ifr = (struct ifreq *)cp;
388       
389       
390       if(strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0)
391         {
392           OLSR_PRINTF(1, "Skipping loopback...\n")
393           continue;
394         }
395
396       OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name)
397       
398       
399       memset(&kernel_route,0,sizeof(struct rtentry));
400       
401       ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;
402       ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
403       ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;
404       ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
405
406       ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
407       ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;
408       
409       //memcpy(&kernel_route.rt_gateway, gw, ipsize);
410       
411            
412            
413       kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
414            
415            
416       if((kernel_route.rt_dev = malloc(6)) == 0)
417         {
418           fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
419           olsr_exit(__func__, EXIT_FAILURE);
420         }
421            
422       strncpy(kernel_route.rt_dev, ifr->ifr_ifrn.ifrn_name, 6);
423
424   
425       //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
426       
427       if((ioctl(s, SIOCDELRT, &kernel_route)) < 0)
428         OLSR_PRINTF(1, "NO\n")
429       else
430         OLSR_PRINTF(1, "YES\n")
431
432
433       free(kernel_route.rt_dev);
434       
435     }
436   
437   close(s);
438   
439   return 0;
440        
441 }