]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dhcp6-client: parse RFC8910 captive portal dhcp6 option
authorRonan Pigott <ronan@rjp.ie>
Thu, 29 Jun 2023 22:55:21 +0000 (15:55 -0700)
committerRonan Pigott <ronan@rjp.ie>
Thu, 29 Jun 2023 23:42:25 +0000 (16:42 -0700)
src/libsystemd-network/dhcp6-lease-internal.h
src/libsystemd-network/dhcp6-option.c
src/libsystemd-network/dhcp6-option.h
src/libsystemd-network/sd-dhcp6-lease.c
src/systemd/sd-dhcp6-lease.h

index 1f10dccbbb0e46e71f78d26366b0ad4d516ad44b..f4c12ca7c4a598d0e400802c2b9540622c4a2287 100644 (file)
@@ -43,6 +43,7 @@ struct sd_dhcp6_lease {
         struct in6_addr *sntp;
         size_t sntp_count;
         char *fqdn;
+        char *captive_portal;
 };
 
 int dhcp6_lease_get_lifetime(sd_dhcp6_lease *lease, usec_t *ret_t1, usec_t *ret_t2, usec_t *ret_valid);
@@ -60,6 +61,7 @@ int dhcp6_lease_add_domains(sd_dhcp6_lease *lease, const uint8_t *optval, size_t
 int dhcp6_lease_add_ntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen);
 int dhcp6_lease_add_sntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen);
 int dhcp6_lease_set_fqdn(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen);
+int dhcp6_lease_set_captive_portal(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen);
 
 int dhcp6_lease_new(sd_dhcp6_lease **ret);
 int dhcp6_lease_new_from_message(
index a6b74e07b287c9efcc278895dc61db4d0b723d39..3409485e11845bda29901e9e72a8ec357f2169da 100644 (file)
@@ -524,6 +524,26 @@ int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_s
         return status;
 }
 
+/* parse a string from dhcp option field. *ret must be initialized */
+int dhcp6_option_parse_string(const uint8_t *data, size_t data_len, char **ret) {
+        _cleanup_free_ char *string = NULL;
+        int r;
+
+        assert(data);
+        assert(ret);
+
+        if (data_len <= 0) {
+                *ret = mfree(*ret);
+                return 0;
+        }
+
+        r = make_cstring((const char *) data, data_len, MAKE_CSTRING_REFUSE_TRAILING_NUL, &string);
+        if (r < 0)
+                return r;
+
+        return free_and_replace(*ret, string);
+}
+
 static int dhcp6_option_parse_ia_options(sd_dhcp6_client *client, const uint8_t *buf, size_t buflen) {
         int r;
 
index 36841dd270cbe95757f29555ec67b60cfcac2f43..614b4f8a43d83890e6c9ce9ecba7005dde835787 100644 (file)
@@ -88,6 +88,7 @@ int dhcp6_option_parse(
                 size_t *ret_option_data_len,
                 const uint8_t **ret_option_data);
 int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_status_message);
+int dhcp6_option_parse_string(const uint8_t *data, size_t data_len, char **ret);
 int dhcp6_option_parse_ia(
                 sd_dhcp6_client *client,
                 be32_t iaid,
index d14c412c1fb8057a8fcf9b29962ffc5865de9be2..89e5a608f8a102108ff55d9be271402e3f44f058 100644 (file)
@@ -445,6 +445,34 @@ int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **ret) {
         return 0;
 }
 
+int dhcp6_lease_set_captive_portal(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen) {
+        _cleanup_free_ char *uri = NULL;
+        int r;
+
+        assert(lease);
+        assert(optval || optlen == 0);
+
+        r = dhcp6_option_parse_string(optval, optlen, &uri);
+        if (r < 0)
+                return r;
+
+        if (uri && !in_charset(uri, URI_VALID))
+                return -EINVAL;
+
+        return free_and_replace(lease->captive_portal, uri);
+}
+
+int sd_dhcp6_lease_get_captive_portal(sd_dhcp6_lease *lease, const char **ret) {
+        assert_return(lease, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        if (!lease->captive_portal)
+                return -ENODATA;
+
+        *ret = lease->captive_portal;
+        return 0;
+}
+
 static int dhcp6_lease_parse_message(
                 sd_dhcp6_client *client,
                 sd_dhcp6_lease *lease,
@@ -605,6 +633,12 @@ static int dhcp6_lease_parse_message(
 
                         break;
 
+                case SD_DHCP6_OPTION_CAPTIVE_PORTAL:
+                        r = dhcp6_lease_set_captive_portal(lease, optval, optlen);
+                        if (r < 0)
+                                log_dhcp6_client_errno(client, r, "Failed to parse captive portal option, ignoring: %m");
+                        break;
+
                 case SD_DHCP6_OPTION_CLIENT_FQDN:
                         r = dhcp6_lease_set_fqdn(lease, optval, optlen);
                         if (r < 0)
@@ -665,6 +699,7 @@ static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) {
         dhcp6_ia_free(lease->ia_pd);
         free(lease->dns);
         free(lease->fqdn);
+        free(lease->captive_portal);
         strv_free(lease->domains);
         free(lease->ntp);
         strv_free(lease->ntp_fqdn);
index 716f6fc17c63b5a985d3ad08b25d2ad191f17d1f..9f52496985bcae32ffb132c832677b6dfe4005c4 100644 (file)
@@ -48,6 +48,7 @@ int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***ret);
 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr **ret);
 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ret);
 int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **ret);
+int sd_dhcp6_lease_get_captive_portal(sd_dhcp6_lease *lease, const char **ret);
 
 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease);
 sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease);