From bdfa65c6ab91f9569a8c0f3371249a40a0a33c9b Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:00:51 +0100 Subject: [PATCH 01/19] Import the patches from the files in the tarball in issue #365 https://github.com/NLnetLabs/unbound/files/5659923/patches.tar.gz from iruzanov. The merge conflicts are fixed, but no changes are made to the patched code. --- daemon/worker.c | 36 ++++++++++--- dnstap/dnstap.c | 104 ++++++++++++++++++++++++++----------- dnstap/dnstap.h | 12 ++++- services/listen_dnsport.c | 64 +++++++++++++++++------ services/listen_dnsport.h | 21 ++++++++ services/outside_network.c | 70 ++++++++++++++++++++----- util/net_help.c | 36 ++++++++++++- util/net_help.h | 10 ++++ util/netevent.c | 85 +++++++++++++++++++++--------- util/netevent.h | 10 +++- 10 files changed, 353 insertions(+), 95 deletions(-) diff --git a/daemon/worker.c b/daemon/worker.c index 76c4bb5b1..36d4208f1 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1159,9 +1159,21 @@ worker_handle_request(struct comm_point* c, void* arg, int error, } #endif #ifdef USE_DNSTAP - if(worker->dtenv.log_client_query_messages) - dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, c->type, - c->buffer); + /* + * sending src (client)/dst (local service) addresses over DNSTAP from incoming request handler + */ + if(worker->dtenv.log_client_query_messages) { + struct sockaddr_storage* dst_addr; + if(repinfo->addr.ss_family == AF_INET) + dst_addr = mk_local_addr(&((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); + else + dst_addr = mk_local_addr(&((struct sockaddr_in6*)repinfo->c->socket->addr->ai_addr)->sin6_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); + log_addr(VERB_ALGO, "request from client", &repinfo->addr, repinfo->addrlen); + log_addr(VERB_ALGO, "to local addr", dst_addr, sizeof(dst_addr)); + dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, dst_addr, c->type, c->buffer); + if(dst_addr) + free(dst_addr); + } #endif acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr, repinfo->addrlen); @@ -1584,9 +1596,21 @@ send_reply_rc: if(is_secure_answer) worker->stats.ans_secure++; } #ifdef USE_DNSTAP - if(worker->dtenv.log_client_response_messages) - dt_msg_send_client_response(&worker->dtenv, &repinfo->addr, - c->type, c->buffer); + /* + * sending src (client)/dst (local service) addresses over DNSTAP from send_reply code label (when we serviced local zone for ex.) + */ + if(worker->dtenv.log_client_response_messages) { + struct sockaddr_storage* dst_addr; + if(repinfo->addr.ss_family == AF_INET) + dst_addr = mk_local_addr(&((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); + else + dst_addr = mk_local_addr(&((struct sockaddr_in6*)repinfo->c->socket->addr->ai_addr)->sin6_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); + log_addr(VERB_ALGO, "from local addr", dst_addr, sizeof(dst_addr)); + log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen); + dt_msg_send_client_response(&worker->dtenv, &repinfo->addr, dst_addr, c->type, c->buffer); + if(dst_addr) + free(dst_addr); + } #endif if(worker->env.cfg->log_replies) { diff --git a/dnstap/dnstap.c b/dnstap/dnstap.c index b8a321670..2ee269be3 100644 --- a/dnstap/dnstap.c +++ b/dnstap/dnstap.c @@ -302,44 +302,75 @@ dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has) static void dt_msg_fill_net(struct dt_msg *dm, - struct sockaddr_storage *ss, + struct sockaddr_storage *qs, + struct sockaddr_storage *rs, enum comm_point_type cptype, - ProtobufCBinaryData *addr, protobuf_c_boolean *has_addr, - uint32_t *port, protobuf_c_boolean *has_port) + ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr, + uint32_t *qport, protobuf_c_boolean *has_qport, + ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr, + uint32_t *rport, protobuf_c_boolean *has_rport) { - log_assert(ss->ss_family == AF_INET6 || ss->ss_family == AF_INET); - if (ss->ss_family == AF_INET6) { - struct sockaddr_in6 *s = (struct sockaddr_in6 *) ss; + log_assert(qs->ss_family == AF_INET6 || qs->ss_family == AF_INET); + if (qs->ss_family == AF_INET6) { + struct sockaddr_in6 *q = (struct sockaddr_in6 *) qs; /* socket_family */ dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6; dm->m.has_socket_family = 1; /* addr: query_address or response_address */ - addr->data = s->sin6_addr.s6_addr; - addr->len = 16; /* IPv6 */ - *has_addr = 1; + qaddr->data = q->sin6_addr.s6_addr; + qaddr->len = 16; /* IPv6 */ + *has_qaddr = 1; /* port: query_port or response_port */ - *port = ntohs(s->sin6_port); - *has_port = 1; - } else if (ss->ss_family == AF_INET) { - struct sockaddr_in *s = (struct sockaddr_in *) ss; + *qport = ntohs(q->sin6_port); + *has_qport = 1; + } else if (qs->ss_family == AF_INET) { + struct sockaddr_in *q = (struct sockaddr_in *) qs; /* socket_family */ dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET; dm->m.has_socket_family = 1; /* addr: query_address or response_address */ - addr->data = (uint8_t *) &s->sin_addr.s_addr; - addr->len = 4; /* IPv4 */ - *has_addr = 1; + qaddr->data = (uint8_t *) &q->sin_addr.s_addr; + qaddr->len = 4; /* IPv4 */ + *has_qaddr = 1; /* port: query_port or response_port */ - *port = ntohs(s->sin_port); - *has_port = 1; + *qport = ntohs(q->sin_port); + *has_qport = 1; } + /* + * This block is to fill second set of fields in DNSTAP-message defined as request_/response_ names. + * Additional responsive structure is: struct sockaddr_storage *rs + */ + if (rs->ss_family == AF_INET6) { + struct sockaddr_in6 *r = (struct sockaddr_in6 *) rs; + + /* addr: query_address or response_address */ + raddr->data = r->sin6_addr.s6_addr; + raddr->len = 16; /* IPv6 */ + *has_raddr = 1; + + /* port: query_port or response_port */ + *rport = ntohs(r->sin6_port); + *has_rport = 1; + } else if (rs->ss_family == AF_INET) { + struct sockaddr_in *r = (struct sockaddr_in *) rs; + + /* addr: query_address or response_address */ + raddr->data = (uint8_t *) &r->sin_addr.s_addr; + raddr->len = 4; /* IPv4 */ + *has_raddr = 1; + + /* port: query_port or response_port */ + *rport = ntohs(r->sin_port); + *has_rport = 1; + } + log_assert(cptype == comm_udp || cptype == comm_tcp); if (cptype == comm_udp) { /* socket_protocol */ @@ -355,6 +386,7 @@ dt_msg_fill_net(struct dt_msg *dm, void dt_msg_send_client_query(struct dt_env *env, struct sockaddr_storage *qsock, + struct sockaddr_storage *rsock, enum comm_point_type cptype, sldns_buffer *qmsg) { @@ -374,11 +406,14 @@ dt_msg_send_client_query(struct dt_env *env, /* query_message */ dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); - /* socket_family, socket_protocol, query_address, query_port */ + /* socket_family, socket_protocol, query_address, query_port, response_address, response_port */ log_assert(cptype == comm_udp || cptype == comm_tcp); - dt_msg_fill_net(&dm, qsock, cptype, + dt_msg_fill_net(&dm, qsock, rsock, cptype, &dm.m.query_address, &dm.m.has_query_address, - &dm.m.query_port, &dm.m.has_query_port); + &dm.m.query_port, &dm.m.has_query_port, + &dm.m.response_address, &dm.m.has_response_address, + &dm.m.response_port, &dm.m.has_response_port); + if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) dt_send(env, dm.buf, dm.len_buf); @@ -387,6 +422,7 @@ dt_msg_send_client_query(struct dt_env *env, void dt_msg_send_client_response(struct dt_env *env, struct sockaddr_storage *qsock, + struct sockaddr_storage *rsock, enum comm_point_type cptype, sldns_buffer *rmsg) { @@ -406,11 +442,13 @@ dt_msg_send_client_response(struct dt_env *env, /* response_message */ dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); - /* socket_family, socket_protocol, query_address, query_port */ + /* socket_family, socket_protocol, query_address, query_port, response_address, response_port */ log_assert(cptype == comm_udp || cptype == comm_tcp); - dt_msg_fill_net(&dm, qsock, cptype, + dt_msg_fill_net(&dm, qsock, rsock, cptype, &dm.m.query_address, &dm.m.has_query_address, - &dm.m.query_port, &dm.m.has_query_port); + &dm.m.query_port, &dm.m.has_query_port, + &dm.m.response_address, &dm.m.has_response_address, + &dm.m.response_port, &dm.m.has_response_port); if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) dt_send(env, dm.buf, dm.len_buf); @@ -419,6 +457,7 @@ dt_msg_send_client_response(struct dt_env *env, void dt_msg_send_outside_query(struct dt_env *env, struct sockaddr_storage *rsock, + struct sockaddr_storage *qsock, enum comm_point_type cptype, uint8_t *zone, size_t zone_len, sldns_buffer *qmsg) @@ -454,11 +493,13 @@ dt_msg_send_outside_query(struct dt_env *env, /* query_message */ dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); - /* socket_family, socket_protocol, response_address, response_port */ + /* socket_family, socket_protocol, response_address, response_port, query_address, query_port */ log_assert(cptype == comm_udp || cptype == comm_tcp); - dt_msg_fill_net(&dm, rsock, cptype, + dt_msg_fill_net(&dm, rsock, qsock, cptype, &dm.m.response_address, &dm.m.has_response_address, - &dm.m.response_port, &dm.m.has_response_port); + &dm.m.response_port, &dm.m.has_response_port, + &dm.m.query_address, &dm.m.has_query_address, + &dm.m.query_port, &dm.m.has_query_port); if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) dt_send(env, dm.buf, dm.len_buf); @@ -467,6 +508,7 @@ dt_msg_send_outside_query(struct dt_env *env, void dt_msg_send_outside_response(struct dt_env *env, struct sockaddr_storage *rsock, + struct sockaddr_storage *qsock, enum comm_point_type cptype, uint8_t *zone, size_t zone_len, uint8_t *qbuf, size_t qbuf_len, @@ -510,11 +552,13 @@ dt_msg_send_outside_response(struct dt_env *env, /* response_message */ dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); - /* socket_family, socket_protocol, response_address, response_port */ + /* socket_family, socket_protocol, response_address, response_port, query_address, query_port */ log_assert(cptype == comm_udp || cptype == comm_tcp); - dt_msg_fill_net(&dm, rsock, cptype, + dt_msg_fill_net(&dm, rsock, qsock, cptype, &dm.m.response_address, &dm.m.has_response_address, - &dm.m.response_port, &dm.m.has_response_port); + &dm.m.response_port, &dm.m.has_response_port, + &dm.m.query_address, &dm.m.has_query_address, + &dm.m.query_port, &dm.m.has_query_port); if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) dt_send(env, dm.buf, dm.len_buf); diff --git a/dnstap/dnstap.h b/dnstap/dnstap.h index 783b8c514..449fae727 100644 --- a/dnstap/dnstap.h +++ b/dnstap/dnstap.h @@ -123,12 +123,14 @@ dt_delete(struct dt_env *env); * Create and send a new dnstap "Message" event of type CLIENT_QUERY. * @param env: dnstap environment object. * @param qsock: address/port of client. + * @param rsock: local (service) address/port. * @param cptype: comm_udp or comm_tcp. * @param qmsg: query message. */ void dt_msg_send_client_query(struct dt_env *env, struct sockaddr_storage *qsock, + struct sockaddr_storage *rsock, enum comm_point_type cptype, struct sldns_buffer *qmsg); @@ -136,12 +138,14 @@ dt_msg_send_client_query(struct dt_env *env, * Create and send a new dnstap "Message" event of type CLIENT_RESPONSE. * @param env: dnstap environment object. * @param qsock: address/port of client. + * @param rsock: local (service) address/port. * @param cptype: comm_udp or comm_tcp. * @param rmsg: response message. */ void dt_msg_send_client_response(struct dt_env *env, struct sockaddr_storage *qsock, + struct sockaddr_storage *rsock, enum comm_point_type cptype, struct sldns_buffer *rmsg); @@ -150,7 +154,8 @@ dt_msg_send_client_response(struct dt_env *env, * FORWARDER_QUERY. The type used is dependent on the value of the RD bit * in the query header. * @param env: dnstap environment object. - * @param rsock: address/port of server the query is being sent to. + * @param rsock: address/port of server (upstream) the query is being sent to. + * @param qsock: address/port of server (local) the query is being sent from. * @param cptype: comm_udp or comm_tcp. * @param zone: query zone. * @param zone_len: length of zone. @@ -159,6 +164,7 @@ dt_msg_send_client_response(struct dt_env *env, void dt_msg_send_outside_query(struct dt_env *env, struct sockaddr_storage *rsock, + struct sockaddr_storage *qsock, enum comm_point_type cptype, uint8_t *zone, size_t zone_len, struct sldns_buffer *qmsg); @@ -168,7 +174,8 @@ dt_msg_send_outside_query(struct dt_env *env, * FORWARDER_RESPONSE. The type used is dependent on the value of the RD bit * in the query header. * @param env: dnstap environment object. - * @param rsock: address/port of server the response was received from. + * @param rsock: address/port of server (upstream) the response was received from. + * @param qsock: address/port of server (local) the response was received to. * @param cptype: comm_udp or comm_tcp. * @param zone: query zone. * @param zone_len: length of zone. @@ -181,6 +188,7 @@ dt_msg_send_outside_query(struct dt_env *env, void dt_msg_send_outside_response(struct dt_env *env, struct sockaddr_storage *rsock, + struct sockaddr_storage *qsock, enum comm_point_type cptype, uint8_t *zone, size_t zone_len, uint8_t *qbuf, size_t qbuf_len, diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 709c9e6ce..02d44fcba 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -133,6 +133,16 @@ verbose_print_addr(struct addrinfo *addr) } } +void +verbose_print_unbound_socket(struct unbound_socket* ub_sock) +{ + if(verbosity >= VERB_ALGO) { + log_info("listing of unbound_socket structure:"); + verbose_print_addr(ub_sock->addr); + log_info("s is: %d, fam is: %s, tcp_read_fd is: %d", ub_sock->s, ub_sock->fam == AF_INET?"AF_INET":"AF_INET6", ub_sock->tcp_read_fd); + } +} + #ifdef HAVE_SYSTEMD static int systemd_get_activated(int family, int socktype, int listen, @@ -916,7 +926,7 @@ 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) + int use_systemd, int dscp, struct unbound_socket** ub_sock) { struct addrinfo *res = NULL; int r, s, inuse, noproto; @@ -958,7 +968,12 @@ make_sock(int stype, const char* ifname, const char* port, *noip6 = 1; } } - freeaddrinfo(res); + + (*ub_sock)->addr = res; + (*ub_sock)->s = s; + (*ub_sock)->fam = hints->ai_family; + (*ub_sock)->tcp_read_fd = -1; + return s; } @@ -967,7 +982,7 @@ 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) + int use_systemd, int dscp, struct unbound_socket** ub_sock) { char* s = strchr(ifname, '@'); if(s) { @@ -990,11 +1005,11 @@ make_sock_port(int stype, const char* ifname, const char* port, p[strlen(s+1)]=0; return make_sock(stype, newif, p, hints, v6only, noip6, rcv, snd, reuseport, transparent, tcp_mss, nodelay, freebind, - use_systemd, dscp); + use_systemd, dscp, ub_sock); } return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd, reuseport, transparent, tcp_mss, nodelay, freebind, use_systemd, - dscp); + dscp, ub_sock); } /** @@ -1005,7 +1020,7 @@ make_sock_port(int stype, const char* ifname, const char* port, * @return false on failure. list in unchanged then. */ static int -port_insert(struct listen_port** list, int s, enum listen_type ftype) +port_insert(struct listen_port** list, int s, enum listen_type ftype, struct unbound_socket* ub_sock) { struct listen_port* item = (struct listen_port*)malloc( sizeof(struct listen_port)); @@ -1014,6 +1029,7 @@ port_insert(struct listen_port** list, int s, enum listen_type ftype) item->next = *list; item->fd = s; item->ftype = ftype; + item->socket = ub_sock; *list = item; return 1; } @@ -1043,7 +1059,7 @@ set_recvpktinfo(int s, int family) return 0; } # else - log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please " + log_err("no IPV6_RECVPKTINFO and IPV6_PKTINFO options, please " "disable interface-automatic or do-ip6 in config"); return 0; # endif /* defined IPV6_RECVPKTINFO */ @@ -1142,6 +1158,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, int s, noip6=0; int is_https = if_is_https(ifname, port, https_port); int nodelay = is_https && http2_nodelay; + struct unbound_socket* ub_sock; #ifdef USE_DNSCRYPT int is_dnscrypt = ((strchr(ifname, '@') && atoi(strchr(ifname, '@')+1) == dnscrypt_port) || @@ -1153,10 +1170,14 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, if(!do_udp && !do_tcp) return 0; + if(do_auto) { + ub_sock = malloc(sizeof(struct unbound_socket)); + if(!ub_sock) + return 0; if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, &noip6, rcv, snd, reuseport, transparent, - tcp_mss, nodelay, freebind, use_systemd, dscp)) == -1) { + tcp_mss, nodelay, freebind, use_systemd, dscp, &ub_sock)) == -1) { if(noip6) { log_warn("IPv6 protocol not available"); return 1; @@ -1169,15 +1190,18 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, return 0; } if(!port_insert(list, s, - is_dnscrypt?listen_type_udpancil_dnscrypt:listen_type_udpancil)) { + is_dnscrypt?listen_type_udpancil_dnscrypt:listen_type_udpancil, ub_sock)) { sock_close(s); return 0; } } else if(do_udp) { + ub_sock = malloc(sizeof(struct unbound_socket)); + if(!ub_sock) + return 0; /* regular udp socket */ if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, &noip6, rcv, snd, reuseport, transparent, - tcp_mss, nodelay, freebind, use_systemd, dscp)) == -1) { + tcp_mss, nodelay, freebind, use_systemd, dscp, &ub_sock)) == -1) { if(noip6) { log_warn("IPv6 protocol not available"); return 1; @@ -1185,12 +1209,15 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, return 0; } if(!port_insert(list, s, - is_dnscrypt?listen_type_udp_dnscrypt:listen_type_udp)) { + is_dnscrypt?listen_type_udp_dnscrypt:listen_type_udp, ub_sock)) { sock_close(s); return 0; } } if(do_tcp) { + ub_sock = malloc(sizeof(struct unbound_socket)); + if(!ub_sock) + return 0; int is_ssl = if_is_ssl(ifname, port, ssl_port, tls_additional_port); enum listen_type port_type; @@ -1204,7 +1231,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, port_type = listen_type_tcp; if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1, &noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay, - freebind, use_systemd, dscp)) == -1) { + freebind, use_systemd, dscp, &ub_sock)) == -1) { if(noip6) { /*log_warn("IPv6 protocol not available");*/ return 1; @@ -1213,7 +1240,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, } if(is_ssl) verbose(VERB_ALGO, "setup TCP for SSL service"); - if(!port_insert(list, s, port_type)) { + if(!port_insert(list, s, port_type, ub_sock)) { sock_close(s); return 0; } @@ -1280,14 +1307,14 @@ listen_create(struct comm_base* base, struct listen_port* ports, if(ports->ftype == listen_type_udp || ports->ftype == listen_type_udp_dnscrypt) cp = comm_point_create_udp(base, ports->fd, - front->udp_buff, cb, cb_arg); + front->udp_buff, cb, cb_arg, ports->socket); else if(ports->ftype == listen_type_tcp || ports->ftype == listen_type_tcp_dnscrypt) cp = comm_point_create_tcp(base, ports->fd, tcp_accept_count, tcp_idle_timeout, harden_large_queries, 0, NULL, tcp_conn_limit, bufsize, front->udp_buff, - ports->ftype, cb, cb_arg); + ports->ftype, cb, cb_arg, ports->socket); else if(ports->ftype == listen_type_ssl || ports->ftype == listen_type_http) { cp = comm_point_create_tcp(base, ports->fd, @@ -1295,7 +1322,7 @@ listen_create(struct comm_base* base, struct listen_port* ports, harden_large_queries, http_max_streams, http_endpoint, tcp_conn_limit, bufsize, front->udp_buff, - ports->ftype, cb, cb_arg); + ports->ftype, cb, cb_arg, ports->socket); if(http_notls && ports->ftype == listen_type_http) cp->ssl = NULL; else @@ -1322,7 +1349,7 @@ listen_create(struct comm_base* base, struct listen_port* ports, } else if(ports->ftype == listen_type_udpancil || ports->ftype == listen_type_udpancil_dnscrypt) cp = comm_point_create_udp_ancil(base, ports->fd, - front->udp_buff, cb, cb_arg); + front->udp_buff, cb, cb_arg, ports->socket); if(!cp) { log_err("can't create commpoint"); listen_delete(front); @@ -1656,6 +1683,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs, } } } + return list; } @@ -1667,6 +1695,8 @@ void listening_ports_free(struct listen_port* list) if(list->fd != -1) { sock_close(list->fd); } + free(list->socket->addr); + free(list->socket); free(list); list = nx; } diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h index 9d6ea2c33..96feea667 100644 --- a/services/listen_dnsport.h +++ b/services/listen_dnsport.h @@ -102,6 +102,20 @@ enum listen_type { listen_type_http }; +/* + * socket properties (just like NSD nsd_socket structure definition) + */ +struct unbound_socket { + /** socket-address structure */ + struct addrinfo * addr; + /** socket descriptor returned by socket() syscall */ + int s; + /** address family (AF_INET/IF_INET6) */ + int fam; + /** descriptor returned by accept() syscall for further usage. TODO: actually it might be useless here unlike in NSD where we have no comm_points mechanism with callback pointers for every created communication point */ + int tcp_read_fd; +}; + /** * Single linked list to store shared ports that have been * opened for use by all threads. @@ -113,6 +127,8 @@ struct listen_port { int fd; /** type of file descriptor, udp or tcp */ enum listen_type ftype; + /** fill in unbpound_socket structure for every opened socket at Unbound startup */ + struct unbound_socket* socket; }; /** @@ -424,4 +440,9 @@ int http2_submit_dns_response(void* v); char* set_ip_dscp(int socket, int addrfamily, int ds); +/** for debug and profiling purposes only + * @param unbound_socket: the structure containing created socket info we want to print or log for + */ +void verbose_print_unbound_socket(struct unbound_socket* ub_sock); + #endif /* LISTEN_DNSPORT_H */ diff --git a/services/outside_network.c b/services/outside_network.c index 0886907f7..5d6b6c3c2 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1440,7 +1440,7 @@ outside_network_create(struct comm_base *base, size_t bufsize, return NULL; } pc->cp = comm_point_create_udp(outnet->base, -1, - outnet->udp_buff, outnet_udp_cb, outnet); + outnet->udp_buff, outnet_udp_cb, outnet, NULL); if(!pc->cp) { log_err("malloc failed"); free(pc); @@ -1921,11 +1921,27 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout) comm_timer_set(pend->timer, &tv); #ifdef USE_DNSTAP + /* + * sending src (local service)/dst (upstream) addresses over DNSTAP + * TODO: right now there are no chances to get the src (local service) addr. So we will pass 0.0.0.0 (::) + * to argument for dt_msg_send_outside_query()/dt_msg_send_outside_response() calls. + * For the both UDP and TCP. + */ if(outnet->dtenv && (outnet->dtenv->log_resolver_query_messages || - outnet->dtenv->log_forwarder_query_messages)) - dt_msg_send_outside_query(outnet->dtenv, &pend->addr, comm_udp, - pend->sq->zone, pend->sq->zonelen, packet); + sq->outnet->dtenv->log_forwarder_query_messages)) { + if(addr_is_ip6(&sq->addr, sq->addrlen)) { + log_addr(VERB_ALGO, "from local addr", &sq->outnet->ip6_ifs->addr, sq->outnet->ip6_ifs->addrlen); + log_addr(VERB_ALGO, "request to upstream", &sq->addr, sq->addrlen); + dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, + comm_tcp, sq->zone, sq->zonelen, packet); + } else { + log_addr(VERB_ALGO, "from local addr", &sq->outnet->ip4_ifs->addr, sq->outnet->ip4_ifs->addrlen); + log_addr(VERB_ALGO, "request to upstream", &sq->addr, sq->addrlen); + dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, + comm_tcp, sq->zone, sq->zonelen, packet); + } + } #endif return 1; } @@ -2707,12 +2723,26 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error, infra_update_tcp_works(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone, sq->zonelen); #ifdef USE_DNSTAP + /* + * sending src (local service)/dst (upstream) addresses over DNSTAP + */ if(error==NETEVENT_NOERROR && sq->outnet->dtenv && (sq->outnet->dtenv->log_resolver_response_messages || - sq->outnet->dtenv->log_forwarder_response_messages)) - dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, - c->type, sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, - &sq->last_sent_time, sq->outnet->now_tv, c->buffer); + sq->outnet->dtenv->log_forwarder_response_messages)) { + if(addr_is_ip6(&sq->addr, sq->addrlen)) { + log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); + log_addr(VERB_ALGO, "to local addr", &sq->outnet->ip6_ifs->addr, sq->outnet->ip6_ifs->addrlen); + dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, + c->type, sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, + &sq->last_sent_time, sq->outnet->now_tv, c->buffer); + } else { + log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); + log_addr(VERB_ALGO, "to local addr", &sq->outnet->ip4_ifs->addr, sq->outnet->ip4_ifs->addrlen); + dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, + c->type, sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, + &sq->last_sent_time, sq->outnet->now_tv, c->buffer); + } + } #endif if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS && (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == @@ -2903,12 +2933,26 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, return 0; } #ifdef USE_DNSTAP + /* + * sending src (local service)/dst (upstream) addresses over DNSTAP + */ if(error == NETEVENT_NOERROR && outnet->dtenv && (outnet->dtenv->log_resolver_response_messages || - outnet->dtenv->log_forwarder_response_messages)) - dt_msg_send_outside_response(outnet->dtenv, &sq->addr, c->type, - sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, - &sq->last_sent_time, sq->outnet->now_tv, c->buffer); + outnet->dtenv->log_forwarder_response_messages)) { + if(addr_is_ip6(&sq->addr, sq->addrlen)) { + log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); + log_addr(VERB_ALGO, "to local addr", &sq->outnet->ip6_ifs->addr, sq->outnet->ip6_ifs->addrlen); + dt_msg_send_outside_response(outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, c->type, + sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, + &sq->last_sent_time, sq->outnet->now_tv, c->buffer); + } else { + log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); + log_addr(VERB_ALGO, "to addr", &sq->outnet->ip4_ifs->addr, sq->outnet->ip4_ifs->addrlen); + dt_msg_send_outside_response(outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, c->type, + sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, + &sq->last_sent_time, sq->outnet->now_tv, c->buffer); + } + } #endif if( (sq->status == serviced_query_UDP_EDNS ||sq->status == serviced_query_UDP_EDNS_FRAG) @@ -3180,7 +3224,7 @@ outnet_comm_point_for_udp(struct outside_network* outnet, return NULL; } cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff, - cb, cb_arg); + cb, cb_arg, NULL); if(!cp) { log_err("malloc failure"); close(fd); diff --git a/util/net_help.c b/util/net_help.c index c5216bc2d..9745adcd3 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -1609,5 +1609,39 @@ sock_close(int socket) { closesocket(socket); } - # endif /* USE_WINSOCK */ + + +struct sockaddr_storage* +mk_local_addr(void* addr, u_short port, u_char family) +{ + struct sockaddr_storage* dst_addr = malloc(sizeof(struct sockaddr_storage)); + if(!dst_addr) { + log_err("malloc failure"); + return NULL; + } + if(family == AF_INET) { + struct in_addr* v4addr = (struct in_addr*)addr; + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr = *v4addr; + sin.sin_port = port; + memcpy(dst_addr, &sin, sizeof(sin)); + } else if(family == AF_INET6) { + struct in6_addr* v6addr = (struct in6_addr*)addr; + struct sockaddr_in6 sin6; + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_len = sizeof(sin6); + sin6.sin6_family = AF_INET6; + sin6.sin6_addr = *v6addr; + sin6.sin6_port = port; + sin6.sin6_flowinfo = 0; + memcpy(dst_addr, &sin6, sizeof(sin6)); + } else { + log_err("unknown inet address family"); + free(dst_addr); + return NULL; + } + return dst_addr; +} diff --git a/util/net_help.h b/util/net_help.h index 45b607a43..d89319c0a 100644 --- a/util/net_help.h +++ b/util/net_help.h @@ -502,4 +502,14 @@ char* sock_strerror(int errn); /** close the socket with close, or wsa closesocket */ void sock_close(int socket); +/** + * Make and fill a stucture of sockaddr_storage* (malloced) type + * Note: currently it needed to form local address used by dnstap functions only + * @param addr: this is in_addr or in6_addr internet address structure + * @param port: TCP/UDP port + * @param family: Internet address family + * @return: pointer to created sockaddr_storage structure or NULL on error + */ +struct sockaddr_storage* mk_local_addr(void* addr, u_short port, u_char family); + #endif /* NET_HELP_H */ diff --git a/util/netevent.c b/util/netevent.c index d3e268a01..e98b76933 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -51,6 +51,16 @@ #include "dnstap/dnstap.h" #include "dnscrypt/dnscrypt.h" #include "services/listen_dnsport.h" +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif + #ifdef HAVE_OPENSSL_SSL_H #include #endif @@ -152,7 +162,7 @@ struct internal_signal { static struct comm_point* comm_point_create_tcp_handler( struct comm_base *base, struct comm_point* parent, size_t bufsize, struct sldns_buffer* spoolbuf, comm_point_callback_type* callback, - void* callback_arg); + void* callback_arg, struct unbound_socket* socket); /* -------- End of local definitions -------- */ @@ -398,14 +408,17 @@ static void p_ancil(const char* str, struct comm_reply* r) log_info("%s: unknown srctype %d", str, r->srctype); return; } + if(r->srctype == 6) { - char buf[1024]; - if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr, - buf, (socklen_t)sizeof(buf)) == 0) { - (void)strlcpy(buf, "(inet_ntop error)", sizeof(buf)); - } - buf[sizeof(buf)-1]=0; - log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex); +#ifdef IPV6_PKTINFO + char buf[1024]; + if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr, + buf, (socklen_t)sizeof(buf)) == 0) { + (void)strlcpy(buf, "(inet_ntop error)", sizeof(buf)); + } + buf[sizeof(buf)-1]=0; + log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex); +#endif } else if(r->srctype == 4) { #ifdef IP_PKTINFO char buf1[1024], buf2[1024]; @@ -3147,7 +3160,7 @@ void comm_point_raw_handle_callback(int ATTR_UNUSED(fd), struct comm_point* comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer, - comm_point_callback_type* callback, void* callback_arg) + comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket) { struct comm_point* c = (struct comm_point*)calloc(1, sizeof(struct comm_point)); @@ -3186,6 +3199,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer, c->inuse = 0; c->callback = callback; c->cb_arg = callback_arg; + c->socket = socket; evbits = UB_EV_READ | UB_EV_PERSIST; /* ub_event stuff */ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, @@ -3206,7 +3220,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer, struct comm_point* comm_point_create_udp_ancil(struct comm_base *base, int fd, sldns_buffer* buffer, - comm_point_callback_type* callback, void* callback_arg) + comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket) { struct comm_point* c = (struct comm_point*)calloc(1, sizeof(struct comm_point)); @@ -3245,6 +3259,7 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd, #endif c->callback = callback; c->cb_arg = callback_arg; + c->socket = socket; evbits = UB_EV_READ | UB_EV_PERSIST; /* ub_event stuff */ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, @@ -3266,7 +3281,7 @@ static struct comm_point* comm_point_create_tcp_handler(struct comm_base *base, struct comm_point* parent, size_t bufsize, struct sldns_buffer* spoolbuf, comm_point_callback_type* callback, - void* callback_arg) + void* callback_arg, struct unbound_socket* socket) { struct comm_point* c = (struct comm_point*)calloc(1, sizeof(struct comm_point)); @@ -3322,6 +3337,7 @@ comm_point_create_tcp_handler(struct comm_base *base, c->repinfo.c = c; c->callback = callback; c->cb_arg = callback_arg; + c->socket = socket; if(spoolbuf) { c->tcp_req_info = tcp_req_info_create(spoolbuf); if(!c->tcp_req_info) { @@ -3479,7 +3495,7 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, uint32_t http_max_streams, char* http_endpoint, struct tcl_list* tcp_conn_limit, size_t bufsize, struct sldns_buffer* spoolbuf, enum listen_type port_type, - comm_point_callback_type* callback, void* callback_arg) + comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket) { struct comm_point* c = (struct comm_point*)calloc(1, sizeof(struct comm_point)); @@ -3529,6 +3545,7 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, #endif c->callback = NULL; c->cb_arg = NULL; + c->socket = socket; evbits = UB_EV_READ | UB_EV_PERSIST; /* ub_event stuff */ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, @@ -3549,7 +3566,7 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, port_type == listen_type_ssl || port_type == listen_type_tcp_dnscrypt) { c->tcp_handlers[i] = comm_point_create_tcp_handler(base, - c, bufsize, spoolbuf, callback, callback_arg); + c, bufsize, spoolbuf, callback, callback_arg, socket); } else if(port_type == listen_type_http) { c->tcp_handlers[i] = comm_point_create_http_handler( base, c, bufsize, harden_large_queries, @@ -3925,20 +3942,40 @@ comm_point_send_reply(struct comm_reply *repinfo) comm_point_send_udp_msg(repinfo->c, buffer, (struct sockaddr*)&repinfo->addr, repinfo->addrlen); #ifdef USE_DNSTAP - if(repinfo->c->dtenv != NULL && - repinfo->c->dtenv->log_client_response_messages) - dt_msg_send_client_response(repinfo->c->dtenv, - &repinfo->addr, repinfo->c->type, repinfo->c->buffer); + /* + * sending src (client)/dst (local service) addresses over DNSTAP from udp callback + */ + if(repinfo->c->dtenv != NULL && repinfo->c->dtenv->log_client_response_messages) { + struct sockaddr_storage* dst_addr; + if(repinfo->addr.ss_family == AF_INET) + dst_addr = mk_local_addr(&((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); + else + dst_addr = mk_local_addr(&((struct sockaddr_in6*)repinfo->c->socket->addr->ai_addr)->sin6_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); + log_addr(VERB_ALGO, "from local addr", dst_addr, sizeof(dst_addr)); + log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen); + dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->addr, dst_addr, repinfo->c->type, repinfo->c->buffer); + if(dst_addr) + free(dst_addr); + } #endif } else { #ifdef USE_DNSTAP - if(repinfo->c->tcp_parent->dtenv != NULL && - repinfo->c->tcp_parent->dtenv->log_client_response_messages) - dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, - &repinfo->addr, repinfo->c->type, - ( repinfo->c->tcp_req_info - ? repinfo->c->tcp_req_info->spool_buffer - : repinfo->c->buffer )); + /* + * sending src (client)/dst (local service) addresses over DNSTAP from TCP callback + */ + if(repinfo->c->tcp_parent->dtenv != NULL && repinfo->c->tcp_parent->dtenv->log_client_response_messages) { + struct sockaddr_storage* dst_addr; + if(repinfo->addr.ss_family == AF_INET) + dst_addr = mk_local_addr(&((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); + else + dst_addr = mk_local_addr(&((struct sockaddr_in6*)repinfo->c->socket->addr->ai_addr)->sin6_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); + log_addr(VERB_ALGO, "from local addr", dst_addr, sizeof(dst_addr)); + log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen); + dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->addr, dst_addr, repinfo->c->type, + ( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer )); + if(dst_addr) + free(dst_addr); + } #endif if(repinfo->c->tcp_req_info) { tcp_req_info_send_reply(repinfo->c->tcp_req_info); diff --git a/util/netevent.h b/util/netevent.h index 266a74ff3..f43f0f49f 100644 --- a/util/netevent.h +++ b/util/netevent.h @@ -70,6 +70,7 @@ struct comm_point; struct comm_reply; struct tcl_list; struct ub_event_base; +struct unbound_socket; struct mesh_state; struct mesh_area; @@ -167,6 +168,8 @@ struct comm_point { /** behind the scenes structure, with say libevent info. alloced. */ struct internal_event* ev; + struct unbound_socket* socket; + /** file descriptor for communication point */ int fd; @@ -493,12 +496,13 @@ struct ub_event_base* comm_base_internal(struct comm_base* b); * @param buffer: shared buffer by UDP sockets from this thread. * @param callback: callback function pointer. * @param callback_arg: will be passed to your callback function. + * @param unbound_socket: and opened socket properties will be passed to your callback function. * @return: returns the allocated communication point. NULL on error. * Sets timeout to NULL. Turns off TCP options. */ struct comm_point* comm_point_create_udp(struct comm_base* base, int fd, struct sldns_buffer* buffer, - comm_point_callback_type* callback, void* callback_arg); + comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket); /** * Create an UDP with ancillary data comm point. Calls malloc. @@ -509,12 +513,13 @@ struct comm_point* comm_point_create_udp(struct comm_base* base, * @param buffer: shared buffer by UDP sockets from this thread. * @param callback: callback function pointer. * @param callback_arg: will be passed to your callback function. + * @param unbound_socket: and opened socket properties will be passed to your callback function. * @return: returns the allocated communication point. NULL on error. * Sets timeout to NULL. Turns off TCP options. */ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base, int fd, struct sldns_buffer* buffer, - comm_point_callback_type* callback, void* callback_arg); + comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket); /** * Create a TCP listener comm point. Calls malloc. @@ -537,6 +542,7 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base, * to select handler type to use. * @param callback: callback function pointer for TCP handlers. * @param callback_arg: will be passed to your callback function. + * @param unbound_socket: and opened socket properties will be passed to your callback function. * @return: returns the TCP listener commpoint. You can find the * TCP handlers in the array inside the listener commpoint. * returns NULL on error. From 31cedb47cbf9033df3670ef5d3e91044a5369046 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:13:58 +0100 Subject: [PATCH 02/19] Remove unused whitespace, add missing header change, make it compile --- dnstap/dnstap.c | 2 +- services/listen_dnsport.c | 6 +++--- services/listen_dnsport.h | 2 +- services/outside_network.c | 10 +++++----- util/net_help.c | 2 +- util/netevent.c | 16 ++++++++-------- util/netevent.h | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/dnstap/dnstap.c b/dnstap/dnstap.c index 2ee269be3..e1abfeeb3 100644 --- a/dnstap/dnstap.c +++ b/dnstap/dnstap.c @@ -345,7 +345,7 @@ dt_msg_fill_net(struct dt_msg *dm, /* * This block is to fill second set of fields in DNSTAP-message defined as request_/response_ names. - * Additional responsive structure is: struct sockaddr_storage *rs + * Additional responsive structure is: struct sockaddr_storage *rs */ if (rs->ss_family == AF_INET6) { struct sockaddr_in6 *r = (struct sockaddr_in6 *) rs; diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 02d44fcba..e8b8fdbd6 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -1215,12 +1215,12 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, } } if(do_tcp) { - ub_sock = malloc(sizeof(struct unbound_socket)); - if(!ub_sock) - return 0; int is_ssl = if_is_ssl(ifname, port, ssl_port, tls_additional_port); enum listen_type port_type; + ub_sock = malloc(sizeof(struct unbound_socket)); + if(!ub_sock) + return 0; if(is_ssl) port_type = listen_type_ssl; else if(is_https) diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h index 96feea667..82f0d9ec6 100644 --- a/services/listen_dnsport.h +++ b/services/listen_dnsport.h @@ -112,7 +112,7 @@ struct unbound_socket { int s; /** address family (AF_INET/IF_INET6) */ int fam; - /** descriptor returned by accept() syscall for further usage. TODO: actually it might be useless here unlike in NSD where we have no comm_points mechanism with callback pointers for every created communication point */ + /** descriptor returned by accept() syscall for further usage. TODO: actually it might be useless here unlike in NSD where we have no comm_points mechanism with callback pointers for every created communication point */ int tcp_read_fd; }; diff --git a/services/outside_network.c b/services/outside_network.c index 5d6b6c3c2..587f33a88 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1923,7 +1923,7 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout) #ifdef USE_DNSTAP /* * sending src (local service)/dst (upstream) addresses over DNSTAP - * TODO: right now there are no chances to get the src (local service) addr. So we will pass 0.0.0.0 (::) + * TODO: right now there are no chances to get the src (local service) addr. So we will pass 0.0.0.0 (::) * to argument for dt_msg_send_outside_query()/dt_msg_send_outside_response() calls. * For the both UDP and TCP. */ @@ -1933,12 +1933,12 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout) if(addr_is_ip6(&sq->addr, sq->addrlen)) { log_addr(VERB_ALGO, "from local addr", &sq->outnet->ip6_ifs->addr, sq->outnet->ip6_ifs->addrlen); log_addr(VERB_ALGO, "request to upstream", &sq->addr, sq->addrlen); - dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, + dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, comm_tcp, sq->zone, sq->zonelen, packet); } else { log_addr(VERB_ALGO, "from local addr", &sq->outnet->ip4_ifs->addr, sq->outnet->ip4_ifs->addrlen); log_addr(VERB_ALGO, "request to upstream", &sq->addr, sq->addrlen); - dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, + dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, comm_tcp, sq->zone, sq->zonelen, packet); } } @@ -2732,13 +2732,13 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error, if(addr_is_ip6(&sq->addr, sq->addrlen)) { log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); log_addr(VERB_ALGO, "to local addr", &sq->outnet->ip6_ifs->addr, sq->outnet->ip6_ifs->addrlen); - dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, + dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, c->type, sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, &sq->last_sent_time, sq->outnet->now_tv, c->buffer); } else { log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); log_addr(VERB_ALGO, "to local addr", &sq->outnet->ip4_ifs->addr, sq->outnet->ip4_ifs->addrlen); - dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, + dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, c->type, sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, &sq->last_sent_time, sq->outnet->now_tv, c->buffer); } diff --git a/util/net_help.c b/util/net_help.c index 9745adcd3..8732ea3df 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -1632,7 +1632,7 @@ mk_local_addr(void* addr, u_short port, u_char family) struct in6_addr* v6addr = (struct in6_addr*)addr; struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_len = sizeof(sin6); + /* sin6.sin6_len = sizeof(sin6); */ sin6.sin6_family = AF_INET6; sin6.sin6_addr = *v6addr; sin6.sin6_port = port; diff --git a/util/netevent.c b/util/netevent.c index e98b76933..713374827 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -411,13 +411,13 @@ static void p_ancil(const char* str, struct comm_reply* r) if(r->srctype == 6) { #ifdef IPV6_PKTINFO - char buf[1024]; - if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr, - buf, (socklen_t)sizeof(buf)) == 0) { - (void)strlcpy(buf, "(inet_ntop error)", sizeof(buf)); - } - buf[sizeof(buf)-1]=0; - log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex); + char buf[1024]; + if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr, + buf, (socklen_t)sizeof(buf)) == 0) { + (void)strlcpy(buf, "(inet_ntop error)", sizeof(buf)); + } + buf[sizeof(buf)-1]=0; + log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex); #endif } else if(r->srctype == 4) { #ifdef IP_PKTINFO @@ -3971,7 +3971,7 @@ comm_point_send_reply(struct comm_reply *repinfo) dst_addr = mk_local_addr(&((struct sockaddr_in6*)repinfo->c->socket->addr->ai_addr)->sin6_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); log_addr(VERB_ALGO, "from local addr", dst_addr, sizeof(dst_addr)); log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen); - dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->addr, dst_addr, repinfo->c->type, + dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->addr, dst_addr, repinfo->c->type, ( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer )); if(dst_addr) free(dst_addr); diff --git a/util/netevent.h b/util/netevent.h index f43f0f49f..c48359ec4 100644 --- a/util/netevent.h +++ b/util/netevent.h @@ -554,7 +554,7 @@ struct comm_point* comm_point_create_tcp(struct comm_base* base, struct tcl_list* tcp_conn_limit, size_t bufsize, struct sldns_buffer* spoolbuf, enum listen_type port_type, - comm_point_callback_type* callback, void* callback_arg); + comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket); /** * Create an outgoing TCP commpoint. No file descriptor is opened, left at -1. From 1f1b93cce647992e853fbc124e3e99e004072531 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:27:14 +0100 Subject: [PATCH 03/19] Fix test code function declaration. --- testcode/fake_event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 591557c35..867ee51e3 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -1627,7 +1627,8 @@ int create_udp_sock(int ATTR_UNUSED(family), int ATTR_UNUSED(socktype), struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base), int ATTR_UNUSED(fd), sldns_buffer* ATTR_UNUSED(buffer), comm_point_callback_type* ATTR_UNUSED(callback), - void* ATTR_UNUSED(callback_arg)) + void* ATTR_UNUSED(callback_arg), + struct unbound_socket* ATTR_UNUSED(socket)) { log_assert(0); return NULL; From 159bf52384e7a7ddade93544248f7b55d0ce53ad Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:27:33 +0100 Subject: [PATCH 04/19] Fix that it passes the actual UDP address instead of first and pass NULL to make tcp log compile. --- services/outside_network.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/services/outside_network.c b/services/outside_network.c index 587f33a88..2afa7a42c 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1929,18 +1929,11 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout) */ if(outnet->dtenv && (outnet->dtenv->log_resolver_query_messages || - sq->outnet->dtenv->log_forwarder_query_messages)) { - if(addr_is_ip6(&sq->addr, sq->addrlen)) { - log_addr(VERB_ALGO, "from local addr", &sq->outnet->ip6_ifs->addr, sq->outnet->ip6_ifs->addrlen); - log_addr(VERB_ALGO, "request to upstream", &sq->addr, sq->addrlen); - dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, - comm_tcp, sq->zone, sq->zonelen, packet); - } else { - log_addr(VERB_ALGO, "from local addr", &sq->outnet->ip4_ifs->addr, sq->outnet->ip4_ifs->addrlen); - log_addr(VERB_ALGO, "request to upstream", &sq->addr, sq->addrlen); - dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, - comm_tcp, sq->zone, sq->zonelen, packet); - } + outnet->dtenv->log_forwarder_query_messages)) { + log_addr(VERB_ALGO, "from local addr", &pend->pc->pif->addr, pend->pc->pif->addrlen); + log_addr(VERB_ALGO, "request to upstream", &pend->addr, pend->addrlen); + dt_msg_send_outside_query(outnet->dtenv, &pend->addr, &pend->pc->pif->addr, comm_udp, + pend->sq->zone, pend->sq->zonelen, packet); } #endif return 1; @@ -2218,7 +2211,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, if(sq->outnet->dtenv && (sq->outnet->dtenv->log_resolver_query_messages || sq->outnet->dtenv->log_forwarder_query_messages)) - dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, + dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, NULL, comm_tcp, sq->zone, sq->zonelen, packet); #endif return w; From 72d3b588cac0ffcadecfcbd09eb133066edad4f7 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:29:57 +0100 Subject: [PATCH 05/19] For the DoH create_http_handler, also pass the socket. --- util/netevent.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/util/netevent.c b/util/netevent.c index 713374827..962f389b4 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -3377,7 +3377,8 @@ static struct comm_point* comm_point_create_http_handler(struct comm_base *base, struct comm_point* parent, size_t bufsize, int harden_large_queries, uint32_t http_max_streams, char* http_endpoint, - comm_point_callback_type* callback, void* callback_arg) + comm_point_callback_type* callback, void* callback_arg, + struct unbound_socket* socket) { struct comm_point* c = (struct comm_point*)calloc(1, sizeof(struct comm_point)); @@ -3431,6 +3432,7 @@ comm_point_create_http_handler(struct comm_base *base, c->repinfo.c = c; c->callback = callback; c->cb_arg = callback_arg; + c->socket = socket; c->http_min_version = http_version_2; c->http2_stream_max_qbuffer_size = bufsize; @@ -3571,7 +3573,7 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, c->tcp_handlers[i] = comm_point_create_http_handler( base, c, bufsize, harden_large_queries, http_max_streams, http_endpoint, - callback, callback_arg); + callback, callback_arg, socket); } else { log_err("could not create tcp handler, unknown listen " From 91bec32cdcafbef382054e97b0e1fe14ef10c96c Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:34:39 +0100 Subject: [PATCH 06/19] For TCP store picked outgoing interface and pass it. --- services/outside_network.c | 12 ++++++++---- services/outside_network.h | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/services/outside_network.c b/services/outside_network.c index 2afa7a42c..5e7bd3124 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -194,15 +194,17 @@ waiting_tcp_delete(struct waiting_tcp* w) * Pick random outgoing-interface of that family, and bind it. * port set to 0 so OS picks a port number for us. * if it is the ANY address, do not bind. + * @param pend: pending tcp structure, for storing the local address choice. * @param w: tcp structure with destination address. * @param s: socket fd. * @return false on error, socket closed. */ static int -pick_outgoing_tcp(struct waiting_tcp* w, int s) +pick_outgoing_tcp(struct pending_tcp* pend, struct waiting_tcp* w, int s) { struct port_if* pi = NULL; int num; + pend->pi = NULL; #ifdef INET6 if(addr_is_ip6(&w->addr, w->addrlen)) num = w->outnet->num_ip6; @@ -222,6 +224,7 @@ pick_outgoing_tcp(struct waiting_tcp* w, int s) #endif pi = &w->outnet->ip4_ifs[ub_random_max(w->outnet->rnd, num)]; log_assert(pi); + pend->pi = pi; if(addr_is_any(&pi->addr, pi->addrlen)) { /* binding to the ANY interface is for listening sockets */ return 1; @@ -560,7 +563,7 @@ outnet_tcp_take_into_use(struct waiting_tcp* w) if(s == -1) return 0; - if(!pick_outgoing_tcp(w, s)) + if(!pick_outgoing_tcp(pend, w, s)) return 0; fd_set_nonblock(s); @@ -2211,8 +2214,9 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, if(sq->outnet->dtenv && (sq->outnet->dtenv->log_resolver_query_messages || sq->outnet->dtenv->log_forwarder_query_messages)) - dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, NULL, - comm_tcp, sq->zone, sq->zonelen, packet); + dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, + &pend->pi->addr, comm_tcp, sq->zone, sq->zonelen, + packet); #endif return w; } diff --git a/services/outside_network.h b/services/outside_network.h index 2fe97fa6c..d49d33e5d 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -344,6 +344,8 @@ struct pending { struct pending_tcp { /** next in list of free tcp comm points, or NULL. */ struct pending_tcp* next_free; + /** port for of the outgoing interface that is used */ + struct port_if* pi; /** tcp comm point it was sent on (and reply must come back on). */ struct comm_point* c; /** the query being serviced, NULL if the pending_tcp is unused. */ From 275f18cc8ed4a6ea4c8792dfc5c7356e8496e54f Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:37:04 +0100 Subject: [PATCH 07/19] Remove useless tcp_read_fd member from struct --- services/listen_dnsport.c | 3 +-- services/listen_dnsport.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index e8b8fdbd6..823d56fd3 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -139,7 +139,7 @@ verbose_print_unbound_socket(struct unbound_socket* ub_sock) if(verbosity >= VERB_ALGO) { log_info("listing of unbound_socket structure:"); verbose_print_addr(ub_sock->addr); - log_info("s is: %d, fam is: %s, tcp_read_fd is: %d", ub_sock->s, ub_sock->fam == AF_INET?"AF_INET":"AF_INET6", ub_sock->tcp_read_fd); + log_info("s is: %d, fam is: %s", ub_sock->s, ub_sock->fam == AF_INET?"AF_INET":"AF_INET6"); } } @@ -972,7 +972,6 @@ make_sock(int stype, const char* ifname, const char* port, (*ub_sock)->addr = res; (*ub_sock)->s = s; (*ub_sock)->fam = hints->ai_family; - (*ub_sock)->tcp_read_fd = -1; return s; } diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h index 82f0d9ec6..692391ed2 100644 --- a/services/listen_dnsport.h +++ b/services/listen_dnsport.h @@ -112,8 +112,6 @@ struct unbound_socket { int s; /** address family (AF_INET/IF_INET6) */ int fam; - /** descriptor returned by accept() syscall for further usage. TODO: actually it might be useless here unlike in NSD where we have no comm_points mechanism with callback pointers for every created communication point */ - int tcp_read_fd; }; /** From 7167153db599d9053b6684e9726b4a2e5c25c413 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:41:07 +0100 Subject: [PATCH 08/19] configure test for struct sockaddr_in6 sin6_len member --- config.h.in | 3 +++ configure | 44 ++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 34 ++++++++++++++++++++++++++++++++++ util/net_help.c | 4 +++- 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/config.h.in b/config.h.in index f993b81b0..98b5f067b 100644 --- a/config.h.in +++ b/config.h.in @@ -571,6 +571,9 @@ /* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */ #undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST +/* Define to 1 if `sin6_len' is a member of `struct sockaddr_in6'. */ +#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN + /* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */ #undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN diff --git a/configure b/configure index 00d36a361..c053ab920 100755 --- a/configure +++ b/configure @@ -20149,6 +20149,50 @@ $as_echo "no" >&6; } fi +fi + +ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_len" "ac_cv_member_struct_sockaddr_in6_sin6_len" " +$ac_includes_default +#if HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_NETINET_TCP_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +" +if test "x$ac_cv_member_struct_sockaddr_in6_sin6_len" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 1 +_ACEOF + + fi ac_fn_c_check_member "$LINENO" "struct sockaddr_un" "sun_len" "ac_cv_member_struct_sockaddr_un_sun_len" " diff --git a/configure.ac b/configure.ac index d648f55ad..fa5536687 100644 --- a/configure.ac +++ b/configure.ac @@ -1533,6 +1533,40 @@ if test $ac_cv_func_daemon = yes; then ]) fi +AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_len],,,[ +AC_INCLUDES_DEFAULT +#if HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_NETINET_TCP_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif +]) AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[ AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_UN_H diff --git a/util/net_help.c b/util/net_help.c index 8732ea3df..9a94556d4 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -1632,7 +1632,9 @@ mk_local_addr(void* addr, u_short port, u_char family) struct in6_addr* v6addr = (struct in6_addr*)addr; struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); - /* sin6.sin6_len = sizeof(sin6); */ +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN + sin6.sin6_len = sizeof(sin6); +#endif sin6.sin6_family = AF_INET6; sin6.sin6_addr = *v6addr; sin6.sin6_port = port; From 9272725cddf400ed7dff10c48d2aaf3fc760393b Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:43:16 +0100 Subject: [PATCH 09/19] Use calloc and freeaddrinfo --- services/listen_dnsport.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 823d56fd3..3de8c5fe4 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -1171,7 +1171,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, return 0; if(do_auto) { - ub_sock = malloc(sizeof(struct unbound_socket)); + ub_sock = calloc(1, sizeof(struct unbound_socket)); if(!ub_sock) return 0; if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, @@ -1194,7 +1194,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, return 0; } } else if(do_udp) { - ub_sock = malloc(sizeof(struct unbound_socket)); + ub_sock = calloc(1, sizeof(struct unbound_socket)); if(!ub_sock) return 0; /* regular udp socket */ @@ -1217,7 +1217,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, int is_ssl = if_is_ssl(ifname, port, ssl_port, tls_additional_port); enum listen_type port_type; - ub_sock = malloc(sizeof(struct unbound_socket)); + ub_sock = calloc(1, sizeof(struct unbound_socket)); if(!ub_sock) return 0; if(is_ssl) @@ -1694,7 +1694,7 @@ void listening_ports_free(struct listen_port* list) if(list->fd != -1) { sock_close(list->fd); } - free(list->socket->addr); + freeaddrinfo(list->socket->addr); free(list->socket); free(list); list = nx; From 6bf1293bcd7dec82dadeab00aaee559147be73f2 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 11:56:35 +0100 Subject: [PATCH 10/19] No need for mk_local_addr, can pass the sockaddr structure. --- config.h.in | 3 --- configure | 44 -------------------------------------------- configure.ac | 34 ---------------------------------- daemon/worker.c | 22 ++++------------------ util/net_help.c | 37 ------------------------------------- util/net_help.h | 10 ---------- util/netevent.c | 22 ++++------------------ 7 files changed, 8 insertions(+), 164 deletions(-) diff --git a/config.h.in b/config.h.in index 98b5f067b..f993b81b0 100644 --- a/config.h.in +++ b/config.h.in @@ -571,9 +571,6 @@ /* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */ #undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST -/* Define to 1 if `sin6_len' is a member of `struct sockaddr_in6'. */ -#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN - /* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */ #undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN diff --git a/configure b/configure index c053ab920..00d36a361 100755 --- a/configure +++ b/configure @@ -20149,50 +20149,6 @@ $as_echo "no" >&6; } fi -fi - -ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_len" "ac_cv_member_struct_sockaddr_in6_sin6_len" " -$ac_includes_default -#if HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_NETINET_TCP_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -" -if test "x$ac_cv_member_struct_sockaddr_in6_sin6_len" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 1 -_ACEOF - - fi ac_fn_c_check_member "$LINENO" "struct sockaddr_un" "sun_len" "ac_cv_member_struct_sockaddr_un_sun_len" " diff --git a/configure.ac b/configure.ac index fa5536687..d648f55ad 100644 --- a/configure.ac +++ b/configure.ac @@ -1533,40 +1533,6 @@ if test $ac_cv_func_daemon = yes; then ]) fi -AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_len],,,[ -AC_INCLUDES_DEFAULT -#if HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_NETINET_TCP_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif -]) AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[ AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_UN_H diff --git a/daemon/worker.c b/daemon/worker.c index 36d4208f1..7134d3914 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1163,16 +1163,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error, * sending src (client)/dst (local service) addresses over DNSTAP from incoming request handler */ if(worker->dtenv.log_client_query_messages) { - struct sockaddr_storage* dst_addr; - if(repinfo->addr.ss_family == AF_INET) - dst_addr = mk_local_addr(&((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); - else - dst_addr = mk_local_addr(&((struct sockaddr_in6*)repinfo->c->socket->addr->ai_addr)->sin6_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); log_addr(VERB_ALGO, "request from client", &repinfo->addr, repinfo->addrlen); - log_addr(VERB_ALGO, "to local addr", dst_addr, sizeof(dst_addr)); - dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, dst_addr, c->type, c->buffer); - if(dst_addr) - free(dst_addr); + log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); + dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer); } #endif acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr, @@ -1600,16 +1593,9 @@ send_reply_rc: * sending src (client)/dst (local service) addresses over DNSTAP from send_reply code label (when we serviced local zone for ex.) */ if(worker->dtenv.log_client_response_messages) { - struct sockaddr_storage* dst_addr; - if(repinfo->addr.ss_family == AF_INET) - dst_addr = mk_local_addr(&((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); - else - dst_addr = mk_local_addr(&((struct sockaddr_in6*)repinfo->c->socket->addr->ai_addr)->sin6_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); - log_addr(VERB_ALGO, "from local addr", dst_addr, sizeof(dst_addr)); + log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen); - dt_msg_send_client_response(&worker->dtenv, &repinfo->addr, dst_addr, c->type, c->buffer); - if(dst_addr) - free(dst_addr); + dt_msg_send_client_response(&worker->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer); } #endif if(worker->env.cfg->log_replies) diff --git a/util/net_help.c b/util/net_help.c index 9a94556d4..557fc127d 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -1610,40 +1610,3 @@ sock_close(int socket) closesocket(socket); } # endif /* USE_WINSOCK */ - - -struct sockaddr_storage* -mk_local_addr(void* addr, u_short port, u_char family) -{ - struct sockaddr_storage* dst_addr = malloc(sizeof(struct sockaddr_storage)); - if(!dst_addr) { - log_err("malloc failure"); - return NULL; - } - if(family == AF_INET) { - struct in_addr* v4addr = (struct in_addr*)addr; - struct sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr = *v4addr; - sin.sin_port = port; - memcpy(dst_addr, &sin, sizeof(sin)); - } else if(family == AF_INET6) { - struct in6_addr* v6addr = (struct in6_addr*)addr; - struct sockaddr_in6 sin6; - memset(&sin6, 0, sizeof(sin6)); -#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN - sin6.sin6_len = sizeof(sin6); -#endif - sin6.sin6_family = AF_INET6; - sin6.sin6_addr = *v6addr; - sin6.sin6_port = port; - sin6.sin6_flowinfo = 0; - memcpy(dst_addr, &sin6, sizeof(sin6)); - } else { - log_err("unknown inet address family"); - free(dst_addr); - return NULL; - } - return dst_addr; -} diff --git a/util/net_help.h b/util/net_help.h index d89319c0a..45b607a43 100644 --- a/util/net_help.h +++ b/util/net_help.h @@ -502,14 +502,4 @@ char* sock_strerror(int errn); /** close the socket with close, or wsa closesocket */ void sock_close(int socket); -/** - * Make and fill a stucture of sockaddr_storage* (malloced) type - * Note: currently it needed to form local address used by dnstap functions only - * @param addr: this is in_addr or in6_addr internet address structure - * @param port: TCP/UDP port - * @param family: Internet address family - * @return: pointer to created sockaddr_storage structure or NULL on error - */ -struct sockaddr_storage* mk_local_addr(void* addr, u_short port, u_char family); - #endif /* NET_HELP_H */ diff --git a/util/netevent.c b/util/netevent.c index 962f389b4..37e6ac4f2 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -3948,16 +3948,9 @@ comm_point_send_reply(struct comm_reply *repinfo) * sending src (client)/dst (local service) addresses over DNSTAP from udp callback */ if(repinfo->c->dtenv != NULL && repinfo->c->dtenv->log_client_response_messages) { - struct sockaddr_storage* dst_addr; - if(repinfo->addr.ss_family == AF_INET) - dst_addr = mk_local_addr(&((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); - else - dst_addr = mk_local_addr(&((struct sockaddr_in6*)repinfo->c->socket->addr->ai_addr)->sin6_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); - log_addr(VERB_ALGO, "from local addr", dst_addr, sizeof(dst_addr)); + log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen); - dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->addr, dst_addr, repinfo->c->type, repinfo->c->buffer); - if(dst_addr) - free(dst_addr); + dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, repinfo->c->buffer); } #endif } else { @@ -3966,17 +3959,10 @@ comm_point_send_reply(struct comm_reply *repinfo) * sending src (client)/dst (local service) addresses over DNSTAP from TCP callback */ if(repinfo->c->tcp_parent->dtenv != NULL && repinfo->c->tcp_parent->dtenv->log_client_response_messages) { - struct sockaddr_storage* dst_addr; - if(repinfo->addr.ss_family == AF_INET) - dst_addr = mk_local_addr(&((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); - else - dst_addr = mk_local_addr(&((struct sockaddr_in6*)repinfo->c->socket->addr->ai_addr)->sin6_addr, ((struct sockaddr_in*)repinfo->c->socket->addr->ai_addr)->sin_port, repinfo->addr.ss_family); - log_addr(VERB_ALGO, "from local addr", dst_addr, sizeof(dst_addr)); + log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen); - dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->addr, dst_addr, repinfo->c->type, + dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, ( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer )); - if(dst_addr) - free(dst_addr); } #endif if(repinfo->c->tcp_req_info) { From 6ce577c4d923058b1bf170a0640ed140c0ee6222 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 12:07:16 +0100 Subject: [PATCH 11/19] Use stored TCP address for callback. --- services/outside_network.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/services/outside_network.c b/services/outside_network.c index 5e7bd3124..027f18ce5 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -2712,6 +2712,11 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error, { struct serviced_query* sq = (struct serviced_query*)arg; struct comm_reply r2; +#ifdef USE_DNSTAP + struct waiting_tcp* w = (struct waiting_tcp*)sq->pending; + struct pending_tcp* pend_tcp = (struct pending_tcp*)w->next_waiting; + struct port_if* pi = pend_tcp->pi; +#endif sq->pending = NULL; /* removed after this callback */ if(error != NETEVENT_NOERROR) log_addr(VERB_QUERY, "tcp error for address", @@ -2726,19 +2731,12 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error, if(error==NETEVENT_NOERROR && sq->outnet->dtenv && (sq->outnet->dtenv->log_resolver_response_messages || sq->outnet->dtenv->log_forwarder_response_messages)) { - if(addr_is_ip6(&sq->addr, sq->addrlen)) { - log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); - log_addr(VERB_ALGO, "to local addr", &sq->outnet->ip6_ifs->addr, sq->outnet->ip6_ifs->addrlen); - dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, - c->type, sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, - &sq->last_sent_time, sq->outnet->now_tv, c->buffer); - } else { - log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); - log_addr(VERB_ALGO, "to local addr", &sq->outnet->ip4_ifs->addr, sq->outnet->ip4_ifs->addrlen); - dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, - c->type, sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, - &sq->last_sent_time, sq->outnet->now_tv, c->buffer); - } + log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); + log_addr(VERB_ALGO, "to local addr", &pi->addr, pi->addrlen); + dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, + &pi->addr, c->type, sq->zone, sq->zonelen, sq->qbuf, + sq->qbuflen, &sq->last_sent_time, sq->outnet->now_tv, + c->buffer); } #endif if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS && From 2baa748bc7df53155d734bf017514387b8aec7c8 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 12:13:50 +0100 Subject: [PATCH 12/19] Use port_if pointer instead of wrong UDP local addr --- services/outside_network.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/services/outside_network.c b/services/outside_network.c index 027f18ce5..1854e5dac 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -2891,6 +2891,10 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, struct serviced_query* sq = (struct serviced_query*)arg; struct outside_network* outnet = sq->outnet; struct timeval now = *sq->outnet->now_tv; +#ifdef USE_DNSTAP + struct pending* p = (struct pending*)sq->pending; + struct port_if* pi = p->pc->pif; +#endif sq->pending = NULL; /* removed after callback */ if(error == NETEVENT_TIMEOUT) { @@ -2934,19 +2938,11 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, if(error == NETEVENT_NOERROR && outnet->dtenv && (outnet->dtenv->log_resolver_response_messages || outnet->dtenv->log_forwarder_response_messages)) { - if(addr_is_ip6(&sq->addr, sq->addrlen)) { - log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); - log_addr(VERB_ALGO, "to local addr", &sq->outnet->ip6_ifs->addr, sq->outnet->ip6_ifs->addrlen); - dt_msg_send_outside_response(outnet->dtenv, &sq->addr, &sq->outnet->ip6_ifs->addr, c->type, - sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, - &sq->last_sent_time, sq->outnet->now_tv, c->buffer); - } else { - log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); - log_addr(VERB_ALGO, "to addr", &sq->outnet->ip4_ifs->addr, sq->outnet->ip4_ifs->addrlen); - dt_msg_send_outside_response(outnet->dtenv, &sq->addr, &sq->outnet->ip4_ifs->addr, c->type, - sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, - &sq->last_sent_time, sq->outnet->now_tv, c->buffer); - } + log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); + log_addr(VERB_ALGO, "to local addr", &pi->addr, pi->addrlen); + dt_msg_send_outside_response(outnet->dtenv, &sq->addr, &pi->addr, c->type, + sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, + &sq->last_sent_time, sq->outnet->now_tv, c->buffer); } #endif if( (sq->status == serviced_query_UDP_EDNS From af96ff157eaa3bc3526d9b288259cde930d25c0d Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 13:52:49 +0100 Subject: [PATCH 13/19] Fix leak of socket mem on failure and fix if tcp has to wait we do not know the interface at the time. Later when it knows the interface we do not have 'sq' with the zone name. --- dnstap/dnstap.c | 4 ++-- services/listen_dnsport.c | 7 +++++++ services/outside_network.c | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dnstap/dnstap.c b/dnstap/dnstap.c index e1abfeeb3..6577a019a 100644 --- a/dnstap/dnstap.c +++ b/dnstap/dnstap.c @@ -347,7 +347,7 @@ dt_msg_fill_net(struct dt_msg *dm, * This block is to fill second set of fields in DNSTAP-message defined as request_/response_ names. * Additional responsive structure is: struct sockaddr_storage *rs */ - if (rs->ss_family == AF_INET6) { + if (rs && rs->ss_family == AF_INET6) { struct sockaddr_in6 *r = (struct sockaddr_in6 *) rs; /* addr: query_address or response_address */ @@ -358,7 +358,7 @@ dt_msg_fill_net(struct dt_msg *dm, /* port: query_port or response_port */ *rport = ntohs(r->sin6_port); *has_rport = 1; - } else if (rs->ss_family == AF_INET) { + } else if (rs && rs->ss_family == AF_INET) { struct sockaddr_in *r = (struct sockaddr_in *) rs; /* addr: query_address or response_address */ diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 3de8c5fe4..9e3ad8b79 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -1177,6 +1177,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, &noip6, rcv, snd, reuseport, transparent, tcp_mss, nodelay, freebind, use_systemd, dscp, &ub_sock)) == -1) { + free(ub_sock); if(noip6) { log_warn("IPv6 protocol not available"); return 1; @@ -1186,11 +1187,13 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, /* getting source addr packet info is highly non-portable */ if(!set_recvpktinfo(s, hints->ai_family)) { sock_close(s); + free(ub_sock); return 0; } if(!port_insert(list, s, is_dnscrypt?listen_type_udpancil_dnscrypt:listen_type_udpancil, ub_sock)) { sock_close(s); + free(ub_sock); return 0; } } else if(do_udp) { @@ -1201,6 +1204,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, &noip6, rcv, snd, reuseport, transparent, tcp_mss, nodelay, freebind, use_systemd, dscp, &ub_sock)) == -1) { + free(ub_sock); if(noip6) { log_warn("IPv6 protocol not available"); return 1; @@ -1210,6 +1214,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, if(!port_insert(list, s, is_dnscrypt?listen_type_udp_dnscrypt:listen_type_udp, ub_sock)) { sock_close(s); + free(ub_sock); return 0; } } @@ -1231,6 +1236,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1, &noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay, freebind, use_systemd, dscp, &ub_sock)) == -1) { + free(ub_sock); if(noip6) { /*log_warn("IPv6 protocol not available");*/ return 1; @@ -1241,6 +1247,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, verbose(VERB_ALGO, "setup TCP for SSL service"); if(!port_insert(list, s, port_type, ub_sock)) { sock_close(s); + free(ub_sock); return 0; } } diff --git a/services/outside_network.c b/services/outside_network.c index 1854e5dac..815a805ce 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -2215,8 +2215,8 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, (sq->outnet->dtenv->log_resolver_query_messages || sq->outnet->dtenv->log_forwarder_query_messages)) dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, - &pend->pi->addr, comm_tcp, sq->zone, sq->zonelen, - packet); + (pend?&pend->pi->addr:NULL), comm_tcp, sq->zone, + sq->zonelen, packet); #endif return w; } From 9ea58b5bc0c8df03e7bcf0dfb4e14ff1371ee7f2 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 14:02:00 +0100 Subject: [PATCH 14/19] Fix for tcp outgoing to have local address logged --- services/outside_network.c | 42 ++++++++++++++++++++++++++++++-------- services/outside_network.h | 4 ++++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/services/outside_network.c b/services/outside_network.c index 815a805ce..abc43e3c2 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -717,6 +717,9 @@ use_free_buffer(struct outside_network* outnet) struct waiting_tcp* w; while(outnet->tcp_free && outnet->tcp_wait_first && !outnet->want_to_quit) { +#ifdef USE_DNSTAP + struct pending_tcp* pend_tcp = NULL; +#endif struct reuse_tcp* reuse = NULL; w = outnet->tcp_wait_first; outnet->tcp_wait_first = w->next_waiting; @@ -728,6 +731,9 @@ use_free_buffer(struct outside_network* outnet) if(reuse) { log_reuse_tcp(VERB_CLIENT, "use free buffer for waiting tcp: " "found reuse", reuse); +#ifdef USE_DNSTAP + pend_tcp = reuse->pending; +#endif reuse_tcp_lru_touch(outnet, reuse); comm_timer_disable(w->timer); w->next_waiting = (void*)reuse->pending; @@ -755,7 +761,21 @@ use_free_buffer(struct outside_network* outnet) NULL); waiting_tcp_delete(w); } +#ifdef USE_DNSTAP + pend_tcp = pend; +#endif } +#ifdef USE_DNSTAP + if(outnet->dtenv && pend_tcp && w->sq && + (outnet->dtenv->log_resolver_query_messages || + outnet->dtenv->log_forwarder_query_messages)) { + sldns_buffer tmp; + sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len); + dt_msg_send_outside_query(outnet->dtenv, &w->sq->addr, + &pend_tcp->pi->addr, comm_tcp, w->sq->zone, + w->sq->zonelen, &tmp); + } +#endif } } @@ -2169,6 +2189,9 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, w->write_wait_next = NULL; w->write_wait_queued = 0; w->error_count = 0; +#ifdef USE_DNSTAP + w->sq = NULL; +#endif if(pend) { /* we have a buffer available right now */ if(reuse) { @@ -2203,21 +2226,24 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, return NULL; } } +#ifdef USE_DNSTAP + if(sq->outnet->dtenv && + (sq->outnet->dtenv->log_resolver_query_messages || + sq->outnet->dtenv->log_forwarder_query_messages)) + dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, + &pend->pi->addr, comm_tcp, sq->zone, + sq->zonelen, packet); +#endif } else { /* queue up */ /* waiting for a buffer on the outside network buffer wait * list */ verbose(VERB_CLIENT, "pending_tcp_query: queue to wait"); +#ifdef USE_DNSTAP + w->sq = sq; +#endif outnet_add_tcp_waiting(sq->outnet, w); } -#ifdef USE_DNSTAP - if(sq->outnet->dtenv && - (sq->outnet->dtenv->log_resolver_query_messages || - sq->outnet->dtenv->log_forwarder_query_messages)) - dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, - (pend?&pend->pi->addr:NULL), comm_tcp, sq->zone, - sq->zonelen, packet); -#endif return w; } diff --git a/services/outside_network.h b/services/outside_network.h index d49d33e5d..5b6481e67 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -410,6 +410,10 @@ struct waiting_tcp { char* tls_auth_name; /** the packet was involved in an error, to stop looping errors */ int error_count; +#ifdef USE_DNSTAP + /** serviced query pointer for dnstap to get logging info, if nonNULL*/ + struct serviced_query* sq; +#endif }; /** From e25f80799ad019d0625edac990ac4612aceac478 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 14:13:46 +0100 Subject: [PATCH 15/19] Fix use after free. --- services/outside_network.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/outside_network.c b/services/outside_network.c index abc43e3c2..4315eaf1b 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -760,13 +760,16 @@ use_free_buffer(struct outside_network* outnet) waiting_tcp_callback(w, NULL, NETEVENT_CLOSED, NULL); waiting_tcp_delete(w); +#ifdef USE_DNSTAP + w = NULL; +#endif } #ifdef USE_DNSTAP pend_tcp = pend; #endif } #ifdef USE_DNSTAP - if(outnet->dtenv && pend_tcp && w->sq && + if(outnet->dtenv && pend_tcp && w && w->sq && (outnet->dtenv->log_resolver_query_messages || outnet->dtenv->log_forwarder_query_messages)) { sldns_buffer tmp; From 51e431ada14237ca9c404883c9e8b41c2f91796e Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 9 Dec 2020 14:17:02 +0100 Subject: [PATCH 16/19] doxygen comments fixup --- services/listen_dnsport.c | 1 + services/listen_dnsport.h | 2 +- util/netevent.h | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 9e3ad8b79..1943f5110 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -1016,6 +1016,7 @@ make_sock_port(int stype, const char* ifname, const char* port, * @param list: list head. changed. * @param s: fd. * @param ftype: if fd is UDP. + * @param ub_sock: socket with address. * @return false on failure. list in unchanged then. */ static int diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h index 692391ed2..5d5f156c1 100644 --- a/services/listen_dnsport.h +++ b/services/listen_dnsport.h @@ -439,7 +439,7 @@ int http2_submit_dns_response(void* v); char* set_ip_dscp(int socket, int addrfamily, int ds); /** for debug and profiling purposes only - * @param unbound_socket: the structure containing created socket info we want to print or log for + * @param ub_sock: the structure containing created socket info we want to print or log for */ void verbose_print_unbound_socket(struct unbound_socket* ub_sock); diff --git a/util/netevent.h b/util/netevent.h index c48359ec4..62e47d228 100644 --- a/util/netevent.h +++ b/util/netevent.h @@ -496,7 +496,7 @@ struct ub_event_base* comm_base_internal(struct comm_base* b); * @param buffer: shared buffer by UDP sockets from this thread. * @param callback: callback function pointer. * @param callback_arg: will be passed to your callback function. - * @param unbound_socket: and opened socket properties will be passed to your callback function. + * @param socket: and opened socket properties will be passed to your callback function. * @return: returns the allocated communication point. NULL on error. * Sets timeout to NULL. Turns off TCP options. */ @@ -513,7 +513,7 @@ struct comm_point* comm_point_create_udp(struct comm_base* base, * @param buffer: shared buffer by UDP sockets from this thread. * @param callback: callback function pointer. * @param callback_arg: will be passed to your callback function. - * @param unbound_socket: and opened socket properties will be passed to your callback function. + * @param socket: and opened socket properties will be passed to your callback function. * @return: returns the allocated communication point. NULL on error. * Sets timeout to NULL. Turns off TCP options. */ @@ -542,7 +542,7 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base, * to select handler type to use. * @param callback: callback function pointer for TCP handlers. * @param callback_arg: will be passed to your callback function. - * @param unbound_socket: and opened socket properties will be passed to your callback function. + * @param socket: and opened socket properties will be passed to your callback function. * @return: returns the TCP listener commpoint. You can find the * TCP handlers in the array inside the listener commpoint. * returns NULL on error. From 1f7d1a00ff8c2610239819198deda8f0f6697acb Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Thu, 10 Dec 2020 08:19:07 +0100 Subject: [PATCH 17/19] Fix for #368: dnstap does not log the DNS message ID for FORWARDER_QUERY --- services/outside_network.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/services/outside_network.c b/services/outside_network.c index 4315eaf1b..04a64d59f 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -2232,10 +2232,14 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, #ifdef USE_DNSTAP if(sq->outnet->dtenv && (sq->outnet->dtenv->log_resolver_query_messages || - sq->outnet->dtenv->log_forwarder_query_messages)) + sq->outnet->dtenv->log_forwarder_query_messages)) { + /* use w->pkt, because it has the ID value */ + sldns_buffer tmp; + sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len); dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, &pend->pi->addr, comm_tcp, sq->zone, - sq->zonelen, packet); + sq->zonelen, &tmp); + } #endif } else { /* queue up */ From 6cda81b7e487afa35fe723eb0f92c6ce6ea42f7c Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 24 Feb 2021 17:36:22 +0100 Subject: [PATCH 18/19] Fix to use a simple pointer in the call of make_sock and make_sock_port. --- services/listen_dnsport.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 9a95a8e32..ceccd6056 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -926,7 +926,7 @@ 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) + int use_systemd, int dscp, struct unbound_socket* ub_sock) { struct addrinfo *res = NULL; int r, s, inuse, noproto; @@ -969,9 +969,9 @@ make_sock(int stype, const char* ifname, const char* port, } } - (*ub_sock)->addr = res; - (*ub_sock)->s = s; - (*ub_sock)->fam = hints->ai_family; + ub_sock->addr = res; + ub_sock->s = s; + ub_sock->fam = hints->ai_family; return s; } @@ -981,7 +981,7 @@ 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) + int use_systemd, int dscp, struct unbound_socket* ub_sock) { char* s = strchr(ifname, '@'); if(s) { @@ -1177,7 +1177,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, return 0; if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, &noip6, rcv, snd, reuseport, transparent, - tcp_mss, nodelay, freebind, use_systemd, dscp, &ub_sock)) == -1) { + tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) { free(ub_sock); if(noip6) { log_warn("IPv6 protocol not available"); @@ -1204,7 +1204,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, /* regular udp socket */ if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, &noip6, rcv, snd, reuseport, transparent, - tcp_mss, nodelay, freebind, use_systemd, dscp, &ub_sock)) == -1) { + tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) { free(ub_sock); if(noip6) { log_warn("IPv6 protocol not available"); @@ -1236,7 +1236,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, port_type = listen_type_tcp; if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1, &noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay, - freebind, use_systemd, dscp, &ub_sock)) == -1) { + freebind, use_systemd, dscp, ub_sock)) == -1) { free(ub_sock); if(noip6) { /*log_warn("IPv6 protocol not available");*/ From 04b4f515a7b3de1dc02d78990f7a0c3d1d6d84aa Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Thu, 25 Feb 2021 08:50:02 +0100 Subject: [PATCH 19/19] Fix comment item. --- services/outside_network.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/services/outside_network.c b/services/outside_network.c index dbe6121f2..89ccb70ad 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1942,9 +1942,10 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout) #ifdef USE_DNSTAP /* * sending src (local service)/dst (upstream) addresses over DNSTAP - * TODO: right now there are no chances to get the src (local service) addr. So we will pass 0.0.0.0 (::) - * to argument for dt_msg_send_outside_query()/dt_msg_send_outside_response() calls. - * For the both UDP and TCP. + * There are no chances to get the src (local service) addr if unbound + * is not configured with specific outgoing IP-addresses. So we will + * pass 0.0.0.0 (::) to argument for + * dt_msg_send_outside_query()/dt_msg_send_outside_response() calls. */ if(outnet->dtenv && (outnet->dtenv->log_resolver_query_messages ||