case SD_DHCP6_OPTION_NIS_DOMAIN_NAME:
case SD_DHCP6_OPTION_NISP_DOMAIN_NAME:
case SD_DHCP6_OPTION_SNTP_SERVER:
+ return true;
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
+ return false; /* This is automatically set when sending INFORMATION_REQUEST message. */
case SD_DHCP6_OPTION_BCMCS_SERVER_D:
case SD_DHCP6_OPTION_BCMCS_SERVER_A:
case SD_DHCP6_OPTION_GEOCONF_CIVIC:
case SD_DHCP6_OPTION_CLIENT_LINKLAYER_ADDR:
case SD_DHCP6_OPTION_LINK_ADDRESS:
case SD_DHCP6_OPTION_RADIUS:
+ case SD_DHCP6_OPTION_SOL_MAX_RT: /* Automatically set when sending SOLICIT message. */
+ case SD_DHCP6_OPTION_INF_MAX_RT: /* Automatically set when sending INFORMATION_REQUEST message. */
return false;
- case SD_DHCP6_OPTION_SOL_MAX_RT:
- case SD_DHCP6_OPTION_INF_MAX_RT:
case SD_DHCP6_OPTION_ADDRSEL:
case SD_DHCP6_OPTION_ADDRSEL_TABLE:
case SD_DHCP6_OPTION_V6_PCP_SERVER:
}
}
+static int client_append_oro(sd_dhcp6_client *client, uint8_t **opt, size_t *optlen) {
+ _cleanup_free_ be16_t *buf = NULL;
+ be16_t *req_opts;
+ size_t n;
+
+ assert(client);
+ assert(opt);
+ assert(optlen);
+
+ switch (client->state) {
+ case DHCP6_STATE_INFORMATION_REQUEST:
+ n = client->n_req_opts;
+ buf = new(be16_t, n + 2);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
+ buf[n++] = htobe16(SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME); /* RFC 8415 section 21.23 */
+ buf[n++] = htobe16(SD_DHCP6_OPTION_INF_MAX_RT); /* RFC 8415 section 21.25 */
+
+ typesafe_qsort(buf, n, be16_compare_func);
+ req_opts = buf;
+ break;
+
+ case DHCP6_STATE_SOLICITATION:
+ n = client->n_req_opts;
+ buf = new(be16_t, n + 1);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
+ buf[n++] = htobe16(SD_DHCP6_OPTION_SOL_MAX_RT); /* RFC 8415 section 21.24 */
+
+ typesafe_qsort(buf, n, be16_compare_func);
+ req_opts = buf;
+ break;
+
+ default:
+ n = client->n_req_opts;
+ req_opts = client->req_opts;
+ }
+
+ return dhcp6_option_append(opt, optlen, SD_DHCP6_OPTION_ORO, n * sizeof(be16_t), req_opts);
+}
+
int dhcp6_client_send_message(sd_dhcp6_client *client) {
_cleanup_free_ DHCP6Message *message = NULL;
struct in6_addr all_servers =
return r;
}
- r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO,
- client->n_req_opts * sizeof(be16_t),
- client->req_opts);
+ r = client_append_oro(client, &opt, &optlen);
if (r < 0)
return r;
0x0f, 0xb4, 0xe5,
/* MUD URL */
/* ORO */
- 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
+ 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0c,
0x00, SD_DHCP6_OPTION_DNS_SERVER,
0x00, SD_DHCP6_OPTION_DOMAIN,
0x00, SD_DHCP6_OPTION_SNTP_SERVER,
+ 0x00, SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME,
0x00, SD_DHCP6_OPTION_NTP_SERVER,
+ 0x00, SD_DHCP6_OPTION_INF_MAX_RT,
/* Client ID */
0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
CLIENT_ID_BYTES,
/* Vendor Options */
/* MUD URL */
/* ORO */
- 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
+ 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0a,
0x00, SD_DHCP6_OPTION_DNS_SERVER,
0x00, SD_DHCP6_OPTION_DOMAIN,
0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0x00, SD_DHCP6_OPTION_NTP_SERVER,
+ 0x00, SD_DHCP6_OPTION_SOL_MAX_RT,
/* Client ID */
0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
CLIENT_ID_BYTES,