? ktrace.out Index: Makefile.in =================================================================== RCS file: /cvs/src/usr.sbin/unbound/Makefile.in,v retrieving revision 1.41 diff -u -p -r1.41 Makefile.in --- Makefile.in 20 Oct 2022 08:26:14 -0000 1.41 +++ Makefile.in 26 Apr 2024 04:44:23 -0000 @@ -139,7 +139,8 @@ validator/val_sigcrypt.c validator/val_u edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \ edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \ $(CACHEDB_SRC) respip/respip.c $(CHECKLOCK_SRC) \ -$(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC) $(IPSET_SRC) +$(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC) $(IPSET_SRC) \ +msgtap/msgtap.c msgtap/libmsgtap.c COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \ as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \ iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \ @@ -152,7 +153,8 @@ autotrust.lo val_anchor.lo rpz.lo proxy_ validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \ val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo $(CACHEDB_OBJ) authzone.lo \ $(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \ -$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo +$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo \ +msgtap.lo libmsgtap.lo COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \ outside_network.lo COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo @@ -456,6 +458,10 @@ dynlibmod.lo dynlibdmod.o: $(srcdir)/dyn cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h $(srcdir)/cachedb/cachedb.h redis.lo redis.o: $(srcdir)/cachedb/redis.c config.h $(srcdir)/cachedb/redis.h +# msgtap +libmsgtap.lo libmsgtap.o: $(srcdir)/msgtap/libmsgtap.c $(srcdir)/msgtap/libmsgtap.h +msgtap.lo msgtap.o: $(srcdir)/msgtap/msgtap.c $(srcdir)/msgtap/msgtap.h + # dnscrypt dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \ dnscrypt/dnscrypt_config.h \ @@ -891,7 +897,7 @@ outside_network.lo outside_network.o: $( $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h \ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \ - $(srcdir)/util/edns.h $(srcdir)/dnstap/dnstap.h + $(srcdir)/util/edns.h $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h alloc.lo alloc.o: $(srcdir)/util/alloc.c config.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ $(srcdir)/util/regional.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ @@ -924,7 +930,7 @@ shm_main.lo shm_main.o: $(srcdir)/util/s $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/services/mesh.h \ + $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h $(srcdir)/services/mesh.h \ $(srcdir)/util/rbtree.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \ $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h \ @@ -984,7 +990,7 @@ netevent.lo netevent.o: $(srcdir)/util/n $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \ $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/sldns/str2wire.h \ - $(srcdir)/dnstap/dnstap.h $(srcdir)/services/listen_dnsport.h + $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h $(srcdir)/services/listen_dnsport.h proxy_protocol.lo proxy_protocol.o: $(srcdir)/util/proxy_protocol.c config.h \ $(srcdir)/util/proxy_protocol.h $(srcdir)/sldns/sbuffer.h net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \ @@ -1254,7 +1260,7 @@ cachedump.lo cachedump.o: $(srcdir)/daem $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ + $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h \ $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \ $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \ $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \ @@ -1267,7 +1273,7 @@ daemon.lo daemon.o: $(srcdir)/daemon/dae $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ + $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h \ $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h \ $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/tcp_conn_limit.h \ @@ -1281,7 +1287,7 @@ remote.lo remote.o: $(srcdir)/daemon/rem $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/alloc.h \ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h \ - $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \ + $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h $(srcdir)/daemon/daemon.h \ $(srcdir)/services/modstack.h $(srcdir)/daemon/cachedump.h $(srcdir)/util/config_file.h \ $(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \ @@ -1298,7 +1304,7 @@ stats.lo stats.o: $(srcdir)/daemon/stats $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ + $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h \ $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \ @@ -1325,7 +1331,7 @@ worker.lo worker.o: $(srcdir)/daemon/wor $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \ + $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h $(srcdir)/daemon/daemon.h \ $(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \ $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \ $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \ @@ -1361,7 +1367,7 @@ worker.lo worker.o: $(srcdir)/daemon/wor $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \ + $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h $(srcdir)/daemon/daemon.h \ $(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \ $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \ $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \ @@ -1386,7 +1392,7 @@ daemon.lo daemon.o: $(srcdir)/daemon/dae $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ + $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h \ $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h \ $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/tcp_conn_limit.h \ @@ -1399,7 +1405,7 @@ stats.lo stats.o: $(srcdir)/daemon/stats $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ + $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h \ $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \ @@ -1566,7 +1572,7 @@ win_svc.lo win_svc.o: $(srcdir)/winrc/wi $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h \ - $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h \ + $(srcdir)/dnstap/dnstap.h $(srcdir)/msgtap/msgtap.h $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h \ $(srcdir)/util/net_help.h w_inst.lo w_inst.o: $(srcdir)/winrc/w_inst.c config.h $(srcdir)/winrc/w_inst.h $(srcdir)/winrc/win_svc.h unbound-service-install.lo unbound-service-install.o: $(srcdir)/winrc/unbound-service-install.c config.h \ Index: daemon/daemon.c =================================================================== RCS file: /cvs/src/usr.sbin/unbound/daemon/daemon.c,v retrieving revision 1.22 diff -u -p -r1.22 daemon.c --- daemon/daemon.c 20 Oct 2022 08:26:14 -0000 1.22 +++ daemon/daemon.c 26 Apr 2024 04:44:23 -0000 @@ -533,6 +533,11 @@ daemon_create_workers(struct daemon* dae fatal_exit("dnstap enabled in config but not built with dnstap support"); #endif } + if (daemon->cfg->msgtap) { + daemon->mtenv = mt_create(daemon->cfg); + if (daemon->mtenv == NULL) + fatal_exit("unable to create msgtap environment"); + } for(i=0; inum; i++) { if(!(daemon->workers[i] = worker_create(daemon, i, shufport+numport*i/daemon->num, @@ -804,6 +809,8 @@ daemon_cleanup(struct daemon* daemon) daemon->workers = NULL; daemon->num = 0; alloc_clear_special(&daemon->superalloc); + mt_delete(daemon->mtenv); + daemon->mtenv = NULL; #ifdef USE_DNSTAP dt_delete(daemon->dtenv); daemon->dtenv = NULL; Index: daemon/daemon.h =================================================================== RCS file: /cvs/src/usr.sbin/unbound/daemon/daemon.h,v retrieving revision 1.7 diff -u -p -r1.7 daemon.h --- daemon/daemon.h 20 Oct 2022 08:26:14 -0000 1.7 +++ daemon/daemon.h 26 Apr 2024 04:44:23 -0000 @@ -129,6 +129,8 @@ struct daemon { /** the dnstap environment master value, copied and changed by threads*/ struct dt_env* dtenv; #endif + /** the msgtap environment */ + struct mt_env* mtenv; struct shm_main_info* shm_info; /** response-ip set with associated actions and tags. */ struct respip_set* respip_set; Index: daemon/worker.c =================================================================== RCS file: /cvs/src/usr.sbin/unbound/daemon/worker.c,v retrieving revision 1.36 diff -u -p -r1.36 worker.c --- daemon/worker.c 20 Oct 2022 08:26:14 -0000 1.36 +++ daemon/worker.c 26 Apr 2024 04:44:23 -0000 @@ -1343,6 +1343,12 @@ worker_handle_request(struct comm_point* dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer); } #endif + if(worker->mtenv.log_client_query_messages) { + mt_msg_send_client_query(&worker->mtenv, + (struct sockaddr *)&repinfo->client_addr, + repinfo->c->socket->addr->ai_addr, + repinfo, c->type, c->buffer); + } /* Check deny/refuse ACLs */ if(repinfo->is_proxied) { if((ret=deny_refuse_all(c, &acl, worker, repinfo, &acladdr, @@ -1793,6 +1799,12 @@ send_reply_rc: dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer); } #endif + if(worker->mtenv.log_client_response_messages) { + mt_msg_send_client_response(&worker->mtenv, + (struct sockaddr *)&repinfo->client_addr, + repinfo->c->socket->addr->ai_addr, + repinfo, c->type, c->buffer); + } if(worker->env.cfg->log_replies) { struct timeval tv; @@ -1939,6 +1951,7 @@ worker_init(struct worker* worker, struc #else void* dtenv = NULL; #endif + struct mt_env* mtenv = &worker->mtenv; #ifdef HAVE_GETTID worker->thread_tid = gettid(); #endif @@ -2002,6 +2015,13 @@ worker_init(struct worker* worker, struc fatal_exit("dt_init failed"); } #endif + if (cfg->msgtap) { + log_assert(worker->daemon->mtenv != NULL); + memcpy(&worker->mtenv, worker->daemon->mtenv, + sizeof(worker->mtenv)); + if (mt_init(&worker->mtenv, worker->base) != 0) + fatal_exit("msgtap worker initialisation failed"); + } worker->front = listen_create(worker->base, ports, cfg->msg_buffer_size, (int)cfg->incoming_num_tcp, cfg->do_tcp_keepalive @@ -2010,7 +2030,7 @@ worker_init(struct worker* worker, struc cfg->harden_large_queries, cfg->http_max_streams, cfg->http_endpoint, cfg->http_notls_downstream, worker->daemon->tcl, worker->daemon->listen_sslctx, - dtenv, worker_handle_request, worker); + dtenv, mtenv, worker_handle_request, worker); if(!worker->front) { log_err("could not create listening sockets"); worker_delete(worker); @@ -2026,7 +2046,7 @@ worker_init(struct worker* worker, struc &worker_alloc_cleanup, worker, cfg->do_udp || cfg->udp_upstream_without_downstream, worker->daemon->connect_sslctx, cfg->delay_close, - cfg->tls_use_sni, dtenv, cfg->udp_connect, + cfg->tls_use_sni, dtenv, mtenv, cfg->udp_connect, cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout, cfg->tcp_auth_query_timeout); if(!worker->back) { @@ -2209,6 +2229,7 @@ worker_delete(struct worker* worker) } dt_deinit(&worker->dtenv); #endif /* USE_DNSTAP */ + mt_deinit(&worker->mtenv); comm_base_delete(worker->base); ub_randfree(worker->rndstate); alloc_clear(&worker->alloc); Index: daemon/worker.h =================================================================== RCS file: /cvs/src/usr.sbin/unbound/daemon/worker.h,v retrieving revision 1.8 diff -u -p -r1.8 worker.h --- daemon/worker.h 20 Oct 2022 08:26:14 -0000 1.8 +++ daemon/worker.h 26 Apr 2024 04:44:23 -0000 @@ -52,6 +52,7 @@ #include "daemon/stats.h" #include "util/module.h" #include "dnstap/dnstap.h" +#include "msgtap/msgtap.h" struct listen_dnsport; struct outside_network; struct config_file; @@ -131,6 +132,8 @@ struct worker { /** dnstap environment, changed for this thread */ struct dt_env dtenv; #endif + /** msgtap environment, changed for this thread */ + struct mt_env mtenv; }; /** Index: libunbound/libworker.c =================================================================== RCS file: /cvs/src/usr.sbin/unbound/libunbound/libworker.c,v retrieving revision 1.29 diff -u -p -r1.29 libworker.c --- libunbound/libworker.c 7 Jun 2022 15:42:53 -0000 1.29 +++ libunbound/libworker.c 26 Apr 2024 04:44:23 -0000 @@ -241,7 +241,8 @@ libworker_setup(struct ub_ctx* ctx, int ports, numports, cfg->unwanted_threshold, cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w, cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx, - cfg->delay_close, cfg->tls_use_sni, NULL, cfg->udp_connect, + cfg->delay_close, cfg->tls_use_sni, NULL, /* mtenv */ NULL, + cfg->udp_connect, cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout, cfg->tcp_auth_query_timeout); w->env->outnet = w->back; Index: msgtap/libmsgtap.c =================================================================== RCS file: msgtap/libmsgtap.c diff -N msgtap/libmsgtap.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ msgtap/libmsgtap.c 26 Apr 2024 04:44:23 -0000 @@ -0,0 +1,100 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2019, 2020 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +#include "msgtap/libmsgtap.h" + +void * +msgtap_md(struct msgtap_metadata *md, uint8_t class, uint8_t type, + uint16_t len) +{ + uint8_t *md_len = (uint8_t *)&md->md_len; + + md->md_class = class; + md->md_type = type; + + md_len[0] = len >> 8; + md_len[1] = len; + + return (md + 1); +} + +void +msgtap_md_u8(struct msgtap_metadata *md, uint8_t class, uint8_t type, + uint8_t u8) +{ + uint8_t *u8p; + + u8p = msgtap_md(md, class, type, sizeof(u8)); + u8p[0] = u8; +} + +void +msgtap_md_u16(struct msgtap_metadata *md, uint8_t class, uint8_t type, + uint16_t u16) +{ + uint8_t *u16p; + + u16p = msgtap_md(md, class, type, sizeof(u16)); + u16p[0] = u16 >> 8; + u16p[1] = u16; +} + +void +msgtap_md_u32(struct msgtap_metadata *md, uint8_t class, uint8_t type, + uint32_t u32) +{ + uint8_t *u32p; + + u32p = msgtap_md(md, class, type, sizeof(u32)); + u32p[0] = u32 >> 24; + u32p[1] = u32 >> 16; + u32p[2] = u32 >> 8; + u32p[3] = u32; +} + +void +msgtap_md_u64(struct msgtap_metadata *md, uint8_t class, uint8_t type, + uint64_t u64) +{ + uint8_t *u64p; + + u64p = msgtap_md(md, class, type, sizeof(u64)); + u64p[0] = u64 >> 56; + u64p[1] = u64 >> 48; + u64p[2] = u64 >> 40; + u64p[3] = u64 >> 32; + u64p[4] = u64 >> 24; + u64p[5] = u64 >> 16; + u64p[6] = u64 >> 8; + u64p[7] = u64; +} + +void +msgtap_md_mem(struct msgtap_metadata *md, uint8_t class, uint8_t type, + const void *src, uint16_t len) +{ + void *dst; + + dst = msgtap_md(md, class, type, len); + memcpy(dst, src, len); +} Index: msgtap/libmsgtap.h =================================================================== RCS file: msgtap/libmsgtap.h diff -N msgtap/libmsgtap.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ msgtap/libmsgtap.h 26 Apr 2024 04:44:23 -0000 @@ -0,0 +1,34 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2019, 2020 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBMSGTAP_H_ +#define _LIBMSGTAP_H_ + +struct msgtap_metadata; + +void *msgtap_md(struct msgtap_metadata *, uint8_t, uint8_t, uint16_t); + +void msgtap_md_u8(struct msgtap_metadata *, uint8_t, uint8_t, uint8_t); +void msgtap_md_u16(struct msgtap_metadata *, uint8_t, uint8_t, uint16_t); +void msgtap_md_u32(struct msgtap_metadata *, uint8_t, uint8_t, uint32_t); +void msgtap_md_u64(struct msgtap_metadata *, uint8_t, uint8_t, uint64_t); + +void msgtap_md_mem(struct msgtap_metadata *, uint8_t, uint8_t, + const void *, uint16_t); + +#endif /* _LIBMSGTAP_H_ */ Index: msgtap/msgtap.c =================================================================== RCS file: msgtap/msgtap.c diff -N msgtap/msgtap.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ msgtap/msgtap.c 26 Apr 2024 04:44:23 -0000 @@ -0,0 +1,1006 @@ +/* msgtap support for Unbound */ + +/* + * Copyright (c) 2021 The University of Queensland + * Copyright (c) 2013-2014, Farsight Security, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "sldns/sbuffer.h" +#include "util/config_file.h" +#include "util/ub_event.h" +#include "util/net_help.h" +#include "util/netevent.h" +#include "util/log.h" + +#include "msgtap/msgtap.h" +#include "msgtap/libmsgtap.h" + +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +struct mt_msg; + +static int mt_connect(struct mt_env *); +static void mt_reconnect(struct mt_env *); + +static struct mt_msg *mt_msg_new(struct mt_env *, uint8_t, uint8_t); +static void mt_msg_send(struct mt_env *, struct mt_msg *, + struct sldns_buffer *); +static void mt_msg_free(struct mt_msg *); + +static int mt_msg_add_bytes(struct mt_msg *, uint8_t, uint8_t, + const void *, size_t); +static int mt_msg_add_iptype(struct mt_msg *, + const struct sockaddr *); +static int mt_msg_add_cptype(struct mt_msg *, + enum comm_point_type); +static int mt_msg_add_net(struct mt_msg *, uint8_t, uint8_t, + const struct sockaddr *sa); +static int mt_msg_add_port(struct mt_msg *, uint8_t, + const struct sockaddr *sa); +static int mt_msg_add_tm(struct mt_msg *, uint64_t); + +static const char mt_name[] = "unbound"; + +static void +mt_apply_identity(struct mt_env *env, struct config_file *cfg) +{ + char buf[MAXHOSTNAMELEN+1]; + if (!cfg->msgtap_send_identity) + return; + free(env->identity); + if (cfg->msgtap_identity == NULL || cfg->msgtap_identity[0] == 0) { + if (gethostname(buf, MAXHOSTNAMELEN) == 0) { + buf[MAXHOSTNAMELEN] = 0; + env->identity = strdup(buf); + } else { + fatal_exit("mt_apply_identity: gethostname() failed"); + } + } else { + env->identity = strdup(cfg->msgtap_identity); + } + if (env->identity == NULL) + fatal_exit("dt_apply_identity: strdup() failed"); + env->identity_len = (unsigned int)strlen(env->identity); + verbose(VERB_OPS, "msgtap identity field set to \"%s\"", + env->identity); +} + +static void +mt_apply_version(struct mt_env *env, struct config_file *cfg) +{ + if (!cfg->msgtap_send_version) + return; + free(env->version); + if (cfg->msgtap_version == NULL || cfg->msgtap_version[0] == 0) + env->version = strdup(PACKAGE_STRING); + else + env->version = strdup(cfg->msgtap_version); + if (env->version == NULL) + fatal_exit("dt_apply_version: strdup() failed"); + env->version_len = (unsigned int)strlen(env->version); + verbose(VERB_OPS, "msgtap version field set to \"%s\"", + env->version); +} + +static void +mt_apply_cfg(struct mt_env *env, struct config_file *cfg) +{ + mt_apply_identity(env, cfg); + mt_apply_version(env, cfg); + + if ((env->log_resolver_query_messages = (unsigned int) + cfg->msgtap_log_resolver_query_messages)) { + verbose(VERB_OPS, "msgtap RESOLVER_QUERY enabled"); + } + if ((env->log_resolver_response_messages = (unsigned int) + cfg->msgtap_log_resolver_response_messages)) + { + verbose(VERB_OPS, "msgtap RESOLVER_RESPONSE enabled"); + } + if ((env->log_client_query_messages = (unsigned int) + cfg->msgtap_log_client_query_messages)) + { + verbose(VERB_OPS, "msgtap CLIENT_QUERY enabled"); + } + if ((env->log_client_response_messages = (unsigned int) + cfg->msgtap_log_client_response_messages)) + { + verbose(VERB_OPS, "msgtap CLIENT_RESPONSE enabled"); + } + if ((env->log_forwarder_query_messages = (unsigned int) + cfg->msgtap_log_forwarder_query_messages)) + { + verbose(VERB_OPS, "msgtap FORWARDER_QUERY enabled"); + } + if ((env->log_forwarder_response_messages = (unsigned int) + cfg->msgtap_log_forwarder_response_messages)) + { + verbose(VERB_OPS, "msgtap FORWARDER_RESPONSE enabled"); + } +} + +struct mt_env * +mt_create(struct config_file *cfg) +{ + char hostname[MAXHOSTNAMELEN]; + struct mt_env *env; + + if (gethostname(hostname, sizeof(hostname)) == -1) { + log_err("msgtap gethostname: %s", strerror(errno)); + return (NULL); + } + + if (cfg->msgtap_socket_path == NULL || + strlen(cfg->msgtap_socket_path) == 0) { + log_err("msgtap: msgtap-socket-path not defined"); + return (NULL); + } + + env = calloc(1, sizeof(*env)); + if (env == NULL) + return (NULL); + + env->hostname = strdup(hostname); + if (env->hostname == NULL) { + log_err("msgtap hostname copy: %s", strerror(errno)); + goto free; + } + env->hostname_len = strlen(env->hostname); + + env->fd = -1; + env->seq = 0; + env->socket_path = strdup(cfg->msgtap_socket_path); + if (env->socket_path == NULL) { + log_err("msgtap: msgtap-socket-path copy: %s", + strerror(ENOMEM)); + goto free_hostname; + } + + mt_apply_cfg(env, cfg); + + return (env); + +free_hostname: + free(env->hostname); +free: + free(env); + return (NULL); +} + +/** + * Initialize per-worker state. + */ +int +mt_init(struct mt_env *env, struct comm_base *cb) +{ + int fd; + + log_warn("msgtap-socket-path %s", env->socket_path); + + env->cb = cb; + + env->pid = getpid(); + env->thrid = getthrid(); + + env->fd = mt_connect(env); + if (env->fd == -1) { + log_warn("msgtap-socket-path %s: %s", + env->socket_path, strerror(errno)); + mt_reconnect(env); + } + + return (0); +} + +/** + * Deletes the per-worker state created by mt_init. + */ +void +mt_deinit(struct mt_env *env) +{ + if (env->reconnect_ev != NULL) { + log_assert(env->fd == -1); + ub_timer_del(env->reconnect_ev); + ub_event_free(env->reconnect_ev); + env->reconnect_ev = NULL; + } + if (env->fd != -1) { + close(env->fd); + env->fd = -1; + } +} + +/** + * Delete msgtap environment object. + */ +void +mt_delete(struct mt_env *env) +{ + free(env->socket_path); + free(env); +} + +static int +mt_msg_add_commnet(struct mt_msg *mt_msg, uint8_t cl_addr, uint8_t cl_port, + const struct sockaddr *sa, const struct comm_reply *rep) +{ + const void *addr; + size_t addrlen; + + switch (rep->srctype) { + case 0: + return (mt_msg_add_net(mt_msg, cl_addr, cl_port, sa)); + case 4: +#ifdef IP_PKTINFO + addr = &rep->pktinfo.v4info.ipi_addr; + addrlen = sizeof(rep->pktinfo.v4info.ipi_addr); +#elif defined(IP_RECVDSTADDR) + addr = &rep->pktinfo.v4addr; + addrlen = sizeof(rep->pktinfo.v4addr); +#endif /* IP_PKTINFO or IP_RECVDSTADDR */ + break; + case 6: + addr = &rep->pktinfo.v6info.ipi6_addr; + addrlen = sizeof(rep->pktinfo.v6info.ipi6_addr); + break; + } + + if (mt_msg_add_bytes(mt_msg, MSGTAP_CLASS_BASE, cl_addr, + addr, addrlen) == -1) { + /* log */ + return (-1); + } + + if (mt_msg_add_port(mt_msg, cl_port, sa) == -1) { + /* log */ + return (-1); + } + + return (0); +} + +void +mt_msg_send_client_query(struct mt_env *env, + const struct sockaddr *qsock, const struct sockaddr *rsock, + const struct comm_reply *rep, + enum comm_point_type cptype, struct sldns_buffer *qmsg) +{ + struct mt_msg *mt_msg; + + mt_msg = mt_msg_new(env, MSGTAP_T_NET_DIR_IN, DNSMSGTAP_MSGTYPE_CQ); + if (mt_msg == NULL) + return; + + if (mt_msg_add_iptype(mt_msg, qsock) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_net(mt_msg, MSGTAP_T_IPSRCADDR, MSGTAP_T_IPSRCPORT, + qsock) == -1) { + /* log */ + goto free; + } + +#if 0 + if (mt_msg_add_commnet(mt_msg, MSGTAP_T_IPDSTADDR, MSGTAP_T_IPDSTPORT, + rsock, rep) == -1) { + /* log */ + goto free; + } +#else + if (mt_msg_add_net(mt_msg, MSGTAP_T_IPDSTADDR, MSGTAP_T_IPDSTPORT, + (const struct sockaddr *)&rep->local_addr) == -1) { + /* log */ + goto free; + } +#endif + + if (mt_msg_add_cptype(mt_msg, cptype) == -1) { + /* log */ + goto free; + } + + mt_msg_send(env, mt_msg, qmsg); +free: + mt_msg_free(mt_msg); +} + +void +mt_msg_send_client_response(struct mt_env *env, + const struct sockaddr *qsock, const struct sockaddr *rsock, + const struct comm_reply *rep, + enum comm_point_type cptype, struct sldns_buffer *rmsg) +{ + struct mt_msg *mt_msg; + + mt_msg = mt_msg_new(env, MSGTAP_T_NET_DIR_OUT, DNSMSGTAP_MSGTYPE_CR); + if (mt_msg == NULL) + return; + + if (mt_msg_add_iptype(mt_msg, qsock) == -1) { + /* log */ + goto free; + } + +#if 0 + if (mt_msg_add_commnet(mt_msg, MSGTAP_T_IPSRCADDR, MSGTAP_T_IPSRCPORT, + rsock, rep) == -1) { + /* log */ + goto free; + } +#else + if (mt_msg_add_net(mt_msg, MSGTAP_T_IPSRCADDR, MSGTAP_T_IPSRCPORT, + (const struct sockaddr *)&rep->local_addr) == -1) { + /* log */ + goto free; + } +#endif + + if (mt_msg_add_net(mt_msg, MSGTAP_T_IPDSTADDR, MSGTAP_T_IPDSTPORT, + qsock) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_cptype(mt_msg, cptype) == -1) { + /* log */ + goto free; + } + + mt_msg_send(env, mt_msg, rmsg); +free: + mt_msg_free(mt_msg); +} + +void +mt_msg_send_outside_query(struct mt_env *env, + const struct sockaddr *rsock, const struct sockaddr *qsock, + enum comm_point_type cptype, const uint8_t *zone, size_t zone_len, + struct sldns_buffer *qmsg) +{ + struct mt_msg *mt_msg; + uint16_t qflags; + uint8_t type; + + qflags = sldns_buffer_read_u16_at(qmsg, 2); + if (qflags & BIT_RD) { + if (!env->log_forwarder_query_messages) + return; + type = DNSMSGTAP_MSGTYPE_FQ; + } else { + if (!env->log_resolver_query_messages) + return; + type = DNSMSGTAP_MSGTYPE_RQ; + } + + mt_msg = mt_msg_new(env, MSGTAP_T_NET_DIR_OUT, type); + if (mt_msg == NULL) + return; + + if (mt_msg_add_iptype(mt_msg, qsock) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_net(mt_msg, MSGTAP_T_IPSRCADDR, MSGTAP_T_IPSRCPORT, + qsock) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_net(mt_msg, MSGTAP_T_IPDSTADDR, MSGTAP_T_IPDSTPORT, + rsock) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_cptype(mt_msg, cptype) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_bytes(mt_msg, + MSGTAP_CLASS_TYPED, DNSMSGTAP_QUERY_ZONE, + zone, zone_len) == -1) { + /* log */ + goto free; + } + + mt_msg_send(env, mt_msg, qmsg); +free: + mt_msg_free(mt_msg); +} + +void +mt_msg_send_outside_response(struct mt_env *env, + const struct sockaddr *rsock, const struct sockaddr *qsock, + enum comm_point_type cptype, + const uint8_t *zone, size_t zone_len, + const uint8_t *qbuf, size_t qbuf_len, + const struct timeval *qtime, const struct timeval *rtime, + struct sldns_buffer *rmsg) +{ + struct mt_msg *mt_msg; + uint16_t qflags; + uint8_t type; + struct timeval diff; + uint64_t ival; + + timersub(rtime, qtime, &diff); + ival = diff.tv_sec * 1000000000ULL; + ival += diff.tv_usec *= 1000ULL; + + qflags = sldns_buffer_read_u16_at(rmsg, 2); + if (qflags & BIT_RD) { + if (!env->log_forwarder_response_messages) + return; + type = DNSMSGTAP_MSGTYPE_FR; + } else { + if (!env->log_resolver_response_messages) + return; + type = DNSMSGTAP_MSGTYPE_RR; + } + + mt_msg = mt_msg_new(env, MSGTAP_T_NET_DIR_IN, type); + if (mt_msg == NULL) + return; + + if (mt_msg_add_tm(mt_msg, ival) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_iptype(mt_msg, qsock) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_net(mt_msg, MSGTAP_T_IPSRCADDR, MSGTAP_T_IPSRCPORT, + rsock) == -1) { + /* log */ + goto free; + } + + /* this appears is 0.0.0.0/53 for some reason */ + if (mt_msg_add_net(mt_msg, MSGTAP_T_IPDSTADDR, MSGTAP_T_IPDSTPORT, + qsock) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_cptype(mt_msg, cptype) == -1) { + /* log */ + goto free; + } + + if (mt_msg_add_bytes(mt_msg, + MSGTAP_CLASS_TYPED, DNSMSGTAP_QUERY_ZONE, + zone, zone_len) == -1) { + /* log */ + goto free; + } + + mt_msg_send(env, mt_msg, rmsg); +free: + mt_msg_free(mt_msg); +} + +struct mt_msg { + void *msg; + size_t msglen; +}; + +static void * +mt_msg_md_realloc(struct mt_msg *mt_msg, size_t len) +{ + uint8_t *msg; + size_t olen, nlen; + + if (len > 0xffff) { + errno = EMSGSIZE; + return (NULL); + } + + olen = mt_msg->msglen; + nlen = olen + sizeof(struct msgtap_metadata) + len; + msg = realloc(mt_msg->msg, nlen); + if (msg == NULL) + return (NULL); + + mt_msg->msg = msg; + mt_msg->msglen = nlen; + + return (msg + olen); +} + +static int +mt_msg_add_ts(struct mt_msg *mt_msg, const struct timespec *ts) +{ + struct msgtap_metadata *md; + uint64_t nsec; + + nsec = (ts->tv_sec * 1000000000ULL) + ts->tv_nsec; + + md = mt_msg_md_realloc(mt_msg, sizeof(nsec)); + if (md == NULL) + return (-1); + + msgtap_md_u64(md, MSGTAP_CLASS_BASE, MSGTAP_T_TS, nsec); + + return (0); +} + +static int +mt_msg_add_tm(struct mt_msg *mt_msg, uint64_t nsec) +{ + struct msgtap_metadata *md; + + md = mt_msg_md_realloc(mt_msg, sizeof(nsec)); + if (md == NULL) + return (-1); + + msgtap_md_u64(md, MSGTAP_CLASS_BASE, MSGTAP_T_TM, nsec); + + return (0); +} + +static int +mt_msg_add_flag(struct mt_msg *mt_msg, uint8_t class, uint8_t type) +{ + struct msgtap_metadata *md; + + md = mt_msg_md_realloc(mt_msg, 0); + if (md == NULL) + return (-1); + + msgtap_md(md, class, type, 0); + + return (0); +} + +static int +mt_msg_add_bytes(struct mt_msg *mt_msg, uint8_t class, uint8_t type, + const void *buf, size_t buflen) +{ + struct msgtap_metadata *md; + + md = mt_msg_md_realloc(mt_msg, buflen); + if (md == NULL) + return (-1); + + msgtap_md_mem(md, class, type, buf, buflen); + + return (0); +} + +static int +mt_msg_add_u32(struct mt_msg *mt_msg, uint8_t class, uint8_t type, uint32_t u32) +{ + struct msgtap_metadata *md; + + md = mt_msg_md_realloc(mt_msg, sizeof(u32)); + if (md == NULL) + return (-1); + + msgtap_md_u32(md, class, type, u32); + + return (0); +} + +static int +mt_msg_add_u16(struct mt_msg *mt_msg, uint8_t class, uint8_t type, uint16_t u16) +{ + struct msgtap_metadata *md; + + md = mt_msg_md_realloc(mt_msg, sizeof(u16)); + if (md == NULL) + return (-1); + + msgtap_md_u16(md, class, type, u16); + + return (0); +} + +static int +mt_msg_add_u8(struct mt_msg *mt_msg, uint8_t class, uint8_t type, uint8_t u8) +{ + struct msgtap_metadata *md; + + md = mt_msg_md_realloc(mt_msg, sizeof(u8)); + if (md == NULL) + return (-1); + + msgtap_md_u8(md, class, type, u8); + + return (0); +} + +static int +mt_msg_add_iptype(struct mt_msg *mt_msg, const struct sockaddr *sa) +{ + uint8_t iptype; + + switch (sa->sa_family) { + case AF_INET: + iptype = MSGTAP_T_IPV4; + break; + case AF_INET6: + iptype = MSGTAP_T_IPV6; + break; + default: + fatal_exit("%s: unsupported address family %u", __func__, + sa->sa_family); + /* NOTREACHED */ + } + + if (mt_msg_add_flag(mt_msg, MSGTAP_CLASS_BASE, iptype) == -1) + return (-1); + + return (0); +} + +static int +mt_msg_add_cptype(struct mt_msg *mt_msg, enum comm_point_type cptype) +{ + uint8_t ipproto; + + switch (cptype) { + case comm_udp: + ipproto = MSGTAP_T_IPPROTO_UDP; + break; + case comm_tcp: + ipproto = MSGTAP_T_IPPROTO_TCP; + break; + default: + fatal_exit("%s: unsupported cptype %u", __func__, cptype); + /* NOTREACHED */ + return (0); + } + + if (mt_msg_add_u8(mt_msg, MSGTAP_CLASS_BASE, MSGTAP_T_IPPROTO, + ipproto) == -1) + return (-1); + + return (0); +} + +static int +mt_msg_add_port(struct mt_msg *mt_msg, uint8_t cl_port, + const struct sockaddr *sa) +{ + in_port_t port; + + switch (sa->sa_family) { + case AF_INET: { + const struct sockaddr_in *sin = (struct sockaddr_in *)sa; + port = sin->sin_port; + break; + } + case AF_INET6: { + const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + port = sin6->sin6_port; + break; + } + default: + fatal_exit("%s: unsupported address family %u", __func__, + sa->sa_family); + /* NOTREACHED */ + } + + if (mt_msg_add_u16(mt_msg, MSGTAP_CLASS_BASE, cl_port, + ntohs(port)) == -1) + return (-1); + + return (0); +} + +static int +mt_msg_add_net(struct mt_msg *mt_msg, uint8_t cl_addr, uint8_t cl_port, + const struct sockaddr *sa) +{ + const void *addr; + in_port_t port; + size_t addrlen; + + switch (sa->sa_family) { + case AF_INET: { + const struct sockaddr_in *sin = (struct sockaddr_in *)sa; + + addr = &sin->sin_addr; + addrlen = sizeof(sin->sin_addr); + + port = sin->sin_port; + + break; + } + case AF_INET6: { + const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + + addr = &sin6->sin6_addr; + addrlen = sizeof(sin6->sin6_addr); + + port = sin6->sin6_port; + + break; + } + default: + fatal_exit("%s: unsupported address family %u", __func__, + sa->sa_family); + /* NOTREACHED */ + } + + if (mt_msg_add_bytes(mt_msg, MSGTAP_CLASS_BASE, cl_addr, + addr, addrlen) == -1) + return (-1); + + if (mt_msg_add_u16(mt_msg, MSGTAP_CLASS_BASE, cl_port, + ntohs(port)) == -1) + return (-1); + + return (0); +} + +static struct mt_msg * +mt_msg_new(struct mt_env *env, uint8_t dir, uint8_t msgtype) +{ + struct mt_msg *mt_msg; + struct msgtap_header *mh; + struct msgtap_metadata *md; + + struct timespec ts; + uint32_t seq; + + seq = env->seq++; + + if (env->fd == -1) + return (NULL); + + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + log_warn("could not get time for msg %u seq %u: %s", + msgtype, seq, strerror(errno)); + return (NULL); + } + + mt_msg = malloc(sizeof(*mt_msg)); + if (mt_msg == NULL) + goto warn; + + mt_msg->msg = NULL; + mt_msg->msglen = 0; + + if (mt_msg_add_ts(mt_msg, &ts) == -1) + goto free; + + if (mt_msg_add_bytes(mt_msg, MSGTAP_CLASS_BASE, MSGTAP_T_HOSTNAME, + env->hostname, env->hostname_len) == -1) + goto free; + + if (mt_msg_add_bytes(mt_msg, MSGTAP_CLASS_BASE, MSGTAP_T_NAME, + mt_name, sizeof(mt_name) - 1) == -1) + goto free; + + if (mt_msg_add_u32(mt_msg, + MSGTAP_CLASS_BASE, MSGTAP_T_PID, env->pid) == -1) + goto free; + + if (mt_msg_add_u32(mt_msg, + MSGTAP_CLASS_BASE, MSGTAP_T_TID, env->thrid) == -1) + goto free; + + if (mt_msg_add_u32(mt_msg, + MSGTAP_CLASS_BASE, MSGTAP_T_SEQ32, seq) == -1) + goto free; + + if (mt_msg_add_u8(mt_msg, + MSGTAP_CLASS_TYPED, DNSMSGTAP_MSGTYPE, msgtype) == -1) + goto free; + + if (mt_msg_add_u8(mt_msg, + MSGTAP_CLASS_BASE, MSGTAP_T_NET_DIR, dir) == -1) + goto free; + + return (mt_msg); + +free: + free(mt_msg->msg); +free_mt_msg: + free(mt_msg); +warn: + log_warn("unable to allocate buffer for msg %u seq %u: %s", + msgtype, seq, strerror(errno)); + + return (NULL); +} + +static void +mt_msg_send(struct mt_env *env, struct mt_msg *mt_msg, + struct sldns_buffer *buf) +{ + struct msgtap_header mh; + struct iovec iov[3]; + struct msghdr msg = { + .msg_iov = iov, + .msg_iovlen = nitems(iov), + }; + uint32_t buflen; + ssize_t rv; + + if (mt_msg->msglen > 0xffffffff) { + /* metadata is too long */ + return; + } + if (sldns_buffer_limit(buf) > 0xffffffff) { + /* buffer is too long */ + return; + } + buflen = sldns_buffer_limit(buf); + + mh.mh_flags = htons(MSGTAP_F_VERSION_0); + mh.mh_type = htons(MSGTAP_TYPE_DNS); + mh.mh_metalen = htonl(mt_msg->msglen); + mh.mh_msglen = htonl(buflen); + mh.mh_caplen = htonl(buflen); + + iov[0].iov_base = &mh; + iov[0].iov_len = sizeof(mh); + iov[1].iov_base = mt_msg->msg; + iov[1].iov_len = mt_msg->msglen; + iov[2].iov_base = sldns_buffer_begin(buf); + iov[2].iov_len = buflen; + + rv = sendmsg(env->fd, &msg, 0); + if (rv == -1) { + switch (errno) { + case ENOBUFS: + /* oh well */ + return; + case EPIPE: + /* we'll try and fix this */ + break; + default: + log_warn("msgtap send: %s", strerror(errno)); + } + + close(env->fd); + env->fd = mt_connect(env); + if (env->fd == -1) { + log_warn("msgtap retry: %s", strerror(errno)); + mt_reconnect(env); + return; + } + + rv = sendmsg(env->fd, &msg, 0); + if (rv == -1) { + log_warn("msgtap send: %s", strerror(errno)); + close(env->fd); + env->fd = -1; + mt_reconnect(env); + return; + } + } +} + +static void +mt_msg_free(struct mt_msg *mt_msg) +{ + free(mt_msg->msg); + free(mt_msg); +} + +/* + * + */ + +static void mt_reconnect_cb(int, short, void *); + +static int +mt_connect(struct mt_env *env) +{ + struct sockaddr_un sun = { .sun_family = AF_UNIX }; + int fd = -1; + + if (strlcpy(sun.sun_path, env->socket_path, + sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) { + errno = ENAMETOOLONG; + return (-1); + } + + fd = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0); + if (fd == -1) + return (-1); + + if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { + close(fd); + return (-1); + } + + /* all good */ + return (fd); +} + +static void +mt_reconnect_add(struct mt_env *env) +{ + struct timeval tv; + + tv.tv_sec = 1; + tv.tv_usec = arc4random_uniform(1000000); + + if (ub_timer_add(env->reconnect_ev, comm_base_internal(env->cb), + mt_reconnect_cb, env, &tv) != 0) + fatal_exit("msgtap reconnect: timer add failed"); +} + +static void +mt_reconnect_cb(int zero, short events, void *arg) +{ + struct mt_env *env = arg; + int fd; + + fd = mt_connect(env); + if (fd == -1) { + mt_reconnect_add(env); + return; + } + + verbose(VERB_OPS, "msgtap %s reconnected (seq %u)", + env->socket_path, env->seq); + + ub_event_free(env->reconnect_ev); + env->reconnect_ev = NULL; + + env->fd = fd; +} + +static void +mt_reconnect(struct mt_env *env) +{ + env->reconnect_ev = ub_event_new(comm_base_internal(env->cb), + 0, UB_EV_TIMEOUT, mt_reconnect_cb, env); + if (env->reconnect_ev == NULL) + fatal_exit("msgtap reconnect: %s", strerror(ENOMEM)); + + mt_reconnect_add(env); +} Index: msgtap/msgtap.h =================================================================== RCS file: msgtap/msgtap.h diff -N msgtap/msgtap.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ msgtap/msgtap.h 26 Apr 2024 04:44:23 -0000 @@ -0,0 +1,190 @@ +/* msgtap support for Unbound */ + +/* + * Copyright (c) 2021 The Universty of Queensland + * Copyright (c) 2013-2014, Farsight Security, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UNBOUND_MSGTAP_H +#define UNBOUND_MSGTAP_H + +struct config_file; +struct ub_event; + +struct mt_env { + char *hostname; + size_t hostname_len; + char *identity; + size_t identity_len; + char *version; + size_t version_len; + + char *socket_path; + struct comm_base * + cb; + + int fd; + struct ub_event *reconnect_ev; + + uint32_t pid; + uint32_t thrid; + uint32_t seq; + + /** whether to log Message/RESOLVER_QUERY */ + unsigned log_resolver_query_messages : 1; + /** whether to log Message/RESOLVER_RESPONSE */ + unsigned log_resolver_response_messages : 1; + /** whether to log Message/CLIENT_QUERY */ + unsigned log_client_query_messages : 1; + /** whether to log Message/CLIENT_RESPONSE */ + unsigned log_client_response_messages : 1; + /** whether to log Message/FORWARDER_QUERY */ + unsigned log_forwarder_query_messages : 1; + /** whether to log Message/FORWARDER_RESPONSE */ + unsigned log_forwarder_response_messages : 1; +}; + +/** + * Create msgtap environment object. Afterwards, call dt_apply_cfg() to fill in + * the config variables and dt_init() to fill in the per-worker state. Each + * worker needs a copy of this object but with its own I/O queue (the fq field + * of the structure) to ensure lock-free access to its own per-worker circular + * queue. Duplicate the environment object if more than one worker needs to + * share access to the dnstap I/O socket. + * @param cfg: with config settings. + * @return dt_env object, NULL on failure. + */ +struct mt_env * + mt_create(struct config_file *cfg); + +/** + * Initialize per-worker state in dnstap environment object. + * @param env: msgtap environment object to initialize, created with mt_create(). + * @param base: event base for wakeup timer. + * @return: true on success, false on failure. + */ +int mt_init(struct mt_env *env, struct comm_base* base); + +/** + * Deletes the per-worker state created by mt_init + */ +void mt_deinit(struct mt_env *env); + +/** + * Delete msgtap environment object. + */ +void mt_delete(struct mt_env *env); + +enum comm_point_type; +struct sockaddr; +struct timeval; +struct sldns_buffer; + +/** + * Create and send a new msgtap record of type CLIENT_QUERY. + * @param env: msgtap 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 +mt_msg_send_client_query(struct mt_env *env, + const struct sockaddr *qsock, + const struct sockaddr *rsock, + const struct comm_reply *rep, + enum comm_point_type cptype, + struct sldns_buffer *qmsg); + +/** + * Create and send a new msgtap record of type CLIENT_RESPONSE. + * @param env: msgtap 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 +mt_msg_send_client_response(struct mt_env *env, + const struct sockaddr *qsock, + const struct sockaddr *rsock, + const struct comm_reply *rep, + enum comm_point_type cptype, + struct sldns_buffer *rmsg); + + +/** + * Create and send a new msgtap record of type RESOLVER_QUERY or + * FORWARDER_QUERY. The type used is dependent on the value of the RD bit + * in the query header. + * @param env: msgtap environment object. + * @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. + * @param qmsg: query message. + */ +void mt_msg_send_outside_query(struct mt_env *env, + const struct sockaddr *rsock, + const struct sockaddr *qsock, + enum comm_point_type cptype, + const uint8_t *zone, size_t zone_len, + struct sldns_buffer *qmsg); + +/** + * Create and send a new msgtap record of type RESOLVER_RESPONSE or + * FORWARDER_RESPONSE. The type used is dependent on the value of the RD bit + * in the query header. + * @param env: msgtap environment object. + * @param rsock: address/port of server (upstream) the response was received fro +m. + * @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. + * @param qbuf: outside_network's qbuf key. + * @param qbuf_len: length of outside_network's qbuf key. + * @param qtime: time query message was sent. + * @param rtime: time response message was sent. + * @param rmsg: response message. + */ +void +mt_msg_send_outside_response(struct mt_env *env, + const struct sockaddr *rsock, const struct sockaddr *qsock, + enum comm_point_type cptype, + const uint8_t *zone, size_t zone_len, + const uint8_t *qbuf, size_t qbuf_len, + const struct timeval *qtime, + const struct timeval *rtime, + struct sldns_buffer *rmsg); + +#endif /* UNBOUND_MSGTAP_H */ Index: services/listen_dnsport.c =================================================================== RCS file: /cvs/src/usr.sbin/unbound/services/listen_dnsport.c,v retrieving revision 1.33 diff -u -p -r1.33 listen_dnsport.c --- services/listen_dnsport.c 20 Oct 2022 08:26:14 -0000 1.33 +++ services/listen_dnsport.c 26 Apr 2024 04:44:23 -0000 @@ -1291,6 +1291,13 @@ ports_create_if(const char* ifname, int } return 0; } + /* getting source addr packet info is highly non-portable */ + if(!set_recvpktinfo(s, hints->ai_family)) { + sock_close(s); + freeaddrinfo(ub_sock->addr); + free(ub_sock); + return 0; + } if(!port_insert(list, s, is_dnscrypt ?listen_type_udp_dnscrypt:listen_type_udp, is_pp2, ub_sock)) { @@ -1394,8 +1401,8 @@ listen_create(struct comm_base* base, st 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) + void* sslctx, struct dt_env* dtenv, struct mt_env* mtenv, + comm_point_callback_type* cb, void *cb_arg) { struct listen_dnsport* front = (struct listen_dnsport*) malloc(sizeof(struct listen_dnsport)); @@ -1416,7 +1423,7 @@ listen_create(struct comm_base* base, st struct comm_point* cp = NULL; if(ports->ftype == listen_type_udp || ports->ftype == listen_type_udp_dnscrypt) { - cp = comm_point_create_udp(base, ports->fd, + cp = comm_point_create_udp_ancil(base, ports->fd, front->udp_buff, ports->pp2_enabled, cb, cb_arg, ports->socket); } else if(ports->ftype == listen_type_tcp || @@ -1480,6 +1487,7 @@ listen_create(struct comm_base* base, st else cp->ssl = sslctx; cp->dtenv = dtenv; + cp->mtenv = mtenv; cp->do_not_close = 1; #ifdef USE_DNSCRYPT if (ports->ftype == listen_type_udp_dnscrypt || Index: services/listen_dnsport.h =================================================================== RCS file: /cvs/src/usr.sbin/unbound/services/listen_dnsport.h,v retrieving revision 1.19 diff -u -p -r1.19 listen_dnsport.h --- services/listen_dnsport.h 20 Oct 2022 08:26:14 -0000 1.19 +++ services/listen_dnsport.h 26 Apr 2024 04:44:23 -0000 @@ -196,8 +196,8 @@ listen_create(struct comm_base* base, st 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); + void* sslctx, struct dt_env* dtenv, struct mt_env* mtenv, + comm_point_callback_type* cb, void *cb_arg); /** * delete the listening structure Index: services/outside_network.c =================================================================== RCS file: /cvs/src/usr.sbin/unbound/services/outside_network.c,v retrieving revision 1.27 diff -u -p -r1.27 outside_network.c --- services/outside_network.c 20 Oct 2022 08:26:14 -0000 1.27 +++ services/outside_network.c 26 Apr 2024 04:44:23 -0000 @@ -61,6 +61,7 @@ #include "util/edns.h" #include "sldns/sbuffer.h" #include "dnstap/dnstap.h" +#include "msgtap/msgtap.h" #ifdef HAVE_OPENSSL_SSL_H #include #endif @@ -917,9 +918,7 @@ use_free_buffer(struct outside_network* { struct waiting_tcp* w; while(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_waiting_tcp_list_pop(outnet); log_assert( @@ -933,9 +932,7 @@ use_free_buffer(struct outside_network* 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; @@ -962,13 +959,9 @@ use_free_buffer(struct outside_network* 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 } else { /* no reuse and no free buffer, put back at the start */ outnet_waiting_tcp_list_add_first(outnet, w, 0); @@ -985,6 +978,16 @@ use_free_buffer(struct outside_network* w->sq->zonelen, &tmp); } #endif + if (outnet->mtenv && pend_tcp && w && w->sq && + (outnet->mtenv->log_resolver_query_messages || + outnet->mtenv->log_forwarder_query_messages)) { + sldns_buffer tmp; + sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len); + mt_msg_send_outside_query(outnet->mtenv, + (struct sockaddr *)&w->sq->addr, + (struct sockaddr *)&pend_tcp->pi->addr, comm_tcp, + w->sq->zone, w->sq->zonelen, &tmp); + } } } @@ -1634,8 +1637,8 @@ outside_network_create(struct comm_base int numavailports, size_t unwanted_threshold, int tcp_mss, void (*unwanted_action)(void*), void* unwanted_param, int do_udp, void* sslctx, int delayclose, int tls_use_sni, struct dt_env* dtenv, - int udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout, - int tcp_auth_query_timeout) + struct mt_env *mtenv, int udp_connect, int max_reuse_tcp_queries, + int tcp_reuse_timeout, int tcp_auth_query_timeout) { struct outside_network* outnet = (struct outside_network*) calloc(1, sizeof(struct outside_network)); @@ -1661,6 +1664,7 @@ outside_network_create(struct comm_base #else (void)dtenv; #endif + outnet->mtenv = mtenv; outnet->svcd_overhead = 0; outnet->want_to_quit = 0; outnet->unwanted_threshold = unwanted_threshold; @@ -2213,6 +2217,14 @@ randomize_and_send_udp(struct pending* p pend->sq->zone, pend->sq->zonelen, packet); } #endif + if(outnet->mtenv && + (outnet->mtenv->log_resolver_query_messages || + outnet->mtenv->log_forwarder_query_messages)) { + mt_msg_send_outside_query(outnet->mtenv, + (struct sockaddr *)&pend->addr, + (struct sockaddr *)&pend->pc->pif->addr, comm_udp, + pend->sq->zone, pend->sq->zonelen, packet); + } return 1; } @@ -2442,9 +2454,7 @@ pending_tcp_query(struct serviced_query* w->write_wait_next = NULL; w->write_wait_queued = 0; w->error_count = 0; -#ifdef USE_DNSTAP w->sq = NULL; -#endif w->in_cb_and_decommission = 0; if(pend) { /* we have a buffer available right now */ @@ -2493,14 +2503,23 @@ pending_tcp_query(struct serviced_query* sq->zonelen, &tmp); } #endif + if (sq->outnet->mtenv && + (sq->outnet->mtenv->log_resolver_query_messages || + sq->outnet->mtenv->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); + mt_msg_send_outside_query(sq->outnet->mtenv, + (struct sockaddr *)&sq->addr, + (struct sockaddr *)&pend->pi->addr, comm_tcp, + sq->zone, sq->zonelen, &tmp); + } } 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_waiting_tcp_list_add(sq->outnet, w, 1); } return w; @@ -3029,7 +3048,6 @@ serviced_tcp_callback(struct comm_point* { 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 = NULL; struct port_if* pi = NULL; @@ -3037,7 +3055,6 @@ serviced_tcp_callback(struct comm_point* pend_tcp = (struct pending_tcp*)w->next_waiting; pi = pend_tcp->pi; } -#endif sq->pending = NULL; /* removed after this callback */ if(error != NETEVENT_NOERROR) log_addr(VERB_QUERY, "tcp error for address", @@ -3060,6 +3077,16 @@ serviced_tcp_callback(struct comm_point* c->buffer); } #endif + if(error==NETEVENT_NOERROR && sq->outnet->mtenv && + (sq->outnet->mtenv->log_resolver_response_messages || + sq->outnet->mtenv->log_forwarder_response_messages)) { + mt_msg_send_outside_response(sq->outnet->mtenv, + (struct sockaddr *)&sq->addr, + (struct sockaddr *)&pi->addr, c->type, + sq->zone, sq->zonelen, sq->qbuf, + sq->qbuflen, &sq->last_sent_time, + sq->outnet->now_tv, c->buffer); + } if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS && (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(sldns_buffer_begin( @@ -3218,9 +3245,7 @@ serviced_udp_callback(struct comm_point* 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; -#endif sq->pending = NULL; /* removed after callback */ if(error == NETEVENT_TIMEOUT) { @@ -3273,6 +3298,16 @@ serviced_udp_callback(struct comm_point* sq->outnet->now_tv, c->buffer); } #endif + if(error == NETEVENT_NOERROR && outnet->mtenv && + (outnet->mtenv->log_resolver_response_messages || + outnet->mtenv->log_forwarder_response_messages)) { + mt_msg_send_outside_response(outnet->mtenv, + (struct sockaddr *)&sq->addr, + (struct sockaddr *)&p->pc->pif->addr, c->type, + sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, + &sq->last_sent_time, sq->outnet->now_tv, + c->buffer); + } if( (sq->status == serviced_query_UDP_EDNS ||sq->status == serviced_query_UDP_EDNS_FRAG) && (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) Index: services/outside_network.h =================================================================== RCS file: /cvs/src/usr.sbin/unbound/services/outside_network.h,v retrieving revision 1.16 diff -u -p -r1.16 outside_network.h --- services/outside_network.h 20 Oct 2022 08:26:14 -0000 1.16 +++ services/outside_network.h 26 Apr 2024 04:44:23 -0000 @@ -147,6 +147,8 @@ struct outside_network { /** dnstap environment */ struct dt_env* dtenv; #endif + /** msgtap environment */ + struct mt_env* mtenv; /** maximum segment size of tcp socket */ int tcp_mss; /** IP_TOS socket option requested on the sockets */ @@ -418,10 +420,8 @@ struct waiting_tcp { int error_count; /** if true, the item is at the cb_and_decommission stage */ int in_cb_and_decommission; -#ifdef USE_DNSTAP /** serviced query pointer for dnstap to get logging info, if nonNULL*/ struct serviced_query* sq; -#endif }; /** @@ -556,6 +556,7 @@ struct serviced_query { * msec to wait on timeouted udp sockets. * @param tls_use_sni: if SNI is used for TLS connections. * @param dtenv: environment to send dnstap events with (if enabled). + * @param mtenv: environment to send msgtap events with (if enabled). * @param udp_connect: if the udp_connect option is enabled. * @param max_reuse_tcp_queries: max number of queries on a reuse connection. * @param tcp_reuse_timeout: timeout for REUSE entries in milliseconds. @@ -569,8 +570,8 @@ struct outside_network* outside_network_ int numavailports, size_t unwanted_threshold, int tcp_mss, void (*unwanted_action)(void*), void* unwanted_param, int do_udp, void* sslctx, int delayclose, int tls_use_sni, struct dt_env *dtenv, - int udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout, - int tcp_auth_query_timeout); + struct mt_env *mtenv, int udp_connect, int max_reuse_tcp_queries, + int tcp_reuse_timeout, int tcp_auth_query_timeout); /** * Delete outside_network structure. Index: util/config_file.c =================================================================== RCS file: /cvs/src/usr.sbin/unbound/util/config_file.c,v retrieving revision 1.31 diff -u -p -r1.31 config_file.c --- util/config_file.c 20 Oct 2022 08:26:14 -0000 1.31 +++ util/config_file.c 26 Apr 2024 04:44:23 -0000 @@ -322,6 +322,16 @@ config_create(void) #endif cfg->dnstap_bidirectional = 1; cfg->dnstap_tls = 1; +#if defined(MSGTAP_SOCKET_PATH) + if(!(cfg->msgtap_socket_path = strdup(MSGTAP_SOCKET_PATH))) + goto error_exit; +#endif + cfg->msgtap_log_resolver_query_messages = 1; + cfg->msgtap_log_resolver_response_messages = 1; + cfg->msgtap_log_client_query_messages = 1; + cfg->msgtap_log_client_response_messages = 1; + cfg->msgtap_log_forwarder_query_messages = 1; + cfg->msgtap_log_forwarder_response_messages = 1; cfg->disable_dnssec_lame_check = 0; cfg->ip_ratelimit = 0; cfg->ratelimit = 0; @@ -745,6 +755,24 @@ int config_set_option(struct config_file else S_YNO("dnstap-log-forwarder-response-messages:", dnstap_log_forwarder_response_messages) #endif + else S_YNO("msgtap-enable:", msgtap) + else S_STR("msgtap-socket-path:", msgtap_socket_path) + else S_YNO("msgtap-send-identity:", msgtap_send_identity) + else S_YNO("msgtap-send-version:", msgtap_send_version) + else S_STR("msgtap-identity:", msgtap_identity) + else S_STR("msgtap-version:", msgtap_version) + else S_YNO("msgtap-log-resolver-query-messages:", + msgtap_log_resolver_query_messages) + else S_YNO("msgtap-log-resolver-response-messages:", + msgtap_log_resolver_response_messages) + else S_YNO("msgtap-log-client-query-messages:", + msgtap_log_client_query_messages) + else S_YNO("msgtap-log-client-response-messages:", + msgtap_log_client_response_messages) + else S_YNO("msgtap-log-forwarder-query-messages:", + msgtap_log_forwarder_query_messages) + else S_YNO("msgtap-log-forwarder-response-messages:", + msgtap_log_forwarder_response_messages) #ifdef USE_DNSCRYPT else S_YNO("dnscrypt-enable:", dnscrypt) else S_NUMBER_NONZERO("dnscrypt-port:", dnscrypt_port) @@ -1639,6 +1667,9 @@ config_delete(struct config_file* cfg) free(cfg->dnstap_tls_client_cert_file); free(cfg->dnstap_identity); free(cfg->dnstap_version); + free(cfg->msgtap_socket_path); + free(cfg->msgtap_identity); + free(cfg->msgtap_version); config_deldblstrlist(cfg->ratelimit_for_domain); config_deldblstrlist(cfg->ratelimit_below_domain); config_delstrlist(cfg->python_script); Index: util/config_file.h =================================================================== RCS file: /cvs/src/usr.sbin/unbound/util/config_file.h,v retrieving revision 1.29 diff -u -p -r1.29 config_file.h --- util/config_file.h 20 Oct 2022 08:26:14 -0000 1.29 +++ util/config_file.h 26 Apr 2024 04:44:23 -0000 @@ -573,6 +573,33 @@ struct config_file { /** true to log dnstap FORWARDER_RESPONSE message events */ int dnstap_log_forwarder_response_messages; + /** true to enable msgtap support */ + int msgtap; + /** msgtap socket path */ + char* msgtap_socket_path; + + /** true to send "identity" via msgtap */ + int msgtap_send_identity; + /** true to send "version" via msgtap */ + int msgtap_send_version; + /** msgtap "identity", hostname is used if "". */ + char* msgtap_identity; + /** msgtap "version", package version is used if "". */ + char* msgtap_version; + + /** true to log msgtap RESOLVER_QUERY message events */ + int msgtap_log_resolver_query_messages; + /** true to log msgtap RESOLVER_RESPONSE message events */ + int msgtap_log_resolver_response_messages; + /** true to log msgtap CLIENT_QUERY message events */ + int msgtap_log_client_query_messages; + /** true to log msgtap CLIENT_RESPONSE message events */ + int msgtap_log_client_response_messages; + /** true to log msgtap FORWARDER_QUERY message events */ + int msgtap_log_forwarder_query_messages; + /** true to log msgtap FORWARDER_RESPONSE message events */ + int msgtap_log_forwarder_response_messages; + /** true to disable DNSSEC lameness check in iterator */ int disable_dnssec_lame_check; Index: util/configlexer.lex =================================================================== RCS file: /cvs/src/usr.sbin/unbound/util/configlexer.lex,v retrieving revision 1.26 diff -u -p -r1.26 configlexer.lex --- util/configlexer.lex 20 Oct 2022 08:26:14 -0000 1.26 +++ util/configlexer.lex 26 Apr 2024 04:44:23 -0000 @@ -500,6 +500,21 @@ dnstap-log-forwarder-query-messages{COLO YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) } dnstap-log-forwarder-response-messages{COLON} { YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) } +msgtap{COLON} { YDVAR(0, VAR_MSGTAP) } +msgtap-enable{COLON} { YDVAR(1, VAR_MSGTAP_ENABLE) } +msgtap-socket-path{COLON} { YDVAR(1, VAR_MSGTAP_SOCKET_PATH) } +msgtap-log-resolver-query-messages{COLON} { + YDVAR(1, VAR_MSGTAP_LOG_RESOLVER_QUERY_MESSAGES) } +msgtap-log-resolver-response-messages{COLON} { + YDVAR(1, VAR_MSGTAP_LOG_RESOLVER_RESPONSE_MESSAGES) } +msgtap-log-client-query-messages{COLON} { + YDVAR(1, VAR_MSGTAP_LOG_CLIENT_QUERY_MESSAGES) } +msgtap-log-client-response-messages{COLON} { + YDVAR(1, VAR_MSGTAP_LOG_CLIENT_RESPONSE_MESSAGES) } +msgtap-log-forwarder-query-messages{COLON} { + YDVAR(1, VAR_MSGTAP_LOG_FORWARDER_QUERY_MESSAGES) } +msgtap-log-forwarder-response-messages{COLON} { + YDVAR(1, VAR_MSGTAP_LOG_FORWARDER_RESPONSE_MESSAGES) } disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) } ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) } ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) } Index: util/configparser.y =================================================================== RCS file: /cvs/src/usr.sbin/unbound/util/configparser.y,v retrieving revision 1.26 diff -u -p -r1.26 configparser.y --- util/configparser.y 20 Oct 2022 08:26:14 -0000 1.26 +++ util/configparser.y 26 Apr 2024 04:44:23 -0000 @@ -134,6 +134,15 @@ extern struct config_parser_state* cfg_p %token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES %token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES %token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES +%token VAR_MSGTAP VAR_MSGTAP_ENABLE VAR_MSGTAP_SOCKET_PATH +%token VAR_MSGTAP_SEND_IDENTITY VAR_MSGTAP_SEND_VERSION +%token VAR_MSGTAP_IDENTITY VAR_MSGTAP_VERSION +%token VAR_MSGTAP_LOG_RESOLVER_QUERY_MESSAGES +%token VAR_MSGTAP_LOG_RESOLVER_RESPONSE_MESSAGES +%token VAR_MSGTAP_LOG_CLIENT_QUERY_MESSAGES +%token VAR_MSGTAP_LOG_CLIENT_RESPONSE_MESSAGES +%token VAR_MSGTAP_LOG_FORWARDER_QUERY_MESSAGES +%token VAR_MSGTAP_LOG_FORWARDER_RESPONSE_MESSAGES %token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA %token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT %token VAR_IP_DSCP @@ -199,7 +208,8 @@ extern struct config_parser_state* cfg_p toplevelvars: /* empty */ | toplevelvars toplevelvar ; toplevelvar: serverstart contents_server | stubstart contents_stub | forwardstart contents_forward | pythonstart contents_py | - rcstart contents_rc | dtstart contents_dt | viewstart contents_view | + rcstart contents_rc | dtstart contents_dt | mtstart contents_mt | + viewstart contents_view | dnscstart contents_dnsc | cachedbstart contents_cachedb | ipsetstart contents_ipset | authstart contents_auth | rpzstart contents_rpz | dynlibstart contents_dl | @@ -3423,6 +3433,131 @@ dt_dnstap_log_forwarder_response_message if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); else cfg_parser->cfg->dnstap_log_forwarder_response_messages = + (strcmp($2, "yes")==0); + free($2); + } + ; +mtstart: VAR_MSGTAP + { + OUTYY(("\nP(msgtap:)\n")); + } + ; +contents_mt: contents_mt content_mt + | ; +content_mt: mt_msgtap_enable | mt_msgtap_socket_path | + mt_msgtap_send_identity | mt_msgtap_send_version | + mt_msgtap_identity | mt_msgtap_version | + mt_msgtap_log_resolver_query_messages | + mt_msgtap_log_resolver_response_messages | + mt_msgtap_log_client_query_messages | + mt_msgtap_log_client_response_messages | + mt_msgtap_log_forwarder_query_messages | + mt_msgtap_log_forwarder_response_messages + ; +mt_msgtap_enable: VAR_MSGTAP_ENABLE STRING_ARG + { + OUTYY(("P(mt_msgtap_enable:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->msgtap = (strcmp($2, "yes")==0); + free($2); + } + ; +mt_msgtap_socket_path: VAR_MSGTAP_SOCKET_PATH STRING_ARG + { + OUTYY(("P(mt_msgtap_socket_path:%s)\n", $2)); + free(cfg_parser->cfg->msgtap_socket_path); + cfg_parser->cfg->msgtap_socket_path = $2; + } + ; +mt_msgtap_send_identity: VAR_MSGTAP_SEND_IDENTITY STRING_ARG + { + OUTYY(("P(mt_msgtap_send_identity:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->msgtap_send_identity = (strcmp($2, "yes")==0); + free($2); + } + ; +mt_msgtap_send_version: VAR_MSGTAP_SEND_VERSION STRING_ARG + { + OUTYY(("P(mt_msgtap_send_version:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->msgtap_send_version = (strcmp($2, "yes")==0); + free($2); + } + ; +mt_msgtap_identity: VAR_MSGTAP_IDENTITY STRING_ARG + { + OUTYY(("P(mt_msgtap_identity:%s)\n", $2)); + free(cfg_parser->cfg->msgtap_identity); + cfg_parser->cfg->msgtap_identity = $2; + } + ; +mt_msgtap_version: VAR_MSGTAP_VERSION STRING_ARG + { + OUTYY(("P(mt_msgtap_version:%s)\n", $2)); + free(cfg_parser->cfg->msgtap_version); + cfg_parser->cfg->msgtap_version = $2; + } + ; +mt_msgtap_log_resolver_query_messages: VAR_MSGTAP_LOG_RESOLVER_QUERY_MESSAGES STRING_ARG + { + OUTYY(("P(mt_msgtap_log_resolver_query_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->msgtap_log_resolver_query_messages = + (strcmp($2, "yes")==0); + free($2); + } + ; +mt_msgtap_log_resolver_response_messages: VAR_MSGTAP_LOG_RESOLVER_RESPONSE_MESSAGES STRING_ARG + { + OUTYY(("P(mt_msgtap_log_resolver_response_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->msgtap_log_resolver_response_messages = + (strcmp($2, "yes")==0); + free($2); + } + ; +mt_msgtap_log_client_query_messages: VAR_MSGTAP_LOG_CLIENT_QUERY_MESSAGES STRING_ARG + { + OUTYY(("P(mt_msgtap_log_client_query_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->msgtap_log_client_query_messages = + (strcmp($2, "yes")==0); + free($2); + } + ; +mt_msgtap_log_client_response_messages: VAR_MSGTAP_LOG_CLIENT_RESPONSE_MESSAGES STRING_ARG + { + OUTYY(("P(mt_msgtap_log_client_response_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->msgtap_log_client_response_messages = + (strcmp($2, "yes")==0); + free($2); + } + ; +mt_msgtap_log_forwarder_query_messages: VAR_MSGTAP_LOG_FORWARDER_QUERY_MESSAGES STRING_ARG + { + OUTYY(("P(mt_msgtap_log_forwarder_query_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->msgtap_log_forwarder_query_messages = + (strcmp($2, "yes")==0); + free($2); + } + ; +mt_msgtap_log_forwarder_response_messages: VAR_MSGTAP_LOG_FORWARDER_RESPONSE_MESSAGES STRING_ARG + { + OUTYY(("P(mt_msgtap_log_forwarder_response_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->msgtap_log_forwarder_response_messages = (strcmp($2, "yes")==0); free($2); } Index: util/netevent.c =================================================================== RCS file: /cvs/src/usr.sbin/unbound/util/netevent.c,v retrieving revision 1.33 diff -u -p -r1.33 netevent.c --- util/netevent.c 20 Oct 2022 08:26:14 -0000 1.33 +++ util/netevent.c 26 Apr 2024 04:44:24 -0000 @@ -50,6 +50,7 @@ #include "sldns/sbuffer.h" #include "sldns/str2wire.h" #include "dnstap/dnstap.h" +#include "msgtap/msgtap.h" #include "dnscrypt/dnscrypt.h" #include "services/listen_dnsport.h" #ifdef HAVE_SYS_TYPES_H @@ -866,6 +867,11 @@ comm_point_udp_ancil_callback(int fd, sh return; } rep.remote_addrlen = msg.msg_namelen; + rep.local_addrlen = sizeof(rep.local_addr); + if(getsockname(fd, (struct sockaddr *)&rep.local_addr, + &rep.local_addrlen) == -1) { + return; + } sldns_buffer_skip(rep.c->buffer, rcv); sldns_buffer_flip(rep.c->buffer); rep.srctype = 0; @@ -875,23 +881,37 @@ comm_point_udp_ancil_callback(int fd, sh cmsg = CMSG_NXTHDR(&msg, cmsg)) { if( cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { + struct sockaddr_in6 *sin6; rep.srctype = 6; memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg), sizeof(struct in6_pktinfo)); + + sin6 = (struct sockaddr_in6 *)&rep.local_addr; + sin6->sin6_addr = rep.pktinfo.v6info.ipi6_addr; break; #ifdef IP_PKTINFO } else if( cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) { + struct sockaddr_in *sin; + rep.srctype = 4; memmove(&rep.pktinfo.v4info, CMSG_DATA(cmsg), sizeof(struct in_pktinfo)); + + sin = (struct sockaddr_in *)&rep.local_addr; + sin->sin_addr = rep.pktinfo.v4info.ipi_addr; break; #elif defined(IP_RECVDSTADDR) } else if( cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) { + struct sockaddr_in *sin; + rep.srctype = 4; memmove(&rep.pktinfo.v4addr, CMSG_DATA(cmsg), sizeof(struct in_addr)); + + sin = (struct sockaddr_in *)&rep.local_addr; + sin->sin_addr = rep.pktinfo.v4addr; break; #endif /* IP_PKTINFO or IP_RECVDSTADDR */ } @@ -1315,6 +1335,12 @@ comm_point_tcp_accept_callback(int fd, s &c_hdl->repinfo.remote_addrlen); if(new_fd == -1) return; + c_hdl->repinfo.local_addrlen = sizeof(c_hdl->repinfo.local_addr); + if(getsockname(new_fd, (struct sockaddr *)&c_hdl->repinfo.local_addr, + &c_hdl->repinfo.local_addrlen) == -1) { + close(new_fd); + return; + } /* Copy remote_address to client_address. * Simplest way/time for streams to do that. */ c_hdl->repinfo.client_addrlen = c_hdl->repinfo.remote_addrlen; @@ -4578,6 +4604,13 @@ comm_point_send_reply(struct comm_reply dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, repinfo->c->buffer); } #endif + if (repinfo->c->mtenv != NULL && + repinfo->c->mtenv->log_client_response_messages) { + mt_msg_send_client_response(repinfo->c->mtenv, + (struct sockaddr *)&repinfo->client_addr, + (struct sockaddr *)repinfo->c->socket->addr->ai_addr, + repinfo, repinfo->c->type, repinfo->c->buffer); + } } else { #ifdef USE_DNSTAP /* @@ -4590,6 +4623,17 @@ comm_point_send_reply(struct comm_reply ( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer )); } #endif + if(repinfo->c->tcp_parent->mtenv != NULL && + repinfo->c->tcp_parent->mtenv->log_client_response_messages) { + mt_msg_send_client_response( + repinfo->c->tcp_parent->mtenv, + (struct sockaddr *)&repinfo->client_addr, + (struct sockaddr *)repinfo->c->socket->addr->ai_addr, + repinfo, repinfo->c->type, + repinfo->c->tcp_req_info ? + repinfo->c->tcp_req_info->spool_buffer : + repinfo->c->buffer); + } if(repinfo->c->tcp_req_info) { tcp_req_info_send_reply(repinfo->c->tcp_req_info); } else if(repinfo->c->use_h2) { Index: util/netevent.h =================================================================== RCS file: /cvs/src/usr.sbin/unbound/util/netevent.h,v retrieving revision 1.20 diff -u -p -r1.20 netevent.h --- util/netevent.h 20 Oct 2022 08:26:14 -0000 1.20 +++ util/netevent.h 26 Apr 2024 04:44:24 -0000 @@ -127,6 +127,8 @@ struct comm_base { struct comm_reply { /** the comm_point with fd to send reply on to. */ struct comm_point* c; + struct sockaddr_storage local_addr; + socklen_t local_addrlen; /** the address (for UDP based communication) */ struct sockaddr_storage remote_addr; /** length of address */ @@ -267,6 +269,9 @@ struct comm_point { /* -------- dnstap ------- */ /** the dnstap environment */ struct dt_env* dtenv; + + /** the msgtap environment */ + struct mt_env* mtenv; /** is this a UDP, TCP-accept or TCP socket. */ enum comm_point_type {