]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
added miniminimininameserver
authorJelte Jansen <jeltejan@NLnetLabs.nl>
Wed, 25 Jan 2006 15:30:50 +0000 (15:30 +0000)
committerJelte Jansen <jeltejan@NLnetLabs.nl>
Wed, 25 Jan 2006 15:30:50 +0000 (15:30 +0000)
only udp, just answers with any match from the zonefile
no error checking
will probably not work on systems other than this linux box
but it's a start :)

examples/Makefile.in
examples/ldnsd.c [new file with mode: 0644]

index f59006e5626299f3645a42ae6d37cdb650cf7070..5dd5efdd4366449fc4dc3675230f81245d8b4b3e 100644 (file)
@@ -37,7 +37,8 @@ SOURCES       = ldns-read-zone.c \
                  ldns-threshold-update.c  \
                  ldns-zsplit.c \
                  ldns-zcat.c \
-                 ldns-dpa.c
+                 ldns-dpa.c \
+                 ldnsd.c
 
 
 PROGRAMS=$(SOURCES:.c=)
@@ -85,6 +86,9 @@ ldns-zsplit:  ldns-zsplit.o
 ldns-zcat:     ldns-zcat.o
                $(LINK) -o $@ $+
 
+ldnsd:         ldnsd.o
+               $(LINK) -o $@ $+
+
 ldns-threshold-update: ldns-threshold-update.o
                $(LINK) -o $@ $+
 
diff --git a/examples/ldnsd.c b/examples/ldnsd.c
new file mode 100644 (file)
index 0000000..83af8fe
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * ldnsd. Light-weight DNS daemon
+ *
+ * Tiny dns server to show how a real one could be built.
+ *
+ * (c) NLnet Labs, 2005
+ * See the file LICENSE for the license
+ */
+
+#include "config.h"
+#include <ldns/dns.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <netinet/igmp.h>
+
+#include <errno.h>
+
+#define INBUF_SIZE 4096
+
+void usage(FILE *output)
+{
+       fprintf(output, "Usage: ldnsd <port> <zone> <zonefile>\n");
+       fprintf(output, "Listens on the specified port and answers queries for the given zone\n");
+       fprintf(output, "This is NOT a full-fledged authoritative nameserver!\n");
+}
+
+static int udp_bind(int sock, int port, const char *my_address)
+{
+    struct sockaddr_in addr;
+
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons((uint16_t)port);
+               addr.sin_addr.s_addr = INADDR_ANY;
+//             if (join_mcast(sock, &addr) == -1) { return -1; }
+/*
+   if (join_group(sock, inet_addr(my_address), INADDR_ANY)) {
+      perror("setsockopt"); 
+   } else {
+      fprintf(stderr, "Ok.\n");
+               }
+*/ 
+    return bind(sock, (struct sockaddr *)&addr, (socklen_t) sizeof(addr));
+}
+
+/* this will probably be moved to a better place in the library itself */
+ldns_rr_list *
+get_rrset(const ldns_zone *zone, const ldns_rdf *owner_name, const ldns_rr_type qtype, const ldns_rr_class qclass)
+{
+       uint16_t i;
+       ldns_rr_list *rrlist = ldns_rr_list_new();
+       ldns_rr *cur_rr;
+       if (!zone || !owner_name) {
+               fprintf(stderr, "Warning: get_rrset called with NULL zone or owner name\n");
+               return rrlist;
+       }
+       
+       for (i = 0; i < ldns_zone_rr_count(zone); i++) {
+               cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
+               if (ldns_dname_compare(ldns_rr_owner(cur_rr), owner_name) == 0 &&
+                   ldns_rr_get_class(cur_rr) == qclass &&
+                   ldns_rr_get_type(cur_rr) == qtype
+                  ) {
+                       ldns_rr_list_push_rr(rrlist, ldns_rr_clone(cur_rr));
+               }
+       }
+       
+       printf("Found rrset of %u rrs\n", (unsigned int) ldns_rr_list_rr_count(rrlist));
+       
+       return rrlist;
+}
+
+int
+main(int argc, char **argv)
+{
+       /* arguments */
+       int port;
+       const char *zone_name;
+       const char *zone_file;
+
+       /* network */
+       int sock;
+       size_t nb;
+       struct sockaddr addr_me;
+       struct sockaddr addr_him;
+       socklen_t hislen;
+       const char *my_address;
+       uint8_t inbuf[INBUF_SIZE];
+       uint8_t *outbuf;
+
+       /* dns */
+       ldns_status status;
+       ldns_pkt *query_pkt;
+       ldns_pkt *answer_pkt;
+       size_t answer_size;
+       ldns_rr *query_rr;
+       ldns_rr_list *answer_qr;
+       ldns_rr_list *answer_an;
+       ldns_rr_list *answer_ns;
+       ldns_rr_list *answer_ad;
+       
+       /* zone */
+       ldns_zone *zone;
+       int line_nr;
+       FILE *zone_fp;
+       
+       /* use this to listen on specified interfaces later? */
+       my_address = NULL;
+               
+       if (argc < 4) {
+               usage(stdout);
+               exit(EXIT_FAILURE);
+       } else {
+               port = atoi(argv[1]);
+               if (port < 1) {
+                       usage(stdout);
+               }
+               zone_name = argv[2];
+               zone_file = argv[3];
+       }
+       
+       printf("Reading zone file %s\n", zone_file);
+       zone_fp = fopen(zone_file, "r");
+       if (!zone_fp) {
+               fprintf(stderr, "Unable to open %s: %s\n", zone_file, strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       
+       line_nr = 0;
+       zone = ldns_zone_new_frm_fp_l(zone_fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr);
+
+       if (!zone) {
+               printf("Zone reader failed, aborting\n");
+               exit(EXIT_FAILURE);
+       } else {
+               printf("Read %u resource records in zone file\n", (unsigned int) ldns_zone_rr_count(zone));
+       }
+
+       fclose(zone_fp);
+
+
+       printf("Listening on port %d\n", port);
+       sock =  socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock < 0) {
+               fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno));
+               exit(1);
+       }
+
+       memset(&addr_me, 0, sizeof(addr_me));
+
+       /* bind: try all ports in that range */
+       if (udp_bind(sock, port, my_address)) {
+               fprintf(stderr, "%s: cannot bind(): %s\n", argv[0], strerror(errno));
+       }
+
+       /* Done. Now receive */
+       while (1) {
+               nb = (size_t) recvfrom(sock, inbuf, INBUF_SIZE, 0, &addr_him, &hislen);
+               if (nb < 1) {
+                       fprintf(stderr, "%s: recvfrom(): %s\n",
+                       argv[0], strerror(errno));
+                       exit(1);
+               }
+
+               /*
+               show(inbuf, nb, nn, hp, sp, ip, bp);
+               */
+               
+               printf("Got query of %u bytes\n", (unsigned int) nb);
+               status = ldns_wire2pkt(&query_pkt, inbuf, nb);
+               if (status != LDNS_STATUS_OK) {
+                       printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
+               } else {
+                       ldns_pkt_print(stdout, query_pkt);
+               }
+               
+               query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
+               printf("QUERY RR: \n");
+               ldns_rr_print(stdout, query_rr);
+               
+               answer_qr = ldns_rr_list_new();
+               ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr));
+
+               answer_an = get_rrset(zone, ldns_rr_owner(query_rr), ldns_rr_get_type(query_rr), ldns_rr_get_class(query_rr));
+               answer_pkt = ldns_pkt_new();
+               
+               answer_ns = ldns_rr_list_new();
+               
+               answer_ad = ldns_rr_list_new();
+               
+               ldns_pkt_set_qr(answer_pkt, 1);
+               ldns_pkt_set_aa(answer_pkt, 1);
+               ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));
+
+               /* aren't there push_rr(section) functions? */
+               /* and why isn't the count automatically updated? */
+               ldns_pkt_set_question(answer_pkt, answer_qr);
+               ldns_pkt_set_qdcount(answer_pkt, ldns_rr_list_rr_count(answer_qr));
+               ldns_pkt_set_answer(answer_pkt, answer_an);
+               ldns_pkt_set_ancount(answer_pkt, ldns_rr_list_rr_count(answer_an));
+               ldns_pkt_set_authority(answer_pkt, answer_ns);
+               ldns_pkt_set_nscount(answer_pkt, ldns_rr_list_rr_count(answer_ns));
+               ldns_pkt_set_additional(answer_pkt, answer_ad);
+               ldns_pkt_set_arcount(answer_pkt, ldns_rr_list_rr_count(answer_ad));
+               
+               status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
+               
+               printf("Answer packet size: %u bytes.\n", (unsigned int) answer_size);
+               if (status != LDNS_STATUS_OK) {
+                       printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
+               } else {
+                       nb = (size_t) sendto(sock, outbuf, answer_size, 0, &addr_him, hislen);
+               }
+               
+               
+               
+       }
+
+        return 0;
+}