Ejemplo n.º 1
0
tb_bool_t tb_ifaddrs_ipaddr(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_bool_t reload, tb_size_t family, tb_ipaddr_ref_t ipaddr)
{
    // check
    tb_assert_and_check_return_val(ifaddrs && ipaddr, tb_false);

    // clear it first
    tb_ipaddr_clear(ipaddr);

    // the iterator
    tb_iterator_ref_t iterator = tb_ifaddrs_itor(ifaddrs, reload);
    tb_assert_and_check_return_val(iterator, tb_false);

    // reload it if the cached interfaces is empty
    if (!reload && !tb_iterator_size(iterator)) iterator = tb_ifaddrs_itor(ifaddrs, tb_true);

    // the ipaddr flags
    tb_uint32_t ipflags = 0;
    if (family == TB_IPADDR_FAMILY_IPV4) ipflags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4;
    else if (family == TB_IPADDR_FAMILY_IPV6) ipflags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6;

    // done
    tb_bool_t ok = tb_false;
    tb_for_all_if (tb_ifaddrs_interface_ref_t, interface, iterator, interface)
    {
        // is this?
        if (    (name || !(interface->flags & TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK))
            &&  (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR)
            &&  (!name || (interface->name && !tb_strcmp(interface->name, name))))
        {
            // ipv4?
            if (    interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4
                &&  (!family || family == TB_IPADDR_FAMILY_IPV4))
            {
                // save ipaddr4
                tb_ipaddr_ipv4_set(ipaddr, &interface->ipaddr4);

                // ok
                ok = tb_true;
                break;
            }
            // ipv6?
            else if (    interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6
                    &&  (!family || family == TB_IPADDR_FAMILY_IPV6))
            {
                // save ipaddr6
                tb_ipaddr_ipv6_set(ipaddr, &interface->ipaddr6);

                // ok
                ok = tb_true;
                break;
            }
        }
    }

    // ok?
    return ok;
}
Ejemplo n.º 2
0
static tb_size_t tb_ifaddrs_netlink_ipaddr_save(tb_ipaddr_ref_t ipaddr, tb_size_t family, tb_size_t scope_id, tb_cpointer_t saddr)
{
    // check
    tb_assert_and_check_return_val(ipaddr && saddr, 0);

    // clear address
    tb_ipaddr_clear(ipaddr);

    // done
    tb_size_t size = 0;
    switch (family)
    {
    case AF_INET:
        {
            // the ipv4 ipaddr
            struct in_addr* addr4 = (struct in_addr*)saddr;

            // save family
            tb_ipaddr_family_set(ipaddr, TB_IPADDR_FAMILY_IPV4);

            // make ipv4
            tb_ipv4_t ipv4;
            ipv4.u32 = (tb_uint32_t)addr4->s_addr;

            // save ipv4
            tb_ipaddr_ipv4_set(ipaddr, &ipv4);

            // save size
            size = sizeof(struct in_addr);
        }
        break;
    case AF_INET6:
        {
            // the ipv6 ipaddr
            struct in6_addr* addr6 = (struct in6_addr*)saddr;

            // check
            tb_assert_static(sizeof(ipaddr->u.ipv6.addr.u8) == sizeof(addr6->s6_addr));
            tb_assert_static(tb_arrayn(ipaddr->u.ipv6.addr.u8) == tb_arrayn(addr6->s6_addr));

            // save family
            tb_ipaddr_family_set(ipaddr, TB_IPADDR_FAMILY_IPV6);

            // make ipv6
            tb_ipv6_t ipv6;
            tb_memcpy(ipv6.addr.u8, addr6->s6_addr, sizeof(ipv6.addr.u8));

            // save scope id
            ipv6.scope_id = 0;
            if (IN6_IS_ADDR_LINKLOCAL(addr6) || IN6_IS_ADDR_MC_LINKLOCAL(addr6))
                ipv6.scope_id = (tb_uint32_t)scope_id;

            // save ipv6
            tb_ipaddr_ipv6_set(ipaddr, &ipv6);

            // save size
            size = sizeof(struct in6_addr);
        }
        break;
    default:
        tb_assert(0);
        break;
    }
    
    // ok?
    return size;
}