summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-dhcp-lease.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd-network/sd-dhcp-lease.c')
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c47
1 files changed, 47 insertions, 0 deletions
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;