/**
 * 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;
}
Ejemplo n.º 2
0
/*********************************************************************************************************
** 函数名称: __netIfShow
** 功能描述: 显示指定的网络接口信息 (ip v4)
** 输 入  : pcIfName      网络接口名
**           netifShow     网络接口结构
** 输 出  : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
static VOID  __netIfShow (CPCHAR  pcIfName, const struct netif  *netifShow)
{
    struct netif    *netif;
    CHAR             cSpeed[32];
    ip_addr_t        ipaddrBroadcast;
    INT              i;

    if ((pcIfName == LW_NULL) && (netifShow == LW_NULL)) {
        return;
    }

    if (netifShow) {
        netif = (struct netif *)netifShow;
    } else {
        netif = netif_find((PCHAR)pcIfName);
    }

    if (netif == LW_NULL) {
        return;
    }

    /*
     *  打印网口基本信息
     */
    printf("%c%c%d       ",   netif->name[0], netif->name[1], netif->num);
    printf("enable: %s ",     (netif_is_up(netif) > 0) ? "true" : "false");
    printf("linkup: %s ",     (netif_is_link_up(netif) > 0) ? "true" : "false");
    printf("MTU: %d ",        netif->mtu);
    printf("multicast: %s\n", (netif->flags & NETIF_FLAG_IGMP) ? "true" : "false");

    /*
     *  打印路由信息
     */
    if (netif == netif_default) {                                       /*  route interface             */
        printf("          metric: 1 ");
    } else {
        printf("          metric: 0 ");
    }
    /*
     *  打印网口硬件地址信息
     */
    if (netif->flags & NETIF_FLAG_ETHARP) {
        printf("type: Ethernet-Cap HWaddr: ");                          /*  以太网络                    */
        for (i = 0; i < netif->hwaddr_len - 1; i++) {
            printf("%02X:", netif->hwaddr[i]);
        }
        printf("%02X\n", netif->hwaddr[netif->hwaddr_len - 1]);
    } else if (netif->flags & NETIF_FLAG_POINTTOPOINT) {
        printf("type: WAN(PPP/SLIP)\n");                                /*  点对点网络接口              */
    } else {
        printf("type: General\n");                                      /*  通用网络接口                */
    }
    
    __netIfSpeed(netif, cSpeed, sizeof(cSpeed));
    
#if LWIP_DHCP
    printf("          DHCP: %s(%s) speed: %s\n", 
                                (netif->flags2 & NETIF_FLAG2_DHCP) ? "Enable" : "Disable",
                                (netif->dhcp) ? "On" : "Off", cSpeed);
#else
    printf("          speed: %s\n", cSpeed);                            /*  打印链接速度                */
#endif                                                                  /*  LWIP_DHCP                   */
                                                                        
    /*
     *  打印网口协议地址信息
     */
    printf("          inet addr: %d.%d.%d.%d ", ip4_addr1(&netif->ip_addr),
                                                ip4_addr2(&netif->ip_addr),
                                                ip4_addr3(&netif->ip_addr),
                                                ip4_addr4(&netif->ip_addr));
    printf("netmask: %d.%d.%d.%d\n", ip4_addr1(&netif->netmask),
                                     ip4_addr2(&netif->netmask),
                                     ip4_addr3(&netif->netmask),
                                     ip4_addr4(&netif->netmask));

    if (netif->flags & NETIF_FLAG_POINTTOPOINT) {
        printf("          P-to-P: %d.%d.%d.%d ", ip4_addr1(&netif->gw),
                                                 ip4_addr2(&netif->gw),
                                                 ip4_addr3(&netif->gw),
                                                 ip4_addr4(&netif->gw));
    } else {
        printf("          gateway: %d.%d.%d.%d ", ip4_addr1(&netif->gw),
                                                  ip4_addr2(&netif->gw),
                                                  ip4_addr3(&netif->gw),
                                                  ip4_addr4(&netif->gw));
    }
    
    if (netif->flags & NETIF_FLAG_BROADCAST) {                          /*  打印广播地址信息            */
        ipaddrBroadcast.addr = (netif->ip_addr.addr | (~netif->netmask.addr));
        printf("broadcast: %d.%d.%d.%d\n", ip4_addr1(&ipaddrBroadcast),
                                           ip4_addr2(&ipaddrBroadcast),
                                           ip4_addr3(&ipaddrBroadcast),
                                           ip4_addr4(&ipaddrBroadcast));
    } else {
        printf("broadcast: Non\n");
    }
    
    /*
     *  打印 ipv6 信息
     */
    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
        PCHAR       pcAddrStat;
        PCHAR       pcAddrType;
        CHAR        cBuffer[64];
        
        if (ip6_addr_istentative(netif->ip6_addr_state[i])) {
            pcAddrStat = "tentative";
        } else if (ip6_addr_isvalid(netif->ip6_addr_state[i])) {
            pcAddrStat = "valid";
        } else if (ip6_addr_ispreferred(netif->ip6_addr_state[i])) {
            pcAddrStat = "preferred";
        } else {
            continue;
        }
        
        if (ip6_addr_isglobal(&netif->ip6_addr[i])) {
            pcAddrType = "global";
        } else if (ip6_addr_islinklocal(&netif->ip6_addr[i])) {
            pcAddrType = "link";
        } else if (ip6_addr_issitelocal(&netif->ip6_addr[i])) {
            pcAddrType = "site";
        } else if (ip6_addr_isuniquelocal(&netif->ip6_addr[i])) {
            pcAddrType = "uniquelocal";
        } else if (ip6_addr_isloopback(&netif->ip6_addr[i])) {
            pcAddrType = "loopback";
        } else {
            pcAddrType = "unknown";
        }
        
        printf("          inet6 addr: %s Scope:%s <%s>\n", 
               ip6addr_ntoa_r(&netif->ip6_addr[i], cBuffer, sizeof(cBuffer)),
               pcAddrType, pcAddrStat);
    }
    
    /*
     *  打印网口收发数据信息
     */
    printf("          RX ucast packets:%u nucast packets:%u dropped:%u\n", netif->ifinucastpkts,
                                                                           netif->ifinnucastpkts,
                                                                           netif->ifindiscards);
    printf("          TX ucast packets:%u nucast packets:%u dropped:%u\n", netif->ifoutucastpkts,
                                                                           netif->ifoutnucastpkts,
                                                                           netif->ifoutdiscards);
    printf("          RX bytes:%u TX bytes:%u\n", netif->ifinoctets,
                                                  netif->ifoutoctets);
    printf("\n");
}