From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server-vie001.gnuweeb.org X-Spam-Level: X-Spam-Status: No, score=-1.2 required=5.0 tests=ALL_TRUSTED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,URIBL_ZEN_BLOCKED_OPENDNS autolearn=ham autolearn_force=no version=3.4.6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gnuweeb.org; s=new2025; t=1758221276; bh=JXUjpsCrDUbyI76UEU1oLMij9DGy/QnmovQ+1gXgh1s=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Message-ID:Date:From: Reply-To:Subject:To:Cc:In-Reply-To:References:Resent-Date: Resent-From:Resent-To:Resent-Cc:User-Agent:Content-Type: Content-Transfer-Encoding; b=V0qeU3fj3hivc8xyJCNoJopZ5FrTozIv0CY4E/UaABO4c+sq7n97erXGeFn/nKndy 35ti7ErYzfKf72P8Ov1/Kqpihsk7bN792H/FdAQ9Wuaw9xYus40LJ9ToW4F9PJ1+mD JGoyj1Rx6jsbMipXLCmrTGutmZKY2c2ZET9Nse369XF1M1zLRdU1BsJAd6i5E7USa1 rEfID1bmjrA2OLTCfgJTSfwGkunnmTq51/tF87fQjpR1C2pLoYHBVYcLE4katxEhr2 ToCsdOeKBYUfkra+VDBc+SzoA3ws2B/V0BcDxX6yNx9/MAtowsTTrcL0EdYv2vYitO gdjvJJUBZhdow== Received: from localhost.localdomain (unknown [68.183.184.174]) by server-vie001.gnuweeb.org (Postfix) with ESMTPSA id C4FED312797B; Thu, 18 Sep 2025 18:47:55 +0000 (UTC) From: Alviro Iskandar Setiawan To: Ammar Faiz Cc: Alviro Iskandar Setiawan , Ahmad Gani , GNU/Weeb Mailing List Subject: [PATCH gwproxy v12 5/8] dns_resolver: Add DNS resolution interface APIs Date: Fri, 19 Sep 2025 01:47:27 +0700 Message-Id: <20250918184730.598305-6-alviro.iskandar@gnuweeb.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250918184730.598305-1-alviro.iskandar@gnuweeb.org> References: <20250918184730.598305-1-alviro.iskandar@gnuweeb.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: Provide an interface for DNS resolution to be used by other components without including the socket handling code. It allows other components to handle the socket I/O as they see fit, flexibly. For instance, using epoll vs using io_uring has different ways of handling the socket I/O. Signed-off-by: Alviro Iskandar Setiawan --- src/gwproxy/dns_resolver.c | 125 +++++++++++++++++++++++++++++++++++++ src/gwproxy/dns_resolver.h | 30 +++++++++ 2 files changed, 155 insertions(+) diff --git a/src/gwproxy/dns_resolver.c b/src/gwproxy/dns_resolver.c index 4d6924f..22fac18 100644 --- a/src/gwproxy/dns_resolver.c +++ b/src/gwproxy/dns_resolver.c @@ -250,3 +250,128 @@ void gwp_dns_res_free(struct gwp_dns_resolver *res) __sys_close(res->udp_fd); memset(res, 0, sizeof(*res)); } + +int gwp_dns_res_prep_query(struct gwp_dns_resolver *res, + struct gwp_dns_packet *gdp) +{ + int af, ret; + ssize_t tmp; + + assert(gdp->gcp); + + if (!gdp->__in_fallback_attempt) { + ret = insert_map(res->sess_map, gdp->gcp, &gdp->txid); + if (ret) + return ret; + } else { + assert(gdp->gcp == lookup_map(res->sess_map, gdp->txid)); + } + + ret = 0; + if (gdp->restyp == GWP_DNS_RESTYP_PREFER_IPV6) { + af = AF_INET6; + gdp->restyp = GWP_DNS_RESTYP_IPV4_ONLY; + gdp->__in_fallback_attempt = true; + } else if (gdp->restyp == GWP_DNS_RESTYP_PREFER_IPV4) { + af = AF_INET; + gdp->restyp = GWP_DNS_RESTYP_IPV6_ONLY; + gdp->__in_fallback_attempt = true; + } else if (gdp->restyp == GWP_DNS_RESTYP_IPV6_ONLY) { + ret = 0; + af = AF_INET6; + } else if (gdp->restyp == GWP_DNS_RESTYP_IPV4_ONLY) { + ret = 0; + af = AF_INET; + } else { + ret = -EINVAL; + goto err; + } + + tmp = gwdns_build_query(gdp->txid, gdp->host, af, gdp->buf, gdp->buf_len); + if (tmp < 0) { + ret = (int)tmp; + goto err; + } + + gdp->buf_len = (uint16_t)tmp; + return ret; + +err: + delete_map(res->sess_map, gdp->txid); + return ret; +} + +void gwp_dns_res_drop_query(struct gwp_dns_resolver *res, + struct gwp_conn_pair *gcp, uint16_t txid) +{ + assert(gcp); + assert(gcp == lookup_map(res->sess_map, txid)); + delete_map(res->sess_map, txid); + (void)gcp; +} + +int gwp_dns_res_fetch_gcp_by_payload(struct gwp_dns_resolver *res, + const uint8_t buf[UDP_MSG_LIMIT], + uint16_t len, + struct gwp_conn_pair **gcp_p) +{ + uint16_t txid; + + if (len < 38) + return -EINVAL; + + memcpy(&txid, buf, 2); + if (txid >= res->sess_map->cap) + return -EINVAL; + + *gcp_p = lookup_map(res->sess_map, txid); + if (!gcp_p) + return -ENOENT; + + return 0; +} + +int gwp_dns_res_complete_query(struct gwp_dns_resolver *res, + struct gwp_dns_packet *gdp, + uint8_t buf[UDP_MSG_LIMIT], + uint16_t len, + struct gwp_sockaddr *addr) +{ + struct gwdns_addrinfo_node *ai = NULL; + char port[sizeof("65535")]; + uint16_t txid; + ssize_t r; + + if (len < 38) + return -EINVAL; + + memcpy(&txid, buf, 2); + if (txid >= res->sess_map->cap) + return -EINVAL; + + if (gdp->txid != txid) + return -EINVAL; + + if (gdp->gcp != res->sess_map->sess_map[txid]) + return -EINVAL; + + snprintf(port, sizeof(port), "%hu", gdp->port); + r = gwdns_parse_query(txid, port, buf, len, &ai); + if (!r) { + *addr = ai->ai_addr; + gwdns_free_parsed_query(ai); + delete_map(res->sess_map, txid); + return 0; + } + + if (gdp->__in_fallback_attempt) { + int tmp = gwp_dns_res_prep_query(res, gdp); + if (!tmp) + return -EAGAIN; + + r = tmp; + } + + delete_map(res->sess_map, txid); + return (int)r; +} diff --git a/src/gwproxy/dns_resolver.h b/src/gwproxy/dns_resolver.h index d4545f1..1e46efd 100644 --- a/src/gwproxy/dns_resolver.h +++ b/src/gwproxy/dns_resolver.h @@ -1,7 +1,9 @@ #ifndef GWPROXY__DNS_RESOLVER_H #define GWPROXY__DNS_RESOLVER_H +#include #include +#include struct gwp_ctx; struct gwp_dns_resolver_map; @@ -12,8 +14,36 @@ struct gwp_dns_resolver { struct gwp_dns_resolver_map *sess_map; }; +struct gwp_dns_packet { + bool __in_fallback_attempt; + uint8_t restyp; + uint16_t txid; + uint16_t buf_len; + uint16_t port; + uint8_t buf[UDP_MSG_LIMIT]; + char *host; + struct gwp_conn_pair *gcp; +}; + int gwp_dns_res_init(struct gwp_ctx *ctx, struct gwp_dns_resolver *gdr, const char *srv_addr); void gwp_dns_res_free(struct gwp_dns_resolver *gdr); +int gwp_dns_res_prep_query(struct gwp_dns_resolver *res, + struct gwp_dns_packet *gdp); + +void gwp_dns_res_drop_query(struct gwp_dns_resolver *res, + struct gwp_conn_pair *gcp, uint16_t txid); + +int gwp_dns_res_fetch_gcp_by_payload(struct gwp_dns_resolver *res, + const uint8_t buf[UDP_MSG_LIMIT], + uint16_t len, + struct gwp_conn_pair **gcp_p); + +int gwp_dns_res_complete_query(struct gwp_dns_resolver *res, + struct gwp_dns_packet *gdp, + uint8_t buf[UDP_MSG_LIMIT], + uint16_t len, + struct gwp_sockaddr *addr); + #endif /* #ifndef GWPROXY__DNS_RESOLVER_H */ -- Alviro Iskandar Setiawan