Re: [systemd-devel] [PATCH 11/11] sd_dhcp6_lease: Support DNS and NTP options
On Tue, Jan 13, 2015 at 02:02:21PM +0200, Patrik Flykt wrote: Store arrays of found DNS and NTP IPv6 addresses and strings of DNS search domains and NTP host names as specified in RFC 3646 and RFC 5908. --- src/libsystemd-network/dhcp6-internal.h | 3 + src/libsystemd-network/dhcp6-lease-internal.h | 18 src/libsystemd-network/dhcp6-option.c | 22 src/libsystemd-network/dhcp6-protocol.h | 6 ++ src/libsystemd-network/sd-dhcp6-client.c | 22 src/libsystemd-network/sd-dhcp6-lease.c | 140 ++ src/systemd/sd-dhcp6-lease.h | 6 ++ 7 files changed, 217 insertions(+) diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h index 4f54ad8..fd7deb9 100644 --- a/src/libsystemd-network/dhcp6-internal.h +++ b/src/libsystemd-network/dhcp6-internal.h @@ -68,6 +68,9 @@ int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, DHCP6IA *ia); +int dhcp6_option_get_ip6addrs(uint8_t *optval, uint16_t optlen, +struct in6_addr **addrs, size_t *size, +size_t *allocated); int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address); int dhcp6_network_send_udp_socket(int s, struct in6_addr *address, diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h index 109e0f4..dcc7913 100644 --- a/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libsystemd-network/dhcp6-lease-internal.h @@ -40,6 +40,19 @@ struct sd_dhcp6_lease { DHCP6IA ia; DHCP6Address *addr_iter; + +struct in6_addr *dns; +size_t dns_size; +size_t dns_allocated; +char *domain_list; +size_t domain_list_size; +size_t domain_list_allocated; This would be confusing, since we often use size to mean allocated size. And also it's not a list. Maybe domains, domains_count, domains_allocated? +struct in6_addr *ntp; +size_t ntp_size; +size_t ntp_allocated; +char *ntp_fqdn; +size_t ntp_fqdn_size; +size_t ntp_fqdn_allocated; }; int dhcp6_lease_clear_timers(DHCP6IA *ia); @@ -56,6 +69,11 @@ int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit); int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid); +int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); +int dhcp6_lease_set_domain_list(sd_dhcp6_lease *lease, uint8_t *optval, +size_t optlen); +int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); + int dhcp6_lease_new(sd_dhcp6_lease **ret); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref); diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index ea863f4..7a7aad4 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -317,3 +317,25 @@ error: return r; } + +int dhcp6_option_get_ip6addrs(uint8_t *optval, uint16_t optlen, +struct in6_addr **addrs, size_t *size, +size_t *allocated) { +size_t in6_size = sizeof(**addrs); + +assert_return(optval, -EINVAL); +assert_return(addrs, -EINVAL); +assert_return(size, -EINVAL); + +if (optlen % in6_size) +return -EINVAL; + +if (!GREEDY_REALLOC0(*addrs, *allocated, *size + optlen)) +return -ENOMEM; Well, in this case !GREEDY_REALLOC0 seems overkill, greedy_realloc0 will be cleaner. +memcpy(*addrs + *size / in6_size, optval, optlen); + +*size += optlen; + +return 0; +} diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h index 3e0f339..9330f23 100644 --- a/src/libsystemd-network/dhcp6-protocol.h +++ b/src/libsystemd-network/dhcp6-protocol.h @@ -134,6 +134,12 @@ enum { }; enum { +DHCP6_NTP_SUBOPTION_SRV_ADDR= 1, +DHCP6_NTP_SUBOPTION_MC_ADDR = 2, +DHCP6_NTP_SUBOPTION_SRV_FQDN= 3, +}; + +enum { DHCP6_STATUS_SUCCESS= 0, DHCP6_STATUS_UNSPEC_FAIL= 1, DHCP6_STATUS_NO_ADDRS_AVAIL = 2, diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 940a606..ca6f316 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -804,7 +804,29 @@ static int client_parse_message(sd_dhcp6_client *client, return r;
[systemd-devel] [PATCH 11/11] sd_dhcp6_lease: Support DNS and NTP options
Store arrays of found DNS and NTP IPv6 addresses and strings of DNS search domains and NTP host names as specified in RFC 3646 and RFC 5908. --- src/libsystemd-network/dhcp6-internal.h | 3 + src/libsystemd-network/dhcp6-lease-internal.h | 18 src/libsystemd-network/dhcp6-option.c | 22 src/libsystemd-network/dhcp6-protocol.h | 6 ++ src/libsystemd-network/sd-dhcp6-client.c | 22 src/libsystemd-network/sd-dhcp6-lease.c | 140 ++ src/systemd/sd-dhcp6-lease.h | 6 ++ 7 files changed, 217 insertions(+) diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h index 4f54ad8..fd7deb9 100644 --- a/src/libsystemd-network/dhcp6-internal.h +++ b/src/libsystemd-network/dhcp6-internal.h @@ -68,6 +68,9 @@ int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, DHCP6IA *ia); +int dhcp6_option_get_ip6addrs(uint8_t *optval, uint16_t optlen, +struct in6_addr **addrs, size_t *size, +size_t *allocated); int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address); int dhcp6_network_send_udp_socket(int s, struct in6_addr *address, diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h index 109e0f4..dcc7913 100644 --- a/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libsystemd-network/dhcp6-lease-internal.h @@ -40,6 +40,19 @@ struct sd_dhcp6_lease { DHCP6IA ia; DHCP6Address *addr_iter; + +struct in6_addr *dns; +size_t dns_size; +size_t dns_allocated; +char *domain_list; +size_t domain_list_size; +size_t domain_list_allocated; +struct in6_addr *ntp; +size_t ntp_size; +size_t ntp_allocated; +char *ntp_fqdn; +size_t ntp_fqdn_size; +size_t ntp_fqdn_allocated; }; int dhcp6_lease_clear_timers(DHCP6IA *ia); @@ -56,6 +69,11 @@ int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit); int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid); +int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); +int dhcp6_lease_set_domain_list(sd_dhcp6_lease *lease, uint8_t *optval, +size_t optlen); +int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); + int dhcp6_lease_new(sd_dhcp6_lease **ret); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref); diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index ea863f4..7a7aad4 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -317,3 +317,25 @@ error: return r; } + +int dhcp6_option_get_ip6addrs(uint8_t *optval, uint16_t optlen, +struct in6_addr **addrs, size_t *size, +size_t *allocated) { +size_t in6_size = sizeof(**addrs); + +assert_return(optval, -EINVAL); +assert_return(addrs, -EINVAL); +assert_return(size, -EINVAL); + +if (optlen % in6_size) +return -EINVAL; + +if (!GREEDY_REALLOC0(*addrs, *allocated, *size + optlen)) +return -ENOMEM; + +memcpy(*addrs + *size / in6_size, optval, optlen); + +*size += optlen; + +return 0; +} diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h index 3e0f339..9330f23 100644 --- a/src/libsystemd-network/dhcp6-protocol.h +++ b/src/libsystemd-network/dhcp6-protocol.h @@ -134,6 +134,12 @@ enum { }; enum { +DHCP6_NTP_SUBOPTION_SRV_ADDR= 1, +DHCP6_NTP_SUBOPTION_MC_ADDR = 2, +DHCP6_NTP_SUBOPTION_SRV_FQDN= 3, +}; + +enum { DHCP6_STATUS_SUCCESS= 0, DHCP6_STATUS_UNSPEC_FAIL= 1, DHCP6_STATUS_NO_ADDRS_AVAIL = 2, diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 940a606..ca6f316 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -804,7 +804,29 @@ static int client_parse_message(sd_dhcp6_client *client, return r; break; + +case DHCP6_OPTION_DNS_SERVERS: +r = dhcp6_lease_set_dns(lease, optval, optlen); +if (r 0) +return r; + +break; + +case DHCP6_OPTION_DOMAIN_LIST: +r = dhcp6_lease_set_domain_list(lease, optval, optlen); +if (r