djbdnscurve6  38
djbdnscurve6
server.c
Go to the documentation of this file.
1 #include "byte.h"
2 #include "case.h"
3 #include "env.h"
4 #include "buffer.h"
5 #include "ip.h"
6 #include "uint_t.h"
7 #include "ndelay.h"
8 #include "socket_if.h"
9 #include "droproot.h"
10 #include "qlog.h"
11 #include "response.h"
12 #include "dns.h"
13 #include "alloc.h"
14 #include "str.h"
15 #include "edns0.h"
16 #include "logmsg.h"
17 
18 uint16 dnsport = 53;
19 extern char *fatal;
20 extern char *starting;
21 extern int respond(char *,char *,char *);
22 extern void initialize(void);
23 int flagdualstack = 0;
25 
26 static char ip[16];
27 static uint16 port;
28 
29 static char buf[MSGSIZE+1];
30 static int len;
31 
32 static char *q;
33 
34 void nomem()
35 {
36  logmsg(fatal,111,FATAL,"out of memory");
37 }
38 
39 static int doit(void)
40 {
41  unsigned int pos;
42  char header[12];
43  char qtype[2];
44  char qclass[2];
45 
46  if (len >= sizeof(buf)) goto NOQ;
47  pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto NOQ;
48  if (header[2] & 128) goto NOQ;
49  if (header[4]) goto NOQ;
50  if (header[5] != 1) goto NOQ;
51 
52  pos = dns_packet_getname(buf,len,pos,&q); if (!pos) goto NOQ;
53  pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) goto NOQ;
54  pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) goto NOQ;
55 
56  if (!response_query(q,qtype,qclass)) goto NOQ;
57  response_id(header);
58  if (byte_equal(qclass,2,DNS_C_IN))
59  response[2] |= 4;
60  else
61  if (byte_diff(qclass,2,DNS_C_ANY)) goto WEIRDCLASS;
62  response[3] &= ~128;
63  if (!(header[2] & 1)) response[2] &= ~1;
64 
65  if (header[2] & 126) goto NOTIMP;
66  if (byte_equal(qtype,2,DNS_T_AXFR)) goto NOTIMP;
67 
68  case_lowerb(q,dns_domain_length(q));
69  if (!respond(q,qtype,ip)) {
70  qlog(ip,port,header,q,qtype," - ");
71  return 0;
72  }
73  qlog(ip,port,header,q,qtype," + ");
74  return 1;
75 
76  NOTIMP:
77  response[3] &= ~15;
78  response[3] |= 4;
79  qlog(ip,port,header,q,qtype," I ");
80  return 1;
81 
82  WEIRDCLASS:
83  response[3] &= ~15;
84  response[3] |= 1;
85  qlog(ip,port,header,q,qtype," C ");
86  return 1;
87 
88  NOQ:
89  qlog(ip,port,"\0\0","","\0\0"," / ");
90  return 0;
91 }
92 
93 int main()
94 {
95  char *x;
96  int udp53;
97  stralloc ifname = {0};
98  uint32 ifidx = 0;
99 
100  x = env_get("IP");
101  if (!x)
102  logmsg(fatal,111,ERROR,"IP not set");
103  if (case_equals(x,"::")) {
104  flagipv6anycast = 1;
105  } else if (case_equals(x,":0")) {
106  flagdualstack = 1;
107  byte_copy(x,2,"::");
108  }
109  if (!ip6_ifscan(x,ip,&ifname))
110  logmsg(fatal,111,FATAL,B("unable to parse IPv6 address: ",x));
111 
112  if (ifname.len > 1) ifidx = socket_getifidx(ifname.s);
113  if (ip6_isv4mapped(ip))
114  udp53 = socket_udp4();
115  else
116  udp53 = socket_udp();
117  if (udp53 == -1)
118  logmsg(fatal,111,FATAL,"unable to create UDP socket");
119 
120  if (flagdualstack) socket_dualstack(udp53);
121  if (flagipv6anycast) socket_ip6anycast(udp53);
122  if (socket_bind_reuse(udp53,ip,dnsport,ifidx) == -1)
123  logmsg(fatal,111,FATAL,"unable to bind UDP socket");
124 
125  droproot(fatal);
126 
127  initialize();
128 
129  ndelay_off(udp53);
130  socket_tryreservein(udp53,65536);
131 
133 
134  for (;;) {
135  len = socket_recv(udp53,buf,sizeof(buf),ip,&port,&ifidx);
136  if (len < 0) continue;
137  if (!doit()) continue;
138  if (flagdualstack)
139  socket_send6(udp53,response,response_len,ip,port,ifidx);
140  else
141  socket_send(udp53,response,response_len,ip,port,ifidx);
142  /* may block for buffer space; if it fails, too bad */
143  }
144 }
unsigned int doit(char *buf, unsigned int len, unsigned int pos)
Definition: axfr-get.c:131
unsigned long port
Definition: axfrdns.c:127
char ip[16]
Definition: axfrdns.c:126
uint16 len
Definition: axfrdns.c:302
char buf[MSGSIZE]
Definition: axfrdns.c:301
unsigned int dns_packet_copy(const char *, unsigned int, unsigned int, char *, unsigned int)
Definition: dns_packet.c:8
#define DNS_T_AXFR
Definition: dns.h:65
#define DNS_C_IN
Definition: dns.h:34
#define MSGSIZE
Definition: dns.h:26
unsigned int dns_domain_length(const char *)
Definition: dns_domain.c:6
#define DNS_C_ANY
Definition: dns.h:35
unsigned int dns_packet_getname(const char *, unsigned int, unsigned int, char **)
Definition: dns_packet.c:35
uint32 ifidx
Definition: dnscache.c:31
stralloc ifname
Definition: dnscache.c:30
struct line * x
void droproot(const char *fatal)
Definition: droproot.c:8
void qlog(const char ip[16], uint16 port, const char id[2], const char *q, const char qtype[2], const char *result)
Definition: qlog.c:51
void log_start(const char *s, const char ip[16], uint32 scope)
Definition: qlog.c:30
void response_id(const char id[2])
Definition: response.c:114
char response[65535]
Definition: response.c:6
unsigned int response_len
Definition: response.c:7
int response_query(const char *q, const char qtype[2], const char qclass[2])
Definition: response.c:54
int flagipv6anycast
Definition: server.c:24
int respond(char *, char *, char *)
char * fatal
Definition: rbldns.c:16
void nomem()
Definition: server.c:34
char * starting
Definition: rbldns.c:159
void initialize(void)
Definition: rbldns.c:161
uint16 dnsport
Definition: server.c:18
int main()
Definition: server.c:93
int flagdualstack
Definition: server.c:23