1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
}
|