diff options
author | Anton Luka Šijanec <anton@sijanec.eu> | 2023-08-06 15:56:08 +0200 |
---|---|---|
committer | Anton Luka Šijanec <anton@sijanec.eu> | 2023-08-06 15:56:08 +0200 |
commit | 4b65846d2e369636e1c947c98c31507d4c08af10 (patch) | |
tree | ba8d82c0c1ca0e54943b86ca68f665cfd66a078f /prog/6/daemon.c | |
parent | raw6 (diff) | |
download | r-4b65846d2e369636e1c947c98c31507d4c08af10.tar r-4b65846d2e369636e1c947c98c31507d4c08af10.tar.gz r-4b65846d2e369636e1c947c98c31507d4c08af10.tar.bz2 r-4b65846d2e369636e1c947c98c31507d4c08af10.tar.lz r-4b65846d2e369636e1c947c98c31507d4c08af10.tar.xz r-4b65846d2e369636e1c947c98c31507d4c08af10.tar.zst r-4b65846d2e369636e1c947c98c31507d4c08af10.zip |
Diffstat (limited to '')
-rw-r--r-- | prog/6/daemon.c | 118 |
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 +} |