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