예제 #1
0
/*
 * XXX: ip6_route is too eager to return single/default netif, and
 * forwarding logic is different from the logic to select outgoing
 * interface for our own packets anyway.
 */
static struct netif *
ip6_route_fwd(struct ip6_addr *dest)
{
  struct netif *netif;
  s8_t i;

  /* Link-local addresses are not routable. */
  if (ip6_addr_islinklocal(dest)) {
    return NULL;
  }

  /* See if the destination subnet matches a configured address. */
  for(netif = netif_list; netif != NULL; netif = netif->next) {
    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
          ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
        return netif;
      }
    }
  }

  /* Get the netif for a suitable router. */
  i = nd6_select_router(dest, NULL);
  if (i >= 0) {
    if (default_router_list[i].neighbor_entry != NULL) {
      if (default_router_list[i].neighbor_entry->netif != NULL) {
        return default_router_list[i].neighbor_entry->netif;
      }
    }
  }

  /* no matching netif found */
  return NULL;
}
예제 #2
0
파일: ip6.c 프로젝트: ORCOS/ORCOS
struct netif *
ip6_route(struct ip6_addr *dest) {
    struct netif *netif;

    for (netif = netif_list; netif != NULL; netif = netif->next) {
        if (ip6_addr_netcmp(dest, &(netif->ip6_addr), &(netif->ip6_netmask))) {
            return netif;
        }
    }

    return netif_default;
}
/**
 * Finds the appropriate network interface for a given IPv6 address. It tries to select
 * a netif following a sequence of heuristics:
 * 1) if there is only 1 netif, return it
 * 2) if the destination is a link-local address, try to match the src address to a netif.
 *    this is a tricky case because with multiple netifs, link-local addresses only have
 *    meaning within a particular subnet/link.
 * 3) tries to match the destination subnet to a configured address
 * 4) tries to find a router
 * 5) tries to match the source address to the netif
 * 6) returns the default netif, if configured
 *
 * @param src the source IPv6 address, if known
 * @param dest the destination IPv6 address for which to find the route
 * @return the netif on which to send to reach dest
 */
struct netif *
ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
{
  struct netif *netif;
  s8_t i;

#ifdef LWIP_HOOK_IP6_ROUTE
  netif = LWIP_HOOK_IP6_ROUTE(src, dest);
  if (netif != NULL) {
    return netif;
  }
#endif

  /* If single netif configuration, fast return. */
  if ((netif_list != NULL) && (netif_list->next == NULL)) {
    if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) {
      return NULL;
    }
    return netif_list;
  }

  /* Special processing for link-local addresses. */
  if (ip6_addr_islinklocal(dest)) {
    if (ip6_addr_isany(src)) {
      /* Use default netif, if Up. */
      if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
        return NULL;
      }
      return netif_default;
    }

    /* Try to find the netif for the source address, checking that link is up. */
    for (netif = netif_list; netif != NULL; netif = netif->next) {
      if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
        continue;
      }
      for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
        if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
            ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
          return netif;
        }
      }
    }

    /* netif not found, use default netif, if up */
    if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
      return NULL;
    }
    return netif_default;
  }

  /* See if the destination subnet matches a configured address. */
  for (netif = netif_list; netif != NULL; netif = netif->next) {
    if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
      continue;
    }
    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
          ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
        return netif;
      }
    }
  }

  /* Get the netif for a suitable router. */
  i = nd6_select_router(dest, NULL);
  if (i >= 0) {
    if (default_router_list[i].neighbor_entry != NULL) {
      if (default_router_list[i].neighbor_entry->netif != NULL) {
        if (netif_is_up(default_router_list[i].neighbor_entry->netif) && netif_is_link_up(default_router_list[i].neighbor_entry->netif)) {
          return default_router_list[i].neighbor_entry->netif;
        }
      }
    }
  }

  /* try with the netif that matches the source address. */
  if (!ip6_addr_isany(src)) {
    for (netif = netif_list; netif != NULL; netif = netif->next) {
      if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
        continue;
      }
      for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
        if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
            ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
          return netif;
        }
      }
    }
  }

#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
  /* loopif is disabled, loopback traffic is passed through any netif */
  if (ip6_addr_isloopback(dest)) {
    /* don't check for link on loopback traffic */
    if (netif_is_up(netif_default)) {
      return netif_default;
    }
    /* default netif is not up, just use any netif for loopback traffic */
    for (netif = netif_list; netif != NULL; netif = netif->next) {
      if (netif_is_up(netif)) {
        return netif;
      }
    }
    return NULL;
  }
#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */

  /* no matching netif found, use default netif, if up */
  if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
    return NULL;
  }
  return netif_default;
}
/**
 * Select the best IPv6 source address for a given destination
 * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior
 * is assumed.
 *
 * @param netif the netif on which to send a packet
 * @param dest the destination we are trying to reach
 * @return the most suitable source address to use, or NULL if no suitable
 *         source address is found
 */
const ip_addr_t *
ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest)
{
  const ip_addr_t *src = NULL;
  u8_t i;

  /* If dest is link-local, choose a link-local source. */
  if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) {
    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
          ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
        return netif_ip_addr6(netif, i);
      }
    }
  }

  /* Choose a site-local with matching prefix. */
  if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) {
    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
          ip6_addr_issitelocal(netif_ip6_addr(netif, i)) &&
          ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
        return netif_ip_addr6(netif, i);
      }
    }
  }

  /* Choose a unique-local with matching prefix. */
  if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) {
    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
          ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) &&
          ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
        return netif_ip_addr6(netif, i);
      }
    }
  }

  /* Choose a global with best matching prefix. */
  if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) {
    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
          ip6_addr_isglobal(netif_ip6_addr(netif, i))) {
        if (src == NULL) {
          src = netif_ip_addr6(netif, i);
        }
        else {
          /* Replace src only if we find a prefix match. */
          /* TODO find longest matching prefix. */
          if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) &&
              ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) {
            src = netif_ip_addr6(netif, i);
          }
        }
      }
    }
    if (src != NULL) {
      return src;
    }
  }

  /* Last resort: see if arbitrary prefix matches. */
  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
    if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
        ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
      return netif_ip_addr6(netif, i);
    }
  }

  return NULL;
}
예제 #5
0
파일: ip6.c 프로젝트: TonyaBaSy/fiasco-l4re
/**
 * Finds the appropriate network interface for a given IPv6 address. It tries to select
 * a netif following a sequence of heuristics:
 * 1) if there is only 1 netif, return it
 * 2) if the destination is a link-local address, try to match the src address to a netif.
 *    this is a tricky case because with multiple netifs, link-local addresses only have
 *    meaning within a particular subnet/link.
 * 3) tries to match the destination subnet to a configured address
 * 4) tries to find a router
 * 5) tries to match the source address to the netif
 * 6) returns the default netif, if configured
 *
 * @param src the source IPv6 address, if known
 * @param dest the destination IPv6 address for which to find the route
 * @return the netif on which to send to reach dest
 */
struct netif *
ip6_route(struct ip6_addr *src, struct ip6_addr *dest)
{
    struct netif *netif;
    s8_t i;

    /* If single netif configuration, fast return. */
    if ((netif_list != NULL) && (netif_list->next == NULL)) {
        return netif_list;
    }

    /* Special processing for link-local addresses. */
    if (ip6_addr_islinklocal(dest)) {
        if (ip6_addr_isany(src)) {
            /* Use default netif. */
            return netif_default;
        }

        /* Try to find the netif for the source address. */
        for(netif = netif_list; netif != NULL; netif = netif->next) {
            for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
                if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
                        ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
                    return netif;
                }
            }
        }

        /* netif not found, use default netif */
        return netif_default;
    }

    /* See if the destination subnet matches a configured address. */
    for(netif = netif_list; netif != NULL; netif = netif->next) {
        for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
            if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
                    ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
                return netif;
            }
        }
    }

    /* Get the netif for a suitable router. */
    i = nd6_select_router(dest, NULL);
    if (i >= 0) {
        if (default_router_list[i].neighbor_entry != NULL) {
            if (default_router_list[i].neighbor_entry->netif != NULL) {
                return default_router_list[i].neighbor_entry->netif;
            }
        }
    }

    /* try with the netif that matches the source address. */
    if (!ip6_addr_isany(src)) {
        for(netif = netif_list; netif != NULL; netif = netif->next) {
            for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
                if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
                        ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
                    return netif;
                }
            }
        }
    }

    /* no matching netif found, use default netif */
    return netif_default;
}