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"
49 #include <linux/types.h>
50 #include <linux/rtnetlink.h>
53 #include <netinet/in.h>
54 #include <sys/ioctl.h>
57 #include <linux/if_tunnel.h>
60 #include <sys/socket.h>
61 #include <sys/ioctl.h>
62 #include <sys/types.h>
66 * This file contains the rtnetlink version of the linux routing code.
67 * You will find the old ioctl version in kernel_routes_ioctl.c
69 * You can deactivate this code (and activating the ioctl one)
70 * by removing the -DLINUX_NETLINK_ROUTING from make/Makefile.linux
72 #ifdef LINUX_NETLINK_ROUTING
74 * The ARM compile complains about alignment. Copied
75 * from /usr/include/linux/netlink.h and adapted for ARM
77 #define MY_NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
78 (struct nlmsghdr*)ARM_NOWARN_ALIGN((((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
81 static void rtnetlink_read(int sock, void *, unsigned int);
89 struct olsr_ipadd_req {
95 int rtnetlink_register_socket(int rtnl_mgrp)
97 int sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
98 struct sockaddr_nl addr;
101 OLSR_PRINTF(1,"could not create rtnetlink socket! %s (%d)", strerror(errno), errno);
105 memset(&addr, 0, sizeof(addr));
106 addr.nl_family = AF_NETLINK;
107 addr.nl_pid = 0; //kernel will assign appropiate number instead of pid (which is already used by primaray rtnetlink socket to add/delete routes)
108 addr.nl_groups = rtnl_mgrp;
110 if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0) {
111 OLSR_PRINTF(1,"could not bind rtnetlink socket! %s (%d)",strerror(errno), errno);
115 add_olsr_socket(sock, NULL, &rtnetlink_read, NULL, SP_IMM_READ);
119 static void netlink_process_link(struct nlmsghdr *h)
121 struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(h);
122 struct interface *iface;
124 char namebuffer[IF_NAMESIZE];
126 iface = if_ifwithindex(ifi->ifi_index);
129 if (iface == NULL && (ifi->ifi_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) {
130 if (if_indextoname(ifi->ifi_index, namebuffer)) {
131 if ((oif = olsrif_ifwithname(namebuffer)) != NULL) {
132 /* try to take interface up, will trigger ifchange */
137 else if (iface != NULL && (ifi->ifi_flags & IFF_UP) == 0) {
138 /* try to take interface down, will trigger ifchange */
139 olsr_remove_interface(iface->olsr_if);
142 if (iface == NULL && oif == NULL) {
143 /* this is not an OLSR interface */
144 if ((ifi->ifi_flags & IFF_UP) != 0 && (ifi->ifi_flags & IFF_RUNNING) != 0) {
145 olsr_trigger_ifchange(ifi->ifi_index, NULL, IFCHG_IF_ADD);
147 else if ((ifi->ifi_flags & IFF_UP) == 0 && (ifi->ifi_flags & IFF_RUNNING) == 0){
148 olsr_trigger_ifchange(ifi->ifi_index, NULL, IFCHG_IF_REMOVE);
153 static void rtnetlink_read(int sock, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
157 struct sockaddr_nl nladdr;
158 struct msghdr msg = {
169 struct nlmsghdr *nlh = (struct nlmsghdr *)ARM_NOWARN_ALIGN(buffer);
172 iov.iov_base = (void *) buffer;
173 iov.iov_len = sizeof(buffer);
175 while ((ret = recvmsg(sock, &msg, MSG_DONTWAIT)) >= 0) {
177 len = nlh->nlmsg_len;
178 plen = len - sizeof(nlh);
179 if (len > ret || plen < 0) {
180 OLSR_PRINTF(1,"Malformed netlink message: "
181 "len=%d left=%d plen=%d\n",
186 OLSR_PRINTF(3, "Netlink message received: type 0x%x\n", nlh->nlmsg_type);
187 if ((nlh->nlmsg_type == RTM_NEWLINK) || ( nlh->nlmsg_type == RTM_DELLINK)) {
188 /* handle ifup/ifdown */
189 netlink_process_link(nlh);
193 if (errno != EAGAIN) {
194 OLSR_PRINTF(1,"netlink listen error %u - %s\n",errno,strerror(errno));
199 olsr_netlink_addreq(struct nlmsghdr *n, size_t reqSize __attribute__ ((unused)), int type, const void *data, int len)
201 struct rtattr *rta = (struct rtattr *)ARM_NOWARN_ALIGN(((char *)n) + NLMSG_ALIGN(n->nlmsg_len));
202 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_LENGTH(len);
203 //produces strange compile error
204 //assert(n->nlmsg_len < reqSize);
205 rta->rta_type = type;
206 rta->rta_len = RTA_LENGTH(len);
207 memcpy(RTA_DATA(rta), data, len);
210 /*rt_entry and nexthop and family and table must only be specified with an flag != RT_NONE && != RT_LO_IP*/
212 olsr_netlink_send(struct nlmsghdr *nl_hdr)
216 struct sockaddr_nl nladdr;
219 struct nlmsgerr *l_err;
222 memset(&nladdr, 0, sizeof(nladdr));
223 memset(&msg, 0, sizeof(msg));
225 nladdr.nl_family = AF_NETLINK;
227 msg.msg_name = &nladdr;
228 msg.msg_namelen = sizeof(nladdr);
232 iov.iov_base = nl_hdr;
233 iov.iov_len = nl_hdr->nlmsg_len;
234 ret = sendmsg(olsr_cnf->rtnl_s, &msg, 0);
236 olsr_syslog(OLSR_LOG_ERR, "Cannot send data to netlink socket (%d: %s)", errno, strerror(errno));
240 iov.iov_base = rcvbuf;
241 iov.iov_len = sizeof(rcvbuf);
242 ret = recvmsg(olsr_cnf->rtnl_s, &msg, 0);
244 olsr_syslog(OLSR_LOG_ERR, "Error while reading answer to netlink message (%d: %s)", errno, strerror(errno));
248 h = (struct nlmsghdr *)ARM_NOWARN_ALIGN(rcvbuf);
249 if (!NLMSG_OK(h, (unsigned int)ret)) {
250 olsr_syslog(OLSR_LOG_ERR, "Received netlink message was malformed (ret=%d, %u)", ret, h->nlmsg_len);
254 if (h->nlmsg_type != NLMSG_ERROR) {
255 olsr_syslog(OLSR_LOG_INFO,
256 "Received unknown netlink response: %u bytes, type %u (not %u) with seqnr %u and flags %u from %u",
257 h->nlmsg_len, h->nlmsg_type, NLMSG_ERROR, h->nlmsg_seq, h->nlmsg_flags, h->nlmsg_pid);
260 if (NLMSG_LENGTH(sizeof(struct nlmsgerr)) > h->nlmsg_len) {
261 olsr_syslog(OLSR_LOG_INFO,"Received invalid netlink message size %lu != %u",
262 (unsigned long int)sizeof(struct nlmsgerr), h->nlmsg_len);
266 l_err = (struct nlmsgerr *)NLMSG_DATA(h);
269 olsr_syslog(OLSR_LOG_INFO,"Received netlink error code %s (%d)", strerror(-l_err->error), l_err->error);
271 return -l_err->error;
274 int olsr_os_policy_rule(int family, int rttable, uint32_t priority, const char *if_name, bool set) {
275 struct olsr_rtreq req;
278 memset(&req, 0, sizeof(req));
280 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
281 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
283 req.n.nlmsg_type = set ? RTM_NEWRULE : RTM_DELRULE;
284 req.r.rtm_family = family;
285 req.r.rtm_table = rttable;
287 /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
288 /* -> olsr only adds deletes unicast routes */
289 req.r.rtm_type = RTN_UNICAST;
291 /* wildcard to delete routes of all protos if no simlar-delete correct proto will get set below */
292 req.r.rtm_protocol = RTPROT_UNSPEC;
294 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
296 olsr_netlink_addreq(&req.n, sizeof(req), RTA_PRIORITY, &priority, sizeof(priority));
298 if (if_name != NULL) {
299 /*add interface name to rule*/
300 olsr_netlink_addreq(&req.n, sizeof(req), RTA_IIF, if_name, strlen(if_name)+1);
303 err = olsr_netlink_send(&req.n);
305 olsr_syslog(OLSR_LOG_ERR,"Error on %s policy rule aimed to activate RtTable %u!",
306 set ? "inserting" : "deleting", rttable);
313 olsr_add_ip(int ifindex, union olsr_ip_addr *ip, const char *l, bool create)
315 struct olsr_ipadd_req req;
317 memset(&req, 0, sizeof(req));
319 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
321 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_ACK;
322 req.n.nlmsg_type = RTM_NEWADDR;
324 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
325 req.n.nlmsg_type = RTM_DELADDR;
327 req.ifa.ifa_family = olsr_cnf->ip_version;
329 olsr_netlink_addreq(&req.n, sizeof(req), IFA_LOCAL, ip, olsr_cnf->ipsize);
331 olsr_netlink_addreq(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1);
334 req.ifa.ifa_prefixlen = olsr_cnf->ipsize * 8;
336 req.ifa.ifa_index = ifindex;
338 return olsr_netlink_send(&req.n);
342 olsr_os_localhost_if(union olsr_ip_addr *ip, bool create)
344 static char l[] = "lo:olsr";
345 return olsr_add_ip(if_nametoindex("lo"), ip, l, create);
348 int olsr_os_ifip(int ifindex, union olsr_ip_addr *ip, bool create) {
349 return olsr_add_ip(ifindex, ip, NULL, create);
352 static int olsr_new_netlink_route(int family, int rttable, int if_index, int metric, int protocol,
353 const union olsr_ip_addr *src, const union olsr_ip_addr *gw, const struct olsr_ip_prefix *dst,
354 bool set, bool del_similar) {
356 struct olsr_rtreq req;
361 struct ipaddr_str buf1, buf2;
363 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",
364 family, rttable, if_index, metric, protocol, src == NULL ? "" : olsr_ip_to_string(&buf1, src),
365 gw == NULL ? "" : olsr_ip_to_string(&buf2, gw), olsr_ip_prefix_to_string(dst),
366 set ? "true" : "false", del_similar ? "true" : "false");
368 family_size = family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr);
370 memset(&req, 0, sizeof(req));
372 req.r.rtm_flags = RTNH_F_ONLINK;
373 req.r.rtm_family = family;
374 req.r.rtm_table = rttable;
376 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
377 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
380 req.n.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
381 req.n.nlmsg_type = RTM_NEWROUTE;
383 req.n.nlmsg_type = RTM_DELROUTE;
386 /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
387 /* -> olsr only adds deletes unicast routes */
388 req.r.rtm_type = RTN_UNICAST;
390 req.r.rtm_dst_len = dst->prefix_len;
393 /* add protocol for setting a route */
394 req.r.rtm_protocol = protocol;
397 /* calculate scope of operation */
398 if (!set && del_similar) {
399 /* as wildcard for fuzzy deletion */
400 req.r.rtm_scope = RT_SCOPE_NOWHERE;
403 /* for all our routes */
404 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
407 if (set || !del_similar) {
409 olsr_netlink_addreq(&req.n, sizeof(req), RTA_OIF, &if_index, sizeof(if_index));
412 if (set && src != NULL) {
414 olsr_netlink_addreq(&req.n, sizeof(req), RTA_PREFSRC, src, family_size);
419 olsr_netlink_addreq(&req.n, sizeof(req), RTA_PRIORITY, &metric, sizeof(metric));
424 olsr_netlink_addreq(&req.n, sizeof(req), RTA_GATEWAY, gw, family_size);
427 /* use destination as gateway, to 'force' linux kernel to do proper source address selection */
428 olsr_netlink_addreq(&req.n, sizeof(req), RTA_GATEWAY, &dst->prefix, family_size);
431 /* add destination */
432 olsr_netlink_addreq(&req.n, sizeof(req), RTA_DST, &dst->prefix, family_size);
434 err = olsr_netlink_send(&req.n);
436 struct ipaddr_str buf;
438 olsr_syslog(OLSR_LOG_ERR, ". error: %s route to %s via %s dev %s onlink (%s %d)",
440 olsr_ip_prefix_to_string(dst), olsr_ip_to_string(&buf, gw),
441 if_ifwithindex_name(if_index), strerror(errno), errno);
444 olsr_syslog(OLSR_LOG_ERR, ". error: %s route to %s via %s dev %s onlink (%s %d)",
446 olsr_ip_prefix_to_string(dst), olsr_ip_to_string(&buf, &dst->prefix), if_ifwithindex_name(if_index),
447 strerror(errno), errno);
454 void olsr_os_niit_6to4_route(const struct olsr_ip_prefix *dst_v6, bool set) {
455 if (olsr_new_netlink_route(AF_INET6,
456 ip_prefix_is_mappedv4_inetgw(dst_v6) ? olsr_cnf->rt_table_default : olsr_cnf->rt_table,
457 olsr_cnf->niit6to4_if_index,
458 RT_METRIC_DEFAULT, olsr_cnf->rt_proto, NULL, NULL, dst_v6, set, false)) {
459 olsr_syslog(OLSR_LOG_ERR, ". error while %s static niit route to %s",
460 set ? "setting" : "removing", olsr_ip_prefix_to_string(dst_v6));
464 void olsr_os_niit_4to6_route(const struct olsr_ip_prefix *dst_v4, bool set) {
465 if (olsr_new_netlink_route(AF_INET,
466 ip_prefix_is_v4_inetgw(dst_v4) ? olsr_cnf->rt_table_default : olsr_cnf->rt_table,
467 olsr_cnf->niit4to6_if_index,
468 RT_METRIC_DEFAULT, olsr_cnf->rt_proto, NULL, NULL, dst_v4, set, false)) {
469 olsr_syslog(OLSR_LOG_ERR, ". error while %s niit route to %s",
470 set ? "setting" : "removing", olsr_ip_prefix_to_string(dst_v4));
474 void olsr_os_inetgw_tunnel_route(uint32_t if_idx, bool ipv4, bool set) {
475 const struct olsr_ip_prefix *dst;
477 assert(olsr_cnf->ip_version == AF_INET6 || ipv4);
479 dst = ipv4 ? &ipv4_internet_route : &ipv6_internet_route;
481 if (olsr_new_netlink_route(ipv4 ? AF_INET : AF_INET6, olsr_cnf->rt_table_tunnel,
482 if_idx, RT_METRIC_DEFAULT, olsr_cnf->rt_proto, NULL, NULL, dst, set, false)) {
483 olsr_syslog(OLSR_LOG_ERR, ". error while %s inetgw tunnel route to %s for if %d",
484 set ? "setting" : "removing", olsr_ip_prefix_to_string(dst), if_idx);
488 static int olsr_os_process_rt_entry(int af_family, const struct rt_entry *rt, bool set) {
490 const struct rt_nexthop *nexthop;
491 union olsr_ip_addr *src;
495 /* calculate metric */
496 if (FIBM_FLAT == olsr_cnf->fib_metric) {
497 metric = RT_METRIC_DEFAULT;
500 metric = set ? rt->rt_best->rtp_metric.hops : rt->rt_metric.hops;
503 if (olsr_cnf->smart_gw_active && is_prefix_inetgw(&rt->rt_dst)) {
504 /* make space for the tunnel gateway route */
509 table = is_prefix_inetgw(&rt->rt_dst)
510 ? olsr_cnf->rt_table_default : olsr_cnf->rt_table;
513 if (rt->rt_best && set) {
514 nexthop = &rt->rt_best->rtp_nexthop;
517 nexthop = &rt->rt_nexthop;
520 /* detect 1-hop hostroute */
521 hostRoute = rt->rt_dst.prefix_len == olsr_cnf->ipsize * 8
522 && ipequal(&nexthop->gateway, &rt->rt_dst.prefix);
526 struct ipaddr_str buf1, buf2;
527 olsr_syslog(OLSR_LOG_INFO, "hostroute (%s) = %d == %d && %s == %s",
528 hostRoute ? "true" : "false",
529 rt->rt_dst.prefix_len, (int)(olsr_cnf->ipsize * 8),
530 olsr_ip_to_string(&buf1, &nexthop->gateway),
531 olsr_ip_to_string(&buf2, &rt->rt_dst.prefix));
536 if (olsr_cnf->use_src_ip_routes) {
537 src = &olsr_cnf->unicast_src_ip;
544 err = olsr_new_netlink_route(af_family, table, nexthop->iif_index, metric, olsr_cnf->rt_proto,
545 src, hostRoute ? NULL : &nexthop->gateway, &rt->rt_dst, set, false);
547 /* resolve "File exist" (17) propblems (on orig and autogen routes)*/
548 if (set && err == 17) {
549 /* a similar route going over another gateway may be present, which has to be deleted! */
550 olsr_syslog(OLSR_LOG_ERR, ". auto-deleting similar routes to resolve 'File exists' (17) while adding route!");
552 /* erase similar rule */
553 err = olsr_new_netlink_route(af_family, table, 0, 0, -1, NULL, NULL, &rt->rt_dst, false, true);
556 /* create this rule a second time if delete worked*/
557 err = olsr_new_netlink_route(af_family, table, nexthop->iif_index, metric, olsr_cnf->rt_proto,
558 src, hostRoute ? NULL : &nexthop->gateway, &rt->rt_dst, set, false);
560 olsr_syslog(OLSR_LOG_ERR, ". %s (%d)", err == 0 ? "successful" : "failed", err);
563 /* report success on "No such process" (3) */
564 else if (!set && err == 3) {
565 /* another similar (but slightly different) route may be present at this point,
566 * if so this will get solved when adding new route to this destination */
567 olsr_syslog(OLSR_LOG_ERR, ". ignoring 'No such process' (3) while deleting route!");
570 /* insert route to gateway on the fly if "Network unreachable" (128) on 2.4 kernels
571 * or on 2.6 kernel No such process (3) or Network unreachable (101) is reported in rtnetlink response
572 * do this only with flat metric, as using metric values inherited from
573 * a target behind the gateway is really strange, and could lead to multiple routes!
574 * anyways if invalid gateway ips may happen we are f*cked up!!
575 * but if not, these on the fly generated routes are no problem, and will only get used when needed */
576 else if (!hostRoute && olsr_cnf->fib_metric == FIBM_FLAT
577 && (err == 128 || err == 101 || err == 3)) {
578 struct olsr_ip_prefix hostPrefix;
581 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (128) while adding route!");
583 else if (err == 101) {
584 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (101) while adding route!");
587 olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'No such process' (3) while adding route!");
590 /* create hostroute */
591 hostPrefix.prefix = nexthop->gateway;
592 hostPrefix.prefix_len = olsr_cnf->ipsize * 8;
594 err = olsr_new_netlink_route(af_family, olsr_cnf->rt_table, nexthop->iif_index,
595 metric, olsr_cnf->rt_proto, src, NULL, &hostPrefix, true, false);
597 /* create this rule a second time if hostrule generation was successful */
598 err = olsr_new_netlink_route(af_family, table, nexthop->iif_index, metric, olsr_cnf->rt_proto,
599 src, hostRoute ? NULL : &nexthop->gateway, &rt->rt_dst, set, false);
601 olsr_syslog(OLSR_LOG_ERR, ". %s (%d)", err == 0 ? "successful" : "failed", err);
608 * Insert a route in the kernel routing table
610 * @param destination the route to add
612 * @return negative on error
615 olsr_ioctl_add_route(const struct rt_entry *rt)
617 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
618 return olsr_os_process_rt_entry(AF_INET, rt, true);
622 *Insert a route in the kernel routing table
624 *@param destination the route to add
626 *@return negative on error
629 olsr_ioctl_add_route6(const struct rt_entry *rt)
631 OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
632 return olsr_os_process_rt_entry(AF_INET6, rt, true);
636 *Remove a route from the kernel
638 *@param destination the route to remove
640 *@return negative on error
643 olsr_ioctl_del_route(const struct rt_entry *rt)
645 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
646 return olsr_os_process_rt_entry(AF_INET, rt, false);
650 *Remove a route from the kernel
652 *@param destination the route to remove
654 *@return negative on error
657 olsr_ioctl_del_route6(const struct rt_entry *rt)
659 OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
660 return olsr_os_process_rt_entry(AF_INET6, rt, false);
667 * indent-tabs-mode: nil