/[cvs]/eggdrop1.9/testcode/dnscache.c
ViewVC logotype

Contents of /eggdrop1.9/testcode/dnscache.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Fri Sep 20 02:06:25 2002 UTC (16 years, 6 months ago) by stdarg
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +217 -58 lines
File MIME type: text/x-chdr
* Moved several things from the core into libegg
* Server module uses new network code
* Lots of stuff removed from the server module, like flood stuff, which should go into a new module
* Moved some things from irc module to server module (mostly bind stuff, like pub)
* Not everything works right now, but I wanted to get it into cvs in case my computer dies a horrible death. I'm going to combine irc/server (mostly) and make a new one for all the default protection stuff.
* Right now server messages are not queued. I thought the code was pretty much beyond repair. The new queueing code will hopefully be more maintainable.
* I'm not sure I added/removed all the files necessary! Let me know if it doesn't compile for you.

1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/socket.h>
4 #include <netinet/in.h>
5 #include "my_socket.h"
6
7 #define DNS_IPV4 1
8 #define DNS_IPV6 2
9 #define DNS_REVERSE 3
10
11 typedef struct dns_query {
12 struct dns_query *next;
13 char *query;
14 int id;
15 int (*callback)(void *client_data, const char *query, const char *result);
16 void *client_data;
17 } dns_query_t;
18
19 typedef struct {
20 unsigned short id;
21 unsigned short flags;
22 unsigned short question_count;
23 unsigned short answer_count;
24 unsigned short ns_count;
25 unsigned short ar_count;
26 } dns_header_t;
27
28 typedef struct {
29 /* char name[]; */
30 unsigned short type;
31 unsigned short class;
32 int ttl;
33 unsigned short rdlength;
34 /* char rdata[]; */
35 } dns_rr_t;
36
37 /* Entries from resolv.conf */
38 typedef struct dns_server {
39 char *ip;
40 int idx;
41 } dns_server_t;
42
43 /* Entries from hosts */
44 typedef struct {
45 char *host, *ip;
46 } dns_host_t;
47
48 static int query_id = 1;
49 static dns_header_t _dns_header = {0};
50 static dns_query_t *query_head = NULL;
51 static dns_host_t *hosts = NULL;
52 static int nhosts = 0;
53 static dns_server_t *servers = NULL;
54 static int nservers = 0;
55 static int curserver = -1;
56
57 static char separators[] = " ,\t";
58
59 static void read_resolv(char *fname);
60 static void read_hosts(char *fname);
61
62 /* Read in .hosts and /etc/hosts and .resolv.conf and /etc/resolv.conf */
63 int dns_init()
64 {
65 FILE *fp;
66 _dns_header.flags = htons(1 << 8 | 1 << 7);
67 _dns_header.question_count = htons(1);
68 read_resolv("/etc/resolv.conf");
69 read_resolv(".resolv.conf");
70 read_hosts("/etc/hosts");
71 read_hosts(".hosts");
72 return(0);
73 }
74
75 const char *dns_next_server()
76 {
77 static int cur_server = 0;
78
79 if (!servers || nservers < 1) return("127.0.0.1");
80 if (cur_server >= nservers) cur_server = 0;
81 return(servers[cur_server].ip);
82 }
83
84 static void add_server(char *ip)
85 {
86 servers = (dns_server_t *)realloc(servers, (nservers+1)*sizeof(*servers));
87 servers[nservers].ip = strdup(ip);
88 servers[nservers].idx = -1;
89 nservers++;
90 }
91
92 static void add_host(char *host, char *ip)
93 {
94 hosts = (dns_host_t *)realloc(hosts, (nhosts+1)*sizeof(*hosts));
95 hosts[nhosts].host = strdup(host);
96 hosts[nhosts].ip = strdup(ip);
97 nhosts++;
98 }
99
100 static int read_thing(char *buf, char *ip)
101 {
102 int skip, len;
103
104 skip = strspn(buf, separators);
105 buf += skip;
106 len = strcspn(buf, separators);
107 memcpy(ip, buf, len);
108 ip[len] = 0;
109 return(skip + len);
110 }
111
112 static void read_resolv(char *fname)
113 {
114 FILE *fp;
115 char buf[512], ip[512];
116
117 fp = fopen(fname, "r");
118 if (!fp) return;
119 while (fgets(buf, sizeof(buf), fp)) {
120 if (!strncasecmp(buf, "nameserver", 10)) {
121 read_thing(buf+10, ip);
122 if (strlen(ip)) add_server(ip);
123 }
124 }
125 fclose(fp);
126 }
127
128 static void read_hosts(char *fname)
129 {
130 FILE *fp;
131 char buf[512], ip[512], host[512];
132 int skip, n;
133
134 fp = fopen(fname, "r");
135 if (!fp) return;
136 while (fgets(buf, sizeof(buf), fp)) {
137 if (strchr(buf, '#')) continue;
138 skip = read_thing(buf, ip);
139 if (!strlen(ip)) continue;
140 while (n = read_thing(buf+skip, host)) {
141 skip += n;
142 if (strlen(host)) add_host(ip, host);
143 }
144 }
145 }
146
147 static int make_header(char *buf, int id)
148 {
149 _dns_header.id = htons(id);
150 memcpy(buf, &_dns_header, 12);
151 return(12);
152 }
153
154 static int cut_host(char *host, char *query)
155 {
156 char *period, *orig;
157 int len;
158
159 orig = query;
160 while (period = strchr(host, '.')) {
161 len = period - host;
162 if (len > 63) return(-1);
163 *query++ = len;
164 memcpy(query, host, len);
165 query += len;
166 host = period+1;
167 }
168 len = strlen(host);
169 if (len) {
170 *query++ = len;
171 memcpy(query, host, len);
172 query += len;
173 }
174 *query++ = 0;
175 return(query-orig);
176 }
177
178 static int reverse_ip(char *host, char *reverse)
179 {
180 char *period;
181 int offset, len;
182
183 printf("reversing %s\n", host);
184 period = strchr(host, '.');
185 if (!period) {
186 len = strlen(host);
187 memcpy(reverse, host, len);
188 return(len);
189 }
190 else {
191 len = period - host;
192 offset = reverse_ip(host+len+1, reverse);
193 reverse[offset++] = '.';
194 memcpy(reverse+offset, host, len);
195 reverse[offset+len] = 0;
196 return(offset+len);
197 }
198 }
199
200 int dns_make_query(char *host, int type, char **buf, int *query_len, int (*callback)(), void *client_data)
201 {
202 char *newhost = NULL;
203 int len = 0;
204 int ns_type = 0;
205 dns_query_t *q;
206
207 if (type == DNS_IPV4) ns_type = 1; /* IPv4 */
208 else if (type == DNS_IPV6) ns_type = 28; /* IPv6 */
209 else if (type == DNS_REVERSE) {
210 /* We need to transform the ip address into the proper form
211 * for reverse lookup. */
212 newhost = (char *)malloc(strlen(host) + 14);
213 reverse_ip(host, newhost);
214 strcat(newhost, ".in-addr.arpa");
215 printf("newhost: %s\n", newhost);
216 host = newhost;
217 ns_type = 12; /* PTR (reverse lookup) */
218 }
219 else return(-1);
220
221 *buf = (char *)malloc(strlen(host) + 512);
222 len = make_header(*buf, query_id);
223 len += cut_host(host, *buf + len);
224 (*buf)[len] = 0; len++; (*buf)[len] = ns_type; len++;
225 (*buf)[len] = 0; len++; (*buf)[len] = 1; len++;
226 if (newhost) free(newhost);
227 *query_len = len;
228
229 q = calloc(1, sizeof(*q));
230 q->id = query_id;
231 query_id++;
232 q->callback = callback;
233 q->client_data = client_data;
234 if (query_head) q->next = query_head->next;
235 query_head = q;
236 return(q->id);
237 }
238
239 static int dns_cancel_query(int id, int issue_callback)
240 {
241 dns_query_t *q, *prev;
242
243 prev = NULL;
244 for (q = query_head; q; q = q->next) {
245 if (q->id == id) break;
246 prev = q;
247 }
248 if (!q) return(-1);
249 if (prev) prev->next = q->next;
250 else query_head = q->next;
251
252 if (issue_callback) q->callback(q->client_data, q->query, NULL);
253 free(q);
254 return(0);
255 }
256
257 static int skip_name(char *ptr, char *end)
258 {
259 int len;
260 char *start = ptr;
261
262 while ((len = *ptr++) > 0) {
263 if (len > 63) {
264 ptr++;
265 break;
266 }
267 else {
268 ptr += len;
269 }
270 }
271 return(ptr - start);
272 }
273
274 static void got_answer(int id, char *answer)
275 {
276 dns_query_t *q, *prev;
277
278 printf("got_answer for id %d: %s\n", id, answer);
279 prev = NULL;
280 for (q = query_head; q; q = q->next) {
281 if (q->id == id) break;
282 prev = q;
283 }
284 if (!q) return;
285
286 if (prev) prev->next = q->next;
287 else query_head = q->next;
288
289 q->callback(q->client_data, q->query, answer);
290 free(q->query);
291 free(q);
292 }
293
294 static void parse_reply(char *response, int nbytes)
295 {
296 dns_header_t header;
297 dns_rr_t reply;
298 char result[512];
299 char *ptr, *end;
300 int i;
301
302 ptr = response;
303 memcpy(&header, ptr, 12);
304 ptr += 12;
305
306 header.id = ntohs(header.id);
307 header.question_count = ntohs(header.question_count);
308 header.answer_count = ntohs(header.answer_count);
309
310 /* Pass over the question. */
311 ptr += skip_name(ptr, end);
312 ptr += 4;
313 /* End of question. */
314
315 for (i = 0; i < header.answer_count; i++) {
316 result[0] = 0;
317 /* Read in the answer. */
318 ptr += skip_name(ptr, end);
319 memcpy(&reply, ptr, 10);
320 reply.type = ntohs(reply.type);
321 reply.rdlength = ntohs(reply.rdlength);
322 ptr += 10;
323 if (reply.type == 1) {
324 //printf("ipv4 reply\n");
325 inet_ntop(AF_INET, ptr, result, 512);
326 got_answer(header.id, result);
327 return;
328 }
329 else if (reply.type == 28) {
330 //printf("ipv6 reply\n");
331 inet_ntop(AF_INET6, ptr, result, 512);
332 got_answer(header.id, result);
333 return;
334 }
335 else if (reply.type == 12) {
336 char *placeholder;
337 int len, dot;
338
339 //printf("reverse-lookup reply\n");
340 placeholder = ptr;
341 result[0] = 0;
342 while ((len = *ptr++) != 0) {
343 if (len > 63) {
344 ptr++;
345 break;
346 }
347 else {
348 dot = ptr[len];
349 ptr[len] = 0;
350 strcat(result, ptr);
351 strcat(result, ".");
352 ptr[len] = dot;
353 ptr += len;
354 }
355 }
356 if (strlen(result)) {
357 result[strlen(result)-1] = 0;
358 got_answer(header.id, result);
359 return;
360 }
361 ptr = placeholder;
362 }
363 ptr += reply.rdlength;
364 }
365 got_answer(header.id, NULL);
366 }
367
368 int dns_lookup(const char *host, int (*callback)())
369 {
370 }
371
372 main (int argc, char *argv[])
373 {
374 char *query, response[512], *ptr, buf[512];
375 int i, len, sock;
376 struct sockaddr_in server;
377 dns_header_t header;
378 dns_rr_t reply;
379 unsigned long addr;
380
381 if (argc != 3) {
382 printf("usage: %s <host> <type>\n", argv[0]);
383 printf(" <type> can be 1 (ipv4), 2 (ipv4), or 3 (reverse lookup)\n");
384 return(0);
385 }
386
387 dns_init();
388 if (!nservers) return(0);
389 server.sin_family = AF_INET;
390 server.sin_port = htons(53);
391 server.sin_addr.s_addr = inet_addr(servers[0].ip);
392
393 len = dns_make_query(argv[1], atoi(argv[2]), &query);
394
395 sock = socket(AF_INET, SOCK_DGRAM, 0);
396
397 if (sock < 0) {
398 perror("socket");
399 return(1);
400 }
401
402 connect(sock, (struct sockaddr *)&server, sizeof(server));
403 write(sock, query, len);
404 len = read(sock, response, 512);
405 printf("parsing reply, %d bytes\n", len);
406 parse_reply(response, len);
407 write(sock, query, len);
408 len = read(sock, response, 512);
409 printf("parsing next reply, %d bytes\n", len);
410 parse_reply(response, len);
411 return(0);
412 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23