diff options
Diffstat (limited to 'src/systemd')
24 files changed, 870 insertions, 314 deletions
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c index b28e0ba0..026015a7 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.c +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c @@ -17,7 +17,6 @@ #include "udev-util.h" #include "virt.h" -#define SYSTEMD_PEN 43793 #define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09) #define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03) #define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */ diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h index b3115125..76abd658 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.h +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h @@ -8,6 +8,8 @@ #include "time-util.h" #include "unaligned.h" +#define SYSTEMD_PEN 43793 + typedef enum DUIDType { DUID_TYPE_LLT = 1, DUID_TYPE_EN = 2, diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h index 6a803d7b..7e814948 100644 --- a/src/systemd/src/libsystemd-network/dhcp-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-internal.h @@ -7,7 +7,6 @@ #include <linux/if_packet.h> #include <net/ethernet.h> -#include <net/if_arp.h> #include <stdint.h> #include "sd-dhcp-client.h" @@ -23,6 +22,11 @@ typedef struct sd_dhcp_option { size_t length; } sd_dhcp_option; +typedef struct DHCPServerData { + struct in_addr *addr; + size_t size; +} DHCPServerData; + extern const struct hash_ops dhcp_option_hash_ops; int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h index 5cbebb4a..aed30d61 100644 --- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h @@ -5,11 +5,9 @@ Copyright © 2013 Intel Corporation. All rights reserved. ***/ -#include <stdint.h> -#include <linux/if_packet.h> - #include "sd-dhcp-client.h" +#include "dhcp-internal.h" #include "dhcp-protocol.h" #include "list.h" #include "util.h" @@ -52,20 +50,7 @@ struct sd_dhcp_lease { struct in_addr *router; size_t router_size; - struct in_addr *dns; - size_t dns_size; - - struct in_addr *ntp; - size_t ntp_size; - - struct in_addr *sip; - size_t sip_size; - - struct in_addr *pop3_server; - size_t pop3_server_size; - - struct in_addr *smtp_server; - size_t smtp_server_size; + DHCPServerData servers[_SD_DHCP_LEASE_SERVER_TYPE_MAX]; struct sd_dhcp_route *static_route; size_t static_route_size, static_route_allocated; diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h index 517e357d..b0d1216e 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h @@ -11,9 +11,21 @@ #include "sd-event.h" #include "list.h" +#include "hashmap.h" #include "macro.h" #include "sparse-endian.h" +typedef struct sd_dhcp6_option { + unsigned n_ref; + + uint32_t enterprise_identifier; + uint16_t option; + void *data; + size_t length; +} sd_dhcp6_option; + +extern const struct hash_ops dhcp6_option_hash_ops; + /* Common option header */ typedef struct DHCP6Option { be16_t code; @@ -87,10 +99,13 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia); int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix); int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn); +int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class); +int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **user_class); +int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options); int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); int dhcp6_option_parse_status(DHCP6Option *option, size_t len); -int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia); +int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code); int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, struct in6_addr **addrs, size_t count, size_t *allocated); diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c index bb4c4d91..d596752b 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/systemd/src/libsystemd-network/dhcp6-option.c @@ -11,6 +11,7 @@ #include "sd-dhcp6-client.h" #include "alloc-util.h" +#include "dhcp-identifier.h" #include "dhcp6-internal.h" #include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" @@ -80,6 +81,39 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, return 0; } +int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options) { + sd_dhcp6_option *options; + Iterator i; + int r; + + assert(buf); + assert(*buf); + assert(buflen); + assert(vendor_options); + + ORDERED_HASHMAP_FOREACH(options, vendor_options, i) { + _cleanup_free_ uint8_t *p = NULL; + size_t total; + + total = 4 + 2 + 2 + options->length; + + p = malloc(total); + if (!p) + return -ENOMEM; + + unaligned_write_be32(p, options->enterprise_identifier); + unaligned_write_be16(p + 4, options->option); + unaligned_write_be16(p + 6, options->length); + memcpy(p + 8, options->data, options->length); + + r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_OPTS, total, p); + if (r < 0) + return r; + } + + return 0; +} + int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) { uint16_t len; uint8_t *ia_hdr; @@ -169,6 +203,75 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { return r; } +int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class) { + _cleanup_free_ uint8_t *p = NULL; + size_t total = 0, offset = 0; + char **s; + + assert_return(buf && *buf && buflen && user_class, -EINVAL); + + STRV_FOREACH(s, user_class) { + size_t len = strlen(*s); + uint8_t *q; + + if (len > 0xffff) + return -ENAMETOOLONG; + q = realloc(p, total + len + 2); + if (!q) + return -ENOMEM; + + p = q; + + unaligned_write_be16(&p[offset], len); + memcpy(&p[offset + 2], *s, len); + + offset += 2 + len; + total += 2 + len; + } + + return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p); +} + +int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **vendor_class) { + _cleanup_free_ uint8_t *p = NULL; + uint32_t enterprise_identifier; + size_t total, offset; + char **s; + + assert(buf); + assert(*buf); + assert(buflen); + assert(vendor_class); + + enterprise_identifier = htobe32(SYSTEMD_PEN); + + p = memdup(&enterprise_identifier, sizeof(enterprise_identifier)); + if (!p) + return -ENOMEM; + + total = sizeof(enterprise_identifier); + offset = total; + + STRV_FOREACH(s, vendor_class) { + size_t len = strlen(*s); + uint8_t *q; + + q = realloc(p, total + len + 2); + if (!q) + return -ENOMEM; + + p = q; + + unaligned_write_be16(&p[offset], len); + memcpy(&p[offset + 2], *s, len); + + offset += 2 + len; + total += 2 + len; + } + + return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_CLASS, total, p); +} + int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) { DHCP6Option *option = (DHCP6Option *)buf; size_t i = sizeof(*option) + sizeof(pd->ia_pd); @@ -349,13 +452,13 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia, return 0; } -int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { +int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code) { + uint32_t lt_t1, lt_t2, lt_valid = 0, lt_min = UINT32_MAX; uint16_t iatype, optlen; - size_t i, len; + size_t iaaddr_offset; int r = 0, status; + size_t i, len; uint16_t opt; - size_t iaaddr_offset; - uint32_t lt_t1, lt_t2, lt_valid = 0, lt_min = UINT32_MAX; assert_return(ia, -EINVAL); assert_return(!ia->addresses, -EINVAL); @@ -465,11 +568,15 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { status = dhcp6_option_parse_status(option, optlen + offsetof(DHCP6Option, data)); if (status < 0) return status; + if (status > 0) { - log_dhcp6_client(client, "IA status %d", - status); + if (ret_status_code) + *ret_status_code = status; - return -EINVAL; + log_dhcp6_client(client, "IA status %s", + dhcp6_message_status_to_string(status)); + + return 0; } break; @@ -513,7 +620,10 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { break; } - return 0; + if (ret_status_code) + *ret_status_code = 0; + + return 1; } int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, @@ -599,3 +709,44 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char * return idx; } + +static sd_dhcp6_option* dhcp6_option_free(sd_dhcp6_option *i) { + if (!i) + return NULL; + + free(i->data); + return mfree(i); +} + +int sd_dhcp6_option_new(uint16_t option, const void *data, size_t length, uint32_t enterprise_identifier, sd_dhcp6_option **ret) { + assert_return(ret, -EINVAL); + assert_return(length == 0 || data, -EINVAL); + + _cleanup_free_ void *q = memdup(data, length); + if (!q) + return -ENOMEM; + + sd_dhcp6_option *p = new(sd_dhcp6_option, 1); + if (!p) + return -ENOMEM; + + *p = (sd_dhcp6_option) { + .n_ref = 1, + .option = option, + .enterprise_identifier = enterprise_identifier, + .length = length, + .data = TAKE_PTR(q), + }; + + *ret = p; + return 0; +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_option, sd_dhcp6_option, dhcp6_option_free); +DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + dhcp6_option_hash_ops, + void, + trivial_hash_func, + trivial_compare_func, + sd_dhcp6_option, + sd_dhcp6_option_unref); diff --git a/src/systemd/src/libsystemd-network/dhcp6-protocol.h b/src/systemd/src/libsystemd-network/dhcp6-protocol.h index ffae4453..f7a27028 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-protocol.h +++ b/src/systemd/src/libsystemd-network/dhcp6-protocol.h @@ -82,14 +82,35 @@ enum { DHCP6_NTP_SUBOPTION_SRV_FQDN = 3, }; +/* + * RFC 8415, RFC 5007 and RFC 7653 status codes: + * https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#dhcpv6-parameters-5 + */ enum { - DHCP6_STATUS_SUCCESS = 0, - DHCP6_STATUS_UNSPEC_FAIL = 1, - DHCP6_STATUS_NO_ADDRS_AVAIL = 2, - DHCP6_STATUS_NO_BINDING = 3, - DHCP6_STATUS_NOT_ON_LINK = 4, - DHCP6_STATUS_USE_MULTICAST = 5, - _DHCP6_STATUS_MAX = 6, + DHCP6_STATUS_SUCCESS = 0, + DHCP6_STATUS_UNSPEC_FAIL = 1, + DHCP6_STATUS_NO_ADDRS_AVAIL = 2, + DHCP6_STATUS_NO_BINDING = 3, + DHCP6_STATUS_NOT_ON_LINK = 4, + DHCP6_STATUS_USE_MULTICAST = 5, + DHCP6_STATUS_NO_PREFIX_AVAIL = 6, + DHCP6_STATUS_UNKNOWN_QUERY_TYPE = 7, + DHCP6_STATUS_MALFORMED_QUERY = 8, + DHCP6_STATUS_NOT_CONFIGURED = 9, + DHCP6_STATUS_NOT_ALLOWED = 10, + DHCP6_STATUS_QUERY_TERMINATED = 11, + DHCP6_STATUS_DATA_MISSING = 12, + DHCP6_STATUS_CATCHUP_COMPLETE = 13, + DHCP6_STATUS_NOT_SUPPORTED = 14, + DHCP6_STATUS_TLS_CONNECTION_REFUSED = 15, + DHCP6_STATUS_ADDRESS_IN_USE = 16, + DHCP6_STATUS_CONFIGURATION_CONFLICT = 17, + DHCP6_STATUS_MISSING_BINDING_INFORMATION = 18, + DHCP6_STATUS_OUTDATED_BINDING_INFORMATION = 19, + DHCP6_STATUS_SERVER_SHUTTING_DOWN = 20, + DHCP6_STATUS_DNS_UPDATE_NOT_SUPPORTED = 21, + DHCP6_STATUS_EXCESSIVE_TIME_SKEW = 22, + _DHCP6_STATUS_MAX = 23, }; enum { diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c index 238d718b..9baa8e8c 100644 --- a/src/systemd/src/libsystemd-network/lldp-neighbor.c +++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c @@ -52,6 +52,7 @@ static void lldp_neighbor_free(sd_lldp_neighbor *n) { free(n->port_description); free(n->system_name); free(n->system_description); + free(n->mud_url); free(n->chassis_id_as_string); free(n->port_id_as_string); free(n); @@ -294,9 +295,20 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) { break; - case SD_LLDP_TYPE_PRIVATE: + case SD_LLDP_TYPE_PRIVATE: { if (length < 4) log_lldp("Found private TLV that is too short, ignoring."); + else { + /* RFC 8520: MUD URL */ + if (memcmp(p, SD_LLDP_OUI_MUD, sizeof(SD_LLDP_OUI_MUD)) == 0 && + p[sizeof(SD_LLDP_OUI_MUD)] == SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION) { + r = parse_string(&n->mud_url, p + sizeof(SD_LLDP_OUI_MUD) + 1, + length - 1 - sizeof(SD_LLDP_OUI_MUD)); + if (r < 0) + return r; + } + } + } break; } @@ -595,6 +607,17 @@ _public_ int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const ch return 0; } +_public_ int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->mud_url) + return -ENODATA; + + *ret = n->mud_url; + return 0; +} + _public_ int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { assert_return(n, -EINVAL); assert_return(ret, -EINVAL); diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.h b/src/systemd/src/libsystemd-network/lldp-neighbor.h index 62dbff42..74175edf 100644 --- a/src/systemd/src/libsystemd-network/lldp-neighbor.h +++ b/src/systemd/src/libsystemd-network/lldp-neighbor.h @@ -54,6 +54,7 @@ struct sd_lldp_neighbor { char *port_description; char *system_name; char *system_description; + char *mud_url; uint16_t port_vlan_id; diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index 94a6236a..6a7382ac 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -195,30 +195,34 @@ bool net_match_config(Set *match_mac, Set *match_permanent_mac, char * const *match_paths, char * const *match_drivers, - char * const *match_types, + char * const *match_iftypes, char * const *match_names, char * const *match_property, char * const *match_wifi_iftype, char * const *match_ssid, Set *match_bssid, - unsigned short iftype, sd_device *device, const struct ether_addr *dev_mac, const struct ether_addr *dev_permanent_mac, + const char *dev_driver, + unsigned short dev_iftype, const char *dev_name, char * const *alternative_names, - enum nl80211_iftype wifi_iftype, - const char *ssid, - const struct ether_addr *bssid) { + enum nl80211_iftype dev_wifi_iftype, + const char *dev_ssid, + const struct ether_addr *dev_bssid) { - const char *dev_path = NULL, *dev_driver = NULL, *mac_str; - _cleanup_free_ char *dev_type; + _cleanup_free_ char *dev_iftype_str; + const char *dev_path = NULL; - dev_type = link_get_type_string(iftype, device); + dev_iftype_str = link_get_type_string(dev_iftype, device); if (device) { + const char *mac_str; + (void) sd_device_get_property_value(device, "ID_PATH", &dev_path); - (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver); + if (!dev_driver) + (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver); if (!dev_name) (void) sd_device_get_sysname(device, &dev_name); if (!dev_mac && @@ -241,7 +245,7 @@ bool net_match_config(Set *match_mac, if (!net_condition_test_strv(match_drivers, dev_driver)) return false; - if (!net_condition_test_strv(match_types, dev_type)) + if (!net_condition_test_strv(match_iftypes, dev_iftype_str)) return false; if (!net_condition_test_ifname(match_names, dev_name, alternative_names)) @@ -250,13 +254,13 @@ bool net_match_config(Set *match_mac, if (!net_condition_test_property(match_property, device)) return false; - if (!net_condition_test_strv(match_wifi_iftype, wifi_iftype_to_string(wifi_iftype))) + if (!net_condition_test_strv(match_wifi_iftype, wifi_iftype_to_string(dev_wifi_iftype))) return false; - if (!net_condition_test_strv(match_ssid, ssid)) + if (!net_condition_test_strv(match_ssid, dev_ssid)) return false; - if (match_bssid && (!bssid || !set_contains(match_bssid, bssid))) + if (match_bssid && (!dev_bssid || !set_contains(match_bssid, dev_bssid))) return false; return true; @@ -660,27 +664,27 @@ int config_parse_bridge_port_priority( size_t serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size, - bool with_leading_space, + bool *with_leading_space, bool (*predicate)(const struct in_addr *addr)) { - size_t count; - size_t i; - assert(f); assert(addresses); - count = 0; + size_t count = 0; + bool _space = false; + if (!with_leading_space) + with_leading_space = &_space; - for (i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { char sbuf[INET_ADDRSTRLEN]; if (predicate && !predicate(&addresses[i])) continue; - if (with_leading_space) + + if (*with_leading_space) fputc(' ', f); - else - with_leading_space = true; fputs(inet_ntop(AF_INET, &addresses[i], sbuf, sizeof(sbuf)), f); count++; + *with_leading_space = true; } return count; @@ -722,20 +726,22 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) { return size; } -void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size) { - unsigned i; - +void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size, bool *with_leading_space) { assert(f); assert(addresses); assert(size); - for (i = 0; i < size; i++) { - char buffer[INET6_ADDRSTRLEN]; + bool _space = false; + if (!with_leading_space) + with_leading_space = &_space; - fputs(inet_ntop(AF_INET6, addresses+i, buffer, sizeof(buffer)), f); + for (size_t i = 0; i < size; i++) { + char buffer[INET6_ADDRSTRLEN]; - if (i < size - 1) + if (*with_leading_space) fputc(' ', f); + fputs(inet_ntop(AF_INET6, addresses+i, buffer, sizeof(buffer)), f); + *with_leading_space = true; } } @@ -776,8 +782,6 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) { } void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) { - unsigned i; - assert(f); assert(key); assert(routes); @@ -785,7 +789,7 @@ void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, siz fprintf(f, "%s=", key); - for (i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { char sbuf[INET_ADDRSTRLEN]; struct in_addr dest, gw; uint8_t length; @@ -794,8 +798,8 @@ void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, siz assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0); assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0); - fprintf(f, "%s/%" PRIu8, inet_ntop(AF_INET, &dest, sbuf, sizeof(sbuf)), length); - fprintf(f, ",%s%s", inet_ntop(AF_INET, &gw, sbuf, sizeof(sbuf)), (i < (size - 1)) ? " ": ""); + fprintf(f, "%s/%" PRIu8, inet_ntop(AF_INET, &dest, sbuf, sizeof sbuf), length); + fprintf(f, ",%s%s", inet_ntop(AF_INET, &gw, sbuf, sizeof sbuf), i < size - 1 ? " ": ""); } fputs("\n", f); diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h index 6724cbbf..8e6377e0 100644 --- a/src/systemd/src/libsystemd-network/network-internal.h +++ b/src/systemd/src/libsystemd-network/network-internal.h @@ -17,23 +17,24 @@ #if 0 /* NM_IGNORED */ bool net_match_config(Set *match_mac, Set *match_permanent_mac, - char * const *match_path, - char * const *match_driver, - char * const *match_type, - char * const *match_name, + char * const *match_paths, + char * const *match_drivers, + char * const *match_iftypes, + char * const *match_names, char * const *match_property, char * const *match_wifi_iftype, char * const *match_ssid, Set *match_bssid, - unsigned short iftype, sd_device *device, const struct ether_addr *dev_mac, const struct ether_addr *dev_permanent_mac, + const char *dev_driver, + unsigned short dev_iftype, const char *dev_name, char * const *alternative_names, - enum nl80211_iftype wifi_iftype, - const char *ssid, - const struct ether_addr *bssid); + enum nl80211_iftype dev_wifi_iftype, + const char *dev_ssid, + const struct ether_addr *dev_bssid); CONFIG_PARSER_PROTOTYPE(config_parse_net_condition); CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr); @@ -51,11 +52,12 @@ const char *net_get_name_persistent(sd_device *device); size_t serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size, - bool with_leading_space, + bool *with_leading_space, bool (*predicate)(const struct in_addr *addr)); int deserialize_in_addrs(struct in_addr **addresses, const char *string); void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, - size_t size); + size_t size, + bool *with_leading_space); int deserialize_in6_addrs(struct in6_addr **addresses, const char *string); /* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */ diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index 63321cca..70821ac2 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -29,6 +29,7 @@ #include "random-util.h" #include "string-util.h" #include "strv.h" +#include "utf8.h" #include "web-util.h" #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */ @@ -37,6 +38,32 @@ #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC) #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE) +typedef struct sd_dhcp_client_id { + uint8_t type; + union { + struct { + /* 0: Generic (non-LL) (RFC 2132) */ + uint8_t data[MAX_CLIENT_ID_LEN]; + } _packed_ gen; + struct { + /* 1: Ethernet Link-Layer (RFC 2132) */ + uint8_t haddr[ETH_ALEN]; + } _packed_ eth; + struct { + /* 2 - 254: ARP/Link-Layer (RFC 2132) */ + uint8_t haddr[0]; + } _packed_ ll; + struct { + /* 255: Node-specific (RFC 4361) */ + be32_t iaid; + struct duid duid; + } _packed_ ns; + struct { + uint8_t data[MAX_CLIENT_ID_LEN]; + } _packed_ raw; + }; +} _packed_ sd_dhcp_client_id; + struct sd_dhcp_client { unsigned n_ref; @@ -58,37 +85,14 @@ struct sd_dhcp_client { uint8_t mac_addr[MAX_MAC_ADDR_LEN]; size_t mac_addr_len; uint16_t arp_type; - struct { - uint8_t type; - union { - struct { - /* 0: Generic (non-LL) (RFC 2132) */ - uint8_t data[MAX_CLIENT_ID_LEN]; - } _packed_ gen; - struct { - /* 1: Ethernet Link-Layer (RFC 2132) */ - uint8_t haddr[ETH_ALEN]; - } _packed_ eth; - struct { - /* 2 - 254: ARP/Link-Layer (RFC 2132) */ - uint8_t haddr[0]; - } _packed_ ll; - struct { - /* 255: Node-specific (RFC 4361) */ - be32_t iaid; - struct duid duid; - } _packed_ ns; - struct { - uint8_t data[MAX_CLIENT_ID_LEN]; - } _packed_ raw; - }; - } _packed_ client_id; + sd_dhcp_client_id client_id; size_t client_id_len; char *hostname; char *vendor_class_identifier; char *mudurl; char **user_class; uint32_t mtu; + uint32_t fallback_lease_lifetime; uint32_t xid; usec_t start_time; uint64_t attempt; @@ -152,6 +156,60 @@ static int client_receive_message_udp( void *userdata); static void client_stop(sd_dhcp_client *client, int error); +int sd_dhcp_client_id_to_string(const void *data, size_t len, char **ret) { + const sd_dhcp_client_id *client_id = data; + _cleanup_free_ char *t = NULL; + int r = 0; + + assert_return(data, -EINVAL); + assert_return(len >= 1, -EINVAL); + assert_return(ret, -EINVAL); + + len -= 1; + if (len > MAX_CLIENT_ID_LEN) + return -EINVAL; + + switch (client_id->type) { + case 0: + if (utf8_is_printable((char *) client_id->gen.data, len)) + r = asprintf(&t, "%.*s", (int) len, client_id->gen.data); + else + r = asprintf(&t, "DATA"); + break; + case 1: + if (len != sizeof_field(sd_dhcp_client_id, eth)) + return -EINVAL; + + r = asprintf(&t, "%x:%x:%x:%x:%x:%x", + client_id->eth.haddr[0], + client_id->eth.haddr[1], + client_id->eth.haddr[2], + client_id->eth.haddr[3], + client_id->eth.haddr[4], + client_id->eth.haddr[5]); + break; + case 2 ... 254: + r = asprintf(&t, "ARP/LL"); + break; + case 255: + if (len < 6) + return -EINVAL; + + uint32_t iaid = be32toh(client_id->ns.iaid); + uint16_t duid_type = be16toh(client_id->ns.duid.type); + if (dhcp_validate_duid_len(duid_type, len - 6, true) < 0) + return -EINVAL; + + r = asprintf(&t, "IAID:0x%x/DUID", iaid); + break; + } + + if (r < 0) + return -ENOMEM; + *ret = TAKE_PTR(t); + return 0; +} + int sd_dhcp_client_set_callback( sd_dhcp_client *client, sd_dhcp_client_callback_t cb, @@ -617,6 +675,15 @@ int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) { return 0; } +int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client *client, uint32_t fallback_lease_lifetime) { + assert_return(client, -EINVAL); + assert_return(fallback_lease_lifetime > 0, -EINVAL); + + client->fallback_lease_lifetime = fallback_lease_lifetime; + + return 0; +} + static int client_notify(sd_dhcp_client *client, int event) { assert(client); @@ -855,36 +922,12 @@ static int dhcp_client_send_raw( packet, len); } -static int client_send_discover(sd_dhcp_client *client) { - _cleanup_free_ DHCPPacket *discover = NULL; - size_t optoffset, optlen; +static int client_append_common_discover_request_options(sd_dhcp_client *client, DHCPPacket *packet, size_t *optoffset, size_t optlen) { sd_dhcp_option *j; Iterator i; int r; assert(client); - assert(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_SELECTING)); - - r = client_message_init(client, &discover, DHCP_DISCOVER, - &optlen, &optoffset); - if (r < 0) - return r; - - /* the client may suggest values for the network address - and lease time in the DHCPDISCOVER message. The client may include - the ’requested IP address’ option to suggest that a particular IP - address be assigned, and may include the ’IP address lease time’ - option to suggest the lease time it would like. - */ - /* RFC7844 section 3: - SHOULD NOT contain any other option. */ - if (!client->anonymize && client->last_addr != INADDR_ANY) { - r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, - 4, &client->last_addr); - if (r < 0) - return r; - } if (client->hostname) { /* According to RFC 4702 "clients that send the Client FQDN option in @@ -895,18 +938,18 @@ static int client_send_discover(sd_dhcp_client *client) { /* it is unclear from RFC 2131 if client should send hostname in DHCPDISCOVER but dhclient does and so we do as well */ - r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, SD_DHCP_OPTION_HOST_NAME, strlen(client->hostname), client->hostname); } else - r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset, + r = client_append_fqdn_option(&packet->dhcp, optlen, optoffset, client->hostname); if (r < 0) return r; } if (client->vendor_class_identifier) { - r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, strlen(client->vendor_class_identifier), client->vendor_class_identifier); @@ -915,7 +958,7 @@ static int client_send_discover(sd_dhcp_client *client) { } if (client->mudurl) { - r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, SD_DHCP_OPTION_MUD_URL, strlen(client->mudurl), client->mudurl); @@ -924,7 +967,7 @@ static int client_send_discover(sd_dhcp_client *client) { } if (client->user_class) { - r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, SD_DHCP_OPTION_USER_CLASS, strv_length(client->user_class), client->user_class); @@ -933,7 +976,7 @@ static int client_send_discover(sd_dhcp_client *client) { } ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) { - r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, j->option, j->length, j->data); if (r < 0) return r; @@ -941,13 +984,50 @@ static int client_send_discover(sd_dhcp_client *client) { if (!ordered_hashmap_isempty(client->vendor_options)) { r = dhcp_option_append( - &discover->dhcp, optlen, &optoffset, 0, + &packet->dhcp, optlen, optoffset, 0, SD_DHCP_OPTION_VENDOR_SPECIFIC, ordered_hashmap_size(client->vendor_options), client->vendor_options); if (r < 0) return r; } + + return 0; +} + +static int client_send_discover(sd_dhcp_client *client) { + _cleanup_free_ DHCPPacket *discover = NULL; + size_t optoffset, optlen; + int r; + + assert(client); + assert(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_SELECTING)); + + r = client_message_init(client, &discover, DHCP_DISCOVER, + &optlen, &optoffset); + if (r < 0) + return r; + + /* the client may suggest values for the network address + and lease time in the DHCPDISCOVER message. The client may include + the ’requested IP address’ option to suggest that a particular IP + address be assigned, and may include the ’IP address lease time’ + option to suggest the lease time it would like. + */ + /* RFC7844 section 3: + SHOULD NOT contain any other option. */ + if (!client->anonymize && client->last_addr != INADDR_ANY) { + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, + 4, &client->last_addr); + if (r < 0) + return r; + } + + r = client_append_common_discover_request_options(client, discover, &optoffset, optlen); + if (r < 0) + return r; + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL); if (r < 0) @@ -1039,36 +1119,9 @@ static int client_send_request(sd_dhcp_client *client) { return -EINVAL; } - if (client->hostname) { - if (dns_name_is_single_label(client->hostname)) - r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_HOST_NAME, - strlen(client->hostname), client->hostname); - else - r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset, - client->hostname); - if (r < 0) - return r; - } - - if (client->vendor_class_identifier) { - r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, - strlen(client->vendor_class_identifier), - client->vendor_class_identifier); - if (r < 0) - return r; - } - - if (client->mudurl) { - r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_MUD_URL, - strlen(client->mudurl), - client->mudurl); - if (r < 0) - return r; - } - + r = client_append_common_discover_request_options(client, request, &optoffset, optlen); + if (r < 0) + return r; r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL); @@ -1424,6 +1477,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_ lease->next_server = offer->siaddr; lease->address = offer->yiaddr; + if (lease->lifetime == 0 && client->fallback_lease_lifetime > 0) + lease->lifetime = client->fallback_lease_lifetime; + if (lease->address == 0 || lease->server_address == 0 || lease->lifetime == 0) { @@ -1904,13 +1960,13 @@ static int client_receive_message_raw( sd_dhcp_client *client = userdata; _cleanup_free_ DHCPPacket *packet = NULL; - uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; + CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata))) control; struct iovec iov = {}; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, - .msg_control = cmsgbuf, - .msg_controllen = sizeof(cmsgbuf), + .msg_control = &control, + .msg_controllen = sizeof(control), }; struct cmsghdr *cmsg; bool checksum = true; @@ -1932,25 +1988,21 @@ static int client_receive_message_raw( iov = IOVEC_MAKE(packet, buflen); - len = recvmsg(fd, &msg, 0); - if (len < 0) { - if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) - return 0; - - return log_dhcp_client_errno(client, errno, - "Could not receive message from raw socket: %m"); - } else if ((size_t)len < sizeof(DHCPPacket)) + len = recvmsg_safe(fd, &msg, 0); + if (IN_SET(len, -EAGAIN, -EINTR, -ENETDOWN)) return 0; + if (len < 0) + return log_dhcp_client_errno(client, len, + "Could not receive message from raw socket: %m"); - CMSG_FOREACH(cmsg, &msg) - if (cmsg->cmsg_level == SOL_PACKET && - cmsg->cmsg_type == PACKET_AUXDATA && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) { - struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg); + if ((size_t) len < sizeof(DHCPPacket)) + return 0; - checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY); - break; - } + cmsg = cmsg_find(&msg, SOL_PACKET, PACKET_AUXDATA, CMSG_LEN(sizeof(struct tpacket_auxdata))); + if (cmsg) { + struct tpacket_auxdata *aux = (struct tpacket_auxdata*) CMSG_DATA(cmsg); + checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY); + } r = dhcp_packet_verify_headers(packet, len, checksum, client->port); if (r < 0) diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c index 86f21290..ae581f91 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c @@ -98,59 +98,40 @@ int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) { return 0; } -int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) { +int sd_dhcp_lease_get_servers( + sd_dhcp_lease *lease, + sd_dhcp_lease_server_type what, + const struct in_addr **addr) { + assert_return(lease, -EINVAL); + assert_return(what >= 0, -EINVAL); + assert_return(what < _SD_DHCP_LEASE_SERVER_TYPE_MAX, -EINVAL); assert_return(addr, -EINVAL); - if (lease->dns_size <= 0) + if (lease->servers[what].size <= 0) return -ENODATA; - *addr = lease->dns; - return (int) lease->dns_size; + *addr = lease->servers[what].addr; + return (int) lease->servers[what].size; } +int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) { + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_DNS, addr); +} int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->ntp_size <= 0) - return -ENODATA; - - *addr = lease->ntp; - return (int) lease->ntp_size; + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_NTP, addr); } - int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->sip_size <= 0) - return -ENODATA; - - *addr = lease->sip; - return (int) lease->sip_size; + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SIP, addr); } - -int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->pop3_server_size <= 0) - return -ENODATA; - - *addr = lease->pop3_server; - return (int) lease->pop3_server_size; +int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr) { + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_POP3, addr); } - -int sd_dhcp_lease_get_smtp_server(sd_dhcp_lease *lease, const struct in_addr **addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->smtp_server_size <= 0) - return -ENODATA; - - *addr = lease->smtp_server; - return (int) lease->smtp_server_size; +int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr) { + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SMTP, addr); +} +int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr) { + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_LPR, addr); } int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { @@ -300,11 +281,10 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) { free(lease->timezone); free(lease->hostname); free(lease->domainname); - free(lease->dns); - free(lease->ntp); - free(lease->sip); - free(lease->pop3_server); - free(lease->smtp_server); + + for (sd_dhcp_lease_server_type i = 0; i < _SD_DHCP_LEASE_SERVER_TYPE_MAX; i++) + free(lease->servers[i].addr); + free(lease->static_route); free(lease->client_id); free(lease->vendor_specific); @@ -410,7 +390,7 @@ static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) { } static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { - assert(option); + assert(option || len == 0); assert(ret); assert(n_ret); @@ -439,33 +419,24 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add } static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { - assert(option); + assert(option || len == 0); assert(ret); assert(n_ret); - if (len <= 0) { - *ret = mfree(*ret); - *n_ret = 0; - } else { - size_t n_addresses; - struct in_addr *addresses; - int l = len - 1; - - if (l % 4 != 0) - return -EINVAL; - - n_addresses = l / 4; + if (len <= 0) + return -EINVAL; - addresses = newdup(struct in_addr, option + 1, n_addresses); - if (!addresses) - return -ENOMEM; + /* The SIP record is like the other, regular server records, but prefixed with a single "encoding" + * byte that is either 0 or 1. We only support it to be 1 for now. Let's drop it and parse it like + * the other fields */ - free(*ret); - *ret = addresses; - *n_ret = n_addresses; + if (option[0] != 1) { /* We only support IP address encoding for now */ + *ret = mfree(*ret); + *n_ret = 0; + return 0; } - return 0; + return lease_parse_in_addrs(option + 1, len - 1, ret, n_ret); } static int lease_parse_routes( @@ -610,35 +581,41 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void break; case SD_DHCP_OPTION_DOMAIN_NAME_SERVER: - r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size); + r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_DNS].addr, &lease->servers[SD_DHCP_LEASE_DNS].size); if (r < 0) log_debug_errno(r, "Failed to parse DNS server, ignoring: %m"); break; case SD_DHCP_OPTION_NTP_SERVER: - r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size); + r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_NTP].addr, &lease->servers[SD_DHCP_LEASE_NTP].size); if (r < 0) log_debug_errno(r, "Failed to parse NTP server, ignoring: %m"); break; case SD_DHCP_OPTION_SIP_SERVER: - r = lease_parse_sip_server(option, len, &lease->sip, &lease->sip_size); + r = lease_parse_sip_server(option, len, &lease->servers[SD_DHCP_LEASE_SIP].addr, &lease->servers[SD_DHCP_LEASE_SIP].size); if (r < 0) log_debug_errno(r, "Failed to parse SIP server, ignoring: %m"); break; case SD_DHCP_OPTION_POP3_SERVER: - r = lease_parse_in_addrs(option, len, &lease->pop3_server, &lease->pop3_server_size); + r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_POP3].addr, &lease->servers[SD_DHCP_LEASE_POP3].size); if (r < 0) log_debug_errno(r, "Failed to parse POP3 server, ignoring: %m"); break; case SD_DHCP_OPTION_SMTP_SERVER: - r = lease_parse_in_addrs(option, len, &lease->smtp_server, &lease->smtp_server_size); + r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_SMTP].addr, &lease->servers[SD_DHCP_LEASE_SMTP].size); if (r < 0) log_debug_errno(r, "Failed to parse SMTP server, ignoring: %m"); break; + case SD_DHCP_OPTION_LPR_SERVER: + r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_LPR].addr, &lease->servers[SD_DHCP_LEASE_LPR].size); + if (r < 0) + log_debug_errno(r, "Failed to parse LPR server, ignoring: %m"); + break; + case SD_DHCP_OPTION_STATIC_ROUTE: r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); if (r < 0) @@ -674,7 +651,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void case SD_DHCP_OPTION_HOST_NAME: r = lease_parse_domain(option, len, &lease->hostname); if (r < 0) { - log_debug_errno(r, "Failed to parse host name, ignoring: %m"); + log_debug_errno(r, "Failed to parse hostname, ignoring: %m"); return 0; } @@ -1075,8 +1052,9 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { *dns = NULL, *ntp = NULL, *sip = NULL, - *pop3_server = NULL, - *smtp_server = NULL, + *pop3 = NULL, + *smtp = NULL, + *lpr = NULL, *mtu = NULL, *routes = NULL, *domains = NULL, @@ -1106,8 +1084,9 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { "DNS", &dns, "NTP", &ntp, "SIP", &sip, - "POP3_SERVERS", &pop3_server, - "SMTP_SERVERS", &smtp_server, + "POP3", &pop3, + "SMTP", &smtp, + "LPR", &lpr, "MTU", &mtu, "DOMAINNAME", &lease->domainname, "HOSTNAME", &lease->hostname, @@ -1197,43 +1176,51 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { } if (dns) { - r = deserialize_in_addrs(&lease->dns, dns); + r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_DNS].addr, dns); if (r < 0) log_debug_errno(r, "Failed to deserialize DNS servers %s, ignoring: %m", dns); else - lease->dns_size = r; + lease->servers[SD_DHCP_LEASE_DNS].size = r; } if (ntp) { - r = deserialize_in_addrs(&lease->ntp, ntp); + r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_NTP].addr, ntp); if (r < 0) log_debug_errno(r, "Failed to deserialize NTP servers %s, ignoring: %m", ntp); else - lease->ntp_size = r; + lease->servers[SD_DHCP_LEASE_NTP].size = r; } if (sip) { - r = deserialize_in_addrs(&lease->sip, sip); + r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_SIP].addr, sip); if (r < 0) log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip); else - lease->sip_size = r; + lease->servers[SD_DHCP_LEASE_SIP].size = r; + } + + if (pop3) { + r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_POP3].addr, pop3); + if (r < 0) + log_debug_errno(r, "Failed to deserialize POP3 server %s, ignoring: %m", pop3); + else + lease->servers[SD_DHCP_LEASE_POP3].size = r; } - if (pop3_server) { - r = deserialize_in_addrs(&lease->pop3_server, pop3_server); + if (smtp) { + r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_SMTP].addr, smtp); if (r < 0) - log_debug_errno(r, "Failed to deserialize POP3 server %s, ignoring: %m", pop3_server); + log_debug_errno(r, "Failed to deserialize SMTP server %s, ignoring: %m", smtp); else - lease->pop3_server_size = r; + lease->servers[SD_DHCP_LEASE_SMTP].size = r; } - if (smtp_server) { - r = deserialize_in_addrs(&lease->smtp_server, smtp_server); + if (lpr) { + r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_LPR].addr, lpr); if (r < 0) - log_debug_errno(r, "Failed to deserialize SMTP server %s, ignoring: %m", smtp_server); + log_debug_errno(r, "Failed to deserialize LPR server %s, ignoring: %m", lpr); else - lease->smtp_server_size = r; + lease->servers[SD_DHCP_LEASE_LPR].size = r; } if (mtu) { diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index 826ad56a..d653b257 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -20,6 +20,7 @@ #include "dns-domain.h" #include "event-util.h" #include "fd-util.h" +#include "hexdecoct.h" #include "hostname-util.h" #include "in-addr-util.h" #include "network-internal.h" @@ -69,6 +70,8 @@ struct sd_dhcp6_client { size_t req_opts_len; char *fqdn; char *mudurl; + char **user_class; + char **vendor_class; sd_event_source *receive_message; usec_t retransmit_time; uint8_t retransmit_count; @@ -80,6 +83,8 @@ struct sd_dhcp6_client { size_t duid_len; usec_t information_request_time_usec; usec_t information_refresh_time_usec; + OrderedHashmap *extra_options; + OrderedHashmap *vendor_options; }; static const uint16_t default_req_opts[] = { @@ -108,12 +113,29 @@ const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int); const char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = { - [DHCP6_STATUS_SUCCESS] = "Success", - [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure", - [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available", - [DHCP6_STATUS_NO_BINDING] = "Binding unavailable", - [DHCP6_STATUS_NOT_ON_LINK] = "Not on link", - [DHCP6_STATUS_USE_MULTICAST] = "Use multicast", + [DHCP6_STATUS_SUCCESS] = "Success", + [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure", + [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available", + [DHCP6_STATUS_NO_BINDING] = "Binding unavailable", + [DHCP6_STATUS_NOT_ON_LINK] = "Not on link", + [DHCP6_STATUS_USE_MULTICAST] = "Use multicast", + [DHCP6_STATUS_NO_PREFIX_AVAIL] = "No prefix available", + [DHCP6_STATUS_UNKNOWN_QUERY_TYPE] = "Unknown query type", + [DHCP6_STATUS_MALFORMED_QUERY] = "Malformed query", + [DHCP6_STATUS_NOT_CONFIGURED] = "Not configured", + [DHCP6_STATUS_NOT_ALLOWED] = "Not allowed", + [DHCP6_STATUS_QUERY_TERMINATED] = "Query terminated", + [DHCP6_STATUS_DATA_MISSING] = "Data missing", + [DHCP6_STATUS_CATCHUP_COMPLETE] = "Catch up complete", + [DHCP6_STATUS_NOT_SUPPORTED] = "Not supported", + [DHCP6_STATUS_TLS_CONNECTION_REFUSED] = "TLS connection refused", + [DHCP6_STATUS_ADDRESS_IN_USE] = "Address in use", + [DHCP6_STATUS_CONFIGURATION_CONFLICT] = "Configuration conflict", + [DHCP6_STATUS_MISSING_BINDING_INFORMATION] = "Missing binding information", + [DHCP6_STATUS_OUTDATED_BINDING_INFORMATION] = "Outdated binding information", + [DHCP6_STATUS_SERVER_SHUTTING_DOWN] = "Server shutting down", + [DHCP6_STATUS_DNS_UPDATE_NOT_SUPPORTED] = "DNS update not supported", + [DHCP6_STATUS_EXCESSIVE_TIME_SKEW] = "Excessive time skew", }; DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int); @@ -207,6 +229,25 @@ int sd_dhcp6_client_set_prefix_delegation_hint( return 0; } +int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client, sd_dhcp6_option *v) { + int r; + + assert_return(client, -EINVAL); + assert_return(v, -EINVAL); + + r = ordered_hashmap_ensure_allocated(&client->vendor_options, &dhcp6_option_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(client->vendor_options, v, v); + if (r < 0) + return r; + + sd_dhcp6_option_ref(v); + + return 1; +} + static int client_ensure_duid(sd_dhcp6_client *client) { if (client->duid_len != 0) return 0; @@ -237,7 +278,8 @@ static int dhcp6_client_set_duid_internal( r = dhcp_validate_duid_len(duid_type, duid_len, false); if (r < 0) return log_dhcp6_client_errno(client, r, "Failed to validate length of DUID: %m"); - log_dhcp6_client(client, "Setting DUID of type %u with unexpected content", duid_type); + + log_dhcp6_client(client, "Using DUID of type %u of incorrect length, proceeding.", duid_type); } client->duid.type = htobe16(duid_type); @@ -296,6 +338,48 @@ int sd_dhcp6_client_set_duid_llt( return dhcp6_client_set_duid_internal(client, DUID_TYPE_LLT, NULL, 0, llt_time); } +static const char* const dhcp6_duid_type_table[_DUID_TYPE_MAX] = { + [DUID_TYPE_LLT] = "DUID-LLT", + [DUID_TYPE_EN] = "DUID-EN/Vendor", + [DUID_TYPE_LL] = "DUID-LL", + [DUID_TYPE_UUID] = "UUID", +}; +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(dhcp6_duid_type, DUIDType); + +int sd_dhcp6_client_duid_as_string( + sd_dhcp6_client *client, + char **duid) { + _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; + const char *v; + int r; + + assert_return(client, -EINVAL); + assert_return(client->duid_len > 0, -ENODATA); + + v = dhcp6_duid_type_to_string(be16toh(client->duid.type)); + if (v) { + s = strdup(v); + if (!s) + return -ENOMEM; + } else { + r = asprintf(&s, "%0x", client->duid.type); + if (r < 0) + return -ENOMEM; + } + + t = hexmem(&client->duid.raw.data, client->duid_len); + if (!t) + return -ENOMEM; + + p = strjoin(s, ":", t); + if (!p) + return -ENOMEM; + + *duid = TAKE_PTR(p); + + return 0; +} + int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) { assert_return(client, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); @@ -307,6 +391,18 @@ int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) { return 0; } +int sd_dhcp6_client_get_iaid(sd_dhcp6_client *client, uint32_t *iaid) { + assert_return(client, -EINVAL); + assert_return(iaid, -EINVAL); + + if (!client->iaid_set) + return -ENODATA; + + *iaid = be32toh(client->ia_na.ia_na.id); + + return 0; +} + int sd_dhcp6_client_set_fqdn( sd_dhcp6_client *client, const char *fqdn) { @@ -345,18 +441,8 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) assert_return(client, -EINVAL); assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); - switch(option) { - - case SD_DHCP6_OPTION_DNS_SERVERS: - case SD_DHCP6_OPTION_DOMAIN_LIST: - case SD_DHCP6_OPTION_SNTP_SERVERS: - case SD_DHCP6_OPTION_NTP_SERVER: - case SD_DHCP6_OPTION_RAPID_COMMIT: - break; - - default: + if (option <= 0 || option >= UINT8_MAX) return -EINVAL; - } for (t = 0; t < client->req_opts_len; t++) if (client->req_opts[t] == htobe16(option)) @@ -371,17 +457,60 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) return 0; } -int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, char *mudurl) { +int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mudurl) { assert_return(client, -EINVAL); assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); assert_return(mudurl, -EINVAL); - assert_return(strlen(mudurl) <= 255, -EINVAL); + assert_return(strlen(mudurl) <= UINT8_MAX, -EINVAL); assert_return(http_url_is_valid(mudurl), -EINVAL); return free_and_strdup(&client->mudurl, mudurl); } +int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_class) { + _cleanup_strv_free_ char **s = NULL; + char **p; + + assert_return(client, -EINVAL); + assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); + + assert_return(user_class, -EINVAL); + + STRV_FOREACH(p, user_class) + if (strlen(*p) > UINT16_MAX) + return -ENAMETOOLONG; + + s = strv_copy(user_class); + if (!s) + return -ENOMEM; + + client->user_class = TAKE_PTR(s); + + return 0; +} + +int sd_dhcp6_client_set_request_vendor_class(sd_dhcp6_client *client, char **vendor_class) { + _cleanup_strv_free_ char **s = NULL; + char **p; + + assert_return(client, -EINVAL); + assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); + assert_return(vendor_class, -EINVAL); + + STRV_FOREACH(p, vendor_class) + if (strlen(*p) > UINT8_MAX) + return -ENAMETOOLONG; + + s = strv_copy(vendor_class); + if (!s) + return -ENOMEM; + + client->vendor_class = TAKE_PTR(s); + + return 0; +} + int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) { assert_return(client, -EINVAL); assert_return(delegation, -EINVAL); @@ -436,6 +565,24 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) { return 0; } +int sd_dhcp6_client_add_option(sd_dhcp6_client *client, sd_dhcp6_option *v) { + int r; + + assert_return(client, -EINVAL); + assert_return(v, -EINVAL); + + r = ordered_hashmap_ensure_allocated(&client->extra_options, &dhcp6_option_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(client->extra_options, UINT_TO_PTR(v->option), v); + if (r < 0) + return r; + + sd_dhcp6_option_ref(v); + return 0; +} + static void client_notify(sd_dhcp6_client *client, int event) { assert(client); @@ -481,7 +628,9 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { _cleanup_free_ DHCP6Message *message = NULL; struct in6_addr all_servers = IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; + struct sd_dhcp6_option *j; size_t len, optlen = 512; + Iterator i; uint8_t *opt; int r; usec_t elapsed_usec; @@ -542,6 +691,25 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; } + if (client->user_class) { + r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class); + if (r < 0) + return r; + } + + if (client->vendor_class) { + r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class); + if (r < 0) + return r; + } + + if (!ordered_hashmap_isempty(client->vendor_options)) { + r = dhcp6_option_append_vendor_option(&opt, &optlen, + client->vendor_options); + if (r < 0) + return r; + } + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix); if (r < 0) @@ -588,6 +756,24 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; } + if (client->user_class) { + r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class); + if (r < 0) + return r; + } + + if (client->vendor_class) { + r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class); + if (r < 0) + return r; + } + + if (!ordered_hashmap_isempty(client->vendor_options)) { + r = dhcp6_option_append_vendor_option(&opt, &optlen, client->vendor_options); + if (r < 0) + return r; + } + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); if (r < 0) @@ -622,6 +808,24 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; } + if (client->user_class) { + r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class); + if (r < 0) + return r; + } + + if (client->vendor_class) { + r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class); + if (r < 0) + return r; + } + + if (!ordered_hashmap_isempty(client->vendor_options)) { + r = dhcp6_option_append_vendor_option(&opt, &optlen, client->vendor_options); + if (r < 0) + return r; + } + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); if (r < 0) @@ -661,6 +865,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (r < 0) return r; + ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) { + r = dhcp6_option_append(&opt, &optlen, j->option, j->length, j->data); + if (r < 0) + return r; + } + r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message, len - optlen); if (r < 0) @@ -888,10 +1098,11 @@ static int client_parse_message( size_t len, sd_dhcp6_lease *lease) { + uint16_t ia_na_status = 0, ia_pd_status = 0; uint32_t lt_t1 = ~0, lt_t2 = ~0; + usec_t irt = IRT_DEFAULT; bool clientid = false; size_t pos = 0; - usec_t irt = IRT_DEFAULT; int r; assert(client); @@ -905,8 +1116,8 @@ static int client_parse_message( DHCP6Option *option = (DHCP6Option *) &message->options[pos]; uint16_t optcode, optlen; be32_t iaid_lease; + int status; uint8_t *optval; - int status; if (len < pos + offsetof(DHCP6Option, data)) return -ENOBUFS; @@ -983,10 +1194,15 @@ static int client_parse_message( break; } - r = dhcp6_option_parse_ia(option, &lease->ia); + r = dhcp6_option_parse_ia(option, &lease->ia, &ia_na_status); if (r < 0 && r != -ENOMSG) return r; + if (ia_na_status == DHCP6_STATUS_NO_ADDRS_AVAIL) { + pos += offsetof(DHCP6Option, data) + optlen; + continue; + } + r = dhcp6_lease_get_iaid(lease, &iaid_lease); if (r < 0) return r; @@ -1011,10 +1227,15 @@ static int client_parse_message( break; } - r = dhcp6_option_parse_ia(option, &lease->pd); + r = dhcp6_option_parse_ia(option, &lease->pd, &ia_pd_status); if (r < 0 && r != -ENOMSG) return r; + if (ia_pd_status == DHCP6_STATUS_NO_PREFIX_AVAIL) { + pos += offsetof(DHCP6Option, data) + optlen; + continue; + } + r = dhcp6_lease_get_pd_iaid(lease, &iaid_lease); if (r < 0) return r; @@ -1078,6 +1299,11 @@ static int client_parse_message( pos += offsetof(DHCP6Option, data) + optlen; } + if (ia_na_status > 0 && ia_pd_status > 0) { + log_dhcp6_client(client, "No IA_PD prefix or IA_NA address received. Ignoring."); + return -EINVAL; + } + if (!clientid) { log_dhcp6_client(client, "%s has incomplete options", dhcp6_message_type_to_string(message->type)); @@ -1573,6 +1799,11 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) { free(client->req_opts); free(client->fqdn); free(client->mudurl); + + ordered_hashmap_free(client->extra_options); + strv_free(client->user_class); + strv_free(client->vendor_class); + return mfree(client); } diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c index 35caec7a..b6dc0279 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c @@ -215,7 +215,7 @@ int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { return 0; } -int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) { +int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **addrs) { assert_return(lease, -EINVAL); assert_return(addrs, -EINVAL); @@ -343,7 +343,7 @@ int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) } int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, - struct in6_addr **addrs) { + const struct in6_addr **addrs) { assert_return(lease, -EINVAL); assert_return(addrs, -EINVAL); diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c index a610546c..0bfaf265 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c @@ -254,12 +254,14 @@ static int ipv4ll_start_internal(sd_ipv4ll *ll, bool reset_generation) { return r; } - return 0; + return 1; } int sd_ipv4ll_start(sd_ipv4ll *ll) { assert_return(ll, -EINVAL); - assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); + + if (sd_ipv4ll_is_running(ll)) + return 0; return ipv4ll_start_internal(ll, true); } diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c index bdf58dac..eb083f5e 100644 --- a/src/systemd/src/libsystemd-network/sd-lldp.c +++ b/src/systemd/src/libsystemd-network/sd-lldp.c @@ -468,7 +468,7 @@ _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { _public_ int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t m) { assert_return(lldp, -EINVAL); - assert_return(m <= 0, -EINVAL); + assert_return(m > 0, -EINVAL); lldp->neighbors_max = m; lldp_make_space(lldp, 0); diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h index da2aa6c7..ac3b5b36 100644 --- a/src/systemd/src/systemd/sd-dhcp-client.h +++ b/src/systemd/src/systemd/sd-dhcp-client.h @@ -48,6 +48,7 @@ enum { SD_DHCP_OPTION_TIME_OFFSET = 2, SD_DHCP_OPTION_ROUTER = 3, SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6, + SD_DHCP_OPTION_LPR_SERVER = 9, SD_DHCP_OPTION_HOST_NAME = 12, SD_DHCP_OPTION_BOOT_FILE_SIZE = 13, SD_DHCP_OPTION_DOMAIN_NAME = 15, @@ -184,6 +185,9 @@ int sd_dhcp_client_get_lease( int sd_dhcp_client_set_service_type( sd_dhcp_client *client, int type); +int sd_dhcp_client_set_fallback_lease_lifetime( + sd_dhcp_client *client, + uint32_t fallback_lease_lifetime); int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v); int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v); @@ -201,6 +205,8 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client); * options when using RFC7844 Anonymity Profiles */ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize); +int sd_dhcp_client_id_to_string(const void *data, size_t len, char **ret); + int sd_dhcp_client_attach_event( sd_dhcp_client *client, sd_event *event, diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h index 1ed5bf27..17bd4918 100644 --- a/src/systemd/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/src/systemd/sd-dhcp-lease.h @@ -33,6 +33,17 @@ typedef struct sd_dhcp_route sd_dhcp_route; sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease); sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease); +typedef enum sd_dhcp_lease_server_type { + SD_DHCP_LEASE_DNS, + SD_DHCP_LEASE_NTP, + SD_DHCP_LEASE_SIP, + SD_DHCP_LEASE_POP3, + SD_DHCP_LEASE_SMTP, + SD_DHCP_LEASE_LPR, + _SD_DHCP_LEASE_SERVER_TYPE_MAX, + _SD_DHCP_LEASE_SERVER_TYPE_INVALID = -1, +} sd_dhcp_lease_server_type; + int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime); int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1); @@ -42,11 +53,13 @@ int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr); +int sd_dhcp_lease_get_servers(sd_dhcp_lease *lease, sd_dhcp_lease_server_type what, const struct in_addr **addr); int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr); -int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr); -int sd_dhcp_lease_get_smtp_server(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains); diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h index 42d4ec75..2b0d63a5 100644 --- a/src/systemd/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/src/systemd/sd-dhcp6-client.h @@ -24,6 +24,7 @@ #include <sys/types.h> #include "sd-dhcp6-lease.h" +#include "sd-dhcp6-option.h" #include "sd-event.h" #include "_sd-common.h" @@ -109,6 +110,12 @@ int sd_dhcp6_client_set_duid_llt( int sd_dhcp6_client_set_iaid( sd_dhcp6_client *client, uint32_t iaid); +int sd_dhcp6_client_get_iaid( + sd_dhcp6_client *client, + uint32_t *iaid); +int sd_dhcp6_client_duid_as_string( + sd_dhcp6_client *client, + char **duid); int sd_dhcp6_client_set_fqdn( sd_dhcp6_client *client, const char *fqdn); @@ -123,7 +130,13 @@ int sd_dhcp6_client_set_request_option( uint16_t option); int sd_dhcp6_client_set_request_mud_url( sd_dhcp6_client *client, - char *mudurl); + const char *mudurl); +int sd_dhcp6_client_set_request_user_class( + sd_dhcp6_client *client, + char** user_class); +int sd_dhcp6_client_set_request_vendor_class( + sd_dhcp6_client *client, + char** vendor_class); int sd_dhcp6_client_set_prefix_delegation_hint( sd_dhcp6_client *client, uint8_t prefixlen, @@ -136,12 +149,17 @@ int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client, int *request); int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client, int request); -int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transaction_id); +int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, + uint32_t transaction_id); +int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client, + sd_dhcp6_option *v); int sd_dhcp6_client_get_lease( sd_dhcp6_client *client, sd_dhcp6_lease **ret); +int sd_dhcp6_client_add_option(sd_dhcp6_client *client, sd_dhcp6_option *v); + int sd_dhcp6_client_stop(sd_dhcp6_client *client); int sd_dhcp6_client_start(sd_dhcp6_client *client); int sd_dhcp6_client_is_running(sd_dhcp6_client *client); diff --git a/src/systemd/src/systemd/sd-dhcp6-lease.h b/src/systemd/src/systemd/sd-dhcp6-lease.h index 33a32a6d..4301c6db 100644 --- a/src/systemd/src/systemd/sd-dhcp6-lease.h +++ b/src/systemd/src/systemd/sd-dhcp6-lease.h @@ -39,10 +39,9 @@ int sd_dhcp6_lease_get_pd(sd_dhcp6_lease *lease, struct in6_addr *prefix, uint32_t *lifetime_preferred, uint32_t *lifetime_valid); -int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs); +int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **addrs); int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains); -int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, - struct in6_addr **addrs); +int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr **addrs); int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn); sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease); diff --git a/src/systemd/src/systemd/sd-dhcp6-option.h b/src/systemd/src/systemd/sd-dhcp6-option.h new file mode 100644 index 00000000..88a49863 --- /dev/null +++ b/src/systemd/src/systemd/sd-dhcp6-option.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddhcp6optionhfoo +#define foosddhcp6optionhfoo + +/*** + 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 <inttypes.h> +#include <sys/types.h> + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_dhcp6_option sd_dhcp6_option; + +int sd_dhcp6_option_new(uint16_t option, const void *data, size_t length, uint32_t enterprise_identifier, sd_dhcp6_option **ret); +sd_dhcp6_option *sd_dhcp6_option_ref(sd_dhcp6_option *ra); +sd_dhcp6_option *sd_dhcp6_option_unref(sd_dhcp6_option *ra); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_option, sd_dhcp6_option_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h index bf3afadc..2dc9f632 100644 --- a/src/systemd/src/systemd/sd-lldp.h +++ b/src/systemd/src/systemd/sd-lldp.h @@ -96,6 +96,9 @@ enum { #define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 } #define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f } +#define SD_LLDP_OUI_MUD (uint8_t[]) { 0x00, 0x00, 0x5E } +#define SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION 0x01 + /* IEEE 802.1AB-2009 Annex E */ enum { SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1, @@ -169,6 +172,7 @@ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec); int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret); int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret); int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret); int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret); int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret); diff --git a/src/systemd/src/systemd/sd-ndisc.h b/src/systemd/src/systemd/sd-ndisc.h index d1bee343..3ddfc8cb 100644 --- a/src/systemd/src/systemd/sd-ndisc.h +++ b/src/systemd/src/systemd/sd-ndisc.h @@ -30,7 +30,7 @@ _SD_BEGIN_DECLARATIONS; -/* Neightbor Discovery Options, RFC 4861, Section 4.6 and +/* Neighbor Discovery Options, RFC 4861, Section 4.6 and * https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-5 */ enum { SD_NDISC_OPTION_SOURCE_LL_ADDRESS = 1, |