happyflow for all signle svcparams

This commit is contained in:
Tom Carpay 2021-05-20 13:28:34 +02:00
parent b61d098950
commit 1a28a27637
2 changed files with 216 additions and 58 deletions

View file

@ -1011,13 +1011,14 @@ sldns_str2wire_svcparam_port(const char* val, uint8_t* rd, size_t* rd_len)
&& *endptr == 0 /* no non-digit chars after digits */
&& port <= 65535) { /* no overflow */
sldns_write_uint16(rd, htons(SVCB_KEY_PORT));
sldns_write_uint16(rd + 2, htons(sizeof(uint16_t)));
sldns_write_uint16(rd + 4, htons(port));
sldns_write_uint16(rd, SVCB_KEY_PORT);
sldns_write_uint16(rd + 2, sizeof(uint16_t));
sldns_write_uint16(rd + 4, port);
*rd_len = 6;
return LDNS_WIREPARSE_ERR_OK;
}
// ERROR: "Could not parse port SvcParamValue"
return -1;
}
@ -1047,8 +1048,8 @@ sldns_str2wire_svcbparam_ipv4hint(const char* val, uint8_t* rd, size_t* rd_len)
/* count is number of comma's in val + 1; so the actual number of IPv4
* addresses in val
*/
sldns_write_uint16(rd, htons(SVCB_KEY_IPV4HINT));
sldns_write_uint16(rd + 2, htons(LDNS_IP4ADDRLEN * count));
sldns_write_uint16(rd, SVCB_KEY_IPV4HINT);
sldns_write_uint16(rd + 2, LDNS_IP4ADDRLEN * count);
*rd_len = 4;
while (count) {
@ -1106,8 +1107,8 @@ sldns_str2wire_svcbparam_ipv6hint(const char* val, uint8_t* rd, size_t* rd_len)
/* count is number of comma's in val + 1; so the actual number of IPv6
* addresses in val
*/
sldns_write_uint16(rd, htons(SVCB_KEY_IPV6HINT));
sldns_write_uint16(rd + 2, htons(LDNS_IP6ADDRLEN * count));
sldns_write_uint16(rd, SVCB_KEY_IPV6HINT);
sldns_write_uint16(rd + 2, LDNS_IP6ADDRLEN * count);
*rd_len = 4;
while (count) {
@ -1169,19 +1170,19 @@ sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len)
// @TODO check if we have space to write in rd_len; look for the best spot
sldns_write_uint16(rd, htons(SVCB_KEY_MANDATORY));
sldns_write_uint16(rd + 2, htons(sizeof(uint16_t) * count));
sldns_write_uint16(rd, SVCB_KEY_MANDATORY);
sldns_write_uint16(rd + 2, sizeof(uint16_t) * count);
*rd_len = 4;
for(;;) {
while (1) {
if (!(next_key = strchr(val, ','))) {
sldns_write_uint16(rd + *rd_len,
htons(sldns_str2wire_svcparam_key_lookup(val, val_len)));
sldns_str2wire_svcparam_key_lookup(val, val_len));
*rd_len += LDNS_IP6ADDRLEN;
break;
} else {
sldns_write_uint16(rd + *rd_len,
htons(sldns_str2wire_svcparam_key_lookup(val, next_key - val)));
sldns_str2wire_svcparam_key_lookup(val, next_key - val));
*rd_len += LDNS_IP6ADDRLEN;
}
@ -1228,7 +1229,7 @@ sldns_str2wire_svcbparam_ech_value(const char* val, uint8_t* rd, size_t* rd_len)
if (wire_len == -1) {
// zc_error_prev_line("invalid base64 data in ech");
return LDNS_WIREPARSE_ERR_INVALID_STR;
return LDNS_WIREPARSE_ERR_SYNTAX_B64;
} else if (wire_len + 4 > *rd_len) {
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
} else {
@ -1236,16 +1237,104 @@ sldns_str2wire_svcbparam_ech_value(const char* val, uint8_t* rd, size_t* rd_len)
sldns_write_uint16(rd + 2, wire_len);
memcpy(rd + 4, buffer, wire_len);
*rd_len = 4 + wire_len;
return LDNS_WIREPARSE_ERR_OK;
}
}
static const char*
sldns_str2wire_svcbparam_parse_alpn_next_unescaped_comma(const char *val)
{
while (*val) {
/* Only return when the comma is not escaped*/
if (*val == '\\'){
++val;
if (!*val)
break;
} else if (*val == ',')
return val;
val++;
}
return NULL;
}
static size_t
sldns_str2wire_svcbparam_parse_alpn_copy_unescaped(uint8_t *dst,
const char *src, size_t len)
{
uint8_t *orig_dst = dst;
while (len) {
if (*src == '\\') {
src++;
len--;
if (!len)
break;
}
*dst++ = *src++;
len--;
}
return (size_t)(dst - orig_dst);
}
int sldns_str2wire_svcbparam_alpn_value(const char* val,
uint8_t* rd, size_t* rd_len)
{
uint8_t unescaped_dst[65536];
uint8_t *dst = unescaped_dst;
const char *next_str;
size_t str_len;
size_t dst_len;
size_t val_len;
int wire_len;
val_len = strlen(val);
if (val_len > sizeof(unescaped_dst)) {
return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW;
}
while (val_len) {
size_t dst_len;
str_len = (next_str = sldns_str2wire_svcbparam_parse_alpn_next_unescaped_comma(val))
? (size_t)(next_str - val) : val_len;
if (str_len > 255) {
// ERROR "alpn strings need to be smaller than 255 chars"
return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW;
}
dst_len = sldns_str2wire_svcbparam_parse_alpn_copy_unescaped(dst + 1, val, str_len);
*dst++ = dst_len;
dst += dst_len;
if (!next_str)
break;
/* skip the comma for the next iteration */
val_len -= next_str - val + 1;
val = next_str + 1;
}
dst_len = dst - unescaped_dst;
sldns_write_uint16(rd, SVCB_KEY_ALPN);
sldns_write_uint16(rd + 2, dst_len);
memcpy(rd + 4, unescaped_dst, dst_len);
*rd_len = 4 + dst_len;
return LDNS_WIREPARSE_ERR_OK;
}
static int
sldns_str2wire_svcparam_key_value(const char *key, size_t key_len,
const char *val, uint8_t* rd, size_t* rd_len)
{
uint16_t svcparamkey = sldns_str2wire_svcparam_key_lookup(key, key_len);
fprintf(stderr, "key: %s\n", key);
fprintf(stderr, "val: %s\n", val);
switch (svcparamkey) {
case SVCB_KEY_PORT:
return sldns_str2wire_svcparam_port(val, rd, rd_len);
@ -1265,7 +1354,7 @@ sldns_str2wire_svcparam_key_value(const char *key, size_t key_len,
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);
return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len);
default:
break;
}

View file

@ -950,7 +950,6 @@ static int
sldns_print_svcparamkey(char** s, size_t* slen, uint16_t svcparamkey)
{
if (svcparamkey < SVCPARAMKEY_COUNT) {
// fprintf(stderr, "HERE\n");
return sldns_str_print(s, slen, "%s", svcparamkey_strs[svcparamkey]);
}
else {
@ -959,106 +958,175 @@ sldns_print_svcparamkey(char** s, size_t* slen, uint16_t svcparamkey)
}
int sldns_wire2str_svcparam_port2str(char** s,
size_t* slen, uint16_t val_len, uint16_t val)
size_t* slen, uint16_t data_len, uint16_t data)
{
int w = 0;
if (val_len != 2)
if (data_len != 2)
return -1; /* wireformat error, a short is 2 bytes */
w = sldns_str_print(s, slen, "=%d", (int)ntohs(val));
w = sldns_str_print(s, slen, "=%d", (int)data);
return w;
}
static int
sldns_wire2str_svcparam_ipv4hint2str(char** s,
size_t* slen, uint16_t val_len, uint8_t* data)
size_t* slen, uint16_t data_len, uint8_t* data)
{
char ip_str[INET_ADDRSTRLEN + 1];
// @TODO actually incorporate this
int w = 0;
assert(val_len > 0);
assert(data_len > 0);
if ((val_len % LDNS_IP4ADDRLEN) == 0) {
if ((data_len % LDNS_IP4ADDRLEN) == 0) {
if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
return 0; /* wireformat error, incorrect size or inet family */
sldns_str_print(s, slen, "=%s", ip_str);
w += sldns_str_print(s, slen, "=%s", ip_str);
data += LDNS_IP4ADDRLEN / sizeof(uint16_t);
while ((val_len -= LDNS_IP4ADDRLEN) > 0) {
while ((data_len -= LDNS_IP4ADDRLEN) > 0) {
if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
return 0; /* wireformat error, incorrect size or inet family */
sldns_str_print(s, slen, ",%s", ip_str);
w += sldns_str_print(s, slen, ",%s", ip_str);
data += LDNS_IP4ADDRLEN / sizeof(uint16_t);
}
return 1;
} else
return 0;
}
return w;
}
int sldns_wire2str_svcparam_ipv6hint2str(char** s,
size_t* slen, uint16_t val_len, uint8_t* data)
size_t* slen, uint16_t data_len, uint8_t* data)
{
char ip_str[INET6_ADDRSTRLEN + 1];
// @TODO actually incorporate this
// @TODO actually incorporate this -> is this correct now?
int w = 0;
assert(val_len > 0);
assert(data_len > 0);
if ((val_len % LDNS_IP6ADDRLEN) == 0) {
// @TODO fix ntohs -> see output
if ((data_len % LDNS_IP6ADDRLEN) == 0) {
if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
return 0; /* wireformat error, incorrect size or inet family */
sldns_str_print(s, slen, "=%s", ip_str);
w += sldns_str_print(s, slen, "=%s", ip_str);
data += LDNS_IP6ADDRLEN / sizeof(uint16_t);
while ((val_len -= LDNS_IP6ADDRLEN) > 0) {
while ((data_len -= LDNS_IP6ADDRLEN) > 0) {
if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
return 0; /* wireformat error, incorrect size or inet family */
sldns_str_print(s, slen, ",%s", ip_str);
w += sldns_str_print(s, slen, ",%s", ip_str);
data += LDNS_IP6ADDRLEN / sizeof(uint16_t);
}
return 1;
} else
return 0;
}
return w;
}
int sldns_wire2str_svcparam_mandatory2str(char** s,
size_t* slen, uint16_t val_len, uint8_t* data)
size_t* slen, uint16_t data_len, uint8_t* data)
{
int w = 0;
assert(val_len > 0);
assert(data_len > 0);
// if (val_len % sizeof(uint16_t))
// return 0; // wireformat error, val_len must be multiple of shorts
// if (data_len % sizeof(uint16_t))
// return 0; // wireformat error, data_len must be multiple of shorts
w += sldns_str_print(s, slen, "=");
w += sldns_print_svcparamkey(s, slen, ntohs(sldns_read_uint16(data)));
w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
data += 2;
while ((val_len -= sizeof(uint16_t))) {
while ((data_len -= sizeof(uint16_t))) {
w += sldns_str_print(s, slen, ",");
w += sldns_print_svcparamkey(s, slen, ntohs(sldns_read_uint16(data)));
w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
data += 2;
}
return w;
}
int sldns_wire2str_svcparam_alpn2str(char** s,
size_t* slen, uint16_t data_len, uint8_t* data)
{
uint8_t *dp = (void *)data;
int w = 0;
assert(data_len > 0); /* Guaranteed by rdata_svcparam_to_string */
w += sldns_str_print(s, slen, "=\"");
while (data_len) {
uint8_t i, str_len = *dp++;
if (str_len > --data_len)
return 0;
for (i = 0; i < str_len; i++) {
if (dp[i] == '"' || dp[i] == '\\')
w += sldns_str_print(s, slen, "\\\\\\%c", dp[i]);
else if (dp[i] == ',')
w += sldns_str_print(s, slen, "\\\\%c", dp[i]);
else if (!isprint(dp[i]))
w += sldns_str_print(s, slen, "\\%03u", (unsigned) dp[i]);
else
w += sldns_str_print(s, slen, "%c", dp[i]);
}
dp += str_len;
if ((data_len -= str_len))
w += sldns_str_print(s, slen, "%s", ",");
}
w += sldns_str_print(s, slen, "\"");
return w;
}
int sldns_wire2str_svcparam_ech2str(char** s,
size_t* slen, uint16_t data_len, uint8_t* data)
{
int size;
int w;
assert(data_len > 0); /* Guaranteed by rdata_svcparam_to_string */
w += sldns_str_print(s, slen, "=\"");
/* b64_ntop_calculate size includes null at the end */
size = sldns_b64_ntop_calculate_size(data_len);
fprintf(stderr, "size %d\n", size);
// @TODO store return value?
sldns_b64_ntop(data, data_len, *s, *slen);
(*s) += size;
(*slen) -= size;
w += sldns_str_print(s, slen, "\"");
// @TODO fix check
// if(size > *slen) {
// buffer_skip(output, size);
// }
return w + size;
}
int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
{
uint16_t svcparamkey, val_len;
uint16_t svcparamkey, data_len;
uint8_t* data = *d;
int written_chars = 0;
if(*dlen == 0) return 0; /* verify that we actualy have data */
svcparamkey = ntohs(sldns_read_uint16(data));
svcparamkey = sldns_read_uint16(data);
written_chars += sldns_print_svcparamkey(s, slen, svcparamkey);
@ -1066,15 +1134,15 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
// @TODO fix this to be dynamic and correct
// fprintf(stderr, "*dlen2: %zu\n", *dlen);
// fprintf(stderr, "val_len %zu\n", val_len);
// fprintf(stderr, "data_len %zu\n", data_len);
(*dlen) = 0;
val_len = ntohs(sldns_read_uint16(data+2));
data_len = sldns_read_uint16(data+2);
// if (size != val_len + 4)
// return 0; wireformat error
// if (!val_len) {
// if (!data_len) {
// /* Some SvcParams MUST have values */
// switch (svcparamkey) {
// case SVCB_KEY_ALPN:
@ -1087,34 +1155,35 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
// return 1;
// }
// }
switch (svcparamkey) {
case SVCB_KEY_PORT:
written_chars += sldns_wire2str_svcparam_port2str(s, slen, val_len, sldns_read_uint16(data+4));
written_chars += sldns_wire2str_svcparam_port2str(s, slen, data_len, sldns_read_uint16(data+4));
break;
case SVCB_KEY_IPV4HINT:
written_chars += sldns_wire2str_svcparam_ipv4hint2str(s, slen, val_len, data+4);
written_chars += sldns_wire2str_svcparam_ipv4hint2str(s, slen, data_len, data+4);
break;
case SVCB_KEY_IPV6HINT:
written_chars += sldns_wire2str_svcparam_ipv6hint2str(s, slen, val_len, data+4);
written_chars += sldns_wire2str_svcparam_ipv6hint2str(s, slen, data_len, data+4);
break;
case SVCB_KEY_MANDATORY:
written_chars += sldns_wire2str_svcparam_mandatory2str(s, slen, val_len, data+4);
written_chars += sldns_wire2str_svcparam_mandatory2str(s, slen, data_len, data+4);
break;
case SVCB_KEY_NO_DEFAULT_ALPN:
return 0; /* wireformat error, should not have a value */
case SVCB_KEY_ALPN:
// written_chars += sldns_wire2str_svcparam_alpn2str(output, val_len, data+2);
// break;
written_chars += sldns_wire2str_svcparam_alpn2str(s, slen, data_len, data+4);
break;
case SVCB_KEY_ECH:
// written_chars += sldns_wire2str_svcparam_ech2str(output, val_len, data+2);
// break;
written_chars += sldns_wire2str_svcparam_ech2str(s, slen, data_len, data+4);
break;
default:
break;
}
// @TODO set str_len to 0: "If the end of the
// * output string is reached, *str_len is set to 0"
// *str_len = 0;
// *slen = 0;
return written_chars;
}