mirror of
https://git.openwrt.org/project/odhcpd.git
synced 2025-12-20 02:17:45 +08:00
dhcpv6-ia: split reconf_msg struct into partial structs
Change send_reconf() so that the various options are each in separate struct. This makes it easy to support a variable-length server DUID in the future. Signed-off-by: David Härdeman <david@hardeman.nu> Link: https://github.com/openwrt/odhcpd/pull/274 Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
This commit is contained in:
committed by
Álvaro Fernández Rojas
parent
a3bf57a399
commit
ae16476bca
108
src/dhcpv6-ia.c
108
src/dhcpv6-ia.c
@@ -137,43 +137,74 @@ static size_t get_preferred_addr(const struct odhcpd_ipaddr *addrs, const size_t
|
||||
return m;
|
||||
}
|
||||
|
||||
enum {
|
||||
IOV_HDR = 0,
|
||||
IOV_SERVERID,
|
||||
IOV_CLIENTID,
|
||||
IOV_MESSAGE,
|
||||
IOV_AUTH,
|
||||
IOV_TOTAL
|
||||
};
|
||||
|
||||
static int send_reconf(struct dhcp_assignment *assign)
|
||||
{
|
||||
struct {
|
||||
struct dhcpv6_client_header hdr;
|
||||
uint16_t srvid_type;
|
||||
uint16_t srvid_len;
|
||||
uint16_t duid_type;
|
||||
uint16_t hardware_type;
|
||||
uint8_t mac[6];
|
||||
uint16_t msg_type;
|
||||
uint16_t msg_len;
|
||||
uint8_t msg_id;
|
||||
struct dhcpv6_auth_reconfigure auth;
|
||||
uint16_t clid_type;
|
||||
uint16_t clid_len;
|
||||
uint8_t clid_data[128];
|
||||
} __attribute__((packed)) reconf_msg = {
|
||||
.hdr = {DHCPV6_MSG_RECONFIGURE, {0, 0, 0}},
|
||||
.srvid_type = htons(DHCPV6_OPT_SERVERID),
|
||||
.srvid_len = htons(10),
|
||||
.duid_type = htons(3),
|
||||
.hardware_type = htons(1),
|
||||
.msg_type = htons(DHCPV6_OPT_RECONF_MSG),
|
||||
.msg_len = htons(1),
|
||||
.msg_id = DHCPV6_MSG_RENEW,
|
||||
.auth = {htons(DHCPV6_OPT_AUTH),
|
||||
htons(sizeof(reconf_msg.auth) - 4), 3, 1, 0,
|
||||
{htonl(time(NULL)), htonl(++serial)}, 2, {0}},
|
||||
.clid_type = htons(DHCPV6_OPT_CLIENTID),
|
||||
.clid_len = htons(assign->clid_len),
|
||||
.clid_data = {0},
|
||||
};
|
||||
struct interface *iface = assign->iface;
|
||||
struct dhcpv6_client_header hdr = {
|
||||
.msg_type = DHCPV6_MSG_RECONFIGURE,
|
||||
.transaction_id = { 0, 0, 0 },
|
||||
};
|
||||
struct {
|
||||
uint16_t code;
|
||||
uint16_t len;
|
||||
uint8_t data[DUID_MAX_LEN];
|
||||
} _packed serverid = {
|
||||
.code = htons(DHCPV6_OPT_SERVERID),
|
||||
.len = 0,
|
||||
.data = { 0 },
|
||||
};
|
||||
struct {
|
||||
uint16_t code;
|
||||
uint16_t len;
|
||||
uint8_t data[DUID_MAX_LEN];
|
||||
} _packed clientid = {
|
||||
.code = htons(DHCPV6_OPT_CLIENTID),
|
||||
.len = htons(assign->clid_len),
|
||||
.data = { 0 },
|
||||
};
|
||||
struct {
|
||||
uint16_t code;
|
||||
uint16_t len;
|
||||
uint8_t id;
|
||||
} _packed message = {
|
||||
.code = htons(DHCPV6_OPT_RECONF_MSG),
|
||||
.len = htons(1),
|
||||
.id = DHCPV6_MSG_RENEW,
|
||||
};
|
||||
struct dhcpv6_auth_reconfigure auth = {
|
||||
.type = htons(DHCPV6_OPT_AUTH),
|
||||
.len = htons(sizeof(struct dhcpv6_auth_reconfigure)),
|
||||
.protocol = 3,
|
||||
.algorithm = 1,
|
||||
.rdm = 0,
|
||||
.replay = { htonl(time(NULL)), htonl(++serial) },
|
||||
.reconf_type = 2,
|
||||
.key = { 0 },
|
||||
};
|
||||
|
||||
odhcpd_get_mac(iface, reconf_msg.mac);
|
||||
memcpy(reconf_msg.clid_data, assign->clid_data, assign->clid_len);
|
||||
struct iovec iov = {&reconf_msg, sizeof(reconf_msg) - 128 + assign->clid_len};
|
||||
uint8_t duid_ll_hdr[] = { 0x00, 0x03, 0x00, 0x01 };
|
||||
memcpy(serverid.data, duid_ll_hdr, sizeof(duid_ll_hdr));
|
||||
odhcpd_get_mac(iface, &serverid.data[sizeof(duid_ll_hdr)]);
|
||||
serverid.len = htons(sizeof(duid_ll_hdr) + ETH_ALEN);
|
||||
|
||||
memcpy(clientid.data, assign->clid_data, assign->clid_len);
|
||||
|
||||
struct iovec iov[IOV_MAX] = {
|
||||
[IOV_HDR] = { &hdr, sizeof(hdr) },
|
||||
[IOV_SERVERID] = { &serverid, sizeof(serverid) },
|
||||
[IOV_CLIENTID] = { &clientid, sizeof(clientid) },
|
||||
[IOV_MESSAGE] = { &message, sizeof(message) },
|
||||
[IOV_AUTH] = { &auth, sizeof(auth) },
|
||||
};
|
||||
|
||||
md5_ctx_t md5;
|
||||
uint8_t secretbytes[64];
|
||||
@@ -185,8 +216,9 @@ static int send_reconf(struct dhcp_assignment *assign)
|
||||
|
||||
md5_begin(&md5);
|
||||
md5_hash(secretbytes, sizeof(secretbytes), &md5);
|
||||
md5_hash(iov.iov_base, iov.iov_len, &md5);
|
||||
md5_end(reconf_msg.auth.key, &md5);
|
||||
for (size_t i = 0; i < ARRAY_SIZE(iov); i++)
|
||||
md5_hash(iov[i].iov_base, iov[i].iov_len, &md5);
|
||||
md5_end(auth.key, &md5);
|
||||
|
||||
for (size_t i = 0; i < sizeof(secretbytes); ++i) {
|
||||
secretbytes[i] ^= 0x36;
|
||||
@@ -195,10 +227,10 @@ static int send_reconf(struct dhcp_assignment *assign)
|
||||
|
||||
md5_begin(&md5);
|
||||
md5_hash(secretbytes, sizeof(secretbytes), &md5);
|
||||
md5_hash(reconf_msg.auth.key, 16, &md5);
|
||||
md5_end(reconf_msg.auth.key, &md5);
|
||||
md5_hash(auth.key, 16, &md5);
|
||||
md5_end(auth.key, &md5);
|
||||
|
||||
return odhcpd_send(iface->dhcpv6_event.uloop.fd, &assign->peer, &iov, 1, iface);
|
||||
return odhcpd_send(iface->dhcpv6_event.uloop.fd, &assign->peer, iov, ARRAY_SIZE(iov), iface);
|
||||
}
|
||||
|
||||
static void dhcpv6_ia_free_assignment(struct dhcp_assignment *a)
|
||||
|
||||
Reference in New Issue
Block a user