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; > > 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 < 0) > + return r; > + > + break; > + > + case DHCP6_OPTION_NTP_SERVER: > + r = dhcp6_lease_set_ntp(lease, optval, optlen); > + if (r < 0) > + return r; > + > + break; > } > + > } > > if (r == -ENOMSG) > diff --git a/src/libsystemd-network/sd-dhcp6-lease.c > b/src/libsystemd-network/sd-dhcp6-lease.c > index b3ae0c0..9b3af50 100644 > --- a/src/libsystemd-network/sd-dhcp6-lease.c > +++ b/src/libsystemd-network/sd-dhcp6-lease.c > @@ -23,6 +23,7 @@ > #include "util.h" > > #include "dhcp6-lease-internal.h" > +#include "dhcp6-protocol.h" > > int dhcp6_lease_clear_timers(DHCP6IA *ia) { > assert_return(ia, -EINVAL); > @@ -179,6 +180,140 @@ int sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease > *lease) { > return 0; > } > > +int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t > optlen) { > + int r; > + > + assert_return(lease, -EINVAL); > + assert_return(optval, -EINVAL); > + > + if (!optlen) == 0 > + return 0; > + > + r = dhcp6_option_get_ip6addrs(optval, optlen, &lease->dns, > + &lease->dns_size, &lease->dns_allocated); > + if (r < 0) { > + log_dhcp6_client(client, "Invalid DNS server option: %s", > + strerror(-r)); > + > + return r; > + } > + > + return 0; > +} > + > +int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) { > + assert_return(lease, -EINVAL); > + assert_return(addrs, -EINVAL); > + > + if (lease->dns_size) { > + *addrs = lease->dns; > + return lease->dns_size / 16; > + } > + > + return -ENOENT; > +} > + > +int dhcp6_lease_set_domain_list(sd_dhcp6_lease *lease, uint8_t *optval, > + size_t optlen) { > + assert_return(lease, -EINVAL); > + assert_return(optval, -EINVAL); > + > + if (!optlen) > + return 0; > + > + if (!GREEDY_REALLOC0(lease->domain_list, > lease->domain_list_allocated, > + lease->domain_list_size + optlen)) > + return -ENOMEM; > + > + memcpy(lease->domain_list + lease->domain_list_size, optval, optlen); > + lease->domain_list_size += optlen; > + > + return 0; > +} > + > +int sd_dhcp6_lease_get_domain_list(sd_dhcp6_lease *lease, char > **domain_list) { > + assert_return(lease, -EINVAL); > + assert_return(domain_list, -EINVAL); > + > + if (lease->domain_list_size) { > + *domain_list = lease->domain_list; > + return lease->domain_list_size; > + } > + > + return -ENOENT; > +} > + > +int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t > optlen) > +{ > + int r; > + uint16_t subopt; > + size_t sublen; > + uint8_t *subval; > + > + while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen, > + &subval)) >= 0) { > + int s; > + > + switch(subopt) { > + case DHCP6_NTP_SUBOPTION_SRV_ADDR: > + case DHCP6_NTP_SUBOPTION_MC_ADDR: > + if (sublen != 16) > + return 0; > + > + s = dhcp6_option_get_ip6addrs(subval, sublen, > + &lease->ntp, > &lease->ntp_size, > + &lease->ntp_allocated); > + if (s < 0) > + return s; > + > + break; > + > + case DHCP6_NTP_SUBOPTION_SRV_FQDN: > + if (!GREEDY_REALLOC0(lease->ntp_fqdn, > + lease->ntp_fqdn_allocated, > + lease->ntp_fqdn_size + > optlen)) > + return -ENOMEM; > + > + memcpy(lease->ntp_fqdn + lease->ntp_fqdn_size, > + optval, optlen); > + lease->ntp_fqdn_size += optlen; > + > + break; > + } > + > + } > + > + if (r != -ENOMSG) > + return r; > + > + return 0; > +} > + > +int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, > + struct in6_addr **addrs) { > + assert_return(lease, -EINVAL); > + assert_return(addrs, -EINVAL); > + > + if (lease->ntp_size) { > + *addrs = lease->ntp; > + return lease->ntp_size / 16; > + } > + > + return -ENOENT; > +} > + > +int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char **ntp_fqdn) { > + assert_return(lease, -EINVAL); > + assert_return(ntp_fqdn, -EINVAL); > + > + if (lease->ntp_fqdn_size) { > + *ntp_fqdn = lease->ntp_fqdn; > + return lease->ntp_fqdn_size; > + } > + > + return -ENOENT; > +} > + > sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) { > if (lease) > assert_se(REFCNT_INC(lease->n_ref) >= 2); > @@ -191,6 +326,11 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease > *lease) { > free(lease->serverid); > dhcp6_lease_free_ia(&lease->ia); > > + free(lease->dns); > + free(lease->domain_list); > + free(lease->ntp); > + free(lease->ntp_fqdn); > + > free(lease); > } > > diff --git a/src/systemd/sd-dhcp6-lease.h b/src/systemd/sd-dhcp6-lease.h > index f7f3d76..e90e7c6 100644 > --- a/src/systemd/sd-dhcp6-lease.h > +++ b/src/systemd/sd-dhcp6-lease.h > @@ -33,6 +33,12 @@ int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, > 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_domain_list(sd_dhcp6_lease *lease, char > **search_list); > +int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, > + 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); > sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease); Zbyszek _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel