state->daemonised = options->daemonised;
state->persistent = options->persistent;
-#ifdef ENABLE_DUID
- if (options->clientid_len == 0) {
- get_duid (iface);
- if (iface->duid_length > 0)
- logger (LOG_INFO, "DUID = %s",
- hwaddr_ntoa (iface->duid, iface->duid_length));
- }
-#endif
-
if (options->request_address.s_addr == 0 &&
(options->doinform || options->dorequest || options->daemonised))
{
}
}
+ if (*options->clientid) {
+ uint8_t family = 0;
+ /* Attempt to see if the ClientID is a hardware address */
+ iface->clientid_len = hwaddr_aton (NULL, options->clientid);
+
+ /* We need to at least try and guess the family */
+ switch (iface->clientid_len) {
+ case ETHER_ADDR_LEN:
+ family = ARPHRD_ETHER;
+ break;
+ case EUI64_ADDR_LEN:
+ family = ARPHRD_IEEE1394;
+ break;
+ case INFINIBAND_ADDR_LEN:
+ family = ARPHRD_INFINIBAND;
+ break;
+ }
+
+ /* It looks and smells like one, so make it one */
+ if (family) {
+ iface->clientid_len += 1;
+ iface->clientid = xmalloc (iface->clientid_len);
+ *iface->clientid = family;
+ hwaddr_aton (iface->clientid + 1, options->clientid);
+ } else {
+ iface->clientid_len = strlen (options->clientid) + 1;
+ iface->clientid = xmalloc (iface->clientid_len);
+ *iface->clientid = '\0';
+ memcpy (iface->clientid + 1,
+ options->clientid, iface->clientid_len - 1);
+ }
+ } else {
+#ifdef ENABLE_DUID
+ unsigned char *duid = NULL;
+ size_t duid_len = 0;
+
+ if (options->doduid) {
+ duid = xmalloc (DUID_LEN);
+ duid_len = get_duid (duid, iface);
+ }
+
+ if (duid_len > 0) {
+ logger (LOG_INFO, "DUID = %s", hwaddr_ntoa (duid, duid_len));
+
+ iface->clientid_len = duid_len + 5;
+ iface->clientid = xmalloc (iface->clientid_len);
+ *iface->clientid = 255; /* RFC 4361 */
+
+ /* IAID is 4 bytes, so if the iface name is 4 bytes use it */
+ if (strlen (iface->name) == 4) {
+ memcpy (iface->clientid + 1, iface->name, 4);
+ } else {
+ /* Name isn't 4 bytes, so use the index */
+ uint32_t ul = htonl (if_nametoindex (iface->name));
+ memcpy (iface->clientid + 1, &ul, 4);
+ }
+
+ memcpy (iface->clientid + 5, duid, duid_len);
+ free (duid);
+ } else {
+#else
+ {
+#endif
+ iface->clientid_len = iface->hwlen + 1;
+ iface->clientid = xmalloc (iface->clientid_len);
+ *iface->clientid = iface->family;
+ memcpy (iface->clientid + 1, iface->hwaddr, iface->hwlen);
+ }
+ }
+
return (true);
}
do_socket (state, SOCKET_CLOSED);
drop_config (state, options);
free_route (iface->previous_routes);
+ free (iface->clientid);
free (iface);
}
}
ssize_t send_message (const interface_t *iface, const dhcp_t *dhcp,
- uint32_t xid, char type,
- const options_t *options)
+ uint32_t xid, char type, const options_t *options)
{
struct udp_dhcp_packet *packet;
dhcpmessage_t *message;
p += options->userclass_len;
}
- if (options->classid_len > 0) {
+ if (*options->classid > 0) {
*p++ = DHCP_CLASSID;
- *p++ = options->classid_len;
- memcpy (p, options->classid, options->classid_len);
- p += options->classid_len;
+ *p++ = l = strlen (options->classid);
+ memcpy (p, options->classid, l);
+ p += l;
}
}
*p++ = DHCP_CLIENTID;
- if (options->clientid_len > 0) {
- /* Attempt to see if the ClientID is a hardware address */
- size_t hwlen = hwaddr_aton (NULL, options->clientid);
- sa_family_t family = 0;
-
- if (hwlen) {
- /* We need to at least try and guess the family */
- switch (hwlen) {
- case ETHER_ADDR_LEN:
- family = ARPHRD_ETHER;
- break;
- case EUI64_ADDR_LEN:
- family = ARPHRD_IEEE1394;
- break;
- case INFINIBAND_ADDR_LEN:
- family = ARPHRD_INFINIBAND;
- break;
- }
- }
-
- /* It looks and smells like one, so make it one */
- if (hwlen && family) {
- unsigned char *hwaddr = xmalloc (hwlen);
- hwaddr_aton (hwaddr, options->clientid);
- *p++ = hwlen + 1;
- *p++ = family;
- memcpy (p, hwaddr, hwlen);
- free (hwaddr);
- p += hwlen;
- } else {
- *p++ = options->clientid_len + 1;
- *p++ = 0;
- memcpy (p, options->clientid, options->clientid_len);
- p += options->clientid_len;
- }
-#ifdef ENABLE_DUID
- } else if (iface->duid && options->doduid) {
- *p++ = iface->duid_length + 5;
- *p++ = 255; /* RFC 4361 */
-
- /* IAID is 4 bytes, so if the iface name is 4 bytes use it */
- if (strlen (iface->name) == 4) {
- memcpy (p, iface->name, 4);
- } else {
- /* Name isn't 4 bytes, so use the index */
- ul = htonl (if_nametoindex (iface->name));
- memcpy (p, &ul, 4);
- }
- p += 4;
-
- memcpy (p, iface->duid, iface->duid_length);
- p += iface->duid_length;
-#endif
- } else {
- *p++ = iface->hwlen + 1;
- *p++ = iface->family;
- memcpy (p, iface->hwaddr, iface->hwlen);
- p += iface->hwlen;
- }
+ *p++ = iface->clientid_len;
+ memcpy (p, iface->clientid, iface->clientid_len);
+ p+= iface->clientid_len;
*p++ = DHCP_END;
};
ssize_t send_message (const interface_t *iface, const dhcp_t *dhcp,
- uint32_t xid, char type,
- const options_t *options);
+ uint32_t xid, char type, const options_t *options);
void free_dhcp (dhcp_t *dhcp);
int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message);
options->script = (char *) DEFAULT_SCRIPT;
snprintf (options->classid, CLASS_ID_MAX_LEN, "%s %s",
PACKAGE, VERSION);
- options->classid_len = strlen (options->classid);
options->doarp = true;
options->dodns = true;
#endif
case 'h':
if (! optarg)
- memset (options->hostname, 0,
- sizeof (options->hostname));
+ *options->hostname = '\0';
else if (strlen (optarg) > MAXHOSTNAMELEN) {
logger (LOG_ERR,
"`%s' too long for HostName string, max is %d",
break;
case 'i':
if (! optarg) {
- memset (options->classid, 0,
- sizeof (options->classid));
- options->classid_len = 0;
+ *options->classid = '\0';
} else if (strlen (optarg) > CLASS_ID_MAX_LEN) {
logger (LOG_ERR,
"`%s' too long for ClassID string, max is %d",
optarg, CLASS_ID_MAX_LEN);
goto abort;
} else
- options->classid_len = strlcpy (options->classid, optarg,
- sizeof (options->classid));
+ strlcpy (options->classid, optarg,
+ sizeof (options->classid));
break;
case 'k':
sig = SIGHUP;
optarg, CLIENT_ID_MAX_LEN);
goto abort;
}
- options->clientid_len = strlcpy (options->clientid, optarg,
- sizeof (options->clientid));
- /* empty string disabled duid */
- if (options->clientid_len == 0)
+ if (strlcpy (options->clientid, optarg,
+ sizeof (options->clientid)) == 0)
+ /* empty string disabled duid */
options->doduid = false;
} else {
char hostname[MAXHOSTNAMELEN];
int fqdn;
char classid[CLASS_ID_MAX_LEN];
- size_t classid_len;
char clientid[CLIENT_ID_MAX_LEN];
- size_t clientid_len;
char userclass[USERCLASS_MAX_LEN];
size_t userclass_len;
uint32_t leasetime;
#define THIRTY_YEARS_IN_SECONDS 946707779
-void get_duid (interface_t *iface)
+size_t get_duid (unsigned char *duid, const interface_t *iface)
{
FILE *f;
uint16_t type = 0;
uint16_t hw = 0;
uint32_t ul;
time_t t;
- unsigned char *p = iface->duid;
int x = 0;
-
+ unsigned char *p = duid;
+ size_t len = 0;
+
if (! iface)
- return;
-
- /* Remove any existing */
- iface->duid[0] = '\0';
- iface->duid_length = 0;
+ return (0);
/* If we already have a DUID then use it as it's never supposed
* to change once we have one even if the interfaces do */
if ((f = fopen (DUIDFILE, "r"))) {
- char *duid = getline (f);
- if (duid) {
- iface->duid_length = hwaddr_aton (NULL, duid);
- if (iface->duid_length &&
- iface->duid_length <= DUID_LEN)
- hwaddr_aton (iface->duid, duid);
- free (duid);
+ char *line = getline (f);
+ if (line) {
+ len = hwaddr_aton (NULL, line);
+ if (len && len <= DUID_LEN)
+ hwaddr_aton (duid, line);
+ free (line);
}
fclose (f);
- if (iface->duid_length)
- return;
+ if (len)
+ return (len);
} else {
if (errno != ENOENT) {
logger (LOG_ERR, "fopen `%s': %s",
DUIDFILE, strerror (errno));
- return;
+ return (0);
}
}
memcpy (p, iface->hwaddr, iface->hwlen);
p += iface->hwlen;
- iface->duid_length = p - iface->duid;
+ len = p - duid;
if (! (f = fopen (DUIDFILE, "w")))
logger (LOG_ERR, "fopen `%s': %s", DUIDFILE, strerror (errno));
else {
- x = fprintf (f, "%s\n",
- hwaddr_ntoa (iface->duid, iface->duid_length));
+ x = fprintf (f, "%s\n", hwaddr_ntoa (duid, len));
fclose (f);
}
/* Failed to write the duid? scrub it, we cannot use it */
if (x < 1) {
- memset (iface->duid, 0, sizeof (iface->duid));
- iface->duid_length = 0;
+ len = 0;
unlink (DUIDFILE);
}
+
+ return (len);
}
#endif
#include "interface.h"
-void get_duid (interface_t *iface);
+size_t get_duid (unsigned char *duid, const interface_t *iface);
#endif
#endif
}
print_clean (f, "INTERFACE", iface->name);
print_clean (f, "CLASSID", options->classid);
- if (options->clientid_len > 0) {
- char *clean = cleanmetas (options->clientid);
- fprintf (f, "CLIENTID='00:%s'\n", clean);
- free (clean);
+ if (iface->clientid_len > 0) {
+ fprintf (f, "CLIENTID='%s'\n",
+ hwaddr_ntoa (iface->clientid, iface->clientid_len));
}
-#ifdef ENABLE_DUID
- else if (iface->duid_length > 0 && options->doduid) {
- unsigned char *duid;
- unsigned char *p;
- uint32_t ul;
-
- p = duid = xmalloc (iface->duid_length + 6);
- *p++ = 255;
-
- /* IAID is 4 bytes, so if the interface name is 4 bytes
- * then use it */
- if (strlen (iface->name) == 4) {
- memcpy (p, iface->name, 4);
- } else {
- /* Name isn't 4 bytes, so use the index */
- ul = htonl (if_nametoindex (iface->name));
- memcpy (p, &ul, 4);
- }
- p += 4;
-
- memcpy (p, iface->duid, iface->duid_length);
- p += iface->duid_length;
-
- fprintf (f, "CLIENTID='%s'\n", hwaddr_ntoa (duid,
- (size_t) (p - duid)));
- free (duid);
- }
-#endif
- else
- fprintf (f, "CLIENTID='%.2X:%s'\n", iface->family,
- hwaddr_ntoa (iface->hwaddr, iface->hwlen));
fprintf (f, "DHCPCHADDR='%s'\n", hwaddr_ntoa (iface->hwaddr,
iface->hwlen));
time_t start_uptime;
-#ifdef ENABLE_DUID
- unsigned char duid[DUID_LEN];
- size_t duid_length;
-#endif
+ unsigned char *clientid;
+ size_t clientid_len;
} interface_t;
void free_address (address_t *addresses);