X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-link.c;h=077626cd17d82c8ff1d4a29e66de047b82569192;hb=6a24f1484fcc1f59f89617afbe4282667a358eab;hp=12944a03a3bca77011e2dfef8998fd3ad6d1342a;hpb=5a8bcb674f71a20e95df55319b34c556638378ce;p=elogind.git diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 12944a03a..077626cd1 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -42,7 +42,7 @@ static bool link_dhcp6_enabled(Link *link) { if (!link->network) return false; - return IN_SET(link->network->dhcp, DHCP_SUPPORT_V6, DHCP_SUPPORT_BOTH); + return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES); } static bool link_dhcp4_enabled(Link *link) { @@ -52,7 +52,7 @@ static bool link_dhcp4_enabled(Link *link) { if (!link->network) return false; - return IN_SET(link->network->dhcp, DHCP_SUPPORT_V4, DHCP_SUPPORT_BOTH); + return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES); } static bool link_dhcp4_server_enabled(Link *link) { @@ -88,14 +88,24 @@ static bool link_lldp_enabled(Link *link) { return link->network->lldp; } -static bool link_ip_forward_enabled(Link *link) { +static bool link_ipv4_forward_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; - return link->network->ip_forward; + return IN_SET(link->network->ip_forward, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES); +} + +static bool link_ipv6_forward_enabled(Link *link) { + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + return IN_SET(link->network->ip_forward, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES); } #define FLAG_STRING(string, flag, old, new) \ @@ -276,6 +286,8 @@ static void link_free(Link *link) { unlink(link->lease_file); free(link->lease_file); + sd_lldp_free(link->lldp); + unlink(link->lldp_file); free(link->lldp_file); @@ -431,7 +443,7 @@ static Address* link_find_dhcp_server_address(Link *link) { assert(link); assert(link->network); - /* The the first statically configured address if there is any */ + /* The first statically configured address if there is any */ LIST_FOREACH(addresses, address, link->network->static_addresses) { if (address->family != AF_INET) @@ -455,63 +467,10 @@ static Address* link_find_dhcp_server_address(Link *link) { } static int link_enter_configured(Link *link) { - int r; - assert(link); assert(link->network); assert(link->state == LINK_STATE_SETTING_ROUTES); - if (link_dhcp4_server_enabled(link) && - !sd_dhcp_server_is_running(link->dhcp_server)) { - struct in_addr pool_start; - Address *address; - - address = link_find_dhcp_server_address(link); - if (!address) { - log_link_warning(link, - "Failed to find suitable address for DHCPv4 server instance."); - link_enter_failed(link); - return 0; - } - - log_link_debug(link, "offering DHCPv4 leases"); - - r = sd_dhcp_server_set_address(link->dhcp_server, - &address->in_addr.in, - address->prefixlen); - if (r < 0) - return r; - - /* offer 32 addresses starting from the address following the server address */ - pool_start.s_addr = htobe32(be32toh(address->in_addr.in.s_addr) + 1); - r = sd_dhcp_server_set_lease_pool(link->dhcp_server, - &pool_start, 32); - if (r < 0) - return r; - - /* TODO: - r = sd_dhcp_server_set_router(link->dhcp_server, - &main_address->in_addr.in); - if (r < 0) - return r; - - r = sd_dhcp_server_set_prefixlen(link->dhcp_server, - main_address->prefixlen); - if (r < 0) - return r; - */ - - r = sd_dhcp_server_start(link->dhcp_server); - if (r < 0) { - log_link_warning(link, "could not start DHCPv4 server " - "instance: %s", strerror(-r)); - - link_enter_failed(link); - - return 0; - } - } - log_link_info(link, "link configured"); link->state = LINK_STATE_CONFIGURED; @@ -671,6 +630,58 @@ static int link_enter_set_addresses(Link *link) { link->link_messages ++; } + /* now that we can figure out a default address for the dhcp server, + start it */ + if (link_dhcp4_server_enabled(link)) { + struct in_addr pool_start; + Address *address; + + address = link_find_dhcp_server_address(link); + if (!address) { + log_link_warning(link, + "Failed to find suitable address for DHCPv4 server instance."); + link_enter_failed(link); + return 0; + } + + r = sd_dhcp_server_set_address(link->dhcp_server, + &address->in_addr.in, + address->prefixlen); + if (r < 0) + return r; + + /* offer 32 addresses starting from the address following the server address */ + pool_start.s_addr = htobe32(be32toh(address->in_addr.in.s_addr) + 1); + r = sd_dhcp_server_set_lease_pool(link->dhcp_server, + &pool_start, 32); + if (r < 0) + return r; + + /* TODO: + r = sd_dhcp_server_set_router(link->dhcp_server, + &main_address->in_addr.in); + if (r < 0) + return r; + + r = sd_dhcp_server_set_prefixlen(link->dhcp_server, + main_address->prefixlen); + if (r < 0) + return r; + */ + + r = sd_dhcp_server_start(link->dhcp_server); + if (r < 0) { + log_link_warning(link, "could not start DHCPv4 server " + "instance: %s", strerror(-r)); + + link_enter_failed(link); + + return 0; + } + + log_link_debug(link, "offering DHCPv4 leases"); + } + if (link->link_messages == 0) { link_enter_set_routes(link); } else @@ -1225,14 +1236,52 @@ static int link_enter_join_netdev(Link *link) { return 0; } -static int link_set_ip_forward(Link *link) { +static int link_set_ipv4_forward(Link *link) { const char *p = NULL; + bool b; int r; - p = strappenda("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding"); - r = write_string_file_no_create(p, link_ip_forward_enabled(link) ? "1" : "0"); + b = link_ipv4_forward_enabled(link); + + p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding"); + r = write_string_file_no_create(p, one_zero(b)); if (r < 0) - log_link_warning_errno(link, r, "Cannot configure IP forwarding for interface: %m"); + log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname); + + if (b) { + _cleanup_free_ char *buf = NULL; + + /* If IP forwarding is turned on for this interface, + * then propagate this to the global setting. Given + * that turning this on has side-effects on other + * fields, we'll try to avoid doing this unless + * necessary, hence check the previous value + * first. Note that we never turn this option off + * again, since all interfaces we manage do not do + * forwarding anyway by default, and ownership rules + * of this control are so unclear. */ + + r = read_one_line_file("/proc/sys/net/ipv4/ip_forward", &buf); + if (r < 0) + log_link_warning_errno(link, r, "Cannot read /proc/sys/net/ipv4/ip_forward: %m"); + else if (!streq(buf, "1")) { + r = write_string_file_no_create("/proc/sys/net/ipv4/ip_forward", "1"); + if (r < 0) + log_link_warning_errno(link, r, "Cannot write /proc/sys/net/ipv4/ip_forward: %m"); + } + } + + return 0; +} + +static int link_set_ipv6_forward(Link *link) { + const char *p = NULL; + int r; + + p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding"); + r = write_string_file_no_create(p, one_zero(link_ipv6_forward_enabled(link))); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m"); return 0; } @@ -1248,7 +1297,11 @@ static int link_configure(Link *link) { if (r < 0) return r; - r = link_set_ip_forward(link); + r = link_set_ipv4_forward(link); + if (r < 0) + return r; + + r = link_set_ipv6_forward(link); if (r < 0) return r; @@ -1331,7 +1384,7 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, if (network->ipv4ll) log_link_debug(link, "ignoring IPv4LL for loopback link"); - if (network->dhcp != DHCP_SUPPORT_NONE) + if (network->dhcp != ADDRESS_FAMILY_NO) log_link_debug(link, "ignoring DHCP clients for loopback link"); if (network->dhcp_server) @@ -1439,7 +1492,10 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use } else { r = link_get(m, ifindex, &link); if (r < 0 || !link) { - log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex); + /* when enumerating we might be out of sync, but we will + * get the address again, so just ignore it */ + if (!m->enumerating) + log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex); return 0; } } @@ -1603,6 +1659,57 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) { return 0; } +static int link_carrier_gained(Link *link) { + int r; + + assert(link); + + if (link->network) { + r = link_acquire_conf(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + return 0; +} + +static int link_carrier_lost(Link *link) { + int r; + + assert(link); + + r = link_stop_clients(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + + return 0; +} + +int link_carrier_reset(Link *link) { + int r; + + assert(link); + + if (link_has_carrier(link)) { + r = link_carrier_lost(link); + if (r < 0) + return r; + + r = link_carrier_gained(link); + if (r < 0) + return r; + + log_link_info(link, "reset carrier"); + } + + return 0; +} + + int link_update(Link *link, sd_rtnl_message *m) { struct ether_addr mac; const char *ifname; @@ -1720,21 +1827,16 @@ int link_update(Link *link, sd_rtnl_message *m) { if (carrier_gained) { log_link_info(link, "gained carrier"); - if (link->network) { - r = link_acquire_conf(link); - if (r < 0) { - link_enter_failed(link); - return r; - } - } + r = link_carrier_gained(link); + if (r < 0) + return r; } else if (carrier_lost) { log_link_info(link, "lost carrier"); - r = link_stop_clients(link); - if (r < 0) { - link_enter_failed(link); + r = link_carrier_lost(link); + if (r < 0) return r; - } + } return 0;