From 7e753d9d28ca93fe0e48fd3605ed7c3371736422 Mon Sep 17 00:00:00 2001 From: Alex Crawford Date: Fri, 31 Jul 2015 20:02:22 -0700 Subject: networkd: add private options to lease struct This stores private-zone DHCP options inside of their respective DHCP lease. These options aren't used by networkd (what would it do with them?), but saving them will allow other programs to query the values. To improve performance, the options are stored in ascending order by tag. --- src/libsystemd-network/sd-dhcp-lease.c | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'src/libsystemd-network/sd-dhcp-lease.c') diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index febf9f87f3..c6b4f0a3ae 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -203,6 +203,14 @@ sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) { sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { if (lease && REFCNT_DEC(lease->n_ref) == 0) { + while (lease->private_options) { + struct sd_dhcp_raw_option *option = lease->private_options; + + LIST_REMOVE(options, lease->private_options, option); + + free(option->data); + free(option); + } free(lease->hostname); free(lease->domainname); free(lease->dns); @@ -607,8 +615,46 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, } break; + + default: + if (code < DHCP_OPTION_PRIVATE_BASE || code > DHCP_OPTION_PRIVATE_LAST) + break; + + r = dhcp_lease_insert_private_option(lease, code, option, len); + if (r < 0) + return r; + } + + return 0; +} + +int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, + const uint8_t *data, uint8_t len) { + struct sd_dhcp_raw_option *cur, *option; + + LIST_FOREACH(options, cur, lease->private_options) { + if (tag < cur->tag) + break; + else if (tag == cur->tag) { + log_error("Ignoring duplicate option, tagged %d.", tag); + return 0; + } } + option = new(struct sd_dhcp_raw_option, 1); + if (!option) + return -ENOMEM; + + option->tag = tag; + option->length = len; + option->data = memdup(data, len); + if (!option->data) { + free(option); + return -ENOMEM; + } + + LIST_INSERT_BEFORE(options, lease->private_options, cur, option); + return 0; } @@ -621,6 +667,7 @@ int dhcp_lease_new(sd_dhcp_lease **ret) { lease->router = INADDR_ANY; lease->n_ref = REFCNT_INIT; + LIST_HEAD_INIT(lease->private_options); *ret = lease; return 0; -- cgit v1.2.3-54-g00ecf