Add new code for creating DHCP option data, and use it in ndhc.c.

This commit is contained in:
Nicholas J. Kain 2011-03-30 07:05:00 -04:00
parent 13d9119f3a
commit 3c85228aaf
3 changed files with 68 additions and 14 deletions

View File

@ -296,10 +296,8 @@ int main(int argc, char **argv)
len = strlen(optarg) > 64 ? 64 : strlen(optarg);
if (client_config.clientid)
free(client_config.clientid);
client_config.clientid = xmalloc(len + 3);
client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
client_config.clientid[OPT_LEN] = len + 1;
memcpy(client_config.clientid + 3, optarg, len);
client_config.clientid =
alloc_dhcp_client_id_option(0, (unsigned char *)optarg, len);
break;
case 'f':
client_config.foreground = 1;
@ -317,10 +315,8 @@ int main(int argc, char **argv)
len = strlen(optarg) > 64 ? 64 : strlen(optarg);
if (client_config.hostname)
free(client_config.hostname);
client_config.hostname = xmalloc(len + 3);
client_config.hostname[OPT_CODE] = DHCP_HOST_NAME;
client_config.hostname[OPT_LEN] = len + 1;
memcpy(client_config.hostname + 3, optarg, len);
client_config.hostname =
alloc_option(DHCP_HOST_NAME, (unsigned char *)optarg, len);
break;
case 'i':
client_config.interface = optarg;
@ -376,11 +372,8 @@ int main(int argc, char **argv)
}
if (!client_config.clientid) {
client_config.clientid = xmalloc(6 + 3);
client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
client_config.clientid[OPT_LEN] = 7;
client_config.clientid[OPT_DATA] = 1;
memcpy(client_config.clientid + 3, client_config.arp, 6);
client_config.clientid =
alloc_dhcp_client_id_option(1, client_config.arp, 6);
}
if (chdir(chroot_dir)) {

View File

@ -8,9 +8,11 @@
#include <stdlib.h>
#include <string.h>
#include "log.h"
#include "options.h"
#include "log.h"
#include "malloc.h"
/* supported options are easily added here */
struct dhcp_option options[] = {
/* name[10] flags code */
@ -56,6 +58,55 @@ int option_lengths[] = {
[OPTION_S32] = 4
};
size_t sizeof_option(unsigned char code, size_t datalen)
{
if (code == DHCP_PADDING || code == DHCP_END)
return 1;
return 2 + datalen;
}
// optdata can be NULL
size_t set_option(unsigned char *buf, size_t buflen, unsigned char code,
unsigned char *optdata, size_t datalen)
{
if (!optdata)
datalen = 0;
if (code == DHCP_PADDING || code == DHCP_END) {
if (buflen < 1)
return 0;
buf[0] = code;
return 1;
}
if (datalen > 255 || buflen < 2 + datalen)
return 0;
buf[0] = code;
buf[1] = datalen;
memcpy(buf + 2, optdata, datalen);
return 2 + datalen;
}
unsigned char *alloc_option(unsigned char code, unsigned char *optdata,
size_t datalen)
{
unsigned char *ret;
size_t len = sizeof_option(code, datalen);
ret = xmalloc(len);
set_option(ret, len, code, optdata, datalen);
return ret;
}
// This is tricky -- the data must be prefixed by one byte indicating the
// type of ARP MAC address (1 for ethernet) or 0 for a purely symbolic
// identifier.
unsigned char *alloc_dhcp_client_id_option(unsigned char type,
unsigned char *idstr, size_t idstrlen)
{
unsigned char data[idstrlen + 1];
data[0] = type;
memcpy(data + 1, idstr, idstrlen);
return alloc_option(DHCP_CLIENT_ID, data, sizeof data);
}
/* Get an option with bounds checking (warning, result is not aligned) */
uint8_t* get_option(struct dhcpMessage *packet, int code)
@ -161,6 +212,7 @@ int add_simple_option(unsigned char *optionptr, unsigned char code,
length = option_lengths[options[i].flags & TYPE_MASK];
}
log_line("aso(): code=0x%02x length=0x%02x", code, length);
option[OPT_CODE] = code;
option[OPT_LEN] = (unsigned char)length;

View File

@ -88,6 +88,15 @@ struct option_set {
extern struct dhcp_option options[];
extern int option_lengths[];
size_t sizeof_option(unsigned char code, size_t datalen);
size_t set_option(unsigned char *buf, size_t buflen, unsigned char code,
unsigned char *optdata, size_t datalen);
unsigned char *alloc_option(unsigned char code, unsigned char *optdata,
size_t datalen);
unsigned char *alloc_dhcp_client_id_option(unsigned char type,
unsigned char *idstr, size_t idstrlen);
uint8_t *get_option(struct dhcpMessage *packet, int code);
int end_option(uint8_t *optionptr);
int add_option_string(unsigned char *optionptr, unsigned char *string);