Logo Search packages:      
Sourcecode: batmand version File versions

route.c

/*
 * Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
 *
 * Marek Lindner
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 *
 */



#define _GNU_SOURCE
#include <sys/ioctl.h>
#include <arpa/inet.h>    /* inet_ntop() */
#include <errno.h>
#include <unistd.h>       /* close() */
#include <linux/if.h>     /* ifr_if, ifr_tun */
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>

#include "../os.h"
#include "../batman.h"


static const char *route_type_to_string[] = {
      [ROUTE_TYPE_UNICAST]      = "route",
       [ROUTE_TYPE_UNREACHABLE] = "unreachable route",
       [ROUTE_TYPE_THROW]       = "throw route",
};

static const char *route_type_to_string_script[] = {
      [ROUTE_TYPE_UNICAST]     = "UNICAST",
      [ROUTE_TYPE_UNREACHABLE] = "UNREACH",
      [ROUTE_TYPE_THROW]       = "THROW",
};

static const char *rule_type_to_string[] = {
      [RULE_TYPE_SRC] = "from",
      [RULE_TYPE_DST] = "to",
      [RULE_TYPE_IIF] = "iif",
};

static const char *rule_type_to_string_script[] = {
      [RULE_TYPE_SRC] = "SRC",
      [RULE_TYPE_DST] = "DST",
      [RULE_TYPE_IIF] = "IIF",
};



/***
 *
 * route types: 0 = RTN_UNICAST, 1 = THROW, 2 = UNREACHABLE
 *
 ***/

void add_del_route(uint32_t dest, uint8_t netmask, uint32_t router, uint32_t src_ip, int32_t ifi, char *dev, uint8_t rt_table, int8_t route_type, int8_t route_action)
{
      int netlink_sock;
      size_t len;
      uint32_t my_router;
      char buf[4096], str1[16], str2[16], str3[16];
      struct rtattr *rta;
      struct sockaddr_nl nladdr;
      struct iovec iov;
      struct msghdr msg;
      struct nlmsghdr *nh;
      struct {
            struct nlmsghdr nlh;
            struct rtmsg rtm;
            char buff[4 * (sizeof(struct rtattr) + 4)];
      } req;

      iov.iov_base = buf;
      iov.iov_len  = sizeof(buf);

      inet_ntop(AF_INET, &dest, str1, sizeof(str1));
      inet_ntop(AF_INET, &router, str2, sizeof(str2));
      inet_ntop(AF_INET, &src_ip, str3, sizeof(str3));

      if (policy_routing_script != NULL) {
            dprintf(policy_routing_pipe, "ROUTE %s %s %s %i %s %s %i %s %i\n", (route_action == ROUTE_DEL ? "del" : "add"), route_type_to_string_script[route_type], str1, netmask, str2, str3, ifi, dev, rt_table);
            return;
      }

      /* adding default route */
      if ((router == dest) && (dest == 0)) {

            if (route_type != ROUTE_TYPE_UNREACHABLE) {
                  debug_output(3, "%s default route via %s (table %i)\n", (route_action == ROUTE_DEL ? "Deleting" : "Adding"), dev, rt_table);
                  debug_output(4, "%s default route via %s (table %i)\n", (route_action == ROUTE_DEL ? "Deleting" : "Adding"), dev, rt_table);
            }

            my_router = router;

      /* single hop neigbor */
      } else if ((router == dest) && (dest != 0)) {

            debug_output(3, "%s route to %s via 0.0.0.0 (table %i - %s)\n", (route_action == ROUTE_DEL ? "Deleting" : "Adding"), str1, rt_table, dev);
            debug_output(4, "%s route to %s via 0.0.0.0 (table %i - %s)\n", (route_action == ROUTE_DEL ? "Deleting" : "Adding"), str1, rt_table, dev);
            my_router = 0;

      /* multihop neighbor */
      } else {

            debug_output(3, "%s %s to %s/%i via %s (table %i - %s)\n", (route_action == ROUTE_DEL ? "Deleting" : "Adding"), route_type_to_string[route_type], str1, netmask, str2, rt_table, dev);
            debug_output(4, "%s %s to %s/%i via %s (table %i - %s)\n", (route_action == ROUTE_DEL ? "Deleting" : "Adding"), route_type_to_string[route_type], str1, netmask, str2, rt_table, dev);
            my_router = router;

      }


      memset(&nladdr, 0, sizeof(struct sockaddr_nl));
      memset(&req, 0, sizeof(req));
      memset(&msg, 0, sizeof(struct msghdr));

      nladdr.nl_family = AF_NETLINK;

      len = sizeof(struct rtmsg) + sizeof(struct rtattr) + 4;

      /* additional information for the outgoing interface and the gateway */
      if (route_type == ROUTE_TYPE_UNICAST)
            len += 2 * (sizeof(struct rtattr) + 4);

      if (src_ip != 0)
            len += sizeof(struct rtattr) + 4;

      req.nlh.nlmsg_len = NLMSG_LENGTH(len);
      req.nlh.nlmsg_pid = getpid();
      req.rtm.rtm_family = AF_INET;
      req.rtm.rtm_table = rt_table;
      req.rtm.rtm_dst_len = netmask;

      if (route_action == ROUTE_DEL) {

            req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
            req.nlh.nlmsg_type = RTM_DELROUTE;
            req.rtm.rtm_scope = RT_SCOPE_NOWHERE;

      } else {

            req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_APPEND;
            req.nlh.nlmsg_type = RTM_NEWROUTE;

            if (route_type == ROUTE_TYPE_UNICAST && my_router == 0 && src_ip != 0)
                  req.rtm.rtm_scope = RT_SCOPE_LINK;
            else
                  req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;

            req.rtm.rtm_protocol = RTPROT_STATIC; /* may be changed to some batman specific value - see <linux/rtnetlink.h> */

            switch(route_type) {
            case ROUTE_TYPE_UNICAST:
                  req.rtm.rtm_type = RTN_UNICAST;
                  break;
            case ROUTE_TYPE_THROW:
                  req.rtm.rtm_type = RTN_THROW;
                  break;
            case ROUTE_TYPE_UNREACHABLE:
                  req.rtm.rtm_type = RTN_UNREACHABLE;
                  break;
            default:
                  debug_output(0, "Error - unknown route type (add_del_route): %i\n", route_type);
                  return;
            }
      }

      rta = (struct rtattr *)req.buff;
      rta->rta_type = RTA_DST;
      rta->rta_len = sizeof(struct rtattr) + 4;
      memcpy(((char *)&req.buff) + sizeof(struct rtattr), (char *)&dest, 4);

      if (route_type == ROUTE_TYPE_UNICAST) {

            rta = (struct rtattr *)(req.buff + sizeof(struct rtattr) + 4);
            rta->rta_type = RTA_GATEWAY;
            rta->rta_len = sizeof(struct rtattr) + 4;
            memcpy(((char *)&req.buff) + 2 * sizeof(struct rtattr) + 4, (char *)&my_router, 4);

            rta = (struct rtattr *)(req.buff + 2 * sizeof(struct rtattr) + 8);
            rta->rta_type = RTA_OIF;
            rta->rta_len = sizeof(struct rtattr) + 4;
            memcpy(((char *)&req.buff) + 3 * sizeof(struct rtattr) + 8, (char *)&ifi, 4);

            if (src_ip != 0) {
                  rta = (struct rtattr *)(req.buff + 3 * sizeof(struct rtattr) + 12);
                  rta->rta_type = RTA_PREFSRC;
                  rta->rta_len = sizeof(struct rtattr) + 4;
                  memcpy(((char *)&req.buff) + 4 * sizeof(struct rtattr) + 12, (char *)&src_ip, 4);
            }

      }

      if ((netlink_sock = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {

            debug_output(0, "Error - can't create netlink socket for routing table manipulation: %s\n", strerror(errno));
            return;

      }

      if (sendto(netlink_sock, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl)) < 0) {

            debug_output(0, "Error - can't send message to kernel via netlink socket for routing table manipulation: %s\n", strerror(errno));
            close(netlink_sock);
            return;

      }


      msg.msg_name = (void *)&nladdr;
      msg.msg_namelen = sizeof(nladdr);
      msg.msg_iov = &iov;
      msg.msg_iovlen = 1;
      msg.msg_control = NULL;

      len = recvmsg( netlink_sock, &msg, 0 );
      nh = (struct nlmsghdr *)buf;

      while (NLMSG_OK(nh, len)) {

            if (nh->nlmsg_type == NLMSG_DONE)
                  break;

            if (( nh->nlmsg_type == NLMSG_ERROR) && (((struct nlmsgerr*)NLMSG_DATA(nh))->error != 0))
                  debug_output(0, "Error - can't %s %s to %s/%i via %s (table %i): %s\n", (route_action == ROUTE_DEL ? "delete" : "add"), route_type_to_string[route_type], str1, netmask, str2, rt_table, strerror(-((struct nlmsgerr*)NLMSG_DATA(nh))->error));

            nh = NLMSG_NEXT(nh, len);

      }

      close(netlink_sock);
}

/***
 *
 * rule types: 0 = RTA_SRC, 1 = RTA_DST, 2 = RTA_IIF
 *
 ***/

void add_del_rule(uint32_t network, uint8_t netmask, int8_t rt_table, uint32_t prio, char *iif, int8_t rule_type, int8_t rule_action)
{
      int netlink_sock;
      size_t len;
      char buf[4096], str1[16];
      struct rtattr *rta;
      struct sockaddr_nl nladdr;
      struct iovec iov;
      struct msghdr msg;
      struct nlmsghdr *nh;
      struct {
            struct nlmsghdr nlh;
            struct rtmsg rtm;
            char buff[2 * (sizeof(struct rtattr) + 4)];
      } req;

      iov.iov_base = buf;
      iov.iov_len  = sizeof(buf);


      inet_ntop(AF_INET, &network, str1, sizeof (str1));

      if (policy_routing_script != NULL) {
            dprintf(policy_routing_pipe, "RULE %s %s %s %i %s %s %u %s %i\n", (rule_action == RULE_DEL ? "del" : "add"), rule_type_to_string[rule_type], str1, netmask, "unused", "unused", prio, iif, rt_table);
            return;
      }


      memset(&nladdr, 0, sizeof(struct sockaddr_nl));
      memset(&req, 0, sizeof(req));
      memset(&msg, 0, sizeof(struct msghdr));

      nladdr.nl_family = AF_NETLINK;

      len = sizeof(struct rtmsg) + sizeof(struct rtattr) + 4;

      if (prio != 0)
            len += sizeof(struct rtattr) + 4;

      req.nlh.nlmsg_len = NLMSG_LENGTH(len);
      req.nlh.nlmsg_pid = getpid();
      req.rtm.rtm_family = AF_INET;
      req.rtm.rtm_table = rt_table;


      if (rule_action == RULE_DEL) {

            req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
            req.nlh.nlmsg_type = RTM_DELRULE;
            req.rtm.rtm_scope = RT_SCOPE_NOWHERE;

      } else {

            req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
            req.nlh.nlmsg_type = RTM_NEWRULE;
            req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
            req.rtm.rtm_protocol = RTPROT_STATIC;
            req.rtm.rtm_type = RTN_UNICAST;

      }

      switch(rule_type) {
      case RULE_TYPE_SRC:
            rta = (struct rtattr *)req.buff;
            rta->rta_type = RTA_SRC;
            req.rtm.rtm_src_len = netmask;
            rta->rta_len = sizeof(struct rtattr) + 4;
            memcpy(((char *)&req.buff) + sizeof(struct rtattr), (char *)&network, 4);
            break;
      case RULE_TYPE_DST:
            rta = (struct rtattr *)req.buff;
            rta->rta_type = RTA_DST;
            req.rtm.rtm_dst_len = netmask;
            rta->rta_len = sizeof(struct rtattr) + 4;
            memcpy(((char *)&req.buff) + sizeof(struct rtattr), (char *)&network, 4);
            break;
      case RULE_TYPE_IIF:
            rta = (struct rtattr *)req.buff;
            rta->rta_len = sizeof(struct rtattr) + 4;

            if (rule_action == RULE_DEL) {
                  rta->rta_type = RTA_SRC;
                  memcpy(((char *)&req.buff) + sizeof(struct rtattr), (char *)&network, 4);
            } else {
                  rta->rta_type = RTA_IIF;
                  memcpy(((char *)&req.buff) + sizeof(struct rtattr), iif, 4);
            }
            break;
      default:
            debug_output(0, "Error - unknown rule type (add_del_rule): %i\n", rule_type);
            return;
      }

      if (prio != 0) {
            rta = (struct rtattr *)(req.buff + sizeof(struct rtattr) + 4);
            rta->rta_type = RTA_PRIORITY;
            rta->rta_len = sizeof(struct rtattr) + 4;
            memcpy(((char *)&req.buff) + 2 * sizeof(struct rtattr) + 4, (char *)&prio, 4);
      }


      if ((netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {

            debug_output(0, "Error - can't create netlink socket for routing rule manipulation: %s\n", strerror(errno));
            return;

      }


      if (sendto(netlink_sock, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl)) < 0)  {

            debug_output( 0, "Error - can't send message to kernel via netlink socket for routing rule manipulation: %s\n", strerror(errno));
            close(netlink_sock);
            return;

      }


      msg.msg_name = (void *)&nladdr;
      msg.msg_namelen = sizeof(nladdr);
      msg.msg_iov = &iov;
      msg.msg_iovlen = 1;
      msg.msg_control = NULL;

      len = recvmsg(netlink_sock, &msg, 0);
      nh = (struct nlmsghdr *)buf;

      while (NLMSG_OK(nh, len)) {

            if (nh->nlmsg_type == NLMSG_DONE)
                  break;

            if ((nh->nlmsg_type == NLMSG_ERROR) && (((struct nlmsgerr*)NLMSG_DATA(nh))->error != 0)) {

                  inet_ntop(AF_INET, &network, str1, sizeof (str1));

                  debug_output(0, "Error - can't %s rule %s %s/%i: %s\n", (rule_action == RULE_DEL ? "delete" : "add"), rule_type_to_string_script[rule_type], str1, netmask, strerror(-((struct nlmsgerr*)NLMSG_DATA(nh))->error));

            }

            nh = NLMSG_NEXT(nh, len);

      }

      close(netlink_sock);
}

int add_del_interface_rules(int8_t rule_action)
{
      int32_t tmp_fd;
      uint32_t addr, netaddr;
      int len;
      uint8_t netmask, if_count = 1;
      char *buf, *buf_ptr;
      struct ifconf ifc;
      struct ifreq *ifr, ifr_tmp;
      struct batman_if *batman_if;


      tmp_fd = socket(AF_INET, SOCK_DGRAM, 0);

      if (tmp_fd < 0) {
            debug_output(0, "Error - can't %s interface rules (udp socket): %s\n", (rule_action == RULE_DEL ? "delete" : "add"), strerror(errno));
            return -1;
      }


      len = 10 * sizeof(struct ifreq); /* initial buffer size guess (10 interfaces) */

      while (1) {

            buf = debugMalloc(len, 601);
            ifc.ifc_len = len;
            ifc.ifc_buf = buf;

            if (ioctl(tmp_fd, SIOCGIFCONF, &ifc) < 0) {

                  debug_output(0, "Error - can't %s interface rules (SIOCGIFCONF): %s\n", (rule_action == RULE_DEL ? "delete" : "add"), strerror(errno));
                  close(tmp_fd);
                  debugFree(buf, 1606);
                  return -1;

            } else {

                  if (ifc.ifc_len < len)
                        break;

            }

            len += 10 * sizeof(struct ifreq);
            debugFree(buf, 1601);

      }

      for (buf_ptr = buf; buf_ptr < buf + ifc.ifc_len;) {

            ifr = (struct ifreq *)buf_ptr;
            buf_ptr += (ifr->ifr_addr.sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr)) + sizeof(ifr->ifr_name);

            /* ignore if not IPv4 interface */
            if (ifr->ifr_addr.sa_family != AF_INET)
                  continue;

            /* the tunnel thread will remove the default route by itself */
            if (strncmp(ifr->ifr_name, "gate", 4) == 0)
                  continue;

            memset(&ifr_tmp, 0, sizeof (struct ifreq));
            strncpy(ifr_tmp.ifr_name, ifr->ifr_name, IFNAMSIZ - 1);

            if (ioctl(tmp_fd, SIOCGIFFLAGS, &ifr_tmp ) < 0) {

                  debug_output(0, "Error - can't get flags of interface %s (interface rules): %s\n", ifr->ifr_name, strerror(errno));
                  continue;

            }

            /* ignore if not up and running */
            if (!( ifr_tmp.ifr_flags & IFF_UP) || !(ifr_tmp.ifr_flags & IFF_RUNNING))
                  continue;


            if (ioctl(tmp_fd, SIOCGIFADDR, &ifr_tmp) < 0) {

                  debug_output(0, "Error - can't get IP address of interface %s (interface rules): %s\n", ifr->ifr_name, strerror(errno));
                  continue;

            }

            addr = ((struct sockaddr_in *)&ifr_tmp.ifr_addr)->sin_addr.s_addr;

            if (ioctl(tmp_fd, SIOCGIFNETMASK, &ifr_tmp) < 0) {

                  debug_output(0, "Error - can't get netmask address of interface %s (interface rules): %s\n", ifr->ifr_name, strerror(errno));
                  continue;

            }

            netaddr = (((struct sockaddr_in *)&ifr_tmp.ifr_addr)->sin_addr.s_addr & addr);
            netmask = bit_count(((struct sockaddr_in *)&ifr_tmp.ifr_addr)->sin_addr.s_addr);

            add_del_route(netaddr, netmask, 0, 0, 0, ifr->ifr_name, BATMAN_RT_TABLE_TUNNEL, ROUTE_TYPE_THROW, rule_action);

            if (is_batman_if(ifr->ifr_name, &batman_if))
                  continue;

            add_del_rule(netaddr, netmask, BATMAN_RT_TABLE_TUNNEL, (rule_action == RULE_DEL ? 0 : BATMAN_RT_PRIO_TUNNEL + if_count), 0, RULE_TYPE_SRC, rule_action);

            if (strncmp( ifr->ifr_name, "lo", IFNAMSIZ - 1) == 0)
                  add_del_rule(0, 0, BATMAN_RT_TABLE_TUNNEL, BATMAN_RT_PRIO_TUNNEL, "lo\0 ", RULE_TYPE_IIF, rule_action);

            if_count++;

      }

      close(tmp_fd);
      debugFree(buf, 1605);

      return 1;
}

int flush_routes_rules(int8_t is_rule)
{
      int netlink_sock, rtl;
      size_t len;
      int32_t dest = 0, router = 0, ifi = 0;
      uint32_t prio = 0;
      int8_t rule_type = 0;
      char buf[8192], *dev = NULL;
      struct sockaddr_nl nladdr;
      struct iovec iov;
      struct msghdr msg;
      struct nlmsghdr *nh;
      struct rtmsg *rtm;
      struct {
            struct nlmsghdr nlh;
            struct rtmsg rtm;
      } req;
      struct rtattr *rtap;

      iov.iov_base = buf;
      iov.iov_len  = sizeof(buf);


      memset(&nladdr, 0, sizeof(struct sockaddr_nl));
      memset(&req, 0, sizeof(req));
      memset(&msg, 0, sizeof(struct msghdr));

      nladdr.nl_family = AF_NETLINK;

      req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(req));
      req.nlh.nlmsg_pid = getpid();
      req.rtm.rtm_family = AF_INET;

      req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
      req.nlh.nlmsg_type = (is_rule ? RTM_GETRULE : RTM_GETROUTE);
      req.rtm.rtm_scope = RTN_UNICAST;

      if ((netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {

            debug_output(0, "Error - can't create netlink socket for flushing the routing table: %s\n", strerror(errno));
            return -1;

      }


      if (sendto(netlink_sock, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl)) < 0) {

            debug_output(0, "Error - can't send message to kernel via netlink socket for flushing the routing table: %s\n", strerror(errno));
            close(netlink_sock);
            return -1;

      }

      msg.msg_name = (void *)&nladdr;
      msg.msg_namelen = sizeof(nladdr);
      msg.msg_iov = &iov;
      msg.msg_iovlen = 1;
      msg.msg_control = NULL;

      len = recvmsg(netlink_sock, &msg, 0);
      nh = (struct nlmsghdr *)buf;

      while (NLMSG_OK(nh, len)) {

            if (nh->nlmsg_type == NLMSG_DONE)
                  break;

            if ((nh->nlmsg_type == NLMSG_ERROR) && (((struct nlmsgerr*)NLMSG_DATA(nh))->error != 0)) {

                  debug_output(0, "Error - can't flush %s: %s \n", (is_rule ? "routing rules" : "routing table"), strerror(-((struct nlmsgerr*)NLMSG_DATA(nh))->error));
                  close(netlink_sock);
                  return -1;

            }

            rtm = (struct rtmsg *)NLMSG_DATA(nh);
            rtap = (struct rtattr *)RTM_RTA(rtm);
            rtl = RTM_PAYLOAD(nh);

            nh = NLMSG_NEXT(nh, len);

            if ((rtm->rtm_table != BATMAN_RT_TABLE_UNREACH) && (rtm->rtm_table != BATMAN_RT_TABLE_NETWORKS) &&
                  (rtm->rtm_table != BATMAN_RT_TABLE_HOSTS) && (rtm->rtm_table != BATMAN_RT_TABLE_TUNNEL))
                  continue;

            while (RTA_OK(rtap, rtl)) {

                  switch(rtap->rta_type) {

                        case RTA_DST:
                              dest = *((int32_t *)RTA_DATA(rtap));
                              rule_type = 1;
                              break;

                        case RTA_SRC:
                              dest = *((int32_t *)RTA_DATA(rtap));
                              rule_type = 0;
                              break;

                        case RTA_GATEWAY:
                              router = *((int32_t *)RTA_DATA(rtap));
                              break;

                        case RTA_OIF:
                              ifi = *((int32_t *)RTA_DATA(rtap));
                              break;

                        case RTA_PRIORITY:
                              prio = *((uint32_t *)RTA_DATA(rtap));
                              break;

                        case RTA_IIF:
                              dev = ((char *)RTA_DATA(rtap));
                              rule_type = 2;
                              break;

                        case 15:  /* FIXME: RTA_TABLE is not always available - not needed but avoid warning */
                              break;

                        case RTA_PREFSRC:  /* rta_type 7 - not needed but avoid warning */
                              break;

                        default:
                              debug_output(0, "Error - unknown rta type: %i \n", rtap->rta_type);
                              break;

                  }

                  rtap = RTA_NEXT(rtap,rtl);

            }

            if (is_rule) {
                  switch (rule_type) {
                  case ROUTE_TYPE_UNICAST:
                        add_del_rule(dest, rtm->rtm_src_len, rtm->rtm_table, prio, 0 , rule_type, RULE_DEL);
                        break;
                  case ROUTE_TYPE_THROW:
                        add_del_rule(dest, rtm->rtm_dst_len, rtm->rtm_table, prio, 0 , rule_type, RULE_DEL);
                        break;
                  case ROUTE_TYPE_UNREACHABLE:
                        add_del_rule(0 , 0, rtm->rtm_table, prio, dev , rule_type, RULE_DEL);
                        break;
                  }
            } else
                  add_del_route(dest, rtm->rtm_dst_len, router, 0, ifi, "unknown", rtm->rtm_table, rtm->rtm_type, ROUTE_DEL);

      }

      close(netlink_sock);
      return 1;
}


Generated by  Doxygen 1.6.0   Back to index