a1605a525f7059675f9fd0ba154aeff17c209da6
[olsrd.git] / src / linux / kernel_routes.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of olsr.org.
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  * $ Id $
23  *
24  */
25
26
27 #include "../kernel_routes.h"
28 #include "../link_set.h"
29 #include "../olsr.h"
30 #include <net/if.h>
31 #include <sys/ioctl.h>
32
33 /**
34  *Insert a route in the kernel routing table
35  *
36  *@param destination the route to add
37  *
38  *@return negative on error
39  */
40 int
41 olsr_ioctl_add_route(struct rt_entry *destination)
42 {
43
44   struct rtentry kernel_route;
45   int tmp;
46
47   olsr_printf(1, "(ioctl)Adding route: %s ", 
48               olsr_ip_to_string(&destination->rt_dst));
49   olsr_printf(1, "gw %s (hopc %d)\n", 
50               olsr_ip_to_string(&destination->rt_router), 
51               destination->rt_metric);
52
53   memset(&kernel_route, 0, sizeof(struct rtentry));
54
55   ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
56   ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
57   ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
58
59   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = destination->rt_dst.v4;
60   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = destination->rt_mask.v4;
61
62   if(destination->rt_dst.v4 != destination->rt_router.v4)
63     {
64       ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr=destination->rt_router.v4;
65     }
66
67   kernel_route.rt_flags = destination->rt_flags;
68   
69   kernel_route.rt_metric = destination->rt_metric + 1;
70
71   /* 
72    * Thales Internet GW fix
73    */
74
75   if((del_gws) &&
76      (destination->rt_dst.v4 == INADDR_ANY) &&
77      (destination->rt_dst.v4 == INADDR_ANY))
78     {
79       delete_all_inet_gws();
80       del_gws = 0;
81     }
82
83   /*
84    * Set interface
85    */
86   if((kernel_route.rt_dev = malloc(strlen(destination->rt_if->int_name) + 1)) == 0)
87     {
88       fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
89       olsr_exit(__func__, EXIT_FAILURE);
90     }
91
92   strcpy(kernel_route.rt_dev, destination->rt_if->int_name);
93
94   
95   //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
96   
97   /*
98   printf("Adding route:\n\tdest: %s\n", olsr_ip_to_string(&destination->rt_dst));    
99   printf("\trouter: %s\n", olsr_ip_to_string(&destination->rt_router));    
100   printf("\tmask: %s\n", olsr_ip_to_string((union olsr_ip_addr *)&destination->rt_mask));    
101   printf("\tmetric: %d\n", destination->rt_metric);    
102   */
103
104   //printf("\tiface: %s\n", kernel_route.rt_dev);    
105   
106   tmp = ioctl(ioctl_s,SIOCADDRT,&kernel_route);
107   /*  kernel_route.rt_dev=*/
108
109   /*
110    *Send IPC route update message
111    */
112   
113   if(use_ipc)
114       {
115         if(destination->rt_router.v4)
116           ipc_route_send_rtentry((union olsr_kernel_route *)&kernel_route, 1, destination->rt_if->int_name); /* Send interface name */
117         else
118           ipc_route_send_rtentry((union olsr_kernel_route *)&kernel_route, 1, NULL);
119       }
120   
121   
122   if (ifnet && kernel_route.rt_dev)
123     {
124       free(kernel_route.rt_dev);
125     }
126   
127   
128   return tmp;
129 }
130
131
132
133
134 /**
135  *Insert a route in the kernel routing table
136  *
137  *@param destination the route to add
138  *
139  *@return negative on error
140  */
141 int
142 olsr_ioctl_add_route6(struct rt_entry *destination)
143 {
144
145   struct in6_rtmsg kernel_route;
146   int tmp;
147   struct in6_addr zeroaddr;
148
149   olsr_printf(2, "(ioctl)Adding route: %s(hopc %d)\n", 
150               olsr_ip_to_string(&destination->rt_dst), 
151               destination->rt_metric + 1);
152   
153
154   memset(&zeroaddr, 0, ipsize); /* Use for comparision */
155
156
157   memset(&kernel_route,0,sizeof(struct in6_rtmsg));
158
159   memcpy(&kernel_route.rtmsg_dst,
160          &destination->rt_dst,
161          ipsize);
162
163   kernel_route.rtmsg_flags = destination->rt_flags;
164   kernel_route.rtmsg_metric = destination->rt_metric;
165   
166   kernel_route.rtmsg_dst_len =   kernel_route.rtmsg_dst_len = destination->rt_mask.v6;
167
168   if(memcmp(&destination->rt_dst, &destination->rt_router.v6, ipsize) != 0)
169     {
170       memcpy(&kernel_route.rtmsg_gateway, 
171              &destination->rt_router,
172              ipsize);
173     }
174
175
176       /*
177        * set interface
178        */
179   kernel_route.rtmsg_ifindex = destination->rt_if->if_index;
180
181
182   
183   //olsr_printf(3, "Adding route to %s using gw ", olsr_ip_to_string((union olsr_ip_addr *)&kernel_route.rtmsg_dst));
184   //olsr_printf(3, "%s\n", olsr_ip_to_string((union olsr_ip_addr *)&kernel_route.rtmsg_gateway));
185
186   if((tmp = ioctl(ioctl_s, SIOCADDRT,&kernel_route)) < 0)
187     {
188       olsr_printf(1, "Add route: %s\n", strerror(errno));
189       olsr_syslog(OLSR_LOG_ERR, "Add route:%m");
190     }
191   else
192     {
193       if(use_ipc)
194         {
195           if(memcmp(&destination->rt_router, &null_addr6, ipsize) != 0)
196             ipc_route_send_rtentry((union olsr_kernel_route *)&kernel_route, 1, destination->rt_if->int_name); // Send interface name
197           else
198             ipc_route_send_rtentry((union olsr_kernel_route *)&kernel_route, 1, NULL);
199         }
200     }
201     return(tmp);
202 }
203
204
205
206 /**
207  *Remove a route from the kernel
208  *
209  *@param destination the route to remove
210  *
211  *@return negative on error
212  */
213 int
214 olsr_ioctl_del_route(struct rt_entry *destination)
215 {
216
217   struct rtentry kernel_route;
218   int tmp;
219
220   olsr_printf(1, "(ioctl)Deleting route: %s(hopc %d)\n", 
221               olsr_ip_to_string(&destination->rt_dst), 
222               destination->rt_metric + 1);
223
224   memset(&kernel_route,0,sizeof(struct rtentry));
225
226   ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
227   ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
228   ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
229
230   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = destination->rt_dst.v4;
231   if(destination->rt_dst.v4 != destination->rt_router.v4)
232     ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = destination->rt_router.v4;
233   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = destination->rt_mask.v4;
234
235
236   kernel_route.rt_dev = NULL;
237
238   kernel_route.rt_flags = destination->rt_flags;
239   
240   kernel_route.rt_metric = destination->rt_metric + 1;
241
242   /*
243   printf("Deleteing route:\n\tdest: %s\n", olsr_ip_to_string(&destination->rt_dst));    
244   printf("\trouter: %s\n", olsr_ip_to_string(&destination->rt_router));    
245   printf("\tmask: %s\n", olsr_ip_to_string((union olsr_ip_addr *)&destination->rt_mask));    
246   printf("\tmetric: %d\n", destination->rt_metric);    
247   //printf("\tiface: %s\n", kernel_route.rt_dev);    
248   */
249
250   tmp = ioctl(ioctl_s, SIOCDELRT, &kernel_route);
251
252
253     /*
254      *Send IPC route update message
255      */
256
257   if(use_ipc)
258     ipc_route_send_rtentry((union olsr_kernel_route *)&kernel_route, 0, NULL);
259
260   return tmp;
261 }
262
263
264
265
266
267
268 /**
269  *Remove a route from the kernel
270  *
271  *@param destination the route to remove
272  *
273  *@return negative on error
274  */
275 int
276 olsr_ioctl_del_route6(struct rt_entry *destination)
277 {
278
279   struct in6_rtmsg kernel_route;
280   int tmp;
281
282   union olsr_ip_addr tmp_addr = destination->rt_dst;
283
284   olsr_printf(2, "(ioctl)Deleting route: %s(hopc %d)\n", 
285               olsr_ip_to_string(&destination->rt_dst), 
286               destination->rt_metric + 1);
287
288
289   olsr_printf(1, "Deleting route: %s\n", olsr_ip_to_string(&tmp_addr));
290
291   memset(&kernel_route,0,sizeof(struct in6_rtmsg));
292
293   kernel_route.rtmsg_dst_len = destination->rt_mask.v6;
294
295   memcpy(&kernel_route.rtmsg_dst, &destination->rt_dst, ipsize);
296
297   memcpy(&kernel_route.rtmsg_gateway, &destination->rt_router, ipsize);
298
299
300   tmp = ioctl(ioctl_s, SIOCDELRT,&kernel_route);
301
302
303     /*
304      *Send IPC route update message
305      */
306
307   if(use_ipc)
308     ipc_route_send_rtentry((union olsr_kernel_route *)&kernel_route, 0, NULL);
309
310   return tmp;
311 }
312
313
314
315 /**
316  *Add a IP in IP tunnel route to a Internet gateway
317  *First add acess to the gateway node trough the tunnel
318  *then add the Internet gateway
319  *
320  *@return negative on error
321  */
322
323 int
324 add_tunnel_route(union olsr_ip_addr *gw)
325 {
326
327   struct rtentry kernel_route;
328   int tmp;
329   //olsr_u32_t adr, netmask;
330
331   /* Get gw netaddress */
332   /*
333   adr = ntohl(gw->v4);
334   if (IN_CLASSA(adr))
335     netmask = IN_CLASSA_NET;
336   else if (IN_CLASSB(adr))
337     netmask = IN_CLASSB_NET;
338   else
339     netmask = IN_CLASSC_NET;
340
341   netmask = htonl(netmask);
342   */
343   /* Global values */
344   /*
345   tunl_netmask = netmask;
346   tunl_gw = gw->v4;
347
348   printf("Adding route to gateway trough tunnel.\n\tNode %s\n", ip_to_string(&tunl_gw));
349   printf("\tMask %s\n", ip_to_string(&netmask));
350   */
351   /* Adding net */
352   /*
353   memset(&kernel_route,0,sizeof(struct rtentry));
354
355   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = tunl_gw;
356   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
357   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = netmask;
358   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
359   //((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
360   //((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
361
362   //memcpy(&kernel_route.rt_gateway, gw, ipsize);
363
364   kernel_route.rt_flags = RTF_UP;// | RTF_HOST;
365
366   kernel_route.rt_metric = 1;
367
368   if((kernel_route.rt_dev = malloc(6)) == 0)
369     {
370       fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
371       olsr_exit(__func__, EXIT_FAILURE);
372     }
373
374   strcpy(kernel_route.rt_dev, "tunl1");
375
376   
377   //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
378
379   if((tmp = ioctl(ioctl_s, SIOCADDRT, &kernel_route)) < 0)
380     perror("Add default Internet route net");
381
382
383   free(kernel_route.rt_dev);
384   */
385
386   /* Adding gateway */
387
388
389   memset(&kernel_route,0,sizeof(struct rtentry));
390
391   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = INADDR_ANY;
392   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
393   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = INADDR_ANY;
394   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
395   ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;//tunl_gw;
396   ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;
397
398
399   //olsr_printf(1, "Adding kernel route for Internet router trough tunnel\n");
400   
401   kernel_route.rt_metric = 0;
402
403   kernel_route.rt_flags = RTF_UP;// | RTF_GATEWAY;
404
405   if((kernel_route.rt_dev = malloc(6)) == 0)
406     {
407       fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
408       olsr_exit(__func__, EXIT_FAILURE);
409     }
410
411   strcpy(kernel_route.rt_dev, "tunl1");
412
413   
414   olsr_printf(1, "Inserting route entry on device %s\n\n", kernel_route.rt_dev);
415
416   if((tmp = ioctl(ioctl_s,SIOCADDRT,&kernel_route)) < 0)
417     {
418       olsr_printf(1, "Add tunnel route: %s\n", strerror(errno));
419       olsr_syslog(OLSR_LOG_ERR, "Add tunnel route:%m");
420     }
421
422   free(kernel_route.rt_dev);
423   
424   return(tmp);
425
426
427 }
428
429
430
431 int
432 delete_tunnel_route()
433 {
434   struct rtentry kernel_route;
435   int tmp;
436
437
438   /* Delete gateway */
439
440   olsr_printf(1, "Deleting tunnel GW route\n");
441
442   memset(&kernel_route,0,sizeof(struct rtentry));
443
444   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = INADDR_ANY;
445   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
446   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = INADDR_ANY;
447   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
448   
449   ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = tunl_gw;
450   ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;
451   
452   kernel_route.rt_metric = 1;
453   
454   kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
455
456   if((kernel_route.rt_dev = malloc(6)) == 0)
457     {
458       fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
459       olsr_exit(__func__, EXIT_FAILURE);
460     }
461
462   strcpy(kernel_route.rt_dev, "tunl1");
463
464   
465   //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
466
467   if((tmp = ioctl(ioctl_s,SIOCDELRT,&kernel_route)) < 0)
468     {
469       olsr_printf(1, "Del tunnel route: %s\n", strerror(errno));
470       olsr_syslog(OLSR_LOG_ERR, "Del tunnel route:%m");
471     }
472   
473   free(kernel_route.rt_dev);
474
475
476
477   olsr_printf(1, "Deleting route gateway trough tunnel.\n\tNet %s\n", ip_to_string(&tunl_gw));
478   olsr_printf(1, "\tMask %s\n", ip_to_string(&tunl_netmask));
479
480   /* Adding net */
481
482   memset(&kernel_route,0,sizeof(struct rtentry));
483
484   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = tunl_gw;
485   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
486   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = tunl_netmask;
487   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
488
489   //memcpy(&kernel_route.rt_gateway, gw, ipsize);
490
491   
492
493   kernel_route.rt_flags = RTF_UP | RTF_HOST;
494
495
496   if((kernel_route.rt_dev = malloc(6)) == 0)
497     {
498       fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
499       olsr_exit(__func__, EXIT_FAILURE);
500     }
501
502   strcpy(kernel_route.rt_dev, "tunl1");
503
504   
505   //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
506
507   if((tmp = ioctl(ioctl_s,SIOCDELRT,&kernel_route)) < 0)
508     {
509       olsr_printf(1, "Del tunnel route: %s\n", strerror(errno));
510       olsr_syslog(OLSR_LOG_ERR, "Del tunnel route:%m");
511     }
512   
513
514   free(kernel_route.rt_dev);
515
516   
517   return(tmp);
518 }
519
520
521
522
523
524
525 int
526 delete_all_inet_gws()
527 {
528   struct rtentry kernel_route;
529   
530   int s;
531   char buf[BUFSIZ], *cp, *cplim;
532   struct ifconf ifc;
533   struct ifreq *ifr;
534   
535   olsr_printf(1, "Internet gateway detected...\nTrying to delete default gateways\n");
536   
537   /* Get a socket */
538   if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
539     {
540       olsr_syslog(OLSR_LOG_ERR, "socket: %m");
541       close(s);
542       return -1;
543     }
544   
545   ifc.ifc_len = sizeof (buf);
546   ifc.ifc_buf = buf;
547   if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) 
548     {
549       olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");
550       close(s);
551       return -1;
552     }
553
554   ifr = ifc.ifc_req;
555 #define size(p) (sizeof (p))
556   cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
557   for (cp = buf; cp < cplim;cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) 
558     {
559       ifr = (struct ifreq *)cp;
560       
561       
562       if(strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0)
563         {
564           olsr_printf(1, "Skipping loopback...\n");
565           continue;
566         }
567
568       olsr_printf(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name);
569       
570       
571       memset(&kernel_route,0,sizeof(struct rtentry));
572       
573       ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;
574       ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
575       ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;
576       ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
577
578       ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
579       ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;
580       
581       //memcpy(&kernel_route.rt_gateway, gw, ipsize);
582       
583            
584            
585       kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
586            
587            
588       if((kernel_route.rt_dev = malloc(6)) == 0)
589         {
590           fprintf(stderr, "Out of memory!\n%s\n", strerror(errno));
591           olsr_exit(__func__, EXIT_FAILURE);
592         }
593            
594       strncpy(kernel_route.rt_dev, ifr->ifr_ifrn.ifrn_name, 6);
595
596   
597       //printf("Inserting route entry on device %s\n\n", kernel_route.rt_dev);
598       
599       if((ioctl(s, SIOCDELRT, &kernel_route)) < 0)
600         olsr_printf(1, "NO\n");
601       else
602         olsr_printf(1, "YES\n");
603
604
605       free(kernel_route.rt_dev);
606       
607     }
608   
609   close(s);
610   
611   return 0;
612        
613 }