#include "random-util.h"
#include "string-util.h"
#include "strv.h"
+#include "web-util.h"
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
size_t client_id_len;
char *hostname;
char *vendor_class_identifier;
+ char *mudurl;
char **user_class;
uint32_t mtu;
uint32_t xid;
usec_t start_time;
uint64_t attempt;
uint64_t max_attempts;
- OrderedHashmap *options;
+ OrderedHashmap *extra_options;
+ OrderedHashmap *vendor_options;
usec_t request_sent;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
return free_and_strdup(&client->vendor_class_identifier, vci);
}
+int sd_dhcp_client_set_mud_url(
+ sd_dhcp_client *client,
+ const char *mudurl) {
+
+ assert_return(client, -EINVAL);
+ assert_return(mudurl, -EINVAL);
+ assert_return(strlen(mudurl) <= 255, -EINVAL);
+ assert_return(http_url_is_valid(mudurl), -EINVAL);
+
+ return free_and_strdup(&client->mudurl, mudurl);
+}
+
int sd_dhcp_client_set_user_class(
sd_dhcp_client *client,
const char* const* user_class) {
return 0;
}
-int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v) {
+int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v) {
int r;
assert_return(client, -EINVAL);
assert_return(v, -EINVAL);
- r = ordered_hashmap_ensure_allocated(&client->options, &dhcp_option_hash_ops);
+ r = ordered_hashmap_ensure_allocated(&client->extra_options, &dhcp_option_hash_ops);
if (r < 0)
return r;
- r = ordered_hashmap_put(client->options, UINT_TO_PTR(v->option), v);
+ r = ordered_hashmap_put(client->extra_options, UINT_TO_PTR(v->option), v);
if (r < 0)
return r;
return 0;
}
+int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v) {
+ int r;
+
+ assert_return(client, -EINVAL);
+ assert_return(v, -EINVAL);
+
+ r = ordered_hashmap_ensure_allocated(&client->vendor_options, &dhcp_option_hash_ops);
+ if (r < 0)
+ return -ENOMEM;
+
+ r = ordered_hashmap_put(client->vendor_options, v, v);
+ if (r < 0)
+ return r;
+
+ sd_dhcp_option_ref(v);
+
+ return 1;
+}
+
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
assert_return(client, -EINVAL);
return r;
}
+ if (client->mudurl) {
+ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+ SD_DHCP_OPTION_MUD_URL,
+ strlen(client->mudurl),
+ client->mudurl);
+ if (r < 0)
+ return r;
+ }
+
if (client->user_class) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_USER_CLASS,
return r;
}
- ORDERED_HASHMAP_FOREACH(j, client->options, i) {
+ ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
j->option, j->length, j->data);
if (r < 0)
return r;
}
+ if (!ordered_hashmap_isempty(client->vendor_options)) {
+ r = dhcp_option_append(
+ &discover->dhcp, optlen, &optoffset, 0,
+ SD_DHCP_OPTION_VENDOR_SPECIFIC,
+ ordered_hashmap_size(client->vendor_options), client->vendor_options);
+ if (r < 0)
+ return r;
+ }
+
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
return r;
}
+ if (client->mudurl) {
+ r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
+ SD_DHCP_OPTION_MUD_URL,
+ strlen(client->mudurl),
+ client->mudurl);
+ if (r < 0)
+ return r;
+ }
+
+
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
iov = IOVEC_MAKE(packet, buflen);
- len = recvmsg(fd, &msg, 0);
- if (len < 0) {
- if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN))
- return 0;
-
- return log_dhcp_client_errno(client, errno,
- "Could not receive message from raw socket: %m");
- } else if ((size_t)len < sizeof(DHCPPacket))
+ len = recvmsg_safe(fd, &msg, 0);
+ if (IN_SET(len, -EAGAIN, -EINTR, -ENETDOWN))
return 0;
+ if (len < 0)
+ return log_dhcp_client_errno(client, len,
+ "Could not receive message from raw socket: %m");
- CMSG_FOREACH(cmsg, &msg)
- if (cmsg->cmsg_level == SOL_PACKET &&
- cmsg->cmsg_type == PACKET_AUXDATA &&
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
- struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
+ if ((size_t) len < sizeof(DHCPPacket))
+ return 0;
- checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
- break;
- }
+ cmsg = cmsg_find(&msg, SOL_PACKET, PACKET_AUXDATA, CMSG_LEN(sizeof(struct tpacket_auxdata)));
+ if (cmsg) {
+ struct tpacket_auxdata *aux = (struct tpacket_auxdata*) CMSG_DATA(cmsg);
+ checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
+ }
r = dhcp_packet_verify_headers(packet, len, checksum, client->port);
if (r < 0)
free(client->req_opts);
free(client->hostname);
free(client->vendor_class_identifier);
+ free(client->mudurl);
client->user_class = strv_free(client->user_class);
- ordered_hashmap_free(client->options);
+ ordered_hashmap_free(client->extra_options);
+ ordered_hashmap_free(client->vendor_options);
return mfree(client);
}