diff options
-rw-r--r-- | configure.ac | 9 | ||||
-rw-r--r-- | man/systemd.network.xml | 43 | ||||
-rw-r--r-- | src/basic/bitmap.c | 43 | ||||
-rw-r--r-- | src/basic/missing.h | 6 | ||||
-rw-r--r-- | src/basic/virt.c | 20 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-types.c | 3 | ||||
-rw-r--r-- | src/network/networkd-link.c | 23 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 5 | ||||
-rw-r--r-- | src/network/networkd.h | 5 | ||||
-rw-r--r-- | src/nspawn/nspawn.c | 6 | ||||
-rw-r--r-- | src/resolve/dns-type.c | 5 | ||||
-rw-r--r-- | src/resolve/dns-type.h | 1 | ||||
-rw-r--r-- | src/resolve/resolved-dns-packet.c | 202 | ||||
-rw-r--r-- | src/resolve/resolved-dns-rr.c | 14 | ||||
-rw-r--r-- | src/resolve/resolved-dns-rr.h | 7 | ||||
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 4 | ||||
-rw-r--r-- | units/systemd-networkd.service.m4.in | 2 |
17 files changed, 283 insertions, 115 deletions
diff --git a/configure.ac b/configure.ac index ff6364aba2..2fddf29f36 100644 --- a/configure.ac +++ b/configure.ac @@ -38,6 +38,11 @@ AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-di AM_SILENT_RULES([yes]) AC_CANONICAL_HOST AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.]) + +AC_CHECK_TOOLS([AR], [gcc-ar ar], [:]) +AC_CHECK_TOOLS([NM], [gcc-nm nm], [:]) +AC_CHECK_TOOLS([RANLIB], [gcc-ranlib ranlib], [:]) + LT_PREREQ(2.2) LT_INIT([disable-static]) @@ -196,7 +201,7 @@ AS_CASE([$CC], [*clang*], AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ - -flto -ffat-lto-objects])], + -flto])], [AC_MSG_RESULT([skipping -flto, optimization not enabled])]) AC_SUBST([OUR_CFLAGS], "$with_cflags $sanitizer_cflags") @@ -302,7 +307,7 @@ AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE, IFLA_IPTUN_ENCAP_DPORT, IFLA_GRE_ENCAP_DPORT, IFLA_BRIDGE_VLAN_INFO, - IFLA_BRPORT_UNICAST_FLOOD, + IFLA_BRPORT_LEARNING_SYNC, NDA_IFINDEX, IFA_FLAGS], [], [], [[ diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 90a0e8fff6..d654db4993 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -669,6 +669,48 @@ following keys.</para> <variablelist class='network-directives'> <varlistentry> + <term><varname>UnicastFlood=</varname></term> + <listitem> + <para>A boolean. UnicastFlood configures whether a given port will flood + unicast traffic for which there is no FDB entry. By default this + flag is off.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>HairPin=</varname></term> + <listitem> + <para> A boolean. Configures whether traffic may be send back + out of the port on which it was received. By default, this + flag is false. and the bridge will not forward traffic back + out of the receiving port. By default the flag is off.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>BPDUGuard=</varname></term> + <listitem> + <para> A boolean. Configures whether STP Bridge Protocol Data Units will be + processed by the bridge port. By default, the flag is false allowing BPDU + processing. Turning this flag on will cause the port to stop processing + STP Bridge Protocol Data Units. By default the flag is off.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>FastLeave=</varname></term> + <listitem> + <para> A boolean. This flag allows the bridge to immediately stop multicast + traffic on a port that receives IGMP Leave message. It is only used with + IGMP snooping if enabled on the bridge. By default the flag is off.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>RootBlock=</varname></term> + <listitem> + <para> A boolean. Configures whether a given port is allowed to + become root port or not. Only used when STP is enabled on the bridge. + By default the flag is off.</para> + </listitem> + </varlistentry> + <varlistentry> <term><varname>Cost=</varname></term> <listitem> <para>Each port in a bridge may have different speed. Cost @@ -678,7 +720,6 @@ </varlistentry> </variablelist> </refsect1> - <refsect1> <title>[BridgeFDB] Section Options</title> <para>The <literal>[BridgeFDB]</literal> section manages the diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c index 7e47c2d09f..bf9d8d4d7c 100644 --- a/src/basic/bitmap.c +++ b/src/basic/bitmap.c @@ -24,7 +24,7 @@ #include "bitmap.h" struct Bitmap { - long long unsigned *bitmaps; + uint64_t *bitmaps; size_t n_bitmaps; size_t bitmaps_allocated; }; @@ -37,9 +37,9 @@ struct Bitmap { /* This indicates that we reached the end of the bitmap */ #define BITMAP_END ((unsigned) -1) -#define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(long long unsigned) * 8)) -#define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(long long unsigned) * 8)) -#define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(long long unsigned) * 8 + (rem)) +#define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(uint64_t) * 8)) +#define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8)) +#define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem)) Bitmap *bitmap_new(void) { return new0(Bitmap, 1); @@ -56,6 +56,8 @@ void bitmap_free(Bitmap *b) { int bitmap_ensure_allocated(Bitmap **b) { Bitmap *a; + assert(b); + if (*b) return 0; @@ -69,7 +71,7 @@ int bitmap_ensure_allocated(Bitmap **b) { } int bitmap_set(Bitmap *b, unsigned n) { - long long unsigned bitmask; + uint64_t bitmask; unsigned offset; assert(b); @@ -87,7 +89,7 @@ int bitmap_set(Bitmap *b, unsigned n) { b->n_bitmaps = offset + 1; } - bitmask = 1ULL << BITMAP_NUM_TO_REM(n); + bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n); b->bitmaps[offset] |= bitmask; @@ -95,26 +97,27 @@ int bitmap_set(Bitmap *b, unsigned n) { } void bitmap_unset(Bitmap *b, unsigned n) { - long long unsigned bitmask; + uint64_t bitmask; unsigned offset; - assert(b); + if (!b) + return; offset = BITMAP_NUM_TO_OFFSET(n); if (offset >= b->n_bitmaps) return; - bitmask = 1ULL << BITMAP_NUM_TO_REM(n); + bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n); b->bitmaps[offset] &= ~bitmask; } bool bitmap_isset(Bitmap *b, unsigned n) { - long long unsigned bitmask; + uint64_t bitmask; unsigned offset; - if (!b || !b->bitmaps) + if (!b) return false; offset = BITMAP_NUM_TO_OFFSET(n); @@ -122,7 +125,7 @@ bool bitmap_isset(Bitmap *b, unsigned n) { if (offset >= b->n_bitmaps) return false; - bitmask = 1ULL << BITMAP_NUM_TO_REM(n); + bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n); return !!(b->bitmaps[offset] & bitmask); } @@ -133,7 +136,7 @@ bool bitmap_isclear(Bitmap *b) { assert(b); for (i = 0; i < b->n_bitmaps; i++) - if (b->bitmaps[i]) + if (b->bitmaps[i] != 0) return false; return true; @@ -146,15 +149,18 @@ void bitmap_clear(Bitmap *b) { } bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n) { - long long unsigned bitmask; + uint64_t bitmask; unsigned offset, rem; + assert(i); + assert(n); + if (!b || i->idx == BITMAP_END) return false; offset = BITMAP_NUM_TO_OFFSET(i->idx); rem = BITMAP_NUM_TO_REM(i->idx); - bitmask = 1ULL << rem; + bitmask = UINT64_C(1) << rem; for (; offset < b->n_bitmaps; offset ++) { if (b->bitmaps[offset]) { @@ -178,7 +184,6 @@ bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n) { } bool bitmap_equal(Bitmap *a, Bitmap *b) { - unsigned i; if (!a ^ !b) return false; @@ -189,9 +194,5 @@ bool bitmap_equal(Bitmap *a, Bitmap *b) { if (a->n_bitmaps != b->n_bitmaps) return false; - for (i = 0; i < a->n_bitmaps; i++) - if (a->bitmaps[i] != b->bitmaps[i]) - return false; - - return true; + return memcmp(a->bitmaps, b->bitmaps, sizeof(uint64_t) * a->n_bitmaps) == 0; } diff --git a/src/basic/missing.h b/src/basic/missing.h index bd49f10e76..ed6cd80c75 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -832,7 +832,7 @@ static inline int setns(int fd, int nstype) { #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) #endif -#if !HAVE_DECL_IFLA_BRPORT_UNICAST_FLOOD +#if !HAVE_DECL_IFLA_BRPORT_LEARNING_SYNC #define IFLA_BRPORT_UNSPEC 0 #define IFLA_BRPORT_STATE 1 #define IFLA_BRPORT_PRIORITY 2 @@ -843,7 +843,9 @@ static inline int setns(int fd, int nstype) { #define IFLA_BRPORT_FAST_LEAVE 7 #define IFLA_BRPORT_LEARNING 8 #define IFLA_BRPORT_UNICAST_FLOOD 9 -#define __IFLA_BRPORT_MAX 10 +#define IFLA_BRPORT_PROXYARP 10 +#define IFLA_BRPORT_LEARNING_SYNC 11 +#define __IFLA_BRPORT_MAX 12 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) #endif diff --git a/src/basic/virt.c b/src/basic/virt.c index 1299a75ed5..a8d26716a1 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -188,7 +188,7 @@ int detect_vm(const char **id) { _cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL; static thread_local int cached_found = -1; static thread_local const char *cached_id = NULL; - const char *_id = NULL; + const char *_id = NULL, *_id_cpuid = NULL; int r; if (_likely_(cached_found >= 0)) { @@ -234,10 +234,26 @@ int detect_vm(const char **id) { /* this will set _id to "other" and return 0 for unknown hypervisors */ r = detect_vm_cpuid(&_id); - if (r != 0) + + /* finish when found a known hypervisor other than kvm */ + if (r < 0 || (r > 0 && !streq(_id, "kvm"))) goto finish; + _id_cpuid = _id; + r = detect_vm_dmi(&_id); + + /* kvm with and without Virtualbox */ + if (streq_ptr(_id_cpuid, "kvm")) { + if (r > 0 && streq(_id, "oracle")) + goto finish; + + _id = _id_cpuid; + r = 1; + goto finish; + } + + /* information from dmi */ if (r != 0) goto finish; diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 8c6fd8ad30..ff1b8a260f 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -329,8 +329,11 @@ static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1] [IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 }, }; static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = { diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 9550e89a15..55510b46e9 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -846,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"); @@ -861,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->bpdu_guard); + 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->root_block); + 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) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 3a78c3d8a8..720f6b9d0b 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -73,6 +73,11 @@ DHCP.CriticalConnection, config_parse_bool, 0 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.BPDUGuard, config_parse_bool, 0, offsetof(Network, bpdu_guard) +Bridge.HairPin, config_parse_bool, 0, offsetof(Network, hairpin) +Bridge.FastLeave, config_parse_bool, 0, offsetof(Network, fast_leave) +Bridge.RootBlock, config_parse_bool, 0, offsetof(Network, root_block) +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 */ diff --git a/src/network/networkd.h b/src/network/networkd.h index fb95f90169..6418c0a536 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -150,6 +150,11 @@ struct Network { bool dhcp_server; + bool bpdu_guard; + bool hairpin; + bool fast_leave; + bool root_block; + bool unicast_flood; unsigned cost; AddressFamilyBoolean ip_forward; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 3428109da4..65b9a5071b 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1785,15 +1785,13 @@ static int setup_pts(const char *dest) { #ifdef HAVE_SELINUX if (arg_selinux_apifs_context) (void) asprintf(&options, - "newinstance,ptmxmode=0666,mode=620,uid=" UID_FMT ",gid=" GID_FMT ",context=\"%s\"", - arg_uid_shift, + "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT ",context=\"%s\"", arg_uid_shift + TTY_GID, arg_selinux_apifs_context); else #endif (void) asprintf(&options, - "newinstance,ptmxmode=0666,mode=620,uid=" UID_FMT ",gid=" GID_FMT, - arg_uid_shift, + "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT, arg_uid_shift + TTY_GID); if (!options) diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c index a3e740896f..e1087b3219 100644 --- a/src/resolve/dns-type.c +++ b/src/resolve/dns-type.c @@ -43,3 +43,8 @@ int dns_type_from_string(const char *s) { return sc->id; } + +/* XXX: find an authorotative list of all pseudo types? */ +bool dns_type_is_pseudo(int n) { + return IN_SET(n, DNS_TYPE_ANY, DNS_TYPE_AXFR, DNS_TYPE_IXFR, DNS_TYPE_OPT); +} diff --git a/src/resolve/dns-type.h b/src/resolve/dns-type.h index 86951d233a..950af36ee3 100644 --- a/src/resolve/dns-type.h +++ b/src/resolve/dns-type.h @@ -25,6 +25,7 @@ const char *dns_type_to_string(int type); int dns_type_from_string(const char *s); +bool dns_type_is_pseudo(int n); /* DNS record types, taken from * http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml. diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 12cd524c40..649e8b74e1 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -275,7 +275,7 @@ static void dns_packet_truncate(DnsPacket *p, size_t sz) { if (p->size <= sz) return; - HASHMAP_FOREACH_KEY(s, n, p->names, i) { + HASHMAP_FOREACH_KEY(n, s, p->names, i) { if (PTR_TO_SIZE(n) < sz) continue; @@ -761,7 +761,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star if (r < 0) goto fail; - r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL); + r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL); break; case DNS_TYPE_DNSKEY: @@ -933,6 +933,42 @@ int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) { return 0; } +static int dns_packet_read_memdup( + DnsPacket *p, size_t size, + void **ret, size_t *ret_size, + size_t *ret_start) { + + const void *src; + size_t start; + int r; + + assert(p); + assert(ret); + + r = dns_packet_read(p, size, &src, &start); + if (r < 0) + return r; + + if (size <= 0) + *ret = NULL; + else { + void *copy; + + copy = memdup(src, size); + if (!copy) + return -ENOMEM; + + *ret = copy; + } + + if (ret_size) + *ret_size = size; + if (ret_start) + *ret_start = start; + + return 0; +} + int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) { const void *d; int r; @@ -1172,9 +1208,12 @@ static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *sta if (bitmap[i] & bitmask) { uint16_t n; - /* XXX: ignore pseudo-types? see RFC4034 section 4.1.2 */ n = (uint16_t) window << 8 | (uint16_t) bit; + /* Ignore pseudo-types. see RFC4034 section 4.1.2 */ + if (dns_type_is_pseudo(n)) + continue; + r = bitmap_set(*types, n); if (r < 0) goto fail; @@ -1197,6 +1236,38 @@ fail: return r; } +static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) { + size_t saved_rindex; + int r; + + saved_rindex = p->rindex; + + while (p->rindex < saved_rindex + size) { + r = dns_packet_read_type_window(p, types, NULL); + if (r < 0) + goto fail; + + /* don't read past end of current RR */ + if (p->rindex > saved_rindex + size) { + r = -EBADMSG; + goto fail; + } + } + + if (p->rindex != saved_rindex + size) { + r = -EBADMSG; + goto fail; + } + + if (start) + *start = saved_rindex; + + return 0; +fail: + dns_packet_rewind(p, saved_rindex); + return r; +} + int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) { _cleanup_free_ char *name = NULL; uint16_t class, type; @@ -1239,26 +1310,6 @@ fail: return r; } -static int dns_packet_read_public_key(DnsPacket *p, size_t length, - void **dp, size_t *lengthp, - size_t *start) { - int r; - const void *d; - void *d2; - - r = dns_packet_read(p, length, &d, NULL); - if (r < 0) - return r; - - d2 = memdup(d, length); - if (!d2) - return -ENOMEM; - - *dp = d2; - *lengthp = length; - return 0; -} - static bool loc_size_ok(uint8_t size) { uint8_t m = size >> 4, e = size & 0xF; @@ -1281,7 +1332,6 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; size_t saved_rindex, offset; uint16_t rdlength; - const void *d; int r; assert(p); @@ -1492,12 +1542,19 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { if (r < 0) goto fail; - r = dns_packet_read_public_key(p, rdlength - 4, - &rr->ds.digest, &rr->ds.digest_size, - NULL); + r = dns_packet_read_memdup(p, rdlength - 4, + &rr->ds.digest, &rr->ds.digest_size, + NULL); if (r < 0) goto fail; + if (rr->ds.digest_size <= 0) { + /* the accepted size depends on the algorithm, but for now + just ensure that the value is greater than zero */ + r = -EBADMSG; + goto fail; + } + break; case DNS_TYPE_SSHFP: r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL); @@ -1508,9 +1565,17 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { if (r < 0) goto fail; - r = dns_packet_read_public_key(p, rdlength - 2, - &rr->sshfp.key, &rr->sshfp.key_size, - NULL); + r = dns_packet_read_memdup(p, rdlength - 2, + &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size, + NULL); + + if (rr->sshfp.fingerprint_size <= 0) { + /* the accepted size depends on the algorithm, but for now + just ensure that the value is greater than zero */ + r = -EBADMSG; + goto fail; + } + break; case DNS_TYPE_DNSKEY: { @@ -1539,9 +1604,17 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { if (r < 0) goto fail; - r = dns_packet_read_public_key(p, rdlength - 4, - &rr->dnskey.key, &rr->dnskey.key_size, - NULL); + r = dns_packet_read_memdup(p, rdlength - 4, + &rr->dnskey.key, &rr->dnskey.key_size, + NULL); + + if (rr->dnskey.key_size <= 0) { + /* the accepted size depends on the algorithm, but for now + just ensure that the value is greater than zero */ + r = -EBADMSG; + goto fail; + } + break; } @@ -1578,9 +1651,17 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { if (r < 0) goto fail; - r = dns_packet_read_public_key(p, offset + rdlength - p->rindex, - &rr->rrsig.signature, &rr->rrsig.signature_size, - NULL); + r = dns_packet_read_memdup(p, offset + rdlength - p->rindex, + &rr->rrsig.signature, &rr->rrsig.signature_size, + NULL); + + if (rr->rrsig.signature_size <= 0) { + /* the accepted size depends on the algorithm, but for now + just ensure that the value is greater than zero */ + r = -EBADMSG; + goto fail; + } + break; case DNS_TYPE_NSEC: @@ -1588,11 +1669,12 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { if (r < 0) goto fail; - while (p->rindex != offset + rdlength) { - r = dns_packet_read_type_window(p, &rr->nsec.types, NULL); - if (r < 0) - goto fail; - } + r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL); + if (r < 0) + goto fail; + + /* NSEC RRs with empty bitmpas makes no sense, but the RFC does not explicitly forbid them + so we allow it */ break; @@ -1611,57 +1693,41 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { if (r < 0) goto fail; + /* this may be zero */ r = dns_packet_read_uint8(p, &size, NULL); if (r < 0) goto fail; - rr->nsec3.salt_size = size; - - r = dns_packet_read_blob(p, &d, rr->nsec3.salt_size, NULL); + r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL); if (r < 0) goto fail; - rr->nsec3.salt = memdup(d, rr->nsec3.salt_size); - if (!rr->nsec3.salt) { - r = -ENOMEM; - goto fail; - } - r = dns_packet_read_uint8(p, &size, NULL); if (r < 0) goto fail; - rr->nsec3.next_hashed_name_size = size; - - r = dns_packet_read(p, rr->nsec3.next_hashed_name_size, &d, NULL); - if (r < 0) + if (size <= 0) { + r = -EBADMSG; goto fail; + } - rr->nsec3.next_hashed_name = memdup(d, rr->nsec3.next_hashed_name_size); - if (!rr->nsec3.next_hashed_name) { - r = -ENOMEM; + r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL); + if (r < 0) goto fail; - } - r = dns_packet_append_types(p, rr->nsec3.types, NULL); + r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL); if (r < 0) goto fail; + /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */ + break; } default: unparseable: - r = dns_packet_read(p, rdlength, &d, NULL); + r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL); if (r < 0) goto fail; - - rr->generic.data = memdup(d, rdlength); - if (!rr->generic.data) { - r = -ENOMEM; - goto fail; - } - - rr->generic.size = rdlength; break; } if (r < 0) diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 9c12205ab8..2bc9f2b520 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -276,7 +276,7 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) { break; case DNS_TYPE_SSHFP: - free(rr->sshfp.key); + free(rr->sshfp.fingerprint); break; case DNS_TYPE_DNSKEY: @@ -434,8 +434,8 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor case DNS_TYPE_SSHFP: return a->sshfp.algorithm == b->sshfp.algorithm && a->sshfp.fptype == b->sshfp.fptype && - a->sshfp.key_size == b->sshfp.key_size && - memcmp(a->sshfp.key, b->sshfp.key, a->sshfp.key_size) == 0; + a->sshfp.fingerprint_size == b->sshfp.fingerprint_size && + memcmp(a->sshfp.fingerprint, b->sshfp.fingerprint, a->sshfp.fingerprint_size) == 0; case DNS_TYPE_DNSKEY: return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag && @@ -687,7 +687,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) { break; case DNS_TYPE_SSHFP: - t = hexmem(rr->sshfp.key, rr->sshfp.key_size); + t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size); if (!t) return -ENOMEM; @@ -776,7 +776,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) { case DNS_TYPE_NSEC3: { _cleanup_free_ char *salt = NULL, *hash = NULL; - if (rr->nsec3.salt_size) { + if (rr->nsec3.salt_size > 0) { salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size); if (!salt) return -ENOMEM; @@ -795,7 +795,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) { rr->nsec3.algorithm, rr->nsec3.flags, rr->nsec3.iterations, - rr->nsec3.salt_size ? salt : "-", + rr->nsec3.salt_size > 0 ? salt : "-", hash, t); if (r < 0) @@ -809,7 +809,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) { if (!t) return -ENOMEM; - r = asprintf(&s, "%s \\# %"PRIu8" %s", k, rr->generic.size, t); + r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.size, t); if (r < 0) return -ENOMEM; break; diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h index bdd5a5c824..0f40f3ceef 100644 --- a/src/resolve/resolved-dns-rr.h +++ b/src/resolve/resolved-dns-rr.h @@ -53,7 +53,7 @@ struct DnsResourceRecord { union { struct { void *data; - uint16_t size; + size_t size; } generic; struct { @@ -117,11 +117,12 @@ struct DnsResourceRecord { size_t digest_size; } ds; + /* https://tools.ietf.org/html/rfc4255#section-3.1 */ struct { uint8_t algorithm; uint8_t fptype; - void *key; - size_t key_size; + void *fingerprint; + size_t fingerprint_size; } sshfp; /* http://tools.ietf.org/html/rfc4034#section-2.1 */ diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index e468f245f7..3d46c99df8 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -417,8 +417,10 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { /* Only consider responses with equivalent query section to the request */ if (!dns_question_is_superset(p->question, t->question) || - !dns_question_is_superset(t->question, p->question)) + !dns_question_is_superset(t->question, p->question)) { dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + return; + } /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */ dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender); diff --git a/units/systemd-networkd.service.m4.in b/units/systemd-networkd.service.m4.in index 64d9130c24..35be713ade 100644 --- a/units/systemd-networkd.service.m4.in +++ b/units/systemd-networkd.service.m4.in @@ -12,7 +12,7 @@ ConditionCapability=CAP_NET_ADMIN DefaultDependencies=no # dbus.service can be dropped once on kdbus, and systemd-udevd.service can be # dropped once tuntap is moved to netlink -After=systemd-udevd.service dbus.service network-pre.target systemd-sysusers.service +After=systemd-udevd.service dbus.service network-pre.target systemd-sysusers.service systemd-sysctl.service Before=network.target multi-user.target shutdown.target Conflicts=shutdown.target Wants=network.target |