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