* Create socket from getaddrinfo results
*/
static int
-make_sock(int stype, const char* ifname, const char* port,
+make_sock(int stype, const char* ifname, int port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
int use_systemd, int dscp, struct unbound_socket* ub_sock,
{
struct addrinfo *res = NULL;
int r, s, inuse, noproto;
+ char portbuf[32];
+ snprintf(portbuf, sizeof(portbuf), "%d", port);
hints->ai_socktype = stype;
*noip6 = 0;
- if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) {
+ if((r=getaddrinfo(ifname, portbuf, hints, &res)) != 0 || !res) {
#ifdef USE_WINSOCK
if(r == EAI_NONAME && hints->ai_family == AF_INET6){
*noip6 = 1; /* 'Host not found' for IP6 on winXP */
}
#endif
log_err("node %s:%s getaddrinfo: %s %s",
- ifname?ifname:"default", port, gai_strerror(r),
+ ifname?ifname:"default", portbuf, gai_strerror(r),
#ifdef EAI_SYSTEM
(r==EAI_SYSTEM?(char*)strerror(errno):"")
#else
/** make socket and first see if ifname contains port override info */
static int
-make_sock_port(int stype, const char* ifname, const char* port,
+make_sock_port(int stype, const char* ifname, int port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
int use_systemd, int dscp, struct unbound_socket* ub_sock,
char* s = strchr(ifname, '@');
if(s) {
/* override port with ifspec@port */
- char p[16];
+ int port;
char newif[128];
if((size_t)(s-ifname) >= sizeof(newif)) {
log_err("ifname too long: %s", ifname);
*noip6 = 0;
return -1;
}
- if(strlen(s+1) >= sizeof(p)) {
- log_err("portnumber too long: %s", ifname);
+ port = atoi(s+1);
+ if(port < 0 || 0 == port || port > 65535) {
+ log_err("invalid portnumber in interface: %s", ifname);
*noip6 = 0;
return -1;
}
(void)strlcpy(newif, ifname, sizeof(newif));
newif[s-ifname] = 0;
- (void)strlcpy(p, s+1, sizeof(p));
- p[strlen(s+1)]=0;
- return make_sock(stype, newif, p, hints, v6only, noip6, rcv,
+ return make_sock(stype, newif, port, hints, v6only, noip6, rcv,
snd, reuseport, transparent, tcp_mss, nodelay, freebind,
use_systemd, dscp, ub_sock, additional);
}
* @param do_udp: if udp should be used.
* @param do_tcp: if tcp should be used.
* @param hints: for getaddrinfo. family and flags have to be set by caller.
- * @param port: Port number to use (as string).
+ * @param port: Port number to use.
* @param list: list of open ports, appended to, changed to point to list head.
* @param rcv: receive buffer size for UDP
* @param snd: send buffer size for UDP
*/
static int
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
- struct addrinfo *hints, const char* port, struct listen_port** list,
+ struct addrinfo *hints, int port, struct listen_port** list,
size_t rcv, size_t snd, int ssl_port,
struct config_strlist* tls_additional_port, int https_port,
struct config_strlist* proxy_protocol_port,
int is_https = if_is_https(ifname, port, https_port);
int is_dnscrypt = if_is_dnscrypt(ifname, port, dnscrypt_port);
int is_pp2 = if_is_pp2(ifname, port, proxy_protocol_port);
+ int is_doq = if_is_quic(ifname, port, quic_port);
/* Always set TCP_NODELAY on TLS connection as it speeds up the TLS
* handshake. DoH had already such option so we respect it.
* Otherwise the server waits before sending more handshake data for
* client waits for more data before ACKing (delayed ACK). */
int nodelay = is_https?http2_nodelay:is_ssl;
struct unbound_socket* ub_sock;
- int is_doq = if_is_quic(ifname, port, quic_port);
const char* add = NULL;
if(!do_udp && !do_tcp)
} else if(is_doq) {
udp_port_type = listen_type_doq;
add = "doq";
- if(((strchr(ifname, '@') &&
- atoi(strchr(ifname, '@')+1) == 53) ||
- (!strchr(ifname, '@') && atoi(port) == 53))) {
- log_err("DNS over QUIC is not allowed on "
- "port 53. Port 53 is for DNS "
- "datagrams. Error for "
- "interface '%s'.", ifname);
+ if(if_listens_on(ifname, port, 53, NULL)) {
+ log_err("DNS over QUIC is strictly not "
+ "allowed on port 53 as per RFC 9250. "
+ "Port 53 is for DNS datagrams. Error "
+ "for interface '%s'.", ifname);
free(ub_sock->addr);
free(ub_sock);
return 0;
}
}
if(do_tcp) {
- int is_ssl = if_is_ssl(ifname, port, ssl_port,
- tls_additional_port);
enum listen_type port_type;
ub_sock = calloc(1, sizeof(struct unbound_socket));
if(!ub_sock)
struct addrinfo hints;
int i, do_ip4, do_ip6;
int do_tcp, do_auto;
- char portbuf[32];
- snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
do_ip4 = cfg->do_ip4;
do_ip6 = cfg->do_ip6;
do_tcp = cfg->do_tcp;
return NULL;
}
now = after;
- snprintf(portbuf, sizeof(portbuf), "%d", extraport);
if(do_ip6) {
hints.ai_family = AF_INET6;
if(!ports_create_if("::0",
do_auto, cfg->do_udp, do_tcp,
- &hints, portbuf, &list,
+ &hints, extraport, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port,
hints.ai_family = AF_INET;
if(!ports_create_if("0.0.0.0",
do_auto, cfg->do_udp, do_tcp,
- &hints, portbuf, &list,
+ &hints, extraport, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port,
hints.ai_family = AF_INET6;
if(!ports_create_if(do_auto?"::0":"::1",
do_auto, cfg->do_udp, do_tcp,
- &hints, portbuf, &list,
+ &hints, cfg->port, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, cfg->proxy_protocol_port,
hints.ai_family = AF_INET;
if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
do_auto, cfg->do_udp, do_tcp,
- &hints, portbuf, &list,
+ &hints, cfg->port, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, cfg->proxy_protocol_port,
continue;
hints.ai_family = AF_INET6;
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
- do_tcp, &hints, portbuf, &list,
+ do_tcp, &hints, cfg->port, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, cfg->proxy_protocol_port,
continue;
hints.ai_family = AF_INET;
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
- do_tcp, &hints, portbuf, &list,
+ do_tcp, &hints, cfg->port, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, cfg->proxy_protocol_port,
return (cfg->control_ifs.first->str[0] != '/');
}
-/** see if interface is https, its port number == the https port number */
int
-if_is_https(const char* ifname, const char* port, int https_port)
+if_listens_on(const char* ifname, int default_port, int port,
+ struct config_strlist* additional_ports)
{
+ struct config_strlist* s;
char* p = strchr(ifname, '@');
- if(!p && atoi(port) == https_port)
- return 1;
- if(p && atoi(p+1) == https_port)
- return 1;
- return 0;
-}
+ int if_port;
+ if(p) if_port = atoi(p+1);
+ else if_port = default_port;
-/** see if config contains https turned on */
-int cfg_has_https(struct config_file* cfg)
-{
- int i;
- char portbuf[32];
- snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
- for(i = 0; i<cfg->num_ifs; i++) {
- if(if_is_https(cfg->ifs[i], portbuf, cfg->https_port))
- return 1;
+ if(port && if_port == port) return 1;
+
+ for(s = additional_ports; s; s = s->next) {
+ if(if_port == atoi(s->str)) return 1;
}
return 0;
}
-/** see if interface is ssl, its port number == the ssl port number */
int
-if_is_ssl(const char* ifname, const char* port, int ssl_port,
+if_is_ssl(const char* ifname, int default_port, int ssl_port,
struct config_strlist* tls_additional_port)
{
- struct config_strlist* s;
- char* p = strchr(ifname, '@');
- if(!p && atoi(port) == ssl_port)
- return 1;
- if(p && atoi(p+1) == ssl_port)
- return 1;
- for(s = tls_additional_port; s; s = s->next) {
- if(p && atoi(p+1) == atoi(s->str))
- return 1;
- if(!p && atoi(port) == atoi(s->str))
- return 1;
- }
- return 0;
+ return if_listens_on(ifname, default_port, ssl_port,
+ tls_additional_port);
}
-/** see if interface is PROXYv2, its port number == the proxy port number */
int
-if_is_pp2(const char* ifname, const char* port,
+if_is_pp2(const char* ifname, int default_port,
struct config_strlist* proxy_protocol_port)
{
- struct config_strlist* s;
- char* p = strchr(ifname, '@');
- for(s = proxy_protocol_port; s; s = s->next) {
- if(p && atoi(p+1) == atoi(s->str))
- return 1;
- if(!p && atoi(port) == atoi(s->str))
- return 1;
- }
- return 0;
+ return if_listens_on(ifname, default_port, 0, proxy_protocol_port);
}
-/** see if interface is DNSCRYPT, its port number == the dnscrypt port number */
int
-if_is_dnscrypt(const char* ifname, const char* port, int dnscrypt_port)
+if_is_https(const char* ifname, int default_port, int https_port)
+{
+ return if_listens_on(ifname, default_port, https_port, NULL);
+}
+
+int
+if_is_dnscrypt(const char* ifname, int default_port, int dnscrypt_port)
{
#ifdef USE_DNSCRYPT
- return ((strchr(ifname, '@') &&
- atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
- (!strchr(ifname, '@') && atoi(port) == dnscrypt_port));
+ return if_listens_on(ifname, default_port, dnscrypt_port, NULL);
#else
(void)ifname;
(void)port;
#endif
}
-/** see if interface is quic, its port number == the quic port number */
int
-if_is_quic(const char* ifname, const char* port, int quic_port)
+if_is_quic(const char* ifname, int default_port, int quic_port)
{
-#ifndef HAVE_NGTCP2
+#ifdef HAVE_NGTCP2
+ return if_listens_on(ifname, default_port, quic_port, NULL);
+#else
(void)ifname;
(void)port;
(void)quic_port;
return 0;
-#else
- char* p = strchr(ifname, '@');
- if(!p && atoi(port) == quic_port)
- return 1;
- if(p && atoi(p+1) == quic_port)
- return 1;
- return 0;
#endif
}
-/** see if config contains quic turned on */
int
-cfg_has_quic(struct config_file* cfg)
+cfg_has_https(struct config_file* cfg)
{
-#ifndef HAVE_NGTCP2
- (void)cfg;
+ int i;
+ for(i = 0; i<cfg->num_ifs; i++) {
+ if(if_is_https(cfg->ifs[i], cfg->port, cfg->https_port))
+ return 1;
+ }
return 0;
-#else
+}
+
+int
+cfg_has_quic(struct config_file* cfg)
+{
+#ifdef HAVE_NGTCP2
int i;
- char portbuf[32];
- snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
for(i = 0; i<cfg->num_ifs; i++) {
- if(if_is_quic(cfg->ifs[i], portbuf, cfg->quic_port))
+ if(if_is_quic(cfg->ifs[i], cfg->port, cfg->quic_port))
return 1;
}
return 0;
+#else
+ (void)cfg;
+ return 0;
#endif
}
/** debug option for unit tests. */
extern int fake_dsa, fake_sha1;
-/** see if interface is https, its port number == the https port number */
-int if_is_https(const char* ifname, const char* port, int https_port);
-
-/**
- * Return true if the config contains settings that enable https.
- * @param cfg: config information.
- * @return true if https ports are used for server.
+/** Return true if interface will listen to specific port(s).
+ * @param ifname: the interface as configured in the configuration file.
+ * @param default_port: the default port to use as the interface port if ifname
+ * does not include a port via the '@' notation.
+ * @param port: port to check for, if 0 it will not be checked.
+ * @param additional_ports: additional configured ports, if any (nonNULL) to
+ * be checked against.
+ * @return true if one of (port, additional_ports) matches the interface port.
*/
-int cfg_has_https(struct config_file* cfg);
+int if_listens_on(const char* ifname, int default_port, int port,
+ struct config_strlist* additional_ports);
+
+/** see if interface will listen on https;
+ * its port number == the https port number */
+int if_is_https(const char* ifname, int default_port, int https_port);
-/** see if interface is ssl, its port number == the ssl port number */
-int if_is_ssl(const char* ifname, const char* port, int ssl_port,
+/** see if interface will listen on ssl;
+ * its port number == the ssl port number or any of the additional ports */
+int if_is_ssl(const char* ifname, int default_port, int ssl_port,
struct config_strlist* tls_additional_port);
-/** see if interface is PROXYv2, its port number == the proxy port number */
-int if_is_pp2(const char* ifname, const char* port,
+/** see if interface will listen on PROXYv2;
+ * its port number == any of the proxy ports number */
+int if_is_pp2(const char* ifname, int default_port,
struct config_strlist* proxy_protocol_port);
-/** see if interface is DNSCRYPT, its port number == the dnscrypt port number */
-int if_is_dnscrypt(const char* ifname, const char* port, int dnscrypt_port);
+/** see if interface will listen on DNSCRYPT;
+ * its port number == the dnscrypt port number */
+int if_is_dnscrypt(const char* ifname, int default_port, int dnscrypt_port);
-/** see if interface is quic, its port number == the quic port number */
-int if_is_quic(const char* ifname, const char* port, int quic_port);
+/** see if interface will listen on quic;
+ * its port number == the quic port number */
+int if_is_quic(const char* ifname, int default_port, int quic_port);
+
+/**
+ * Return true if the config contains settings that enable https.
+ * @param cfg: config information.
+ * @return true if https ports are used for server.
+ */
+int cfg_has_https(struct config_file* cfg);
/**
* Return true if the config contains settings that enable quic.