Merge pull request #617 from NLnetLabs/update-host-notation

Update stub/forward-host notation to accept port and tls-auth-name
This commit is contained in:
gthess 2022-02-02 11:56:27 +01:00 committed by GitHub
commit 11f2e7e6ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 200 additions and 82 deletions

View File

@ -2015,7 +2015,7 @@ print_root_fwds(RES* ssl, struct iter_forwards* fwds, uint8_t* root)
/** parse args into delegpt */
static struct delegpt*
parse_delegpt(RES* ssl, char* args, uint8_t* nm, int allow_names)
parse_delegpt(RES* ssl, char* args, uint8_t* nm)
{
/* parse args and add in */
char* p = args;
@ -2037,40 +2037,35 @@ parse_delegpt(RES* ssl, char* args, uint8_t* nm, int allow_names)
}
/* parse address */
if(!authextstrtoaddr(todo, &addr, &addrlen, &auth_name)) {
if(allow_names) {
uint8_t* n = NULL;
size_t ln;
int lb;
if(!parse_arg_name(ssl, todo, &n, &ln, &lb)) {
(void)ssl_printf(ssl, "error cannot "
"parse IP address or name "
"'%s'\n", todo);
delegpt_free_mlc(dp);
return NULL;
}
if(!delegpt_add_ns_mlc(dp, n, 0)) {
(void)ssl_printf(ssl, "error out of memory\n");
free(n);
delegpt_free_mlc(dp);
return NULL;
}
free(n);
} else {
uint8_t* dname= NULL;
int port;
dname = authextstrtodname(todo, &port, &auth_name);
if(!dname) {
(void)ssl_printf(ssl, "error cannot parse"
" IP address '%s'\n", todo);
" '%s'\n", todo);
delegpt_free_mlc(dp);
return NULL;
}
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
if(auth_name)
log_err("no name verification functionality in "
"ssl library, ignored name for %s", todo);
#endif
if(!delegpt_add_ns_mlc(dp, dname, 0, auth_name, port)) {
(void)ssl_printf(ssl, "error out of memory\n");
free(dname);
delegpt_free_mlc(dp);
return NULL;
}
} else {
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
if(auth_name)
log_err("no name verification functionality in "
log_err("no name verification functionality in "
"ssl library, ignored name for %s", todo);
#endif
/* add address */
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
auth_name)) {
auth_name, -1)) {
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
return NULL;
@ -2103,7 +2098,7 @@ do_forward(RES* ssl, struct worker* worker, char* args)
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root);
} else {
struct delegpt* dp;
if(!(dp = parse_delegpt(ssl, args, root, 0)))
if(!(dp = parse_delegpt(ssl, args, root)))
return;
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
(void)ssl_printf(ssl, "error out of memory\n");
@ -2149,7 +2144,7 @@ parse_fs_args(RES* ssl, char* args, uint8_t** nm, struct delegpt** dp,
/* parse dp */
if(dp) {
if(!(*dp = parse_delegpt(ssl, args, *nm, 1))) {
if(!(*dp = parse_delegpt(ssl, args, *nm))) {
free(*nm);
return 0;
}

View File

@ -1861,13 +1861,19 @@ Name of the stub zone. This is the full domain name of the zone.
.TP
.B stub\-host: \fI<domain name>
Name of stub zone nameserver. Is itself resolved before it is used.
To use a nondefault port for DNS communication append '@' with the port number.
If tls is enabled, then you can append a '#' and a name, then it'll check the
tls authentication certificates with that name. If you combine the '@'
and '#', the '@' comes first. If only '#' is used the default port is the
configured tls\-port.
.TP
.B stub\-addr: \fI<IP address>
IP address of stub zone nameserver. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
If tls is enabled, then you can append a '#' and a name, then it'll check
the tls authentication certificates with that name. If you combine
the '@' and '#', the '@' comes first.
If tls is enabled, then you can append a '#' and a name, then it'll check the
tls authentication certificates with that name. If you combine the '@'
and '#', the '@' comes first. If only '#' is used the default port is the
configured tls\-port.
.TP
.B stub\-prime: \fI<yes or no>
This option is by default no. If enabled it performs NS set priming,
@ -1918,13 +1924,19 @@ Name of the forward zone. This is the full domain name of the zone.
.TP
.B forward\-host: \fI<domain name>
Name of server to forward to. Is itself resolved before it is used.
To use a nondefault port for DNS communication append '@' with the port number.
If tls is enabled, then you can append a '#' and a name, then it'll check the
tls authentication certificates with that name. If you combine the '@'
and '#', the '@' comes first. If only '#' is used the default port is the
configured tls\-port.
.TP
.B forward\-addr: \fI<IP address>
IP address of server to forward to. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
If tls is enabled, then you can append a '#' and a name, then it'll check
the tls authentication certificates with that name. If you combine
the '@' and '#', the '@' comes first.
If tls is enabled, then you can append a '#' and a name, then it'll check the
tls authentication certificates with that name. If you combine the '@'
and '#', the '@' comes first. If only '#' is used the default port is the
configured tls\-port.
.IP
At high verbosity it logs the TLS certificate, with TLS enabled.
If you leave out the '#' and auth name from the forward\-addr, any

View File

@ -75,7 +75,8 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
copy->ssl_upstream = dp->ssl_upstream;
copy->tcp_upstream = dp->tcp_upstream;
for(ns = dp->nslist; ns; ns = ns->next) {
if(!delegpt_add_ns(copy, region, ns->name, ns->lame))
if(!delegpt_add_ns(copy, region, ns->name, ns->lame,
ns->tls_auth_name, ns->port))
return NULL;
copy->nslist->resolved = ns->resolved;
copy->nslist->got4 = ns->got4;
@ -84,8 +85,8 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
copy->nslist->done_pside6 = ns->done_pside6;
}
for(a = dp->target_list; a; a = a->next_target) {
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
a->bogus, a->lame, a->tls_auth_name, NULL))
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
a->bogus, a->lame, a->tls_auth_name, -1, NULL))
return NULL;
}
return copy;
@ -102,7 +103,7 @@ delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name)
int
delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
uint8_t lame)
uint8_t lame, char* tls_auth_name, int port)
{
struct delegpt_ns* ns;
size_t len;
@ -126,6 +127,14 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
ns->lame = lame;
ns->done_pside4 = 0;
ns->done_pside6 = 0;
ns->port = port;
if(tls_auth_name) {
ns->tls_auth_name = regional_strdup(region, tls_auth_name);
if(!ns->tls_auth_name)
return 0;
} else {
ns->tls_auth_name = NULL;
}
return ns->name != 0;
}
@ -159,9 +168,9 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr,
return NULL;
}
int
delegpt_add_target(struct delegpt* dp, struct regional* region,
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
int
delegpt_add_target(struct delegpt* dp, struct regional* region,
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions)
{
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
@ -177,17 +186,22 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
if(ns->got4 && ns->got6)
ns->resolved = 1;
}
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL,
additions);
log_assert(ns->port>0);
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame,
ns->tls_auth_name, ns->port, additions);
}
int
delegpt_add_addr(struct delegpt* dp, struct regional* region,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
uint8_t lame, char* tls_auth_name, int* additions)
int
delegpt_add_addr(struct delegpt* dp, struct regional* region,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
uint8_t lame, char* tls_auth_name, int port, int* additions)
{
struct delegpt_addr* a;
log_assert(!dp->dp_type_mlc);
if(port != -1) {
log_assert(port>0);
sockaddr_store_port(addr, addrlen, port);
}
/* check for duplicates */
if((a = delegpt_find_addr(dp, addr, addrlen))) {
if(bogus)
@ -412,7 +426,8 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
(size_t)sldns_read_uint16(nsdata->rr_data[i]))
continue; /* bad format */
/* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame))
if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame,
NULL, UNBOUND_DNS_PORT))
return 0;
}
return 1;
@ -429,7 +444,6 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
log_assert(!dp->dp_type_mlc);
memset(&sa, 0, len);
sa.sin_family = AF_INET;
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
for(i=0; i<d->count; i++) {
if(d->rr_len[i] != 2 + INET_SIZE)
continue;
@ -453,7 +467,6 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
log_assert(!dp->dp_type_mlc);
memset(&sa, 0, len);
sa.sin6_family = AF_INET6;
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
for(i=0; i<d->count; i++) {
if(d->rr_len[i] != 2 + INET6_SIZE) /* rdatalen + len of IP6 */
continue;
@ -555,6 +568,7 @@ void delegpt_free_mlc(struct delegpt* dp)
while(n) {
nn = n->next;
free(n->name);
free(n->tls_auth_name);
free(n);
n = nn;
}
@ -577,7 +591,8 @@ int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name)
return (dp->name != NULL);
}
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
char* tls_auth_name, int port)
{
struct delegpt_ns* ns;
size_t len;
@ -604,14 +619,30 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
ns->lame = (uint8_t)lame;
ns->done_pside4 = 0;
ns->done_pside6 = 0;
ns->port = port;
if(tls_auth_name) {
ns->tls_auth_name = strdup(tls_auth_name);
if(!ns->tls_auth_name) {
free(ns->name);
free(ns);
return 0;
}
} else {
ns->tls_auth_name = NULL;
}
return 1;
}
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name)
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name,
int port)
{
struct delegpt_addr* a;
log_assert(dp->dp_type_mlc);
if(port != -1) {
log_assert(port>0);
sockaddr_store_port(addr, addrlen, port);
}
/* check for duplicates */
if((a = delegpt_find_addr(dp, addr, addrlen))) {
if(bogus)
@ -664,7 +695,9 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
if(ns->got4 && ns->got6)
ns->resolved = 1;
}
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, NULL);
log_assert(ns->port>0);
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame,
ns->tls_auth_name, ns->port);
}
size_t delegpt_get_mem(struct delegpt* dp)

View File

@ -126,6 +126,11 @@ struct delegpt_ns {
* Also enabled if a parent-side cache entry exists, or a parent-side
* negative-cache entry exists. */
uint8_t done_pside6;
/** the TLS authentication name, (if not NULL) to use. */
char* tls_auth_name;
/** the port to use; it should mosty be the default 53 but configured
* upstreams can provide nondefault ports. */
int port;
};
/**
@ -191,10 +196,12 @@ int delegpt_set_name(struct delegpt* dp, struct regional* regional,
* @param regional: where to allocate the info.
* @param name: domain name in wire format.
* @param lame: name is lame, disprefer it.
* @param tls_auth_name: TLS authentication name (or NULL).
* @param port: port to use for resolved addresses.
* @return false on error.
*/
int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
uint8_t* name, uint8_t lame);
int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
uint8_t* name, uint8_t lame, char* tls_auth_name, int port);
/**
* Add NS rrset; calls add_ns repeatedly.
@ -271,12 +278,14 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
* @param bogus: if address is bogus.
* @param lame: if address is lame.
* @param tls_auth_name: TLS authentication name (or NULL).
* @param port: the port to use; if -1 the port is taken from addr.
* @param additions: will be set to 1 if a new address is added
* @return false on error.
*/
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t bogus, uint8_t lame, char* tls_auth_name, int* additions);
uint8_t bogus, uint8_t lame, char* tls_auth_name, int port,
int* additions);
/**
* Find NS record in name list of delegation point.
@ -404,22 +413,27 @@ int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name);
* @param dp: must have been created with delegpt_create_mlc.
* @param name: the name to add.
* @param lame: the name is lame, disprefer.
* @param tls_auth_name: TLS authentication name (or NULL).
* @param port: port to use for resolved addresses.
* @return false on error.
*/
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame);
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
char* tls_auth_name, int port);
/**
* add an address to a malloced delegation point.
* @param dp: must have been created with delegpt_create_mlc.
* @param dp: must have been created with delegpt_create_mlc.
* @param addr: the address.
* @param addrlen: the length of addr.
* @param bogus: if address is bogus.
* @param lame: if address is lame.
* @param tls_auth_name: TLS authentication name (or NULL).
* @param port: the port to use; if -1 the port is taken from addr.
* @return false on error.
*/
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name);
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name,
int port);
/**
* Add target address to the delegation point.

View File

@ -200,21 +200,27 @@ read_fwds_name(struct config_stub* s)
}
/** set fwd host names */
static int
static int
read_fwds_host(struct config_stub* s, struct delegpt* dp)
{
struct config_strlist* p;
uint8_t* dname;
size_t dname_len;
char* tls_auth_name;
int port;
for(p = s->hosts; p; p = p->next) {
log_assert(p->str);
dname = sldns_str2wire_dname(p->str, &dname_len);
dname = authextstrtodname(p->str, &port, &tls_auth_name);
if(!dname) {
log_err("cannot parse forward %s server name: '%s'",
s->name, p->str);
return 0;
}
if(!delegpt_add_ns_mlc(dp, dname, 0)) {
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
if(tls_auth_name)
log_err("no name verification functionality in "
"ssl library, ignored name for %s", p->str);
#endif
if(!delegpt_add_ns_mlc(dp, dname, 0, tls_auth_name, port)) {
free(dname);
log_err("out of memory");
return 0;
@ -245,7 +251,7 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp)
"ssl library, ignored name for %s", p->str);
#endif
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
tls_auth_name)) {
tls_auth_name, -1)) {
log_err("out of memory");
return 0;
}

View File

@ -99,7 +99,7 @@ ah(struct delegpt* dp, const char* sv, const char* ip)
log_err("could not parse %s", sv);
return 0;
}
if(!delegpt_add_ns_mlc(dp, dname, 0) ||
if(!delegpt_add_ns_mlc(dp, dname, 0, NULL, UNBOUND_DNS_PORT) ||
!extstrtoaddr(ip, &addr, &addrlen) ||
!delegpt_add_target_mlc(dp, dname, dname_len,
&addr, addrlen, 0, 0)) {
@ -213,21 +213,27 @@ read_stubs_name(struct config_stub* s)
}
/** set stub host names */
static int
static int
read_stubs_host(struct config_stub* s, struct delegpt* dp)
{
struct config_strlist* p;
size_t dname_len;
uint8_t* dname;
char* tls_auth_name;
int port;
for(p = s->hosts; p; p = p->next) {
log_assert(p->str);
dname = sldns_str2wire_dname(p->str, &dname_len);
dname = authextstrtodname(p->str, &port, &tls_auth_name);
if(!dname) {
log_err("cannot parse stub %s nameserver name: '%s'",
s->name, p->str);
return 0;
}
if(!delegpt_add_ns_mlc(dp, dname, 0)) {
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
if(tls_auth_name)
log_err("no name verification functionality in "
"ssl library, ignored name for %s", p->str);
#endif
if(!delegpt_add_ns_mlc(dp, dname, 0, tls_auth_name, port)) {
free(dname);
log_err("out of memory");
return 0;
@ -258,7 +264,7 @@ read_stubs_addr(struct config_stub* s, struct delegpt* dp)
"ssl library, ignored name for %s", p->str);
#endif
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
auth_name)) {
auth_name, -1)) {
log_err("out of memory");
return 0;
}
@ -338,7 +344,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
if(sldns_wirerr_get_type(rr, rr_len, dname_len)
== LDNS_RR_TYPE_NS) {
if(!delegpt_add_ns_mlc(dp, sldns_wirerr_get_rdata(rr,
rr_len, dname_len), 0)) {
rr_len, dname_len), 0, NULL, UNBOUND_DNS_PORT)) {
log_err("out of memory reading root hints");
goto stop_read;
}

View File

@ -1958,12 +1958,13 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
iq->chase_flags &= ~BIT_RD; /* go to authorities */
for(ns = p->nslist; ns; ns=ns->next) {
(void)delegpt_add_ns(iq->dp, qstate->region,
ns->name, ns->lame);
ns->name, ns->lame, ns->tls_auth_name,
ns->port);
}
for(a = p->target_list; a; a=a->next_target) {
(void)delegpt_add_addr(iq->dp, qstate->region,
&a->addr, a->addrlen, a->bogus,
a->lame, a->tls_auth_name, NULL);
a->lame, a->tls_auth_name, -1, NULL);
}
}
iq->dp->has_parent_side_NS = 1;
@ -3342,21 +3343,22 @@ processTargetResponse(struct module_qstate* qstate, int id,
log_err("out of memory adding pside glue");
}
/* This response is relevant to the current query, so we
* add (attempt to add, anyway) this target(s) and reactivate
* the original event.
* NOTE: we could only look for the AnswerRRset if the
/* This response is relevant to the current query, so we
* add (attempt to add, anyway) this target(s) and reactivate
* the original event.
* NOTE: we could only look for the AnswerRRset if the
* response type was ANSWER. */
rrset = reply_find_answer_rrset(&iq->qchase, qstate->return_msg->rep);
if(rrset) {
int additions = 0;
/* if CNAMEs have been followed - add new NS to delegpt. */
/* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */
if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
rrset->rk.dname_len)) {
/* if dpns->lame then set newcname ns lame too */
if(!delegpt_add_ns(foriq->dp, forq->region,
rrset->rk.dname, dpns->lame))
if(!delegpt_add_ns(foriq->dp, forq->region,
rrset->rk.dname, dpns->lame, dpns->tls_auth_name,
dpns->port))
log_err("out of memory adding cnamed-ns");
}
/* if dpns->lame then set the address(es) lame too */

View File

@ -55,6 +55,7 @@
#include "util/config_file.h"
#include "sldns/parseutil.h"
#include "sldns/wire2str.h"
#include "sldns/str2wire.h"
#include <fcntl.h>
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
@ -479,6 +480,42 @@ int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
return ipstrtoaddr(str, port, addr, addrlen);
}
uint8_t* authextstrtodname(char* str, int* port, char** auth_name)
{
char* s;
uint8_t* dname;
size_t dname_len;
*port = UNBOUND_DNS_PORT;
*auth_name = NULL;
if((s=strchr(str, '@'))) {
char* hash = strchr(s+1, '#');
if(hash) {
*auth_name = hash+1;
} else {
*auth_name = NULL;
}
*port = atoi(s+1);
if(*port == 0) {
if(!hash && strcmp(s+1,"0")!=0)
return 0;
if(hash && strncmp(s+1,"0#",2)!=0)
return 0;
}
*s = 0;
dname = sldns_str2wire_dname(str, &dname_len);
*s = '@';
} else if((s=strchr(str, '#'))) {
*port = UNBOUND_DNS_OVER_TLS_PORT;
*auth_name = s+1;
*s = 0;
dname = sldns_str2wire_dname(str, &dname_len);
*s = '#';
} else {
dname = sldns_str2wire_dname(str, &dname_len);
}
return dname;
}
/** store port number into sockaddr structure */
void
sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port)

View File

@ -210,17 +210,30 @@ int netblockstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
/**
* Convert address string, with "@port" appendix, to sockaddr.
* It can also have an "#tls-auth-name" appendix (after the port).
* The returned tls-auth-name string is a pointer into the input string.
* Uses DNS port by default.
* The returned auth_name string is a pointer into the input string.
* Uses DNS port by default; TLS port when a '#tls-auth-name' is configured.
* @param str: the string
* @param addr: where to store sockaddr.
* @param addrlen: length of stored sockaddr is returned.
* @param auth_name: returned pointer to tls_auth_name, or NULL if none.
* @return 0 on error.
*/
int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
socklen_t* addrlen, char** auth_name);
/**
* Convert domain string, with "@port" appendix, to dname.
* It can also have an "#tls-auth-name" appendix (after the port).
* The return port is the parsed port.
* Uses DNS port by default; TLS port when a '#tls-auth-name' is configured.
* The returned auth_name string is a pointer into the input string.
* @param str: the string
* @param port: pointer to be assigned the parsed port value.
* @param auth_name: returned pointer to tls_auth_name, or NULL if none.
* @return pointer to the dname.
*/
uint8_t* authextstrtodname(char* str, int* port, char** auth_name);
/**
* Store port number into sockaddr structure
* @param addr: sockaddr structure, ip4 or ip6.