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.");
|
log_line("Packet does not specify a DHCP message type. Ignoring.");
|
||||||
return 0;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +577,8 @@ static struct dhcpmsg init_packet(char type, uint32_t xid)
|
|||||||
};
|
};
|
||||||
add_option_msgtype(&packet, type);
|
add_option_msgtype(&packet, type);
|
||||||
memcpy(packet.chaddr, client_config.arp, 6);
|
memcpy(packet.chaddr, client_config.arp, 6);
|
||||||
add_option_clientid(&packet);
|
add_option_clientid(&packet, client_config.clientid,
|
||||||
|
client_config.clientid_len);
|
||||||
return packet;
|
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 = {
|
struct client_config_t client_config = {
|
||||||
.interface = "eth0",
|
.interface = "eth0",
|
||||||
.arp = "\0\0\0\0\0\0",
|
.arp = "\0\0\0\0\0\0",
|
||||||
|
.clientid_len = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void show_usage(void)
|
static void show_usage(void)
|
||||||
@ -202,17 +203,24 @@ static int is_string_hwaddr(char *str, size_t slen)
|
|||||||
return 0;
|
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;
|
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);
|
uint8_t mac[6];
|
||||||
client_config.clientid[3] = strtol(str+9, NULL, 16);
|
for (size_t i = 0; i < sizeof mac; ++i)
|
||||||
client_config.clientid[4] = strtol(str+12, NULL, 16);
|
mac[i] = strtol(str+i*3, NULL, 16);
|
||||||
client_config.clientid[5] = strtol(str+15, NULL, 16);
|
client_config.clientid[0] = 1; // Ethernet MAC type
|
||||||
client_config.clientid[6] = '\0';
|
memcpy(&client_config.clientid + 1, mac, sizeof mac);
|
||||||
|
client_config.clientid_len = 7;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,11 +435,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'c':
|
case 'c':
|
||||||
if (!get_clientid_mac_string(optarg, strlen(optarg)))
|
get_clientid_string(optarg, strlen(optarg));
|
||||||
strnkcpy(client_config.clientid, optarg,
|
|
||||||
sizeof client_config.clientid);
|
|
||||||
else
|
|
||||||
client_config.clientid_mac = 1;
|
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
client_config.foreground = 1;
|
client_config.foreground = 1;
|
||||||
|
@ -55,9 +55,9 @@ struct client_config_t {
|
|||||||
char quit_after_lease; // Quit after obtaining lease
|
char quit_after_lease; // Quit after obtaining lease
|
||||||
char abort_if_no_lease; // Abort if no lease
|
char abort_if_no_lease; // Abort if no lease
|
||||||
char background_if_no_lease; // Fork to background 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 interface[IFNAMSIZ]; // The name of the interface to use
|
||||||
char clientid[64]; // Optional client id 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 hostname[64]; // Optional hostname to use
|
||||||
char vendor[64]; // Vendor identification that will be sent
|
char vendor[64]; // Vendor identification that will be sent
|
||||||
int ifindex; // Index number of the interface to use
|
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,
|
client_config.interface,
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
memcpy(client_config.arp, mac, 6);
|
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 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -272,6 +272,11 @@ void add_option_serverid(struct dhcpmsg *packet, uint32_t sid)
|
|||||||
add_u32_option(packet, DCODE_SERVER_ID, 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
|
#ifndef NDHS_BUILD
|
||||||
void add_option_maxsize(struct dhcpmsg *packet)
|
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);
|
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)
|
void add_option_hostname(struct dhcpmsg *packet)
|
||||||
{
|
{
|
||||||
size_t len = strlen(client_config.hostname);
|
size_t len = strlen(client_config.hostname);
|
||||||
if (len)
|
if (len)
|
||||||
add_option_string(packet, DCODE_HOSTNAME, client_config.hostname, 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
|
#endif
|
||||||
|
|
||||||
uint32_t get_option_router(struct dhcpmsg *packet)
|
uint32_t get_option_router(struct dhcpmsg *packet)
|
||||||
@ -368,3 +349,13 @@ uint32_t get_option_leasetime(struct dhcpmsg *packet)
|
|||||||
}
|
}
|
||||||
return ret;
|
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_msgtype(struct dhcpmsg *packet, uint8_t type);
|
||||||
void add_option_reqip(struct dhcpmsg *packet, uint32_t ip);
|
void add_option_reqip(struct dhcpmsg *packet, uint32_t ip);
|
||||||
void add_option_serverid(struct dhcpmsg *packet, uint32_t sid);
|
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
|
#ifndef NDHS_BUILD
|
||||||
void add_option_maxsize(struct dhcpmsg *packet);
|
void add_option_maxsize(struct dhcpmsg *packet);
|
||||||
void add_option_vendor(struct dhcpmsg *packet);
|
void add_option_vendor(struct dhcpmsg *packet);
|
||||||
void add_option_clientid(struct dhcpmsg *packet);
|
|
||||||
void add_option_hostname(struct dhcpmsg *packet);
|
void add_option_hostname(struct dhcpmsg *packet);
|
||||||
#else
|
|
||||||
void add_option_clientid(struct dhcpmsg *packet, char *clientid, size_t clen);
|
|
||||||
#endif
|
#endif
|
||||||
uint32_t get_option_router(struct dhcpmsg *packet);
|
uint32_t get_option_router(struct dhcpmsg *packet);
|
||||||
uint8_t get_option_msgtype(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_serverid(struct dhcpmsg *packet, int *found);
|
||||||
uint32_t get_option_leasetime(struct dhcpmsg *packet);
|
uint32_t get_option_leasetime(struct dhcpmsg *packet);
|
||||||
|
size_t get_option_clientid(struct dhcpmsg *packet, char *cbuf, size_t clen);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,6 +38,11 @@ static inline unsigned long long curms()
|
|||||||
return ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000ULL;
|
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_add(int epfd, int fd);
|
||||||
void epoll_del(int epfd, int fd);
|
void epoll_del(int epfd, int fd);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user