char sabuf[INET6_ADDRSTRLEN];
const char *sa;
int pfxlen;
+ uint64_t vl;
/* RFC6603 Section 4.2 */
if (strcmp(ifp->name, ifs->name) == 0) {
sla, ia)) == -1)
return NULL;
+ if (ffs64(sla->suffix) > 128 - pfxlen) {
+ logger(ifp->ctx, LOG_ERR,
+ "%s: suffix %" PRIu64 " + prefix_len %d > 128",
+ ifp->name, sla->suffix, pfxlen);
+ return NULL;
+ }
a = calloc(1, sizeof(*a));
if (a == NULL) {
a->prefix = addr;
a->prefix_len = (uint8_t)pfxlen;
- /* Wang a 1 at the end as the prefix could be >64
- * making SLAAC impossible. */
- a->addr = a->prefix;
- a->addr.s6_addr[sizeof(a->addr.s6_addr) - 1] =
- (uint8_t)(a->addr.s6_addr[sizeof(a->addr.s6_addr) - 1] + 1);
+ /* Add our suffix */
+ a->addr = addr;
+ vl = be64dec(addr.s6_addr + 8);
+ vl |= sla->suffix;
+ be64enc(a->addr.s6_addr + 8, vl);
state = D6_STATE(ifp);
/* Remove any exiting address */
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 19, 2015
+.Dd January 29, 2016
.Dt DHCPCD.CONF 5
.Os
.Sh NAME
You can request more than one ia_ta by specifying a unique
.Ar iaid
for each one.
-.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
+.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 Op / Ar suffix
Request a DHCPv6 Delegated Prefix for
.Ar iaid .
This option must be used in an
.Ar interface
and
.Ar sla_id .
-Each assigned address will have a suffix of 1.
+Each assigned address will have a
+.Ar suffix ,
+defaulting to 1.
You cannot assign a prefix to the requesting interface unless the
DHCPv6 server supports
.Li RFC6603
if (strlcpy(sla->ifname, p,
sizeof(sla->ifname)) >= sizeof(sla->ifname))
{
- logger(ctx, LOG_ERR, "%s: interface name too long",
- arg);
+ logger(ctx, LOG_ERR,
+ "%s: interface name too long", arg);
goto err_sla;
}
+ sla->sla_set = 0;
+ sla->prefix_len = 0;
+ sla->suffix = 1;
p = np;
if (p) {
np = strchr(p, '/');
if (np)
*np++ = '\0';
- if (*p == '\0')
- sla->sla_set = 0;
- else {
+ if (*p != '\0') {
sla->sla = (uint32_t)strtou(p, NULL,
0, 0, UINT32_MAX, &e);
sla->sla_set = 1;
goto err_sla;
}
}
- if (np) {
+ p = np;
+ }
+ if (p) {
+ np = strchr(p, '/');
+ if (np)
+ *np++ = '\0';
+ if (*p != '\0') {
sla->prefix_len = (uint8_t)strtou(np,
- NULL, 0, 0, 120, &e);
+ NULL, 0, 0, 120, &e);
if (e) {
- logger(ctx, LOG_ERR, "%s: failed to "
+ logger(ctx, LOG_ERR,
+ "%s: failed to "
"convert prefix len",
ifname);
goto err_sla;
}
- } else
- sla->prefix_len = 0;
- } else {
- sla->sla_set = 0;
- sla->prefix_len = 0;
+ }
+ p = np;
+ }
+ if (p) {
+ np = strchr(p, '/');
+ if (np)
+ *np = '\0';
+ if (*p != '\0') {
+ sla->suffix = (uint64_t)strtou(p, NULL,
+ 0, 0, UINT64_MAX, &e);
+ if (e) {
+ logger(ctx, LOG_ERR,
+ "%s: failed to "
+ "convert suffix",
+ ifname);
+ goto err_sla;
+ }
+ }
}
/* Sanity check */
for (sl = 0; sl < ia->sla_len - 1; sl++) {
char ifname[IF_NAMESIZE];
uint32_t sla;
uint8_t prefix_len;
+ uint64_t suffix;
int8_t sla_set;
};