*ret_sec = be32toh(*(uint32_t*) (ri + 4));
return 0;
}
+
+int sd_ndisc_router_captive_portal_get_uri(sd_ndisc_router *rt, const char **ret_uri, size_t *ret_size) {
+ int r;
+ const char *nd_opt_captive_portal;
+ size_t length;
+
+ assert_return(rt, -EINVAL);
+ assert_return(ret_uri, -EINVAL);
+
+ r = sd_ndisc_router_option_is_type(rt, SD_NDISC_OPTION_CAPTIVE_PORTAL);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EMEDIUMTYPE;
+
+ r = sd_ndisc_router_option_get_raw(rt, (void *)&nd_opt_captive_portal, &length);
+ if (r < 0)
+ return r;
+
+ /* The length field has units of 8 octets */
+ assert(length % 8 == 0);
+ if (length == 0)
+ return -EBADMSG;
+
+ /* Check that the message is not truncated by an embedded NUL.
+ * NUL padding to a multiple of 8 is expected. */
+ size_t size = strnlen(nd_opt_captive_portal + 2, length - 2);
+ if (DIV_ROUND_UP(size + 2, 8) != length / 8)
+ return -EBADMSG;
+
+ /* Let's not return an empty buffer */
+ if (size == 0) {
+ *ret_uri = NULL;
+ *ret_size = 0;
+ return 0;
+ }
+
+ *ret_uri = nd_opt_captive_portal + 2;
+ *ret_size = size;
+
+ return 0;
+}
free(link->ssid);
free(link->previous_ssid);
free(link->driver);
+ free(link->ndisc_captive_portal);
unlink_and_free(link->lease_file);
unlink_and_free(link->lldp_file);
sd_event_source *ndisc_expire;
Set *ndisc_rdnss;
Set *ndisc_dnssl;
+ char *ndisc_captive_portal;
unsigned ndisc_messages;
bool ndisc_configured:1;
ndisc_dnssl_compare_func,
free);
+static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt) {
+ const char *uri;
+ _cleanup_free_ char *captive_portal = NULL;
+ size_t len;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(rt);
+
+ if (!link->network->ipv6_accept_ra_use_captive_portal)
+ return 0;
+
+ r = sd_ndisc_router_captive_portal_get_uri(rt, &uri, &len);
+ if (r < 0)
+ return r;
+
+ if (len == 0) {
+ mfree(link->ndisc_captive_portal);
+ return 0;
+ }
+
+ r = make_cstring(uri, len, MAKE_CSTRING_REFUSE_TRAILING_NUL, &captive_portal);
+ if (r < 0)
+ return r;
+
+ if (!in_charset(captive_portal, URI_VALID))
+ return -EINVAL;
+
+ if (!streq_ptr(link->ndisc_captive_portal, captive_portal)) {
+ free_and_replace(link->ndisc_captive_portal, captive_portal);
+ link_dirty(link);
+ }
+
+ return 0;
+}
+
static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
_cleanup_strv_free_ char **l = NULL;
usec_t lifetime_usec, timestamp_usec;
case SD_NDISC_OPTION_DNSSL:
r = ndisc_router_process_dnssl(link, rt);
break;
+ case SD_NDISC_OPTION_CAPTIVE_PORTAL:
+ r = ndisc_router_process_captive_portal(link, rt);
+ break;
}
if (r < 0 && r != -EBADMSG)
return r;
.ipv6_accept_ra = -1,
.ipv6_accept_ra_use_dns = true,
.ipv6_accept_ra_use_gateway = true,
+ .ipv6_accept_ra_use_captive_portal = true,
.ipv6_accept_ra_use_route_prefix = true,
.ipv6_accept_ra_use_autonomous_prefix = true,
.ipv6_accept_ra_use_onlink_prefix = true,
bool ipv6_accept_ra_use_onlink_prefix;
bool ipv6_accept_ra_use_mtu;
bool ipv6_accept_ra_quickack;
+ bool ipv6_accept_ra_use_captive_portal;
bool active_slave;
bool primary_slave;
DHCPUseDomains ipv6_accept_ra_use_domains;
int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret);
int sd_ndisc_router_dnssl_get_lifetime(sd_ndisc_router *rt, uint32_t *ret);
+/* Specific option access: SD_NDISC_OPTION_CAPTIVE_PORTAL */
+int sd_ndisc_router_captive_portal_get_uri(sd_ndisc_router *rt, const char **uri, size_t *size);
+
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc_router, sd_ndisc_router_unref);