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