summaryrefslogtreecommitdiffstats
path: root/prog/6/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'prog/6/daemon.c')
-rw-r--r--prog/6/daemon.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/prog/6/daemon.c b/prog/6/daemon.c
new file mode 100644
index 0000000..849ebb3
--- /dev/null
+++ b/prog/6/daemon.c
@@ -0,0 +1,118 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <poll.h>
+#include <arpa/nameser.h>
+#include <sys/uio.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <resolv.h>
+#include <errno.h>
+#define DEBUG 1
+int handle (unsigned char * packet, int bytes) {
+ HEADER * header = (HEADER *) packet;
+ ns_msg handle;
+ if (ns_initparse(packet, bytes, &handle) == -1)
+ return -1;
+ if (header->qr) // response
+ return -1;
+ header->qr = 1;
+ header->tc = 0;
+ header->aa = 0;
+ header->ra = 0;
+ if (header->opcode) {
+ header->rcode = NOTIMP;
+ return bytes;
+ }
+ if (header->qdcount != 1) {
+ header->rcode = FORMERR;
+ return bytes;
+ }
+ ns_rr rr;
+ if (ns_parserr(handle, ms_s_qd, 0, &rr) == -1) {
+ header->rcode = FORMERR;
+ return bytes;
+ }
+
+}
+int main (int argc, char ** argv) {
+ if (argc != 3) {
+ fprintf(stderr, "%s port config\n"
+ " port: 53 (UDP listening port) (configurable to allow many daemons)\n"
+ " config: file name of the configuration file (use 6c to check syntax)\n"
+ "creates PTR and AAAA records with on-the-fly method (RFC 8501, section 2.5)\n"
+ "an example of records created for IPv6 2001:db8:1\n"
+ " 1.0.[...].0.8.B.D.0.1.0.0.2.IP6.ARPA. 127800 IN PTR 1.0.[...].0.8.B.D.0.1.0.0.2.IP6.ARPA.\n"
+ " 1.0.[...].0.8.B.D.0.1.0.0.2.IP6.ARPA. 127800 IN AAAA 2001:db8::1\n"
+ "more information:\n"
+ " - SOA serial will be the number of days since 2023-08-06\n"
+ " - refresh, retry and expire in SOA will have values conforming to standard, but\n"
+ " they are irrelevant, as potential 6d slaves are not real DNS slaves\n"
+ " - negative cache TTL is 1337, this is irrelevant, as nxdomains aren't expected\n"
+ " - to exit after reading and printing out the configuration, run %s dry <config>\n"
+ , argv[0]);
+ return 1;
+ }
+ int sock = socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
+ if (sock == -1) {
+ perror("socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)");
+ return 2;
+ }
+ struct sockaddr_in6 listen = {
+ .sin6_family = AF_INET6,
+ .sin6_port = htons(53),
+ .sin6_addr = IN6ADDR_ANY_INIT
+ };
+ if (bind(sock, (struct sockaddr *) &listen, sizeof listen) == -1) {
+ perror("bind(sock, &listen, sizeof listen)");
+ return 3;
+ }
+ struct pollfd pfd = {
+ .fd = sock,
+ .events = POLLIN
+ };
+ while (poll(&pfd, 1, -1) != -1) {
+ if (pfd.revents & POLLERR) {
+ fprintf(stderr, "POLLERR\n");
+ return 5;
+ }
+ if (pfd.revents & POLLHUP) {
+ fprintf(stderr, "POLLHUP\n");
+ return 6;
+ }
+ if (pfd.revents & POLLNVAL) {
+ fprintf(stderr, "POLLNVAL\n");
+ return 7;
+ }
+ struct sockaddr_in6 sender;
+ unsigned char packet[512];
+ struct iovec parts[] = {
+ {
+ .iov_base = packet,
+ .iov_len = sizeof packet
+ }
+ };
+ struct msghdr msg = {
+ .msg_name = &sender,
+ .msg_namelen = sizeof sender,
+ .msg_iov = parts,
+ .msg_iovlen = sizeof parts/sizeof parts[0]
+ };
+ int bytes = recvmsg(sock, &msg, MSG_DONTWAIT | MSG_TRUNC);
+ if (bytes == -1) {
+ perror("recvmsg");
+ return 8;
+ }
+ int len = handle(packet, bytes);
+ if (len >= 0) {
+ if (sendto(sock, packet, len, MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *) &sender, sizeof sender) == -1 && errno != EACCES) {
+ perror("sendto");
+ return 9;
+ }
+ }
+ }
+ perror("poll");
+ return 4; // there really is no successful exit code, this program should run indefinitely
+}