Example #1
0
static int dhcp4_update_address(Link *link,
                                struct in_addr *address,
                                struct in_addr *netmask,
                                uint32_t lifetime) {
        _cleanup_address_free_ Address *addr = NULL;
        unsigned prefixlen;
        int r;

        assert(address);
        assert(netmask);
        assert(lifetime);

        prefixlen = in_addr_netmask_to_prefixlen(netmask);

        r = address_new_dynamic(&addr);
        if (r < 0)
                return r;

        addr->family = AF_INET;
        addr->in_addr.in.s_addr = address->s_addr;
        addr->cinfo.ifa_prefered = lifetime;
        addr->cinfo.ifa_valid = lifetime;
        addr->prefixlen = prefixlen;
        addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;

        /* use update rather than configure so that we will update the
         * lifetime of an existing address if it has already been configured */
        r = address_update(addr, link, &dhcp4_address_handler);
        if (r < 0)
                return r;

        return 0;
}
static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr,
                                uint8_t prefixlen, uint32_t lifetime_preferred,
                                uint32_t lifetime_valid) {
        int r;
        _cleanup_address_free_ Address *addr = NULL;

        r = address_new_dynamic(&addr);
        if (r < 0)
                return r;

        addr->family = AF_INET6;
        memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));

        addr->flags = IFA_F_NOPREFIXROUTE;
        addr->prefixlen = prefixlen;

        addr->cinfo.ifa_prefered = lifetime_preferred;
        addr->cinfo.ifa_valid = lifetime_valid;

        log_link_struct(link, LOG_INFO, "MESSAGE=%-*s: DHCPv6 address "SD_ICMP6_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
                        IFNAMSIZ,
                        link->ifname, SD_ICMP6_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
                        addr->prefixlen, lifetime_preferred, lifetime_valid,
                        NULL);

        r = address_update(addr, link, dhcp6_address_handler);
        if (r < 0)
                log_link_warning(link, "Could not assign DHCPv6 address: %s",
                                strerror(-r));

        return r;
}
Example #3
0
static void test_address_equality(void) {
        _cleanup_address_free_ Address *a1 = NULL, *a2 = NULL;

        assert_se(address_new_dynamic(&a1) >= 0);
        assert_se(address_new_dynamic(&a2) >= 0);

        assert_se(address_equal(NULL, NULL));
        assert_se(!address_equal(a1, NULL));
        assert_se(!address_equal(NULL, a2));
        assert_se(address_equal(a1, a2));

        a1->family = AF_INET;
        assert_se(!address_equal(a1, a2));

        a2->family = AF_INET;
        assert_se(address_equal(a1, a2));

        assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in));
        assert_se(address_equal(a1, a2));
        assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in));
        assert_se(address_equal(a1, a2));
        a1->prefixlen = 10;
        assert_se(!address_equal(a1, a2));
        a2->prefixlen = 10;
        assert_se(address_equal(a1, a2));

        assert_se(inet_pton(AF_INET, "192.168.3.10", &a2->in_addr.in));
        assert_se(address_equal(a1, a2));

        a1->family = AF_INET6;
        assert_se(!address_equal(a1, a2));

        a2->family = AF_INET6;
        assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr.in6));
        assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr.in6));
        assert_se(address_equal(a1, a2));

        a2->prefixlen = 8;
        assert_se(address_equal(a1, a2));

        assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr.in6));
        assert_se(!address_equal(a1, a2));
}
Example #4
0
static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
        _cleanup_address_free_ Address *ll_addr = NULL;
        _cleanup_route_free_ Route *route = NULL;
        struct in_addr address;
        int r;

        assert(ll);
        assert(link);

        r = sd_ipv4ll_get_address(ll, &address);
        if (r == -ENOENT)
                return 0;
        else if (r < 0)
                return r;

        log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u",
                       ADDRESS_FMT_VAL(address));

        r = address_new_dynamic(&ll_addr);
        if (r < 0)
                return r;

        ll_addr->family = AF_INET;
        ll_addr->in_addr.in = address;
        ll_addr->prefixlen = 16;
        ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
        ll_addr->scope = RT_SCOPE_LINK;

        r = address_configure(ll_addr, link, ipv4ll_address_handler);
        if (r < 0)
                return r;

        link->ipv4ll_address = false;

        r = route_new_dynamic(&route, RTPROT_STATIC);
        if (r < 0)
                return r;

        route->family = AF_INET;
        route->scope = RT_SCOPE_LINK;
        route->metrics = IPV4LL_ROUTE_METRIC;

        r = route_configure(route, link, ipv4ll_route_handler);
        if (r < 0)
                return r;

        link->ipv4ll_route = false;

        return 0;
}
Example #5
0
static int ipv4ll_address_lost(Link *link) {
        _cleanup_address_free_ Address *address = NULL;
        _cleanup_route_free_ Route *route = NULL;
        struct in_addr addr;
        int r;

        assert(link);

        link->ipv4ll_route = false;
        link->ipv4ll_address =  false;

        r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
        if (r < 0)
                return 0;

        log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr));

        r = address_new_dynamic(&address);
        if (r < 0) {
                log_link_error(link, "Could not allocate address: %s", strerror(-r));
                return r;
        }

        address->family = AF_INET;
        address->in_addr.in = addr;
        address->prefixlen = 16;
        address->scope = RT_SCOPE_LINK;

        address_drop(address, link, &link_address_drop_handler);

        r = route_new_dynamic(&route, RTPROT_UNSPEC);
        if (r < 0) {
                log_link_error(link, "Could not allocate route: %s",
                               strerror(-r));
                return r;
        }

        route->family = AF_INET;
        route->scope = RT_SCOPE_LINK;
        route->metrics = IPV4LL_ROUTE_METRIC;

        route_drop(route, link, &link_route_drop_handler);

        link_client_handler(link);

        return 0;
}
Example #6
0
int config_parse_dns(const char *unit,
                     const char *filename,
                     unsigned line,
                     const char *section,
                     unsigned section_line,
                     const char *lvalue,
                     int ltype,
                     const char *rvalue,
                     void *data,
                     void *userdata) {
    Address **dns = data;
    _cleanup_address_free_ Address *n = NULL;
    int r;

    assert(filename);
    assert(section);
    assert(lvalue);
    assert(rvalue);
    assert(data);

    r = address_new_dynamic(&n);
    if (r < 0)
        return r;

    r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
    if (r < 0) {
        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                   "DNS address is invalid, ignoring assignment: %s", rvalue);
        return 0;
    }

    *dns = n;
    n = NULL;

    return 0;
}
Example #7
0
static int dhcp_lease_lost(Link *link) {
        _cleanup_address_free_ Address *address = NULL;
        struct in_addr addr;
        struct in_addr netmask;
        struct in_addr gateway;
        unsigned prefixlen = 0;
        int r;

        assert(link);
        assert(link->dhcp_lease);

        log_link_warning(link, "DHCP lease lost");

        if (link->network->dhcp_routes) {
                struct sd_dhcp_route *routes;
                int n, i;

                n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
                if (n >= 0) {
                        for (i = 0; i < n; i++) {
                                _cleanup_route_free_ Route *route = NULL;

                                r = route_new_dynamic(&route, RTPROT_UNSPEC);
                                if (r >= 0) {
                                        route->family = AF_INET;
                                        route->in_addr.in = routes[i].gw_addr;
                                        route->dst_addr.in = routes[i].dst_addr;
                                        route->dst_prefixlen = routes[i].dst_prefixlen;

                                        route_drop(route, link,
                                                   &link_route_drop_handler);
                                }
                        }
                }
        }

        r = address_new_dynamic(&address);
        if (r >= 0) {
                r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
                if (r >= 0) {
                        _cleanup_route_free_ Route *route_gw = NULL;
                        _cleanup_route_free_ Route *route = NULL;

                        r = route_new_dynamic(&route_gw, RTPROT_UNSPEC);
                        if (r >= 0) {
                                route_gw->family = AF_INET;
                                route_gw->dst_addr.in = gateway;
                                route_gw->dst_prefixlen = 32;
                                route_gw->scope = RT_SCOPE_LINK;

                                route_drop(route_gw, link,
                                           &link_route_drop_handler);
                        }

                        r = route_new_dynamic(&route, RTPROT_UNSPEC);
                        if (r >= 0) {
                                route->family = AF_INET;
                                route->in_addr.in = gateway;

                                route_drop(route, link,
                                           &link_route_drop_handler);
                        }
                }

                r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
                if (r >= 0) {
                        r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
                        if (r >= 0)
                                prefixlen = in_addr_netmask_to_prefixlen(&netmask);

                        address->family = AF_INET;
                        address->in_addr.in = addr;
                        address->prefixlen = prefixlen;

                        address_drop(address, link, &link_address_drop_handler);
                }
        }

        if (link->network->dhcp_mtu) {
                uint16_t mtu;

                r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
                if (r >= 0 && link->original_mtu != mtu) {
                        r = link_set_mtu(link, link->original_mtu);
                        if (r < 0) {
                                log_link_warning(link,
                                                 "DHCP error: could not reset MTU");
                                link_enter_failed(link);
                                return r;
                        }
                }
        }

        if (link->network->dhcp_hostname) {
                const char *hostname = NULL;

                if (!link->network->hostname)
                        r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
                else
                        hostname = link->network->hostname;

                if (r >= 0 || hostname) {
                        r = link_set_hostname(link, hostname);
                        if (r < 0)
                                log_link_error_errno(link, r,
                                                     "Failed to set transient hostname to '%s': %m",
                                                     hostname);

                }
        }

        link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
        link->dhcp4_configured = false;

        return 0;
}