diff --git a/src/dhcpv6.c b/src/dhcpv6.c index 01bda16..53aa68d 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -194,7 +195,7 @@ static char *dhcpv6_status_code_to_str(uint16_t code) return "Unknown"; } -int init_dhcpv6(const char *ifname, unsigned int options, int sol_timeout) +int init_dhcpv6(const char *ifname, unsigned int options, int sol_timeout, const char *duid_path) { client_options = options; dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = sol_timeout; @@ -247,6 +248,29 @@ int init_dhcpv6(const char *ifname, unsigned int options, int sol_timeout) odhcp6c_add_state(STATE_CLIENT_ID, duid, sizeof(duid)); } + // Write duid to path + if (duid_path) { + // read duid + size_t duid_len; + void *duid = odhcp6c_get_state(STATE_CLIENT_ID, &duid_len); + char duid_buf[duid_len * 2 + 1]; + script_hexlify(duid_buf, &((uint8_t *) duid)[4], duid_len - 4); + duid_buf[duid_len * 2] = 0; + + // generate path + char file_path[strlen(duid_path) + strlen(ifname) + 2]; + sprintf(file_path, "%s.%s", duid_path, ifname); + + // write to file + FILE *fp = fopen(file_path, "w"); + if (fp) { + fprintf(fp, "%s\n", duid_buf); + fclose(fp); + } else { + syslog(LOG_ERR, "Failed to write DUID '%s' into file '%s'!", duid_buf, file_path); + }; + } + // Create ORO if (!(client_options & DHCPV6_STRICT_OPTIONS)) { uint16_t oro[] = { diff --git a/src/odhcp6c.c b/src/odhcp6c.c index e713da9..d986b66 100644 --- a/src/odhcp6c.c +++ b/src/odhcp6c.c @@ -169,6 +169,7 @@ int main(_unused int argc, char* const argv[]) // Allocate resources const char *pidfile = NULL; const char *script = "/usr/sbin/odhcp6c-update"; + const char *duid_path = "/var/run/odhcp6c-duid"; ssize_t l; uint8_t buf[134], *o_data; char *optpos; @@ -187,7 +188,7 @@ int main(_unused int argc, char* const argv[]) unsigned int ra_options = RA_RDNSS_DEFAULT_LIFETIME; unsigned int ra_holdoff_interval = RA_MIN_ADV_INTERVAL; - while ((c = getopt(argc, argv, "S::DN:V:P:FB:c:i:r:Ru:Ux:s:kt:m:Lhedp:fav")) != -1) { + while ((c = getopt(argc, argv, "S::DN:V:P:FB:c:C:i:r:Ru:Ux:s:kt:m:Lhedp:fav")) != -1) { switch (c) { case 'S': allow_slaac_only = (optarg) ? atoi(optarg) : -1; @@ -284,6 +285,10 @@ int main(_unused int argc, char* const argv[]) help = true; break; + case 'C': + duid_path = optarg; + break; + case 'i': if (inet_pton(AF_INET6, optarg, &ifid) != 1) help = true; @@ -417,7 +422,7 @@ int main(_unused int argc, char* const argv[]) signal(SIGUSR2, sighandler); if ((urandom_fd = open("/dev/urandom", O_CLOEXEC | O_RDONLY)) < 0 || - init_dhcpv6(ifname, client_options, sol_timeout) || + init_dhcpv6(ifname, client_options, sol_timeout, duid_path) || ra_init(ifname, &ifid, ra_options, ra_holdoff_interval) || script_init(script, ifname)) { syslog(LOG_ERR, "failed to initialize: %s", strerror(errno)); @@ -620,6 +625,7 @@ static int usage(void) " -x 0x1f4:ABBA - option 500\n" " -x 202:'\"file\"' - option 202\n" " -c Override client-ID (base-16 encoded 16-bit type + value)\n" + " -C Export used client-ID to specified path\n" " -i Use a custom interface identifier for RA handling\n" " -r Options to be requested (comma-separated)\n" " -R Do not request any options except those specified with -r\n" diff --git a/src/odhcp6c.h b/src/odhcp6c.h index 0831775..4d4f120 100644 --- a/src/odhcp6c.h +++ b/src/odhcp6c.h @@ -392,7 +392,7 @@ struct odhcp6c_opt { const char *str; }; -int init_dhcpv6(const char *ifname, unsigned int client_options, int sol_timeout); +int init_dhcpv6(const char *ifname, unsigned int client_options, int sol_timeout, const char *duid_path); int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd, bool stateful_only); int dhcpv6_request(enum dhcpv6_msg type); int dhcpv6_poll_reconfigure(void); @@ -408,6 +408,7 @@ int ra_get_reachable(void); int ra_get_retransmit(void); int script_init(const char *path, const char *ifname); +void script_hexlify(char *dst, const uint8_t *src, size_t len); ssize_t script_unhexlify(uint8_t *dst, size_t len, const char *src); void script_call(const char *status, int delay, bool resume); diff --git a/src/script.c b/src/script.c index bb93a53..5c52cbf 100644 --- a/src/script.c +++ b/src/script.c @@ -84,7 +84,7 @@ ssize_t script_unhexlify(uint8_t *dst, size_t len, const char *src) return c; } -static void script_hexlify(char *dst, const uint8_t *src, size_t len) +void script_hexlify(char *dst, const uint8_t *src, size_t len) { for (size_t i = 0; i < len; ++i) { *dst++ = hexdigits[src[i] >> 4];