diff options
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/networkd-dhcp4.c | 41 | ||||
-rw-r--r-- | src/network/networkd-link.c | 101 | ||||
-rw-r--r-- | src/network/networkd-netdev-bond.c | 7 | ||||
-rw-r--r-- | src/network/networkd-netdev-bond.h | 6 | ||||
-rw-r--r-- | src/network/networkd-netdev-gperf.gperf | 3 | ||||
-rw-r--r-- | src/network/networkd-netdev-tunnel.c | 71 | ||||
-rw-r--r-- | src/network/networkd-netdev-tunnel.h | 28 | ||||
-rw-r--r-- | src/network/networkd-netdev-tuntap.c | 3 | ||||
-rw-r--r-- | src/network/networkd-netdev-tuntap.h | 1 | ||||
-rw-r--r-- | src/network/networkd-netdev-vxlan.h | 11 | ||||
-rw-r--r-- | src/network/networkd-netdev.c | 13 | ||||
-rw-r--r-- | src/network/networkd-network-bus.c | 6 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 137 | ||||
-rw-r--r-- | src/network/networkd-network.c | 98 | ||||
-rw-r--r-- | src/network/networkd-wait-online.c | 2 | ||||
-rw-r--r-- | src/network/networkd.c | 2 | ||||
-rw-r--r-- | src/network/networkd.h | 50 |
17 files changed, 457 insertions, 123 deletions
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index d446bfa8b3..4aa301b112 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -270,12 +270,18 @@ static int dhcp_lease_lost(Link *link) { if (link->network->dhcp_hostname) { const char *hostname = NULL; - r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname); - if (r >= 0 && hostname) { - r = link_set_hostname(link, ""); + 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(link, - "Failed to reset transient hostname"); + log_link_error_errno(link, r, + "Failed to set transient hostname to '%s': %m", + hostname); + } } @@ -464,8 +470,12 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { if (link->network->dhcp_hostname) { const char *hostname; - r = sd_dhcp_lease_get_hostname(lease, &hostname); - if (r >= 0) { + if (!link->network->hostname) + r = sd_dhcp_lease_get_hostname(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); @@ -616,14 +626,19 @@ int dhcp4_configure(Link *link) { if (link->network->dhcp_sendhost) { _cleanup_free_ char *hostname = NULL; + const char *hn = NULL; + + if (!link->network->hostname) { + hostname = gethostname_malloc(); + if (!hostname) + return -ENOMEM; - hostname = gethostname_malloc(); - if (!hostname) - return -ENOMEM; + hn = hostname; + } else + hn = link->network->hostname; - if (!is_localhost(hostname)) { - r = sd_dhcp_client_set_hostname(link->dhcp_client, - hostname); + if (!is_localhost(hn)) { + r = sd_dhcp_client_set_hostname(link->dhcp_client, hn); if (r < 0) return r; } diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 16243a5352..f20f68b482 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -116,6 +116,16 @@ static bool link_ipv6_forward_enabled(Link *link) { return link->network->ip_forward & ADDRESS_FAMILY_IPV6; } +static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) { + if (link->flags & IFF_LOOPBACK) + return _IPV6_PRIVACY_EXTENSIONS_INVALID; + + if (!link->network) + return _IPV6_PRIVACY_EXTENSIONS_INVALID; + + return link->network->ipv6_privacy_extensions; +} + #define FLAG_STRING(string, flag, old, new) \ (((old ^ new) & flag) \ ? ((old & flag) ? (" -" string) : (" +" string)) \ @@ -836,9 +846,6 @@ static int link_set_bridge(Link *link) { assert(link); assert(link->network); - if(link->network->cost == 0) - return 0; - r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); @@ -851,6 +858,26 @@ static int link_set_bridge(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m"); + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m"); + + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m"); + + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m"); + + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m"); + + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m"); + if(link->network->cost != 0) { r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost); if (r < 0) @@ -1360,8 +1387,7 @@ static int link_joined(Link *link) { return link_enter_set_addresses(link); } -static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, - void *userdata) { +static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; @@ -1474,35 +1500,84 @@ static int link_enter_join_netdev(Link *link) { } static int link_set_ipv4_forward(Link *link) { - const char *p = NULL; + const char *p = NULL, *v; int r; + if (link->flags & IFF_LOOPBACK) + return 0; + if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID) return 0; p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding"); - r = write_string_file_no_create(p, one_zero(link_ipv4_forward_enabled(link))); - if (r < 0) + v = one_zero(link_ipv4_forward_enabled(link)); + + r = write_string_file(p, v, 0); + if (r < 0) { + /* If the right value is set anyway, don't complain */ + if (verify_one_line_file(p, v) > 0) + return 0; + log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname); + } return 0; } static int link_set_ipv6_forward(Link *link) { - const char *p = NULL; + const char *p = NULL, *v = NULL; int r; /* Make this a NOP if IPv6 is not available */ if (!socket_ipv6_is_supported()) return 0; + if (link->flags & IFF_LOOPBACK) + return 0; + if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID) return 0; 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) + v = one_zero(link_ipv6_forward_enabled(link)); + + r = write_string_file(p, v, 0); + if (r < 0) { + /* If the right value is set anyway, don't complain */ + if (verify_one_line_file(p, v) > 0) + return 0; + log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m"); + } + + return 0; +} + +static int link_set_ipv6_privacy_extensions(Link *link) { + char buf[DECIMAL_STR_MAX(unsigned) + 1]; + IPv6PrivacyExtensions s; + const char *p = NULL; + int r; + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + s = link_ipv6_privacy_extensions(link); + if (s == _IPV6_PRIVACY_EXTENSIONS_INVALID) + return 0; + + p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr"); + xsprintf(buf, "%u", link->network->ipv6_privacy_extensions); + + r = write_string_file(p, buf, 0); + if (r < 0) { + /* If the right value is set anyway, don't complain */ + if (verify_one_line_file(p, buf) > 0) + return 0; + + log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m"); + } return 0; } @@ -1526,6 +1601,10 @@ static int link_configure(Link *link) { if (r < 0) return r; + r = link_set_ipv6_privacy_extensions(link); + if (r < 0) + return r; + if (link_ipv4ll_enabled(link)) { r = ipv4ll_configure(link); if (r < 0) diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c index 6336ff58a7..a60034dbe6 100644 --- a/src/network/networkd-netdev-bond.c +++ b/src/network/networkd-netdev-bond.c @@ -25,7 +25,6 @@ #include "conf-parser.h" #include "sd-netlink.h" -#include "netlink-types.h" #include "networkd-netdev-bond.h" #include "missing.h" @@ -372,11 +371,11 @@ int config_parse_arp_ip_target_address(const char *unit, b->n_arp_ip_targets ++; buffer = NULL; - - if (b->n_arp_ip_targets > BOND_ARP_TARGETS_MAX) - break; } + if (b->n_arp_ip_targets > NETDEV_BOND_ARP_TARGETS_MAX) + log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "More than the maximum number of kernel-supported ARP ip targets specified: %d > %d", b->n_arp_ip_targets, NETDEV_BOND_ARP_TARGETS_MAX); + return 0; } diff --git a/src/network/networkd-netdev-bond.h b/src/network/networkd-netdev-bond.h index 32d1702d58..9991fa731f 100644 --- a/src/network/networkd-netdev-bond.h +++ b/src/network/networkd-netdev-bond.h @@ -25,6 +25,12 @@ typedef struct Bond Bond; #include "networkd-netdev.h" +/* + * Maximum number of targets supported by the kernel for a single + * bond netdev. + */ +#define NETDEV_BOND_ARP_TARGETS_MAX 16 + typedef enum BondMode { NETDEV_BOND_MODE_BALANCE_RR, NETDEV_BOND_MODE_ACTIVE_BACKUP, diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index 66ed2e013c..fa3ba38a3b 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -36,6 +36,8 @@ Tunnel.TOS, config_parse_unsigned, 0, Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl) Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc) Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode) +Tunnel.IPv6FlowLabel, config_parse_ipv6_flowlabel, 0, offsetof(Tunnel, ipv6_flowlabel) +Tunnel.CopyDSCP, config_parse_bool, 0, offsetof(Tunnel, copy_dscp) Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer) Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer) VXLAN.Id, config_parse_uint64, 0, offsetof(VxLan, id) @@ -59,6 +61,7 @@ Tun.Group, config_parse_string, 0, Tap.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) Tap.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) Tap.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) +Tap.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr) Tap.User, config_parse_string, 0, offsetof(TunTap, user_name) Tap.Group, config_parse_string, 0, offsetof(TunTap, group_name) Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode) diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c index 5533fb5c7b..7fd9ef584b 100644 --- a/src/network/networkd-netdev-tunnel.c +++ b/src/network/networkd-netdev-tunnel.c @@ -33,6 +33,7 @@ #include "conf-parser.h" #define DEFAULT_TNL_HOP_LIMIT 64 +#define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF) static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = { [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6", @@ -184,6 +185,16 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m"); + if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) { + r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m"); + } + + r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m"); + return r; } @@ -264,6 +275,19 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); + if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) { + r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m"); + } + + if (t->copy_dscp) + t->flags |= IP6_TNL_F_RCV_DSCP_COPY; + + r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m"); + switch (t->ip6tnl_mode) { case NETDEV_IP6_TNL_MODE_IP6IP6: proto = IPPROTO_IPV6; @@ -380,6 +404,52 @@ int config_parse_tunnel_address(const char *unit, return 0; } +static const char* const ipv6_flowlabel_table[_NETDEV_IPV6_FLOWLABEL_MAX] = { + [NETDEV_IPV6_FLOWLABEL_INHERIT] = "inherit", +}; + +DEFINE_STRING_TABLE_LOOKUP(ipv6_flowlabel, IPv6FlowLabel); + +int config_parse_ipv6_flowlabel(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) { + IPv6FlowLabel *ipv6_flowlabel = data; + Tunnel *t = userdata; + IPv6FlowLabel s; + int k = 0; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(ipv6_flowlabel); + + s = ipv6_flowlabel_from_string(rvalue); + if (s != _NETDEV_IPV6_FLOWLABEL_INVALID) { + *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL; + t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; + } else { + r = config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata); + if (r >= 0) { + if (k > 0xFFFFF) + log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue); + else { + *ipv6_flowlabel = htonl(k) & IP6_FLOWINFO_FLOWLABEL; + t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; + } + } + } + + return 0; +} + static void ipip_init(NetDev *n) { Tunnel *t = IPIP(n); @@ -452,6 +522,7 @@ static void ip6tnl_init(NetDev *n) { t->ttl = DEFAULT_TNL_HOP_LIMIT; t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID; + t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID; } const NetDevVTable ipip_vtable = { diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h index 88f57ac105..1fd2b94ae1 100644 --- a/src/network/networkd-netdev-tunnel.h +++ b/src/network/networkd-netdev-tunnel.h @@ -33,6 +33,12 @@ typedef enum Ip6TnlMode { _NETDEV_IP6_TNL_MODE_INVALID = -1, } Ip6TnlMode; +typedef enum IPv6FlowLabel { + NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1, + _NETDEV_IPV6_FLOWLABEL_MAX, + _NETDEV_IPV6_FLOWLABEL_INVALID = -1, +} IPv6FlowLabel; + struct Tunnel { NetDev meta; @@ -48,8 +54,10 @@ struct Tunnel { union in_addr_union remote; Ip6TnlMode ip6tnl_mode; + IPv6FlowLabel ipv6_flowlabel; bool pmtudisc; + bool copy_dscp; }; extern const NetDevVTable ipip_vtable; @@ -70,3 +78,23 @@ int config_parse_ip6tnl_mode(const char *unit, const char *filename, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); + +int config_parse_tunnel_address(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); + +const char *ipv6_flowlabel_to_string(IPv6FlowLabel d) _const_; +IPv6FlowLabel ipv6_flowlabel_from_string(const char *d) _pure_; + +int config_parse_ipv6_flowlabel(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); diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c index 378312f091..ba84e802fc 100644 --- a/src/network/networkd-netdev-tuntap.c +++ b/src/network/networkd-netdev-tuntap.c @@ -51,6 +51,9 @@ static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) { if (t->multi_queue) ifr->ifr_flags |= IFF_MULTI_QUEUE; + if (t->vnet_hdr) + ifr->ifr_flags |= IFF_VNET_HDR; + strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1); return 0; diff --git a/src/network/networkd-netdev-tuntap.h b/src/network/networkd-netdev-tuntap.h index b804875bbb..29f8bb0ea5 100644 --- a/src/network/networkd-netdev-tuntap.h +++ b/src/network/networkd-netdev-tuntap.h @@ -33,6 +33,7 @@ struct TunTap { bool one_queue; bool multi_queue; bool packet_info; + bool vnet_hdr; }; extern const NetDevVTable tun_vtable; diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h index fe5254e91f..e7d1306f13 100644 --- a/src/network/networkd-netdev-vxlan.h +++ b/src/network/networkd-netdev-vxlan.h @@ -53,3 +53,14 @@ struct VxLan { }; extern const NetDevVTable vxlan_vtable; + +int config_parse_vxlan_group_address(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); diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index ece9ecc251..6949b403c8 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -92,10 +92,11 @@ static void netdev_cancel_callbacks(NetDev *netdev) { assert(netdev->manager); assert(netdev->manager->rtnl); - callback->callback(netdev->manager->rtnl, m, link); + callback->callback(netdev->manager->rtnl, m, callback->link); } LIST_REMOVE(callbacks, netdev->callbacks, callback); + link_unref(callback->link); free(callback); } } @@ -177,6 +178,8 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) { static int netdev_enter_failed(NetDev *netdev) { netdev->state = NETDEV_STATE_FAILED; + netdev_cancel_callbacks(netdev); + return 0; } @@ -266,12 +269,20 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call int r; assert(netdev); + assert(netdev->manager); + assert(netdev->manager->rtnl); assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND)); if (netdev->state == NETDEV_STATE_READY) { r = netdev_enslave_ready(netdev, link, callback); if (r < 0) return r; + } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) { + _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL; + + r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m); + if (r >= 0) + callback(netdev->manager->rtnl, m, link); } else { /* the netdev is not yet read, save this request for when it is */ netdev_join_callback *cb; diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c index b5f8f5cfb2..5717a15327 100644 --- a/src/network/networkd-network-bus.c +++ b/src/network/networkd-network-bus.c @@ -53,11 +53,7 @@ static int property_get_ether_addrs( return r; } - r = sd_bus_message_close_container(reply); - if (r < 0) - return r; - - return 1; + return sd_bus_message_close_container(reply); } const sd_bus_vtable network_vtable[] = { diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index b05bc949f2..83224d7109 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -15,69 +15,76 @@ struct ConfigPerfItem; %struct-type %includes %% -Match.MACAddress, config_parse_hwaddr, 0, offsetof(Network, match_mac) -Match.Path, config_parse_strv, 0, offsetof(Network, match_path) -Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver) -Match.Type, config_parse_strv, 0, offsetof(Network, match_type) -Match.Name, config_parse_ifnames, 0, offsetof(Network, match_name) -Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, match_host) -Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, match_virt) -Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel) -Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch) -Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac) -Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu) -Network.Description, config_parse_string, 0, offsetof(Network, description) -Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge) -Network.Bond, config_parse_netdev, 0, offsetof(Network, bond) -Network.VLAN, config_parse_netdev, 0, 0 -Network.MACVLAN, config_parse_netdev, 0, 0 -Network.IPVLAN, config_parse_netdev, 0, 0 -Network.VXLAN, config_parse_netdev, 0, 0 -Network.Tunnel, config_parse_tunnel, 0, 0 -Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp) -Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server) -Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local) -Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route) -Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token) -Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp) -Network.Address, config_parse_address, 0, 0 -Network.Gateway, config_parse_gateway, 0, 0 -Network.Domains, config_parse_domains, 0, offsetof(Network, domains) -Network.DNS, config_parse_strv, 0, offsetof(Network, dns) -Network.LLMNR, config_parse_llmnr, 0, offsetof(Network, llmnr) -Network.NTP, config_parse_strv, 0, offsetof(Network, ntp) -Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward) -Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade) -Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier) -Address.Address, config_parse_address, 0, 0 -Address.Peer, config_parse_address, 0, 0 -Address.Broadcast, config_parse_broadcast, 0, 0 -Address.Label, config_parse_label, 0, 0 -Route.Gateway, config_parse_gateway, 0, 0 -Route.Destination, config_parse_destination, 0, 0 -Route.Source, config_parse_destination, 0, 0 -Route.Metric, config_parse_route_priority, 0, 0 -Route.Scope, config_parse_route_scope, 0, 0 -DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) -DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns) -DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp) -DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu) -DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname) -DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains) -DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes) -DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost) -DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast) -DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) -DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) -DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) -Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost) -BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0 -BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0 +Match.MACAddress, config_parse_hwaddr, 0, offsetof(Network, match_mac) +Match.Path, config_parse_strv, 0, offsetof(Network, match_path) +Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver) +Match.Type, config_parse_strv, 0, offsetof(Network, match_type) +Match.Name, config_parse_ifnames, 0, offsetof(Network, match_name) +Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, match_host) +Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, match_virt) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel) +Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch) +Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac) +Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu) +Network.Description, config_parse_string, 0, offsetof(Network, description) +Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge) +Network.Bond, config_parse_netdev, 0, offsetof(Network, bond) +Network.VLAN, config_parse_netdev, 0, 0 +Network.MACVLAN, config_parse_netdev, 0, 0 +Network.IPVLAN, config_parse_netdev, 0, 0 +Network.VXLAN, config_parse_netdev, 0, 0 +Network.Tunnel, config_parse_tunnel, 0, 0 +Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp) +Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server) +Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local) +Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route) +Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token) +Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp) +Network.Address, config_parse_address, 0, 0 +Network.Gateway, config_parse_gateway, 0, 0 +Network.Domains, config_parse_domains, 0, offsetof(Network, domains) +Network.DNS, config_parse_strv, 0, offsetof(Network, dns) +Network.LLMNR, config_parse_llmnr, 0, offsetof(Network, llmnr) +Network.NTP, config_parse_strv, 0, offsetof(Network, ntp) +Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward) +Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade) +Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions) +Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier) +Address.Address, config_parse_address, 0, 0 +Address.Peer, config_parse_address, 0, 0 +Address.Broadcast, config_parse_broadcast, 0, 0 +Address.Label, config_parse_label, 0, 0 +Route.Gateway, config_parse_gateway, 0, 0 +Route.Destination, config_parse_destination, 0, 0 +Route.Source, config_parse_destination, 0, 0 +Route.Metric, config_parse_route_priority, 0, 0 +Route.Scope, config_parse_route_scope, 0, 0 +DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) +DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns) +DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp) +DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu) +DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname) +DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains) +DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes) +DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost) +DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, hostname) +DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast) +DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) +DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) +DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) +Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost) +Bridge.UseBPDU, config_parse_bool, 0, offsetof(Network, use_bpdu) +Bridge.HairPin, config_parse_bool, 0, offsetof(Network, hairpin) +Bridge.FastLeave, config_parse_bool, 0, offsetof(Network, fast_leave) +Bridge.AllowPortToBeRoot, config_parse_bool, 0, offsetof(Network, allow_port_to_be_root) +Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood) +BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0 +BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0 /* backwards compatibility: do not add new entries to this section */ -Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) -DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns) -DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu) -DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname) -DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains) -DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains) -DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) +Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) +DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns) +DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu) +DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname) +DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains) +DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains) +DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index ec95c8661e..d8f42621af 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -107,10 +107,16 @@ static int network_load_one(Manager *manager, const char *filename) { network->dhcp_route_metric = DHCP_ROUTE_METRIC; network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID; + network->use_bpdu = true; + network->allow_port_to_be_root = true; + network->unicast_flood = true; + network->llmnr = LLMNR_SUPPORT_YES; network->link_local = ADDRESS_FAMILY_IPV6; + network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO; + r = config_parse(NULL, filename, file, "Match\0" "Link\0" @@ -205,6 +211,7 @@ void network_free(Network *network) { free(network->description); free(network->dhcp_vendor_class_identifier); + free(network->hostname); free(network->mac); @@ -751,3 +758,94 @@ int config_parse_address_family_boolean_with_kernel( return 0; } + +static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = { + [IPV6_PRIVACY_EXTENSIONS_NO] = "no", + [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", + [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions); + +int config_parse_ipv6_privacy_extensions( + 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) { + + IPv6PrivacyExtensions *ipv6_privacy_extensions = data; + int k; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(ipv6_privacy_extensions); + + /* Our enum shall be a superset of booleans, hence first try + * to parse as boolean, and then as enum */ + + k = parse_boolean(rvalue); + if (k > 0) + *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES; + else if (k == 0) + *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO; + else { + IPv6PrivacyExtensions s; + + s = ipv6_privacy_extensions_from_string(rvalue); + if (s < 0) { + + if (streq(rvalue, "kernel")) + s = _IPV6_PRIVACY_EXTENSIONS_INVALID; + else { + log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue); + return 0; + } + } + + *ipv6_privacy_extensions = s; + } + + return 0; +} + +int config_parse_hostname(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) { + char **hostname = data; + char *hn = NULL; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = config_parse_string(unit, filename, line, section, section_line, + lvalue, ltype, rvalue, &hn, userdata); + if (r < 0) + return r; + + if (!hostname_is_valid(hn)) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "hostname is not valid, ignoring assignment: %s", rvalue); + + free(hn); + return 0; + } + + *hostname = hn; + + return 0; +} diff --git a/src/network/networkd-wait-online.c b/src/network/networkd-wait-online.c index 32c31fdf3d..d958b48771 100644 --- a/src/network/networkd-wait-online.c +++ b/src/network/networkd-wait-online.c @@ -66,7 +66,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "+hiq", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "+hi:q", options, NULL)) >= 0) switch (c) { diff --git a/src/network/networkd.c b/src/network/networkd.c index 9fe8a5fa15..e6259043fa 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) { r = manager_rtnl_enumerate_addresses(m); if (r < 0) { - log_error_errno(r, "Could not enumerate links: %m"); + log_error_errno(r, "Could not enumerate addresses: %m"); goto out; } diff --git a/src/network/networkd.h b/src/network/networkd.h index ac6e2c8a8e..a285a4b08f 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -90,6 +90,15 @@ typedef enum DCHPClientIdentifier { _DHCP_CLIENT_ID_INVALID = -1, } DCHPClientIdentifier; +typedef enum IPv6PrivacyExtensions { + /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ + IPV6_PRIVACY_EXTENSIONS_NO, + IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC, + IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ + _IPV6_PRIVACY_EXTENSIONS_MAX, + _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, +} IPv6PrivacyExtensions; + struct FdbEntry { Network *network; unsigned section; @@ -124,6 +133,7 @@ struct Network { AddressFamilyBoolean dhcp; DCHPClientIdentifier dhcp_client_identifier; char *dhcp_vendor_class_identifier; + char *hostname; bool dhcp_dns; bool dhcp_ntp; bool dhcp_mtu; @@ -140,11 +150,18 @@ struct Network { bool dhcp_server; + bool use_bpdu; + bool hairpin; + bool fast_leave; + bool allow_port_to_be_root; + bool unicast_flood; unsigned cost; AddressFamilyBoolean ip_forward; bool ip_masquerade; + IPv6PrivacyExtensions ipv6_privacy_extensions; + struct ether_addr *mac; unsigned mtu; @@ -308,28 +325,6 @@ int config_parse_tunnel(const char *unit, void *data, void *userdata); -int config_parse_tunnel_address(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); - -int config_parse_vxlan_group_address(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); - extern const sd_bus_vtable network_vtable[]; int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); @@ -455,3 +450,14 @@ int config_parse_address_family_boolean_with_kernel(const char *unit, const char const char* link_operstate_to_string(LinkOperationalState s) _const_; LinkOperationalState link_operstate_from_string(const char *s) _pure_; + +/* IPv6 privacy extensions support */ + +const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; +IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; + +int config_parse_ipv6_privacy_extensions(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); + + +/* Hostname */ +int config_parse_hostname(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); |