/* write rdata length */
sldns_write_uint16(rr+dname_len+8, (uint16_t)(rr_cur_len-dname_len-10));
*rr_len = rr_cur_len;
+ /* SVCB/HTTPS handling */
+ if (rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS) {
+
+
+
+ // 1. Find the size
+ // 2. qsort the data according to the keys
+ // 3. verify that keys are unique
+ // 4. verify that mandatory keys are present and unique
+
+
+ }
return LDNS_WIREPARSE_ERR_OK;
}
if (!strncmp(key, "ipv6hint", sizeof("ipv6hint")-1))
return SVCB_KEY_IPV6HINT;
break;
+
case sizeof("ech")-1:
if (!strncmp(key, "ech", sizeof("ech")-1))
return SVCB_KEY_ECH;
break;
+
default:
break;
}
- if (key_len > sizeof(buf) - 1) {}
+
+ if (key_len > sizeof(buf) - 1) {}
// ERROR: Unknown SvcParamKey
else {
memcpy(buf, key, key_len);
size_t str_len;
size_t dst_len;
size_t val_len;
- int wire_len;
val_len = strlen(val);
sldns_str2wire_svcparam_key_value(const char *key, size_t key_len,
const char *val, uint8_t* rd, size_t* rd_len)
{
+ size_t str_len;
uint16_t svcparamkey = sldns_str2wire_svcparam_key_lookup(key, key_len);
+
+ // @TODO add case where svcparamkey == -1
+
+ /* key and no value case*/
+ if (val == NULL) {
+ sldns_write_uint16(rd, svcparamkey);
+ sldns_write_uint16(rd + 2, 0);
+ *rd_len = 4;
+
+ return LDNS_WIREPARSE_ERR_OK;
+ }
+
+ // @TODO unescape characters in the value list
+
+ // if (val[0] == '"' && val[str_len - 1]) {
+
+ // }
+
+ /* value is non-empty */
switch (svcparamkey) {
case SVCB_KEY_PORT:
return sldns_str2wire_svcparam_port(val, rd, rd_len);
case SVCB_KEY_MANDATORY:
return sldns_str2wire_svcbparam_mandatory(val, rd, rd_len);
case SVCB_KEY_NO_DEFAULT_ALPN:
+
+ // @TODO is this superfluous now?
+
return sldns_str2wire_svcbparam_no_default_alpn(val, rd, rd_len);
- // if(zone_is_slave(parser->current_zone->opts))
- // zc_warning_prev_line("no-default-alpn should not have a value");
- // else
- // zc_error_prev_line("no-default-alpn should not have a value");
- // break;
case SVCB_KEY_ECH:
return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len);
case SVCB_KEY_ALPN:
return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len);
default:
- break;
+ // @TODO escaping here -> copy from alpn?
+
+ str_len = strlen(val);
+ sldns_write_uint16(rd, svcparamkey);
+ sldns_write_uint16(rd + 2, str_len);
+ memcpy(rd + 4, val, str_len);
+ *rd_len = 4 + str_len;
+
+ return LDNS_WIREPARSE_ERR_OK;
}
// @TODO change to error?
int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_len)
{
+ size_t str_len;
const char* eq_pos;
-
- int ret;
+ char unescaped_val[65536];
+ char* val_out = unescaped_val;
+ const char* val_in;
eq_pos = strchr(str, '=');
- // @TODO handle "key=" case
+ if (eq_pos != NULL && eq_pos[1]) { /* case: key=value */
+ val_in = eq_pos + 1;
+
+ /* unescape characters and "" blocks */
+ if (*val_in == '"') {
+ val_in++;
+ while (*val_in != '"' && sldns_parse_char( (uint8_t*) val_out, &val_in)) {
+ val_out++;
+ }
+ } else {
+ while ( sldns_parse_char( (uint8_t*) val_out, &val_in)) {
+ val_out++;
+ }
+ }
+ *val_out = 0;
- /* Verify that we have a have a value */
- if (eq_pos != NULL) {
- return sldns_str2wire_svcparam_key_value(str, eq_pos - str, eq_pos + 1, rd, rd_len);
- } else {
+ return sldns_str2wire_svcparam_key_value(str, eq_pos - str,
+ unescaped_val[0] ? unescaped_val : NULL, rd, rd_len);
+ } else if (eq_pos != NULL && !(eq_pos[1])) { /* case: key= */
+ return sldns_str2wire_svcparam_key_value(str, eq_pos - str, NULL, rd, rd_len);
+ } else { /* case: key */
return sldns_str2wire_svcparam_key_value(str, strlen(str), NULL, rd, rd_len);
}
/* draft-ietf-dnsop-svcb-https-04: 6. Initial SvcParamKeys */
const char *svcparamkey_strs[] = {
"mandatory", "alpn", "no-default-alpn", "port",
- "ipv4hint", "echconfig", "ipv6hint"
+ "ipv4hint", "ech", "ipv6hint"
};
char* sldns_wire2str_pkt(uint8_t* data, size_t len)
if (data_len != 2)
return -1; /* wireformat error, a short is 2 bytes */
w = sldns_str_print(s, slen, "=%d", (int)sldns_read_uint16(data));
+ *data += 2;
+
return w;
}
int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
{
+ char ch;
uint16_t svcparamkey, data_len;
int written_chars = 0;
- int r;
+ int r, i;
/* verify that we have enough data to read svcparamkey and data_len */
if(*dlen < 4)
*d += 4;
*dlen -= 4;
+ // fprintf(stderr, "data_len: %hu\n", data_len);
+
/* verify that we have data_len data */
if (data_len > *dlen)
return -1;
written_chars += sldns_print_svcparamkey(s, slen, svcparamkey);
if (!data_len) {
+
/* Some SvcParams MUST have values */
switch (svcparamkey) {
case SVCB_KEY_ALPN:
case SVCB_KEY_IPV4HINT:
case SVCB_KEY_IPV6HINT:
case SVCB_KEY_MANDATORY:
- return -1;
+ return LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE;
default:
- return written_chars;
+ return LDNS_WIREPARSE_ERR_OK;
}
}
+
switch (svcparamkey) {
case SVCB_KEY_PORT:
r = sldns_wire2str_svcparam_port2str(s, slen, data_len, *d);
r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d);
break;
default:
+ r += sldns_str_print(s, slen, "=\"");
+
+ for (i = 0; i < data_len; i++) {
+ ch = (*d)[i];
+
+ if (ch == '"' || ch == '\\')
+ r += sldns_str_print(s, slen, "\\%c", ch);
+
+ else if (!isprint(ch))
+ r += sldns_str_print(s, slen, "\\%03u", (unsigned) ch);
+
+ else
+ r += sldns_str_print(s, slen, "%c", ch);
+
+ }
+ r += sldns_str_print(s, slen, "%c", '"');
break;
}
if (r <= 0)