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;
}
static int dhcp6_prefix_expired(Link *link) {
        int r;
        sd_dhcp6_lease *lease;
        struct in6_addr *expired_prefix, ip6_addr;
        uint8_t expired_prefixlen;
        uint32_t lifetime_preferred, lifetime_valid;

        r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery,
                                        &expired_prefix, &expired_prefixlen);
        if (r < 0)
                return r;

        r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease);
        if (r < 0)
                return r;

        log_link_struct(link, LOG_INFO,
                        "MESSAGE=%-*s: IPv6 prefix "SD_ICMP6_ADDRESS_FORMAT_STR"/%d expired",
                        IFNAMSIZ, link->ifname,
                        SD_ICMP6_ADDRESS_FORMAT_VAL(*expired_prefix),
                        expired_prefixlen, NULL);

        sd_dhcp6_lease_reset_address_iter(lease);

        while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
                                                &lifetime_preferred,
                                                &lifetime_valid) >= 0) {

                r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen,
                                        &ip6_addr);
                if (r < 0)
                        continue;

                log_link_struct(link, LOG_INFO,
                                "MESSAGE=%-*s: IPv6 prefix length updated "SD_ICMP6_ADDRESS_FORMAT_STR"/%d",
                                IFNAMSIZ, link->ifname,
                                SD_ICMP6_ADDRESS_FORMAT_VAL(ip6_addr), 128,
                                NULL);

                dhcp6_address_update(link, &ip6_addr, 128, lifetime_preferred,
                                     lifetime_valid);
        }

        return 0;
}
示例#3
0
static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
        sd_dhcp_lease *lease;
        struct in_addr address;
        struct in_addr netmask;
        struct in_addr gateway;
        unsigned prefixlen;
        uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
        int r;

        assert(client);
        assert(link);

        r = sd_dhcp_client_get_lease(client, &lease);
        if (r < 0) {
                log_link_warning(link, "DHCP error: no lease: %s",
                                 strerror(-r));
                return r;
        }

        r = sd_dhcp_lease_get_address(lease, &address);
        if (r < 0) {
                log_link_warning(link, "DHCP error: no address: %s",
                                 strerror(-r));
                return r;
        }

        r = sd_dhcp_lease_get_netmask(lease, &netmask);
        if (r < 0) {
                log_link_warning(link, "DHCP error: no netmask: %s",
                                 strerror(-r));
                return r;
        }

        prefixlen = in_addr_netmask_to_prefixlen(&netmask);

        r = sd_dhcp_lease_get_router(lease, &gateway);
        if (r < 0 && r != -ENOENT) {
                log_link_warning(link, "DHCP error: could not get gateway: %s",
                                 strerror(-r));
                return r;
        }

        if (r >= 0)
                log_link_struct(link, LOG_INFO,
                                "MESSAGE=%-*s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
                                 IFNAMSIZ,
                                 link->ifname,
                                 ADDRESS_FMT_VAL(address),
                                 prefixlen,
                                 ADDRESS_FMT_VAL(gateway),
                                 "ADDRESS=%u.%u.%u.%u",
                                 ADDRESS_FMT_VAL(address),
                                 "PREFIXLEN=%u",
                                 prefixlen,
                                 "GATEWAY=%u.%u.%u.%u",
                                 ADDRESS_FMT_VAL(gateway),
                                 NULL);
        else
                log_link_struct(link, LOG_INFO,
                                "MESSAGE=%-*s: DHCPv4 address %u.%u.%u.%u/%u",
                                 IFNAMSIZ,
                                 link->ifname,
                                 ADDRESS_FMT_VAL(address),
                                 prefixlen,
                                 "ADDRESS=%u.%u.%u.%u",
                                 ADDRESS_FMT_VAL(address),
                                 "PREFIXLEN=%u",
                                 prefixlen,
                                 NULL);

        link->dhcp_lease = lease;

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

                r = sd_dhcp_lease_get_mtu(lease, &mtu);
                if (r >= 0) {
                        r = link_set_mtu(link, mtu);
                        if (r < 0)
                                log_link_error(link, "Failed to set MTU "
                                               "to %" PRIu16, mtu);
                }
        }

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

                r = sd_dhcp_lease_get_hostname(lease, &hostname);
                if (r >= 0) {
                        r = link_set_hostname(link, hostname);
                        if (r < 0)
                                log_link_error(link,
                                               "Failed to set transient hostname to '%s'",
                                               hostname);
                }
        }

        if (!link->network->dhcp_critical) {
                r = sd_dhcp_lease_get_lifetime(link->dhcp_lease,
                                               &lifetime);
                if (r < 0) {
                        log_link_warning(link,
                                         "DHCP error: no lifetime: %s",
                                         strerror(-r));
                        return r;
                }
        }

        r = dhcp4_update_address(link, &address, &netmask, lifetime);
        if (r < 0) {
                log_link_warning(link, "could not update IP address: %s",
                                 strerror(-r));
                link_enter_failed(link);
                return r;
        }

        return 0;
}