Make ndhc RFC6842-compliant.
All this entails is that ndhc needs to check to make sure that if the remote server sends a dhcp packet with a client identifier, the client identifier of that packet matches the client identifier that ndhc uses to identify itself. If the remote server does not attach a client identifier to its dhcp packets, then the behavior of ndhc does not change.
This commit is contained in:
parent
3d0f46580a
commit
cd269c7261
12
ndhc/dhcp.c
12
ndhc/dhcp.c
@ -527,6 +527,15 @@ static int validate_dhcp_packet(struct client_state_t *cs, size_t len,
|
||||
log_line("Packet does not specify a DHCP message type. Ignoring.");
|
||||
return 0;
|
||||
}
|
||||
char clientid[MAX_DOPT_SIZE];
|
||||
size_t cidlen = get_option_clientid(packet, clientid, MAX_DOPT_SIZE);
|
||||
if (cidlen == 0)
|
||||
return 1;
|
||||
if (memcmp(client_config.clientid, clientid,
|
||||
min_size_t(cidlen, client_config.clientid_len))) {
|
||||
log_line("Packet clientid does not match our clientid. Ignoring.");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -568,7 +577,8 @@ static struct dhcpmsg init_packet(char type, uint32_t xid)
|
||||
};
|
||||
add_option_msgtype(&packet, type);
|
||||
memcpy(packet.chaddr, client_config.arp, 6);
|
||||
add_option_clientid(&packet);
|
||||
add_option_clientid(&packet, client_config.clientid,
|
||||
client_config.clientid_len);
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
32
ndhc/ndhc.c
32
ndhc/ndhc.c
@ -88,6 +88,7 @@ struct client_state_t cs = {
|
||||
struct client_config_t client_config = {
|
||||
.interface = "eth0",
|
||||
.arp = "\0\0\0\0\0\0",
|
||||
.clientid_len = 0,
|
||||
};
|
||||
|
||||
static void show_usage(void)
|
||||
@ -202,17 +203,24 @@ static int is_string_hwaddr(char *str, size_t slen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_clientid_mac_string(char *str, size_t slen)
|
||||
static int get_clientid_string(char *str, size_t slen)
|
||||
{
|
||||
if (!is_string_hwaddr(str, slen))
|
||||
if (!slen)
|
||||
return -1;
|
||||
if (!is_string_hwaddr(str, slen)) {
|
||||
client_config.clientid[0] = 0;
|
||||
memcpy(&client_config.clientid + 1, str,
|
||||
min_size_t(slen, sizeof client_config.clientid - 1));
|
||||
client_config.clientid_len = slen + 1;
|
||||
return 0;
|
||||
client_config.clientid[0] = strtol(str, NULL, 16);
|
||||
client_config.clientid[1] = strtol(str+3, NULL, 16);
|
||||
client_config.clientid[2] = strtol(str+6, NULL, 16);
|
||||
client_config.clientid[3] = strtol(str+9, NULL, 16);
|
||||
client_config.clientid[4] = strtol(str+12, NULL, 16);
|
||||
client_config.clientid[5] = strtol(str+15, NULL, 16);
|
||||
client_config.clientid[6] = '\0';
|
||||
}
|
||||
|
||||
uint8_t mac[6];
|
||||
for (size_t i = 0; i < sizeof mac; ++i)
|
||||
mac[i] = strtol(str+i*3, NULL, 16);
|
||||
client_config.clientid[0] = 1; // Ethernet MAC type
|
||||
memcpy(&client_config.clientid + 1, mac, sizeof mac);
|
||||
client_config.clientid_len = 7;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -427,11 +435,7 @@ int main(int argc, char **argv)
|
||||
|
||||
switch (c) {
|
||||
case 'c':
|
||||
if (!get_clientid_mac_string(optarg, strlen(optarg)))
|
||||
strnkcpy(client_config.clientid, optarg,
|
||||
sizeof client_config.clientid);
|
||||
else
|
||||
client_config.clientid_mac = 1;
|
||||
get_clientid_string(optarg, strlen(optarg));
|
||||
break;
|
||||
case 'f':
|
||||
client_config.foreground = 1;
|
||||
|
@ -55,9 +55,9 @@ struct client_config_t {
|
||||
char quit_after_lease; // Quit after obtaining lease
|
||||
char abort_if_no_lease; // Abort if no lease
|
||||
char background_if_no_lease; // Fork to background if no lease
|
||||
char clientid_mac; // If true, then the clientid is a MAC addr
|
||||
char interface[IFNAMSIZ]; // The name of the interface to use
|
||||
char clientid[64]; // Optional client id to use
|
||||
uint8_t clientid_len; // Length of the clientid
|
||||
char hostname[64]; // Optional hostname to use
|
||||
char vendor[64]; // Vendor identification that will be sent
|
||||
int ifindex; // Index number of the interface to use
|
||||
|
@ -121,6 +121,11 @@ static int get_if_index_and_mac(const struct nlmsghdr *nlh,
|
||||
client_config.interface,
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
memcpy(client_config.arp, mac, 6);
|
||||
if (client_config.clientid_len < 2) {
|
||||
client_config.clientid[0] = 1; // Ethernet MAC type
|
||||
memcpy(&client_config.clientid + 1, mac, 6);
|
||||
client_config.clientid_len = 7;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -272,6 +272,11 @@ void add_option_serverid(struct dhcpmsg *packet, uint32_t sid)
|
||||
add_u32_option(packet, DCODE_SERVER_ID, sid);
|
||||
}
|
||||
|
||||
void add_option_clientid(struct dhcpmsg *packet, char *clientid, size_t clen)
|
||||
{
|
||||
add_option_string(packet, DCODE_CLIENT_ID, clientid, clen);
|
||||
}
|
||||
|
||||
#ifndef NDHS_BUILD
|
||||
void add_option_maxsize(struct dhcpmsg *packet)
|
||||
{
|
||||
@ -288,36 +293,12 @@ void add_option_vendor(struct dhcpmsg *packet)
|
||||
add_option_string(packet, DCODE_VENDOR, "ndhc", sizeof "ndhc" - 1);
|
||||
}
|
||||
|
||||
void add_option_clientid(struct dhcpmsg *packet)
|
||||
{
|
||||
char buf[sizeof client_config.clientid + 1];
|
||||
size_t len = 6;
|
||||
buf[0] = 1; // Ethernet MAC
|
||||
if (!client_config.clientid_mac) {
|
||||
size_t slen = strlen(client_config.clientid);
|
||||
if (!slen) {
|
||||
memcpy(buf+1, client_config.arp, len);
|
||||
} else {
|
||||
buf[0] = 0; // Not a hardware address
|
||||
len = slen;
|
||||
memcpy(buf+1, client_config.clientid, slen);
|
||||
}
|
||||
} else
|
||||
memcpy(buf+1, client_config.clientid, len);
|
||||
add_option_string(packet, DCODE_CLIENT_ID, buf, len+1);
|
||||
}
|
||||
|
||||
void add_option_hostname(struct dhcpmsg *packet)
|
||||
{
|
||||
size_t len = strlen(client_config.hostname);
|
||||
if (len)
|
||||
add_option_string(packet, DCODE_HOSTNAME, client_config.hostname, len);
|
||||
}
|
||||
#else
|
||||
void add_option_clientid(struct dhcpmsg *packet, char *clientid, size_t clen)
|
||||
{
|
||||
add_option_string(packet, DCODE_CLIENT_ID, clientid, clen);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t get_option_router(struct dhcpmsg *packet)
|
||||
@ -368,3 +349,13 @@ uint32_t get_option_leasetime(struct dhcpmsg *packet)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Returned buffer is not nul-terminated.
|
||||
size_t get_option_clientid(struct dhcpmsg *packet, char *cbuf, size_t clen)
|
||||
{
|
||||
if (clen < 1)
|
||||
return 0;
|
||||
ssize_t ol = get_dhcp_opt(packet, DCODE_CLIENT_ID,
|
||||
(uint8_t *)cbuf, clen);
|
||||
return ol > 0 ? ol : 0;
|
||||
}
|
||||
|
@ -71,17 +71,16 @@ void add_option_broadcast(struct dhcpmsg *packet, uint32_t bc);
|
||||
void add_option_msgtype(struct dhcpmsg *packet, uint8_t type);
|
||||
void add_option_reqip(struct dhcpmsg *packet, uint32_t ip);
|
||||
void add_option_serverid(struct dhcpmsg *packet, uint32_t sid);
|
||||
void add_option_clientid(struct dhcpmsg *packet, char *clientid, size_t clen);
|
||||
#ifndef NDHS_BUILD
|
||||
void add_option_maxsize(struct dhcpmsg *packet);
|
||||
void add_option_vendor(struct dhcpmsg *packet);
|
||||
void add_option_clientid(struct dhcpmsg *packet);
|
||||
void add_option_hostname(struct dhcpmsg *packet);
|
||||
#else
|
||||
void add_option_clientid(struct dhcpmsg *packet, char *clientid, size_t clen);
|
||||
#endif
|
||||
uint32_t get_option_router(struct dhcpmsg *packet);
|
||||
uint8_t get_option_msgtype(struct dhcpmsg *packet);
|
||||
uint32_t get_option_serverid(struct dhcpmsg *packet, int *found);
|
||||
uint32_t get_option_leasetime(struct dhcpmsg *packet);
|
||||
size_t get_option_clientid(struct dhcpmsg *packet, char *cbuf, size_t clen);
|
||||
|
||||
#endif
|
||||
|
@ -38,6 +38,11 @@ static inline unsigned long long curms()
|
||||
return ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000ULL;
|
||||
}
|
||||
|
||||
static inline size_t min_size_t(size_t a, size_t b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
void epoll_add(int epfd, int fd);
|
||||
void epoll_del(int epfd, int fd);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user