listen_dnsport.c File Reference
#include "config.h"
#include <sys/time.h>
#include <limits.h>
#include <ctype.h>
#include "services/listen_dnsport.h"
#include "services/outside_network.h"
#include "util/netevent.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
#include "sldns/sbuffer.h"
#include "sldns/parseutil.h"
#include "services/mesh.h"
#include "util/fptr_wlist.h"
#include "util/locks.h"
#include <fcntl.h>

Macros

#define TCP_BACKLOG   256
 number of queued TCP connections for listen()
 

Functions

static void verbose_print_addr (struct addrinfo *addr)
 Debug print of the getaddrinfo returned address. More...
 
void verbose_print_unbound_socket (struct unbound_socket *ub_sock)
 for debug and profiling purposes only More...
 
int create_udp_sock (int family, int socktype, struct sockaddr *addr, socklen_t addrlen, int v6only, int *inuse, int *noproto, int rcv, int snd, int listen, int *reuseport, int transparent, int freebind, int use_systemd, int dscp)
 Create and bind nonblocking UDP socket. More...
 
int create_tcp_accept_sock (struct addrinfo *addr, int v6only, int *noproto, int *reuseport, int transparent, int mss, int nodelay, int freebind, int use_systemd, int dscp)
 Create and bind TCP listening socket. More...
 
char * set_ip_dscp (int socket, int addrfamily, int dscp)
 
int create_local_accept_sock (const char *path, int *noproto, int use_systemd)
 Create and bind local listening socket. More...
 
static int make_sock (int stype, const char *ifname, const char *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)
 Create socket from getaddrinfo results.
 
static int make_sock_port (int stype, const char *ifname, const char *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)
 make socket and first see if ifname contains port override info
 
static int port_insert (struct listen_port **list, int s, enum listen_type ftype, struct unbound_socket *ub_sock)
 Add port to open ports list. More...
 
static int set_recvpktinfo (int s, int family)
 set fd to receive source address packet info
 
static int if_is_ssl (const char *ifname, const char *port, int ssl_port, struct config_strlist *tls_additional_port)
 see if interface is ssl, its port number == the ssl port number
 
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, size_t rcv, size_t snd, int ssl_port, struct config_strlist *tls_additional_port, int https_port, int *reuseport, int transparent, int tcp_mss, int freebind, int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp)
 Helper for ports_open. More...
 
static int listen_cp_insert (struct comm_point *c, struct listen_dnsport *front)
 Add items to commpoint list in front. More...
 
void listen_setup_locks (void)
 setup the locks for the listen ports
 
void listen_desetup_locks (void)
 desetup the locks for the listen ports
 
struct listen_dnsportlisten_create (struct comm_base *base, struct listen_port *ports, size_t bufsize, int tcp_accept_count, int tcp_idle_timeout, int harden_large_queries, uint32_t http_max_streams, char *http_endpoint, int http_notls, struct tcl_list *tcp_conn_limit, void *sslctx, struct dt_env *dtenv, comm_point_callback_type *cb, void *cb_arg)
 Create commpoints with for this thread for the shared ports. More...
 
void listen_list_delete (struct listen_list *list)
 delete listen_list of commpoints. More...
 
void listen_delete (struct listen_dnsport *front)
 delete the listening structure More...
 
int resolve_interface_names (char **ifs, int num_ifs, struct config_strlist *list, char ***resif, int *num_resif)
 Resolve interface names in config and store result IP addresses. More...
 
struct listen_portlistening_ports_open (struct config_file *cfg, char **ifs, int num_ifs, int *reuseport)
 Create shared listening ports Getaddrinfo, create socket, bind and listen to zero or more interfaces for IP4 and/or IP6, for UDP and/or TCP. More...
 
void listening_ports_free (struct listen_port *list)
 Close and delete the (list of) listening ports.
 
size_t listen_get_mem (struct listen_dnsport *listen)
 get memory size used by the listening structs More...
 
void listen_stop_accept (struct listen_dnsport *listen)
 stop accept handlers for TCP (until enabled again) More...
 
void listen_start_accept (struct listen_dnsport *listen)
 start accept handlers for TCP (was stopped before) More...
 
struct tcp_req_infotcp_req_info_create (struct sldns_buffer *spoolbuf)
 Create tcp request info structure that keeps track of open requests on the TCP channel that are resolved at the same time, and the pending results that have to get written back to that client. More...
 
void tcp_req_info_delete (struct tcp_req_info *req)
 Delete tcp request structure. More...
 
void tcp_req_info_clear (struct tcp_req_info *req)
 Clear tcp request structure. More...
 
void tcp_req_info_remove_mesh_state (struct tcp_req_info *req, struct mesh_state *m)
 Remove mesh state entry from list in tcp_req_info. More...
 
static void tcp_req_info_setup_listen (struct tcp_req_info *req)
 setup listening for read or write
 
static struct tcp_req_done_itemtcp_req_info_pop_done (struct tcp_req_info *req)
 remove first item from list of pending results
 
static void tcp_req_info_start_write_buf (struct tcp_req_info *req, uint8_t *buf, size_t len)
 Send given buffer and setup to write.
 
static void tcp_req_pickup_next_result (struct tcp_req_info *req)
 pick up the next result and start writing it to the channel
 
int tcp_req_info_handle_read_close (struct tcp_req_info *req)
 the read channel has closed More...
 
void tcp_req_info_handle_writedone (struct tcp_req_info *req)
 Handle write done of the last result packet. More...
 
void tcp_req_info_handle_readdone (struct tcp_req_info *req)
 Handle read done of a new request from the client. More...
 
int tcp_req_info_add_meshstate (struct tcp_req_info *req, struct mesh_area *mesh, struct mesh_state *m)
 Add mesh state to the tcp req list of open requests. More...
 
static int tcp_req_info_add_result (struct tcp_req_info *req, uint8_t *buf, size_t len)
 Add a result to the result list. More...
 
void tcp_req_info_send_reply (struct tcp_req_info *req)
 Send reply on tcp simultaneous answer channel. More...
 
size_t tcp_req_info_get_stream_buffer_size (void)
 get the size of currently used tcp stream wait buffers (in bytes)
 
size_t http2_get_query_buffer_size (void)
 get the size of currently used HTTP2 query buffers (in bytes)
 
size_t http2_get_response_buffer_size (void)
 get the size of currently used HTTP2 response buffers (in bytes)
 
int http2_submit_dns_response (void *ATTR_UNUSED(v))
 

Variables

static lock_basic_type stream_wait_count_lock
 lock on the counter of stream buffer memory
 
static lock_basic_type http2_query_buffer_count_lock
 lock on the counter of HTTP2 query buffer memory
 
static lock_basic_type http2_response_buffer_count_lock
 lock on the counter of HTTP2 response buffer memory
 
static size_t stream_wait_count = 0
 size (in bytes) of stream wait buffers
 
static int stream_wait_lock_inited = 0
 is the lock initialised for stream wait buffers
 
static size_t http2_query_buffer_count = 0
 size (in bytes) of HTTP2 query buffers
 
static int http2_query_buffer_lock_inited = 0
 is the lock initialised for HTTP2 query buffers
 
static size_t http2_response_buffer_count = 0
 size (in bytes) of HTTP2 response buffers
 
static int http2_response_buffer_lock_inited = 0
 is the lock initialised for HTTP2 response buffers
 

Detailed Description

This file has functions to get queries from clients.

Function Documentation

◆ verbose_print_addr()

static void verbose_print_addr ( struct addrinfo *  addr)
static

Debug print of the getaddrinfo returned address.

Parameters
addrthe address returned.

References VERB_ALGO, verbose(), and verbosity.

Referenced by create_tcp_accept_sock(), make_sock(), and verbose_print_unbound_socket().

◆ verbose_print_unbound_socket()

void verbose_print_unbound_socket ( struct unbound_socket ub_sock)

for debug and profiling purposes only

Parameters
ub_sockthe structure containing created socket info we want to print or log for

References unbound_socket::addr, unbound_socket::fam, log_info(), unbound_socket::s, VERB_ALGO, verbose_print_addr(), and verbosity.

◆ create_udp_sock()

int create_udp_sock ( int  family,
int  socktype,
struct sockaddr *  addr,
socklen_t  addrlen,
int  v6only,
int *  inuse,
int *  noproto,
int  rcv,
int  snd,
int  listen,
int *  reuseport,
int  transparent,
int  freebind,
int  use_systemd,
int  dscp 
)

Create and bind nonblocking UDP socket.

Parameters
familyfor socket call.
socktypefor socket call.
addrfor bind call.
addrlenfor bind call.
v6onlyif enabled, IP6 sockets get IP6ONLY option set. if enabled with value 2 IP6ONLY option is disabled.
inuseon error, this is set true if the port was in use.
noprotoon error, this is set true if cause is that the IPv6 proto (family) is not available.
rcvset size on rcvbuf with socket option, if 0 it is not set.
sndset size on sndbuf with socket option, if 0 it is not set.
listenif true, this is a listening UDP port, eg port 53, and set SO_REUSEADDR on it.
reuseportif nonNULL and true, try to set SO_REUSEPORT on listening UDP port. Set to false on return if it failed to do so.
transparentset IP_TRANSPARENT socket option.
freebindset IP_FREEBIND socket option.
use_systemdif true, fetch sockets from systemd.
dscpDSCP to use.
Returns
: the socket. -1 on error.

References log_err(), log_warn(), sock_close(), sock_strerror(), and verbosity.

Referenced by fd_for_dest(), and make_sock().

◆ create_tcp_accept_sock()

int create_tcp_accept_sock ( struct addrinfo *  addr,
int  v6only,
int *  noproto,
int *  reuseport,
int  transparent,
int  mss,
int  nodelay,
int  freebind,
int  use_systemd,
int  dscp 
)

Create and bind TCP listening socket.

Parameters
addraddress info ready to make socket.
v6onlyenable ip6 only flag on ip6 sockets.
noprotoif error caused by lack of protocol support.
reuseportif nonNULL and true, try to set SO_REUSEPORT on listening UDP port. Set to false on return if it failed to do so.
transparentset IP_TRANSPARENT socket option.
mssmaximum segment size of the socket. if zero, leaves the default.
nodelayif true set TCP_NODELAY and TCP_QUICKACK socket options.
freebindset IP_FREEBIND socket option.
use_systemdif true, fetch sockets from systemd.
dscpDSCP to use.
Returns
: the socket. -1 on error.

References log_err(), log_warn(), sock_close(), sock_strerror(), VERB_ALGO, verbose(), verbose_print_addr(), and verbosity.

Referenced by add_open(), and make_sock().

◆ create_local_accept_sock()

int create_local_accept_sock ( const char *  path,
int *  noproto,
int  use_systemd 
)

Create and bind local listening socket.

Parameters
pathpath to the socket.
noprotoon error, this is set true if cause is that local sockets are not supported.
use_systemdif true, fetch sockets from systemd.
Returns
: the socket. -1 on error.

References fd_set_nonblock(), log_err(), sock_close(), TCP_BACKLOG, VERB_ALGO, and verbose().

Referenced by add_open(), and tap_socket_setup().

◆ port_insert()

static int port_insert ( struct listen_port **  list,
int  s,
enum listen_type  ftype,
struct unbound_socket ub_sock 
)
static

Add port to open ports list.

Parameters
listlist head. changed.
sfd.
ftypeif fd is UDP.
ub_socksocket with address.
Returns
false on failure. list in unchanged then.

References listen_port::fd, listen_port::ftype, listen_port::next, and listen_port::socket.

Referenced by ports_create_if().

◆ ports_create_if()

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,
size_t  rcv,
size_t  snd,
int  ssl_port,
struct config_strlist tls_additional_port,
int  https_port,
int *  reuseport,
int  transparent,
int  tcp_mss,
int  freebind,
int  http2_nodelay,
int  use_systemd,
int  dnscrypt_port,
int  dscp 
)
static

Helper for ports_open.

Creates one interface (or NULL for default).

Parameters
ifnameThe interface ip address.
do_autouse automatic interface detection. If enabled, then ifname must be the wildcard name.
do_udpif udp should be used.
do_tcpif tcp should be used.
hintsfor getaddrinfo. family and flags have to be set by caller.
portPort number to use (as string).
listlist of open ports, appended to, changed to point to list head.
rcvreceive buffer size for UDP
sndsend buffer size for UDP
ssl_portssl service port number
tls_additional_portlist of additional ssl service port numbers.
https_portDoH service port number
reuseporttry to set SO_REUSEPORT if nonNULL and true. set to false on exit if reuseport failed due to no kernel support.
transparentset IP_TRANSPARENT socket option.
tcp_mssmaximum segment size of tcp socket. default if zero.
freebindset IP_FREEBIND socket option.
http2_nodelayset TCP_NODELAY on HTTP/2 connection
use_systemdif true, fetch sockets from systemd.
dnscrypt_portdnscrypt service port number
dscpDSCP to use.
Returns
: returns false on error.

References unbound_socket::addr, if_is_https(), if_is_ssl(), listen_type_http, listen_type_ssl, listen_type_tcp, listen_type_tcp_dnscrypt, listen_type_udp, listen_type_udp_dnscrypt, listen_type_udpancil, listen_type_udpancil_dnscrypt, log_warn(), make_sock_port(), port_insert(), unbound_socket::s, set_recvpktinfo(), sock_close(), VERB_ALGO, and verbose().

Referenced by listening_ports_open().

◆ listen_cp_insert()

static int listen_cp_insert ( struct comm_point c,
struct listen_dnsport front 
)
static

Add items to commpoint list in front.

Parameters
ccommpoint to add.
frontlisten struct.
Returns
: false on failure.

References listen_list::com, listen_dnsport::cps, and listen_list::next.

◆ listen_create()

struct listen_dnsport* listen_create ( struct comm_base base,
struct listen_port ports,
size_t  bufsize,
int  tcp_accept_count,
int  tcp_idle_timeout,
int  harden_large_queries,
uint32_t  http_max_streams,
char *  http_endpoint,
int  http_notls,
struct tcl_list tcp_conn_limit,
void *  sslctx,
struct dt_env *  dtenv,
comm_point_callback_type cb,
void *  cb_arg 
)

Create commpoints with for this thread for the shared ports.

Parameters
basethe comm_base that provides event functionality. for default all ifs.
portsthe list of shared ports.
bufsizesize of datagram buffer.
tcp_accept_countmax number of simultaneous TCP connections from clients.
tcp_idle_timeoutidle timeout for TCP connections in msec.
harden_large_querieswhether query size should be limited.
http_max_streamsmaximum number of HTTP/2 streams per connection.
http_endpointHTTP endpoint to service queries on
http_notlsno TLS for http downstream
tcp_conn_limitTCP connection limit info.
sslctxnonNULL if ssl context.
dtenvnonNULL if dnstap enabled.
cbcallback function when a request arrives. It is passed the packet and user argument. Return true to send a reply.
cb_arguser data argument for callback function.
Returns
: the malloced listening structure, ready for use. NULL on error.

References listen_dnsport::cps, listen_port::ftype, listen_type_udp, listen_type_udp_dnscrypt, sldns_buffer_new(), and listen_dnsport::udp_buff.

◆ listen_list_delete()

void listen_list_delete ( struct listen_list list)

delete listen_list of commpoints.

Calls commpointdelete() on items. This may close the fds or not depending on flags.

Parameters
listto delete.

References listen_list::com, comm_point_delete(), and listen_list::next.

Referenced by daemon_remote_clear(), and listen_delete().

◆ listen_delete()

void listen_delete ( struct listen_dnsport listen)

delete the listening structure

Parameters
listenlistening structure.

Referenced by worker_delete().

◆ resolve_interface_names()

int resolve_interface_names ( char **  ifs,
int  num_ifs,
struct config_strlist list,
char ***  resif,
int *  num_resif 
)

Resolve interface names in config and store result IP addresses.

Parameters
ifsarray of interfaces. The list of interface names, if not NULL.
num_ifslength of ifs array.
listif not NULL, this is used as the list of interface names.
resifstring array (malloced array of malloced strings) with result. NULL if cfg has none.
num_resiflength of resif. Zero if cfg has zero num_ifs.
Returns
0 on failure.

References config_del_strarray(), log_err(), config_strlist::next, and config_strlist::str.

Referenced by contact_server(), daemon_open_shared_ports(), and daemon_remote_open_ports().

◆ listening_ports_open()

struct listen_port* listening_ports_open ( struct config_file cfg,
char **  ifs,
int  num_ifs,
int *  reuseport 
)

Create shared listening ports Getaddrinfo, create socket, bind and listen to zero or more interfaces for IP4 and/or IP6, for UDP and/or TCP.

On the given port number. It creates the sockets.

Parameters
cfgsettings on what ports to open.
ifsinterfaces to open, array of IP addresses, "ip[@port]".
num_ifslength of ifs.
reuseportset to true if you want reuseport, or NULL to not have it, set to false on exit if reuseport failed to apply (because of no kernel support).
Returns
: linked list of ports or NULL on error.

References config_file::dnscrypt_port, config_file::do_ip4, config_file::do_ip6, config_file::do_tcp, config_file::do_udp, config_file::http_nodelay, config_file::https_port, config_file::if_automatic, config_file::if_automatic_ports, config_file::incoming_num_tcp, config_file::ip_dscp, config_file::ip_freebind, config_file::ip_transparent, listening_ports_free(), log_err(), config_file::port, ports_create_if(), config_file::so_rcvbuf, config_file::so_sndbuf, config_file::ssl_port, str_is_ip6(), config_file::tcp_mss, config_file::tls_additional_port, and config_file::use_systemd.

Referenced by daemon_open_shared_ports().

◆ listen_get_mem()

size_t listen_get_mem ( struct listen_dnsport listen)

get memory size used by the listening structs

Parameters
listenlistening structure.
Returns
: size in bytes.

References listen_dnsport::base, listen_dnsport::cps, listen_list::next, sldns_buffer_capacity(), and listen_dnsport::udp_buff.

◆ listen_stop_accept()

void listen_stop_accept ( struct listen_dnsport listen)

stop accept handlers for TCP (until enabled again)

Parameters
listenlistening structure.

References listen_list::com, listen_dnsport::cps, listen_list::next, comm_point::tcp_free, and comm_point::type.

Referenced by worker_stop_accept().

◆ listen_start_accept()

void listen_start_accept ( struct listen_dnsport listen)

start accept handlers for TCP (was stopped before)

Parameters
listenlistening structure.

References listen_list::com, listen_dnsport::cps, listen_list::next, comm_point::tcp_free, and comm_point::type.

Referenced by worker_start_accept().

◆ tcp_req_info_create()

struct tcp_req_info* tcp_req_info_create ( struct sldns_buffer spoolbuf)

Create tcp request info structure that keeps track of open requests on the TCP channel that are resolved at the same time, and the pending results that have to get written back to that client.

Parameters
spoolbufshared buffer
Returns
new structure or NULL on alloc failure.

References log_err(), and tcp_req_info::spool_buffer.

Referenced by comm_point_create_tcp_handler().

◆ tcp_req_info_delete()

void tcp_req_info_delete ( struct tcp_req_info req)

Delete tcp request structure.

Called by owning commpoint. Removes mesh entry references and stored results from the lists.

Parameters
reqthe tcp request info

References tcp_req_info_clear().

Referenced by comm_point_create_tcp_handler(), and comm_point_delete().

◆ tcp_req_info_clear()

◆ tcp_req_info_remove_mesh_state()

void tcp_req_info_remove_mesh_state ( struct tcp_req_info req,
struct mesh_state m 
)

Remove mesh state entry from list in tcp_req_info.

caller has to manage the mesh state reply entry in the mesh state.

Parameters
reqthe tcp req info that has the entry removed from the list.
mthe state removed from the list.

References tcp_req_open_item::mesh_state, tcp_req_open_item::next, tcp_req_info::num_open_req, and tcp_req_info::open_req_list.

◆ tcp_req_info_handle_read_close()

int tcp_req_info_handle_read_close ( struct tcp_req_info req)

the read channel has closed

Parameters
reqrequest. remaining queries are looked up and answered.
Returns
zero if nothing to do, just close the tcp.

References tcp_req_info::cp, comm_point::fd, tcp_req_info::num_done_req, tcp_req_info::num_open_req, tcp_req_info::read_is_closed, comm_point::tcp_byte_count, tcp_req_info_setup_listen(), tcp_req_pickup_next_result(), VERB_ALGO, and verbose().

Referenced by comm_point_tcp_handle_read(), and ssl_handle_read().

◆ tcp_req_info_handle_writedone()

void tcp_req_info_handle_writedone ( struct tcp_req_info req)

◆ tcp_req_info_handle_readdone()

◆ tcp_req_info_add_meshstate()

int tcp_req_info_add_meshstate ( struct tcp_req_info req,
struct mesh_area mesh,
struct mesh_state m 
)

Add mesh state to the tcp req list of open requests.

So the comm_reply can be removed off the mesh reply list when the tcp channel has to be closed (for other reasons then that that request was done, eg. channel closed by client or some format error).

Parameters
reqtcp req info structure. It keeps track of the simultaneous requests and results on a tcp (or TLS) channel.
meshmesh area for the state.
mmesh state to add.
Returns
0 on failure (malloc failure).

References log_assert, tcp_req_open_item::mesh, tcp_req_open_item::mesh_state, tcp_req_open_item::next, tcp_req_info::num_open_req, and tcp_req_info::open_req_list.

◆ tcp_req_info_add_result()

static int tcp_req_info_add_result ( struct tcp_req_info req,
uint8_t *  buf,
size_t  len 
)
static

◆ tcp_req_info_send_reply()