From: Roy Marples Date: Fri, 15 Nov 2013 13:43:41 +0000 (+0000) Subject: Allow IAID to be configured in DHCPv4 clientid. X-Git-Tag: v6.2.0~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ebc9d360fab092318d9ce64a70b9693b33a87d0b;p=thirdparty%2Fdhcpcd.git Allow IAID to be configured in DHCPv4 clientid. Use this as the default for DHCPv6 IA's as well. Rename if_iaid to if_ia as it's really an IA containing an IAID. --- diff --git a/dhcp.c b/dhcp.c index c46a7f8c..b237ca98 100644 --- a/dhcp.c +++ b/dhcp.c @@ -2512,8 +2512,7 @@ dhcp_init(struct interface *ifp) { struct dhcp_state *state; const struct if_options *ifo; - unsigned char *duid; - size_t len, ifl; + size_t len; state = D_STATE(ifp); if (state == NULL) { @@ -2546,33 +2545,15 @@ dhcp_init(struct interface *ifp) goto eexit; memcpy(state->clientid, ifo->clientid, ifo->clientid[0] + 1); } else if (ifo->options & DHCPCD_CLIENTID) { - len = 0; if (ifo->options & DHCPCD_DUID) { - duid = malloc(DUID_LEN); - if (duid == NULL) - goto eexit; - if ((len = get_duid(duid, ifp)) == 0) - syslog(LOG_ERR, "get_duid: %m"); - } else - duid = NULL; - if (len > 0) { - state->clientid = malloc(len + 6); + state->clientid = malloc(duid_len + 6); if (state->clientid == NULL) goto eexit; - state->clientid[0] = len + 5; + state->clientid[0] = duid_len + 5; state->clientid[1] = 255; /* RFC 4361 */ - ifl = strlen(ifp->name); - if (ifl < 5) { - memcpy(state->clientid + 2, ifp->name, ifl); - if (ifl < 4) - memset(state->clientid + 2 + ifl, - 0, 4 - ifl); - } else { - ifl = htonl(ifp->index); - memcpy(state->clientid + 2, &ifl, 4); - } - memcpy(state->clientid + 6, duid, len); - } else if (len == 0) { + memcpy(state->clientid + 2, ifo->iaid, 4); + memcpy(state->clientid + 6, duid, duid_len); + } else { len = ifp->hwlen + 1; state->clientid = malloc(len + 1); if (state->clientid == NULL) @@ -2582,7 +2563,6 @@ dhcp_init(struct interface *ifp) memcpy(state->clientid + 2, ifp->hwaddr, ifp->hwlen); } - free(duid); } if (ifo->options & DHCPCD_CLIENTID) syslog(LOG_DEBUG, "%s: using ClientID %s", ifp->name, diff --git a/dhcp6.c b/dhcp6.c index a562b734..fbdc8a46 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -78,8 +78,6 @@ static struct msghdr rcvhdr; static struct iovec rcviov[2]; static unsigned char *rcvbuf; static unsigned char ansbuf[1500]; -static unsigned char *duid; -static uint16_t duid_len; static char ntopbuf[INET6_ADDRSTRLEN]; static char *status; static size_t status_len; @@ -153,7 +151,6 @@ dhcp6_cleanup(void) free(sndbuf); free(rcvbuf); - free(duid); free(status); } #endif @@ -470,7 +467,7 @@ dhcp6_makemessage(struct interface *ifp) /* FALLTHROUGH */ case DH6S_INIT: /* FALLTHROUGH */ case DH6S_DISCOVER: - len += ifo->iaid_len * (sizeof(*o) + (sizeof(u32) * 3)); + len += ifo->ia_len * (sizeof(*o) + (sizeof(u32) * 3)); IA = 1; break; default: @@ -567,18 +564,18 @@ dhcp6_makemessage(struct interface *ifp) o->len = 0; } - for (l = 0; IA && l < ifo->iaid_len; l++) { + for (l = 0; IA && l < ifo->ia_len; l++) { o = D6_NEXT_OPTION(o); o->code = htons(ifo->ia_type); o->len = htons(sizeof(u32) + sizeof(u32) + sizeof(u32)); p = D6_OPTION_DATA(o); - memcpy(p, ifo->iaid[l].iaid, sizeof(u32)); + memcpy(p, ifo->ia[l].iaid, sizeof(u32)); p += sizeof(u32); memset(p, 0, sizeof(u32) + sizeof(u32)); TAILQ_FOREACH(ap, &state->addrs, next) { if (ap->prefix_vltime == 0) continue; - if (memcmp(ifo->iaid[l].iaid, ap->iaid, sizeof(u32))) + if (memcmp(ifo->ia[l].iaid, ap->iaid, sizeof(u32))) continue; so = D6_NEXT_OPTION(o); if (ifo->ia_type == D6_OPTION_IA_PD) { @@ -1813,7 +1810,7 @@ dhcp6_delegate_prefix(struct interface *ifp) struct dhcp6_state *state, *ifd_state; struct ipv6_addr *ap; size_t i, j, k; - struct if_iaid *iaid; + struct if_ia *ia; struct if_sla *sla; struct interface *ifd; uint8_t carrier_warned; @@ -1829,12 +1826,12 @@ dhcp6_delegate_prefix(struct interface *ifp) syslog(LOG_DEBUG, "%s: delegated prefix %s", ifp->name, ap->saddr); } - for (i = 0; i < ifo->iaid_len; i++) { - iaid = &ifo->iaid[i]; - if (memcmp(iaid->iaid, ap->iaid, - sizeof(iaid->iaid))) + for (i = 0; i < ifo->ia_len; i++) { + ia = &ifo->ia[i]; + if (memcmp(ia->iaid, ap->iaid, + sizeof(ia->iaid))) continue; - if (iaid->sla_len == 0) { + if (ia->sla_len == 0) { /* no SLA configured, so lets * automate it */ if (ifp == ifd) @@ -1851,8 +1848,8 @@ dhcp6_delegate_prefix(struct interface *ifp) NULL, ifp)) k++; } - for (j = 0; j < iaid->sla_len; j++) { - sla = &iaid->sla[j]; + for (j = 0; j < ia->sla_len; j++) { + sla = &ia->sla[j]; if (strcmp(ifd->name, sla->ifname)) continue; if (ifd->carrier == LINK_DOWN) { @@ -1880,12 +1877,12 @@ dhcp6_delegate_prefix(struct interface *ifp) } /* Warn about configured interfaces for delegation that do not exist */ - for (i = 0; i < ifo->iaid_len; i++) { - iaid = &ifo->iaid[i]; - for (j = 0; j < iaid->sla_len; j++) { - sla = &iaid->sla[j]; + for (i = 0; i < ifo->ia_len; i++) { + ia = &ifo->ia[i]; + for (j = 0; j < ia->sla_len; j++) { + sla = &ia->sla[j]; for (k = 0; k < i; j++) - if (strcmp(sla->ifname, iaid->sla[j].ifname) == 0) + if (strcmp(sla->ifname, ia->sla[j].ifname) == 0) break; if (j >= i && find_interface(sla->ifname) == NULL) syslog(LOG_ERR, @@ -1910,7 +1907,7 @@ dhcp6_find_delegates(struct interface *ifp) struct dhcp6_state *state; struct ipv6_addr *ap; size_t i, j, k; - struct if_iaid *iaid; + struct if_ia *ia; struct if_sla *sla; struct interface *ifd; @@ -1923,13 +1920,13 @@ dhcp6_find_delegates(struct interface *ifp) if (state == NULL || state->state != DH6S_BOUND) continue; TAILQ_FOREACH(ap, &state->addrs, next) { - for (i = 0; i < ifo->iaid_len; i++) { - iaid = &ifo->iaid[i]; - if (memcmp(iaid->iaid, ap->iaid, - sizeof(iaid->iaid))) + for (i = 0; i < ifo->ia_len; i++) { + ia = &ifo->ia[i]; + if (memcmp(ia->iaid, ap->iaid, + sizeof(ia->iaid))) continue; - for (j = 0; j < iaid->sla_len; j++) { - sla = &iaid->sla[j]; + for (j = 0; j < ia->sla_len; j++) { + sla = &ia->sla[j]; if (strcmp(ifp->name, sla->ifname)) continue; if (ipv6_linklocal(ifp) == NULL) { @@ -2417,13 +2414,6 @@ dhcp6_start(struct interface *ifp, enum DH6S init_state) if (sock == -1 && dhcp6_open() == -1) return -1; - if (duid == NULL) { - duid = malloc(DUID_LEN); - if (duid == NULL) - return -1; - duid_len = get_duid(duid, ifp); - } - ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state)); state = D6_STATE(ifp); if (state == NULL) diff --git a/dhcpcd.8.in b/dhcpcd.8.in index c9845470..3117c946 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 12, 2013 +.Dd November 15, 2013 .Dt DHCPCD 8 .Os .Sh NAME @@ -125,6 +125,8 @@ is also an implemenation of the DHCPv6 client as specified in By default, .Nm only starts DHCPv6 when instructed to do so by an IPV6 Router Advertisement. +If no Identity Association is configured, +then a Non-temporary Address is requested. .Ss Local Link configuration If .Nm diff --git a/dhcpcd.c b/dhcpcd.c index 36d73824..a01a0b43 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -57,6 +57,7 @@ const char copyright[] = "Copyright (c) 2006-2013 Roy Marples"; #include "dev.h" #include "dhcpcd.h" #include "dhcp6.h" +#include "duid.h" #include "eloop.h" #include "if-options.h" #include "if-pref.h" @@ -141,6 +142,7 @@ cleanup(void) struct interface *ifp; int i; + free(duid); free_options(if_options); if (ifaces) { @@ -319,7 +321,7 @@ configure_interface1(struct interface *ifp) { struct if_options *ifo = ifp->options; int ra_global, ra_iface; - + uint32_t len; /* Do any platform specific configuration */ if_conf(ifp); @@ -336,6 +338,9 @@ configure_interface1(struct interface *ifp) if (ifo->metric != -1) ifp->metric = ifo->metric; + if (!(ifo->options & DHCPCD_IPV6)) + ifo->options &= ~DHCPCD_IPV6RS; + /* We want to disable kernel interface RA as early as possible. */ if (ifo->options & DHCPCD_IPV6RS) { ra_global = check_ipv6(NULL, options & DHCPCD_IPV6RA_OWN ? 1:0); @@ -361,6 +366,35 @@ configure_interface1(struct interface *ifp) ifo->options |= DHCPCD_CLIENTID | DHCPCD_BROADCAST; break; } + + if (!(ifo->options & DHCPCD_IAID)) { + len = strlen(ifp->name); + if (len <= sizeof(ifo->iaid)) { + memcpy(ifo->iaid, ifp->name, len); + memset(ifo->iaid + len, 0, sizeof(ifo->iaid) - len); + } else { + /* IAID is the same size as a uint32_t */ + len = htonl(ifp->index); + memcpy(ifo->iaid, &len, sizeof(len)); + } + ifo->options |= DHCPCD_IAID; + } + +#ifdef INET6 + if (ifo->ia == NULL && ifo->options & DHCPCD_IPV6) { + ifo->ia = malloc(sizeof(*ifo->ia)); + if (ifo->ia == NULL) + syslog(LOG_ERR, "%s: %m", __func__); + else { + if (ifo->ia_type == 0) + ifo->ia_type = D6_OPTION_IA_NA; + memcpy(ifo->ia->iaid, ifo->iaid, sizeof(ifo->iaid)); + ifo->ia_len = 1; + ifo->ia->sla = NULL; + ifo->ia->sla_len = 0; + } + } +#endif } int @@ -457,6 +491,7 @@ start_interface(void *arg) struct interface *ifp = arg; struct if_options *ifo = ifp->options; int nolease; + size_t i; handle_carrier(LINK_UNKNOWN, 0, ifp->name); if (ifp->carrier == LINK_DOWN) { @@ -464,6 +499,27 @@ start_interface(void *arg) return; } + if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6)) { + /* Report client DUID */ + if (duid == NULL) { + if (duid_init(ifp) == 0) + return; + syslog(LOG_INFO, "DUID %s", + hwaddr_ntoa(duid, duid_len)); + } + + /* Report IAIDs */ + syslog(LOG_INFO, "%s: IAID %s", ifp->name, + hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid))); + for (i = 0; i < ifo->ia_len; i++) { + if (memcmp(ifo->iaid, ifo->ia[i].iaid, + sizeof(ifo->iaid))) + syslog(LOG_INFO, "%s: IAID %s", ifp->name, + hwaddr_ntoa(ifo->ia[i].iaid, + sizeof(ifo->ia[i].iaid))); + } + } + if (ifo->options & DHCPCD_IPV6) { if (ifo->options & DHCPCD_IPV6RS && !(ifo->options & DHCPCD_INFORM)) diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in index c58be91e..535f088a 100644 --- a/dhcpcd.conf.5.in +++ b/dhcpcd.conf.5.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 10, 2013 +.Dd November 15, 2013 .Dt DHCPCD.CONF 5 .Os .Sh NAME @@ -135,12 +135,19 @@ Generate an .Rs .%T "RFC 4361" .Re -compliant clientid. +compliant DHCP Unique Identifier. If persistent storage is available then a DUID-LLT (link local address + time) is generated, otherwise DUID-LL is generated (link local address). +This, plus the IAID will be used as the +.Ic clientid . The DUID-LLT generated will be held in .Pa @SYSCONFDIR@/dhcpcd.duid and should not be copied to other hosts. +.It Ic iaid Ar iaid +Set the Interface Association Identifier to +.Ar iaid . +This defaults to the interface name if 4 or less characters. +If more then it defaults to the interface index. .It Ic persistent .Nm dhcpcd normally de-configures the interface and configuration when it exits. @@ -172,16 +179,19 @@ option above to control how the hostname is set on the host. .It Ic ia_na Op Ar iaid Request a DHCPv6 Normal Address for .Ar iaid . -If none is specified, a default .Ar iaid -is used. -If the interface name is 4 characters or less then that is used, -otherwise the interface index is used. -You can request more than one ia_na by specifying a unique iaid for each one. +defaults to the +.Ic iaid +option as described above. +You can request more than one ia_na by specifying a unique +.Ar iaid +for each one. .It Ic ia_ta Op Ar iaid Request a DHCPv6 Temporary Address for .Ar iaid . -You can request more than one ia_ta by specifying a unique iaid for each one. +You can request more than one ia_ta by specifying a unique +.Ar iaid +for each one. .It Ic ia_pd Op Ar iaid Op Ar interface Op / Ar sla_id Op / Ar prefix_len Request a DHCPv6 Delegated Prefix for .Ar iaid . @@ -461,5 +471,7 @@ of a randomly generated number. .Sh AUTHORS .An Roy Marples Aq Mt roy@marples.name .Sh BUGS +When configuring DHCPv6 you can only select one IA type. +.Pp Please report them to .Lk http://roy.marples.name/projects/dhcpcd diff --git a/dhcpcd.h b/dhcpcd.h index 4f0f56f5..67fe6d1c 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -44,7 +44,7 @@ #define LINK_DOWN -1 #define IF_DATA_IPV4 0 -#define IF_DATA_DHCP 1 +#define IF_DATA_DHCP 1 #define IF_DATA_IPV6 2 #define IF_DATA_IPV6ND 3 #define IF_DATA_DHCP6 4 diff --git a/duid.c b/duid.c index 4a77f76f..a119828f 100644 --- a/duid.c +++ b/duid.c @@ -1,6 +1,6 @@ /* * dhcpcd - DHCP client daemon - * Copyright (c) 2006-2008 Roy Marples + * Copyright (c) 2006-2013 Roy Marples * All rights reserved * Redistribution and use in source and binary forms, with or without @@ -51,15 +51,18 @@ #include "duid.h" #include "net.h" +unsigned char *duid = NULL; +size_t duid_len = 0; + static size_t -make_duid(unsigned char *duid, const struct interface *ifp, uint16_t type) +duid_make(unsigned char *d, const struct interface *ifp, uint16_t type) { unsigned char *p; uint16_t u16; time_t t; uint32_t u32; - p = duid; + p = d; u16 = htons(type); memcpy(p, &u16, 2); p += 2; @@ -77,17 +80,17 @@ make_duid(unsigned char *duid, const struct interface *ifp, uint16_t type) /* Finally, add the MAC address of the interface */ memcpy(p, ifp->hwaddr, ifp->hwlen); p += ifp->hwlen; - return p - duid; + return p - d; } -size_t -get_duid(unsigned char *duid, const struct interface *iface) +static size_t +duid_get(unsigned char *d, const struct interface *ifp) { FILE *f; int x = 0; size_t len = 0; char *line; - const struct interface *ifp; + const struct interface *ifp2; /* 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 */ @@ -95,7 +98,7 @@ get_duid(unsigned char *duid, const struct interface *iface) while ((line = get_line(f))) { len = hwaddr_aton(NULL, line); if (len && len <= DUID_LEN) { - hwaddr_aton(duid, line); + hwaddr_aton(d, line); break; } len = 0; @@ -109,37 +112,51 @@ get_duid(unsigned char *duid, const struct interface *iface) } /* No file? OK, lets make one based on our interface */ - if (iface->family == ARPHRD_NETROM) { + if (ifp->family == ARPHRD_NETROM) { syslog(LOG_WARNING, "%s: is a NET/ROM psuedo interface", - iface->name); - TAILQ_FOREACH(ifp, ifaces, next) { - if (ifp->family != ARPHRD_NETROM) + ifp->name); + TAILQ_FOREACH(ifp2, ifaces, next) { + if (ifp2->family != ARPHRD_NETROM) break; } - if (ifp) { - iface = ifp; + if (ifp2) { + ifp = ifp2; syslog(LOG_WARNING, "picked interface %s to generate a DUID", - iface->name); + ifp->name); } else { syslog(LOG_WARNING, "no interfaces have a fixed hardware address"); - return make_duid(duid, iface, DUID_LL); + return duid_make(d, ifp, DUID_LL); } } if (!(f = fopen(DUID, "w"))) { syslog(LOG_ERR, "error writing DUID: %s: %m", DUID); - return make_duid(duid, iface, DUID_LL); + return duid_make(d, ifp, DUID_LL); } - len = make_duid(duid, iface, DUID_LLT); - x = fprintf(f, "%s\n", hwaddr_ntoa(duid, len)); + len = duid_make(d, ifp, DUID_LLT); + x = fprintf(f, "%s\n", hwaddr_ntoa(d, len)); fclose(f); /* Failed to write the duid? scrub it, we cannot use it */ if (x < 1) { syslog(LOG_ERR, "error writing DUID: %s: %m", DUID); unlink(DUID); - return make_duid(duid, iface, DUID_LL); + return duid_make(d, ifp, DUID_LL); } return len; } + +size_t duid_init(const struct interface *ifp) +{ + + if (duid == NULL) { + duid = malloc(DUID_LEN); + if (duid == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + return 0; + } + duid_len = duid_get(duid, ifp); + } + return duid_len; +} diff --git a/duid.h b/duid.h index 4693102b..b3ab00ee 100644 --- a/duid.h +++ b/duid.h @@ -1,6 +1,6 @@ /* * dhcpcd - DHCP client daemon - * Copyright (c) 2006-2008 Roy Marples + * Copyright (c) 2006-2013 Roy Marples * All rights reserved * Redistribution and use in source and binary forms, with or without @@ -30,6 +30,9 @@ #include "net.h" -size_t get_duid(unsigned char *duid, const struct interface *iface); +extern unsigned char *duid; +extern size_t duid_len; + +size_t duid_init(const struct interface *); #endif diff --git a/if-options.c b/if-options.c index f0a09e33..effc6e54 100644 --- a/if-options.c +++ b/if-options.c @@ -72,6 +72,7 @@ unsigned long long options = 0; #define O_NODEV O_BASE + 15 #define O_NOIPV4 O_BASE + 16 #define O_NOIPV6 O_BASE + 17 +#define O_IAID O_BASE + 18 char *dev_load; @@ -134,6 +135,7 @@ const struct option cf_options[] = { {"noipv4", no_argument, NULL, O_NOIPV4}, {"noipv6", no_argument, NULL, O_NOIPV6}, {"noalias", no_argument, NULL, O_NOALIAS}, + {"iaid", no_argument, NULL, O_IAID}, {"ia_na", no_argument, NULL, O_IA_NA}, {"ia_ta", no_argument, NULL, O_IA_TA}, {"ia_pd", no_argument, NULL, O_IA_PD}, @@ -334,6 +336,35 @@ parse_string_hwaddr(char *sbuf, ssize_t slen, const char *str, int clid) return l; } +static int +parse_iaid(uint8_t *iaid, const char *arg, size_t len) +{ + unsigned long l; + size_t s; + uint32_t u32; + char *np; + + errno = 0; + l = strtoul(arg, &np, 0); + if (l <= (unsigned long)UINT32_MAX && errno == 0 && *np == '\0') { + u32 = htonl(l); + memcpy(iaid, &u32, sizeof(u32)); + return 0; + } + + if ((s = parse_string((char *)iaid, len, arg)) < 1) { + syslog(LOG_ERR, "%s: invalid IAID", arg); + return -1; + } + if (s < 4) + iaid[3] = '\0'; + if (s < 3) + iaid[2] = '\0'; + if (s < 2) + iaid[1] = '\0'; + return 0; +} + static char ** splitv(int *argc, char **argv, const char *arg) { @@ -449,11 +480,9 @@ parse_option(struct if_options *ifo, int opt, const char *arg) const struct dhcp_opt *d; uint8_t *request, *require, *no; #ifdef INET6 - long l; - uint32_t u32; size_t sl; - struct if_iaid *iaid; - uint8_t _iaid[4]; + struct if_ia *ia; + uint8_t iaid[4]; struct if_sla *sla, *slap; #endif @@ -520,7 +549,7 @@ parse_option(struct if_options *ifo, int opt, const char *arg) return -1; } errno = 0; - ifo->leasetime = (uint32_t)strtol(arg, NULL, 0); + ifo->leasetime = (uint32_t)strtoul(arg, NULL, 0); if (errno == EINVAL || errno == ERANGE) { syslog(LOG_ERR, "`%s' out of range", arg); return -1; @@ -954,6 +983,10 @@ parse_option(struct if_options *ifo, int opt, const char *arg) } break; #endif + case O_IAID: + if (parse_iaid(ifo->iaid, arg, sizeof(ifo->iaid)) == -1) + return -1; + ifo->options |= DHCPCD_IAID; case O_IPV6RS: ifo->options |= DHCPCD_IPV6RS; break; @@ -994,52 +1027,34 @@ parse_option(struct if_options *ifo, int opt, const char *arg) fp = strchr(arg, ' '); if (fp) *fp++ = '\0'; - errno = 0; - l = strtol(arg, &np, 0); - if (l >= 0 && l <= (long)UINT32_MAX && - errno == 0 && *np == '\0') - { - u32 = htonl(l); - memcpy(&_iaid, &u32, sizeof(_iaid)); - goto got_iaid; - } - if ((s = parse_string((char *)_iaid, sizeof(_iaid), arg)) < 1) { - syslog(LOG_ERR, "%s: invalid IAID", arg); + if (parse_iaid(iaid, arg, sizeof(iaid)) == -1) return -1; - } - if (s < 4) - _iaid[3] = '\0'; - if (s < 3) - _iaid[2] = '\0'; - if (s < 2) - _iaid[1] = '\0'; -got_iaid: - iaid = NULL; - for (sl = 0; sl < ifo->iaid_len; sl++) { - if (ifo->iaid[sl].iaid[0] == _iaid[0] && - ifo->iaid[sl].iaid[1] == _iaid[1] && - ifo->iaid[sl].iaid[2] == _iaid[2] && - ifo->iaid[sl].iaid[3] == _iaid[3]) + ia = NULL; + for (sl = 0; sl < ifo->ia_len; sl++) { + if (ifo->ia[sl].iaid[0] == iaid[0] && + ifo->ia[sl].iaid[1] == iaid[1] && + ifo->ia[sl].iaid[2] == iaid[2] && + ifo->ia[sl].iaid[3] == iaid[3]) { - iaid = &ifo->iaid[sl]; + ia = &ifo->ia[sl]; break; } } - if (iaid == NULL) { - iaid = realloc(ifo->iaid, - sizeof(*ifo->iaid) * (ifo->iaid_len + 1)); - if (iaid == NULL) { + if (ia == NULL) { + ia = realloc(ifo->ia, + sizeof(*ifo->ia) * (ifo->ia_len + 1)); + if (ia == NULL) { syslog(LOG_ERR, "%s: %m", __func__); return -1; } - ifo->iaid = iaid; - iaid = &ifo->iaid[ifo->iaid_len++]; - iaid->iaid[0] = _iaid[0]; - iaid->iaid[1] = _iaid[1]; - iaid->iaid[2] = _iaid[2]; - iaid->iaid[3] = _iaid[3]; - iaid->sla = NULL; - iaid->sla_len = 0; + ifo->ia = ia; + ia = &ifo->ia[ifo->ia_len++]; + ia->iaid[0] = iaid[0]; + ia->iaid[1] = iaid[1]; + ia->iaid[2] = iaid[2]; + ia->iaid[3] = iaid[3]; + ia->sla = NULL; + ia->sla_len = 0; } if (ifo->ia_type != D6_OPTION_IA_PD) break; @@ -1047,14 +1062,14 @@ got_iaid: fp = strchr(p, ' '); if (fp) *fp++ = '\0'; - sla = realloc(iaid->sla, - sizeof(*iaid->sla) * (iaid->sla_len + 1)); + sla = realloc(ia->sla, + sizeof(*ia->sla) * (ia->sla_len + 1)); if (sla == NULL) { syslog(LOG_ERR, "%s: %m", __func__); return -1; } - iaid->sla = sla; - sla = &iaid->sla[iaid->sla_len++]; + ia->sla = sla; + sla = &ia->sla[ia->sla_len++]; np = strchr(p, '/'); if (np) *np++ = '\0'; @@ -1090,8 +1105,8 @@ got_iaid: sla->sla_set = 0; /* Sanity - check there are no more * unspecified SLA's */ - for (sl = 0; sl < iaid->sla_len - 1; sl++) { - slap = &iaid->sla[sl]; + for (sl = 0; sl < ia->sla_len - 1; sl++) { + slap = &ia->sla[sl]; if (slap->sla_set == 0 && strcmp(slap->ifname, sla->ifname) == 0) @@ -1101,14 +1116,14 @@ got_iaid: "same interface twice with " "an automatic SLA", sla->ifname); - iaid->sla_len--; + ia->sla_len--; break; } } } } - break; #endif + break; case O_HOSTNAME_SHORT: ifo->options |= DHCPCD_HOSTNAME | DHCPCD_HOSTNAME_SHORT; break; @@ -1166,39 +1181,6 @@ finish_config(struct if_options *ifo) } } -#ifdef INET6 -static void -finish_config6(struct if_options *ifo, const char *ifname) -{ - - if (!(ifo->options & DHCPCD_IPV6)) - ifo->options &= ~DHCPCD_IPV6RS; - - if (ifname && ifo->iaid_len == 0 && ifo->options & DHCPCD_IPV6) { - ifo->iaid = malloc(sizeof(*ifo->iaid)); - if (ifo->iaid == NULL) - syslog(LOG_ERR, "%s: %m", __func__); - else { - if (ifo->ia_type == 0) - ifo->ia_type = D6_OPTION_IA_NA; - ifo->iaid_len = strlen(ifname); - if (ifo->iaid_len <= sizeof(ifo->iaid->iaid)) { - strncpy((char *)ifo->iaid->iaid, ifname, - sizeof(ifo->iaid->iaid)); - memset(ifo->iaid->iaid + ifo->iaid_len, 0, - sizeof(ifo->iaid->iaid) -ifo->iaid_len); - } else { - uint32_t idx = if_nametoindex(ifname); - memcpy(ifo->iaid->iaid, &idx, sizeof(idx)); - } - ifo->iaid_len = 1; - ifo->iaid->sla = NULL; - ifo->iaid->sla_len = 0; - } - } -} -#endif - struct if_options * read_config(const char *file, const char *ifname, const char *ssid, const char *profile) @@ -1290,9 +1272,6 @@ read_config(const char *file, } finish_config(ifo); -#ifdef INET6 - finish_config6(ifo, ifname); -#endif return ifo; } @@ -1314,9 +1293,6 @@ add_options(struct if_options *ifo, int argc, char **argv) } finish_config(ifo); -#ifdef INET6 - finish_config6(ifo, NULL); -#endif return r; } @@ -1343,10 +1319,11 @@ free_options(struct if_options *ifo) free(ifo->blacklist); free(ifo->fallback); #ifdef INET6 - for (i = 0; i < ifo->iaid_len; i++) - free(ifo->iaid[i].sla); - free(ifo->iaid); + for (i = 0; i < ifo->ia_len; i++) + free(ifo->ia[i].sla); #endif + free(ifo->ia); + free(ifo); } } diff --git a/if-options.h b/if-options.h index 80bb5902..e3189ad4 100644 --- a/if-options.h +++ b/if-options.h @@ -97,6 +97,7 @@ #define DHCPCD_WAITIP4 (1ULL << 45) #define DHCPCD_WAITIP6 (1ULL << 46) #define DHCPCD_DEV (1ULL << 47) +#define DHCPCD_IAID (1ULL << 48) extern const struct option cf_options[]; @@ -107,13 +108,16 @@ struct if_sla { int8_t sla_set; }; -struct if_iaid { +struct if_ia { uint8_t iaid[4]; +#ifdef INET6 size_t sla_len; struct if_sla *sla; +#endif }; struct if_options { + uint8_t iaid[4]; int metric; uint8_t requestmask[256 / 8]; uint8_t requiremask[256 / 8]; @@ -150,10 +154,10 @@ struct if_options { in_addr_t *arping; char *fallback; -#ifdef INET6 uint16_t ia_type; - size_t iaid_len; - struct if_iaid *iaid; + struct if_ia *ia; + size_t ia_len; +#ifdef INET6 int dadtransmits; #endif };