diff -rup systemd-232/src/libsystemd/sd-network/sd-network.c systemd-232-new/src/libsystemd/sd-network/sd-network.c --- systemd-232/src/libsystemd/sd-network/sd-network.c 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/libsystemd/sd-network/sd-network.c 2016-11-18 11:49:42.311168130 -0800 @@ -267,6 +267,51 @@ _public_ int sd_network_link_get_carrier return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_BY", ret); } +static int network_get_file_str(const char *key, const char *fpath, int ifindex, char **ret) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; + + assert_return(ifindex > 0, -EINVAL); + assert_return(fpath, -EINVAL); + assert_return(ret, -EINVAL); + + if (asprintf(&p, "%s/%d", fpath, ifindex) < 0) + return -ENOMEM; + + r = parse_env_file(p, NEWLINE, key, &s, NULL); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) + return -ENODATA; + + *ret = s; + s = NULL; + return 0; +} + +_public_ int sd_network_link_get_clientid(int ifindex, char **clientid) { + return network_get_file_str("CLIENTID", + "/run/systemd/netif/leases", + ifindex, + clientid); +} + +_public_ int sd_network_link_get_iaid(int ifindex, char **iaid) { + return network_get_file_str("IAID", + "/run/systemd/netif/leases6", + ifindex, + iaid); +} + +_public_ int sd_network_link_get_duid(int ifindex, char **duid) { + return network_get_file_str("DUID", + "/run/systemd/netif/leases6", + ifindex, + duid); +} + static inline int MONITOR_TO_FD(sd_network_monitor *m) { return (int) (unsigned long) m - 1; } diff -rup systemd-232/src/libsystemd-network/dhcp6-lease-internal.h systemd-232-new/src/libsystemd-network/dhcp6-lease-internal.h --- systemd-232/src/libsystemd-network/dhcp6-lease-internal.h 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/libsystemd-network/dhcp6-lease-internal.h 2016-11-18 11:51:58.231165060 -0800 @@ -23,7 +23,7 @@ #include <stdint.h> #include "sd-dhcp6-lease.h" - +#include "dhcp-identifier.h" #include "dhcp6-internal.h" struct sd_dhcp6_lease { @@ -35,6 +35,8 @@ struct sd_dhcp6_lease { bool rapid_commit; DHCP6IA ia; + struct duid *duid; + size_t duid_len; DHCP6Address *addr_iter; @@ -63,6 +65,7 @@ int dhcp6_lease_set_rapid_commit(sd_dhcp 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_duid(sd_dhcp6_lease *lease, struct duid *duid, size_t duid_len); int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, @@ -72,3 +75,4 @@ int dhcp6_lease_set_sntp(sd_dhcp6_lease size_t optlen) ; int dhcp6_lease_new(sd_dhcp6_lease **ret); +int dhcp6_lease_save(sd_dhcp6_lease *lease, const char *lease_file); diff -rup systemd-232/src/libsystemd-network/sd-dhcp6-client.c systemd-232-new/src/libsystemd-network/sd-dhcp6-client.c --- systemd-232/src/libsystemd-network/sd-dhcp6-client.c 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/libsystemd-network/sd-dhcp6-client.c 2016-11-18 11:56:00.967159576 -0800 @@ -222,6 +222,23 @@ int sd_dhcp6_client_set_duid( return 0; } +int sd_dhcp6_client_get_duid(sd_dhcp6_client *client, uint16_t *duid_type, + const uint8_t **duid, size_t *duid_len) { + assert_return(client, -EINVAL); + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + *duid_type = 0; + *duid_len = 0; + *duid = NULL; + if (client->duid_len > 0) { + *duid_type = be16toh(client->duid.type); + *duid_len = client->duid_len - sizeof(client->duid.type); + *duid = client->duid.raw.data; + } + + 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); @@ -231,6 +248,14 @@ int sd_dhcp6_client_set_iaid(sd_dhcp6_cl return 0; } +int sd_dhcp6_client_get_iaid(sd_dhcp6_client *client, uint32_t *iaid) { + assert_return(client, -EINVAL); + + *iaid = be32toh(client->ia_na.id); + + return 0; +} + int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled) { assert_return(client, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); @@ -777,6 +802,10 @@ static int client_parse_message( if (r < 0 && r != -ENOMSG) return r; + r = dhcp6_lease_set_duid(lease, &client->duid, client->duid_len); + if (r < 0) + return r; + r = dhcp6_lease_get_iaid(lease, &iaid_lease); if (r < 0) return r; diff -rup systemd-232/src/libsystemd-network/sd-dhcp6-lease.c systemd-232-new/src/libsystemd-network/sd-dhcp6-lease.c --- systemd-232/src/libsystemd-network/sd-dhcp6-lease.c 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/libsystemd-network/sd-dhcp6-lease.c 2016-11-18 11:58:53.619155676 -0800 @@ -18,11 +18,15 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <arpa/inet.h> #include <errno.h> #include "alloc-util.h" #include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" +#include "fd-util.h" +#include "fileio.h" +#include "hexdecoct.h" #include "strv.h" #include "util.h" @@ -148,6 +152,15 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease return 0; } +int dhcp6_lease_set_duid(sd_dhcp6_lease *lease, struct duid *duid, size_t duid_len) { + assert_return(lease, -EINVAL); + assert_return(duid, -EINVAL); + + lease->duid = duid; + lease->duid_len = duid_len; + return 0; +} + int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr, uint32_t *lifetime_preferred, uint32_t *lifetime_valid) { @@ -406,3 +419,74 @@ int dhcp6_lease_new(sd_dhcp6_lease **ret *ret = lease; return 0; } + +int dhcp6_lease_save(sd_dhcp6_lease *lease, const char *lease_file) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + char addr6[INET6_ADDRSTRLEN]; + const char *paddr6; + struct in6_addr ip6_addr; + uint32_t lifetime_preferred, lifetime_valid; + be32_t iaid_lease; + const struct in6_addr *addresses; + int r; + + assert(lease); + assert(lease_file); + + r = fopen_temporary(lease_file, &f, &temp_path); + if (r < 0) + goto fail; + + fchmod(fileno(f), 0644); + + fprintf(f, "# This is private data. Do not parse.\n"); + + sd_dhcp6_lease_reset_address_iter(lease); + do { + r = sd_dhcp6_lease_get_address(lease, &ip6_addr, + &lifetime_preferred, + &lifetime_valid); + if (r >= 0) { + paddr6 = inet_ntop(AF_INET6, &ip6_addr, addr6, + INET6_ADDRSTRLEN); + if (paddr6 != NULL) { + fprintf(f, "ADDRESS=%s\n", paddr6); + fprintf(f, "LIFETIME_PREFERRED=%u\n", lifetime_preferred); + fprintf(f, "LIFETIME_VALID=%u\n", lifetime_valid); + } + } + } while (r >=0); + + r = dhcp6_lease_get_iaid(lease, &iaid_lease); + if (r == 0) + fprintf(f, "IAID=%u\n", be32toh(iaid_lease)); + + if (lease->duid_len > 0) { + _cleanup_free_ char *duid_hex; + + duid_hex = hexmem(lease->duid, lease->duid_len); + if (duid_hex == NULL) { + r = -ENOMEM; + goto fail; + } + fprintf(f, "DUID=%s\n", duid_hex); + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, lease_file) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save lease data %s: %m", lease_file); +} diff -rup systemd-232/src/network/networkctl.c systemd-232-new/src/network/networkctl.c --- systemd-232/src/network/networkctl.c 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/network/networkctl.c 2016-11-18 12:03:23.539149579 -0800 @@ -700,6 +700,7 @@ static int link_status_one( _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL; _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL; + _cleanup_free_ char *clientid = NULL, *duid = NULL, *iaid = NULL; _cleanup_(sd_device_unrefp) sd_device *d = NULL; char devid[2 + DECIMAL_STR_MAX(int)]; _cleanup_free_ char *t = NULL, *network = NULL; @@ -802,6 +803,18 @@ static int link_status_one( if (tz) printf(" Time Zone: %s\n", tz); + (void) sd_network_link_get_clientid(info->ifindex, &clientid); + if (clientid) + printf(" CLIENTID: %s\n", clientid); + + (void) sd_network_link_get_iaid(info->ifindex, &iaid); + if (iaid) + printf(" IAID: %s\n", iaid); + + (void) sd_network_link_get_duid(info->ifindex, &duid); + if (duid) + printf(" DUID: %s\n", duid); + (void) dump_lldp_neighbors(" Connected To: ", info->ifindex); return 0; diff -rup systemd-232/src/network/networkd.c systemd-232-new/src/network/networkd.c --- systemd-232/src/network/networkd.c 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/network/networkd.c 2016-11-18 12:15:34.639133063 -0800 @@ -64,6 +64,10 @@ int main(int argc, char *argv[]) { if (r < 0) log_warning_errno(r, "Could not create runtime directory 'leases': %m"); + r = mkdir_safe_label("/run/systemd/netif/leases6", 0755, uid, gid); + if (r < 0) + log_warning_errno(r, "Could not create runtime directory 'leases6': %m"); + r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'lldp': %m"); diff -rup systemd-232/src/network/networkd-dhcp6.c systemd-232-new/src/network/networkd-dhcp6.c --- systemd-232/src/network/networkd-dhcp6.c 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/network/networkd-dhcp6.c 2016-11-18 12:07:42.279143734 -0800 @@ -115,6 +115,7 @@ static int dhcp6_lease_address_acquired( if (r < 0) return r; } + link->dhcp6_lease = sd_dhcp6_lease_ref(lease); return 0; } @@ -137,7 +138,9 @@ static void dhcp6_handler(sd_dhcp6_clien if (sd_dhcp6_client_get_lease(client, NULL) >= 0) log_link_warning(link, "DHCPv6 lease lost"); + link->dhcp6_lease = sd_dhcp6_lease_unref(link->dhcp6_lease); link->dhcp6_configured = false; + link_dirty(link); break; case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE: @@ -156,6 +159,7 @@ static void dhcp6_handler(sd_dhcp6_clien } link->dhcp6_configured = true; + link_dirty(link); break; default: diff -rup systemd-232/src/network/networkd-link.c systemd-232-new/src/network/networkd-link.c --- systemd-232/src/network/networkd-link.c 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/network/networkd-link.c 2016-11-18 12:13:35.631135751 -0800 @@ -24,6 +24,7 @@ #include "alloc-util.h" #include "bus-util.h" #include "dhcp-lease-internal.h" +#include "dhcp6-lease-internal.h" #include "fd-util.h" #include "fileio.h" #include "netlink-util.h" @@ -459,6 +460,9 @@ static int link_new(Manager *manager, sd if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0) return -ENOMEM; + if (asprintf(&link->lease6_file, "/run/systemd/netif/leases6/%d", link->ifindex) < 0) + return -ENOMEM; + if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0) return -ENOMEM; @@ -506,10 +510,12 @@ static void link_free(Link *link) { sd_dhcp_server_unref(link->dhcp_server); sd_dhcp_client_unref(link->dhcp_client); sd_dhcp_lease_unref(link->dhcp_lease); + sd_dhcp6_lease_unref(link->dhcp6_lease); link_lldp_emit_stop(link); free(link->lease_file); + free(link->lease6_file); sd_lldp_unref(link->lldp); free(link->lldp_file); @@ -3216,6 +3222,7 @@ int link_save(Link *link) { assert(link); assert(link->state_file); assert(link->lease_file); + assert(link->lease6_file); assert(link->manager); if (link->state == LINK_STATE_LINGER) { @@ -3461,6 +3468,31 @@ int link_save(Link *link) { } else unlink(link->lease_file); + if (link->dhcp6_lease) { + struct in6_addr addr6; + uint32_t lp, lv; + assert(link->network); + + fputs("DHCP6_ADDRESS=", f); + + sd_dhcp6_lease_reset_address_iter(link->dhcp6_lease); + while (sd_dhcp6_lease_get_address(link->dhcp6_lease, + &addr6, &lp, &lv) >= 0) { + serialize_in6_addrs(f, &addr6, 1); + fputc(' ', f); + } + fputc('\n', f); + + r = dhcp6_lease_save(link->dhcp6_lease, link->lease6_file); + if (r < 0) + goto fail; + + fprintf(f, + "DHCP6_LEASE=%s\n", + link->lease6_file); + } else + unlink(link->lease6_file); + if (link->ipv4ll) { struct in_addr address; diff -rup systemd-232/src/network/networkd-link.h systemd-232-new/src/network/networkd-link.h --- systemd-232/src/network/networkd-link.h 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/network/networkd-link.h 2016-11-18 12:14:27.359134583 -0800 @@ -95,6 +95,7 @@ typedef struct Link { sd_dhcp_client *dhcp_client; sd_dhcp_lease *dhcp_lease; char *lease_file; + char *lease6_file; uint16_t original_mtu; unsigned dhcp4_messages; bool dhcp4_configured; @@ -118,6 +119,7 @@ typedef struct Link { Set *ndisc_dnssl; sd_dhcp6_client *dhcp6_client; + sd_dhcp6_lease *dhcp6_lease; bool rtnl_extended_attrs; /* This is about LLDP reception */ diff -rup systemd-232/src/systemd/sd-dhcp6-client.h systemd-232-new/src/systemd/sd-dhcp6-client.h --- systemd-232/src/systemd/sd-dhcp6-client.h 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/systemd/sd-dhcp6-client.h 2016-11-18 12:17:27.783130507 -0800 @@ -98,9 +98,17 @@ int sd_dhcp6_client_set_duid( uint16_t duid_type, const void *duid, size_t duid_len); +int sd_dhcp6_client_get_duid( + sd_dhcp6_client *client, + uint16_t *duid_type, + const uint8_t **duid, + size_t *duid_len); 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_set_information_request( sd_dhcp6_client *client, int enabled); diff -rup systemd-232/src/systemd/sd-network.h systemd-232-new/src/systemd/sd-network.h --- systemd-232/src/systemd/sd-network.h 2016-11-03 10:16:42.000000000 -0700 +++ systemd-232-new/src/systemd/sd-network.h 2016-11-18 12:18:31.199129074 -0800 @@ -145,6 +145,15 @@ int sd_network_link_get_carrier_bound_to /* Get the CARRIERS that are bound to current link. */ int sd_network_link_get_carrier_bound_by(int ifindex, int **ifindexes); +/* Get the CLIENTID if the link has a IPv4 DHCP address. */ +int sd_network_link_get_clientid(int ifindex, char **clientid); + +/* Get the IAID if the link has a IPv6 DHCP address. */ +int sd_network_link_get_iaid(int ifindex, char **iaid); + +/* Get the DUID if the link has a IPv6 DHCP address. */ +int sd_network_link_get_duid(int ifindex, char **duid); + /* Get the timezone that was learnt on a specific link. */ int sd_network_link_get_timezone(int ifindex, char **timezone);