diff options
| -rw-r--r-- | src/network/networkd-link.c | 294 | 
1 files changed, 168 insertions, 126 deletions
| diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 363602e962..0a363b2547 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -410,175 +410,217 @@ static int link_set_mtu(Link *link, uint32_t mtu) {          return 0;  } -static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) { -        Link *link = userdata; -        struct in_addr address; -        struct in_addr netmask; -        struct in_addr gateway; -        unsigned prefixlen; +static int dhcp_lease_lost(sd_dhcp_client *client, Link *link) {          int r; +        assert(client);          assert(link); -        assert(link->network); -        assert(link->manager); -        if (link->state == LINK_STATE_FAILED) -                return; +        if (link->dhcp_address) { +                address_drop(link->dhcp_address, link, address_drop_handler); -        if (event < 0) { -                log_warning_link(link, "DHCP error: %s", strerror(-event)); -                link_enter_failed(link); -                return; +                address_free(link->dhcp_address); +                link->dhcp_address = NULL;          } -        if (event == DHCP_EVENT_NO_LEASE) -                log_debug_link(link, "IP address in use."); - -        if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED || -            event == DHCP_EVENT_STOP) { -                if (link->network->dhcp_critical) { -                        log_warning_link(link, "DHCPv4 connection considered system critical, " -                                         "ignoring request to reconfigure it down."); -                        return; -                } +        if (link->dhcp_route) { +                route_free(link->dhcp_route); +                link->dhcp_route = NULL; +        } -                if (link->dhcp_address) { -                        address_drop(link->dhcp_address, link, address_drop_handler); +        if (link->network->dhcp_mtu) { +                uint16_t mtu; -                        address_free(link->dhcp_address); -                        link->dhcp_address = NULL; +                r = sd_dhcp_client_get_mtu(client, &mtu); +                if (r >= 0 && link->original_mtu != mtu) { +                        r = link_set_mtu(link, link->original_mtu); +                        if (r < 0) { +                                log_warning_link(link, "DHCP error: could not reset MTU"); +                                link_enter_failed(link); +                                return r; +                        }                  } +        } -                if (link->dhcp_route) { -                        route_free(link->dhcp_route); -                        link->dhcp_route = NULL; -                } +        if (link->network->dhcp_hostname) { +                r = set_hostname(link->manager->bus, ""); +                if (r < 0) +                        log_error("Failed to reset transient hostname"); +        } -                if (link->network->dhcp_mtu) { -                        uint16_t mtu; +        return 0; +} -                        r = sd_dhcp_client_get_mtu(client, &mtu); -                        if (r >= 0 && link->original_mtu != mtu) { -                                r = link_set_mtu(link, link->original_mtu); -                                if (r < 0) { -                                        log_warning_link(link, "DHCP error: could not reset MTU"); -                                        link_enter_failed(link); -                                        return; -                                } -                        } -                } +static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { +        struct in_addr address; +        struct in_addr netmask; +        struct in_addr gateway; +        unsigned prefixlen; +        _cleanup_address_free_ Address *addr = NULL; +        _cleanup_route_free_ Route *rt = NULL; +        struct in_addr *nameservers; +        size_t nameservers_size; +        int r; -                if (link->network->dhcp_hostname) { -                        r = set_hostname(link->manager->bus, ""); -                        if (r < 0) -                                log_error("Failed to reset transient hostname"); -                } -        } +        assert(client); +        assert(link);          r = sd_dhcp_client_get_address(client, &address);          if (r < 0) { -                log_warning_link(link, "DHCP error: no address"); -                link_enter_failed(link); -                return; +                log_warning_link(link, "DHCP error: no address: %s", +                                 strerror(-r)); +                return r;          }          r = sd_dhcp_client_get_netmask(client, &netmask);          if (r < 0) { -                log_warning_link(link, "DHCP error: no netmask"); -                link_enter_failed(link); -                return; +                log_warning_link(link, "DHCP error: no netmask: %s", +                                 strerror(-r)); +                return r;          }          prefixlen = net_netmask_to_prefixlen(&netmask);          r = sd_dhcp_client_get_router(client, &gateway);          if (r < 0) { -                log_warning_link(link, "DHCP error: no router"); -                link_enter_failed(link); -                return; +                log_warning_link(link, "DHCP error: no router: %s", +                                 strerror(-r)); +                return r;          } -        if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) { -                _cleanup_address_free_ Address *addr = NULL; -                _cleanup_route_free_ Route *rt = NULL; -                struct in_addr *nameservers; -                size_t nameservers_size; - -                log_struct_link(LOG_INFO, link, -                                "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u", -                                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); -                r = address_new_dynamic(&addr); -                if (r < 0) { -                        log_error_link(link, "Could not allocate address"); -                        link_enter_failed(link); -                        return; -                } +        log_struct_link(LOG_INFO, link, +                        "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u", +                         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); -                addr->family = AF_INET; -                addr->in_addr.in = address; -                addr->prefixlen = prefixlen; -                addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr; +        r = address_new_dynamic(&addr); +        if (r < 0) { +                log_error_link(link, "Could not allocate address: %s", +                               strerror(-r)); +                return r; +        } -                r = route_new_dynamic(&rt); -                if (r < 0) { -                        log_error_link(link, "Could not allocate route"); -                        link_enter_failed(link); -                        return; +        addr->family = AF_INET; +        addr->in_addr.in = address; +        addr->prefixlen = prefixlen; +        addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr; + +        r = route_new_dynamic(&rt); +        if (r < 0) { +                log_error_link(link, "Could not allocate route: %s", +                               strerror(-r)); +                return r; +        } + +        rt->family = AF_INET; +        rt->in_addr.in = gateway; + +        link->dhcp_address = addr; +        link->dhcp_route = rt; +        addr = NULL; +        rt = NULL; + +        if (link->network->dhcp_dns) { +                r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size); +                if (r >= 0) { +                        r = manager_update_resolv_conf(link->manager); +                        if (r < 0) +                                log_error("Failed to update resolv.conf");                  } +        } + +        if (link->network->dhcp_mtu) { +                uint16_t mtu; -                rt->family = AF_INET; -                rt->in_addr.in = gateway; +                r = sd_dhcp_client_get_mtu(client, &mtu); +                if (r >= 0) { +                        r = link_set_mtu(link, mtu); +                        if (r < 0) +                                log_error_link(link, "Failed to set MTU " +                                               "to %" PRIu16, mtu); +                } +        } -                link->dhcp_address = addr; -                link->dhcp_route = rt; -                addr = NULL; -                rt = NULL; +        if (link->network->dhcp_hostname) { +                const char *hostname; -                if (link->network->dhcp_dns) { -                        r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size); -                        if (r >= 0) { -                                r = manager_update_resolv_conf(link->manager); -                                if (r < 0) -                                        log_error("Failed to update resolv.conf"); -                        } +                r = sd_dhcp_client_get_hostname(client, &hostname); +                if (r >= 0) { +                        r = set_hostname(link->manager->bus, hostname); +                        if (r < 0) +                                log_error("Failed to set transient hostname " +                                          "to '%s'", hostname);                  } +        } -                if (link->network->dhcp_mtu) { -                        uint16_t mtu; - -                        r = sd_dhcp_client_get_mtu(client, &mtu); -                        if (r >= 0) { -                                r = link_set_mtu(link, mtu); -                                if (r < 0) -                                        log_error_link(link, "Failed to set MTU " -                                                             "to %" PRIu16, mtu); +        link_enter_set_addresses(link); + +        return 0; +} + +static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) { +        Link *link = userdata; +        int r; + +        assert(link); +        assert(link->network); +        assert(link->manager); + +        if (link->state == LINK_STATE_FAILED) +                return; + +        switch (event) { +                case DHCP_EVENT_NO_LEASE: +                        log_debug_link(link, "IP address in use."); +                        break; +                case DHCP_EVENT_EXPIRED: +                case DHCP_EVENT_STOP: +                case DHCP_EVENT_IP_CHANGE: +                        if (link->network->dhcp_critical) { +                                log_error_link(link, "DHCPv4 connection considered system critical, " +                                               "ignoring request to reconfigure it."); +                                return;                          } -                } -                if (link->network->dhcp_hostname) { -                        const char *hostname; +                        r = dhcp_lease_lost(client, link); +                        if (r < 0) { +                                link_enter_failed(link); +                                return; +                        } -                        r = sd_dhcp_client_get_hostname(client, &hostname); -                        if (r >= 0) { -                                r = set_hostname(link->manager->bus, hostname); -                                if (r < 0) -                                        log_error("Failed to set transient hostname " -                                                  "to '%s'", hostname); +                        if (event == DHCP_EVENT_IP_CHANGE) { +                                r = dhcp_lease_acquired(client, link); +                                if (r < 0) { +                                        link_enter_failed(link); +                                        return; +                                }                          } -                } -                link_enter_set_addresses(link); +                        break; +                case DHCP_EVENT_IP_ACQUIRE: +                        r = dhcp_lease_acquired(client, link); +                        if (r < 0) { +                                link_enter_failed(link); +                                return; +                        } +                        break; +                default: +                        if (event < 0) +                                log_warning_link(link, "DHCP error: %s", strerror(-event)); +                        else +                                log_warning_link(link, "DHCP unknown event: %d", event); +                        link_enter_failed(link); +                        break;          }          return; | 
