Skip to content

Commit

Permalink
config: rewrite ifid handling
Browse files Browse the repository at this point in the history
* remove ifid-random;
* add ifid eui-64; mode
* make default mode fall back to ifid random;
* use arc4random() to avoid lack of randomness
* adjust the manual page accordingly
* do not pretent u_int64_t actually gives us the
  highest bit as strtoll() is used in the lexer
* wrap current and random sets into a function
* shorten the current and random internals

This doesn't break backwards compatibility except
for the ifid-random; which we never used.  We are
removing it after a very brief time in the repo
to condense the ifid feature set and making its
utility automatic to support broader use cases
out of the box.
  • Loading branch information
fichtner committed Jun 6, 2024
1 parent 047d904 commit f5422a8
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 39 deletions.
10 changes: 5 additions & 5 deletions cfparse.y
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ void cf_init(void);
%}

%token INTERFACE IFNAME
%token PREFIX_INTERFACE SLA_ID SLA_LEN IFID IFID_RAND RANDOM DUID_ID
%token PREFIX_INTERFACE SLA_ID SLA_LEN IFID EUI64 RANDOM DUID_ID
%token ID_ASSOC IA_PD IAID IA_NA
%token ADDRESS
%token REQUEST SEND ALLOW PREFERENCE
Expand All @@ -139,7 +139,7 @@ void cf_init(void);

%union {
long long num;
char* str;
char *str;
struct cf_list *list;
struct dhcp6_prefix *prefix;
struct dhcp6_range *range;
Expand Down Expand Up @@ -1069,7 +1069,7 @@ ifparam:
struct cf_list *l;

MAKE_CFLIST(l, IFPARAM_IFID, NULL, NULL);
l->num = (u_int64_t)$2;
l->num = $2;
$$ = l;
}
| IFID RANDOM EOS
Expand All @@ -1079,11 +1079,11 @@ ifparam:
MAKE_CFLIST(l, IFPARAM_IFID_RAND, NULL, NULL);
$$ = l;
}
| IFID_RAND EOS
| IFID EUI64 EOS
{
struct cf_list *l;

MAKE_CFLIST(l, IFPARAM_IFID_RAND, NULL, NULL);
MAKE_CFLIST(l, IFPARAM_IFID_EUI64, NULL, NULL);
$$ = l;
}
;
Expand Down
2 changes: 1 addition & 1 deletion cftoken.l
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ ecl \}
<S_CNF>sla-id { DECHO; return (SLA_ID); }
<S_CNF>sla-len { DECHO; return (SLA_LEN); }
<S_CNF>ifid { DECHO; return (IFID); }
<S_CNF>ifid-random { DECHO; return (IFID_RAND); }
<S_CNF>random { DECHO; return (RANDOM); }
<S_CNF>eui-64 { DECHO; return (EUI64); }
/* duration */
<S_CNF>infinity { DECHO; return (INFINITY); }
Expand Down
66 changes: 50 additions & 16 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ static int configure_duid(char *, struct duid *);
static int configure_addr(struct cf_list *, struct dhcp6_list *, const char *);
static int configure_domain(struct cf_list *, struct dhcp6_list *,
const char *);
static int get_default_ifid(struct prefix_ifconf *);
static int set_default_ifid(struct prefix_ifconf *);
static int set_current_ifid(struct prefix_ifconf *, long long);
static int set_random_ifid(struct prefix_ifconf *);
static void clear_poolconf(struct pool_conf *);
static struct pool_conf *create_pool(char *, struct dhcp6_range *);
struct host_conf *find_dynamic_hostconf(struct duid *);
Expand Down Expand Up @@ -531,7 +533,7 @@ add_pd_pif(iapdc, cfl0, if_count)
{
struct cf_list *cfl;
struct prefix_ifconf *pif;
int i, use_default_ifid = 1;
int ifid_done = 0;

/* duplication check */
for (pif = TAILQ_FIRST(&iapdc->iapd_pif_list); pif;
Expand Down Expand Up @@ -581,17 +583,22 @@ add_pd_pif(iapdc, cfl0, if_count)
goto bad;
}
break;
case IFPARAM_IFID_RAND:
for (i = 0; i < pif->ifid_len ; i++) {
cfl->num = cfl->num * 2 + rand() % 2;
case IFPARAM_IFID_EUI64:
if (set_default_ifid(pif)) {
d_printf(LOG_NOTICE, FNAME,
"failed to get default IF ID for %s",
pif->ifname);
goto bad;
}
/* FALLTHROUGH */
ifid_done = 1;
break;
case IFPARAM_IFID_RAND:
set_random_ifid(pif);
ifid_done = 1;
break;
case IFPARAM_IFID:
for (i = sizeof(pif->ifid) -1; i >= 0; i--) {
pif->ifid[i] = (cfl->num >> 8 *
(sizeof(pif->ifid) - 1 - i)) & 0xff;
}
use_default_ifid = 0;
set_current_ifid(pif, cfl->num);
ifid_done = 1;
break;
default:
d_printf(LOG_ERR, FNAME, "%s:%d internal error: "
Expand All @@ -601,11 +608,11 @@ add_pd_pif(iapdc, cfl0, if_count)
}
}

/* XXX consider a fallback to ifid-random here */
if (use_default_ifid && get_default_ifid(pif)) {
if (!ifid_done && set_default_ifid(pif)) {
d_printf(LOG_NOTICE, FNAME,
"failed to get default IF ID for %s", pif->ifname);
goto bad;
"failed to get default IF ID for %s, using random ID",
pif->ifname);
set_random_ifid(pif);
}

TAILQ_INSERT_TAIL(&iapdc->iapd_pif_list, pif, link);
Expand Down Expand Up @@ -1290,7 +1297,7 @@ configure_duid(str, duid)

/* we currently only construct EUI-64 based interface ID */
static int
get_default_ifid(pif)
set_default_ifid(pif)
struct prefix_ifconf *pif;
{
struct ifaddrs *ifa, *ifap;
Expand Down Expand Up @@ -1378,6 +1385,33 @@ get_default_ifid(pif)
return (-1);
}

static int
set_current_ifid(struct prefix_ifconf *pif, long long value)
{
int i;

/* similar to EUI-64 and only passed a 64 bit SIGNED integer anyway */
for (i = 15; i >= 8; i--) {
pif->ifid[i] = value & 0xff;
value >>= 8;
}

return (0);
}

static int
set_random_ifid(struct prefix_ifconf *pif)
{
int i;

/* similar to EUI-64 and only passed a 64 bit SIGNED integer anyway */
for (i = 15; i >= 8; i--) {
pif->ifid[i] = arc4random() & 0xff;
}

return (0);
}

void
configure_cleanup()
{
Expand Down
4 changes: 2 additions & 2 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ enum { DECL_SEND, DECL_ALLOW, DECL_INFO_ONLY, DECL_REQUEST, DECL_DUID,
DECL_PREFIX, DECL_PREFERENCE, DECL_SCRIPT, DECL_DELAYEDKEY,
DECL_ADDRESS,
DECL_RANGE, DECL_ADDRESSPOOL,
IFPARAM_SLA_ID, IFPARAM_SLA_LEN, IFPARAM_IFID, IFPARAM_IFID_RAND,
IFPARAM_SLA_ID, IFPARAM_SLA_LEN,
IFPARAM_IFID, IFPARAM_IFID_RAND, IFPARAM_IFID_EUI64,
DHCPOPT_RAPID_COMMIT, DHCPOPT_AUTHINFO,
DHCPOPT_DNS, DHCPOPT_DNSNAME,
DHCPOPT_IA_PD, DHCPOPT_IA_NA, DHCPOPT_NTP,
Expand All @@ -287,7 +288,6 @@ enum { DECL_SEND, DECL_ALLOW, DECL_INFO_ONLY, DECL_REQUEST, DECL_DUID,
DHCPOPT_SIP, DHCPOPT_SIPNAME,
AUTHPARAM_PROTO, AUTHPARAM_ALG, AUTHPARAM_RDM, AUTHPARAM_KEY,
KEYPARAM_REALM, KEYPARAM_KEYID, KEYPARAM_SECRET, KEYPARAM_EXPIRE,
/* XXX */
DHCPOPT_RAW };

typedef enum {DHCP6_MODE_SERVER, DHCP6_MODE_CLIENT, DHCP6_MODE_RELAY }
Expand Down
27 changes: 12 additions & 15 deletions dhcp6c.conf.5
Original file line number Diff line number Diff line change
Expand Up @@ -436,26 +436,23 @@ the default value 16 will be used.
.It Ic ifid Ar ID ;
This statement specifies the interface identifier value.
.Ar ID
must be a decimal integer.
shall be a decimal integer.
It will be combined with the delegated prefix and the
.Ic sla-id
to form a complete interface address.
If the special value
.Ar random
is given, the behaviour is the same as providing
.Ic ifid-random .
When this option is omitted, the default is to use the EUI-64 address of the
.Ar interface .
.It Ic ifid-random ;
This statement instructs the client to generate a pseudo random
interface identifier value.
This will override the
.Ic ifid
statement, if present.
The resulting value will be combined with the delegated prefix and the
.Ic sla-id
to form a complete interface address.
This option is provided for syntax compatibility.
is given, it instructs the client to generate a pseudo random value
during configuration parsing.
If the special value
.Ar eui-64
is given, only the EUI-64 address generation will be attempted which
reflects the historic client behaviour.
When this option is omitted,
.Ar eui-64
will be used, and if it fails the client will fall back to
.Ar random
to allow operation for interfaces without a hardware address.
.El
.El
.\"
Expand Down

0 comments on commit f5422a8

Please sign in to comment.