src/linux/kernel_routes.c
author Henning Rogge <hrogge@googlemail.com>
Fri Oct 16 17:18:44 2009 +0200 (2 years ago)
branchOLSRD_0_5_6_BRANCH
changeset 1881 438bd63a1ab8
parent 1874edfeedcc1c40
permissions -rw-r--r--
Fix segfault in "lost interface" monitor if interface goes down which is no OLSR interface
andreto@1
     1
/*
andreto@308
     2
 * The olsr.org Optimized Link-State Routing daemon(olsrd)
sven-ola@1694
     3
 * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
bernd@1216
     4
 * Copyright (c) 2007, Sven-Ola for the policy routing stuff
andreto@308
     5
 * All rights reserved.
andreto@1
     6
 *
sven-ola@1695
     7
 * Redistribution and use in source and binary forms, with or without
sven-ola@1695
     8
 * modification, are permitted provided that the following conditions
andreto@308
     9
 * are met:
andreto@1
    10
 *
sven-ola@1695
    11
 * * Redistributions of source code must retain the above copyright
andreto@308
    12
 *   notice, this list of conditions and the following disclaimer.
sven-ola@1695
    13
 * * Redistributions in binary form must reproduce the above copyright
sven-ola@1695
    14
 *   notice, this list of conditions and the following disclaimer in
sven-ola@1695
    15
 *   the documentation and/or other materials provided with the
andreto@308
    16
 *   distribution.
sven-ola@1695
    17
 * * Neither the name of olsr.org, olsrd nor the names of its
sven-ola@1695
    18
 *   contributors may be used to endorse or promote products derived
andreto@308
    19
 *   from this software without specific prior written permission.
andreto@1
    20
 *
sven-ola@1695
    21
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
sven-ola@1695
    22
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
sven-ola@1695
    23
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
sven-ola@1695
    24
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
sven-ola@1695
    25
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
sven-ola@1695
    26
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
sven-ola@1695
    27
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sven-ola@1695
    28
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
sven-ola@1695
    29
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sven-ola@1695
    30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
sven-ola@1695
    31
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
andreto@308
    32
 * POSSIBILITY OF SUCH DAMAGE.
andreto@1
    33
 *
andreto@308
    34
 * Visit http://www.olsr.org for more information.
andreto@1
    35
 *
andreto@308
    36
 * If you find this software useful feel free to make a donation
andreto@315
    37
 * to the project. For more information see the website or contact
andreto@308
    38
 * the copyright holders.
andreto@308
    39
 *
andreto@1
    40
 */
andreto@1
    41
andreto@618
    42
#include "kernel_routes.h"
bernd@1252
    43
#include "ipc_frontend.h"
markus@1763
    44
#include "log.h"
markus@1763
    45
markus@1777
    46
/* values for control flag to handle recursive route corrections 
markus@1777
    47
 *  currently only requires in linux specific kernel_routes.c */
markus@1763
    48
markus@1763
    49
#define RT_ORIG_REQUEST 0
markus@1763
    50
#define RT_RETRY_AFTER_ADD_GATEWAY 1
markus@1763
    51
#define RT_RETRY_AFTER_DELETE_SIMILAR 2
markus@1763
    52
#define RT_DELETE_SIMILAR_ROUTE 3
markus@1763
    53
#define RT_AUTO_ADD_GATEWAY_ROUTE 4
markus@1763
    54
#define RT_DELETE_SIMILAR_AUTO_ROUTE 5
andreto@1
    55
bernd@1216
    56
#if !LINUX_POLICY_ROUTING
bernd@1216
    57
sven-ola@1716
    58
static int delete_all_inet_gws(void);
bernd@1234
    59
bernd@1234
    60
#else /* !LINUX_POLICY_ROUTING */
bernd@1234
    61
bernd@1234
    62
#include <assert.h>
bernd@1235
    63
#include <linux/types.h>
bernd@1234
    64
#include <linux/rtnetlink.h>
bernd@1234
    65
Markus@1870
    66
extern struct rtnl_handle rth;
Markus@1870
    67
sven-ola@1716
    68
struct olsr_rtreq {
sven-ola@1442
    69
  struct nlmsghdr n;
sven-ola@1696
    70
  struct rtmsg r;
sven-ola@1696
    71
  char buf[512];
bernd@1234
    72
};
bernd@1234
    73
Markus@1870
    74
#if LINUX_RTNETLINK_LISTEN
Markus@1870
    75
#include "ifnet.h"
Markus@1870
    76
#include "socket_parser.h"
Markus@1870
    77
Markus@1870
    78
int rtnetlink_register_socket(int rtnl_mgrp)
Markus@1870
    79
{
Markus@1870
    80
  int sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
Markus@1870
    81
  struct sockaddr_nl addr;
Markus@1870
    82
Markus@1870
    83
  if (sock<0) {
Markus@1870
    84
    OLSR_PRINTF(1,"could not create rtnetlink socket! %d",sock);
Markus@1870
    85
  }
Markus@1870
    86
  else {
Markus@1870
    87
    addr.nl_family = AF_NETLINK;
Markus@1870
    88
    addr.nl_pid = 0; //kernel will assign appropiate number instead of pid (which is already used by primaray rtnetlink socket to add/delete routes)
Markus@1870
    89
    addr.nl_groups = rtnl_mgrp;
Markus@1870
    90
    if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0) {
Markus@1870
    91
      OLSR_PRINTF(1,"could not bind socket! (%d %s)",errno,strerror(errno));
Markus@1870
    92
    }
Markus@1870
    93
    else {
Markus@1870
    94
      add_olsr_socket(sock, &rtnetlink_read);
Markus@1870
    95
    }
Markus@1870
    96
    fcntl(sock, F_SETFL, O_NONBLOCK);
Markus@1870
    97
  }
Markus@1870
    98
  return sock;
Markus@1870
    99
}
Markus@1870
   100
Markus@1870
   101
static void netlink_process_link(struct nlmsghdr *h)
Markus@1870
   102
{
Markus@1870
   103
  struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(h);
hrogge@1881
   104
  struct interface *iface;
hrogge@1881
   105
  struct olsr_if *tmp_if;
hrogge@1881
   106
hrogge@1881
   107
  iface = if_ifwithindex(ifi->ifi_index);
hrogge@1881
   108
  if (iface == NULL) {
hrogge@1881
   109
    return;
hrogge@1881
   110
  }
Markus@1870
   111
  
Markus@1870
   112
  //all IFF flags: LOOPBACK,BROADCAST;POINTOPOINT;MULTICAST;NOARP;ALLMULTI;PROMISC;MASTER;SLAVE;DEBUG;DYNAMIC;AUTOMEDIA;PORTSEL;NOTRAILERS;UP;LOWER_UP;DORMANT
Markus@1870
   113
  /* check if interface is up and running? (a not running interface keeps its routes, so better not react like on ifdown!!??) */
Markus@1870
   114
  if (ifi->ifi_flags&IFF_UP) {
Markus@1870
   115
    OLSR_PRINTF(3,"interface %s changed but is still up! ", iface->int_name);
Markus@1870
   116
    return; //we are currently only interested in interfaces that are/go down
Markus@1870
   117
  } else {
Markus@1870
   118
    OLSR_PRINTF(1,"interface %s is down! ", iface->int_name);
Markus@1870
   119
  }
Markus@1870
   120
Markus@1870
   121
  //only for still configured interfaces (ifup has to be detected with regular interface polling)
hrogge@1881
   122
  for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) {
hrogge@1881
   123
    if (tmp_if->interf==iface) {
hrogge@1881
   124
      OLSR_PRINTF(1,"-> removing %s from olsr config! ", iface->int_name);
hrogge@1881
   125
      RemoveInterface(tmp_if,true);
hrogge@1881
   126
      break;
Markus@1870
   127
    }
Markus@1870
   128
  }
Markus@1870
   129
}
Markus@1870
   130
Markus@1870
   131
Markus@1870
   132
void rtnetlink_read(int sock)
Markus@1870
   133
{
Markus@1870
   134
  int len, plen;
Markus@1870
   135
  struct iovec iov;
Markus@1870
   136
  struct sockaddr_nl nladdr;
Markus@1870
   137
  struct msghdr msg = {
Markus@1870
   138
    &nladdr,
Markus@1870
   139
    sizeof(nladdr),
Markus@1870
   140
    &iov,
Markus@1870
   141
    1,
Markus@1870
   142
    NULL,
Markus@1870
   143
    0,
Markus@1870
   144
    0
Markus@1870
   145
  };
Markus@1870
   146
Markus@1870
   147
  char buffer[4096];
Markus@1870
   148
  struct nlmsghdr *nlh = (struct nlmsghdr *)(ARM_NOWARN_ALIGN) buffer;
Markus@1870
   149
  int ret;
Markus@1870
   150
Markus@1870
   151
  iov.iov_base = (void *) buffer;
Markus@1870
   152
  iov.iov_len = sizeof(buffer);
Markus@1870
   153
Markus@1870
   154
  while (true) { //read until ret<0;
Markus@1870
   155
    ret=recvmsg(sock, &msg, 0);
Markus@1870
   156
    if (ret<0) {
Markus@1870
   157
      if (errno != EAGAIN) OLSR_PRINTF(1,"\nnetlink listen error %u - %s",errno,strerror(errno));
Markus@1870
   158
      return;
Markus@1870
   159
    }
Markus@1870
   160
    /*check message*/
Markus@1870
   161
    len = nlh->nlmsg_len;
Markus@1870
   162
    plen = len - sizeof(nlh);
Markus@1870
   163
    if (len > ret || plen < 0) {
Markus@1870
   164
      OLSR_PRINTF(1,"Malformed netlink message: "
Markus@1870
   165
             "len=%d left=%d plen=%d",
Markus@1870
   166
              len, ret, plen);
Markus@1870
   167
      return;
Markus@1870
   168
    }
Markus@1870
   169
    if ( (nlh->nlmsg_type == RTM_NEWLINK) || ( nlh->nlmsg_type == RTM_DELLINK) ) netlink_process_link(nlh);
Markus@1870
   170
  }
Markus@1870
   171
}
Markus@1870
   172
Markus@1870
   173
#endif /*linux_rtnetlink_listen*/
Markus@1870
   174
sven-ola@1696
   175
static void
sven-ola@1716
   176
olsr_netlink_addreq(struct olsr_rtreq *req, int type, const void *data, int len)
bernd@1234
   177
{
sven-ola@1854
   178
  struct rtattr *rta = (struct rtattr *)(ARM_NOWARN_ALIGN)(((char *)req) + NLMSG_ALIGN(req->n.nlmsg_len));
sven-ola@1716
   179
  req->n.nlmsg_len = NLMSG_ALIGN(req->n.nlmsg_len) + RTA_LENGTH(len);
sven-ola@1716
   180
  assert(req->n.nlmsg_len < sizeof(struct olsr_rtreq));
sven-ola@1442
   181
  rta->rta_type = type;
sven-ola@1716
   182
  rta->rta_len = RTA_LENGTH(len);
sven-ola@1716
   183
  memcpy(RTA_DATA(rta), data, len);
bernd@1234
   184
}
bernd@1234
   185
markus@1763
   186
/* returns
markus@1777
   187
 * -1 on unrecoverable error (calling function will have to handle it)
markus@1777
   188
 *  0 on unexpected but recoverable rtnetlink behaviour
markus@1777
   189
 *    but some of the implemented recovery methods only cure symptoms, 
markus@1777
   190
 *    not the cause, like unintelligent ordering of inserted routes.
markus@1777
   191
 *  1 on success */
sven-ola@1696
   192
static int
markus@1763
   193
olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd, uint8_t flag)
bernd@1234
   194
{
markus@1777
   195
  int ret = 1; /* helper variable for rtnetlink_message processing */
markus@1777
   196
  int rt_ret = -2;  /* if no response from rtnetlink it must be considered as failed! */
sven-ola@1442
   197
  struct olsr_rtreq req;
sven-ola@1442
   198
  struct iovec iov;
sven-ola@1442
   199
  struct sockaddr_nl nladdr;
sven-ola@1696
   200
  struct msghdr msg = {
sven-ola@1442
   201
    &nladdr,
sven-ola@1716
   202
    sizeof(nladdr),
sven-ola@1442
   203
    &iov,
sven-ola@1442
   204
    1,
sven-ola@1442
   205
    NULL,
sven-ola@1442
   206
    0,
sven-ola@1442
   207
    0
sven-ola@1442
   208
  };
Markus@1838
   209
Markus@1838
   210
  uint32_t metric = 0;
hrogge@1839
   211
  const struct rt_nexthop *nexthop = NULL;
Markus@1840
   212
  if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE ) ) {
Markus@1859
   213
    if (FIBM_FLAT == olsr_cnf->fib_metric) {
hrogge@1839
   214
      metric = RT_METRIC_DEFAULT;
hrogge@1839
   215
    }
hrogge@1839
   216
    else {
hrogge@1839
   217
      metric = (RTM_NEWROUTE == cmd) ? rt->rt_best->rtp_metric.hops : rt->rt_metric.hops;
hrogge@1839
   218
    }
Markus@1838
   219
hrogge@1839
   220
    if (( RTM_NEWROUTE == cmd ) ||
hrogge@1839
   221
        (( RTM_DELROUTE == cmd ) && ( RT_DELETE_SIMILAR_ROUTE == flag || RT_DELETE_SIMILAR_AUTO_ROUTE == flag ))) {
Markus@1838
   222
      nexthop = &rt->rt_best->rtp_nexthop;
hrogge@1839
   223
    }
hrogge@1839
   224
    else {
hrogge@1839
   225
      nexthop = &rt->rt_nexthop;
hrogge@1839
   226
    }
Markus@1838
   227
  }
Markus@1838
   228
markus@1777
   229
  memset(&req, 0, sizeof(req));
bernd@1234
   230
sven-ola@1716
   231
  req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
sven-ola@1696
   232
  req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
sven-ola@1442
   233
  req.n.nlmsg_type = cmd;
sven-ola@1442
   234
  req.r.rtm_family = family;
sven-ola@1442
   235
  req.r.rtm_table = rttable;
hrogge@1839
   236
markus@1777
   237
  /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
hrogge@1839
   238
  /* -> olsr only adds deletes unicast routes */
hrogge@1839
   239
  req.r.rtm_type = RTN_UNICAST;
hrogge@1839
   240
hrogge@1839
   241
  /* wildcard to delete routes of all protos if no simlar-delete correct proto will get set below */
hrogge@1839
   242
  req.r.rtm_protocol = RTPROT_UNSPEC;
hrogge@1839
   243
hrogge@1839
   244
  /* as wildcard for deletion */
hrogge@1839
   245
  req.r.rtm_scope = RT_SCOPE_NOWHERE;
bernd@1234
   246
Markus@1840
   247
  if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE ) ) {
Markus@1764
   248
    req.r.rtm_dst_len = rt->rt_dst.prefix_len;
markus@1763
   249
markus@1777
   250
    /* do not specify much as we wanna delete similar/conflicting routes */
Markus@1828
   251
    if ( ( flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE )) {
markus@1786
   252
      /* 0 gets replaced by OS-specifc default (3)
markus@1786
   253
       * 1 is reserved so we take 0 instead (this really makes some sense)
markus@1786
   254
       * other numbers are used 1:1 */
markus@1777
   255
      req.r.rtm_protocol = ( (olsr_cnf->rtproto<1) ? RTPROT_BOOT : ( (olsr_cnf->rtproto==1) ? 0 : olsr_cnf->rtproto) );
Markus@1764
   256
      req.r.rtm_scope = RT_SCOPE_LINK;
markus@1777
   257
Markus@1764
   258
      /*add interface*/
Markus@1764
   259
      olsr_netlink_addreq(&req, RTA_OIF, &nexthop->iif_index, sizeof(nexthop->iif_index));
markus@1774
   260
hrogge@1839
   261
#if SOURCE_IP_ROUTES
markus@1777
   262
      /* source ip here is based on now static olsr_cnf->main_addr in this olsr-0.5.6-r4, should be based on orignator-id in newer olsrds */
hrogge@1839
   263
      if (AF_INET == family) {
hrogge@1839
   264
        olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v4.s_addr, sizeof(olsr_cnf->main_addr.v4.s_addr));
hrogge@1839
   265
      }
hrogge@1839
   266
      else {
hrogge@1839
   267
        olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v6.s6_addr, sizeof(olsr_cnf->main_addr.v6.s6_addr));
hrogge@1839
   268
      }
hrogge@1839
   269
#endif
Markus@1764
   270
    }
Markus@1764
   271
markus@1777
   272
    /* metric is specified always as we can only delete one route per iteration, and wanna hit the correct one first */
markus@1763
   273
    if (FIBM_APPROX != olsr_cnf->fib_metric || (RTM_NEWROUTE == cmd) ) {
markus@1763
   274
      olsr_netlink_addreq(&req, RTA_PRIORITY, &metric, sizeof(metric));
markus@1763
   275
    }
markus@1763
   276
markus@1777
   277
    /* make sure that netmask = /32 as this is an autogenarated route */
hrogge@1839
   278
    if (( flag == RT_AUTO_ADD_GATEWAY_ROUTE ) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) {
hrogge@1839
   279
      req.r.rtm_dst_len = 32;
hrogge@1839
   280
    }
markus@1763
   281
Markus@1764
   282
    /* for ipv4 or ipv6 we add gateway if one is specified, 
Markus@1764
   283
    * or leave gateway away if we want to delete similar routes aswell, 
markus@1777
   284
    * or even use the gateway as target if we add a auto-generated route, 
markus@1777
   285
    * or if delete-similar to make insertion of auto-generated route possible */
Markus@1764
   286
    if (AF_INET == family) {
Markus@1828
   287
      if ( ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE) && 
Markus@1828
   288
           ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE) && (rt->rt_dst.prefix.v4.s_addr != nexthop->gateway.v4.s_addr) ) {
Markus@1764
   289
        olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v4, sizeof(nexthop->gateway.v4));
Markus@1764
   290
        req.r.rtm_scope = RT_SCOPE_UNIVERSE;
Markus@1764
   291
      }
Markus@1828
   292
      olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ? 
Markus@1764
   293
                          &nexthop->gateway.v4 : &rt->rt_dst.prefix.v4, sizeof(rt->rt_dst.prefix.v4));
Markus@1764
   294
    } else {
Markus@1828
   295
      if ( ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE) 
Markus@1828
   296
          && (0 != memcmp(&rt->rt_dst.prefix.v6, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6))) ) {
Markus@1764
   297
        olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6));
Markus@1764
   298
        req.r.rtm_scope = RT_SCOPE_UNIVERSE;
Markus@1764
   299
      }
Markus@1828
   300
      olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ? 
markus@1777
   301
                          &nexthop->gateway.v6 : &rt->rt_dst.prefix.v6, sizeof(rt->rt_dst.prefix.v6));
sven-ola@1442
   302
    }
hrogge@1839
   303
  } else {
hrogge@1839
   304
    /* add or delete a rule */
Markus@1764
   305
    static uint32_t priority = 65535;
hrogge@1839
   306
Markus@1764
   307
    req.r.rtm_scope = RT_SCOPE_UNIVERSE;
Markus@1764
   308
    olsr_netlink_addreq(&req, RTA_PRIORITY, &priority, sizeof(priority));
sven-ola@1716
   309
  }
markus@1763
   310
sven-ola@1442
   311
  iov.iov_base = &req.n;
sven-ola@1442
   312
  iov.iov_len = req.n.nlmsg_len;
sven-ola@1716
   313
  memset(&nladdr, 0, sizeof(nladdr));
sven-ola@1442
   314
  nladdr.nl_family = AF_NETLINK;
sven-ola@1716
   315
  if (0 <= (ret = sendmsg(olsr_cnf->rtnl_s, &msg, 0))) {
sven-ola@1716
   316
    iov.iov_base = req.buf;
sven-ola@1716
   317
    iov.iov_len = sizeof(req.buf);
sven-ola@1716
   318
    if (0 < (ret = recvmsg(olsr_cnf->rtnl_s, &msg, 0))) {
sven-ola@1854
   319
      struct nlmsghdr *h = (struct nlmsghdr *)(ARM_NOWARN_ALIGN)req.buf;
sven-ola@1716
   320
      while (NLMSG_OK(h, (unsigned int)ret)) {
markus@1763
   321
        if (NLMSG_DONE == h->nlmsg_type) {
hrogge@1839
   322
          /* seems to reached never */
markus@1763
   323
          olsr_syslog(OLSR_LOG_INFO, "_received NLMSG_DONE");
sven-ola@1716
   324
          break;
markus@1763
   325
        }
sven-ola@1716
   326
        if (NLMSG_ERROR == h->nlmsg_type) {
sven-ola@1716
   327
          if (NLMSG_LENGTH(sizeof(struct nlmsgerr) <= h->nlmsg_len)) {
markus@1763
   328
            struct ipaddr_str ibuf;
markus@1763
   329
            struct ipaddr_str gbuf;
sven-ola@1716
   330
            struct nlmsgerr *l_err = (struct nlmsgerr *)NLMSG_DATA(h);
sven-ola@1716
   331
            errno = -l_err->error;
markus@1777
   332
            if (0 != errno) {
hrogge@1839
   333
              const char *const err_msg = strerror(errno);
markus@1763
   334
              struct ipaddr_str buf;
markus@1763
   335
              rt_ret = -1;
hrogge@1839
   336
markus@1777
   337
              /* syslog debug output for various situations */
Markus@1764
   338
              if ( cmd == RTM_NEWRULE ) {
Markus@1767
   339
                olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on inserting empty policy rule aimed to activate RtTable %u!", err_msg, errno, rttable);
Markus@1764
   340
              }
Markus@1764
   341
              else if ( cmd == RTM_DELRULE ) {
Markus@1767
   342
                olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on deleting empty policy rule aimed to activate rtTable %u!", err_msg, errno, rttable);
Markus@1764
   343
              }
Markus@1768
   344
              else if ( flag <= RT_RETRY_AFTER_DELETE_SIMILAR ) {
hrogge@1839
   345
                if (rt->rt_dst.prefix.v4.s_addr!=nexthop->gateway.v4.s_addr) {
hrogge@1839
   346
                  olsr_syslog(OLSR_LOG_ERR, "error '%s' (%d) %s route to %s/%d via %s dev %s",
hrogge@1839
   347
                      err_msg, errno, (cmd == RTM_NEWROUTE) ? "add" : "del",
hrogge@1839
   348
                      olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), req.r.rtm_dst_len,
hrogge@1839
   349
                      olsr_ip_to_string(&gbuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
hrogge@1839
   350
                }
hrogge@1839
   351
                else {
hrogge@1839
   352
                  olsr_syslog(OLSR_LOG_ERR, "error '%s' (%d) %s route to %s/%d dev %s",
hrogge@1839
   353
                      err_msg, errno, (cmd == RTM_NEWROUTE) ? "add" : "del",
hrogge@1839
   354
                      olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), req.r.rtm_dst_len, if_ifwithindex_name(nexthop->iif_index));
hrogge@1839
   355
                }
Markus@1768
   356
              }
hrogge@1839
   357
              else if (flag == RT_AUTO_ADD_GATEWAY_ROUTE) {
hrogge@1839
   358
                olsr_syslog(OLSR_LOG_ERR, ". error '%s' (%d) auto-add route to %s dev %s", err_msg, errno,
hrogge@1839
   359
                    olsr_ip_to_string(&ibuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
hrogge@1839
   360
              }
hrogge@1839
   361
              else if (flag == RT_DELETE_SIMILAR_ROUTE) {
hrogge@1839
   362
                olsr_syslog(OLSR_LOG_ERR, ". error '%s' (%d) auto-delete route to %s dev %s", err_msg, errno,
hrogge@1839
   363
                    olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix), if_ifwithindex_name(nexthop->iif_index));
hrogge@1839
   364
              }
hrogge@1839
   365
              else if (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) {
hrogge@1839
   366
                olsr_syslog(OLSR_LOG_ERR, ". . error '%s' (%d) auto-delete similar route to %s dev %s", err_msg, errno,
hrogge@1839
   367
                    olsr_ip_to_string(&ibuf,&nexthop->gateway), if_ifwithindex_name(nexthop->iif_index));
hrogge@1839
   368
              }
hrogge@1839
   369
              else {
hrogge@1839
   370
                /* should never happen */
Markus@1768
   371
                olsr_syslog(OLSR_LOG_ERR, "# invalid internal route delete/add flag (%d) used!", flag);
markus@1763
   372
              }
markus@1763
   373
            }
hrogge@1839
   374
            else {
hrogge@1839
   375
              /* netlink acks requests with an errno=0 NLMSG_ERROR response! */
markus@1763
   376
              rt_ret = 1;
markus@1763
   377
            }
markus@1763
   378
markus@1763
   379
            /* resolve "File exist" (17) propblems (on orig and autogen routes)*/	
hrogge@1839
   380
            if ((errno == 17) && (cmd == RTM_NEWROUTE) && ((flag == RT_ORIG_REQUEST) || (flag == RT_AUTO_ADD_GATEWAY_ROUTE))) {
markus@1777
   381
              /* a similar route going over another gateway may be present, which has to be deleted! */
Markus@1767
   382
              olsr_syslog(OLSR_LOG_ERR, ". auto-deleting similar routes to resolve 'File exists' (17) while adding route!");
markus@1777
   383
              rt_ret = RT_DELETE_SIMILAR_ROUTE; /* processing will contiune after this loop */
markus@1763
   384
            }
markus@1763
   385
            /* report success on "No such process" (3) */
Markus@1828
   386
            else if ((errno == 3) && (cmd == RTM_DELROUTE) && (flag == RT_ORIG_REQUEST)) {
markus@1777
   387
              /* another similar (but slightly different) route may be present at this point
markus@1777
   388
              * , if so this will get solved when adding new route to this destination */
Markus@1767
   389
              olsr_syslog(OLSR_LOG_ERR, ". ignoring 'No such process' (3) while deleting route!");
markus@1763
   390
              rt_ret = 0;
markus@1763
   391
            }
Markus@1767
   392
            /* insert route to gateway on the fly if "Network unreachable" (128) on 2.4 kernels
Markus@1836
   393
             * or on 2.6 kernel No such process (3) or Network unreachable (101) is reported in rtnetlink response
markus@1763
   394
             * do this only with flat metric, as using metric values inherited from 
markus@1763
   395
             * a target behind the gateway is really strange, and could lead to multiple routes!
Markus@1767
   396
             * anyways if invalid gateway ips may happen we are f*cked up!!
markus@1777
   397
             * but if not, these on the fly generated routes are no problem, and will only get used when needed */
hrogge@1839
   398
            else if ( ( (errno == 3) || (errno == 101) || (errno == 128) )
hrogge@1839
   399
                && (flag == RT_ORIG_REQUEST) && (FIBM_FLAT == olsr_cnf->fib_metric)
Markus@1828
   400
                     && (cmd == RTM_NEWROUTE) && (rt->rt_dst.prefix.v4.s_addr!=nexthop->gateway.v4.s_addr)) {
hrogge@1839
   401
              if (errno == 128)  {
hrogge@1839
   402
                olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (128) while adding route!");
hrogge@1839
   403
              }
hrogge@1839
   404
              else if (errno == 101) {
hrogge@1839
   405
                olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'Network unreachable' (101) while adding route!");
hrogge@1839
   406
              }
hrogge@1839
   407
              else {
hrogge@1839
   408
                olsr_syslog(OLSR_LOG_ERR, ". autogenerating route to handle 'No such process' (3) while adding route!");
hrogge@1839
   409
              }
markus@1777
   410
hrogge@1839
   411
              /* processing will contiune after this loop */
hrogge@1839
   412
              rt_ret = RT_AUTO_ADD_GATEWAY_ROUTE;
markus@1763
   413
            }
sven-ola@1716
   414
          }
markus@1777
   415
          /* report invalid message size */
hrogge@1839
   416
          else {
hrogge@1839
   417
            olsr_syslog(OLSR_LOG_INFO,"_received invalid netlink message size %lu != %u",
hrogge@1839
   418
                (unsigned long int)sizeof(struct nlmsgerr), h->nlmsg_len);
hrogge@1839
   419
          }
sven-ola@1442
   420
        }
markus@1777
   421
        /* log all other messages */
hrogge@1839
   422
        else {
hrogge@1839
   423
          olsr_syslog(OLSR_LOG_INFO,"_received %u Byte rtnetlink response of type %u with seqnr %u and flags %u from %u (%u)",
hrogge@1839
   424
              h->nlmsg_len, h->nlmsg_type, h->nlmsg_seq, h->nlmsg_flags, h->nlmsg_pid, NLMSG_ERROR);
hrogge@1839
   425
        }
sven-ola@1854
   426
/*
sven-ola@1854
   427
 * The ARM compile complains about alignment. Copied
sven-ola@1854
   428
 * from /usr/include/linux/netlink.h and adapted for ARM
sven-ola@1854
   429
 */
sven-ola@1854
   430
#define MY_NLMSG_NEXT(nlh,len)	 ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
sven-ola@1854
   431
				  (struct nlmsghdr*)(ARM_NOWARN_ALIGN)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
sven-ola@1854
   432
        h = MY_NLMSG_NEXT(h, ret);
sven-ola@1716
   433
      }
sven-ola@1442
   434
    }
markus@1763
   435
  }
hrogge@1839
   436
  if ( rt_ret == RT_DELETE_SIMILAR_ROUTE ) {
hrogge@1839
   437
    /* delete all routes that may collide */
hrogge@1839
   438
markus@1763
   439
    /* recursive call to delete simlar routes, using flag 2 to invoke deletion of similar, not only exact matches*/
markus@1777
   440
    rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_DELROUTE, 
hrogge@1839
   441
        flag == RT_AUTO_ADD_GATEWAY_ROUTE ? RT_DELETE_SIMILAR_AUTO_ROUTE : RT_DELETE_SIMILAR_ROUTE);
markus@1777
   442
markus@1777
   443
    /* retry insert original route, if deleting similar succeeded, using flag=1 to prevent recursions */
hrogge@1839
   444
    if (rt_ret > 0) {
hrogge@1839
   445
      rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_RETRY_AFTER_DELETE_SIMILAR);
hrogge@1839
   446
    }
hrogge@1839
   447
    else {
hrogge@1839
   448
      olsr_syslog(OLSR_LOG_ERR, ". failed on auto-deleting similar route conflicting with above route!");
hrogge@1839
   449
    }
markus@1763
   450
markus@1777
   451
    /* set appropriate return code for original request, while returning simple -1/1 if called recursive */
markus@1763
   452
    if (flag != RT_AUTO_ADD_GATEWAY_ROUTE) {
hrogge@1839
   453
      if (rt_ret > 0) {
hrogge@1839
   454
        /* successful recovery */
hrogge@1839
   455
        rt_ret = 0;
hrogge@1839
   456
      }
hrogge@1839
   457
      else {
hrogge@1839
   458
        /* unrecoverable error */
hrogge@1839
   459
        rt_ret = -1;
hrogge@1839
   460
      }
sven-ola@1716
   461
    }
sven-ola@1716
   462
  }
hrogge@1839
   463
  if ( rt_ret == RT_AUTO_ADD_GATEWAY_ROUTE ) {
hrogge@1839
   464
    /* autoadd route via gateway */
hrogge@1839
   465
markus@1777
   466
    /* recursive call to invoke creation of a route to the gateway */
markus@1763
   467
    rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_AUTO_ADD_GATEWAY_ROUTE);
markus@1777
   468
markus@1777
   469
    /* retry insert original route, if above succeeded without problems */
hrogge@1839
   470
    if (rt_ret > 0) {
hrogge@1839
   471
      rt_ret = olsr_netlink_route_int(rt, family, rttable, RTM_NEWROUTE, RT_RETRY_AFTER_ADD_GATEWAY);
hrogge@1839
   472
    }
hrogge@1839
   473
    else {
hrogge@1839
   474
      olsr_syslog(OLSR_LOG_ERR, ". failed on inserting auto-generated route to gateway of above route!");
hrogge@1839
   475
    }
markus@1763
   476
markus@1763
   477
    /* set appropriate return code for original request*/
hrogge@1839
   478
    if (rt_ret > 0) {
hrogge@1839
   479
      /* successful recovery */
hrogge@1839
   480
      rt_ret = 0;
hrogge@1839
   481
    }
hrogge@1839
   482
    else {
hrogge@1839
   483
      /* unrecoverable error */
hrogge@1839
   484
      rt_ret = -1;
hrogge@1839
   485
    }
markus@1763
   486
  }
hrogge@1839
   487
  /* send ipc update on success */
hrogge@1839
   488
  if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE )
hrogge@1839
   489
      && (flag = RT_ORIG_REQUEST) && (0 <= rt_ret && olsr_cnf->ipc_connections > 0) ) {
hrogge@1839
   490
    ipc_route_send_rtentry(&rt->rt_dst.prefix, &nexthop->gateway, metric,
hrogge@1839
   491
        RTM_NEWROUTE == cmd, if_ifwithindex_name(nexthop->iif_index));
markus@1763
   492
  }
hrogge@1839
   493
  if (rt_ret == -2) {
hrogge@1839
   494
    olsr_syslog(OLSR_LOG_ERR,"no rtnetlink response! (no system ressources left?, everything may happen now ...)");
hrogge@1839
   495
  }
markus@1763
   496
  return rt_ret;
bernd@1234
   497
}
markus@1763
   498
hrogge@1839
   499
/* external wrapper function for above patched multi purpose rtnetlink function */
Markus@1764
   500
int
Markus@1764
   501
olsr_netlink_rule(uint8_t family, uint8_t rttable, uint16_t cmd)
Markus@1764
   502
{
Markus@1840
   503
  return olsr_netlink_route_int(NULL, family, rttable, cmd, RT_ORIG_REQUEST);
Markus@1764
   504
}
Markus@1764
   505
hrogge@1839
   506
/* internal wrapper function for above patched function */
markus@1763
   507
static int
markus@1763
   508
olsr_netlink_route(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd)
markus@1763
   509
{
markus@1763
   510
  return olsr_netlink_route_int(rt, family, rttable, cmd, RT_ORIG_REQUEST);
markus@1763
   511
}
markus@1763
   512
bernd@1234
   513
#endif /* LINUX_POLICY_ROUTING */
andreto@541
   514
bernd@1198
   515
/**
bernd@1198
   516
 * Insert a route in the kernel routing table
bernd@1198
   517
 *
bernd@1198
   518
 * @param destination the route to add
bernd@1198
   519
 *
bernd@1198
   520
 * @return negative on error
bernd@1198
   521
 */
bernd@1198
   522
int
sven-ola@1716
   523
olsr_ioctl_add_route(const struct rt_entry *rt)
bernd@1198
   524
{
bernd@1234
   525
#if !LINUX_POLICY_ROUTING
bernd@1198
   526
  struct rtentry kernel_route;
bernd@1198
   527
  union olsr_ip_addr mask;
bernd@1198
   528
  int rslt;
bernd@1234
   529
#endif /* LINUX_POLICY_ROUTING */
andreto@541
   530
sven-ola@1716
   531
  OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
bernd@1198
   532
bernd@1234
   533
#if !LINUX_POLICY_ROUTING
sven-ola@1716
   534
  memset(&kernel_route, 0, sizeof(struct rtentry));
bernd@1198
   535
sven-ola@1716
   536
  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
sven-ola@1716
   537
  ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
sven-ola@1716
   538
  ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
bernd@1198
   539
sven-ola@1716
   540
  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
bernd@1198
   541
sven-ola@1716
   542
  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
sven-ola@1716
   543
    return -1;
sven-ola@1716
   544
  }
sven-ola@1716
   545
  ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
bernd@1198
   546
sven-ola@1716
   547
  if (rt->rt_dst.prefix.v4.s_addr != rt->rt_best->rtp_nexthop.gateway.v4.s_addr) {
sven-ola@1716
   548
    ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_best->rtp_nexthop.gateway.v4;
sven-ola@1716
   549
  }
bernd@1198
   550
sven-ola@1716
   551
  kernel_route.rt_flags = olsr_rt_flags(rt);
sven-ola@1716
   552
  kernel_route.rt_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
bernd@1198
   553
bernd@1198
   554
  /*
bernd@1198
   555
   * Set interface
bernd@1198
   556
   */
sven-ola@1716
   557
  kernel_route.rt_dev = if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index);
bernd@1198
   558
bernd@1198
   559
  /* delete existing default route before ? */
sven-ola@1718
   560
  if ((olsr_cnf->del_gws) && (rt->rt_dst.prefix.v4.s_addr == INADDR_ANY) && (rt->rt_dst.prefix_len == INADDR_ANY)) {
sven-ola@1716
   561
    delete_all_inet_gws();
sven-ola@1737
   562
    olsr_cnf->del_gws = false;
sven-ola@1716
   563
  }
bernd@1198
   564
sven-ola@1716
   565
  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
bernd@1198
   566
sven-ola@1716
   567
    /*
sven-ola@1716
   568
     * Send IPC route update message
sven-ola@1716
   569
     */
sven-ola@1717
   570
    ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
sven-ola@1717
   571
                           if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
sven-ola@1716
   572
  }
bernd@1198
   573
bernd@1198
   574
  return rslt;
bernd@1234
   575
#else /* !LINUX_POLICY_ROUTING */
sven-ola@1716
   576
  if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable) {
sven-ola@1716
   577
    /*
sven-ola@1716
   578
     * Users start whining about not having internet with policy
sven-ola@1716
   579
     * routing activated and no static default route in table 254.
sven-ola@1716
   580
     * We maintain a fallback defroute in the default=253 table.
sven-ola@1716
   581
     */
sven-ola@1716
   582
    olsr_netlink_route(rt, AF_INET, 253, RTM_NEWROUTE);
sven-ola@1716
   583
  }
hrogge@1839
   584
  if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
sven-ola@1716
   585
    return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_NEWROUTE);
hrogge@1839
   586
  }
hrogge@1839
   587
  else {
sven-ola@1716
   588
    return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_NEWROUTE);
hrogge@1839
   589
  }
bernd@1234
   590
#endif /* LINUX_POLICY_ROUTING */
bernd@1198
   591
}
bernd@1198
   592
andreto@1
   593
/**
andreto@1
   594
 *Insert a route in the kernel routing table
andreto@1
   595
 *
andreto@1
   596
 *@param destination the route to add
andreto@1
   597
 *
andreto@1
   598
 *@return negative on error
andreto@1
   599
 */
andreto@1
   600
int
sven-ola@1716
   601
olsr_ioctl_add_route6(const struct rt_entry *rt)
andreto@1
   602
{
bernd@1234
   603
#if !LINUX_POLICY_ROUTING
andreto@1
   604
  struct in6_rtmsg kernel_route;
bernd@1198
   605
  int rslt;
andreto@1
   606
sven-ola@1716
   607
  OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
andreto@1
   608
sven-ola@1716
   609
  memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
andreto@1
   610
sven-ola@1696
   611
  kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6;
bernd@1198
   612
  kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
andreto@1
   613
bernd@1308
   614
  kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
bernd@1198
   615
sven-ola@1716
   616
  kernel_route.rtmsg_flags = olsr_rt_flags(rt);
sven-ola@1716
   617
  kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
sven-ola@1695
   618
bernd@1198
   619
  /*
bernd@1198
   620
   * set interface
bernd@1198
   621
   */
bernd@1199
   622
  kernel_route.rtmsg_ifindex = rt->rt_best->rtp_nexthop.iif_index;
sven-ola@1695
   623
bernd@1198
   624
  /* XXX delete 0/0 route before ? */
andreto@1
   625
sven-ola@1716
   626
  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
andreto@1
   627
sven-ola@1716
   628
    /*
sven-ola@1716
   629
     * Send IPC route update message
sven-ola@1716
   630
     */
sven-ola@1717
   631
    ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
sven-ola@1717
   632
                           if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
sven-ola@1716
   633
  }
bernd@1198
   634
  return rslt;
bernd@1234
   635
#else /* !LINUX_POLICY_ROUTING */
hrogge@1839
   636
  if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
sven-ola@1716
   637
    return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_NEWROUTE);
hrogge@1839
   638
  }
hrogge@1839
   639
  else {
sven-ola@1716
   640
    return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_NEWROUTE);
hrogge@1839
   641
  }
bernd@1234
   642
#endif /* LINUX_POLICY_ROUTING */
andreto@1
   643
}
andreto@1
   644
andreto@1
   645
/**
andreto@1
   646
 *Remove a route from the kernel
andreto@1
   647
 *
andreto@1
   648
 *@param destination the route to remove
andreto@1
   649
 *
andreto@1
   650
 *@return negative on error
andreto@1
   651
 */
andreto@1
   652
int
sven-ola@1716
   653
olsr_ioctl_del_route(const struct rt_entry *rt)
andreto@1
   654
{
bernd@1234
   655
#if !LINUX_POLICY_ROUTING
andreto@1
   656
  struct rtentry kernel_route;
bernd@1198
   657
  union olsr_ip_addr mask;
bernd@1198
   658
  int rslt;
bernd@1234
   659
#endif /* LINUX_POLICY_ROUTING */
andreto@1
   660
sven-ola@1716
   661
  OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
bernd@1198
   662
bernd@1234
   663
#if !LINUX_POLICY_ROUTING
sven-ola@1716
   664
  memset(&kernel_route, 0, sizeof(struct rtentry));
andreto@1
   665
sven-ola@1716
   666
  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
sven-ola@1716
   667
  ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
sven-ola@1716
   668
  ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
andreto@1
   669
sven-ola@1716
   670
  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
andreto@1
   671
sven-ola@1716
   672
  if (rt->rt_dst.prefix.v4.s_addr != rt->rt_nexthop.gateway.v4.s_addr) {
sven-ola@1716
   673
    ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_nexthop.gateway.v4;
sven-ola@1716
   674
  }
andreto@1
   675
sven-ola@1716
   676
  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
sven-ola@1716
   677
    return -1;
sven-ola@1716
   678
  } else {
sven-ola@1716
   679
    ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
sven-ola@1716
   680
  }
bernd@1198
   681
sven-ola@1716
   682
  kernel_route.rt_flags = olsr_rt_flags(rt);
sven-ola@1716
   683
  kernel_route.rt_metric = olsr_fib_metric(&rt->rt_metric.hops);
bernd@1198
   684
bernd@1198
   685
  /*
bernd@1198
   686
   * Set interface
bernd@1198
   687
   */
andreto@1
   688
  kernel_route.rt_dev = NULL;
andreto@1
   689
sven-ola@1716
   690
  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route)) >= 0) {
andreto@1
   691
sven-ola@1716
   692
    /*
sven-ola@1716
   693
     * Send IPC route update message
sven-ola@1716
   694
     */
sven-ola@1716
   695
    ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
sven-ola@1716
   696
  }
andreto@1
   697
bernd@1198
   698
  return rslt;
bernd@1234
   699
#else /* !LINUX_POLICY_ROUTING */
sven-ola@1716
   700
  if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable) {
sven-ola@1716
   701
    /*
sven-ola@1716
   702
     * Also remove the fallback default route
sven-ola@1716
   703
     */
sven-ola@1716
   704
    olsr_netlink_route(rt, AF_INET, 253, RTM_DELROUTE);
sven-ola@1716
   705
  }
hrogge@1839
   706
  if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
sven-ola@1716
   707
    return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_DELROUTE);
hrogge@1839
   708
  }
hrogge@1839
   709
  else {
sven-ola@1716
   710
    return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_DELROUTE);
hrogge@1839
   711
  }
bernd@1234
   712
#endif /* LINUX_POLICY_ROUTING */
andreto@1
   713
}
andreto@1
   714
andreto@1
   715
/**
andreto@1
   716
 *Remove a route from the kernel
andreto@1
   717
 *
andreto@1
   718
 *@param destination the route to remove
andreto@1
   719
 *
andreto@1
   720
 *@return negative on error
andreto@1
   721
 */
andreto@1
   722
int
sven-ola@1716
   723
olsr_ioctl_del_route6(const struct rt_entry *rt)
andreto@1
   724
{
bernd@1234
   725
#if !LINUX_POLICY_ROUTING
andreto@1
   726
  struct in6_rtmsg kernel_route;
bernd@1198
   727
  int rslt;
bernd@1234
   728
#endif /* LINUX_POLICY_ROUTING */
andreto@1
   729
sven-ola@1716
   730
  OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
andreto@1
   731
bernd@1234
   732
#if !LINUX_POLICY_ROUTING
sven-ola@1716
   733
  memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
andreto@1
   734
sven-ola@1696
   735
  kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6;
bernd@1198
   736
  kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
andreto@1
   737
bernd@1308
   738
  kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
andreto@1
   739
sven-ola@1716
   740
  kernel_route.rtmsg_flags = olsr_rt_flags(rt);
sven-ola@1716
   741
  kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
andreto@94
   742
sven-ola@1716
   743
  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route) >= 0)) {
andreto@1
   744
sven-ola@1716
   745
    /*
sven-ola@1716
   746
     * Send IPC route update message
sven-ola@1716
   747
     */
sven-ola@1716
   748
    ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
sven-ola@1716
   749
  }
andreto@1
   750
bernd@1198
   751
  return rslt;
bernd@1234
   752
#else /* !LINUX_POLICY_ROUTING */
hrogge@1839
   753
  if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0) {
sven-ola@1716
   754
    return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_DELROUTE);
hrogge@1839
   755
  }
hrogge@1839
   756
  else {
sven-ola@1716
   757
    return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_DELROUTE);
hrogge@1839
   758
  }
bernd@1234
   759
#endif /* LINUX_POLICY_ROUTING */
andreto@1
   760
}
andreto@1
   761
bernd@1234
   762
#if !LINUX_POLICY_ROUTING
sven-ola@1696
   763
static int
sven-ola@1716
   764
delete_all_inet_gws(void)
sven-ola@1695
   765
{
andreto@1
   766
  int s;
andreto@1
   767
  char buf[BUFSIZ], *cp, *cplim;
andreto@1
   768
  struct ifconf ifc;
andreto@1
   769
  struct ifreq *ifr;
sven-ola@1695
   770
sven-ola@1716
   771
  OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n");
sven-ola@1695
   772
andreto@1
   773
  /* Get a socket */
sven-ola@1716
   774
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
sven-ola@1716
   775
    olsr_syslog(OLSR_LOG_ERR, "socket: %m");
sven-ola@1716
   776
    return -1;
sven-ola@1716
   777
  }
sven-ola@1695
   778
sven-ola@1716
   779
  ifc.ifc_len = sizeof(buf);
andreto@1
   780
  ifc.ifc_buf = buf;
sven-ola@1716
   781
  if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
sven-ola@1716
   782
    olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");
sven-ola@1716
   783
    close(s);
sven-ola@1716
   784
    return -1;
sven-ola@1716
   785
  }
andreto@1
   786
andreto@1
   787
  ifr = ifc.ifc_req;
sven-ola@1696
   788
  cplim = buf + ifc.ifc_len;    /*skip over if's with big ifr_addr's */
sven-ola@1716
   789
  for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) {
sven-ola@1716
   790
    struct rtentry kernel_route;
sven-ola@1716
   791
    ifr = (struct ifreq *)cp;
sven-ola@1695
   792
sven-ola@1716
   793
    if (strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0) {
sven-ola@1716
   794
      OLSR_PRINTF(1, "Skipping loopback...\n");
sven-ola@1716
   795
      continue;
sven-ola@1716
   796
    }
sven-ola@1695
   797
sven-ola@1716
   798
    OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name);
andreto@1
   799
sven-ola@1716
   800
    memset(&kernel_route, 0, sizeof(struct rtentry));
sven-ola@1695
   801
sven-ola@1716
   802
    ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;
sven-ola@1716
   803
    ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
sven-ola@1716
   804
    ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;
sven-ola@1716
   805
    ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;
sven-ola@1695
   806
sven-ola@1716
   807
    ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
sven-ola@1716
   808
    ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
bernd@1198
   809
sven-ola@1716
   810
    kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
sven-ola@1695
   811
sven-ola@1716
   812
    kernel_route.rt_dev = ifr->ifr_ifrn.ifrn_name;
andreto@1
   813
sven-ola@1716
   814
    if ((ioctl(s, SIOCDELRT, &kernel_route)) < 0)
sven-ola@1716
   815
      OLSR_PRINTF(1, "NO\n");
sven-ola@1716
   816
    else
sven-ola@1716
   817
      OLSR_PRINTF(1, "YES\n");
sven-ola@1716
   818
  }
sven-ola@1716
   819
  close(s);
sven-ola@1695
   820
  return 0;
andreto@1
   821
}
bernd@1216
   822
#endif /* LINUX_POLICY_ROUTING */
bernd@1216
   823
bernd@1198
   824
/*
bernd@1198
   825
 * Local Variables:
bernd@1198
   826
 * c-basic-offset: 2
bernd@1704
   827
 * indent-tabs-mode: nil
bernd@1198
   828
 * End:
bernd@1198
   829
 */