/**
 * Insert a route in the kernel routing table
 *
 * @param destination the route to add
 *
 * @return negative on error
 */
int
olsr_ioctl_add_route(const struct rt_entry *rt)
{
  char if_name[IFNAMSIZ];
  struct rtentry kernel_route;
  union olsr_ip_addr mask;
  int rslt;

  OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));

  memset(&kernel_route, 0, sizeof(struct rtentry));

  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET;
  ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET;
  ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET;

  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;

  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
    return -1;
  }
  ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;

  if (rt->rt_dst.prefix.v4.s_addr != rt->rt_best->rtp_nexthop.gateway.v4.s_addr) {
    ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_best->rtp_nexthop.gateway.v4;
  }

  kernel_route.rt_flags = olsr_rt_flags(rt);
  kernel_route.rt_metric = olsr_fib_metric(&rt->rt_best->rtp_metric);

  /*
   * Set interface
   */
  strcpy(if_name, if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
  kernel_route.rt_dev = if_name;

  /* delete existing default route before ? */
  if ((olsr_cnf->del_gws) && (rt->rt_dst.prefix.v4.s_addr == INADDR_ANY) && (rt->rt_dst.prefix_len == INADDR_ANY)) {
    delete_all_inet_gws();
    olsr_cnf->del_gws = false;
  }

  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {

    /*
     * Send IPC route update message
     */
    ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
                           if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
  }

  return rslt;
}
/**
 *Insert a route in the kernel routing table
 *
 *@param destination the route to add
 *
 *@return negative on error
 */
int
olsr_ioctl_add_route6(const struct rt_entry *rt)
{
  struct in6_rtmsg kernel_route;
  int rslt;

  OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));

  memset(&kernel_route, 0, sizeof(struct in6_rtmsg));

  kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6;
  kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;

  kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;

  kernel_route.rtmsg_flags = olsr_rt_flags(rt);
  kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric);

  /*
   * set interface
   */
  kernel_route.rtmsg_ifindex = rt->rt_best->rtp_nexthop.iif_index;

  /* XXX delete 0/0 route before ? */

  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {

    /*
     * Send IPC route update message
     */
    ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1,
                           if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
  }
  return rslt;
}
Ejemplo n.º 3
0
/**
 * Print the routingtree to STDOUT
 *
 */
void
olsr_print_routing_table(struct avl_tree *tree)
{
#ifndef NODEBUG
  /* The whole function makes no sense without it. */
  struct avl_node *rt_tree_node;
  struct lqtextbuffer lqbuffer;

  OLSR_PRINTF(6, "ROUTING TABLE\n");

  for (rt_tree_node = avl_walk_first(tree); rt_tree_node != NULL; rt_tree_node = avl_walk_next(rt_tree_node)) {
    struct avl_node *rtp_tree_node;
    struct ipaddr_str prefixstr, origstr, gwstr;
    struct rt_entry *rt = rt_tree2rt(rt_tree_node);

    /* first the route entry */
    OLSR_PRINTF(6, "%s/%u, via %s, best-originator %s\n", olsr_ip_to_string(&prefixstr, &rt->rt_dst.prefix), rt->rt_dst.prefix_len,
                olsr_ip_to_string(&origstr, &rt->rt_nexthop.gateway), olsr_ip_to_string(&gwstr, &rt->rt_best->rtp_originator));

    /* walk the per-originator path tree of routes */
    for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = avl_walk_next(rtp_tree_node)) {
      struct rt_path *rtp = rtp_tree2rtp(rtp_tree_node);
      OLSR_PRINTF(6, "\tfrom %s, cost %s, metric %u, via %s, %s, v %u\n", olsr_ip_to_string(&origstr, &rtp->rtp_originator),
                  get_linkcost_text(rtp->rtp_metric.cost, true, &lqbuffer), rtp->rtp_metric.hops, olsr_ip_to_string(&gwstr,
                                                                                                                    &rtp->
                                                                                                                    rtp_nexthop.
                                                                                                                    gateway),
                  if_ifwithindex_name(rt->rt_nexthop.iif_index), rtp->rtp_version);
    }
  }
#endif /* NODEBUG */
  tree = NULL;                  /* squelch compiler warnings */
}
Ejemplo n.º 4
0
int iterRouteTabNext(char *buff, int len)
{
  struct avl_node *rt_tree_node;

  if (iterRouteTab == NULL)
    return -1;

  snprintf(buff, len, "destination~%s~gateway~%s~interface~%s~metric~%d~",
           rawIpAddrToString(&iterRouteTab->rt_dst.prefix, ipAddrLen),
           rawIpAddrToString(&iterRouteTab->rt_best->rtp_nexthop.gateway, ipAddrLen),
           if_ifwithindex_name(iterRouteTab->rt_best->rtp_nexthop.iif_index),
           iterRouteTab->rt_best->rtp_metric.hops);

  rt_tree_node = avl_walk_next(&iterRouteTab->rt_tree_node);
  if (rt_tree_node) {
      iterRouteTab = rt_tree2rt(rt_tree_node);
  } else {
      iterRouteTab = NULL;
  }

  return 0;
}
/*
 * Sends an add or delete message via the routing socket.
 * The message consists of:
 *  - a header i.e. struct rt_msghdr
 *  - 0-8 socket address structures
 */
static int
add_del_route(const struct rt_entry *rt, int add)
{
  struct rt_msghdr *rtm;               /* message to send to the routing socket */
  unsigned char buff[512];
  unsigned char *walker;               /* points within the buffer */
  struct sockaddr_in sin4;             /* internet style sockaddr */
  struct sockaddr_dl *sdl;             /* link level sockaddr */
  struct ifaddrs *addrs;
  struct ifaddrs *awalker;
  const struct rt_nexthop *nexthop;
  union olsr_ip_addr mask;             /* netmask as ip address */
  int sin_size, sdl_size;              /* payload of the message */
  int len;                             /* message size written to routing socket */

  if (add) {
    OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
  } else {
    OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
  }

  memset(buff, 0, sizeof(buff));
  memset(&sin4, 0, sizeof(sin4));

  sin4.sin_len = sizeof(sin4);
  sin4.sin_family = AF_INET;

  sin_size = 1 + ((sizeof(struct sockaddr_in) - 1) | (sizeof(long) - 1));
  sdl_size = 1 + ((sizeof(struct sockaddr_dl) - 1) | (sizeof(long) - 1));

  /**********************************************************************
   *                  FILL THE ROUTING MESSAGE HEADER
   **********************************************************************/

  /* position header to the beginning of the buffer */
  rtm = (struct rt_msghdr *)buff;

  rtm->rtm_version = RTM_VERSION;
  rtm->rtm_type = add ? RTM_ADD : RTM_DELETE;
  rtm->rtm_index = 0;           /* is ignored in outgoing messages */
  rtm->rtm_flags = olsr_rt_flags(rt);
  rtm->rtm_pid = OLSR_PID;
  rtm->rtm_seq = ++seq;

  /* walk to the end of the header */
  walker = buff + sizeof(struct rt_msghdr);

  /**********************************************************************
   *                  SET  DESTINATION OF THE ROUTE
   **********************************************************************/

#ifdef _WRS_KERNEL
  /*
   * vxWorks: change proto or tos
   */
  OLSR_PRINTF(8, "\t- Setting Protocol: 0\n");
  ((struct sockaddr_rt *)(&sin4))->srt_proto = 0;
  OLSR_PRINTF(8, "\t- Setting TOS: 0\n");
  ((struct sockaddr_rt *)(&sin4))->srt_tos = 0;
#endif

  sin4.sin_addr = rt->rt_dst.prefix.v4;
  memcpy(walker, &sin4, sizeof(sin4));
  walker += sin_size;
  rtm->rtm_addrs = RTA_DST;

  /**********************************************************************
   *                  SET GATEWAY OF THE ROUTE
   **********************************************************************/

#ifdef _WRS_KERNEL
  /*
   * vxWorks: Route with no gateway is deleted
   */
  if (add) {
#endif
    nexthop = olsr_get_nh(rt);
    if (0 != (rtm->rtm_flags & RTF_GATEWAY)) {
      sin4.sin_addr = nexthop->gateway.v4;
      memcpy(walker, &sin4, sizeof(sin4));
      walker += sin_size;
      rtm->rtm_addrs |= RTA_GATEWAY;
    }
    else {
      /*
       * Host is directly reachable, so add
       * the output interface MAC address.
       */
      if (getifaddrs(&addrs)) {
        fprintf(stderr, "\ngetifaddrs() failed\n");
        return -1;
      }

      for (awalker = addrs; awalker != NULL; awalker = awalker->ifa_next)
        if (awalker->ifa_addr->sa_family == AF_LINK && strcmp(awalker->ifa_name, if_ifwithindex_name(nexthop->iif_index)) == 0)
          break;

      if (awalker == NULL) {
        fprintf(stderr, "\nInterface %s not found\n", if_ifwithindex_name(nexthop->iif_index));
        freeifaddrs(addrs);
        return -1;
      }

      /* sdl is "struct sockaddr_dl" */
      sdl = (struct sockaddr_dl *)awalker->ifa_addr;
      memcpy(walker, sdl, sdl->sdl_len);
      walker += sdl_size;
      rtm->rtm_addrs |= RTA_GATEWAY;
#ifdef RTF_CLONING
      rtm->rtm_flags |= RTF_CLONING;
#endif
#ifndef _WRS_KERNEL
      rtm->rtm_flags &= ~RTF_HOST;
#endif
      freeifaddrs(addrs);
    }
#ifdef _WRS_KERNEL
  }
#endif

  /**********************************************************************
   *                         SET  NETMASK
   **********************************************************************/

  if (0 == (rtm->rtm_flags & RTF_HOST)) {
    olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len);
    sin4.sin_addr = mask.v4;
    memcpy(walker, &sin4, sizeof(sin4));
    walker += sin_size;
    rtm->rtm_addrs |= RTA_NETMASK;
  }

  /**********************************************************************
   *           WRITE CONFIGURATION MESSAGE TO THE ROUTING SOCKET
   **********************************************************************/

  rtm->rtm_msglen = (unsigned short)(walker - buff);
  len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
  if (0 != rtm->rtm_errno || len < rtm->rtm_msglen) {
    fprintf(stderr, "\nCannot write to routing socket: (rtm_errno= 0x%x) (last error message: %s)\n",
              rtm->rtm_errno,strerror(errno));
    if (add) {
      fprintf(stderr, " Failed on Adding %s\n", olsr_rtp_to_string(rt->rt_best));
    } else {
      fprintf(stderr, " Failed on Deleting %s\n",olsr_rt_to_string(rt));
    }
  }
  return 0;
}