Mercurial > hg > dhcpcd
changeset 2542:28b1ed6d98ad draft
Allow the request of a DHCPv6 address or prefix, a prefix length must be specified.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Sat, 21 Jun 2014 11:42:36 +0000 |
| parents | 98b581c3152b |
| children | 8255dad7230c |
| files | dhcp6.c dhcpcd.conf.5.in if-options.c if-options.h ipv6.h |
| diffstat | 5 files changed, 110 insertions(+), 49 deletions(-) [+] |
line wrap: on
line diff
--- a/dhcp6.c Fri Jun 20 22:32:44 2014 +0000 +++ b/dhcp6.c Sat Jun 21 11:42:36 2014 +0000 @@ -405,12 +405,15 @@ case DH6S_REBIND: /* FALLTHROUGH */ case DH6S_CONFIRM: + /* FALLTHROUGH */ + case DH6S_DISCOVER: if (m == NULL) { m = state->new; ml = state->new_len; } TAILQ_FOREACH(ap, &state->addrs, next) { - if (ap->prefix_vltime == 0) + if (ap->prefix_vltime == 0 && + !(ap->flags & IPV6_AF_REQUEST)) continue; if (ifo->ia_type == D6_OPTION_IA_PD) len += sizeof(*o) + sizeof(u8) + @@ -421,8 +424,7 @@ sizeof(u32) + sizeof(u32); } /* FALLTHROUGH */ - case DH6S_INIT: /* FALLTHROUGH */ - case DH6S_DISCOVER: + case DH6S_INIT: len += ifo->ia_len * (sizeof(*o) + (sizeof(u32) * 3)); IA = 1; break; @@ -536,7 +538,8 @@ p += sizeof(u32); memset(p, 0, sizeof(u32) + sizeof(u32)); TAILQ_FOREACH(ap, &state->addrs, next) { - if (ap->prefix_vltime == 0) + if (ap->prefix_vltime == 0 && + !(ap->flags & IPV6_AF_REQUEST)) continue; if (memcmp(ifo->ia[l].iaid, ap->iaid, sizeof(u32))) continue; @@ -949,10 +952,51 @@ } static void +dhcp6_dadcallback(void *arg) +{ + struct ipv6_addr *ap = arg; + struct interface *ifp; + struct dhcp6_state *state; + int wascompleted; + + wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED); + ap->flags |= IPV6_AF_DADCOMPLETED; + if (ap->flags & IPV6_AF_DUPLICATED) + /* XXX FIXME + * We should decline the address */ + syslog(LOG_WARNING, "%s: DAD detected %s", + ap->iface->name, ap->saddr); + + if (!wascompleted) { + ifp = ap->iface; + state = D6_STATE(ifp); + if (state->state == DH6S_BOUND || + state->state == DH6S_DELEGATED) + { + TAILQ_FOREACH(ap, &state->addrs, next) { + if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) { + wascompleted = 1; + break; + } + } + if (!wascompleted) { + syslog(LOG_DEBUG, "%s: DHCPv6 DAD completed", + ifp->name); + script_runreason(ifp, state->reason); + dhcpcd_daemonise(ifp->ctx); + } + } + } +} + +static void dhcp6_startdiscover(void *arg) { struct interface *ifp; struct dhcp6_state *state; + size_t i; + struct if_ia *ia; + struct ipv6_addr *a; ifp = arg; dhcp6_delete_delegates(ifp); @@ -974,6 +1018,30 @@ dhcp6_freedrop_addrs(ifp, 0, NULL); unlink(state->leasefile); + /* Add any requested prefixes / addresses */ + for (i = 0; i < ifp->options->ia_len; i++) { + ia = &ifp->options->ia[i]; + if (ia->prefix_len) { + a = calloc(1, sizeof(*a)); + if (a == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + return NULL; + } + a->flags = IPV6_AF_REQUEST; + a->iface = ifp; + a->dadcallback = dhcp6_dadcallback; + memcpy(&a->iaid, &ia->iaid, sizeof(a->iaid)); + //a->prefix_pltime = 0; + //a->prefix_vltime = 0; + if (ifp->options->ia_type == D6_OPTION_IA_PD) + memcpy(&a->prefix, &ia->addr, sizeof(a->addr)); + else + memcpy(&a->addr, &ia->addr, sizeof(a->addr)); + a->prefix_len = ia->prefix_len; + TAILQ_INSERT_TAIL(&state->addrs, a, next); + } + } + if (dhcp6_makemessage(ifp) == -1) syslog(LOG_ERR, "%s: dhcp6_makemessage: %m", ifp->name); else @@ -1264,44 +1332,6 @@ return 0; } -static void -dhcp6_dadcallback(void *arg) -{ - struct ipv6_addr *ap = arg; - struct interface *ifp; - struct dhcp6_state *state; - int wascompleted; - - wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED); - ap->flags |= IPV6_AF_DADCOMPLETED; - if (ap->flags & IPV6_AF_DUPLICATED) - /* XXX FIXME - * We should decline the address */ - syslog(LOG_WARNING, "%s: DAD detected %s", - ap->iface->name, ap->saddr); - - if (!wascompleted) { - ifp = ap->iface; - state = D6_STATE(ifp); - if (state->state == DH6S_BOUND || - state->state == DH6S_DELEGATED) - { - TAILQ_FOREACH(ap, &state->addrs, next) { - if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) { - wascompleted = 1; - break; - } - } - if (!wascompleted) { - syslog(LOG_DEBUG, "%s: DHCPv6 DAD completed", - ifp->name); - script_runreason(ifp, state->reason); - dhcpcd_daemonise(ifp->ctx); - } - } - } -} - static int dhcp6_findna(struct interface *ifp, const uint8_t *iaid, const uint8_t *d, size_t l) @@ -1370,7 +1400,7 @@ "%s/%d", ia, a->prefix_len); TAILQ_INSERT_TAIL(&state->addrs, a, next); } else - a->flags &= ~IPV6_AF_STALE; + a->flags &= ~(IPV6_AF_STALE | IPV6_AF_REQUEST); memcpy(&u32, p, sizeof(u32)); a->prefix_pltime = ntohl(u32); p += sizeof(u32); @@ -1455,7 +1485,7 @@ "%s/%d", ia, a->prefix_len); TAILQ_INSERT_TAIL(&state->addrs, a, next); } else { - a->flags &= ~IPV6_AF_STALE; + a->flags &= ~(IPV6_AF_STALE | IPV6_AF_REQUEST); if (a->prefix_vltime != vltime) a->flags |= IPV6_AF_NEW; }
--- a/dhcpcd.conf.5.in Fri Jun 20 22:32:44 2014 +0000 +++ b/dhcpcd.conf.5.in Sat Jun 21 11:42:36 2014 +0000 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 6, 2014 +.Dd June 20, 2014 .Dt DHCPCD.CONF 5 .Os .Sh NAME @@ -214,7 +214,7 @@ Also, see the .Ic env option above to control how the hostname is set on the host. -.It Ic ia_na Op Ar iaid +.It Ic ia_na Op Ar iaid Op / address Op / prefix_len Request a DHCPv6 Normal Address for .Ar iaid . .Ar iaid @@ -230,7 +230,7 @@ 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 +.It Ic ia_pd Op Ar iaid Oo / Ar prefix / Ar prefix_len Oc Op Ar interface Op / Ar sla_id Op / Ar prefix_len Request a DHCPv6 Delegated Prefix for .Ar iaid . This option must be used in an
--- a/if-options.c Fri Jun 20 22:32:44 2014 +0000 +++ b/if-options.c Sat Jun 21 11:42:36 2014 +0000 @@ -1236,6 +1236,9 @@ fp = strwhite(arg); if (fp) *fp++ = '\0'; + p = strchr(arg, '/'); + if (p) + *p++ = '\0'; if (parse_iaid(iaid, arg, sizeof(iaid)) == -1) return -1; ia = NULL; @@ -1262,8 +1265,33 @@ ia->iaid[1] = iaid[1]; ia->iaid[2] = iaid[2]; ia->iaid[3] = iaid[3]; + if (p == NULL) { + memset(&ia->addr, 0, sizeof(ia->addr)); + ia->prefix_len = 0; + } else { + arg = p; + p = strchr(arg, '/'); + if (p) + *p++ = '\0'; + if (inet_pton(AF_INET6, arg, &ia->addr) == -1) { + syslog(LOG_ERR, "%s: %m", arg); + memset(&ia->addr, 0, sizeof(ia->addr)); + } + if (p) { + i = atoint(p); + if (i != -1 && (i < 8 || i > 120)) { + errno = EINVAL; + i = -1; + } + if (i == -1) { + syslog(LOG_ERR, "%s: %m", p); + ia->prefix_len = 0; + } else + ia->prefix_len = (uint8_t)i; + } + } + ia->sla_len = 0; ia->sla = NULL; - ia->sla_len = 0; } if (ifo->ia_type != D6_OPTION_IA_PD) break;
--- a/if-options.h Fri Jun 20 22:32:44 2014 +0000 +++ b/if-options.h Sat Jun 21 11:42:36 2014 +0000 @@ -115,6 +115,8 @@ struct if_ia { uint8_t iaid[4]; #ifdef INET6 + struct in6_addr addr; + uint8_t prefix_len; size_t sla_len; struct if_sla *sla; #endif
--- a/ipv6.h Fri Jun 20 22:32:44 2014 +0000 +++ b/ipv6.h Sat Jun 21 11:42:36 2014 +0000 @@ -109,7 +109,8 @@ #define IPV6_AF_DADCOMPLETED 0x0040 #define IPV6_AF_DELEGATED 0x0080 #define IPV6_AF_DELEGATEDPFX 0x0100 -#define IPV6_AF_DELEGATEDZERO 0X0200 +#define IPV6_AF_DELEGATEDZERO 0x0200 +#define IPV6_AF_REQUEST 0x0400 struct rt6 { TAILQ_ENTRY(rt6) next;
