release
[hcoop/zz_old/debian/djbdns.git] / server.c
CommitLineData
dc0d77d7
CE
1#include "byte.h"
2#include "case.h"
3#include "env.h"
4#include "buffer.h"
5#include "strerr.h"
6#include "ip4.h"
7#include "uint16.h"
8#include "ndelay.h"
9#include "socket.h"
10#include "droproot.h"
11#include "qlog.h"
12#include "response.h"
13#include "dns.h"
14
15extern char *fatal;
16extern char *starting;
17extern int respond(char *,char *,char *);
18extern void initialize(void);
19
20static char ip[4];
21static uint16 port;
22
23static char buf[513];
24static int len;
25
26static char *q;
27
28static int doit(void)
29{
30 unsigned int pos;
31 char header[12];
32 char qtype[2];
33 char qclass[2];
34
35 if (len >= sizeof buf) goto NOQ;
36 pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto NOQ;
37 if (header[2] & 128) goto NOQ;
38 if (header[4]) goto NOQ;
39 if (header[5] != 1) goto NOQ;
40
41 pos = dns_packet_getname(buf,len,pos,&q); if (!pos) goto NOQ;
42 pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) goto NOQ;
43 pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) goto NOQ;
44
45 if (!response_query(q,qtype,qclass)) goto NOQ;
46 response_id(header);
47 if (byte_equal(qclass,2,DNS_C_IN))
48 response[2] |= 4;
49 else
50 if (byte_diff(qclass,2,DNS_C_ANY)) goto WEIRDCLASS;
51 response[3] &= ~128;
52 if (!(header[2] & 1)) response[2] &= ~1;
53
54 if (header[2] & 126) goto NOTIMP;
55 if (byte_equal(qtype,2,DNS_T_AXFR)) goto NOTIMP;
56
57 case_lowerb(q,dns_domain_length(q));
58 if (!respond(q,qtype,ip)) {
59 qlog(ip,port,header,q,qtype," - ");
60 return 0;
61 }
62 qlog(ip,port,header,q,qtype," + ");
63 return 1;
64
65 NOTIMP:
66 response[3] &= ~15;
67 response[3] |= 4;
68 qlog(ip,port,header,q,qtype," I ");
69 return 1;
70
71 WEIRDCLASS:
72 response[3] &= ~15;
73 response[3] |= 1;
74 qlog(ip,port,header,q,qtype," C ");
75 return 1;
76
77 NOQ:
78 qlog(ip,port,"\0\0","","\0\0"," / ");
79 return 0;
80}
81
82int main()
83{
84 char *x;
85 int udp53;
86
87 x = env_get("IP");
88 if (!x)
89 strerr_die2x(111,fatal,"$IP not set");
90 if (!ip4_scan(x,ip))
91 strerr_die3x(111,fatal,"unable to parse IP address ",x);
92
93 udp53 = socket_udp();
94 if (udp53 == -1)
95 strerr_die2sys(111,fatal,"unable to create UDP socket: ");
96 if (socket_bind4_reuse(udp53,ip,53) == -1)
97 strerr_die2sys(111,fatal,"unable to bind UDP socket: ");
98
99 droproot(fatal);
100
101 initialize();
102
103 ndelay_off(udp53);
104 socket_tryreservein(udp53,65536);
105
106 buffer_putsflush(buffer_2,starting);
107
108 for (;;) {
109 len = socket_recv4(udp53,buf,sizeof buf,ip,&port);
110 if (len < 0) continue;
111 if (!doit()) continue;
112 if (response_len > 512) response_tc();
113 socket_send4(udp53,response,response_len,ip,port);
114 /* may block for buffer space; if it fails, too bad */
115 }
116}