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"
46 /* values for control flag to handle recursive route corrections
47 * currently only requires in linux specific kernel_routes.c */
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
57 #if !LINUX_POLICY_ROUTING
59 static int delete_all_inet_gws(void);
61 #else /* !LINUX_POLICY_ROUTING */
64 #include <linux/types.h>
65 #include <linux/rtnetlink.h>
68 #include <netinet/in.h>
69 #include <sys/ioctl.h>
72 #include <linux/if_tunnel.h>
75 #include <sys/socket.h>
76 #include <sys/ioctl.h>
77 #include <sys/types.h>
80 extern struct rtnl_handle rth;
88 /*takes up an interface*/
89 int olsr_dev_up(const char * dev,bool set_ip)
93 s = socket(PF_INET, SOCK_DGRAM, 0);
98 memset(&ifr, 0, sizeof(ifr));
99 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
102 struct sockaddr_in sin;
103 memset(&sin, 0, sizeof(struct sockaddr_in));
104 sin.sin_family = AF_INET;
105 sin.sin_addr.s_addr = 0x01020304;//!!??use originator address
106 memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr_in));
108 r = ioctl(s, SIOCSIFADDR, &ifr);
113 /*reset ifreq fuild for IFFLGAS*/
114 memset(&sin, 0, sizeof( struct sockaddr_in) );
117 ifr.ifr_flags = IFF_UP; //!!?? read old flags and before setting new ones
118 r = ioctl(s, SIOCGIFFLAGS, &ifr);
119 /*check if already up*/
120 if ((short int)ifr.ifr_flags & IFF_UP) return true;
122 ifr.ifr_flags |= IFF_UP;
123 r = ioctl(s, SIOCSIFFLAGS, &ifr);
131 #if LINUX_RTNETLINK_LISTEN
133 #include "socket_parser.h"
135 int rtnetlink_register_socket(int rtnl_mgrp)
137 int sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
138 struct sockaddr_nl addr;
141 OLSR_PRINTF(1,"could not create rtnetlink socket! %d",sock);
144 memset(&addr, 0, sizeof(addr));
146 addr.nl_family = AF_NETLINK;
147 addr.nl_pid = 0; //kernel will assign appropiate number instead of pid (which is already used by primaray rtnetlink socket to add/delete routes)
148 addr.nl_groups = rtnl_mgrp;
149 if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0) {
150 OLSR_PRINTF(1,"could not bind socket! (%d %s)",errno,strerror(errno));
153 add_olsr_socket(sock, &rtnetlink_read);
155 fcntl(sock, F_SETFL, O_NONBLOCK);
160 static void netlink_process_link(struct nlmsghdr *h)
162 struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(h);
163 struct interface *iface;
164 struct olsr_if *tmp_if;
166 iface = if_ifwithindex(ifi->ifi_index);
171 //all IFF flags: LOOPBACK,BROADCAST;POINTOPOINT;MULTICAST;NOARP;ALLMULTI;PROMISC;MASTER;SLAVE;DEBUG;DYNAMIC;AUTOMEDIA;PORTSEL;NOTRAILERS;UP;LOWER_UP;DORMANT
172 /* check if interface is up and running? (a not running interface keeps its routes, so better not react like on ifdown!!??) */
173 if (ifi->ifi_flags&IFF_UP) {
174 OLSR_PRINTF(3,"interface %s changed but is still up! ", iface->int_name);
175 return; //we are currently only interested in interfaces that are/go down
177 OLSR_PRINTF(1,"interface %s is down! ", iface->int_name);
180 //only for still configured interfaces (ifup has to be detected with regular interface polling)
181 for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) {
182 if (tmp_if->interf==iface) {
183 OLSR_PRINTF(1,"-> removing %s from olsr config! ", iface->int_name);
184 RemoveInterface(tmp_if,true);
190 void rtnetlink_read(int sock)
194 struct sockaddr_nl nladdr;
195 struct msghdr msg = {
206 struct nlmsghdr *nlh = (struct nlmsghdr *)(ARM_NOWARN_ALIGN) buffer;
209 iov.iov_base = (void *) buffer;
210 iov.iov_len = sizeof(buffer);
212 while (true) { //read until ret<0;
213 ret=recvmsg(sock, &msg, 0);
215 if (errno != EAGAIN) OLSR_PRINTF(1,"\nnetlink listen error %u - %s",errno,strerror(errno));
219 len = nlh->nlmsg_len;
220 plen = len - sizeof(nlh);
221 if (len > ret || plen < 0) {
222 OLSR_PRINTF(1,"Malformed netlink message: "
223 "len=%d left=%d plen=%d",
227 if ( (nlh->nlmsg_type == RTM_NEWLINK) || ( nlh->nlmsg_type == RTM_DELLINK) ) netlink_process_link(nlh);
231 //!!?? listen on our own tunlx interfaces aswell
233 #endif /*linux_rtnetlink_listen*/
235 /*create or change a ipip tunnel ipv4 only*/
236 static int set_tunl(int cmd, unsigned long int ipv4)
241 struct ip_tunnel_parm p;
245 p.iph.protocol=IPPROTO_IPIP; //IPPROTO_IPV6
246 p.iph.saddr=0x00000000;
249 strncpy(p.name, olsr_cnf->ipip_name, IFNAMSIZ);
251 //specify existing interface name
252 if (cmd!=SIOCADDTUNNEL) strncpy(ifr.ifr_name, olsr_cnf->ipip_name, IFNAMSIZ);
254 ifr.ifr_ifru.ifru_data = (void *) &p;
255 fd = socket(AF_INET, SOCK_DGRAM, 0);//warning hardcoded AF_INET
256 err = ioctl(fd, cmd, &ifr);
257 if (err) perror("ioctl");
263 olsr_netlink_addreq(struct olsr_rtreq *req, int type, const void *data, int len)
265 struct rtattr *rta = (struct rtattr *)(ARM_NOWARN_ALIGN)(((char *)req) + NLMSG_ALIGN(req->n.nlmsg_len));
266 req->n.nlmsg_len = NLMSG_ALIGN(req->n.nlmsg_len) + RTA_LENGTH(len);
267 assert(req->n.nlmsg_len < sizeof(struct olsr_rtreq));
268 rta->rta_type = type;
269 rta->rta_len = RTA_LENGTH(len);
270 memcpy(RTA_DATA(rta), data, len);
274 * -1 on unrecoverable error (calling function will have to handle it)
275 * 0 on unexpected but recoverable rtnetlink behaviour
276 * but some of the implemented recovery methods only cure symptoms,
277 * not the cause, like unintelligent ordering of inserted routes.
280 olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd, uint16_t flag)
282 int ret = 1; /* helper variable for rtnetlink_message processing */
283 int rt_ret = -2; /* if no response from rtnetlink it must be considered as failed! */
284 struct olsr_rtreq req;
286 struct sockaddr_nl nladdr;
287 struct msghdr msg = {
298 const struct rt_nexthop *nexthop = NULL;
299 if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE ) ) {
300 if (FIBM_FLAT == olsr_cnf->fib_metric) {
301 metric = RT_METRIC_DEFAULT;
304 metric = (RTM_NEWROUTE == cmd) ? rt->rt_best->rtp_metric.hops : rt->rt_metric.hops;
307 if (( RTM_NEWROUTE == cmd ) ||
308 (( RTM_DELROUTE == cmd ) && ( RT_DELETE_SIMILAR_ROUTE == flag || RT_DELETE_SIMILAR_AUTO_ROUTE == flag ))) {
309 nexthop = &rt->rt_best->rtp_nexthop;
312 nexthop = &rt->rt_nexthop;
316 memset(&req, 0, sizeof(req));
318 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
319 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
320 req.n.nlmsg_type = cmd;
322 /*sanity check for niit ipv4 over ipv6 routes*/
323 if (family == AF_INET && flag == RT_NIIT) {
324 olsr_syslog(OLSR_LOG_ERR,"niit makes no sense with olsrd running on ipv4!");
328 if (flag == RT_NIIT) {
329 req.r.rtm_family=AF_INET; /*we create an ipv4 niit route*/
332 req.r.rtm_family = family;
335 req.r.rtm_table = rttable;
337 /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
338 /* -> olsr only adds deletes unicast routes */
339 req.r.rtm_type = RTN_UNICAST;
341 /* wildcard to delete routes of all protos if no simlar-delete correct proto will get set below */
342 req.r.rtm_protocol = RTPROT_UNSPEC;
344 /* as wildcard for deletion */
345 req.r.rtm_scope = RT_SCOPE_NOWHERE;
347 if ( ( cmd == RTM_NEWRULE ) || ( cmd == RTM_DELRULE ) ) {
348 /* add or delete a rule */
349 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
350 olsr_netlink_addreq(&req, RTA_PRIORITY, &flag, sizeof(flag));
352 /*add interface name to rule*/
353 //olsr_netlink_addreq(&req, RTA_interface, &rt, sizeof(?));
354 printf("rule interface %s ignored!",(const char *) rt);
358 req.r.rtm_dst_len = rt->rt_dst.prefix_len;
360 /* do not specify much as we wanna delete similar/conflicting routes */
361 if ( ( flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE )) {
362 /* 0 gets replaced by OS-specifc default (3)
363 * 1 is reserved so we take 0 instead (this really makes some sense)
364 * other numbers are used 1:1 */
365 req.r.rtm_protocol = ( (olsr_cnf->rtproto<1) ? RTPROT_BOOT : ( (olsr_cnf->rtproto==1) ? 0 : olsr_cnf->rtproto) );
366 req.r.rtm_scope = RT_SCOPE_LINK;
369 if ((&olsr_cnf->smart_gateway_active) && (rt->rt_dst.prefix_len == 0) && (&olsr_cnf->ipip_if_index==NULL))
372 set_tunl(SIOCADDTUNNEL,rt->rt_best->rtp_originator.v4.s_addr);
373 //!!?? currently it gets never deleted at shutdown, anyways reusing existing tunnel might be a safe approach if creating fails?
374 //set tunnel up with originator ip
375 olsr_dev_up(olsr_cnf->ipip_name,true);
376 //find out iifindex (maybe it works even if above failed (old tunnel))
377 olsr_cnf->ipip_if_index=if_nametoindex(olsr_cnf->ipip_name);
381 if ((&olsr_cnf->smart_gateway_active) && family != AF_INET)
383 printf("smart gateway not available for ipv6 currently");
386 else if ((&olsr_cnf->smart_gateway_active) && (rt->rt_dst.prefix_len == 0) && (&olsr_cnf->ipip_if_index))
388 //change tunnel to new originator og potentially new gateway
389 if (olsr_cnf->ipip_remote_address != rt->rt_best->rtp_originator.v4.s_addr)
391 struct ipaddr_str buf;
392 printf("changing tunnel to %s",olsr_ip_to_string(&buf,&rt->rt_best->rtp_originator));
393 olsr_cnf->ipip_remote_address = rt->rt_best->rtp_originator.v4.s_addr;
394 set_tunl(SIOCCHGTUNNEL,olsr_cnf->ipip_remote_address);
397 olsr_netlink_addreq(&req, RTA_OIF, &olsr_cnf->niit_if_index, sizeof(&olsr_cnf->ipip_if_index));
399 else if (flag == RT_NIIT) {
400 olsr_netlink_addreq(&req, RTA_OIF, &olsr_cnf->niit_if_index, sizeof(&olsr_cnf->niit_if_index));
403 olsr_netlink_addreq(&req, RTA_OIF, &nexthop->iif_index, sizeof(nexthop->iif_index));
408 * source ip here is based on now static olsr_cnf->main_addr in this olsr-0.5.6-r4,
409 * should be based on orignator-id in newer olsrds
411 if (flag != RT_NIIT) {
412 if (AF_INET == family) {
413 olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v4.s_addr, sizeof(olsr_cnf->main_addr.v4.s_addr));
416 olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v6.s6_addr, sizeof(olsr_cnf->main_addr.v6.s6_addr));
422 /* metric is specified always as we can only delete one route per iteration, and wanna hit the correct one first */
423 if (FIBM_APPROX != olsr_cnf->fib_metric || (RTM_NEWROUTE == cmd) ) {
424 olsr_netlink_addreq(&req, RTA_PRIORITY, &metric, sizeof(metric));
427 /* make sure that netmask = maxplen (32 or 128) as this is an autogenarated (host)route */
428 if (( flag == RT_AUTO_ADD_GATEWAY_ROUTE ) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) {
429 req.r.rtm_dst_len = olsr_cnf->maxplen;
433 * for ipv4 or ipv6 we add gateway if one is specified,
434 * or leave gateway away if we want to delete similar routes aswell,
435 * or even use the gateway as target if we add a auto-generated route,
436 * or if delete-similar to make insertion of auto-generated route possible
438 if (AF_INET == family) {
439 if ( !( (rt->rt_dst.prefix_len == 0) && (olsr_cnf->smart_gateway_active) )
440 && ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE) &&
441 ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE) && (rt->rt_dst.prefix.v4.s_addr != nexthop->gateway.v4.s_addr) ) {
442 olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v4, sizeof(nexthop->gateway.v4));
443 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
445 olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ?
446 &nexthop->gateway.v4 : &rt->rt_dst.prefix.v4, sizeof(rt->rt_dst.prefix.v4));
448 if (flag == RT_NIIT) {
449 union olsr_ip_addr ipv4_addr;
450 /* create an ipv4 route */
451 olsr_syslog(OLSR_LOG_ERR,"niit suport not fully implemented!!");
452 olsr_netlink_addreq(&req, RTA_DST, olsr_ipv6_to_ipv4(&rt->rt_dst.prefix, &ipv4_addr), sizeof(ipv4_addr.v4));
455 if ( !( (rt->rt_dst.prefix_len == 0) && (olsr_cnf->smart_gateway_active) )
456 && ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE)
457 && (0 != memcmp(&rt->rt_dst.prefix.v6, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6))) ) {
458 olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6));
459 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
461 olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ?
462 &nexthop->gateway.v6 : &rt->rt_dst.prefix.v6, sizeof(rt->rt_dst.prefix.v6));
467 iov.iov_base = &req.n;
468 iov.iov_len = req.n.nlmsg_len;
469 memset(&nladdr, 0, sizeof(nladdr));
470 nladdr.nl_family = AF_NETLINK;
471 if (0 <= (ret = sendmsg(olsr_cnf->rtnl_s, &msg, 0))) {
472 iov.iov_base = req.buf;
473 iov.iov_len = sizeof(req.buf);
474 if (0 < (ret = recvmsg(olsr_cnf->rtnl_s, &msg, 0))) {
475 struct nlmsghdr *h = (struct nlmsghdr *)(ARM_NOWARN_ALIGN)req.buf;
476 while (NLMSG_OK(h, (unsigned int)ret)) {
477 if (NLMSG_DONE == h->nlmsg_type) {
478 /* seems to reached never */
479 olsr_syslog(OLSR_LOG_INFO, "_received NLMSG_DONE");
482 if (NLMSG_ERROR == h->nlmsg_type) {
483 if (NLMSG_LENGTH(sizeof(struct nlmsgerr) <= h->nlmsg_len)) {
484 struct ipaddr_str ibuf;
485 struct ipaddr_str gbuf;
486 struct nlmsgerr *l_err = (struct nlmsgerr *)NLMSG_DATA(h);
487 errno = -l_err->error;
489 const char *const err_msg = strerror(errno);
490 struct ipaddr_str buf;
493 /* syslog debug output for various situations */
494 if ( cmd == RTM_NEWRULE ) {
495 olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on inserting empty policy rule aimed to activate RtTable %u!", err_msg, errno, rttable);
497 else if ( cmd == RTM_DELRULE ) {
498 olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on deleting empty policy rule aimed to activate rtTable %u!", err_msg, errno, rttable);
500 else if ( flag == RT_NIIT ) {
501 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));
503 else if ( flag <= RT_RETRY_AFTER_DELETE_SIMILAR ) {
504 if (rt->rt_dst.prefix.v4.s_addr!=nexthop->gateway.v4.s_addr) {
505 olsr_syslog(OLSR_LOG_ERR, "error '%s' (%d) %s route to %s/%d via %s dev %s",
506 err_msg, errno, (cmd == RTM_NEWROUTE) ? "add" : "del",
507 olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), req.r.rtm_dst_len,
508 olsr_ip_to_string(&gbuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
511 olsr_syslog(OLSR_LOG_ERR, "error '%s' (%d) %s route to %s/%d dev %s",
512 err_msg, errno, (cmd == RTM_NEWROUTE) ? "add" : "del",
513 olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), req.r.rtm_dst_len, if_ifwithindex_name(nexthop->iif_index));
516 else if (flag == RT_AUTO_ADD_GATEWAY_ROUTE) {
517 olsr_syslog(OLSR_LOG_ERR, ". error '%s' (%d) auto-add route to %s dev %s", err_msg, errno,
518 olsr_ip_to_string(&ibuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
520 else if (flag == RT_DELETE_SIMILAR_ROUTE) {
521 olsr_syslog(OLSR_LOG_ERR, ". error '%s' (%d) auto-delete route to %s dev %s", err_msg, errno,
522 olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), if_ifwithindex_name(nexthop->iif_index));
524 else if (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) {
525 olsr_syslog(OLSR_LOG_ERR, ". . error '%s' (%d) auto-delete similar route to %s dev %s", err_msg, errno,
526 olsr_ip_to_string(&ibuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
529 /* should never happen */
530 olsr_syslog(OLSR_LOG_ERR, "# invalid internal route delete/add flag (%d) used!", flag);
534 /* netlink acks requests with an errno=0 NLMSG_ERROR response! */
538 /* resolve "File exist" (17) propblems (on orig and autogen routes)*/
539 if ((errno == 17) && (cmd == RTM_NEWROUTE) && ((flag == RT_ORIG_REQUEST) || (flag == RT_AUTO_ADD_GATEWAY_ROUTE))) {
540 /* a similar route going over another gateway may be present, which has to be deleted! */
541 olsr_syslog(OLSR_LOG_ERR, ". auto-deleting similar routes to resolve 'File exists' (17) while adding route!");
542 rt_ret = RT_DELETE_SIMILAR_ROUTE; /* processing will contiune after this loop */
544 /* report success on "No such process" (3) */
545 else if ((errno == 3) && (cmd == RTM_DELROUTE) && (flag == RT_ORIG_REQUEST)) {
546 /* another similar (but slightly different) route may be present at this point
547 * , if so this will get solved when adding new route to this destination */
548 olsr_syslog(OLSR_LOG_ERR, ". ignoring 'No such process' (3) while deleting route!");
551 /* insert route to gateway on the fly if "Network unreachable" (128) on 2.4 kernels
552 * or on 2.6 kernel No such process (3) or Network unreachable (101) is reported in rtnetlink response
553 * do this only with flat metric, as using metric values inherited from
554 * a target behind the gateway is really strange, and could lead to multiple routes!
555 * anyways if invalid gateway ips may happen we are f*cked up!!
556 * but if not, these on the fly generated routes are no problem, and will only get used when needed */
557 else if ( ( (errno == 3) || (errno == 101) || (errno == 128) )
558 && (flag == RT_ORIG_REQUEST) && (FIBM_FLAT == olsr_cnf->fib_metric)
559 && (cmd == RTM_NEWROUTE) && (rt->rt_dst.prefix.v4.s_addr!=nexthop->gateway.v4.s_addr)) {
561 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (128) while adding route!");
563 else if (errno == 101) {
564 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (101) while adding route!");
567 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'No such process' (3) while adding route!");
570 /* processing will contiune after this loop */
571 rt_ret = RT_AUTO_ADD_GATEWAY_ROUTE;
574 /* report invalid message size */
576 olsr_syslog(OLSR_LOG_INFO,"_received invalid netlink message size %lu != %u",
577 (unsigned long int)sizeof(struct nlmsgerr), h->nlmsg_len);
580 /* log all other messages */
582 olsr_syslog(OLSR_LOG_INFO,"_received %u Byte rtnetlink response of type %u with seqnr %u and flags %u from %u (%u)",
583 h->nlmsg_len, h->nlmsg_type, h->nlmsg_seq, h->nlmsg_flags, h->nlmsg_pid, NLMSG_ERROR);
586 * The ARM compile complains about alignment. Copied
587 * from /usr/include/linux/netlink.h and adapted for ARM
589 #define MY_NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
590 (struct nlmsghdr*)(ARM_NOWARN_ALIGN)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
591 h = MY_NLMSG_NEXT(h, ret);
595 if ( rt_ret == RT_DELETE_SIMILAR_ROUTE ) {
596 /* delete all routes that may collide */
598 /* recursive call to delete simlar routes, using flag 2 to invoke deletion of similar, not only exact matches*/
599 rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_DELROUTE,
600 flag == RT_AUTO_ADD_GATEWAY_ROUTE ? RT_DELETE_SIMILAR_AUTO_ROUTE : RT_DELETE_SIMILAR_ROUTE);
602 /* retry insert original route, if deleting similar succeeded, using flag=1 to prevent recursions */
604 rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_RETRY_AFTER_DELETE_SIMILAR);
607 olsr_syslog(OLSR_LOG_ERR, ". failed on auto-deleting similar route conflicting with above route!");
610 /* set appropriate return code for original request, while returning simple -1/1 if called recursive */
611 if (flag != RT_AUTO_ADD_GATEWAY_ROUTE) {
613 /* successful recovery */
617 /* unrecoverable error */
622 if ( rt_ret == RT_AUTO_ADD_GATEWAY_ROUTE ) {
623 /* autoadd route via gateway */
625 /* recursive call to invoke creation of a route to the gateway */
626 rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_AUTO_ADD_GATEWAY_ROUTE);
628 /* retry insert original route, if above succeeded without problems */
630 rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_RETRY_AFTER_ADD_GATEWAY);
633 olsr_syslog(OLSR_LOG_ERR, ". failed on inserting auto-generated route to gateway of above route!");
636 /* set appropriate return code for original request*/
638 /* successful recovery */
642 /* unrecoverable error */
646 /* send ipc update on success */
647 if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE )
648 && (flag == RT_ORIG_REQUEST) && (0 <= rt_ret && olsr_cnf->ipc_connections > 0) ) {
649 ipc_route_send_rtentry(&rt->rt_dst.prefix, &nexthop->gateway, metric,
650 RTM_NEWROUTE == cmd, if_ifwithindex_name(nexthop->iif_index));
653 olsr_syslog(OLSR_LOG_ERR,"no rtnetlink response! (no system ressources left?, everything may happen now ...)");
658 /* external wrapper function for above patched multi purpose rtnetlink function */
660 olsr_netlink_rule(uint8_t family, uint8_t rttable, uint16_t cmd, uint32_t priority, char* dev)
662 printf("rule priority not supported");
663 return olsr_netlink_route_int((const struct rt_entry *) dev, family, rttable, cmd, priority);
666 /* internal wrapper function for above patched function */
668 olsr_netlink_route(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd)
670 /*create/delete niit route if we have an niit device*/
671 if ((olsr_cnf->niit_if_index!=0) && (family != AF_INET) && (olsr_is_niit_ip(&rt->rt_dst.prefix))) {
672 olsr_netlink_route_int(rt, family, rttable, cmd, RT_NIIT);
675 return olsr_netlink_route_int(rt, family, rttable, cmd, RT_ORIG_REQUEST);
678 #endif /* LINUX_POLICY_ROUTING */
681 * Insert a route in the kernel routing table
683 * @param destination the route to add
685 * @return negative on error
688 olsr_ioctl_add_route(const struct rt_entry *rt)
690 #if !LINUX_POLICY_ROUTING
691 struct rtentry kernel_route;
692 union olsr_ip_addr mask;
694 #endif /* LINUX_POLICY_ROUTING */
696 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
698 #if !LINUX_POLICY_ROUTING
699 memset(&kernel_route, 0, sizeof(struct rtentry));
701 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
702 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
703 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
705 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
707 if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
710 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
712 if (rt->rt_dst.prefix.v4.s_addr != rt->rt_best->rtp_nexthop.gateway.v4.s_addr) {
713 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_best->rtp_nexthop.gateway.v4;
716 kernel_route.rt_flags = olsr_rt_flags(rt);
717 kernel_route.rt_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
722 kernel_route.rt_dev = if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index);
724 /* delete existing default route before ? */
725 if ((olsr_cnf->del_gws) && (rt->rt_dst.prefix.v4.s_addr == INADDR_ANY) && (rt->rt_dst.prefix_len == INADDR_ANY)) {
726 delete_all_inet_gws();
727 olsr_cnf->del_gws = false;
730 if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
733 * Send IPC route update message
735 ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
736 if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
740 #else /* !LINUX_POLICY_ROUTING */
741 if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable) {
743 * Users start whining about not having internet with policy
744 * routing activated and no static default route in table 254.
745 * We maintain a fallback defroute in the default=253 table.
747 olsr_netlink_route(rt, AF_INET, 253, RTM_NEWROUTE);
749 if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
750 return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_NEWROUTE);
753 return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_NEWROUTE);
755 #endif /* LINUX_POLICY_ROUTING */
759 *Insert a route in the kernel routing table
761 *@param destination the route to add
763 *@return negative on error
766 olsr_ioctl_add_route6(const struct rt_entry *rt)
768 #if !LINUX_POLICY_ROUTING
769 struct in6_rtmsg kernel_route;
772 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
774 memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
776 kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6;
777 kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
779 kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
781 kernel_route.rtmsg_flags = olsr_rt_flags(rt);
782 kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
787 kernel_route.rtmsg_ifindex = rt->rt_best->rtp_nexthop.iif_index;
789 /* XXX delete 0/0 route before ? */
791 if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
794 * Send IPC route update message
796 ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
797 if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
800 #else /* !LINUX_POLICY_ROUTING */
801 if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
802 return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_NEWROUTE);
805 return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_NEWROUTE);
807 #endif /* LINUX_POLICY_ROUTING */
811 *Remove a route from the kernel
813 *@param destination the route to remove
815 *@return negative on error
818 olsr_ioctl_del_route(const struct rt_entry *rt)
820 #if !LINUX_POLICY_ROUTING
821 struct rtentry kernel_route;
822 union olsr_ip_addr mask;
824 #endif /* LINUX_POLICY_ROUTING */
826 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
828 #if !LINUX_POLICY_ROUTING
829 memset(&kernel_route, 0, sizeof(struct rtentry));
831 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
832 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
833 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
835 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
837 if (rt->rt_dst.prefix.v4.s_addr != rt->rt_nexthop.gateway.v4.s_addr) {
838 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_nexthop.gateway.v4;
841 if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
844 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
847 kernel_route.rt_flags = olsr_rt_flags(rt);
848 kernel_route.rt_metric = olsr_fib_metric(&rt->rt_metric.hops);
853 kernel_route.rt_dev = NULL;
855 if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route)) >= 0) {
858 * Send IPC route update message
860 ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
864 #else /* !LINUX_POLICY_ROUTING */
865 if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable) {
867 * Also remove the fallback default route
869 olsr_netlink_route(rt, AF_INET, 253, RTM_DELROUTE);
871 if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
872 return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_DELROUTE);
875 return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_DELROUTE);
877 #endif /* LINUX_POLICY_ROUTING */
881 *Remove a route from the kernel
883 *@param destination the route to remove
885 *@return negative on error
888 olsr_ioctl_del_route6(const struct rt_entry *rt)
890 #if !LINUX_POLICY_ROUTING
891 struct in6_rtmsg kernel_route;
893 #endif /* LINUX_POLICY_ROUTING */
895 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
897 #if !LINUX_POLICY_ROUTING
898 memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
900 kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6;
901 kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
903 kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
905 kernel_route.rtmsg_flags = olsr_rt_flags(rt);
906 kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
908 if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route) >= 0)) {
911 * Send IPC route update message
913 ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
917 #else /* !LINUX_POLICY_ROUTING */
918 if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
919 return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_DELROUTE);
922 return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_DELROUTE);
924 #endif /* LINUX_POLICY_ROUTING */
927 #if !LINUX_POLICY_ROUTING
929 delete_all_inet_gws(void)
932 char buf[BUFSIZ], *cp, *cplim;
936 OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n");
939 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
940 olsr_syslog(OLSR_LOG_ERR, "socket: %m");
944 ifc.ifc_len = sizeof(buf);
946 if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
947 olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");
953 cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
954 for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) {
955 struct rtentry kernel_route;
956 ifr = (struct ifreq *)cp;
958 if (strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0) {
959 OLSR_PRINTF(1, "Skipping loopback...\n");
963 OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name);
965 memset(&kernel_route, 0, sizeof(struct rtentry));
967 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;
968 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
969 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;
970 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
972 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
973 ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
975 kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
977 kernel_route.rt_dev = ifr->ifr_ifrn.ifrn_name;
979 if ((ioctl(s, SIOCDELRT, &kernel_route)) < 0)
980 OLSR_PRINTF(1, "NO\n");
982 OLSR_PRINTF(1, "YES\n");
987 #endif /* LINUX_POLICY_ROUTING */
992 * indent-tabs-mode: nil