317
static void set_dnssl_timeout (NMIP6Device *device);
320
dnssl_expired (gpointer user_data)
322
NMIP6Device *device = user_data;
323
CallbackInfo info = { device, IP6_DHCP_OPT_NONE };
325
nm_log_dbg (LOGD_IP6, "(%s): IPv6 DNSSL information expired", device->iface);
327
set_dnssl_timeout (device);
328
emit_config_changed (&info);
333
set_dnssl_timeout (NMIP6Device *device)
335
time_t expires = 0, now = time (NULL);
339
if (device->dnssl_timeout_id) {
340
g_source_remove (device->dnssl_timeout_id);
341
device->dnssl_timeout_id = 0;
344
/* Find the soonest expiration time. */
345
for (i = 0; i < device->dnssl_domains->len; i++) {
346
dnssl = &g_array_index (device->dnssl_domains, NMIP6DNSSL, i);
347
if (dnssl->expires == 0)
350
/* If the entry has already expired, remove it; the "+ 1" is
351
* because g_timeout_add_seconds() might fudge the timing a
354
if (dnssl->expires <= now + 1) {
355
nm_log_dbg (LOGD_IP6, "(%s): removing expired RA-provided domain %s",
356
device->iface, dnssl->domain);
357
g_array_remove_index (device->dnssl_domains, i--);
361
if (!expires || dnssl->expires < expires)
362
expires = dnssl->expires;
366
device->dnssl_timeout_id = g_timeout_add_seconds (expires - now,
303
372
static CallbackInfo *
304
373
callback_info_new (NMIP6Device *device, guint dhcp_opts, gboolean success)
571
640
#define ND_OPT_RDNSS 25
641
#define ND_OPT_DNSSL 31
572
643
struct nd_opt_rdnss {
573
644
uint8_t nd_opt_rdnss_type;
574
645
uint8_t nd_opt_rdnss_len;
575
646
uint16_t nd_opt_rdnss_reserved1;
576
647
uint32_t nd_opt_rdnss_lifetime;
577
648
/* followed by one or more IPv6 addresses */
649
} __attribute__ ((packed));
651
struct nd_opt_dnssl {
652
uint8_t nd_opt_dnssl_type;
653
uint8_t nd_opt_dnssl_len;
654
uint16_t nd_opt_dnssl_reserved1;
655
uint32_t nd_opt_dnssl_lifetime;
656
/* followed by one or more suffixes */
657
} __attribute__ ((packed));
660
process_nduseropt_rdnss (NMIP6Device *device, struct nd_opt_hdr *opt)
663
struct nd_opt_rdnss *rdnss_opt;
664
time_t now = time (NULL);
665
struct in6_addr *addr;
667
NMIP6RDNSS server, *cur_server;
668
gboolean changed = FALSE;
671
opt_len = opt->nd_opt_len;
673
if (opt_len < 3 || (opt_len & 1) == 0)
676
rdnss_opt = (struct nd_opt_rdnss *) opt;
678
new_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS));
680
/* Pad the DNS server expiry somewhat to give a bit of slack in cases
681
* where one RA gets lost or something (which can happen on unreliable
682
* links like WiFi where certain types of frames are not retransmitted).
683
* Note that 0 has special meaning and is therefore not adjusted.
685
server.expires = ntohl (rdnss_opt->nd_opt_rdnss_lifetime);
686
if (server.expires > 0)
687
server.expires += now + 10;
689
for (addr = (struct in6_addr *) (rdnss_opt + 1); opt_len >= 2; addr++, opt_len -= 2) {
690
char buf[INET6_ADDRSTRLEN + 1];
692
if (!inet_ntop (AF_INET6, addr, buf, sizeof (buf)))
693
strcpy(buf, "[invalid]");
695
for (i = 0; i < device->rdnss_servers->len; i++) {
696
cur_server = &(g_array_index (device->rdnss_servers, NMIP6RDNSS, i));
698
if (!IN6_ARE_ADDR_EQUAL (addr, &cur_server->addr))
701
cur_server->expires = server.expires;
703
if (server.expires > 0) {
704
nm_log_dbg (LOGD_IP6, "(%s): refreshing RA-provided nameserver %s (expires in %d seconds)",
706
server.expires - now);
710
nm_log_dbg (LOGD_IP6, "(%s): removing RA-provided nameserver %s on router request",
713
g_array_remove_index (device->rdnss_servers, i);
718
if (server.expires == 0)
720
if (i < device->rdnss_servers->len)
723
nm_log_dbg (LOGD_IP6, "(%s): found RA-provided nameserver %s (expires in %d seconds)",
724
device->iface, buf, server.expires - now);
727
g_array_append_val (new_servers, server);
730
/* New servers must be added in the order they are listed in the
731
* RA option and before any existing servers.
733
* Note: This is the place to remove servers if we want to cap the
734
* number of resolvers. The RFC states that the one to expire
735
* first of the existing servers should be removed.
737
if (new_servers->len) {
738
g_array_prepend_vals (device->rdnss_servers,
739
new_servers->data, new_servers->len);
743
g_array_free (new_servers, TRUE);
745
/* Timeouts may have changed even if IPs didn't */
746
set_rdnss_timeout (device);
752
parse_dnssl_domain (const unsigned char *buffer, size_t maxlen)
754
static char domain[256];
767
if (label_len > maxlen)
769
if ((sizeof (domain) - strlen (domain)) < (label_len + 2))
772
if (domain[0] != '\0')
773
strcat (domain, ".");
774
strncat (domain, (const char *)buffer, label_len);
783
process_nduseropt_dnssl (NMIP6Device *device, struct nd_opt_hdr *opt)
786
struct nd_opt_dnssl *dnssl_opt;
787
unsigned char *opt_ptr;
788
time_t now = time (NULL);
790
NMIP6DNSSL domain, *cur_domain;
794
opt_len = opt->nd_opt_len;
799
dnssl_opt = (struct nd_opt_dnssl *) opt;
801
opt_ptr = (unsigned char *)(dnssl_opt + 1);
802
opt_len = (opt_len - 1) * 8; /* prefer bytes for later handling */
804
new_domains = g_array_new (FALSE, FALSE, sizeof (NMIP6DNSSL));
808
/* Pad the DNS server expiry somewhat to give a bit of slack in cases
809
* where one RA gets lost or something (which can happen on unreliable
810
* links like wifi where certain types of frames are not retransmitted).
811
* Note that 0 has special meaning and is therefore not adjusted.
813
domain.expires = ntohl (dnssl_opt->nd_opt_dnssl_lifetime);
814
if (domain.expires > 0)
815
domain.expires += now + 10;
818
const char *domain_str;
820
domain_str = parse_dnssl_domain (opt_ptr, opt_len);
821
if (domain_str == NULL) {
822
nm_log_dbg (LOGD_IP6, "(%s): invalid DNSSL option, parsing aborted",
827
/* The DNSSL encoding of domains happen to occupy the same size
828
* as the length of the resulting string, including terminating
830
opt_ptr += strlen (domain_str) + 1;
831
opt_len -= strlen (domain_str) + 1;
833
/* Ignore empty domains. They're probably just padding... */
834
if (domain_str[0] == '\0')
837
for (i = 0; i < device->dnssl_domains->len; i++) {
838
cur_domain = &(g_array_index (device->dnssl_domains, NMIP6DNSSL, i));
840
if (strcmp (domain_str, cur_domain->domain) != 0)
843
cur_domain->expires = domain.expires;
845
if (domain.expires > 0) {
846
nm_log_dbg (LOGD_IP6, "(%s): refreshing RA-provided domain %s (expires in %d seconds)",
847
device->iface, domain_str,
848
domain.expires - now);
852
nm_log_dbg (LOGD_IP6, "(%s): removing RA-provided domain %s on router request",
853
device->iface, domain_str);
855
g_array_remove_index (device->dnssl_domains, i);
860
if (domain.expires == 0)
862
if (i < device->dnssl_domains->len)
865
nm_log_dbg (LOGD_IP6, "(%s): found RA-provided domain %s (expires in %d seconds)",
866
device->iface, domain_str, domain.expires - now);
868
g_assert (strlen (domain_str) < sizeof (domain.domain));
869
strcpy (domain.domain, domain_str);
870
g_array_append_val (new_domains, domain);
873
/* New domains must be added in the order they are listed in the
874
* RA option and before any existing domains.
876
* Note: This is the place to remove domains if we want to cap the
877
* number of domains. The RFC states that the one to expire
878
* first of the existing domains should be removed.
880
if (new_domains->len) {
881
g_array_prepend_vals (device->dnssl_domains,
882
new_domains->data, new_domains->len);
886
g_array_free (new_domains, TRUE);
888
/* Timeouts may have changed even if domains didn't */
889
set_dnssl_timeout (device);
580
894
static NMIP6Device *
581
895
process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg)
619
926
if (nd_opt_len == 0 || opts_len < (nd_opt_len << 3))
622
if (opt->nd_opt_type != ND_OPT_RDNSS)
625
if (nd_opt_len < 3 || (nd_opt_len & 1) == 0)
628
rdnss_opt = (struct nd_opt_rdnss *) opt;
630
/* Pad the DNS server expiry somewhat to give a bit of slack in cases
631
* where one RA gets lost or something (which can happen on unreliable
632
* links like wifi where certain types of frames are not retransmitted).
634
server.expires = now + ntohl (rdnss_opt->nd_opt_rdnss_lifetime) + 10;
636
for (addr = (struct in6_addr *) (rdnss_opt + 1); nd_opt_len >= 2; addr++, nd_opt_len -= 2) {
637
char buf[INET6_ADDRSTRLEN + 1];
639
if (inet_ntop (AF_INET6, addr, buf, sizeof (buf))) {
640
nm_log_dbg (LOGD_IP6, "(%s): found RA-provided nameserver %s (expires in %d seconds)",
642
ntohl (rdnss_opt->nd_opt_rdnss_lifetime));
646
g_array_append_val (servers, server);
929
switch (opt->nd_opt_type) {
931
changed = process_nduseropt_rdnss (device, opt);
934
changed = process_nduseropt_dnssl (device, opt);
650
938
opts_len -= opt->nd_opt_len << 3;
651
939
opt = (struct nd_opt_hdr *) ((uint8_t *) opt + (opt->nd_opt_len << 3));
654
/* See if anything (other than expiration time) changed */
655
if (servers->len != device->rdnss_servers->len)
658
for (i = 0; i < servers->len; i++) {
659
sa = &(g_array_index (servers, NMIP6RDNSS, i));
660
sb = &(g_array_index (device->rdnss_servers, NMIP6RDNSS, i));
661
if (IN6_ARE_ADDR_EQUAL (&sa->addr, &sb->addr) == FALSE) {
670
nm_log_dbg (LOGD_IP6, "(%s): RA-provided nameservers changed", device->iface);
673
/* Always copy in new servers (even if unchanged) to get their updated
676
g_array_free (device->rdnss_servers, TRUE);
677
device->rdnss_servers = servers;
679
/* Timeouts may have changed even if IPs didn't */
680
set_rdnss_timeout (device);