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=1753679731; bh=6aE40hzPs25pKZe0iuBYiWm9sduIl6k66bi4eNuelbY=; 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=rc7k/mlTPeONY01p3ciOMjsViTGpBTuW3Dn9kkNEkfJh7BMDKCoog83YXDiJQ7cIr QL2MUoRegJivd3oB6XIAhOBVrtMONWLXxzDN7ZqDFYR5wShoouLkJzWO7HKcW/+JzE HshOBv+2ofZR2cqOsTBvwGV1gwuLexK0NWGAlYxz2Hw6nTOz6pf+ezSqKOtEok/600 XgokUvCCxi3tXzd8+yWB3OetfMIIakAqH/Wp5kGZTP1QUQ4EwIPYiJjWMtSATa6ORx 2NKE0slNSEJw9cX8VbbhLkONO8WZ9SJ10h7iHGPxuq2IIhIa8h6+4yF2eWXAypAWde i+B/qA+Mci0hg== Received: from zero (unknown [182.253.228.104]) by server-vie001.gnuweeb.org (Postfix) with ESMTPSA id 60DA13126E4C; Mon, 28 Jul 2025 05:15:30 +0000 (UTC) From: ReYuki To: GNU/Weeb Mailing List Cc: ReYuki Subject: [PATCH gwproxy v1 2/2] add support for AAAA record type Date: Mon, 28 Jul 2025 12:14:35 +0700 Message-ID: <20250728051438.48089-3-reyuki@gnuweeb.org> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250728051438.48089-1-reyuki@gnuweeb.org> References: <20250728051438.48089-1-reyuki@gnuweeb.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: From: ReYuki https://datatracker.ietf.org/doc/html/rfc3596 2.1 AAAA record type The AAAA resource record type is a record specific to the Internet class that stores a single IPv6 address. The IANA assigned value of the type is 28 (decimal). the following is a sample from dig command (strace -x -s 512 dig A google.com): // dns request query packet // header section \xfd\x11 // id \x01\x20 // flags \x00\x01 // qdcount \x00\x00 // ancount \x00\x00 // nscount \x00\x01 // arcount // question section // name \x06\x67\x6f\x6f\x67\x6c\x65 \x03\x63\x6f\x6d \x00\x00 // type \x1c\x00 // class // additional resource section \x01\x00\x00\x29\x04\xd0\x00\x00\x00\x00\x00\x0c\x00\x0a\x00\x08\x21\x06\x68\xe2\x80\xc2\xe8\xb8 // dns response answer packet // header section \xfd\x11 // id \x81\x80 // flags \x00\x01 // qdcount \x00\x04 // ancount \x00\x00 // nscount \x00\x01 // arcount // question section \x06\x67\x6f\x6f\x67\x6c\x65 \x03\x63\x6f\x6d \x00 \x00\x1c // type \x00\x01 // class // (1) answer section \xc0\x0c // name \x00\x1c // type \x00\x01 // class \x00\x00\x06\xd1 // ttl \x00\x10 // rdlength \x24\x04\x68\x00\x40\x03\x0c\x0f\x00\x00\x00\x00\x00\x00\x00\x8a // rdata // (2) answer section \xc0\x0c \x00\x1c \x00\x01 \x00\x00\x06\xd1 \x00\x10 \x24\x04\x68\x00\x40\x03\x0c\x0f\x00\x00\x00\x00\x00\x00\x00\x65 // (3) answer section \xc0\x0c \x00\x1c \x00\x01 \x00\x00\x06\xd1 \x00\x10 \x24\x04\x68\x00\x40\x03\x0c\x0f\x00\x00\x00\x00\x00\x00\x00\x66 // (4) answer section \xc0\x0c \x00\x1c \x00\x01 \x00\x00\x06\xd1 \x00\x10 \x24\x04\x68\x00\x40\x03\x0c\x0f\x00\x00\x00\x00\x00\x00\x00\x64 // additional resource section \x00\x00\x29\x10\x00\x00\x00\x00\x00\x00\x00 --- dnsclient.c | 7 +++++-- gwdnsparserlib.c | 14 +++++++++++++- gwdnsparserlib.h | 4 +++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/dnsclient.c b/dnsclient.c index 4d96b18..6f2e66c 100644 --- a/dnsclient.c +++ b/dnsclient.c @@ -83,6 +83,7 @@ static int send_query(struct io_uring *ring, int sockfd, char *domain, gwdns_que q.domain = domain; q.dst_buffer = buff->question; q.dst_len = UDP_MSG_LIMIT; + q.type = TYPE_AAAA; payload_len = construct_question(&q); if (payload_len < 0) return -1; @@ -161,13 +162,15 @@ static int resolv_addr(char **domains, gwdns_resolv_hint *hint, gwdns_resolv_ctx ctx->sqe_nr--; printf("cqe->res=%d cqe->user_data=%llx\n", cqe->res, CLEAR_ID(cqe->user_data)); if (EXTRACT_ID(cqe->user_data) == ID) { - char ipstr[INET_ADDRSTRLEN]; + char ipstr[INET6_ADDRSTRLEN]; gwdns_answ_data d; cqe->user_data = CLEAR_ID(cqe->user_data); ret = serialize_answ((uint16_t)cqe->user_data, (uint8_t *)buff[idx].answr, cqe->res, &d); for (size_t i = 0; i < d.hdr.ancount; i++) { - inet_ntop(AF_INET, d.rr_answ[i]->rdata, ipstr, sizeof(ipstr)); + gwdns_serialized_answ *p = d.rr_answ[i]; + int sa_family = p->rr_type == TYPE_AAAA ? AF_INET6 : AF_INET; + inet_ntop(sa_family, p->rdata, ipstr, sizeof(ipstr)); printf("%s\n", ipstr); } diff --git a/gwdnsparserlib.c b/gwdnsparserlib.c index aa883d9..022ccc2 100644 --- a/gwdnsparserlib.c +++ b/gwdnsparserlib.c @@ -1,3 +1,5 @@ +#define _DEFAULT_SOURCE +#include #include "gwdnsparserlib.h" static ssize_t construct_qname(uint8_t *dst, size_t dst_len, const char *qname) @@ -126,14 +128,21 @@ int serialize_answ(uint16_t txid, uint8_t *in, size_t in_len, gwdns_answ_data *o in += 2; // NAME memcpy(&item->rr_type, in, 2); + item->rr_type = ntohs(item->rr_type); in += 2; // TYPE memcpy(&item->rr_class, in, 2); + item->rr_class = ntohs(item->rr_class); in += 2; // CLASS memcpy(&item->ttl, in, 4); + item->ttl = be32toh(item->ttl); in += 4; // TTL memcpy(&rdlength, in, sizeof(rdlength)); rdlength = ntohs(rdlength); + if (item->rr_type == TYPE_AAAA && rdlength != sizeof(struct in6_addr)) + return -EINVAL; + if (item->rr_type == TYPE_A && rdlength != sizeof(struct in_addr)) + return -EINVAL; item->rdlength = rdlength; in += 2; @@ -153,6 +162,9 @@ ssize_t construct_question(gwdns_question_part *question) size_t required_len; ssize_t bw; + if (question->type != TYPE_AAAA && question->type != TYPE_A) + return -EINVAL; + hdr = &pkt.hdr; /* * the memset implicitly set opcode to query @@ -177,7 +189,7 @@ ssize_t construct_question(gwdns_question_part *question) return bw; pkt.body[bw++] = 0x0; - qtype = htons(TYPE_A); + qtype = htons(question->type); qclass = htons(CLASS_IN); memcpy(&pkt.body[bw], &qtype, 2); bw += 2; diff --git a/gwdnsparserlib.h b/gwdnsparserlib.h index d24e414..c5948d0 100644 --- a/gwdnsparserlib.h +++ b/gwdnsparserlib.h @@ -91,6 +91,7 @@ typedef enum { TYPE_MINFO = 14, // mailbox or mail list information TYPE_MX = 15, // mail exchange TYPE_TXT = 16, // text strings + TYPE_AAAA = 28, // text strings QTYPE_AXFR = 252, // A request for a transfer of an entire zone QTYPE_MAILB = 253, // A request for mailbox-related records (MB, MG or MR) QTYPE_ALL = 255 // A request for all records @@ -119,6 +120,7 @@ typedef struct { typedef struct { uint8_t *dst_buffer; + uint16_t type; size_t dst_len; char *domain; } gwdns_question_part; @@ -190,7 +192,7 @@ typedef struct { * possible error are: * - ENAMETOOLONG domain name in question.name is too long. * - ENOBUFS length in question.dst_len is not sufficient. -* - EINVAL malformed question.name +* - EINVAL malformed or unsupported value in question data */ ssize_t construct_question(gwdns_question_part *question); -- ReYuki