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
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 * Visit http://www.olsr.org for more information.
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.
42 #include "kernel_routes.h"
43 #include "ipc_frontend.h"
47 /* values for control flag to handle recursive route corrections
48 * currently only requires in linux specific kernel_routes.c */
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
59 #if !LINUX_POLICY_ROUTING
61 static int delete_all_inet_gws(void);
63 #else /* !LINUX_POLICY_ROUTING */
66 #include <linux/types.h>
67 #include <linux/rtnetlink.h>
70 #include <netinet/in.h>
71 #include <sys/ioctl.h>
74 #include <linux/if_tunnel.h>
77 #include <sys/socket.h>
78 #include <sys/ioctl.h>
79 #include <sys/types.h>
82 extern struct rtnl_handle rth;
90 #if LINUX_RTNETLINK_LISTEN
92 #include "socket_parser.h"
94 int rtnetlink_register_socket(int rtnl_mgrp)
96 int sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
97 struct sockaddr_nl addr;
100 OLSR_PRINTF(1,"could not create rtnetlink socket! %d",sock);
103 memset(&addr, 0, sizeof(addr));
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));
112 add_olsr_socket(sock, &rtnetlink_read);
114 fcntl(sock, F_SETFL, O_NONBLOCK);
119 static void netlink_process_link(struct nlmsghdr *h)
121 struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(h);
122 struct interface *iface;
123 struct olsr_if *tmp_if;
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)
131 printf("is up now\n");
132 olsr_cnf->ipip_if_up=true;
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)*/
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;
141 else printf("interface is down, but was never up -> ignoring!\n");
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*/
159 iface = if_ifwithindex(ifi->ifi_index);
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
170 OLSR_PRINTF(1,"interface %s is down!\n", iface->int_name);
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 olsr_remove_interface(tmp_if,true);
183 void rtnetlink_read(int sock)
187 struct sockaddr_nl nladdr;
188 struct msghdr msg = {
199 struct nlmsghdr *nlh = (struct nlmsghdr *)(ARM_NOWARN_ALIGN) buffer;
202 iov.iov_base = (void *) buffer;
203 iov.iov_len = sizeof(buffer);
205 while (true) { //read until ret<0;
206 ret=recvmsg(sock, &msg, 0);
208 if (errno != EAGAIN) OLSR_PRINTF(1,"netlink listen error %u - %s\n",errno,strerror(errno));
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",
220 if ( (nlh->nlmsg_type == RTM_NEWLINK) || ( nlh->nlmsg_type == RTM_DELLINK) ) netlink_process_link(nlh);
224 //!!?? listen on our own tunlx interfaces aswell
226 #endif /*linux_rtnetlink_listen*/
228 /*create or change a ipip tunnel ipv4 only*/
229 static int set_tunl(int cmd, unsigned long int ipv4)
234 struct ip_tunnel_parm p;
238 p.iph.protocol=IPPROTO_IPIP; //IPPROTO_IPV6
239 p.iph.saddr=0x00000000;
242 strncpy(p.name, olsr_cnf->ipip_name, IFNAMSIZ);
243 printf("set tunl to name: %s\n",p.name);
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);
249 printf("set tunl %s\n",ifr.ifr_name);
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");
260 int olsr_del_tunl(void)
262 printf("-----\ndelete olsrtunle!\n");
263 return set_tunl(SIOCDELTUNNEL,0x00000000);//!!??test if this deletes tunnel
267 olsr_netlink_addreq(struct nlmsghdr *n, size_t reqSize __attribute__ ((unused)), int type, const void *data, int len)
269 struct rtattr *rta = (struct rtattr *)(ARM_NOWARN_ALIGN)(((char *)n) + NLMSG_ALIGN(n->nlmsg_len));
270 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_LENGTH(len);
271 //produces strange compile error
272 //assert(n->nlmsg_len < reqSize);
273 rta->rta_type = type;
274 rta->rta_len = RTA_LENGTH(len);
275 memcpy(RTA_DATA(rta), data, len);
279 * The ARM compile complains about alignment. Copied
280 * from /usr/include/linux/netlink.h and adapted for ARM
282 #define MY_NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
283 (struct nlmsghdr*)(ARM_NOWARN_ALIGN)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
285 /*rt_entry and nexthop and family and table must only be specified with an flag != RT_NONE && != RT_LO_IP*/
287 olsr_netlink_send(struct nlmsghdr *nl_hdr)
291 struct sockaddr_nl nladdr;
294 struct nlmsgerr *l_err;
297 memset(&nladdr, 0, sizeof(nladdr));
298 memset(&msg, 0, sizeof(msg));
300 nladdr.nl_family = AF_NETLINK;
302 msg.msg_name = &nladdr;
303 msg.msg_namelen = sizeof(nladdr);
307 iov.iov_base = nl_hdr;
308 iov.iov_len = nl_hdr->nlmsg_len;
309 ret = sendmsg(olsr_cnf->rtnl_s, &msg, 0);
311 olsr_syslog(OLSR_LOG_ERR, "Cannot send data to netlink socket (%d: %s)", errno, strerror(errno));
315 iov.iov_base = rcvbuf;
316 iov.iov_len = sizeof(rcvbuf);
317 ret = recvmsg(olsr_cnf->rtnl_s, &msg, 0);
319 olsr_syslog(OLSR_LOG_ERR, "Error while reading answer to netlink message (%d: %s)", errno, strerror(errno));
323 h = (struct nlmsghdr *)(ARM_NOWARN_ALIGN)rcvbuf;
324 if (!NLMSG_OK(h, (unsigned int)ret)) {
325 olsr_syslog(OLSR_LOG_ERR, "Received netlink message was malformed (ret=%d, %u)", ret, h->nlmsg_len);
329 if (h->nlmsg_type != NLMSG_ERROR) {
330 olsr_syslog(OLSR_LOG_INFO,
331 "Received unknown netlink response: %u bytes, type %u (not %u) with seqnr %u and flags %u from %u",
332 h->nlmsg_len, h->nlmsg_type, NLMSG_ERROR, h->nlmsg_seq, h->nlmsg_flags, h->nlmsg_pid);
335 if (NLMSG_LENGTH(sizeof(struct nlmsgerr)) > h->nlmsg_len) {
336 olsr_syslog(OLSR_LOG_INFO,"Received invalid netlink message size %lu != %u",
337 (unsigned long int)sizeof(struct nlmsgerr), h->nlmsg_len);
341 l_err = (struct nlmsgerr *)NLMSG_DATA(h);
344 olsr_syslog(OLSR_LOG_INFO,"Received netlink error code %s (%d)", strerror(-l_err->error), l_err->error);
346 return -l_err->error;
349 int olsr_netlink_rule(int family, int rttable, uint32_t priority, const char *if_name, bool set) {
350 struct olsr_rtreq req;
353 memset(&req, 0, sizeof(req));
355 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
356 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
358 req.n.nlmsg_type = set ? RTM_NEWRULE : RTM_DELRULE;
359 req.r.rtm_family = family;
360 req.r.rtm_table = rttable;
362 /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
363 /* -> olsr only adds deletes unicast routes */
364 req.r.rtm_type = RTN_UNICAST;
366 /* wildcard to delete routes of all protos if no simlar-delete correct proto will get set below */
367 req.r.rtm_protocol = RTPROT_UNSPEC;
369 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
371 olsr_netlink_addreq(&req.n, sizeof(req), RTA_PRIORITY, &priority, sizeof(priority));
373 if (if_name != NULL) {
374 /*add interface name to rule*/
375 olsr_netlink_addreq(&req.n, sizeof(req), RTA_IIF, if_name, strlen(if_name)+1);
378 err = olsr_netlink_send(&req.n);
380 olsr_syslog(OLSR_LOG_ERR,"Error on %s empty policy rule aimed to activate RtTable %u!",
381 set ? "inserting" : "deleting", rttable);
387 int olsr_new_netlink_route(int family, int rttable, int if_index, int metric, int protocol,
388 const union olsr_ip_addr *src, const union olsr_ip_addr *gw, const struct olsr_ip_prefix *dst,
389 bool set, bool del_similar);
391 int olsr_new_netlink_route(int family, int rttable, int if_index, int metric, int protocol,
392 const union olsr_ip_addr *src, const union olsr_ip_addr *gw, const struct olsr_ip_prefix *dst,
393 bool set, bool del_similar) {
395 struct olsr_rtreq req;
400 struct ipaddr_str buf1, buf2;
402 olsr_syslog(OLSR_LOG_INFO, "new_netlink_route: family=%d,rttable=%d,if_index=%d,metric=%d,protocol=%d,src=%s,gw=%s,dst=%s,set=%s,del_similar=%s",
403 family, rttable, if_index, metric, protocol, src == NULL ? "" : olsr_ip_to_string(&buf1, src),
404 gw == NULL ? "" : olsr_ip_to_string(&buf2, gw), olsr_ip_prefix_to_string(dst),
405 set ? "true" : "false", del_similar ? "true" : "false");
407 family_size = family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr);
409 memset(&req, 0, sizeof(req));
411 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
412 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
414 req.n.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
417 req.n.nlmsg_type = set ? RTM_NEWROUTE : RTM_DELROUTE;
418 req.r.rtm_family = family;
419 req.r.rtm_table = rttable;
421 /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
422 /* -> olsr only adds deletes unicast routes */
423 req.r.rtm_type = RTN_UNICAST;
425 req.r.rtm_dst_len = dst->prefix_len;
428 /* add protocol for setting a route */
429 req.r.rtm_protocol = protocol;
432 /* calculate scope of operation */
433 if (!set && del_similar) {
434 /* as wildcard for fuzzy deletion */
435 req.r.rtm_scope = RT_SCOPE_NOWHERE;
438 /* for multihop routes */
439 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
442 /* for link neighbor routes */
443 req.r.rtm_scope = RT_SCOPE_LINK;
446 if (set || !del_similar) {
448 olsr_netlink_addreq(&req.n, sizeof(req), RTA_OIF, &if_index, sizeof(if_index));
451 if (set && src != NULL) {
453 olsr_netlink_addreq(&req.n, sizeof(req), RTA_PREFSRC, src, family_size);
458 olsr_netlink_addreq(&req.n, sizeof(req), RTA_PRIORITY, &metric, sizeof(metric));
463 olsr_netlink_addreq(&req.n, sizeof(req), RTA_GATEWAY, gw, family_size);
466 /* add destination */
467 olsr_netlink_addreq(&req.n, sizeof(req), RTA_DST, &dst->prefix, family_size);
469 err = olsr_netlink_send(&req.n);
472 struct ipaddr_str buf;
473 olsr_syslog(OLSR_LOG_ERR, ". error: %s route to %s via %s dev %s",
475 olsr_ip_prefix_to_string(dst), olsr_ip_to_string(&buf, gw), if_ifwithindex_name(if_index));
478 olsr_syslog(OLSR_LOG_ERR, ". error: %s route to %s dev %s",
480 olsr_ip_prefix_to_string(dst), if_ifwithindex_name(if_index));
487 int olsr_netlink_static_niit_routes(const struct olsr_ip_prefix *route, bool set) {
489 if (!is_prefix_niit_ipv6(route)) {
493 /* TODO: in welche Table kommen die NIIT-Routen ? ne eigene ? */
494 err = olsr_new_netlink_route(AF_INET6, olsr_cnf->rttable, olsr_cnf->niit6to4_if_index,
495 RT_METRIC_DEFAULT, RTPROT_BOOT, NULL, NULL, route, set, false);
497 olsr_syslog(OLSR_LOG_ERR, ". error while %s static niit route to %s",
498 set ? "setting" : "removing", olsr_ip_prefix_to_string(route));
503 static void olsr_netlink_process_niit(const struct rt_entry *rt, bool set) {
504 struct olsr_ip_prefix dst_v4;
505 if (!olsr_cnf->use_niit || !is_prefix_niit_ipv6(&rt->rt_dst)) {
509 prefix_mappedv4_to_v4(&dst_v4, &rt->rt_dst);
511 /* TODO: in welche Table kommen die NIIT-Routen ? ne eigene ? */
512 if (olsr_new_netlink_route(AF_INET, olsr_cnf->rttable, olsr_cnf->niit4to6_if_index,
513 RT_METRIC_DEFAULT, RTPROT_BOOT, NULL, NULL, &dst_v4, set, false)) {
514 olsr_syslog(OLSR_LOG_ERR, ". error while %s niit route to %s",
515 set ? "setting" : "removing", olsr_ip_prefix_to_string(&dst_v4));
519 static bool olsr_netlink_process_smartgw(const struct rt_entry *rt, bool set) {
520 if (!olsr_cnf->smart_gw_active || !is_prefix_inetgw(&rt->rt_dst)) {
524 /* TODO maybe block internet gateway route */
528 int olsr_netlink_process_rt_entry(const struct rt_entry *rt, bool set);
530 int olsr_netlink_process_rt_entry(const struct rt_entry *rt, bool set) {
531 int metric, protocol, table;
532 const struct rt_nexthop *nexthop;
533 union olsr_ip_addr *src;
537 /* handle NIIT special case */
538 olsr_netlink_process_niit(rt, set);
540 /* handle smart gateway case */
541 if (olsr_netlink_process_smartgw(rt, set)) {
542 /* skip inetgw routes if smartgw is active */
546 /* calculate metric */
547 if (FIBM_FLAT == olsr_cnf->fib_metric) {
548 metric = RT_METRIC_DEFAULT;
551 metric = set ? rt->rt_best->rtp_metric.hops : rt->rt_metric.hops;
555 * 0 gets replaced by OS-specifc default (3)
556 * 1 is reserved so we take 0 instead (this really makes some sense)
557 * other numbers are used directly without change */
558 protocol = olsr_cnf->rtproto;
560 protocol = protocol < 1 ? RTPROT_BOOT : 0;
564 table = is_prefix_inetgw(&rt->rt_dst)
565 ? olsr_cnf->rttable_default : olsr_cnf->rttable;
568 if (rt->rt_best && set) {
569 nexthop = &rt->rt_best->rtp_nexthop;
572 nexthop = &rt->rt_nexthop;
575 /* detect 1-hop hostroute */
576 hostRoute = rt->rt_dst.prefix_len == olsr_cnf->ipsize * 8
577 && ipequal(&nexthop->gateway, &rt->rt_dst.prefix);
580 struct ipaddr_str buf1, buf2;
581 olsr_syslog(OLSR_LOG_INFO, "hostroute (%s) = %d == %d && %s == %s",
582 hostRoute ? "true" : "false",
583 rt->rt_dst.prefix_len, (int)(olsr_cnf->ipsize * 8),
584 olsr_ip_to_string(&buf1, &nexthop->gateway),
585 olsr_ip_to_string(&buf2, &rt->rt_dst.prefix));
592 err = olsr_new_netlink_route(olsr_cnf->ip_version, table, nexthop->iif_index, metric, protocol,
593 src, hostRoute ? NULL : &nexthop->gateway, &rt->rt_dst, set, false);
595 /* resolve "File exist" (17) propblems (on orig and autogen routes)*/
596 if (set && err == 17) {
597 /* a similar route going over another gateway may be present, which has to be deleted! */
598 olsr_syslog(OLSR_LOG_ERR, ". auto-deleting similar routes to resolve 'File exists' (17) while adding route!");
600 /* erase similar rule */
601 err = olsr_new_netlink_route(olsr_cnf->ip_version, table, 0, 0, -1, NULL, NULL, &rt->rt_dst, false, true);
604 /* create this rule a second time if delete worked*/
605 err = olsr_new_netlink_route(olsr_cnf->ip_version, table, nexthop->iif_index, metric, protocol,
606 src, hostRoute ? NULL : &nexthop->gateway, &rt->rt_dst, set, false);
608 olsr_syslog(OLSR_LOG_ERR, ". %s (%d)", err == 0 ? "successful" : "failed", err);
611 /* report success on "No such process" (3) */
612 else if (!set && err == 3) {
613 /* another similar (but slightly different) route may be present at this point,
614 * if so this will get solved when adding new route to this destination */
615 olsr_syslog(OLSR_LOG_ERR, ". ignoring 'No such process' (3) while deleting route!");
618 /* insert route to gateway on the fly if "Network unreachable" (128) on 2.4 kernels
619 * or on 2.6 kernel No such process (3) or Network unreachable (101) is reported in rtnetlink response
620 * do this only with flat metric, as using metric values inherited from
621 * a target behind the gateway is really strange, and could lead to multiple routes!
622 * anyways if invalid gateway ips may happen we are f*cked up!!
623 * but if not, these on the fly generated routes are no problem, and will only get used when needed */
624 else if (!hostRoute && olsr_cnf->fib_metric == FIBM_FLAT
625 && (err == 128 || err == 101 || err == 3)) {
626 struct olsr_ip_prefix hostPrefix;
629 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (128) while adding route!");
631 else if (err == 101) {
632 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (101) while adding route!");
635 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'No such process' (3) while adding route!");
638 /* create hostroute */
639 hostPrefix.prefix = nexthop->gateway;
640 hostPrefix.prefix_len = olsr_cnf->ipsize * 8;
642 err = olsr_new_netlink_route(olsr_cnf->ip_version, olsr_cnf->rttable, nexthop->iif_index,
643 metric, protocol, src, NULL, &hostPrefix, true, false);
645 /* create this rule a second time if hostrule generation was successful */
646 err = olsr_new_netlink_route(olsr_cnf->ip_version, table, nexthop->iif_index, metric, protocol,
647 src, hostRoute ? NULL : &nexthop->gateway, &rt->rt_dst, set, false);
649 olsr_syslog(OLSR_LOG_ERR, ". %s (%d)", err == 0 ? "successful" : "failed", err);
657 * -1 on unrecoverable error (calling function will have to handle it)
658 * 0 on unexpected but recoverable rtnetlink behaviour
659 * but some of the implemented recovery methods only cure symptoms,
660 * not the cause, like unintelligent ordering of inserted routes.
663 olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd, uint32_t flag)
665 int ret = 1; /* helper variable for rtnetlink_message processing */
666 int rt_ret = -2; /* if no response from rtnetlink it must be considered as failed! */
667 struct olsr_rtreq req;
669 struct sockaddr_nl nladdr;
670 struct msghdr msg = {
681 const struct rt_nexthop *nexthop = NULL;
682 if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE ) ) {
683 if (FIBM_FLAT == olsr_cnf->fib_metric) {
684 metric = RT_METRIC_DEFAULT;
687 metric = (RTM_NEWROUTE == cmd) ? rt->rt_best->rtp_metric.hops : rt->rt_metric.hops;
690 if (( RTM_NEWROUTE == cmd ) ||
691 (( RTM_DELROUTE == cmd ) && ( RT_DELETE_SIMILAR_ROUTE == flag || RT_DELETE_SIMILAR_AUTO_ROUTE == flag ))) {
692 nexthop = &rt->rt_best->rtp_nexthop;
695 nexthop = &rt->rt_nexthop;
699 memset(&req, 0, sizeof(req));
701 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
702 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
703 req.n.nlmsg_type = cmd;
705 /*sanity check for niit ipv4 over ipv6 routes*/
706 if (family == AF_INET && flag == RT_NIIT) {
707 olsr_syslog(OLSR_LOG_ERR,"niit makes no sense with olsrd running on ipv4!");
711 if (flag == RT_NIIT) {
712 req.r.rtm_family=AF_INET; /*we create an ipv4 niit route*/
715 req.r.rtm_family = family;
718 req.r.rtm_table = rttable;
720 /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
721 /* -> olsr only adds deletes unicast routes */
722 req.r.rtm_type = RTN_UNICAST;
724 /* wildcard to delete routes of all protos if no simlar-delete correct proto will get set below */
725 req.r.rtm_protocol = RTPROT_UNSPEC;
727 /* as wildcard for deletion */
728 req.r.rtm_scope = RT_SCOPE_NOWHERE;
730 if ( ( cmd == RTM_NEWRULE ) || ( cmd == RTM_DELRULE ) ) {
731 /* add or delete a rule */
732 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
733 olsr_netlink_addreq(&req, RTA_PRIORITY, &flag, sizeof(flag));
735 /*add interface name to rule*/
736 olsr_netlink_addreq(&req, RTA_IIF, rt, strlen((const char*) rt)+1);
737 //printf("\nrule to interface %s!",(const char*) rt);
741 req.r.rtm_dst_len = rt->rt_dst.prefix_len;
743 /* do not specify much as we wanna delete similar/conflicting routes */
744 if ( ( flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE )) {
745 /* 0 gets replaced by OS-specifc default (3)
746 * 1 is reserved so we take 0 instead (this really makes some sense)
747 * other numbers are used 1:1 */
748 req.r.rtm_protocol = ( (olsr_cnf->rtproto<1) ? RTPROT_BOOT : ( (olsr_cnf->rtproto==1) ? 0 : olsr_cnf->rtproto) );
749 req.r.rtm_scope = RT_SCOPE_LINK;
752 if ((olsr_cnf->smart_gw_active) && family != AF_INET)
754 printf("smart gateway not available for ipv6 currently\n");
757 else if(flag == RT_SMARTGW)
758 //else if ((olsr_cnf->smart_gateway_active) && (rt->rt_dst.prefix_len == 0) && (&olsr_cnf->ipip_if_index))
760 //add interface (without nexthop if possible (if not use &rt->rt_best->rtp_originator))
761 olsr_netlink_addreq(&req, RTA_OIF, &olsr_cnf->ipip_if_index, sizeof(&olsr_cnf->ipip_if_index));
763 else if (flag == RT_NIIT) {
764 olsr_netlink_addreq(&req, RTA_OIF, &olsr_cnf->niit4to6_if_index, sizeof(&olsr_cnf->niit4to6_if_index));
767 olsr_netlink_addreq(&req, RTA_OIF, &nexthop->iif_index, sizeof(nexthop->iif_index));
772 * source ip here is based on now static olsr_cnf->main_addr in this olsr-0.5.6-r4,
773 * should be based on orignator-id in newer olsrds
775 if (flag != RT_NIIT) {
776 if (AF_INET == family) {
777 olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v4.s_addr, sizeof(olsr_cnf->main_addr.v4.s_addr));
780 olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v6.s6_addr, sizeof(olsr_cnf->main_addr.v6.s6_addr));
786 /* metric is specified always as we can only delete one route per iteration, and wanna hit the correct one first */
787 if (FIBM_APPROX != olsr_cnf->fib_metric || (RTM_NEWROUTE == cmd) ) {
788 olsr_netlink_addreq(&req, RTA_PRIORITY, &metric, sizeof(metric));
791 /* make sure that netmask = maxplen (32 or 128) as this is an autogenarated (host)route */
792 if (( flag == RT_AUTO_ADD_GATEWAY_ROUTE ) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) {
793 req.r.rtm_dst_len = olsr_cnf->maxplen;
797 * for ipv4 or ipv6 we add gateway if one is specified,
798 * or leave gateway away if we want to delete similar routes aswell,
799 * or even use the gateway as target if we add a auto-generated route,
800 * or if delete-similar to make insertion of auto-generated route possible
802 if (AF_INET == family) {
803 if ( ( flag != RT_SMARTGW )
804 && ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE) &&
805 ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE) && (rt->rt_dst.prefix.v4.s_addr != nexthop->gateway.v4.s_addr) ) {
806 olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v4, sizeof(nexthop->gateway.v4));
807 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
809 olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ?
810 &nexthop->gateway.v4 : &rt->rt_dst.prefix.v4, sizeof(rt->rt_dst.prefix.v4));
812 if (flag == RT_NIIT) {
813 union olsr_ip_addr ipv4_addr;
814 /* create an ipv4 route */
815 olsr_syslog(OLSR_LOG_ERR,"niit suport not fully implemented!!\n");
817 /* fix prefix length */
818 req.r.rtm_dst_len = rt->rt_dst.prefix_len - 96;
819 olsr_netlink_addreq(&req, RTA_DST, olsr_ipv6_to_ipv4(&rt->rt_dst.prefix, &ipv4_addr), sizeof(ipv4_addr.v4));
822 if ( ( flag != RT_SMARTGW )
823 && ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE)
824 && (0 != memcmp(&rt->rt_dst.prefix.v6, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6))) ) {
825 olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6));
826 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
828 olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ?
829 &nexthop->gateway.v6 : &rt->rt_dst.prefix.v6, sizeof(rt->rt_dst.prefix.v6));
834 iov.iov_base = &req.n;
835 iov.iov_len = req.n.nlmsg_len;
836 memset(&nladdr, 0, sizeof(nladdr));
837 nladdr.nl_family = AF_NETLINK;
838 if (0 <= (ret = sendmsg(olsr_cnf->rtnl_s, &msg, 0))) {
839 iov.iov_base = req.buf;
840 iov.iov_len = sizeof(req.buf);
841 if (0 < (ret = recvmsg(olsr_cnf->rtnl_s, &msg, 0))) {
842 struct nlmsghdr *h = (struct nlmsghdr *)(ARM_NOWARN_ALIGN)req.buf;
843 while (NLMSG_OK(h, (unsigned int)ret)) {
844 if (NLMSG_DONE == h->nlmsg_type) {
845 /* seems to reached never */
846 olsr_syslog(OLSR_LOG_INFO, "_received NLMSG_DONE");
849 if (NLMSG_ERROR == h->nlmsg_type) {
850 if (NLMSG_LENGTH(sizeof(struct nlmsgerr) <= h->nlmsg_len)) {
851 struct ipaddr_str ibuf;
852 struct ipaddr_str gbuf;
853 struct nlmsgerr *l_err = (struct nlmsgerr *)NLMSG_DATA(h);
854 errno = -l_err->error;
856 const char *const err_msg = strerror(errno);
857 struct ipaddr_str buf;
860 /* syslog debug output for various situations */
861 if ( cmd == RTM_NEWRULE ) {
862 olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on inserting empty policy rule aimed to activate RtTable %u!", err_msg, errno, rttable);
864 else if ( cmd == RTM_DELRULE ) {
865 olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on deleting empty policy rule aimed to activate rtTable %u!", err_msg, errno, rttable);
867 else if ( flag == RT_NIIT ) {
868 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));
870 else if ( flag <= RT_RETRY_AFTER_DELETE_SIMILAR ) {
871 if (rt->rt_dst.prefix.v4.s_addr!=nexthop->gateway.v4.s_addr) {
872 olsr_syslog(OLSR_LOG_ERR, "error '%s' (%d) %s route to %s/%d via %s dev %s",
873 err_msg, errno, (cmd == RTM_NEWROUTE) ? "add" : "del",
874 olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), req.r.rtm_dst_len,
875 olsr_ip_to_string(&gbuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
878 olsr_syslog(OLSR_LOG_ERR, "error '%s' (%d) %s route to %s/%d dev %s",
879 err_msg, errno, (cmd == RTM_NEWROUTE) ? "add" : "del",
880 olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), req.r.rtm_dst_len, if_ifwithindex_name(nexthop->iif_index));
883 else if (flag == RT_AUTO_ADD_GATEWAY_ROUTE) {
884 olsr_syslog(OLSR_LOG_ERR, ". error '%s' (%d) auto-add route to %s dev %s", err_msg, errno,
885 olsr_ip_to_string(&ibuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
887 else if (flag == RT_DELETE_SIMILAR_ROUTE) {
888 olsr_syslog(OLSR_LOG_ERR, ". error '%s' (%d) auto-delete route to %s dev %s", err_msg, errno,
889 olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), if_ifwithindex_name(nexthop->iif_index));
891 else if (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) {
892 olsr_syslog(OLSR_LOG_ERR, ". . error '%s' (%d) auto-delete similar route to %s dev %s", err_msg, errno,
893 olsr_ip_to_string(&ibuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
896 /* should never happen */
897 olsr_syslog(OLSR_LOG_ERR, "# invalid internal route delete/add flag (%d) used!", flag);
901 /* netlink acks requests with an errno=0 NLMSG_ERROR response! */
905 /* resolve "File exist" (17) propblems (on orig and autogen routes)*/
906 if ((errno == 17) && (cmd == RTM_NEWROUTE) && ((flag == RT_ORIG_REQUEST) || (flag == RT_AUTO_ADD_GATEWAY_ROUTE))) {
907 /* a similar route going over another gateway may be present, which has to be deleted! */
908 olsr_syslog(OLSR_LOG_ERR, ". auto-deleting similar routes to resolve 'File exists' (17) while adding route!");
909 rt_ret = RT_DELETE_SIMILAR_ROUTE; /* processing will contiune after this loop */
911 /* report success on "No such process" (3) */
912 else if ((errno == 3) && (cmd == RTM_DELROUTE) && (flag == RT_ORIG_REQUEST)) {
913 /* another similar (but slightly different) route may be present at this point
914 * , if so this will get solved when adding new route to this destination */
915 olsr_syslog(OLSR_LOG_ERR, ". ignoring 'No such process' (3) while deleting route!");
918 /* insert route to gateway on the fly if "Network unreachable" (128) on 2.4 kernels
919 * or on 2.6 kernel No such process (3) or Network unreachable (101) is reported in rtnetlink response
920 * do this only with flat metric, as using metric values inherited from
921 * a target behind the gateway is really strange, and could lead to multiple routes!
922 * anyways if invalid gateway ips may happen we are f*cked up!!
923 * but if not, these on the fly generated routes are no problem, and will only get used when needed */
924 else if ( ( (errno == 3) || (errno == 101) || (errno == 128) )
925 && (flag == RT_ORIG_REQUEST) && (FIBM_FLAT == olsr_cnf->fib_metric)
926 && (cmd == RTM_NEWROUTE) && (rt->rt_dst.prefix.v4.s_addr!=nexthop->gateway.v4.s_addr)) {
928 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (128) while adding route!");
930 else if (errno == 101) {
931 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (101) while adding route!");
934 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'No such process' (3) while adding route!");
937 /* processing will contiune after this loop */
938 rt_ret = RT_AUTO_ADD_GATEWAY_ROUTE;
941 /* report invalid message size */
943 olsr_syslog(OLSR_LOG_INFO,"_received invalid netlink message size %lu != %u",
944 (unsigned long int)sizeof(struct nlmsgerr), h->nlmsg_len);
947 /* log all other messages */
949 olsr_syslog(OLSR_LOG_INFO,"_received %u Byte rtnetlink response of type %u with seqnr %u and flags %u from %u (%u)",
950 h->nlmsg_len, h->nlmsg_type, h->nlmsg_seq, h->nlmsg_flags, h->nlmsg_pid, NLMSG_ERROR);
953 * The ARM compile complains about alignment. Copied
954 * from /usr/include/linux/netlink.h and adapted for ARM
956 #define MY_NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
957 (struct nlmsghdr*)(ARM_NOWARN_ALIGN)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
958 h = MY_NLMSG_NEXT(h, ret);
962 if ( rt_ret == RT_DELETE_SIMILAR_ROUTE ) {
963 /* delete all routes that may collide */
965 /* recursive call to delete simlar routes, using flag 2 to invoke deletion of similar, not only exact matches*/
966 rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_DELROUTE,
967 flag == RT_AUTO_ADD_GATEWAY_ROUTE ? RT_DELETE_SIMILAR_AUTO_ROUTE : RT_DELETE_SIMILAR_ROUTE);
969 /* retry insert original route, if deleting similar succeeded, using flag=1 to prevent recursions */
971 rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_RETRY_AFTER_DELETE_SIMILAR);
974 olsr_syslog(OLSR_LOG_ERR, ". failed on auto-deleting similar route conflicting with above route!");
977 /* set appropriate return code for original request, while returning simple -1/1 if called recursive */
978 if (flag != RT_AUTO_ADD_GATEWAY_ROUTE) {
980 /* successful recovery */
984 /* unrecoverable error */
989 if ( rt_ret == RT_AUTO_ADD_GATEWAY_ROUTE ) {
990 /* autoadd route via gateway */
992 /* recursive call to invoke creation of a route to the gateway */
993 rt_ret = olsr_netlink_route_int(rt, family, olsr_cnf->rttable, RTM_NEWROUTE, RT_AUTO_ADD_GATEWAY_ROUTE);
995 /* retry insert original route, if above succeeded without problems */
997 rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_RETRY_AFTER_ADD_GATEWAY);
1000 olsr_syslog(OLSR_LOG_ERR, ". failed on inserting auto-generated route to gateway of above route!");
1003 /* set appropriate return code for original request*/
1005 /* successful recovery */
1009 /* unrecoverable error */
1013 /* send ipc update on success */
1014 if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE )
1015 && (flag == RT_ORIG_REQUEST) && (0 <= rt_ret && olsr_cnf->ipc_connections > 0) ) {
1016 ipc_route_send_rtentry(&rt->rt_dst.prefix, &nexthop->gateway, metric,
1017 RTM_NEWROUTE == cmd, if_ifwithindex_name(nexthop->iif_index));
1020 olsr_syslog(OLSR_LOG_ERR,"no rtnetlink response! (no system ressources left?, everything may happen now ...)");
1025 /* external wrapper function for above patched multi purpose rtnetlink function */
1027 olsr_netlink_rule(uint8_t family, uint8_t rttable, uint16_t cmd, uint32_t priority, char* dev)
1029 return olsr_netlink_route_int((const struct rt_entry *) dev, family, rttable, cmd, priority);
1033 /* internal wrapper function for above patched function */
1034 /* added smartgw and niit route creation*/
1036 olsr_netlink_route(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd)
1038 /*check if this rule is relevant for smartgw*/
1039 if ((olsr_cnf->smart_gw_active) && (rt->rt_dst.prefix_len == 0) )
1041 if (cmd == RTM_DELROUTE){ /*should we do something sane here!!??*/
1042 printf("ignoreing deletion of default route for smart gateway!!\n");
1046 if (!olsr_cnf->ipip_if_index) {
1048 printf("creating tunnel %s\n",olsr_cnf->ipip_name);
1050 set_tunl(SIOCADDTUNNEL,rt->rt_best->rtp_originator.v4.s_addr);
1051 olsr_cnf->ipip_if_up=false;/*rtnetlink monitoring will detect it up*/
1052 /*!!?? currently it gets never deleted on shutdown, anyways reusing existing tunnel might be a safe approach if creating fails?*/
1053 /*set tunnel up with originator ip*/
1054 r=olsr_if_setip(olsr_cnf->ipip_name, &olsr_cnf->main_addr, 0);
1055 printf("result of ifup is %i\n",r);
1056 /*find out iifindex (maybe it works even if above failed (old tunnel))*/
1057 olsr_cnf->ipip_if_index=if_nametoindex(olsr_cnf->ipip_name);
1058 printf("index of new olsrtunl is %i\n",olsr_cnf->ipip_if_index);
1062 printf("changing tunnel %s:\n",olsr_cnf->ipip_name);
1063 /*change tunnel to new originator or potentially new gateway*/
1064 if ((olsr_cnf->ipip_remote_address != rt->rt_best->rtp_originator.v4.s_addr) && (rt->rt_best->rtp_originator.v4.s_addr != 0x00000000) ) {
1065 struct ipaddr_str buf;
1066 printf("changing tunnel to %s\n",olsr_ip_to_string(&buf,&rt->rt_best->rtp_originator));
1067 olsr_cnf->ipip_remote_address = rt->rt_best->rtp_originator.v4.s_addr;
1068 set_tunl(SIOCCHGTUNNEL,olsr_cnf->ipip_remote_address);
1071 /*create route into tunnel*/
1072 olsr_netlink_route_int(rt, family, olsr_cnf->rttable_smartgw, cmd, RT_SMARTGW);
1075 /*normal route in default route table*/
1077 /*create/delete niit route if we have an niit device*/
1078 if ((olsr_cnf->niit4to6_if_index!=0) && (family != AF_INET) && (olsr_is_niit_ipv6(&rt->rt_dst.prefix))) {
1079 olsr_netlink_route_int(rt, family, rttable, cmd, RT_NIIT);
1082 return olsr_netlink_route_int(rt, family, rttable, cmd, RT_ORIG_REQUEST);
1086 #endif /* LINUX_POLICY_ROUTING */
1089 * Insert a route in the kernel routing table
1091 * @param destination the route to add
1093 * @return negative on error
1096 olsr_ioctl_add_route(const struct rt_entry *rt)
1098 #if !LINUX_POLICY_ROUTING
1099 struct rtentry kernel_route;
1100 union olsr_ip_addr mask;
1102 #endif /* LINUX_POLICY_ROUTING */
1104 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
1106 #if !LINUX_POLICY_ROUTING
1107 memset(&kernel_route, 0, sizeof(struct rtentry));
1109 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
1110 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
1111 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
1113 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
1115 if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
1118 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
1120 if (rt->rt_dst.prefix.v4.s_addr != rt->rt_best->rtp_nexthop.gateway.v4.s_addr) {
1121 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_best->rtp_nexthop.gateway.v4;
1124 kernel_route.rt_flags = olsr_rt_flags(rt);
1125 kernel_route.rt_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
1130 kernel_route.rt_dev = if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index);
1132 /* delete existing default route before ? */
1133 if ((olsr_cnf->del_gws) && (rt->rt_dst.prefix.v4.s_addr == INADDR_ANY) && (rt->rt_dst.prefix_len == INADDR_ANY)) {
1134 delete_all_inet_gws();
1135 olsr_cnf->del_gws = false;
1138 if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
1141 * Send IPC route update message
1143 ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
1144 if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
1148 #else /* !LINUX_POLICY_ROUTING */
1150 /*put large hnas also into RtTabledefault (if smartgateway is active) as they may be used to replace (huge parts) of a normal default route*/
1151 if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable) {
1153 * Users start whining about not having internet with policy
1154 * routing activated and no static default route in table 254.
1155 * We maintain a fallback defroute in the default=253 table.
1157 * which was always insane but togehter with smartgateways policy routing its too insane
1159 if (!olsr_cnf->smart_gw_active) olsr_netlink_route(rt, AF_INET, 253, RTM_NEWROUTE);
1161 if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
1162 return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_NEWROUTE);
1165 return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_NEWROUTE);
1169 return olsr_netlink_process_rt_entry(rt, true);
1170 #endif /* LINUX_POLICY_ROUTING */
1174 *Insert a route in the kernel routing table
1176 *@param destination the route to add
1178 *@return negative on error
1181 olsr_ioctl_add_route6(const struct rt_entry *rt)
1183 #if !LINUX_POLICY_ROUTING
1184 struct in6_rtmsg kernel_route;
1187 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
1189 memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
1191 kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6;
1192 kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
1194 kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
1196 kernel_route.rtmsg_flags = olsr_rt_flags(rt);
1197 kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
1202 kernel_route.rtmsg_ifindex = rt->rt_best->rtp_nexthop.iif_index;
1204 /* XXX delete 0/0 route before ? */
1206 if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
1209 * Send IPC route update message
1211 ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
1212 if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
1215 #else /* !LINUX_POLICY_ROUTING */
1218 if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
1219 return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_NEWROUTE);
1222 return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_NEWROUTE);
1226 return olsr_netlink_process_rt_entry(rt, true);
1227 #endif /* LINUX_POLICY_ROUTING */
1231 *Remove a route from the kernel
1233 *@param destination the route to remove
1235 *@return negative on error
1238 olsr_ioctl_del_route(const struct rt_entry *rt)
1240 #if !LINUX_POLICY_ROUTING
1241 struct rtentry kernel_route;
1242 union olsr_ip_addr mask;
1244 #endif /* LINUX_POLICY_ROUTING */
1246 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
1248 #if !LINUX_POLICY_ROUTING
1249 memset(&kernel_route, 0, sizeof(struct rtentry));
1251 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
1252 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
1253 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
1255 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
1257 if (rt->rt_dst.prefix.v4.s_addr != rt->rt_nexthop.gateway.v4.s_addr) {
1258 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_nexthop.gateway.v4;
1261 if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
1264 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
1267 kernel_route.rt_flags = olsr_rt_flags(rt);
1268 kernel_route.rt_metric = olsr_fib_metric(&rt->rt_metric.hops);
1273 kernel_route.rt_dev = NULL;
1275 if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route)) >= 0) {
1278 * Send IPC route update message
1280 ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
1284 #else /* !LINUX_POLICY_ROUTING */
1287 if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable) {
1289 * Also remove the fallback default route
1291 olsr_netlink_route(rt, AF_INET, 253, RTM_DELROUTE);
1293 if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
1294 return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_DELROUTE);
1297 return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_DELROUTE);
1300 return olsr_netlink_process_rt_entry(rt, false);
1301 #endif /* LINUX_POLICY_ROUTING */
1305 *Remove a route from the kernel
1307 *@param destination the route to remove
1309 *@return negative on error
1312 olsr_ioctl_del_route6(const struct rt_entry *rt)
1314 #if !LINUX_POLICY_ROUTING
1315 struct in6_rtmsg kernel_route;
1317 #endif /* LINUX_POLICY_ROUTING */
1319 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
1321 #if !LINUX_POLICY_ROUTING
1322 memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
1324 kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6;
1325 kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
1327 kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
1329 kernel_route.rtmsg_flags = olsr_rt_flags(rt);
1330 kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
1332 if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route) >= 0)) {
1335 * Send IPC route update message
1337 ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
1341 #else /* !LINUX_POLICY_ROUTING */
1343 if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
1344 return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_DELROUTE);
1347 return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_DELROUTE);
1350 return olsr_netlink_process_rt_entry(rt, false);
1351 #endif /* LINUX_POLICY_ROUTING */
1354 #if !LINUX_POLICY_ROUTING
1356 delete_all_inet_gws(void)
1359 char buf[BUFSIZ], *cp, *cplim;
1363 OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n");
1366 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1367 olsr_syslog(OLSR_LOG_ERR, "socket: %m");
1371 ifc.ifc_len = sizeof(buf);
1373 if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
1374 olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");
1380 cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
1381 for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) {
1382 struct rtentry kernel_route;
1383 ifr = (struct ifreq *)cp;
1385 if (strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0) {
1386 OLSR_PRINTF(1, "Skipping loopback...\n");
1390 OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name);
1392 memset(&kernel_route, 0, sizeof(struct rtentry));
1394 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;
1395 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
1396 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;
1397 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
1399 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
1400 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
1402 kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
1404 kernel_route.rt_dev = ifr->ifr_ifrn.ifrn_name;
1406 if ((ioctl(s, SIOCDELRT, &kernel_route)) < 0)
1407 OLSR_PRINTF(1, "NO\n");
1409 OLSR_PRINTF(1, "YES\n");
1414 #endif /* LINUX_POLICY_ROUTING */
1419 * indent-tabs-mode: nil