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=1753679729; bh=OSDWBwvAlsNlGgT3+7fl2BjMBnDTKBIux08UU+xNM6s=; 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=Uo0yGo25hNMRenAn5G2WbUaTuPRlSl0GT6gEsp4AJpn4xozDaDVtG23y0YpU1rtCr 6UOth1fpDCGxVer3IGybVzjFYit6HkxcJuxRbctwQbyioKJz4WWBJzL5CsXP+Ou34/ 7Phn+HuCmTodJCaNpQntLhIt9MVZ+9z2VD0iOxc6FKV7bcE9v8kMdYkb472MK54AU0 1X4tjwqRxrkKA4eq6ZNBy4ZQGTjVtHsqBrY6k3CYaOKuanAKSqW2GEqCJaaqPjCann oC59hHeXC2pVtSU3r7Kdo+IyKdVR0HthRPASP+XIqqmw76Plzu7UwyD7FunuF2khSx w+C7bJSLOiiGg== Received: from zero (unknown [182.253.228.104]) by server-vie001.gnuweeb.org (Postfix) with ESMTPSA id 40F9F3126E47; Mon, 28 Jul 2025 05:15:29 +0000 (UTC) From: ReYuki To: GNU/Weeb Mailing List Cc: ReYuki Subject: [PATCH gwproxy v1 1/2] add unit test Date: Mon, 28 Jul 2025 12:14:34 +0700 Message-ID: <20250728051438.48089-2-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 --- Makefile | 7 +++ gwdnsparserlib.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++- gwdnsparserlib.h | 21 ++++++--- 3 files changed, 135 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 9a03526..031695a 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ INOTIFYSRC := test_inotify.c linux.c DNSCLIENTSRC := dnsclient.c general.c gwdnsparserlib.c GWSOCKS5LIBSRC := gwsocks5lib.c linux.c general.c GWDNSLIBSRC := gwdnslib.c linux.c +PARSERLIBSRC := gwdnsparserlib.c OBJS1 := $(patsubst %.c,$(BUILDDIR)/%.o,$(GWPROXYSRC)) OBJS2 := $(patsubst %.c,$(BUILDDIR)/%.o,$(CONVERTERSRC)) @@ -13,6 +14,7 @@ OBJS3 := $(patsubst %.c,$(BUILDDIR)/%.o,$(INOTIFYSRC)) OBJS5 := $(patsubst %.c,$(BUILDDIR)/%.o,$(DNSCLIENTSRC)) OBJS6 := $(patsubst %.c,$(BUILDDIR)/%.o,$(GWSOCKS5LIBSRC)) OBJS7 := $(patsubst %.c,$(BUILDDIR)/%.o,$(GWDNSLIBSRC)) +OBJS8 := $(patsubst %.c,$(BUILDDIR)/%.o,$(PARSERLIBSRC)) TARGET1 := $(BUILDDIR)/gwproxy TARGET2 := $(BUILDDIR)/ip_converter @@ -20,6 +22,7 @@ TARGET3 := $(BUILDDIR)/test_inotify TARGET5 := $(BUILDDIR)/dnsclient TARGET6 := $(BUILDDIR)/gwsocks5lib TARGET7 := $(BUILDDIR)/gwdnslib +TARGET8 := $(BUILDDIR)/gwdnsparserlib CC := gcc CFLAGS := -Wmaybe-uninitialized -Wall -Wextra -Os -g3 @@ -44,6 +47,8 @@ $(TARGET6): CFLAGS += -DRUNTEST -DENABLE_DUMP $(TARGET6): $(OBJS6) $(TARGET7): CFLAGS += -DRUNTEST $(TARGET7): $(OBJS7) +$(TARGET8): CFLAGS += -DRUNTEST +$(TARGET8): $(OBJS8) # test without log: make CFLAGS="-DENABLE_LOG=false" -B test_conventional test_conventional: $(TARGET1) @@ -55,6 +60,8 @@ test_dnsclient: $(TARGET5) $< 1.1.1.1 53 google.com github.com facebook.com test_gwsocks5lib: $(TARGET6) $< +test_gwdnsparserlib: $(TARGET8) + $< .PHONY: clean clean: diff --git a/gwdnsparserlib.c b/gwdnsparserlib.c index bf19c87..aa883d9 100644 --- a/gwdnsparserlib.c +++ b/gwdnsparserlib.c @@ -135,8 +135,6 @@ int serialize_answ(uint16_t txid, uint8_t *in, size_t in_len, gwdns_answ_data *o memcpy(&rdlength, in, sizeof(rdlength)); rdlength = ntohs(rdlength); item->rdlength = rdlength; - /* TODO: for now it's always assume the size is 4 bytes long (IPv4) */ - assert(rdlength == 4); in += 2; item->rdata = malloc(rdlength); @@ -194,3 +192,115 @@ ssize_t construct_question(gwdns_question_part *question) return required_len; } + +#ifdef RUNTEST + +void test_simulate_ipv4query(void) +{ + char buff[UDP_MSG_LIMIT]; + gwdns_query_pkt *send_pkt; + uint8_t recv_pkt[] = { + /* Header (12 bytes) */ + 0x00, 0x00, /* transaction ID - STUB! */ + 0x81, 0x80, /* Flags: QR=1, AA=0, RD=1, RA=1, RCODE=0 */ + 0x00, 0x01, /* QDCOUNT = 1 */ + 0x00, 0x06, /* ANCOUNT = 6 */ + 0x00, 0x00, /* NSCOUNT = 0 */ + 0x00, 0x00, /* ARCOUNT = 0 */ + + /* Question Section */ + /* Pointer label compression may be used in answers */ + 0x06, 'g','o','o','g','l','e', + 0x03, 'c','o','m', + 0x00, /* Terminate name */ + 0x00, 0x01, /* QTYPE = A */ + 0x00, 0x01, /* QCLASS = IN */ + + /* Answer Section (6 records) */ + /* Each Answer record: name pointer, type, class, ttl, rdlength, rdata */ + /* First Answer */ + 0xC0, 0x0C, /* Name: pointer to offset 0x0C (start of question name) */ + 0x00, 0x01, /* TYPE = A */ + 0x00, 0x01, /* CLASS = IN */ + 0x00, 0x00, 0x08, 0x62, /* TTL = 0x00000862 = 2146 sec */ + 0x00, 0x04, /* RDLENGTH = 4 */ + 0x4A, 0x7D, 0x18, 0x71, /* RDATA = 74.125.24.113 */ + + /* Second Answer */ + 0xC0, 0x0C, + 0x00, 0x01, + 0x00, 0x01, + 0x00, 0x00, 0x08, 0x62, + 0x00, 0x04, + 0x4A, 0x7D, 0x18, 0x65, /* 74.125.24.101 */ + + /* Third Answer */ + 0xC0, 0x0C, + 0x00, 0x01, + 0x00, 0x01, + 0x00, 0x00, 0x08, 0x62, + 0x00, 0x04, + 0x4A, 0x7D, 0x18, 0x8B, /* 74.125.24.139 */ + + /* Fourth Answer */ + 0xC0, 0x0C, + 0x00, 0x01, + 0x00, 0x01, + 0x00, 0x00, 0x08, 0x62, + 0x00, 0x04, + 0x4A, 0x7D, 0x18, 0x8A, /* 74.125.24.138 */ + + /* Fifth Answer */ + 0xC0, 0x0C, + 0x00, 0x01, + 0x00, 0x01, + 0x00, 0x00, 0x08, 0x62, + 0x00, 0x04, + 0x4A, 0x7D, 0x18, 0x64, /* 74.125.24.100 */ + + /* Sixth Answer */ + 0xC0, 0x0C, + 0x00, 0x01, + 0x00, 0x01, + 0x00, 0x00, 0x08, 0x62, + 0x00, 0x04, + 0x4A, 0x7D, 0x18, 0x66, /* 74.125.24.102 */ + }; + gwdns_answ_data d; + char first_label[] = "google"; + char second_label[] = "com"; + + memset(&d, 0, sizeof(d)); + gwdns_question_part q = { + .domain = "google.com", + .dst_buffer = (uint8_t *)buff, + .dst_len = sizeof(buff) + }; + assert(construct_question(&q) > 0); + + assert(buff[12] == 6); + assert(!memcmp(&buff[13], first_label, 6)); + + assert(buff[13 + 6] == 3); + assert(!memcmp(&buff[13 + 6 + 1], second_label, 3)); + + // fill the STUB + memcpy(recv_pkt, buff, 2); + + send_pkt = (void *)buff; + assert(!serialize_answ(send_pkt->hdr.id, recv_pkt, sizeof(recv_pkt), &d)); +} + +void run_all_tests(void) +{ + test_simulate_ipv4query(); + fprintf(stderr, "all tests passed!\n"); +} + +int main(void) +{ + run_all_tests(); + return 0; +} + +#endif diff --git a/gwdnsparserlib.h b/gwdnsparserlib.h index 3513442..d24e414 100644 --- a/gwdnsparserlib.h +++ b/gwdnsparserlib.h @@ -181,6 +181,17 @@ typedef struct { size_t domain_nr; } gwdns_resolv_hint; +/* +* Construct question packet +* +* @param prepared question +* @return length of bytes written into dst_buffer on success, or a negative integer on failure. +* +* 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 +*/ ssize_t construct_question(gwdns_question_part *question); /* @@ -192,10 +203,10 @@ ssize_t construct_question(gwdns_question_part *question); * @return zero on success or a negative number on failure * * possible error are: -* -EAGAIN in buffer is not sufficient, no bytes are processed, need more data. -* -EINVAL the content of in buffer is not valid. -* -ENOMEM failed to allocate dynamic memory. -* -ENODATA the packet didn't contain any answers. -* -EPROTO the DNS server can't understand your question +* -EAGAIN in buffer is not sufficient, no bytes are processed, need more data. +* -EINVAL the content of in buffer is not valid. +* -ENOMEM failed to allocate dynamic memory. +* -ENODATA the packet didn't contain any answers. +* -EPROTO the DNS server can't understand your question */ int serialize_answ(uint16_t txid, uint8_t *in, size_t in_len, gwdns_answ_data *out); \ No newline at end of file -- ReYuki