[systemd-commits] 4 commits - src/libsystemd-network
Tom Gundersen
tomegun at kemper.freedesktop.org
Tue May 20 14:31:40 PDT 2014
src/libsystemd-network/dhcp-internal.h | 6
src/libsystemd-network/dhcp-lease-internal.h | 12 +
src/libsystemd-network/dhcp-option.c | 113 ++++++------
src/libsystemd-network/dhcp-packet.c | 15 -
src/libsystemd-network/dhcp-protocol.h | 11 +
src/libsystemd-network/sd-dhcp-client.c | 57 +++---
src/libsystemd-network/sd-dhcp-lease.c | 240 +++++++++++++++++++++------
src/libsystemd-network/test-dhcp-option.c | 58 ++----
8 files changed, 323 insertions(+), 189 deletions(-)
New commits:
commit f5c0c00f400e6f1fa58c5faf8bc93ca9057d4463
Author: Tom Gundersen <teg at jklm.no>
Date: Tue May 20 22:02:49 2014 +0200
dhcp-lease: add support for parsing a few more dhcp options
diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h
index 297bacb..ff09583 100644
--- a/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/libsystemd-network/dhcp-lease-internal.h
@@ -35,19 +35,31 @@
struct sd_dhcp_lease {
RefCount n_ref;
+ int32_t time_offset;
uint32_t t1;
uint32_t t2;
uint32_t lifetime;
+ uint32_t mtu_aging_timeout;
be32_t address;
be32_t server_address;
be32_t subnet_mask;
be32_t router;
be32_t next_server;
+ be32_t broadcast;
struct in_addr *dns;
size_t dns_size;
struct in_addr *ntp;
size_t ntp_size;
+ struct in_addr *policy_filter;
+ size_t policy_filter_size;
+ struct in_addr *static_route;
+ size_t static_route_size;
+ uint16_t boot_file_size;
+ uint16_t mdr;
uint16_t mtu;
+ uint8_t ttl;
+ bool ip_forward;
+ bool ip_forward_non_local;
char *domainname;
char *hostname;
char *root_path;
diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h
index 11de186..260508f 100644
--- a/src/libsystemd-network/dhcp-protocol.h
+++ b/src/libsystemd-network/dhcp-protocol.h
@@ -105,12 +105,22 @@ enum {
enum {
DHCP_OPTION_PAD = 0,
DHCP_OPTION_SUBNET_MASK = 1,
+ DHCP_OPTION_TIME_OFFSET = 2,
DHCP_OPTION_ROUTER = 3,
DHCP_OPTION_DOMAIN_NAME_SERVER = 6,
DHCP_OPTION_HOST_NAME = 12,
+ DHCP_OPTION_BOOT_FILE_SIZE = 13,
DHCP_OPTION_DOMAIN_NAME = 15,
DHCP_OPTION_ROOT_PATH = 17,
+ DHCP_OPTION_ENABLE_IP_FORWARDING = 19,
+ DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20,
+ DHCP_OPTION_POLICY_FILTER = 21,
+ DHCP_OPTION_INTERFACE_MDR = 22,
+ DHCP_OPTION_INTERFACE_TTL = 23,
+ DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
DHCP_OPTION_INTERFACE_MTU = 26,
+ DHCP_OPTION_BROADCAST = 28,
+ DHCP_OPTION_STATIC_ROUTE = 33,
DHCP_OPTION_NTP_SERVER = 42,
DHCP_OPTION_REQUESTED_IP_ADDRESS = 50,
DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51,
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index 2ec45ca..3203b7a 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -196,6 +196,10 @@ static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, ui
}
}
+static void lease_parse_s32(const uint8_t *option, size_t len, int32_t *ret) {
+ lease_parse_u32(option, len, (uint32_t *)ret, 0);
+}
+
static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
be16_t val;
@@ -219,6 +223,26 @@ static void lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {
memcpy(ret, option, 4);
}
+static void lease_parse_bool(const uint8_t *option, size_t len, bool *ret) {
+ assert(option);
+ assert(ret);
+
+ if (len == 1)
+ *ret = !!(*option);
+}
+
+static void lease_parse_u8(const uint8_t *option, size_t len, uint8_t *ret, uint8_t min) {
+ assert(option);
+ assert(ret);
+
+ if (len == 1) {
+ *ret = *option;
+
+ if (*ret < min)
+ *ret = min;
+ }
+}
+
static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
assert(option);
assert(ret);
@@ -237,12 +261,12 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
return 0;
}
-static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
+static int lease_parse_in_addrs_aux(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size, size_t mult) {
assert(option);
assert(ret);
assert(ret_size);
- if (len && !(len % 4)) {
+ if (len && !(len % (4 * mult))) {
size_t size;
struct in_addr *addresses;
@@ -260,6 +284,14 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add
return 0;
}
+static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
+ return lease_parse_in_addrs_aux(option, len, ret, ret_size, 1);
+}
+
+static int lease_parse_in_addrs_pairs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
+ return lease_parse_in_addrs_aux(option, len, ret, ret_size, 2);
+}
+
int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
void *user_data) {
sd_dhcp_lease *lease = user_data;
@@ -269,6 +301,16 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
switch(code) {
+ case DHCP_OPTION_TIME_OFFSET:
+ lease_parse_s32(option, len, &lease->time_offset);
+
+ break;
+
+ case DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT:
+ lease_parse_u32(option, len, &lease->mtu_aging_timeout, 0);
+
+ break;
+
case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
lease_parse_u32(option, len, &lease->lifetime, 1);
@@ -284,6 +326,11 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
break;
+ case DHCP_OPTION_BROADCAST:
+ lease_parse_be32(option, len, &lease->broadcast);
+
+ break;
+
case DHCP_OPTION_ROUTER:
lease_parse_be32(option, len, &lease->router);
@@ -303,11 +350,40 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
break;
+ case DHCP_OPTION_POLICY_FILTER:
+ r = lease_parse_in_addrs_pairs(option, len, &lease->policy_filter, &lease->policy_filter_size);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case DHCP_OPTION_STATIC_ROUTE:
+ r = lease_parse_in_addrs_pairs(option, len, &lease->static_route, &lease->static_route_size);
+ if (r < 0)
+ return r;
+
+ break;
+
case DHCP_OPTION_INTERFACE_MTU:
lease_parse_u16(option, len, &lease->mtu, 68);
break;
+ case DHCP_OPTION_INTERFACE_MDR:
+ lease_parse_u16(option, len, &lease->mdr, 576);
+
+ break;
+
+ case DHCP_OPTION_INTERFACE_TTL:
+ lease_parse_u8(option, len, &lease->ttl, 1);
+
+ break;
+
+ case DHCP_OPTION_BOOT_FILE_SIZE:
+ lease_parse_u16(option, len, &lease->boot_file_size, 0);
+
+ break;
+
case DHCP_OPTION_DOMAIN_NAME:
r = lease_parse_string(option, len, &lease->domainname);
if (r < 0)
@@ -338,6 +414,16 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
lease_parse_u32(option, len, &lease->t2, 1);
break;
+
+ case DHCP_OPTION_ENABLE_IP_FORWARDING:
+ lease_parse_bool(option, len, &lease->ip_forward);
+
+ break;
+
+ case DHCP_OPTION_ENABLE_IP_FORWARDING_NL:
+ lease_parse_bool(option, len, &lease->ip_forward_non_local);
+
+ break;
}
return 0;
commit e140ae58f1c10bbd75ef94afc07d07b82323b506
Author: Tom Gundersen <teg at jklm.no>
Date: Tue May 20 16:40:59 2014 +0200
dhcp-lease: refactor lease parsing
Use helper functions, and add some more sanity checking/asserts.
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index cf71f11..2ec45ca 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -181,113 +181,161 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
return NULL;
}
+static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
+ be32_t val;
+
+ assert(option);
+ assert(ret);
+
+ if (len == 4) {
+ memcpy(&val, option, 4);
+ *ret = be32toh(val);
+
+ if (*ret < min)
+ *ret = min;
+ }
+}
+
+static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
+ be16_t val;
+
+ assert(option);
+ assert(ret);
+
+ if (len == 2) {
+ memcpy(&val, option, 2);
+ *ret = be16toh(val);
+
+ if (*ret < min)
+ *ret = min;
+ }
+}
+
+static void lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {
+ assert(option);
+ assert(ret);
+
+ if (len == 4)
+ memcpy(ret, option, 4);
+}
+
+static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
+ assert(option);
+ assert(ret);
+
+ if (len >= 1) {
+ char *string;
+
+ string = strndup((const char *)option, len);
+ if (!string)
+ return -errno;
+
+ free(*ret);
+ *ret = string;
+ }
+
+ return 0;
+}
+
+static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
+ assert(option);
+ assert(ret);
+ assert(ret_size);
+
+ if (len && !(len % 4)) {
+ size_t size;
+ struct in_addr *addresses;
+
+ size = len / 4;
+
+ addresses = newdup(struct in_addr, option, size);
+ if (!addresses)
+ return -ENOMEM;
+
+ free(*ret);
+ *ret = addresses;
+ *ret_size = size;
+ }
+
+ return 0;
+}
+
int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
void *user_data) {
sd_dhcp_lease *lease = user_data;
- be32_t val;
+ int r;
+
+ assert(lease);
switch(code) {
case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
- if (len == 4) {
- memcpy(&val, option, 4);
- lease->lifetime = be32toh(val);
- }
+ lease_parse_u32(option, len, &lease->lifetime, 1);
break;
case DHCP_OPTION_SERVER_IDENTIFIER:
- if (len >= 4)
- memcpy(&lease->server_address, option, 4);
+ lease_parse_be32(option, len, &lease->server_address);
break;
case DHCP_OPTION_SUBNET_MASK:
- if (len >= 4)
- memcpy(&lease->subnet_mask, option, 4);
+ lease_parse_be32(option, len, &lease->subnet_mask);
break;
case DHCP_OPTION_ROUTER:
- if (len >= 4)
- memcpy(&lease->router, option, 4);
+ lease_parse_be32(option, len, &lease->router);
break;
case DHCP_OPTION_DOMAIN_NAME_SERVER:
- if (len && !(len % 4)) {
- lease->dns_size = len / 4;
-
- free(lease->dns);
- lease->dns = newdup(struct in_addr, option, lease->dns_size);
- if (!lease->dns)
- return -ENOMEM;
- }
+ r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);
+ if (r < 0)
+ return r;
break;
case DHCP_OPTION_NTP_SERVER:
- if (len && !(len % 4)) {
- lease->ntp_size = len / 4;
-
- free(lease->ntp);
- lease->ntp = newdup(struct in_addr, option, lease->ntp_size);
- if (!lease->ntp)
- return -ENOMEM;
- }
+ r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);
+ if (r < 0)
+ return r;
break;
case DHCP_OPTION_INTERFACE_MTU:
- if (len >= 2) {
- be16_t mtu;
-
- memcpy(&mtu, option, 2);
- lease->mtu = be16toh(mtu);
-
- if (lease->mtu < 68)
- lease->mtu = 0;
- }
+ lease_parse_u16(option, len, &lease->mtu, 68);
break;
case DHCP_OPTION_DOMAIN_NAME:
- if (len >= 1) {
- free(lease->domainname);
- lease->domainname = strndup((const char *)option, len);
- }
+ r = lease_parse_string(option, len, &lease->domainname);
+ if (r < 0)
+ return r;
break;
case DHCP_OPTION_HOST_NAME:
- if (len >= 1) {
- free(lease->hostname);
- lease->hostname = strndup((const char *)option, len);
- }
+ r = lease_parse_string(option, len, &lease->hostname);
+ if (r < 0)
+ return r;
break;
case DHCP_OPTION_ROOT_PATH:
- if (len >= 1) {
- free(lease->root_path);
- lease->root_path = strndup((const char *)option, len);
- }
+ r = lease_parse_string(option, len, &lease->root_path);
+ if (r < 0)
+ return r;
break;
case DHCP_OPTION_RENEWAL_T1_TIME:
- if (len == 4) {
- memcpy(&val, option, 4);
- lease->t1 = be32toh(val);
- }
+ lease_parse_u32(option, len, &lease->t1, 1);
break;
case DHCP_OPTION_REBINDING_T2_TIME:
- if (len == 4) {
- memcpy(&val, option, 4);
- lease->t2 = be32toh(val);
- }
+ lease_parse_u32(option, len, &lease->t2, 1);
break;
}
commit 32008a9636b3781112d349e77ee9e3279104b01c
Author: Tom Gundersen <teg at jklm.no>
Date: Tue May 20 13:07:19 2014 +0200
sd-dhcp: refactor parse_options
Similar to the previous patch, exchange a length and a pointer with only one offset variable.
Also fix the type of the options to be uint8_t[], rather than uint8_t*.
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index 7bf8812..6895092 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -60,86 +60,86 @@ int dhcp_option_append(uint8_t options[], size_t size, size_t *offset,
return 0;
}
-static int parse_options(const uint8_t *buf, size_t buflen, uint8_t *overload,
+static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload,
uint8_t *message_type, dhcp_option_cb_t cb,
- void *user_data)
-{
- const uint8_t *code = buf;
- const uint8_t *len;
+ void *user_data) {
+ uint8_t code, len;
+ size_t offset = 0;
- while (buflen > 0) {
- switch (*code) {
+ while (offset < buflen) {
+ switch (options[offset]) {
case DHCP_OPTION_PAD:
- buflen -= 1;
- code++;
+ offset++;
+
break;
case DHCP_OPTION_END:
return 0;
case DHCP_OPTION_MESSAGE_TYPE:
- if (buflen < 3)
+ if (buflen < offset + 3)
return -ENOBUFS;
- buflen -= 3;
- len = code + 1;
- if (*len != 1)
+ len = options[++offset];
+ if (len != 1)
return -EINVAL;
if (message_type)
- *message_type = *(len + 1);
+ *message_type = options[++offset];
+ else
+ offset++;
- code += 3;
+ offset++;
break;
case DHCP_OPTION_OVERLOAD:
- if (buflen < 3)
+ if (buflen < offset + 3)
return -ENOBUFS;
- buflen -= 3;
- len = code + 1;
- if (*len != 1)
+ len = options[++offset];
+ if (len != 1)
return -EINVAL;
if (overload)
- *overload = *(len + 1);
+ *overload = options[++offset];
+ else
+ offset++;
- code += 3;
+ offset++;
break;
default:
- if (buflen < 3)
+ if (buflen < offset + 3)
return -ENOBUFS;
- len = code + 1;
+ code = options[offset];
+ len = options[++offset];
- if (buflen < (size_t)*len + 2)
+ if (buflen < ++offset + len)
return -EINVAL;
- buflen -= *len + 2;
if (cb)
- cb(*code, *len, len + 1, user_data);
+ cb(code, len, &options[offset], user_data);
- code += *len + 2;
+ offset += len;
break;
}
}
- if (buflen)
+ if (offset < buflen)
return -EINVAL;
return 0;
}
int dhcp_option_parse(DHCPMessage *message, size_t len,
- dhcp_option_cb_t cb, void *user_data)
-{
+ dhcp_option_cb_t cb, void *user_data) {
uint8_t overload = 0;
uint8_t message_type = 0;
- int res;
+ int r;
if (!message)
return -EINVAL;
@@ -149,23 +149,23 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
len -= sizeof(DHCPMessage);
- res = parse_options(message->options, len, &overload, &message_type,
- cb, user_data);
- if (res < 0)
- return res;
+ r = parse_options(message->options, len, &overload, &message_type,
+ cb, user_data);
+ if (r < 0)
+ return r;
if (overload & DHCP_OVERLOAD_FILE) {
- res = parse_options(message->file, sizeof(message->file),
+ r = parse_options(message->file, sizeof(message->file),
NULL, &message_type, cb, user_data);
- if (res < 0)
- return res;
+ if (r < 0)
+ return r;
}
if (overload & DHCP_OVERLOAD_SNAME) {
- res = parse_options(message->sname, sizeof(message->sname),
+ r = parse_options(message->sname, sizeof(message->sname),
NULL, &message_type, cb, user_data);
- if (res < 0)
- return res;
+ if (r < 0)
+ return r;
}
if (message_type)
commit 20b958bf157dfb2f521b191ef7158035bcaa3003
Author: Tom Gundersen <teg at jklm.no>
Date: Tue May 20 11:04:50 2014 +0200
sd-dhcp: refactor dhcp_option_append
Store a pointer to the options in the DHCPMessage struct, and pass
this together with an offset around, rather than a uint8_t**.
This avoids us having to (re)compute the pointer; and changes
dhcp_option_append from adjusting both the pointer to the next
option and the remaining size of the options, to just adjusting
the current offset.
This makes the code a bit simpler to follow IMHO, but there should
be no functional change.
diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
index eb4a6cd..56423a2 100644
--- a/src/libsystemd-network/dhcp-internal.h
+++ b/src/libsystemd-network/dhcp-internal.h
@@ -36,8 +36,8 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
const void *packet, size_t len);
-int dhcp_option_append(uint8_t **buf, size_t *buflen, uint8_t code,
- size_t optlen, const void *optval);
+int dhcp_option_append(uint8_t options[], size_t size, size_t *offset,
+ uint8_t code, size_t optlen, const void *optval);
typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len,
const uint8_t *option, void *user_data);
@@ -46,7 +46,7 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
dhcp_option_cb_t cb, void *user_data);
int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type,
- uint8_t **opt, size_t *optlen);
+ uint8_t options[], size_t optlen, size_t *optoffset);
uint16_t dhcp_packet_checksum(void *buf, size_t len);
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index 1b92e86..7bf8812 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -26,37 +26,33 @@
#include "dhcp-internal.h"
-int dhcp_option_append(uint8_t **buf, size_t *buflen, uint8_t code,
- size_t optlen, const void *optval)
-{
- if (!buf || !buflen)
- return -EINVAL;
+int dhcp_option_append(uint8_t options[], size_t size, size_t *offset,
+ uint8_t code, size_t optlen, const void *optval) {
+ assert(options);
+ assert(offset);
switch (code) {
case DHCP_OPTION_PAD:
case DHCP_OPTION_END:
- if (*buflen < 1)
+ if (size - *offset < 1)
return -ENOBUFS;
- (*buf)[0] = code;
- *buf += 1;
- *buflen -= 1;
+ options[*offset] = code;
+ *offset += 1;
break;
default:
- if (*buflen < optlen + 2)
+ if (size - *offset < optlen + 2)
return -ENOBUFS;
- if (!optval)
- return -EINVAL;
+ assert(optval);
- (*buf)[0] = code;
- (*buf)[1] = optlen;
- memcpy(&(*buf)[2], optval, optlen);
+ options[*offset] = code;
+ options[*offset + 1] = optlen;
+ memcpy(&options[*offset + 2], optval, optlen);
- *buf += optlen + 2;
- *buflen -= (optlen + 2);
+ *offset += optlen + 2;
break;
}
@@ -143,7 +139,6 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
{
uint8_t overload = 0;
uint8_t message_type = 0;
- uint8_t *opt = (uint8_t *)(message + 1);
int res;
if (!message)
@@ -154,7 +149,7 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
len -= sizeof(DHCPMessage);
- res = parse_options(opt, len, &overload, &message_type,
+ res = parse_options(message->options, len, &overload, &message_type,
cb, user_data);
if (res < 0)
return res;
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
index d72d7a6..10b6457 100644
--- a/src/libsystemd-network/dhcp-packet.c
+++ b/src/libsystemd-network/dhcp-packet.c
@@ -38,8 +38,9 @@
#define DHCP_CLIENT_MIN_OPTIONS_SIZE 312
int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
- uint8_t type, uint8_t **opt, size_t *optlen) {
- int err;
+ uint8_t type, uint8_t options[], size_t optlen, size_t *optoffset) {
+ size_t offset = 0;
+ int r;
assert(op == BOOTREQUEST || op == BOOTREPLY);
@@ -49,12 +50,12 @@ int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
message->xid = htobe32(xid);
message->magic = htobe32(DHCP_MAGIC_COOKIE);
- *opt = (uint8_t *)(message + 1);
+ r = dhcp_option_append(message->options, optlen, &offset,
+ DHCP_OPTION_MESSAGE_TYPE, 1, &type);
+ if (r < 0)
+ return r;
- err = dhcp_option_append(opt, optlen, DHCP_OPTION_MESSAGE_TYPE, 1,
- &type);
- if (err < 0)
- return err;
+ *optoffset = offset;
return 0;
}
diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h
index 539606c..11de186 100644
--- a/src/libsystemd-network/dhcp-protocol.h
+++ b/src/libsystemd-network/dhcp-protocol.h
@@ -44,6 +44,7 @@ struct DHCPMessage {
uint8_t sname[64];
uint8_t file[128];
be32_t magic;
+ uint8_t options[0];
} _packed_;
typedef struct DHCPMessage DHCPMessage;
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 94235cf..cee4ccf 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -257,19 +257,18 @@ static sd_dhcp_client *client_stop(sd_dhcp_client *client, int error) {
}
static int client_message_init(sd_dhcp_client *client, DHCPMessage *message,
- uint8_t type, uint8_t **opt, size_t *optlen) {
+ uint8_t type, size_t optlen, size_t *optoffset) {
be16_t max_size;
int r;
assert(client);
assert(client->secs);
assert(message);
- assert(opt);
- assert(optlen);
+ assert(optoffset);
assert(type == DHCP_DISCOVER || type == DHCP_REQUEST);
- r = dhcp_message_init(message, BOOTREQUEST, client->xid, type, opt,
- optlen);
+ r = dhcp_message_init(message, BOOTREQUEST, client->xid, type,
+ message->options, optlen, optoffset);
if (r < 0)
return r;
@@ -285,7 +284,8 @@ static int client_message_init(sd_dhcp_client *client, DHCPMessage *message,
/* Some DHCP servers will refuse to issue an DHCP lease if the Client
Identifier option is not set */
- r = dhcp_option_append(opt, optlen, DHCP_OPTION_CLIENT_IDENTIFIER,
+ r = dhcp_option_append(message->options, optlen, optoffset,
+ DHCP_OPTION_CLIENT_IDENTIFIER,
sizeof(client->client_id), &client->client_id);
if (r < 0)
return r;
@@ -299,10 +299,9 @@ static int client_message_init(sd_dhcp_client *client, DHCPMessage *message,
it MUST include that list in any subsequent DHCPREQUEST
messages.
*/
- r = dhcp_option_append(opt, optlen,
+ r = dhcp_option_append(message->options, optlen, optoffset,
DHCP_OPTION_PARAMETER_REQUEST_LIST,
- client->req_opts_size,
- client->req_opts);
+ client->req_opts_size, client->req_opts);
if (r < 0)
return r;
@@ -316,7 +315,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPMessage *message,
*/
max_size = htobe16(DHCP_IP_UDP_SIZE + DHCP_MESSAGE_SIZE +
DHCP_MIN_OPTIONS_SIZE);
- r = dhcp_option_append(opt, optlen,
+ r = dhcp_option_append(message->options, optlen, optoffset,
DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
2, &max_size);
if (r < 0)
@@ -336,8 +335,7 @@ static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
static int client_send_discover(sd_dhcp_client *client) {
_cleanup_free_ DHCPPacket *discover = NULL;
- size_t optlen, len;
- uint8_t *opt;
+ size_t optoffset, optlen, len;
usec_t time_now;
int r;
@@ -364,7 +362,7 @@ static int client_send_discover(sd_dhcp_client *client) {
return -ENOMEM;
r = client_message_init(client, &discover->dhcp, DHCP_DISCOVER,
- &opt, &optlen);
+ optlen, &optoffset);
if (r < 0)
return r;
@@ -375,22 +373,21 @@ static int client_send_discover(sd_dhcp_client *client) {
option to suggest the lease time it would like.
*/
if (client->last_addr != INADDR_ANY) {
- r = dhcp_option_append(&opt, &optlen,
- DHCP_OPTION_REQUESTED_IP_ADDRESS,
- 4, &client->last_addr);
+ r = dhcp_option_append(discover->dhcp.options, optlen, &optoffset,
+ DHCP_OPTION_REQUESTED_IP_ADDRESS,
+ 4, &client->last_addr);
if (r < 0)
return r;
}
- r = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
- if (r < 0)
- return r;
+ r = dhcp_option_append(discover->dhcp.options, optlen, &optoffset,
+ DHCP_OPTION_END, 0, NULL);
/* We currently ignore:
The client SHOULD wait a random time between one and ten seconds to
desynchronize the use of DHCP at startup.
*/
- r = dhcp_client_send_raw(client, discover, len - optlen);
+ r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
if (r < 0)
return r;
@@ -401,8 +398,7 @@ static int client_send_discover(sd_dhcp_client *client) {
static int client_send_request(sd_dhcp_client *client) {
_cleanup_free_ DHCPPacket *request;
- size_t optlen, len;
- uint8_t *opt;
+ size_t optoffset, optlen, len;
int r;
optlen = DHCP_MIN_OPTIONS_SIZE;
@@ -412,8 +408,8 @@ static int client_send_request(sd_dhcp_client *client) {
if (!request)
return -ENOMEM;
- r = client_message_init(client, &request->dhcp, DHCP_REQUEST, &opt,
- &optlen);
+ r = client_message_init(client, &request->dhcp, DHCP_REQUEST,
+ optlen, &optoffset);
if (r < 0)
return r;
@@ -428,13 +424,13 @@ static int client_send_request(sd_dhcp_client *client) {
filled in with the yiaddr value from the chosen DHCPOFFER.
*/
- r = dhcp_option_append(&opt, &optlen,
+ r = dhcp_option_append(request->dhcp.options, optlen, &optoffset,
DHCP_OPTION_SERVER_IDENTIFIER,
4, &client->lease->server_address);
if (r < 0)
return r;
- r = dhcp_option_append(&opt, &optlen,
+ r = dhcp_option_append(request->dhcp.options, optlen, &optoffset,
DHCP_OPTION_REQUESTED_IP_ADDRESS,
4, &client->lease->address);
if (r < 0)
@@ -447,7 +443,7 @@ static int client_send_request(sd_dhcp_client *client) {
option MUST be filled in with clientâs notion of its previously
assigned address. âciaddrâ MUST be zero.
*/
- r = dhcp_option_append(&opt, &optlen,
+ r = dhcp_option_append(request->dhcp.options, optlen, &optoffset,
DHCP_OPTION_REQUESTED_IP_ADDRESS,
4, &client->last_addr);
if (r < 0)
@@ -480,7 +476,8 @@ static int client_send_request(sd_dhcp_client *client) {
return -EINVAL;
}
- r = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
+ r = dhcp_option_append(request->dhcp.options, optlen, &optoffset,
+ DHCP_OPTION_END, 0, NULL);
if (r < 0)
return r;
@@ -489,9 +486,9 @@ static int client_send_request(sd_dhcp_client *client) {
client->lease->server_address,
DHCP_PORT_SERVER,
&request->dhcp,
- len - optlen - DHCP_IP_UDP_SIZE);
+ sizeof(DHCPMessage) + optoffset);
} else {
- r = dhcp_client_send_raw(client, request, len - optlen);
+ r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
}
if (r < 0)
return r;
diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c
index 35db8c1..eaf6a53 100644
--- a/src/libsystemd-network/test-dhcp-option.c
+++ b/src/libsystemd-network/test-dhcp-option.c
@@ -85,16 +85,14 @@ static void test_invalid_buffer_length(void)
static void test_message_init(void)
{
_cleanup_free_ DHCPMessage *message = NULL;
- size_t optlen = 3;
+ size_t optlen = 3, optoffset;
size_t len = sizeof(DHCPMessage) + optlen;
- uint8_t *opt, *magic;
+ uint8_t *magic;
message = malloc0(len);
- opt = (uint8_t *)(message + 1);
-
assert_se(dhcp_message_init(message, BOOTREQUEST, 0x12345678,
- DHCP_DISCOVER, &opt, &optlen) >= 0);
+ DHCP_DISCOVER, message->options, optlen, &optoffset) >= 0);
assert_se(message->xid == htobe32(0x12345678));
assert_se(message->op == BOOTREQUEST);
@@ -115,13 +113,11 @@ static DHCPMessage *create_message(uint8_t *options, uint16_t optlen,
{
DHCPMessage *message;
size_t len = sizeof(DHCPMessage) + optlen;
- uint8_t *opt;
message = malloc0(len);
- opt = (uint8_t *)(message + 1);
if (options && optlen)
- memcpy(opt, options, optlen);
+ memcpy(&message->options, options, optlen);
if (file && filelen <= 128)
memcpy(&message->file, file, filelen);
@@ -308,46 +304,34 @@ static uint8_t options[64] = {
static void test_option_set(void)
{
- size_t len, oldlen;
- int pos, i;
- uint8_t *opt;
-
- assert_se(dhcp_option_append(NULL, NULL, 0, 0, NULL) == -EINVAL);
-
- len = 0;
- opt = &result[0];
- assert_se(dhcp_option_append(&opt, NULL, 0, 0, NULL) == -EINVAL);
- assert_se(opt == &result[0] && len == 0);
+ size_t offset = 0, len, pos;
+ unsigned i;
- assert_se(dhcp_option_append(&opt, &len, DHCP_OPTION_PAD,
+ assert_se(dhcp_option_append(result, 0, &offset, DHCP_OPTION_PAD,
0, NULL) == -ENOBUFS);
- assert_se(opt == &result[0] && len == 0);
+ assert_se(offset == 0);
- opt = &result[4];
- len = 1;
- assert_se(dhcp_option_append(&opt, &len, DHCP_OPTION_PAD,
+ offset = 4;
+ assert_se(dhcp_option_append(result, 1, &offset, DHCP_OPTION_PAD,
0, NULL) >= 0);
- assert_se(opt == &result[5] && len == 0);
+ assert_se(offset == 5);
- pos = 4;
+ offset = pos = 4;
len = 60;
while (pos < 64 && options[pos] != DHCP_OPTION_END) {
- opt = &result[pos];
- oldlen = len;
+ offset = pos;
- assert_se(dhcp_option_append(&opt, &len, options[pos],
- options[pos + 1],
- &options[pos + 2]) >= 0);
+ assert_se(dhcp_option_append(result, len, &offset,
+ options[pos],
+ options[pos + 1],
+ &options[pos + 2]) >= 0);
- if (options[pos] == DHCP_OPTION_PAD) {
- assert_se(opt == &result[pos + 1]);
- assert_se(len == oldlen - 1);
+ if (options[pos] == DHCP_OPTION_PAD)
pos++;
- } else {
- assert_se(opt == &result[pos + 2 + options[pos + 1]]);
- assert_se(len == oldlen - 2 - options[pos + 1]);
+ else
pos += 2 + options[pos + 1];
- }
+
+ assert_se(offset == pos);
}
for (i = 0; i < pos; i++) {
More information about the systemd-commits
mailing list