diff options
Diffstat (limited to 'src')
35 files changed, 537 insertions, 164 deletions
diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c index 1447fa84aa..aa7ccd1afd 100644 --- a/src/basic/in-addr-util.c +++ b/src/basic/in-addr-util.c @@ -20,12 +20,14 @@ #include <arpa/inet.h> #include <endian.h> #include <errno.h> +#include <net/if.h> #include <stdint.h> #include <stdlib.h> #include "alloc-util.h" #include "in-addr-util.h" #include "macro.h" +#include "parse-util.h" #include "util.h" bool in4_addr_is_null(const struct in_addr *a) { @@ -232,6 +234,48 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) { return 0; } +int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { + size_t l; + char *x; + int r; + + assert(u); + assert(ret); + + /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly + * handle IPv6 link-local addresses. */ + + if (family != AF_INET6) + goto fallback; + if (ifindex <= 0) + goto fallback; + + r = in_addr_is_link_local(family, u); + if (r < 0) + return r; + if (r == 0) + goto fallback; + + l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1; + x = new(char, l); + if (!x) + return -ENOMEM; + + errno = 0; + if (!inet_ntop(family, u, x, l)) { + free(x); + return errno > 0 ? -errno : -EINVAL; + } + + sprintf(strchr(x, 0), "%%%i", ifindex); + *ret = x; + + return 0; + +fallback: + return in_addr_to_string(family, u, ret); +} + int in_addr_from_string(int family, const char *s, union in_addr_union *ret) { assert(s); @@ -269,6 +313,47 @@ int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *re return -EINVAL; } +int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) { + const char *suffix; + int r, ifi = 0; + + assert(s); + assert(family); + assert(ret); + + /* Similar to in_addr_from_string_auto() but also parses an optionally appended IPv6 zone suffix ("scope id") + * if one is found. */ + + suffix = strchr(s, '%'); + if (suffix) { + + if (ifindex) { + /* If we shall return the interface index, try to parse it */ + r = parse_ifindex(suffix + 1, &ifi); + if (r < 0) { + unsigned u; + + u = if_nametoindex(suffix + 1); + if (u <= 0) + return -errno; + + ifi = (int) u; + } + } + + s = strndupa(s, suffix - s); + } + + r = in_addr_from_string_auto(s, family, ret); + if (r < 0) + return r; + + if (ifindex) + *ifindex = ifi; + + return r; +} + unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr) { assert(addr); diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h index 62cc1e1aa4..d60064aef8 100644 --- a/src/basic/in-addr-util.h +++ b/src/basic/in-addr-util.h @@ -46,8 +46,10 @@ int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_ int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen); int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen); int in_addr_to_string(int family, const union in_addr_union *u, char **ret); +int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret); int in_addr_from_string(int family, const char *s, union in_addr_union *ret); int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *ret); +int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex); unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr); struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen); int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen); diff --git a/src/core/execute.c b/src/core/execute.c index 2cef70e668..e718c43df9 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -552,6 +552,10 @@ static int chown_terminal(int fd, uid_t uid) { assert(fd >= 0); + /* Before we chown/chmod the TTY, let's ensure this is actually a tty */ + if (isatty(fd) < 1) + return 0; + /* This might fail. What matters are the results. */ (void) fchown(fd, uid, -1); (void) fchmod(fd, TTY_MODE); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index b53301a147..2d8f6296c8 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -3743,7 +3743,7 @@ static int merge_by_names(Unit **u, Set *names, const char *id) { /* If the symlink name we are looking at is unit template, then we must search for instance of this template */ - if (unit_name_is_valid(k, UNIT_NAME_TEMPLATE)) { + if (unit_name_is_valid(k, UNIT_NAME_TEMPLATE) && (*u)->instance) { _cleanup_free_ char *instance = NULL; r = unit_name_replace_instance(k, (*u)->instance, &instance); diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index 1160dacdf1..e12cd93d1c 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -29,7 +29,9 @@ #include "fs-util.h" #include "hwdb-internal.h" #include "hwdb-util.h" +#include "label.h" #include "mkdir.h" +#include "selinux-util.h" #include "strbuf.h" #include "string-util.h" #include "strv.h" @@ -643,12 +645,12 @@ static int hwdb_update(int argc, char *argv[], void *userdata) { if (!hwdb_bin) return -ENOMEM; - mkdir_parents(hwdb_bin, 0755); + mkdir_parents_label(hwdb_bin, 0755); r = trie_store(trie, hwdb_bin); if (r < 0) return log_error_errno(r, "Failure writing database %s: %m", hwdb_bin); - return 0; + return label_fix(hwdb_bin, false, false); } static void help(void) { @@ -732,6 +734,8 @@ int main (int argc, char *argv[]) { if (r <= 0) goto finish; + mac_selinux_init(); + r = hwdb_main(argc, argv); finish: diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c index 91701405a5..43114eb825 100644 --- a/src/libsystemd/sd-netlink/sd-netlink.c +++ b/src/libsystemd/sd-netlink/sd-netlink.c @@ -144,7 +144,10 @@ int sd_netlink_open(sd_netlink **ret) { return 0; } -int sd_netlink_inc_rcvbuf(const sd_netlink *const rtnl, const int size) { +int sd_netlink_inc_rcvbuf(sd_netlink *rtnl, size_t size) { + assert_return(rtnl, -EINVAL); + assert_return(!rtnl_pid_changed(rtnl), -ECHILD); + return fd_inc_rcvbuf(rtnl->fd, size); } diff --git a/src/login/logind-action.c b/src/login/logind-action.c index 9a8089f97c..8ef48dbaa1 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -85,7 +85,7 @@ int manager_handle_action( } /* If the key handling is inhibited, don't do anything */ - if (inhibit_key > 0) { + if (!ignore_inhibited && inhibit_key > 0) { if (manager_is_inhibited(m, inhibit_key, INHIBIT_BLOCK, NULL, true, false, 0, NULL)) { log_debug("Refusing operation, %s is inhibited.", inhibit_what_to_string(inhibit_key)); return 0; @@ -124,7 +124,7 @@ int manager_handle_action( return -EALREADY; } - inhibit_operation = handle == HANDLE_SUSPEND || handle == HANDLE_HIBERNATE || handle == HANDLE_HYBRID_SLEEP ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN; + inhibit_operation = IN_SET(handle, HANDLE_SUSPEND, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP) ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN; /* If the actual operation is inhibited, warn and fail */ if (!ignore_inhibited && diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 367c340e08..5498e352d8 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -32,6 +32,9 @@ #include "utf8.h" #include "util.h" +#define ADDRESSES_PER_LINK_MAX 2048U +#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U + int address_new(Address **ret) { _cleanup_address_free_ Address *address = NULL; @@ -54,6 +57,9 @@ int address_new_static(Network *network, unsigned section, Address **ret) { _cleanup_address_free_ Address *address = NULL; int r; + assert(network); + assert(ret); + if (section) { address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section)); if (address) { @@ -64,18 +70,21 @@ int address_new_static(Network *network, unsigned section, Address **ret) { } } + if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX) + return -E2BIG; + r = address_new(&address); if (r < 0) return r; if (section) { address->section = section; - hashmap_put(network->addresses_by_section, - UINT_TO_PTR(address->section), address); + hashmap_put(network->addresses_by_section, UINT_TO_PTR(address->section), address); } address->network = network; LIST_APPEND(addresses, network->static_addresses, address); + network->n_static_addresses++; *ret = address; address = NULL; @@ -89,10 +98,11 @@ void address_free(Address *address) { if (address->network) { LIST_REMOVE(addresses, address->network->static_addresses, address); + assert(address->network->n_static_addresses > 0); + address->network->n_static_addresses--; if (address->section) - hashmap_remove(address->network->addresses_by_section, - UINT_TO_PTR(address->section)); + hashmap_remove(address->network->addresses_by_section, UINT_TO_PTR(address->section)); } if (address->link) { @@ -328,7 +338,12 @@ static int address_release(Address *address) { return 0; } -int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo) { +int address_update( + Address *address, + unsigned char flags, + unsigned char scope, + const struct ifa_cacheinfo *cinfo) { + bool ready; int r; @@ -383,31 +398,38 @@ int address_drop(Address *address) { return 0; } -int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { - Address address = {}, *existing; +int address_get(Link *link, + int family, + const union in_addr_union *in_addr, + unsigned char prefixlen, + Address **ret) { + + Address address, *existing; assert(link); assert(in_addr); - assert(ret); - address.family = family; - address.in_addr = *in_addr; - address.prefixlen = prefixlen; + address = (Address) { + .family = family, + .in_addr = *in_addr, + .prefixlen = prefixlen, + }; existing = set_get(link->addresses, &address); if (existing) { - *ret = existing; - + if (ret) + *ret = existing; return 1; - } else { - existing = set_get(link->addresses_foreign, &address); - if (!existing) - return -ENOENT; } - *ret = existing; + existing = set_get(link->addresses_foreign, &address); + if (existing) { + if (ret) + *ret = existing; + return 0; + } - return 0; + return -ENOENT; } int address_remove( @@ -509,7 +531,12 @@ static int address_acquire(Link *link, Address *original, Address **ret) { return 0; } -int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update) { +int address_configure( + Address *address, + Link *link, + sd_netlink_message_handler_t callback, + bool update) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -520,6 +547,11 @@ int address_configure(Address *address, Link *link, sd_netlink_message_handler_t assert(link->manager); assert(link->manager->rtnl); + /* If this is a new address, then refuse adding more than the limit */ + if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 && + set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX) + return -E2BIG; + r = address_acquire(link, address, &address); if (r < 0) return r; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 784ab18b27..03c4bea7c6 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -63,7 +63,7 @@ void address_free(Address *address); int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); -int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo); +int address_update(Address *address, unsigned char flags, unsigned char scope, const struct ifa_cacheinfo *cinfo); int address_drop(Address *address); int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update); int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback); diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 241f486211..9829438ba2 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -27,14 +27,19 @@ #include "networkd.h" #include "util.h" +#define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U + /* create a new FDB entry or get an existing one. */ -int fdb_entry_new_static(Network *const network, - const unsigned section, - FdbEntry **ret) { +int fdb_entry_new_static( + Network *network, + unsigned section, + FdbEntry **ret) { + _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; struct ether_addr *mac_addr = NULL; assert(network); + assert(ret); /* search entry in hashmap first. */ if (section) { @@ -47,6 +52,9 @@ int fdb_entry_new_static(Network *const network, } } + if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX) + return -E2BIG; + /* allocate space for MAC address. */ mac_addr = new0(struct ether_addr, 1); if (!mac_addr) @@ -54,7 +62,6 @@ int fdb_entry_new_static(Network *const network, /* allocate space for and FDB entry. */ fdb_entry = new0(FdbEntry, 1); - if (!fdb_entry) { /* free previously allocated space for mac_addr. */ free(mac_addr); @@ -66,6 +73,7 @@ int fdb_entry_new_static(Network *const network, fdb_entry->mac_addr = mac_addr; LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry); + network->n_static_fdb_entries++; if (section) { fdb_entry->section = section; @@ -94,7 +102,7 @@ static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda } /* send a request to the kernel to add a FDB entry in its static MAC table. */ -int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry) { +int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; sd_netlink *rtnl; int r; @@ -145,12 +153,13 @@ void fdb_entry_free(FdbEntry *fdb_entry) { return; if (fdb_entry->network) { - LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, - fdb_entry); + LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry); + + assert(fdb_entry->network->n_static_fdb_entries > 0); + fdb_entry->network->n_static_fdb_entries--; if (fdb_entry->section) - hashmap_remove(fdb_entry->network->fdb_entries_by_section, - UINT_TO_PTR(fdb_entry->section)); + hashmap_remove(fdb_entry->network->fdb_entries_by_section, UINT_TO_PTR(fdb_entry->section)); } free(fdb_entry->mac_addr); diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h index 84410714f5..2d7d28735c 100644 --- a/src/network/networkd-fdb.h +++ b/src/network/networkd-fdb.h @@ -36,9 +36,9 @@ struct FdbEntry { LIST_FIELDS(FdbEntry, static_fdb_entries); }; -int fdb_entry_new_static(Network *const network, const unsigned section, FdbEntry **ret); +int fdb_entry_new_static(Network *network, unsigned section, FdbEntry **ret); void fdb_entry_free(FdbEntry *fdb_entry); -int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry); +int fdb_entry_configure(Link *link, FdbEntry *fdb_entry); DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free); #define _cleanup_fdbentry_free_ _cleanup_(fdb_entry_freep) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 11628339b9..6746d88fc8 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1096,7 +1096,7 @@ int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *u return 1; } -static int link_set_bridge_fdb(Link *const link) { +static int link_set_bridge_fdb(Link *link) { FdbEntry *fdb_entry; int r = 0; @@ -1111,7 +1111,7 @@ static int link_set_bridge_fdb(Link *const link) { return r; } -static int link_set_proxy_arp(Link *const link) { +static int link_set_proxy_arp(Link *link) { const char *p = NULL; int r; diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index adc64977b9..a9512cd77b 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -3,6 +3,7 @@ #include "conf-parser.h" #include "network-internal.h" #include "networkd-netdev-bond.h" +#include "networkd-netdev-bridge.h" #include "networkd-netdev-ipvlan.h" #include "networkd-netdev-macvlan.h" #include "networkd-netdev-tunnel.h" @@ -10,8 +11,8 @@ #include "networkd-netdev-veth.h" #include "networkd-netdev-vlan.h" #include "networkd-netdev-vxlan.h" -#include "networkd-netdev-bridge.h" #include "networkd-netdev.h" +#include "vlan-util.h" %} struct ConfigPerfItem; %null_strings @@ -33,7 +34,7 @@ NetDev.Name, config_parse_ifname, 0, NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind) NetDev.MTUBytes, config_parse_iec_size, 0, offsetof(NetDev, mtu) NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac) -VLAN.Id, config_parse_uint64, 0, offsetof(VLan, id) +VLAN.Id, config_parse_vlanid, 0, offsetof(VLan, id) MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) diff --git a/src/network/networkd-netdev-vlan.c b/src/network/networkd-netdev-vlan.c index b1f4714afa..3cc072388f 100644 --- a/src/network/networkd-netdev-vlan.c +++ b/src/network/networkd-netdev-vlan.c @@ -20,6 +20,7 @@ #include <net/if.h> #include "networkd-netdev-vlan.h" +#include "vlan-util.h" static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { VLan *v; @@ -33,11 +34,9 @@ static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlin assert(v); - if (v->id <= VLANID_MAX) { - r = sd_netlink_message_append_u16(req, IFLA_VLAN_ID, v->id); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_ID attribute: %m"); - } + r = sd_netlink_message_append_u16(req, IFLA_VLAN_ID, v->id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_ID attribute: %m"); return 0; } @@ -52,8 +51,8 @@ static int netdev_vlan_verify(NetDev *netdev, const char *filename) { assert(v); - if (v->id > VLANID_MAX) { - log_warning("VLAN without valid Id (%"PRIu64") configured in %s. Ignoring", v->id, filename); + if (v->id == VLANID_INVALID) { + log_warning("VLAN without valid Id (%"PRIu16") configured in %s.", v->id, filename); return -EINVAL; } @@ -66,7 +65,7 @@ static void vlan_init(NetDev *netdev) { assert(netdev); assert(v); - v->id = VLANID_MAX + 1; + v->id = VLANID_INVALID; } const NetDevVTable vlan_vtable = { diff --git a/src/network/networkd-netdev-vlan.h b/src/network/networkd-netdev-vlan.h index 73aacf4a0f..2dfe314b6e 100644 --- a/src/network/networkd-netdev-vlan.h +++ b/src/network/networkd-netdev-vlan.h @@ -23,12 +23,10 @@ typedef struct VLan VLan; #include "networkd-netdev.h" -#define VLANID_MAX 4094 - struct VLan { NetDev meta; - uint64_t id; + uint16_t id; }; DEFINE_NETDEV_CAST(VLAN, VLan); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index b54616b838..a49748d1b1 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -172,6 +172,10 @@ struct Network { LIST_HEAD(Route, static_routes); LIST_HEAD(FdbEntry, static_fdb_entries); + unsigned n_static_addresses; + unsigned n_static_routes; + unsigned n_static_fdb_entries; + Hashmap *addresses_by_section; Hashmap *routes_by_section; Hashmap *fdb_entries_by_section; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index f001de772a..6359f967a2 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -28,6 +28,9 @@ #include "string-util.h" #include "util.h" +#define ROUTES_PER_LINK_MAX 2048U +#define STATIC_ROUTES_PER_NETWORK_MAX 1024U + int route_new(Route **ret) { _cleanup_route_free_ Route *route = NULL; @@ -51,6 +54,9 @@ int route_new_static(Network *network, unsigned section, Route **ret) { _cleanup_route_free_ Route *route = NULL; int r; + assert(network); + assert(ret); + if (section) { route = hashmap_get(network->routes_by_section, UINT_TO_PTR(section)); if (route) { @@ -61,6 +67,9 @@ int route_new_static(Network *network, unsigned section, Route **ret) { } } + if (network->n_static_routes >= STATIC_ROUTES_PER_NETWORK_MAX) + return -E2BIG; + r = route_new(&route); if (r < 0) return r; @@ -77,6 +86,7 @@ int route_new_static(Network *network, unsigned section, Route **ret) { route->network = network; LIST_PREPEND(routes, network->static_routes, route); + network->n_static_routes++; *ret = route; route = NULL; @@ -91,9 +101,11 @@ void route_free(Route *route) { if (route->network) { LIST_REMOVE(routes, route->network->static_routes, route); + assert(route->network->n_static_routes > 0); + route->network->n_static_routes--; + if (route->section) - hashmap_remove(route->network->routes_by_section, - UINT_TO_PTR(route->section)); + hashmap_remove(route->network->routes_by_section, UINT_TO_PTR(route->section)); } if (route->link) { @@ -176,48 +188,55 @@ static const struct hash_ops route_hash_ops = { int route_get(Link *link, int family, - union in_addr_union *dst, + const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret) { - Route route = { + + Route route, *existing; + + assert(link); + assert(dst); + + route = (Route) { .family = family, + .dst = *dst, .dst_prefixlen = dst_prefixlen, .tos = tos, .priority = priority, .table = table, - }, *existing; - - assert(link); - assert(dst); - assert(ret); - - route.dst = *dst; + }; existing = set_get(link->routes, &route); if (existing) { - *ret = existing; + if (ret) + *ret = existing; return 1; - } else { - existing = set_get(link->routes_foreign, &route); - if (!existing) - return -ENOENT; } - *ret = existing; + existing = set_get(link->routes_foreign, &route); + if (existing) { + if (ret) + *ret = existing; + return 0; + } - return 0; + return -ENOENT; } -static int route_add_internal(Link *link, Set **routes, - int family, - union in_addr_union *dst, - unsigned char dst_prefixlen, - unsigned char tos, - uint32_t priority, - unsigned char table, Route **ret) { +static int route_add_internal( + Link *link, + Set **routes, + int family, + const union in_addr_union *dst, + unsigned char dst_prefixlen, + unsigned char tos, + uint32_t priority, + unsigned char table, + Route **ret) { + _cleanup_route_free_ Route *route = NULL; int r; @@ -254,23 +273,29 @@ static int route_add_internal(Link *link, Set **routes, return 0; } -int route_add_foreign(Link *link, - int family, - union in_addr_union *dst, - unsigned char dst_prefixlen, - unsigned char tos, - uint32_t priority, - unsigned char table, Route **ret) { +int route_add_foreign( + Link *link, + int family, + const union in_addr_union *dst, + unsigned char dst_prefixlen, + unsigned char tos, + uint32_t priority, + unsigned char table, + Route **ret) { + return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, tos, priority, table, ret); } -int route_add(Link *link, +int route_add( + Link *link, int family, - union in_addr_union *dst, + const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, - unsigned char table, Route **ret) { + unsigned char table, + Route **ret) { + Route *route; int r; @@ -303,12 +328,13 @@ int route_add(Link *link, } int route_update(Route *route, - union in_addr_union *src, + const union in_addr_union *src, unsigned char src_prefixlen, - union in_addr_union *gw, - union in_addr_union *prefsrc, + const union in_addr_union *gw, + const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol) { + assert(route); assert(src); assert(gw); @@ -449,8 +475,11 @@ int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { return 1; } -int route_configure(Route *route, Link *link, - sd_netlink_message_handler_t callback) { +int route_configure( + Route *route, + Link *link, + sd_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; usec_t lifetime; @@ -462,6 +491,10 @@ int route_configure(Route *route, Link *link, assert(link->ifindex > 0); assert(route->family == AF_INET || route->family == AF_INET6); + if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 && + set_size(route->link->routes) >= ROUTES_PER_LINK_MAX) + return -E2BIG; + r = sd_rtnl_message_new_route(link->manager->rtnl, &req, RTM_NEWROUTE, route->family, route->protocol); diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 39de8363ed..d4e4dbac0b 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -57,10 +57,10 @@ void route_free(Route *route); int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback); int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback); -int route_get(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); -int route_add(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); -int route_add_foreign(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); -int route_update(Route *route, union in_addr_union *src, unsigned char src_prefixlen, union in_addr_union *gw, union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol); +int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); +int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); +int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); +int route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol); int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata); diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index 33f7c61557..6d4e5746f7 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -1221,7 +1221,7 @@ int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex return r; if (with_ifindex) { - r = sd_bus_message_append(reply, "i", s->link ? s->link->ifindex : 0); + r = sd_bus_message_append(reply, "i", dns_server_ifindex(s)); if (r < 0) return r; } diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 990dc03b60..fecf7ecccf 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -27,18 +27,18 @@ int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { union in_addr_union address; - int family, r; + int family, r, ifindex = 0; DnsServer *s; assert(m); assert(word); - r = in_addr_from_string_auto(word, &family, &address); + r = in_addr_ifindex_from_string_auto(word, &family, &address, &ifindex); if (r < 0) return r; /* Filter out duplicates */ - s = dns_server_find(manager_get_first_dns_server(m, type), family, &address); + s = dns_server_find(manager_get_first_dns_server(m, type), family, &address, ifindex); if (s) { /* * Drop the marker. This is used to find the servers @@ -50,7 +50,7 @@ int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char return 0; } - return dns_server_new(m, NULL, type, NULL, family, &address); + return dns_server_new(m, NULL, type, NULL, family, &address, ifindex); } int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) { @@ -70,7 +70,7 @@ int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, con r = manager_add_dns_server_by_string(m, type, word); if (r < 0) - log_warning_errno(r, "Failed to add DNS server address '%s', ignoring.", word); + log_warning_errno(r, "Failed to add DNS server address '%s', ignoring: %m", word); } return 0; @@ -125,7 +125,7 @@ int manager_parse_search_domains_and_warn(Manager *m, const char *string) { r = manager_add_search_domain_by_string(m, word); if (r < 0) - log_warning_errno(r, "Failed to add search domain '%s', ignoring.", word); + log_warning_errno(r, "Failed to add search domain '%s', ignoring: %m", word); } return 0; diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 66e4585c18..6a69d7b7c2 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -307,7 +307,7 @@ static int dns_scope_socket( union sockaddr_union sa = {}; socklen_t salen; static const int one = 1; - int ret, r; + int ret, r, ifindex; assert(s); @@ -315,6 +315,8 @@ static int dns_scope_socket( assert(family == AF_UNSPEC); assert(!address); + ifindex = dns_server_ifindex(server); + sa.sa.sa_family = server->family; if (server->family == AF_INET) { sa.in.sin_port = htobe16(port); @@ -323,7 +325,7 @@ static int dns_scope_socket( } else if (server->family == AF_INET6) { sa.in6.sin6_port = htobe16(port); sa.in6.sin6_addr = server->address.in6; - sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0; + sa.in6.sin6_scope_id = ifindex; salen = sizeof(sa.in6); } else return -EAFNOSUPPORT; @@ -332,6 +334,7 @@ static int dns_scope_socket( assert(address); sa.sa.sa_family = family; + ifindex = s->link ? s->link->ifindex : 0; if (family == AF_INET) { sa.in.sin_port = htobe16(port); @@ -340,7 +343,7 @@ static int dns_scope_socket( } else if (family == AF_INET6) { sa.in6.sin6_port = htobe16(port); sa.in6.sin6_addr = address->in6; - sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0; + sa.in6.sin6_scope_id = ifindex; salen = sizeof(sa.in6); } else return -EAFNOSUPPORT; @@ -357,14 +360,14 @@ static int dns_scope_socket( } if (s->link) { - uint32_t ifindex = htobe32(s->link->ifindex); + be32_t ifindex_be = htobe32(ifindex); if (sa.sa.sa_family == AF_INET) { - r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)); + r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)); if (r < 0) return -errno; } else if (sa.sa.sa_family == AF_INET6) { - r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex)); + r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)); if (r < 0) return -errno; } diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 3095c042db..5acfcb4239 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -43,7 +43,8 @@ int dns_server_new( DnsServerType type, Link *l, int family, - const union in_addr_union *in_addr) { + const union in_addr_union *in_addr, + int ifindex) { DnsServer *s; @@ -75,6 +76,7 @@ int dns_server_new( s->type = type; s->family = family; s->address = *in_addr; + s->ifindex = ifindex; s->resend_timeout = DNS_TIMEOUT_MIN_USEC; switch (type) { @@ -518,11 +520,24 @@ int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeature return dns_packet_append_opt(packet, packet_size, edns_do, NULL); } +int dns_server_ifindex(const DnsServer *s) { + assert(s); + + /* The link ifindex always takes precedence */ + if (s->link) + return s->link->ifindex; + + if (s->ifindex > 0) + return s->ifindex; + + return 0; +} + const char *dns_server_string(DnsServer *server) { assert(server); if (!server->server_string) - (void) in_addr_to_string(server->family, &server->address, &server->server_string); + (void) in_addr_ifindex_to_string(server->family, &server->address, dns_server_ifindex(server), &server->server_string); return strna(server->server_string); } @@ -571,17 +586,28 @@ static void dns_server_hash_func(const void *p, struct siphash *state) { siphash24_compress(&s->family, sizeof(s->family), state); siphash24_compress(&s->address, FAMILY_ADDRESS_SIZE(s->family), state); + siphash24_compress(&s->ifindex, sizeof(s->ifindex), state); } static int dns_server_compare_func(const void *a, const void *b) { const DnsServer *x = a, *y = b; + int r; if (x->family < y->family) return -1; if (x->family > y->family) return 1; - return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family)); + r = memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family)); + if (r != 0) + return r; + + if (x->ifindex < y->ifindex) + return -1; + if (x->ifindex > y->ifindex) + return 1; + + return 0; } const struct hash_ops dns_server_hash_ops = { @@ -623,11 +649,11 @@ void dns_server_mark_all(DnsServer *first) { dns_server_mark_all(first->servers_next); } -DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr) { +DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, int ifindex) { DnsServer *s; LIST_FOREACH(servers, s, first) - if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0) + if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0 && s->ifindex == ifindex) return s; return NULL; diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index 9f4a69c37a..463c5724a7 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -62,6 +62,7 @@ struct DnsServer { int family; union in_addr_union address; + int ifindex; /* for IPv6 link-local DNS servers */ char *server_string; @@ -101,7 +102,8 @@ int dns_server_new( DnsServerType type, Link *link, int family, - const union in_addr_union *address); + const union in_addr_union *address, + int ifindex); DnsServer* dns_server_ref(DnsServer *s); DnsServer* dns_server_unref(DnsServer *s); @@ -121,12 +123,13 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s); int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level); const char *dns_server_string(DnsServer *server); +int dns_server_ifindex(const DnsServer *s); bool dns_server_dnssec_supported(DnsServer *server); void dns_server_warn_downgrade(DnsServer *server); -DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr); +DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, int ifindex); void dns_server_unlink_all(DnsServer *first); void dns_server_unlink_marked(DnsServer *first); diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c index 7f21891819..6aff427192 100644 --- a/src/resolve/resolved-link-bus.c +++ b/src/resolve/resolved-link-bus.c @@ -23,6 +23,7 @@ #include "resolve-util.h" #include "resolved-bus.h" #include "resolved-link-bus.h" +#include "resolved-resolv-conf.h" #include "strv.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_resolve_support, resolve_support, ResolveSupport); @@ -218,11 +219,11 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ for (i = 0; i < n; i++) { DnsServer *s; - s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address); + s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address, 0); if (s) dns_server_move_back_and_unmark(s); else { - r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address); + r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address, 0); if (r < 0) goto clear; } @@ -232,6 +233,8 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ dns_server_unlink_marked(l->dns_servers); link_allocate_scopes(l); + (void) manager_write_resolv_conf(l->manager); + return sd_bus_reply_method_return(message, NULL); clear: @@ -306,6 +309,9 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_ goto clear; dns_search_domain_unlink_marked(l->search_domains); + + (void) manager_write_resolv_conf(l->manager); + return sd_bus_reply_method_return(message, NULL); clear: @@ -444,6 +450,8 @@ int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error link_allocate_scopes(l); link_add_rrs(l, false); + (void) manager_write_resolv_conf(l->manager); + return sd_bus_reply_method_return(message, NULL); } diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index b0dc65036d..b189c21920 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -216,11 +216,11 @@ static int link_update_dns_servers(Link *l) { if (r < 0) goto clear; - s = dns_server_find(l->dns_servers, family, &a); + s = dns_server_find(l->dns_servers, family, &a, 0); if (s) dns_server_move_back_and_unmark(s); else { - r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a); + r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0); if (r < 0) goto clear; } diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 9600bde1e9..8dc7891143 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -284,9 +284,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void * log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex); } - r = manager_write_resolv_conf(m); - if (r < 0) - log_warning_errno(r, "Could not update "PRIVATE_RESOLV_CONF": %m"); + (void) manager_write_resolv_conf(m); return 0; } @@ -903,7 +901,7 @@ int manager_send(Manager *m, int fd, int ifindex, int family, const union in_add if (family == AF_INET) return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p); - else if (family == AF_INET6) + if (family == AF_INET6) return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p); return -EAFNOSUPPORT; diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index fa89de4c21..ae17aef3ab 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -92,7 +92,7 @@ int manager_read_resolv_conf(Manager *m) { a = first_word(l, "nameserver"); if (a) { - r = manager_add_dns_server_by_string(m, DNS_SERVER_SYSTEM, a); + r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_SYSTEM, a); if (r < 0) log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a); @@ -149,9 +149,7 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { assert(f); assert(count); - (void) dns_server_string(s); - - if (!s->server_string) { + if (!dns_server_string(s)) { log_warning("Our of memory, or invalid DNS address. Ignoring server."); return; } @@ -160,7 +158,7 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f); (*count)++; - fprintf(f, "nameserver %s\n", s->server_string); + fprintf(f, "nameserver %s\n", dns_server_string(s)); } static void write_resolv_conf_search( @@ -227,29 +225,31 @@ int manager_write_resolv_conf(Manager *m) { assert(m); /* Read the system /etc/resolv.conf first */ - manager_read_resolv_conf(m); + (void) manager_read_resolv_conf(m); /* Add the full list to a set, to filter out duplicates */ r = manager_compile_dns_servers(m, &dns); if (r < 0) - return r; + return log_warning_errno(r, "Failed to compile list of DNS servers: %m"); r = manager_compile_search_domains(m, &domains); if (r < 0) - return r; + return log_warning_errno(r, "Failed to compile list of search domains: %m"); r = fopen_temporary_label(PRIVATE_RESOLV_CONF, PRIVATE_RESOLV_CONF, &f, &temp_path); if (r < 0) - return r; + return log_warning_errno(r, "Failed to open private resolv.conf file for writing: %m"); - fchmod(fileno(f), 0644); + (void) fchmod(fileno(f), 0644); r = write_resolv_conf_contents(f, dns, domains); - if (r < 0) + if (r < 0) { + log_error_errno(r, "Failed to write private resolv.conf contents: %m"); goto fail; + } if (rename(temp_path, PRIVATE_RESOLV_CONF) < 0) { - r = -errno; + r = log_error_errno(errno, "Failed to move private resolv.conf file into place: %m"); goto fail; } @@ -258,5 +258,6 @@ int manager_write_resolv_conf(Manager *m) { fail: (void) unlink(PRIVATE_RESOLV_CONF); (void) unlink(temp_path); + return r; } diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index 161ea03412..6cef401870 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -85,11 +85,8 @@ int main(int argc, char *argv[]) { goto finish; } - /* Write finish default resolv.conf to avoid a dangling - * symlink */ - r = manager_write_resolv_conf(m); - if (r < 0) - log_warning_errno(r, "Could not create "PRIVATE_RESOLV_CONF": %m"); + /* Write finish default resolv.conf to avoid a dangling symlink */ + (void) manager_write_resolv_conf(m); sd_notify(false, "READY=1\n" diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 4efbf3710f..8cfa936347 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1085,6 +1085,19 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ break; } + case SD_BUS_TYPE_DOUBLE: { + double d; + double *p = userdata; + + r = sd_bus_message_read_basic(m, type, &d); + if (r < 0) + break; + + *p = d; + + break; + } + default: break; } diff --git a/src/shared/vlan-util.c b/src/shared/vlan-util.c new file mode 100644 index 0000000000..78d66dd3d9 --- /dev/null +++ b/src/shared/vlan-util.c @@ -0,0 +1,69 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "vlan-util.h" +#include "parse-util.h" +#include "conf-parser.h" + +int parse_vlanid(const char *p, uint16_t *ret) { + uint16_t id; + int r; + + r = safe_atou16(p, &id); + if (r < 0) + return r; + if (!vlanid_is_valid(id)) + return -ERANGE; + + *ret = id; + return 0; +} + +int config_parse_vlanid( + 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) { + + uint16_t *id = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_vlanid(rvalue, id); + if (r == -ERANGE) { + log_syntax(unit, LOG_ERR, filename, line, r, "VLAN identifier outside of valid range 0…4094, ignoring: %s", rvalue); + return 0; + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VLAN identifier value, ignoring: %s", rvalue); + return 0; + } + + return 0; +} diff --git a/src/shared/vlan-util.h b/src/shared/vlan-util.h new file mode 100644 index 0000000000..ce6763b3a3 --- /dev/null +++ b/src/shared/vlan-util.h @@ -0,0 +1,35 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdbool.h> +#include <inttypes.h> + +#define VLANID_MAX 4094 +#define VLANID_INVALID UINT16_MAX + +/* Note that we permit VLAN Id 0 here, as that is apparently OK by the Linux kernel */ +static inline bool vlanid_is_valid(uint16_t id) { + return id <= VLANID_MAX; +} + +int parse_vlanid(const char *p, uint16_t *ret); + +int config_parse_vlanid(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/systemd/sd-netlink.h b/src/systemd/sd-netlink.h index 3ae110c080..7efa8ebe5a 100644 --- a/src/systemd/sd-netlink.h +++ b/src/systemd/sd-netlink.h @@ -43,7 +43,7 @@ typedef int (*sd_netlink_message_handler_t)(sd_netlink *nl, sd_netlink_message * int sd_netlink_new_from_netlink(sd_netlink **nl, int fd); int sd_netlink_open(sd_netlink **nl); int sd_netlink_open_fd(sd_netlink **nl, int fd); -int sd_netlink_inc_rcvbuf(const sd_netlink *const rtnl, const int size); +int sd_netlink_inc_rcvbuf(sd_netlink *nl, const size_t size); sd_netlink *sd_netlink_ref(sd_netlink *nl); sd_netlink *sd_netlink_unref(sd_netlink *nl); diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c index 4e12071e93..3ed8f23ff9 100644 --- a/src/sysv-generator/sysv-generator.c +++ b/src/sysv-generator/sysv-generator.c @@ -856,7 +856,7 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic _cleanup_free_ char *name = NULL, *fpath = NULL; int a, b; - if (de->d_name[0] != 'S' && de->d_name[0] != 'K') + if (de->d_name[0] != 'S') continue; if (strlen(de->d_name) < 4) @@ -886,28 +886,23 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic continue; } - if (de->d_name[0] == 'S') { + service->sysv_start_priority = MAX(a*10 + b, service->sysv_start_priority); - service->sysv_start_priority = MAX(a*10 + b, service->sysv_start_priority); - - r = set_ensure_allocated(&runlevel_services[i], NULL); - if (r < 0) { - log_oom(); - goto finish; - } - - r = set_put(runlevel_services[i], service); - if (r < 0) { - log_oom(); - goto finish; - } + r = set_ensure_allocated(&runlevel_services[i], NULL); + if (r < 0) { + log_oom(); + goto finish; + } + r = set_put(runlevel_services[i], service); + if (r < 0) { + log_oom(); + goto finish; } } } } - for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) SET_FOREACH(service, runlevel_services[i], j) { r = strv_extend(&service->before, rcnd_table[i].target); diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index b480fdaa9c..1a439bd0d4 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -286,6 +286,55 @@ static void test_in_addr_to_string(void) { test_in_addr_to_string_one(AF_INET6, "fe80::"); } +static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) { + _cleanup_free_ char *r = NULL; + union in_addr_union ua, uuaa; + int ff, ifindex2; + + assert_se(in_addr_from_string(f, a, &ua) >= 0); + assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0); + printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r); + assert_se(streq(b, r)); + + assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0); + assert_se(ff == f); + assert_se(in_addr_equal(f, &ua, &uuaa)); + assert_se(ifindex2 == ifindex || ifindex2 == 0); +} + +static void test_in_addr_ifindex_to_string(void) { + test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1"); + test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13"); + test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1"); +} + +static void test_in_addr_ifindex_from_string_auto(void) { + int family, ifindex; + union in_addr_union ua; + + /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */ + + assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0); + assert_se(family == AF_INET6); + assert_se(ifindex == 0); + + assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0); + assert_se(family == AF_INET6); + assert_se(ifindex == 19); + + assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0); + assert_se(family == AF_INET6); + assert_se(ifindex == LOOPBACK_IFINDEX); + + assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV); +} + static void *connect_thread(void *arg) { union sockaddr_union *sa = arg; _cleanup_close_ int fd = -1; @@ -398,6 +447,8 @@ int main(int argc, char *argv[]) { test_in_addr_prefix_intersect(); test_in_addr_prefix_next(); test_in_addr_to_string(); + test_in_addr_ifindex_to_string(); + test_in_addr_ifindex_from_string_auto(); test_nameinfo_pretty(); diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c index ed0ea5ce5f..3c58445836 100644 --- a/src/udev/udev-builtin-blkid.c +++ b/src/udev/udev-builtin-blkid.c @@ -147,11 +147,6 @@ static int find_gpt_root(struct udev_device *dev, blkid_probe pr, bool test) { if (sd_id128_equal(type, GPT_ESP)) { sd_id128_t id, esp; - unsigned long long flags; - - flags = blkid_partition_get_flags(pp); - if (flags & GPT_FLAG_NO_AUTO) - continue; /* We found an ESP, let's see if it matches * the ESP we booted from. */ @@ -167,6 +162,11 @@ static int find_gpt_root(struct udev_device *dev, blkid_probe pr, bool test) { found_esp = true; } else if (sd_id128_equal(type, GPT_ROOT_NATIVE)) { + unsigned long long flags; + + flags = blkid_partition_get_flags(pp); + if (flags & GPT_FLAG_NO_AUTO) + continue; /* We found a suitable root partition, let's * remember the first one. */ |