While RFC6106 mandates that the RDNSS lifetime is capped to the default
lifetime, this behaviour is often undesirable. In particular, it prevents
accepting RDNSS records from RAs that don't also advertise a default route
(set the default lifetime to 0).
Therefore, make it possible to opt out of this behaviour and respect the
RDNSS lifetime independently of the default lifetime using the new command
line switch -L.
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
int logopt = LOG_PID;
int c;
unsigned int client_options = DHCPV6_CLIENT_FQDN | DHCPV6_ACCEPT_RECONFIGURE;
int logopt = LOG_PID;
int c;
unsigned int client_options = DHCPV6_CLIENT_FQDN | DHCPV6_ACCEPT_RECONFIGURE;
+ unsigned int ra_options = RA_RDNSS_DEFAULT_LIFETIME;
- while ((c = getopt(argc, argv, "S::N:V:P:FB:c:i:r:Ru:s:kt:m:hedp:fav")) != -1) {
+ while ((c = getopt(argc, argv, "S::N:V:P:FB:c:i:r:Ru:s:kt:m:Lhedp:fav")) != -1) {
switch (c) {
case 'S':
allow_slaac_only = (optarg) ? atoi(optarg) : -1;
switch (c) {
case 'S':
allow_slaac_only = (optarg) ? atoi(optarg) : -1;
min_update_interval = atoi(optarg);
break;
min_update_interval = atoi(optarg);
break;
+ case 'L':
+ ra_options &= ~RA_RDNSS_DEFAULT_LIFETIME;
+ break;
+
case 'e':
logopt |= LOG_PERROR;
break;
case 'e':
logopt |= LOG_PERROR;
break;
if ((urandom_fd = open("/dev/urandom", O_CLOEXEC | O_RDONLY)) < 0 ||
init_dhcpv6(ifname, client_options, sol_timeout) ||
if ((urandom_fd = open("/dev/urandom", O_CLOEXEC | O_RDONLY)) < 0 ||
init_dhcpv6(ifname, client_options, sol_timeout) ||
- ra_init(ifname, &ifid) || script_init(script, ifname)) {
+ ra_init(ifname, &ifid, ra_options) ||
+ script_init(script, ifname)) {
syslog(LOG_ERR, "failed to initialize: %s", strerror(errno));
return 3;
}
syslog(LOG_ERR, "failed to initialize: %s", strerror(errno));
return 3;
}
" -k Don't send a RELEASE when stopping\n"
" -t <seconds> Maximum timeout for DHCPv6-SOLICIT (120)\n"
" -m <seconds> Minimum time between accepting updates (30)\n"
" -k Don't send a RELEASE when stopping\n"
" -t <seconds> Maximum timeout for DHCPv6-SOLICIT (120)\n"
" -m <seconds> Minimum time between accepting updates (30)\n"
+ " -L Ignore default lifetime for RDNSS records\n"
"\nInvocation options:\n"
" -p <pidfile> Set pidfile (/var/run/odhcp6c.pid)\n"
" -d Daemonize\n"
"\nInvocation options:\n"
" -p <pidfile> Set pidfile (/var/run/odhcp6c.pid)\n"
" -d Daemonize\n"
+enum ra_config {
+ RA_RDNSS_DEFAULT_LIFETIME = 1,
+};
+
enum odhcp6c_ia_mode {
IA_MODE_NONE,
IA_MODE_TRY,
enum odhcp6c_ia_mode {
IA_MODE_NONE,
IA_MODE_TRY,
static char if_name[IF_NAMESIZE] = {0};
static volatile int rs_attempt = 0;
static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
static char if_name[IF_NAMESIZE] = {0};
static volatile int rs_attempt = 0;
static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
+static unsigned int ra_options = 0;
struct {
struct icmp6_hdr hdr;
struct {
struct icmp6_hdr hdr;
static void ra_send_rs(int signal __attribute__((unused)));
static void ra_send_rs(int signal __attribute__((unused)));
-int ra_init(const char *ifname, const struct in6_addr *ifid)
+int ra_init(const char *ifname, const struct in6_addr *ifid, unsigned int options)
+ ra_options = options;
+
const pid_t ourpid = getpid();
sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
if (sock < 0)
const pid_t ourpid = getpid();
sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
if (sock < 0)
- int states[2] = {STATE_RA_DNS, STATE_RA_SEARCH};
- for (size_t i = 0; i < 2; ++i) {
- size_t ra_dns_len;
- uint8_t *start = odhcp6c_get_state(states[i], &ra_dns_len);
- for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
- (uint8_t*)c < &start[ra_dns_len] &&
- (uint8_t*)odhcp6c_next_entry(c) <= &start[ra_dns_len];
- c = odhcp6c_next_entry(c))
- if (IN6_ARE_ADDR_EQUAL(&c->router, &from.sin6_addr) &&
- c->valid > router_valid)
- c->valid = router_valid;
+ if (ra_options & RA_RDNSS_DEFAULT_LIFETIME) {
+ int states[2] = {STATE_RA_DNS, STATE_RA_SEARCH};
+ for (size_t i = 0; i < 2; ++i) {
+ size_t ra_dns_len;
+ uint8_t *start = odhcp6c_get_state(states[i], &ra_dns_len);
+ for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
+ (uint8_t*)c < &start[ra_dns_len] &&
+ (uint8_t*)odhcp6c_next_entry(c) <= &start[ra_dns_len];
+ c = odhcp6c_next_entry(c))
+ if (IN6_ARE_ADDR_EQUAL(&c->router, &from.sin6_addr) &&
+ c->valid > router_valid)
+ c->valid = router_valid;
+ }
(void*)(opt + opt->len) <= (void*)(end); opt += opt->len)
(void*)(opt + opt->len) <= (void*)(end); opt += opt->len)
-int ra_init(const char *ifname, const struct in6_addr *ifid);
+int ra_init(const char *ifname, const struct in6_addr *ifid, unsigned int options);
bool ra_link_up(void);
bool ra_process(void);
bool ra_link_up(void);
bool ra_process(void);