§3 Precedence of API URIs
"
A device may learn about Captive Portal API URIs through more than one of (or
indeed all of) the above options. Implementations can select their own
precedence order (e.g., prefer one of the IPv6 options before the DHCPv4 option,
or vice versa, et cetera).
If the URIs learned via more than one option described in Section 2 are not all
identical, this condition should be logged for the device owner or
administrator; it is a network configuration error if the learned URIs are not
all identical.
"
We log the 'network configuration error' but proceed in an attempt to be useful
(since the RFC makes no mention of disregarding the URI) and prefer DHCPv6,
since this is the DHCPv6 client.
Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcp6c/pull/127
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
odhcp6c_clear_state(STATE_S46_MAPT);
odhcp6c_clear_state(STATE_S46_MAPE);
odhcp6c_clear_state(STATE_S46_LW);
- odhcp6c_clear_state(STATE_CAPT_PORT);
+ odhcp6c_clear_state(STATE_CAPT_PORT_DHCPV6);
odhcp6c_clear_state(STATE_PASSTHRU);
odhcp6c_clear_state(STATE_CUSTOM_OPTS);
continue;
memcpy(copy, odata, olen);
copy[uri_len] = '\0';
- odhcp6c_add_state(STATE_CAPT_PORT, odata, olen);
+ odhcp6c_add_state(STATE_CAPT_PORT_DHCPV6, odata, olen);
free(copy);
}
break;
odhcp6c_clear_state(STATE_NTP_FQDN);
odhcp6c_clear_state(STATE_SIP_IP);
odhcp6c_clear_state(STATE_SIP_FQDN);
- odhcp6c_clear_state(STATE_CAPT_PORT);
+ odhcp6c_clear_state(STATE_CAPT_PORT_DHCPV6);
bound = false;
size_t oro_len = 0;
STATE_S46_MAPT,
STATE_S46_MAPE,
STATE_S46_LW,
- STATE_CAPT_PORT,
+ STATE_CAPT_PORT_RA,
+ STATE_CAPT_PORT_DHCPV6,
STATE_PASSTHRU,
_STATE_MAX
};
memcpy(copy, buf, uri_len);
copy[uri_len] = '\0';
- odhcp6c_clear_state(STATE_CAPT_PORT);
- odhcp6c_add_state(STATE_CAPT_PORT, copy, uri_len);
+ odhcp6c_clear_state(STATE_CAPT_PORT_RA);
+ odhcp6c_add_state(STATE_CAPT_PORT_RA, copy, uri_len);
free(copy);
}
}
} else if (pid == 0) {
size_t dns_len, search_len, custom_len, sntp_ip_len, ntp_ip_len, ntp_dns_len;
size_t sip_ip_len, sip_fqdn_len, aftr_name_len, addr_len;
- size_t s46_mapt_len, s46_mape_len, s46_lw_len, capt_port_len, passthru_len;
+ size_t s46_mapt_len, s46_mape_len, s46_lw_len, passthru_len;
+ size_t capt_port_ra_len, capt_port_dhcpv6_len;
signal(SIGTERM, SIG_DFL);
if (delay > 0) {
uint8_t *s46_mapt = odhcp6c_get_state(STATE_S46_MAPT, &s46_mapt_len);
uint8_t *s46_mape = odhcp6c_get_state(STATE_S46_MAPE, &s46_mape_len);
uint8_t *s46_lw = odhcp6c_get_state(STATE_S46_LW, &s46_lw_len);
- uint8_t *capt_port = odhcp6c_get_state(STATE_CAPT_PORT, &capt_port_len);
+ uint8_t *capt_port_ra = odhcp6c_get_state(STATE_CAPT_PORT_RA, &capt_port_ra_len);
+ uint8_t *capt_port_dhcpv6 = odhcp6c_get_state(STATE_CAPT_PORT_DHCPV6, &capt_port_dhcpv6_len);
uint8_t *passthru = odhcp6c_get_state(STATE_PASSTHRU, &passthru_len);
size_t prefix_len, address_len, ra_pref_len,
uint8_t *ra_dns = odhcp6c_get_state(STATE_RA_DNS, &ra_dns_len);
uint8_t *ra_search = odhcp6c_get_state(STATE_RA_SEARCH, &ra_search_len);
+ /* RFC8910 §3 */
+ if (capt_port_ra_len > 0 && capt_port_dhcpv6_len > 0) {
+ if (capt_port_ra_len != capt_port_dhcpv6_len ||
+ !memcmp(capt_port_dhcpv6, capt_port_ra, capt_port_dhcpv6_len))
+ syslog(LOG_ERR,
+ "%s received via different vectors differ: preferring URI from DHCPv6",
+ CAPT_PORT_URI_STR);
+ }
+
ipv6_to_env("SERVER", addr, addr_len / sizeof(*addr));
ipv6_to_env("RDNSS", dns, dns_len / sizeof(*dns));
ipv6_to_env("SNTP_IP", sntp, sntp_ip_len / sizeof(*sntp));
s46_to_env(STATE_S46_MAPE, s46_mape, s46_mape_len);
s46_to_env(STATE_S46_MAPT, s46_mapt, s46_mapt_len);
s46_to_env(STATE_S46_LW, s46_lw, s46_lw_len);
- string_to_env(CAPT_PORT_URI_STR, capt_port, capt_port_len);
+ if (capt_port_dhcpv6_len > 0)
+ string_to_env(CAPT_PORT_URI_STR, capt_port_dhcpv6, capt_port_dhcpv6_len);
+ else if (capt_port_ra_len > 0)
+ string_to_env(CAPT_PORT_URI_STR, capt_port_ra, capt_port_ra_len);
bin_to_env(custom, custom_len);
if (odhcp6c_is_bound()) {
char *buf = NULL;
size_t dns_len, search_len, custom_len, sntp_ip_len, ntp_ip_len, ntp_dns_len;
size_t sip_ip_len, sip_fqdn_len, aftr_name_len, addr_len;
- size_t s46_mapt_len, s46_mape_len, s46_lw_len, capt_port_len, passthru_len;
+ size_t s46_mapt_len, s46_mape_len, s46_lw_len, passthru_len;
+ size_t capt_port_ra_len, capt_port_dhcpv6_len;
struct in6_addr *addr = odhcp6c_get_state(STATE_SERVER_ADDR, &addr_len);
struct in6_addr *dns = odhcp6c_get_state(STATE_DNS, &dns_len);
uint8_t *search = odhcp6c_get_state(STATE_SEARCH, &search_len);
uint8_t *s46_mapt = odhcp6c_get_state(STATE_S46_MAPT, &s46_mapt_len);
uint8_t *s46_mape = odhcp6c_get_state(STATE_S46_MAPE, &s46_mape_len);
uint8_t *s46_lw = odhcp6c_get_state(STATE_S46_LW, &s46_lw_len);
- uint8_t *capt_port = odhcp6c_get_state(STATE_CAPT_PORT, &capt_port_len);
+ uint8_t *capt_port_ra = odhcp6c_get_state(STATE_CAPT_PORT_RA, &capt_port_ra_len);
+ uint8_t *capt_port_dhcpv6 = odhcp6c_get_state(STATE_CAPT_PORT_DHCPV6, &capt_port_dhcpv6_len);
uint8_t *passthru = odhcp6c_get_state(STATE_PASSTHRU, &passthru_len);
size_t prefix_len, address_len, ra_pref_len,
blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
+ /* RFC8910 §3 */
+ if (capt_port_ra_len > 0 && capt_port_dhcpv6_len > 0) {
+ if (capt_port_ra_len != capt_port_dhcpv6_len ||
+ !memcmp(capt_port_dhcpv6, capt_port_ra, capt_port_dhcpv6_len))
+ syslog(LOG_ERR,
+ "%s received via different vectors differ: preferring URI from DHCPv6",
+ CAPT_PORT_URI_STR);
+ }
+
blobmsg_add_string(&b, "DHCPV6_STATE", dhcpv6_state_to_str(dhcpv6_get_state()));
CHECK(ipv6_to_blob("SERVER", addr, addr_len / sizeof(*addr)));
CHECK(s46_to_blob(STATE_S46_MAPE, s46_mape, s46_mape_len));
CHECK(s46_to_blob(STATE_S46_MAPT, s46_mapt, s46_mapt_len));
CHECK(s46_to_blob(STATE_S46_LW, s46_lw, s46_lw_len));
- blobmsg_add_string(&b, CAPT_PORT_URI_STR, (char *)capt_port);
+ if (capt_port_dhcpv6_len > 0)
+ blobmsg_add_string(&b, CAPT_PORT_URI_STR, (char *)capt_port_dhcpv6);
+ else if (capt_port_ra_len > 0)
+ blobmsg_add_string(&b, CAPT_PORT_URI_STR, (char *)capt_port_ra);
CHECK(bin_to_blob(custom, custom_len));
if (odhcp6c_is_bound()) {