94a244b9e8d052cbe7a32e8fecee818872eba328
[olsrd.git] / src / linux / kernel_routes.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
4  * Copyright (c) 2007, Sven-Ola for the policy routing stuff
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include "kernel_routes.h"
43 #include "ipc_frontend.h"
44 #include "log.h"
45
46 /* values for control flag to handle recursive route corrections 
47  *  currently only requires in linux specific kernel_routes.c */
48
49 #define RT_ORIG_REQUEST 0
50 #define RT_RETRY_AFTER_ADD_GATEWAY 1
51 #define RT_RETRY_AFTER_DELETE_SIMILAR 2
52 #define RT_DELETE_SIMILAR_ROUTE 3
53 #define RT_AUTO_ADD_GATEWAY_ROUTE 4
54 #define RT_DELETE_SIMILAR_AUTO_ROUTE 5
55 #define RT_NIIT 6
56 #define RT_SMARTGW 7
57
58 #if !LINUX_POLICY_ROUTING
59
60 static int delete_all_inet_gws(void);
61
62 #else /* !LINUX_POLICY_ROUTING */
63
64 #include <assert.h>
65 #include <linux/types.h>
66 #include <linux/rtnetlink.h>
67
68 //ipip includes
69 #include <netinet/in.h>
70 #include <sys/ioctl.h>
71 #include <net/if.h>
72 #include <linux/ip.h>
73 #include <linux/if_tunnel.h>
74
75 //ifup includes
76 #include <sys/socket.h>
77 #include <sys/ioctl.h>
78 #include <sys/types.h>
79 #include <net/if.h>
80
81 extern struct rtnl_handle rth;
82
83 struct olsr_rtreq {
84   struct nlmsghdr n;
85   struct rtmsg r;
86   char buf[512];
87 };
88
89 /*takes up or down (flag IF_SET_DOWN) an interface (optionally able to configure an /32 ip aswell IF_SET_IP)*/
90 /* parameter
91  * dev device name
92  * flags:
93  * IF_SET_UP, IF_SET_DOWN set interface up or down
94  * IF_CHECK_UP, IF_CHECK_DOWN only check interface state, dont change (returns false or 1)
95  * IF_SET_IP set interface up and set interface ip to originator address
96  * return value:
97  * 0 on error/failure (or failed CHECK)
98  * -1 on success (and interface state was changed)
99  *  1 if interface was already up/down*/
100 int olsr_ifconfig(const char * dev,int flag)
101 {
102   int s, r;
103   struct ifreq ifr;
104   s = socket(PF_INET, SOCK_DGRAM, 0);
105   if (s < 0) {
106     perror("socket");
107     return(-1);
108   }
109   memset(&ifr, 0, sizeof(ifr));
110   strncpy(ifr.ifr_name, dev, IFNAMSIZ);
111
112   if (flag == IF_SET_IP){
113     struct sockaddr_in sin;
114     memset(&sin, 0, sizeof(struct sockaddr_in));
115     sin.sin_family = AF_INET; //ipv4 only!
116     sin.sin_addr.s_addr = olsr_cnf->main_addr.v4.s_addr;
117     memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr_in));
118
119     r = ioctl(s, SIOCSIFADDR, &ifr);
120     if (r < 0){
121       perror("ioctl");
122       return false;
123     }
124     /*reset ifreq fuild for IFFLGAS*/
125     memset(&sin, 0, sizeof( struct sockaddr_in) );
126   }
127
128   ifr.ifr_flags = IFF_UP; //!!?? read old flags and before setting new ones
129   r = ioctl(s, SIOCGIFFLAGS, &ifr);
130   /*set to UP/DOWN now*/
131   if ((flag == IF_SET_DOWN)||(flag == IF_CHECK_DOWN)) {
132     /*check if already down*/
133     if ((short int)ifr.ifr_flags & IFF_UP) ifr.ifr_flags &= ~IFF_UP;
134     else return 1;
135     if (flag == IF_CHECK_DOWN) return false;
136   }
137   else {
138     /*check if already up*/
139     if ((short int)ifr.ifr_flags & IFF_UP) return 1;
140     else ifr.ifr_flags |= IFF_UP;
141     if (flag == IF_CHECK_UP) return false;
142   }
143   
144   r = ioctl(s, SIOCSIFFLAGS, &ifr);
145   if (r < 0) {
146     perror("ioctl");
147     return false;
148   }
149   return -1;
150 }
151                                         
152 #if LINUX_RTNETLINK_LISTEN
153 #include "ifnet.h"
154 #include "socket_parser.h"
155
156 int rtnetlink_register_socket(int rtnl_mgrp)
157 {
158   int sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
159   struct sockaddr_nl addr;
160
161   if (sock<0) {
162     OLSR_PRINTF(1,"could not create rtnetlink socket! %d",sock);
163   }
164   else {
165     memset(&addr, 0, sizeof(addr));
166
167     addr.nl_family = AF_NETLINK;
168     addr.nl_pid = 0; //kernel will assign appropiate number instead of pid (which is already used by primaray rtnetlink socket to add/delete routes)
169     addr.nl_groups = rtnl_mgrp;
170     if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0) {
171       OLSR_PRINTF(1,"could not bind socket! (%d %s)",errno,strerror(errno));
172     }
173     else {
174       add_olsr_socket(sock, &rtnetlink_read);
175     }
176     fcntl(sock, F_SETFL, O_NONBLOCK);
177   }
178   return sock;
179 }
180
181 static void netlink_process_link(struct nlmsghdr *h)
182 {
183   struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(h);
184   struct interface *iface;
185   struct olsr_if *tmp_if;
186
187   /*monitor tunl0 and olsrtunl*/
188   if (olsr_cnf->smart_gw_active) {
189     if (ifi->ifi_index==olsr_cnf->ipip_if_index) {
190       printf("olsrtunl state change:\n");
191       if (ifi->ifi_flags&IFF_UP)
192       {
193         printf("is up now\n");
194         olsr_cnf->ipip_if_up=true;
195       }
196       else if (olsr_cnf->ipip_if_up) {
197         /*we try to delete the interface completely (only if it is down, and was up before)*/
198         olsr_del_tunl();
199         //!!?? shall we mark the default route dirty?
200         /*we mark it unexisting -> we will create the tunnel again (if gateway changes)*/
201         olsr_cnf->ipip_if_index = olsr_cnf->ipip_if_up = false;
202       }
203       else printf("interface is down, but was never up -> ignoring!\n");
204       return;
205     }
206     if (ifi->ifi_index==olsr_cnf->ipip_base_if.if_index) {
207       if (ifi->ifi_flags&IFF_UP) {
208         /*we try to take it up again (if its only down it might workout)*/
209         printf("tunl0 is down, we try to take it up again\n");
210         if (olsr_ifconfig("tunl0",IF_SET_UP)) return; //!!?? todo: test if we can really know that its up now
211         /*we disable -> this should stop us announcing being a smart gateway, 
212         * and can not use tunnels as its unlikely to be able to crete them without tunl0*/
213         olsr_cnf->smart_gw_active=false;
214         /*recovery is not easy as potentially the ipip module is not loaded any more*/
215         /*but it could just mean the tunl0 is down, and the gatewaytunnel would work*/
216         return;
217       }
218     }
219   }
220
221   iface = if_ifwithindex(ifi->ifi_index);
222   if (iface == NULL) {
223     return;
224   }
225   
226   //all IFF flags: LOOPBACK,BROADCAST;POINTOPOINT;MULTICAST;NOARP;ALLMULTI;PROMISC;MASTER;SLAVE;DEBUG;DYNAMIC;AUTOMEDIA;PORTSEL;NOTRAILERS;UP;LOWER_UP;DORMANT
227   /* check if interface is up and running? (a not running interface keeps its routes, so better not react like on ifdown!!??) */
228   if (ifi->ifi_flags&IFF_UP) {
229     OLSR_PRINTF(3,"interface %s changed but is still up!\n", iface->int_name);
230     return; //we are currently only interested in interfaces that are/go down
231   } else {
232     OLSR_PRINTF(1,"interface %s is down!\n", iface->int_name);
233   }
234
235   //only for still configured interfaces (ifup has to be detected with regular interface polling)
236   for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) {
237     if (tmp_if->interf==iface) {
238       OLSR_PRINTF(1,"-> removing %s from olsr config!\n", iface->int_name);
239       RemoveInterface(tmp_if,true);
240       break;
241     }
242   }
243 }
244
245 void rtnetlink_read(int sock)
246 {
247   int len, plen;
248   struct iovec iov;
249   struct sockaddr_nl nladdr;
250   struct msghdr msg = {
251     &nladdr,
252     sizeof(nladdr),
253     &iov,
254     1,
255     NULL,
256     0,
257     0
258   };
259
260   char buffer[4096];
261   struct nlmsghdr *nlh = (struct nlmsghdr *)(ARM_NOWARN_ALIGN) buffer;
262   int ret;
263
264   iov.iov_base = (void *) buffer;
265   iov.iov_len = sizeof(buffer);
266
267   while (true) { //read until ret<0;
268     ret=recvmsg(sock, &msg, 0);
269     if (ret<0) {
270       if (errno != EAGAIN) OLSR_PRINTF(1,"netlink listen error %u - %s\n",errno,strerror(errno));
271       return;
272     }
273     /*check message*/
274     len = nlh->nlmsg_len;
275     plen = len - sizeof(nlh);
276     if (len > ret || plen < 0) {
277       OLSR_PRINTF(1,"Malformed netlink message: "
278              "len=%d left=%d plen=%d\n",
279               len, ret, plen);
280       return;
281     }
282     if ( (nlh->nlmsg_type == RTM_NEWLINK) || ( nlh->nlmsg_type == RTM_DELLINK) ) netlink_process_link(nlh);
283   }
284 }
285
286 //!!?? listen on our own tunlx interfaces aswell
287
288 #endif /*linux_rtnetlink_listen*/
289
290 /*create or change a ipip tunnel ipv4 only*/
291 static int set_tunl(int cmd, unsigned long int ipv4)
292 {
293   struct ifreq ifr;
294   int fd;
295   int err;
296   struct ip_tunnel_parm p;
297
298   p.iph.version = 4;
299   p.iph.ihl = 5;
300   p.iph.protocol=IPPROTO_IPIP; //IPPROTO_IPV6
301   p.iph.saddr=0x00000000;
302   p.iph.daddr=ipv4;
303
304   strncpy(p.name, olsr_cnf->ipip_name, IFNAMSIZ);
305 printf("set tunl to name: %s\n",p.name);
306
307   //specify existing interface name
308   if (cmd==SIOCADDTUNNEL) strncpy(ifr.ifr_name, TUNL_BASE, IFNAMSIZ);
309   else strncpy(ifr.ifr_name, olsr_cnf->ipip_name, IFNAMSIZ);
310
311 printf("set tunl %s\n",ifr.ifr_name);
312
313   ifr.ifr_ifru.ifru_data = (void *) &p;
314   fd = socket(AF_INET, SOCK_DGRAM, 0);//warning hardcoded AF_INET
315   err = ioctl(fd, cmd, &ifr);
316 printf("set tunl result %i\n",err);
317   if (err) perror("ioctl");
318   close(fd);
319   return err;
320 }
321
322 int olsr_del_tunl(void)
323 {
324   printf("-----\ndelete olsrtunle!\n");
325   return set_tunl(SIOCDELTUNNEL,0x00000000);//!!??test if this deletes tunnel
326 }
327
328 static void
329 olsr_netlink_addreq(struct olsr_rtreq *req, int type, const void *data, int len)
330 {
331   struct rtattr *rta = (struct rtattr *)(ARM_NOWARN_ALIGN)(((char *)req) + NLMSG_ALIGN(req->n.nlmsg_len));
332   req->n.nlmsg_len = NLMSG_ALIGN(req->n.nlmsg_len) + RTA_LENGTH(len);
333   assert(req->n.nlmsg_len < sizeof(struct olsr_rtreq));
334   rta->rta_type = type;
335   rta->rta_len = RTA_LENGTH(len);
336   memcpy(RTA_DATA(rta), data, len);
337 }
338
339 /* returns
340  * -1 on unrecoverable error (calling function will have to handle it)
341  *  0 on unexpected but recoverable rtnetlink behaviour
342  *    but some of the implemented recovery methods only cure symptoms, 
343  *    not the cause, like unintelligent ordering of inserted routes.
344  *  1 on success */
345 static int
346 olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd, uint32_t flag)
347 {
348   int ret = 1; /* helper variable for rtnetlink_message processing */
349   int rt_ret = -2;  /* if no response from rtnetlink it must be considered as failed! */
350   struct olsr_rtreq req;
351   struct iovec iov;
352   struct sockaddr_nl nladdr;
353   struct msghdr msg = {
354     &nladdr,
355     sizeof(nladdr),
356     &iov,
357     1,
358     NULL,
359     0,
360     0
361   };
362
363   uint32_t metric = 0;
364   const struct rt_nexthop *nexthop = NULL;
365   if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE ) ) {
366     if (FIBM_FLAT == olsr_cnf->fib_metric) {
367       metric = RT_METRIC_DEFAULT;
368     }
369     else {
370       metric = (RTM_NEWROUTE == cmd) ? rt->rt_best->rtp_metric.hops : rt->rt_metric.hops;
371     }
372
373     if (( RTM_NEWROUTE == cmd ) ||
374         (( RTM_DELROUTE == cmd ) && ( RT_DELETE_SIMILAR_ROUTE == flag || RT_DELETE_SIMILAR_AUTO_ROUTE == flag ))) {
375       nexthop = &rt->rt_best->rtp_nexthop;
376     }
377     else {
378       nexthop = &rt->rt_nexthop;
379     }
380   }
381
382   memset(&req, 0, sizeof(req));
383
384   req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
385   req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
386   req.n.nlmsg_type = cmd;
387   
388   /*sanity check for niit ipv4 over ipv6 routes*/
389   if (family == AF_INET && flag == RT_NIIT) {
390     olsr_syslog(OLSR_LOG_ERR,"niit makes no sense with olsrd running on ipv4!");
391     return -1;
392   }
393
394   if (flag == RT_NIIT) {
395     req.r.rtm_family=AF_INET; /*we create an ipv4 niit route*/
396   }
397   else {
398     req.r.rtm_family = family;
399   }
400
401   req.r.rtm_table = rttable;
402
403   /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
404   /* -> olsr only adds deletes unicast routes */
405   req.r.rtm_type = RTN_UNICAST;
406
407   /* wildcard to delete routes of all protos if no simlar-delete correct proto will get set below */
408   req.r.rtm_protocol = RTPROT_UNSPEC;
409
410   /* as wildcard for deletion */
411   req.r.rtm_scope = RT_SCOPE_NOWHERE;
412
413   if ( ( cmd == RTM_NEWRULE ) || ( cmd == RTM_DELRULE ) ) {
414     /* add or delete a rule */
415     req.r.rtm_scope = RT_SCOPE_UNIVERSE;
416     olsr_netlink_addreq(&req, RTA_PRIORITY, &flag, sizeof(flag));
417     if (rt!=NULL) {
418       /*add interface name to rule*/
419       olsr_netlink_addreq(&req, RTA_IIF, rt, strlen((const char*) rt)+1);
420       //printf("\nrule to interface %s!",(const char*) rt);
421     } 
422   }
423   else {
424     req.r.rtm_dst_len = rt->rt_dst.prefix_len;
425
426     /* do not specify much as we wanna delete similar/conflicting routes */
427     if ( ( flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE )) {
428       /* 0 gets replaced by OS-specifc default (3)
429        * 1 is reserved so we take 0 instead (this really makes some sense)
430        * other numbers are used 1:1 */
431       req.r.rtm_protocol = ( (olsr_cnf->rtproto<1) ? RTPROT_BOOT : ( (olsr_cnf->rtproto==1) ? 0 : olsr_cnf->rtproto) );
432       req.r.rtm_scope = RT_SCOPE_LINK;
433
434       /*add interface*/
435       if ((olsr_cnf->smart_gw_active) && family != AF_INET)
436       {
437         printf("smart gateway not available for ipv6 currently\n");
438         return -1;
439       }
440       else if(flag == RT_SMARTGW)
441       //else if ((olsr_cnf->smart_gateway_active) && (rt->rt_dst.prefix_len == 0) && (&olsr_cnf->ipip_if_index))
442       {
443         //add interface (without nexthop if possible (if not use &rt->rt_best->rtp_originator))
444         olsr_netlink_addreq(&req, RTA_OIF, &olsr_cnf->ipip_if_index, sizeof(&olsr_cnf->ipip_if_index));
445       }
446       else if (flag == RT_NIIT) {
447         olsr_netlink_addreq(&req, RTA_OIF, &olsr_cnf->niit_if_index, sizeof(&olsr_cnf->niit_if_index));
448       }
449       else {
450         olsr_netlink_addreq(&req, RTA_OIF, &nexthop->iif_index, sizeof(nexthop->iif_index));
451       }
452
453 #if SOURCE_IP_ROUTES
454       /**
455        * source ip here is based on now static olsr_cnf->main_addr in this olsr-0.5.6-r4,
456        * should be based on orignator-id in newer olsrds
457        **/
458       if (flag != RT_NIIT) {
459         if (AF_INET == family) {
460           olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v4.s_addr, sizeof(olsr_cnf->main_addr.v4.s_addr));
461         }
462         else {
463           olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v6.s6_addr, sizeof(olsr_cnf->main_addr.v6.s6_addr));
464         }
465       }
466 #endif
467     }
468
469     /* metric is specified always as we can only delete one route per iteration, and wanna hit the correct one first */
470     if (FIBM_APPROX != olsr_cnf->fib_metric || (RTM_NEWROUTE == cmd) ) {
471       olsr_netlink_addreq(&req, RTA_PRIORITY, &metric, sizeof(metric));
472     }
473
474     /* make sure that netmask = maxplen (32 or 128) as this is an autogenarated (host)route */
475     if (( flag == RT_AUTO_ADD_GATEWAY_ROUTE ) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) {
476       req.r.rtm_dst_len = olsr_cnf->maxplen;
477     }
478
479     /**
480      * for ipv4 or ipv6 we add gateway if one is specified,
481      * or leave gateway away if we want to delete similar routes aswell,
482      * or even use the gateway as target if we add a auto-generated route,
483      * or if delete-similar to make insertion of auto-generated route possible
484      **/
485     if (AF_INET == family) {
486       if ( ( flag != RT_SMARTGW )
487            && ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE) && 
488            ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE) && (rt->rt_dst.prefix.v4.s_addr != nexthop->gateway.v4.s_addr) ) {
489         olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v4, sizeof(nexthop->gateway.v4));
490         req.r.rtm_scope = RT_SCOPE_UNIVERSE;
491       }
492       olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ? 
493                           &nexthop->gateway.v4 : &rt->rt_dst.prefix.v4, sizeof(rt->rt_dst.prefix.v4));
494     } else {
495       if (flag == RT_NIIT) {
496         union olsr_ip_addr ipv4_addr;
497         /* create an ipv4 route */
498         olsr_syslog(OLSR_LOG_ERR,"niit suport not fully implemented!!\n");
499
500         /* fix prefix length */
501         req.r.rtm_dst_len = rt->rt_dst.prefix_len - 96;
502         olsr_netlink_addreq(&req, RTA_DST, olsr_ipv6_to_ipv4(&rt->rt_dst.prefix, &ipv4_addr), sizeof(ipv4_addr.v4));
503       }
504       else {
505         if ( ( flag != RT_SMARTGW ) 
506             && ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE) 
507             && (0 != memcmp(&rt->rt_dst.prefix.v6, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6))) ) {
508           olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6));
509           req.r.rtm_scope = RT_SCOPE_UNIVERSE;
510         }
511         olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ? 
512                             &nexthop->gateway.v6 : &rt->rt_dst.prefix.v6, sizeof(rt->rt_dst.prefix.v6));
513       }
514     }
515   }
516
517   iov.iov_base = &req.n;
518   iov.iov_len = req.n.nlmsg_len;
519   memset(&nladdr, 0, sizeof(nladdr));
520   nladdr.nl_family = AF_NETLINK;
521   if (0 <= (ret = sendmsg(olsr_cnf->rtnl_s, &msg, 0))) {
522     iov.iov_base = req.buf;
523     iov.iov_len = sizeof(req.buf);
524     if (0 < (ret = recvmsg(olsr_cnf->rtnl_s, &msg, 0))) {
525       struct nlmsghdr *h = (struct nlmsghdr *)(ARM_NOWARN_ALIGN)req.buf;
526       while (NLMSG_OK(h, (unsigned int)ret)) {
527         if (NLMSG_DONE == h->nlmsg_type) {
528           /* seems to reached never */
529           olsr_syslog(OLSR_LOG_INFO, "_received NLMSG_DONE");
530           break;
531         }
532         if (NLMSG_ERROR == h->nlmsg_type) {
533           if (NLMSG_LENGTH(sizeof(struct nlmsgerr) <= h->nlmsg_len)) {
534             struct ipaddr_str ibuf;
535             struct ipaddr_str gbuf;
536             struct nlmsgerr *l_err = (struct nlmsgerr *)NLMSG_DATA(h);
537             errno = -l_err->error;
538             if (0 != errno) {
539               const char *const err_msg = strerror(errno);
540               struct ipaddr_str buf;
541               rt_ret = -1;
542
543               /* syslog debug output for various situations */
544               if ( cmd == RTM_NEWRULE ) {
545                 olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on inserting empty policy rule aimed to activate RtTable %u!", err_msg, errno, rttable);
546               }
547               else if ( cmd == RTM_DELRULE ) {
548                 olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on deleting empty policy rule aimed to activate rtTable %u!", err_msg, errno, rttable);
549               }
550               else if ( flag == RT_NIIT ) {
551                 olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on manipulating niit route of %s!", err_msg, errno, olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix));
552               }
553               else if ( flag <= RT_RETRY_AFTER_DELETE_SIMILAR ) {
554                 if (rt->rt_dst.prefix.v4.s_addr!=nexthop->gateway.v4.s_addr) {
555                   olsr_syslog(OLSR_LOG_ERR, "error '%s' (%d) %s route to %s/%d via %s dev %s",
556                       err_msg, errno, (cmd == RTM_NEWROUTE) ? "add" : "del",
557                       olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), req.r.rtm_dst_len,
558                       olsr_ip_to_string(&gbuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
559                 }
560                 else {
561                   olsr_syslog(OLSR_LOG_ERR, "error '%s' (%d) %s route to %s/%d dev %s",
562                       err_msg, errno, (cmd == RTM_NEWROUTE) ? "add" : "del",
563                       olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), req.r.rtm_dst_len, if_ifwithindex_name(nexthop->iif_index));
564                 }
565               }
566               else if (flag == RT_AUTO_ADD_GATEWAY_ROUTE) {
567                 olsr_syslog(OLSR_LOG_ERR, ". error '%s' (%d) auto-add route to %s dev %s", err_msg, errno,
568                     olsr_ip_to_string(&ibuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
569               }
570               else if (flag == RT_DELETE_SIMILAR_ROUTE) {
571                 olsr_syslog(OLSR_LOG_ERR, ". error '%s' (%d) auto-delete route to %s dev %s", err_msg, errno,
572                     olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), if_ifwithindex_name(nexthop->iif_index));
573               }
574               else if (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) {
575                 olsr_syslog(OLSR_LOG_ERR, ". . error '%s' (%d) auto-delete similar route to %s dev %s", err_msg, errno,
576                     olsr_ip_to_string(&ibuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
577               }
578               else {
579                 /* should never happen */
580                 olsr_syslog(OLSR_LOG_ERR, "# invalid internal route delete/add flag (%d) used!", flag);
581               }
582             }
583             else {
584               /* netlink acks requests with an errno=0 NLMSG_ERROR response! */
585               rt_ret = 1;
586             }
587
588             /* resolve "File exist" (17) propblems (on orig and autogen routes)*/       
589             if ((errno == 17) && (cmd == RTM_NEWROUTE) && ((flag == RT_ORIG_REQUEST) || (flag == RT_AUTO_ADD_GATEWAY_ROUTE))) {
590               /* a similar route going over another gateway may be present, which has to be deleted! */
591               olsr_syslog(OLSR_LOG_ERR, ". auto-deleting similar routes to resolve 'File exists' (17) while adding route!");
592               rt_ret = RT_DELETE_SIMILAR_ROUTE; /* processing will contiune after this loop */
593             }
594             /* report success on "No such process" (3) */
595             else if ((errno == 3) && (cmd == RTM_DELROUTE) && (flag == RT_ORIG_REQUEST)) {
596               /* another similar (but slightly different) route may be present at this point
597               * , if so this will get solved when adding new route to this destination */
598               olsr_syslog(OLSR_LOG_ERR, ". ignoring 'No such process' (3) while deleting route!");
599               rt_ret = 0;
600             }
601             /* insert route to gateway on the fly if "Network unreachable" (128) on 2.4 kernels
602              * or on 2.6 kernel No such process (3) or Network unreachable (101) is reported in rtnetlink response
603              * do this only with flat metric, as using metric values inherited from 
604              * a target behind the gateway is really strange, and could lead to multiple routes!
605              * anyways if invalid gateway ips may happen we are f*cked up!!
606              * but if not, these on the fly generated routes are no problem, and will only get used when needed */
607             else if ( ( (errno == 3) || (errno == 101) || (errno == 128) )
608                 && (flag == RT_ORIG_REQUEST) && (FIBM_FLAT == olsr_cnf->fib_metric)
609                      && (cmd == RTM_NEWROUTE) && (rt->rt_dst.prefix.v4.s_addr!=nexthop->gateway.v4.s_addr)) {
610               if (errno == 128)  {
611                 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (128) while adding route!");
612               }
613               else if (errno == 101) {
614                 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (101) while adding route!");
615               }
616               else {
617                 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'No such process' (3) while adding route!");
618               }
619
620               /* processing will contiune after this loop */
621               rt_ret = RT_AUTO_ADD_GATEWAY_ROUTE;
622             }
623           }
624           /* report invalid message size */
625           else {
626             olsr_syslog(OLSR_LOG_INFO,"_received invalid netlink message size %lu != %u",
627                 (unsigned long int)sizeof(struct nlmsgerr), h->nlmsg_len);
628           }
629         }
630         /* log all other messages */
631         else {
632           olsr_syslog(OLSR_LOG_INFO,"_received %u Byte rtnetlink response of type %u with seqnr %u and flags %u from %u (%u)",
633               h->nlmsg_len, h->nlmsg_type, h->nlmsg_seq, h->nlmsg_flags, h->nlmsg_pid, NLMSG_ERROR);
634         }
635 /*
636  * The ARM compile complains about alignment. Copied
637  * from /usr/include/linux/netlink.h and adapted for ARM
638  */
639 #define MY_NLMSG_NEXT(nlh,len)   ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
640                                   (struct nlmsghdr*)(ARM_NOWARN_ALIGN)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
641         h = MY_NLMSG_NEXT(h, ret);
642       }
643     }
644   }
645   if ( rt_ret == RT_DELETE_SIMILAR_ROUTE ) {
646     /* delete all routes that may collide */
647
648     /* recursive call to delete simlar routes, using flag 2 to invoke deletion of similar, not only exact matches*/
649     rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_DELROUTE, 
650         flag == RT_AUTO_ADD_GATEWAY_ROUTE ? RT_DELETE_SIMILAR_AUTO_ROUTE : RT_DELETE_SIMILAR_ROUTE);
651
652     /* retry insert original route, if deleting similar succeeded, using flag=1 to prevent recursions */
653     if (rt_ret > 0) {
654       rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_RETRY_AFTER_DELETE_SIMILAR);
655     }
656     else {
657       olsr_syslog(OLSR_LOG_ERR, ". failed on auto-deleting similar route conflicting with above route!");
658     }
659
660     /* set appropriate return code for original request, while returning simple -1/1 if called recursive */
661     if (flag != RT_AUTO_ADD_GATEWAY_ROUTE) {
662       if (rt_ret > 0) {
663         /* successful recovery */
664         rt_ret = 0;
665       }
666       else {
667         /* unrecoverable error */
668         rt_ret = -1;
669       }
670     }
671   }
672   if ( rt_ret == RT_AUTO_ADD_GATEWAY_ROUTE ) {
673     /* autoadd route via gateway */
674
675     /* recursive call to invoke creation of a route to the gateway */
676     rt_ret = olsr_netlink_route_int(rt, family, olsr_cnf->rttable, RTM_NEWROUTE, RT_AUTO_ADD_GATEWAY_ROUTE);
677
678     /* retry insert original route, if above succeeded without problems */
679     if (rt_ret > 0) {
680       rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_RETRY_AFTER_ADD_GATEWAY);
681     }
682     else {
683       olsr_syslog(OLSR_LOG_ERR, ". failed on inserting auto-generated route to gateway of above route!");
684     }
685
686     /* set appropriate return code for original request*/
687     if (rt_ret > 0) {
688       /* successful recovery */
689       rt_ret = 0;
690     }
691     else {
692       /* unrecoverable error */
693       rt_ret = -1;
694     }
695   }
696   /* send ipc update on success */
697   if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE )
698       && (flag == RT_ORIG_REQUEST) && (0 <= rt_ret && olsr_cnf->ipc_connections > 0) ) {
699     ipc_route_send_rtentry(&rt->rt_dst.prefix, &nexthop->gateway, metric,
700         RTM_NEWROUTE == cmd, if_ifwithindex_name(nexthop->iif_index));
701   }
702   if (rt_ret == -2) {
703     olsr_syslog(OLSR_LOG_ERR,"no rtnetlink response! (no system ressources left?, everything may happen now ...)");
704   }
705   return rt_ret;
706 }
707
708 /* external wrapper function for above patched multi purpose rtnetlink function */
709 int
710 olsr_netlink_rule(uint8_t family, uint8_t rttable, uint16_t cmd, uint32_t priority, char* dev)
711 {
712   return olsr_netlink_route_int((const struct rt_entry *) dev, family, rttable, cmd, priority);
713 }
714
715 /* internal wrapper function for above patched function */
716 /* added smartgw and niit route creation*/
717 static int
718 olsr_netlink_route(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd)
719 {
720   /*check if this rule is relevant for smartgw*/
721   if ((olsr_cnf->smart_gw_active) && (rt->rt_dst.prefix_len == 0) )
722   { 
723     if (cmd == RTM_DELROUTE){ /*should we do something sane here!!??*/
724       printf("ignoreing deletion of default route for smart gateway!!\n");
725     }
726     else
727     {
728       if (!olsr_cnf->ipip_if_index) {
729 int r;
730         printf("creating tunnel %s\n",olsr_cnf->ipip_name);
731         /*create tunnel*/
732         set_tunl(SIOCADDTUNNEL,rt->rt_best->rtp_originator.v4.s_addr);
733         olsr_cnf->ipip_if_up=false;/*rtnetlink monitoring will detect it up*/
734         /*!!?? currently it gets never deleted on shutdown, anyways reusing existing tunnel might be a safe approach if creating fails?*/
735         /*set tunnel up with originator ip*/
736         r=olsr_ifconfig(olsr_cnf->ipip_name,IF_SET_IP);
737 printf("result of ifup is %i\n",r);
738         /*find out iifindex (maybe it works even if above failed (old tunnel))*/
739         olsr_cnf->ipip_if_index=if_nametoindex(olsr_cnf->ipip_name);
740 printf("index of new olsrtunl is %i\n",olsr_cnf->ipip_if_index);
741       }
742       else
743       {
744         printf("changing tunnel %s:\n",olsr_cnf->ipip_name);
745         /*change tunnel to new originator or potentially new gateway*/
746         if ((olsr_cnf->ipip_remote_address != rt->rt_best->rtp_originator.v4.s_addr) && (rt->rt_best->rtp_originator.v4.s_addr != 0x00000000) ) {
747           struct ipaddr_str buf;
748           printf("changing tunnel to %s\n",olsr_ip_to_string(&buf,&rt->rt_best->rtp_originator));
749           olsr_cnf->ipip_remote_address = rt->rt_best->rtp_originator.v4.s_addr;
750           set_tunl(SIOCCHGTUNNEL,olsr_cnf->ipip_remote_address);
751         }
752       }
753       /*create route into tunnel*/
754       olsr_netlink_route_int(rt, family, olsr_cnf->rttable_smartgw, cmd, RT_SMARTGW);
755     }
756   }
757   /*normal route in default route table*/
758
759   /*create/delete niit route if we have an niit device*/
760   if ((olsr_cnf->niit_if_index!=0) && (family != AF_INET) && (olsr_is_niit_ipv6(&rt->rt_dst.prefix))) {
761     olsr_netlink_route_int(rt, family, rttable, cmd, RT_NIIT);
762   }
763
764   return olsr_netlink_route_int(rt, family, rttable, cmd, RT_ORIG_REQUEST);
765 }
766
767 #endif /* LINUX_POLICY_ROUTING */
768
769 /**
770  * Insert a route in the kernel routing table
771  *
772  * @param destination the route to add
773  *
774  * @return negative on error
775  */
776 int
777 olsr_ioctl_add_route(const struct rt_entry *rt)
778 {
779 #if !LINUX_POLICY_ROUTING
780   struct rtentry kernel_route;
781   union olsr_ip_addr mask;
782   int rslt;
783 #endif /* LINUX_POLICY_ROUTING */
784
785   OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
786
787 #if !LINUX_POLICY_ROUTING
788   memset(&kernel_route, 0, sizeof(struct rtentry));
789
790   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
791   ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
792   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
793
794   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
795
796   if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
797     return -1;
798   }
799   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
800
801   if (rt->rt_dst.prefix.v4.s_addr != rt->rt_best->rtp_nexthop.gateway.v4.s_addr) {
802     ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_best->rtp_nexthop.gateway.v4;
803   }
804
805   kernel_route.rt_flags = olsr_rt_flags(rt);
806   kernel_route.rt_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
807
808   /*
809    * Set interface
810    */
811   kernel_route.rt_dev = if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index);
812
813   /* delete existing default route before ? */
814   if ((olsr_cnf->del_gws) && (rt->rt_dst.prefix.v4.s_addr == INADDR_ANY) && (rt->rt_dst.prefix_len == INADDR_ANY)) {
815     delete_all_inet_gws();
816     olsr_cnf->del_gws = false;
817   }
818
819   if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
820
821     /*
822      * Send IPC route update message
823      */
824     ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
825                            if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
826   }
827
828   return rslt;
829 #else /* !LINUX_POLICY_ROUTING */
830   /*put large hnas also into RtTabledefault (if smartgateway is active) as they may be used to replace (huge parts) of a normal default route*/
831   if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable) {
832     /*
833      * Users start whining about not having internet with policy
834      * routing activated and no static default route in table 254.
835      * We maintain a fallback defroute in the default=253 table.
836      *
837      * which was always insane but togehter with smartgateways policy routing its too insane
838      */
839     if (!olsr_cnf->smart_gw_active) olsr_netlink_route(rt, AF_INET, 253, RTM_NEWROUTE);
840   }
841   if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
842     return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_NEWROUTE);
843   }
844   else {
845     return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_NEWROUTE);
846   }
847 #endif /* LINUX_POLICY_ROUTING */
848 }
849
850 /**
851  *Insert a route in the kernel routing table
852  *
853  *@param destination the route to add
854  *
855  *@return negative on error
856  */
857 int
858 olsr_ioctl_add_route6(const struct rt_entry *rt)
859 {
860 #if !LINUX_POLICY_ROUTING
861   struct in6_rtmsg kernel_route;
862   int rslt;
863
864   OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
865
866   memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
867
868   kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6;
869   kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
870
871   kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
872
873   kernel_route.rtmsg_flags = olsr_rt_flags(rt);
874   kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
875
876   /*
877    * set interface
878    */
879   kernel_route.rtmsg_ifindex = rt->rt_best->rtp_nexthop.iif_index;
880
881   /* XXX delete 0/0 route before ? */
882
883   if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
884
885     /*
886      * Send IPC route update message
887      */
888     ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
889                            if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
890   }
891   return rslt;
892 #else /* !LINUX_POLICY_ROUTING */
893   if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
894     return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_NEWROUTE);
895   }
896   else {
897     return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_NEWROUTE);
898   }
899 #endif /* LINUX_POLICY_ROUTING */
900 }
901
902 /**
903  *Remove a route from the kernel
904  *
905  *@param destination the route to remove
906  *
907  *@return negative on error
908  */
909 int
910 olsr_ioctl_del_route(const struct rt_entry *rt)
911 {
912 #if !LINUX_POLICY_ROUTING
913   struct rtentry kernel_route;
914   union olsr_ip_addr mask;
915   int rslt;
916 #endif /* LINUX_POLICY_ROUTING */
917
918   OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
919
920 #if !LINUX_POLICY_ROUTING
921   memset(&kernel_route, 0, sizeof(struct rtentry));
922
923   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
924   ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
925   ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
926
927   ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
928
929   if (rt->rt_dst.prefix.v4.s_addr != rt->rt_nexthop.gateway.v4.s_addr) {
930     ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_nexthop.gateway.v4;
931   }
932
933   if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
934     return -1;
935   } else {
936     ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
937   }
938
939   kernel_route.rt_flags = olsr_rt_flags(rt);
940   kernel_route.rt_metric = olsr_fib_metric(&rt->rt_metric.hops);
941
942   /*
943    * Set interface
944    */
945   kernel_route.rt_dev = NULL;
946
947   if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route)) >= 0) {
948
949     /*
950      * Send IPC route update message
951      */
952     ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
953   }
954
955   return rslt;
956 #else /* !LINUX_POLICY_ROUTING */
957   if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable) {
958     /*
959      * Also remove the fallback default route
960      */
961     olsr_netlink_route(rt, AF_INET, 253, RTM_DELROUTE);
962   }
963   if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
964     return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_DELROUTE);
965   }
966   else {
967     return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_DELROUTE);
968   }
969 #endif /* LINUX_POLICY_ROUTING */
970 }
971
972 /**
973  *Remove a route from the kernel
974  *
975  *@param destination the route to remove
976  *
977  *@return negative on error
978  */
979 int
980 olsr_ioctl_del_route6(const struct rt_entry *rt)
981 {
982 #if !LINUX_POLICY_ROUTING
983   struct in6_rtmsg kernel_route;
984   int rslt;
985 #endif /* LINUX_POLICY_ROUTING */
986
987   OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
988
989 #if !LINUX_POLICY_ROUTING
990   memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
991
992   kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6;
993   kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
994
995   kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
996
997   kernel_route.rtmsg_flags = olsr_rt_flags(rt);
998   kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
999
1000   if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route) >= 0)) {
1001
1002     /*
1003      * Send IPC route update message
1004      */
1005     ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
1006   }
1007
1008   return rslt;
1009 #else /* !LINUX_POLICY_ROUTING */
1010   if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
1011     return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_DELROUTE);
1012   }
1013   else {
1014     return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_DELROUTE);
1015   }
1016 #endif /* LINUX_POLICY_ROUTING */
1017 }
1018
1019 #if !LINUX_POLICY_ROUTING
1020 static int
1021 delete_all_inet_gws(void)
1022 {
1023   int s;
1024   char buf[BUFSIZ], *cp, *cplim;
1025   struct ifconf ifc;
1026   struct ifreq *ifr;
1027
1028   OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n");
1029
1030   /* Get a socket */
1031   if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1032     olsr_syslog(OLSR_LOG_ERR, "socket: %m");
1033     return -1;
1034   }
1035
1036   ifc.ifc_len = sizeof(buf);
1037   ifc.ifc_buf = buf;
1038   if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
1039     olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");
1040     close(s);
1041     return -1;
1042   }
1043
1044   ifr = ifc.ifc_req;
1045   cplim = buf + ifc.ifc_len;    /*skip over if's with big ifr_addr's */
1046   for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) {
1047     struct rtentry kernel_route;
1048     ifr = (struct ifreq *)cp;
1049
1050     if (strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0) {
1051       OLSR_PRINTF(1, "Skipping loopback...\n");
1052       continue;
1053     }
1054
1055     OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name);
1056
1057     memset(&kernel_route, 0, sizeof(struct rtentry));
1058
1059     ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;
1060     ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
1061     ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;
1062     ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
1063
1064     ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
1065     ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
1066
1067     kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
1068
1069     kernel_route.rt_dev = ifr->ifr_ifrn.ifrn_name;
1070
1071     if ((ioctl(s, SIOCDELRT, &kernel_route)) < 0)
1072       OLSR_PRINTF(1, "NO\n");
1073     else
1074       OLSR_PRINTF(1, "YES\n");
1075   }
1076   close(s);
1077   return 0;
1078 }
1079 #endif /* LINUX_POLICY_ROUTING */
1080
1081 /*
1082  * Local Variables:
1083  * c-basic-offset: 2
1084  * indent-tabs-mode: nil
1085  * End:
1086  */