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

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

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


Revision 1.2 - (hide annotations) (download) (as text)
Fri Sep 20 02:06:25 2002 UTC (17 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 stdarg 1.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 stdarg 1.2 #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 stdarg 1.1
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 stdarg 1.2 /* 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 stdarg 1.1 static int query_id = 1;
49     static dns_header_t _dns_header = {0};
50 stdarg 1.2 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 stdarg 1.1
59 stdarg 1.2 static void read_resolv(char *fname);
60     static void read_hosts(char *fname);
61 stdarg 1.1
62 stdarg 1.2 /* Read in .hosts and /etc/hosts and .resolv.conf and /etc/resolv.conf */
63 stdarg 1.1 int dns_init()
64     {
65 stdarg 1.2 FILE *fp;
66 stdarg 1.1 _dns_header.flags = htons(1 << 8 | 1 << 7);
67     _dns_header.question_count = htons(1);
68 stdarg 1.2 read_resolv("/etc/resolv.conf");
69     read_resolv(".resolv.conf");
70     read_hosts("/etc/hosts");
71     read_hosts(".hosts");
72 stdarg 1.1 return(0);
73     }
74    
75 stdarg 1.2 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 stdarg 1.1 {
102 stdarg 1.2 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 stdarg 1.1 }
111    
112 stdarg 1.2 static void read_resolv(char *fname)
113 stdarg 1.1 {
114 stdarg 1.2 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 stdarg 1.1 }
125 stdarg 1.2 fclose(fp);
126 stdarg 1.1 }
127    
128 stdarg 1.2 static void read_hosts(char *fname)
129 stdarg 1.1 {
130 stdarg 1.2 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 stdarg 1.1 }
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 stdarg 1.2 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 stdarg 1.1 {
202 stdarg 1.2 char *newhost = NULL;
203 stdarg 1.1 int len = 0;
204     int ns_type = 0;
205 stdarg 1.2 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 stdarg 1.1
252 stdarg 1.2 if (issue_callback) q->callback(q->client_data, q->query, NULL);
253     free(q);
254     return(0);
255 stdarg 1.1 }
256    
257 stdarg 1.2 static int skip_name(char *ptr, char *end)
258 stdarg 1.1 {
259     int len;
260 stdarg 1.2 char *start = ptr;
261 stdarg 1.1
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 stdarg 1.2 static void got_answer(int id, char *answer)
275 stdarg 1.1 {
276 stdarg 1.2 dns_query_t *q, *prev;
277 stdarg 1.1
278 stdarg 1.2 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 stdarg 1.1 }
284 stdarg 1.2 if (!q) return;
285    
286     if (prev) prev->next = q->next;
287     else query_head = q->next;
288 stdarg 1.1
289 stdarg 1.2 q->callback(q->client_data, q->query, answer);
290     free(q->query);
291     free(q);
292 stdarg 1.1 }
293    
294 stdarg 1.2 static void parse_reply(char *response, int nbytes)
295 stdarg 1.1 {
296     dns_header_t header;
297     dns_rr_t reply;
298     char result[512];
299 stdarg 1.2 char *ptr, *end;
300 stdarg 1.1 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 stdarg 1.2 //printf("ipv4 reply\n");
325 stdarg 1.1 inet_ntop(AF_INET, ptr, result, 512);
326 stdarg 1.2 got_answer(header.id, result);
327     return;
328 stdarg 1.1 }
329     else if (reply.type == 28) {
330 stdarg 1.2 //printf("ipv6 reply\n");
331 stdarg 1.1 inet_ntop(AF_INET6, ptr, result, 512);
332 stdarg 1.2 got_answer(header.id, result);
333     return;
334 stdarg 1.1 }
335     else if (reply.type == 12) {
336     char *placeholder;
337     int len, dot;
338    
339 stdarg 1.2 //printf("reverse-lookup reply\n");
340 stdarg 1.1 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 stdarg 1.2 return;
360 stdarg 1.1 }
361     ptr = placeholder;
362     }
363     ptr += reply.rdlength;
364     }
365     got_answer(header.id, NULL);
366     }
367    
368 stdarg 1.2 int dns_lookup(const char *host, int (*callback)())
369     {
370     }
371    
372 stdarg 1.1 main (int argc, char *argv[])
373     {
374 stdarg 1.2 char *query, response[512], *ptr, buf[512];
375 stdarg 1.1 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 stdarg 1.2 if (argc != 3) {
382     printf("usage: %s <host> <type>\n", argv[0]);
383 stdarg 1.1 printf(" <type> can be 1 (ipv4), 2 (ipv4), or 3 (reverse lookup)\n");
384     return(0);
385     }
386    
387 stdarg 1.2 dns_init();
388     if (!nservers) return(0);
389 stdarg 1.1 server.sin_family = AF_INET;
390     server.sin_port = htons(53);
391 stdarg 1.2 server.sin_addr.s_addr = inet_addr(servers[0].ip);
392 stdarg 1.1
393 stdarg 1.2 len = dns_make_query(argv[1], atoi(argv[2]), &query);
394 stdarg 1.1
395     sock = socket(AF_INET, SOCK_DGRAM, 0);
396    
397     if (sock < 0) {
398     perror("socket");
399     return(1);
400     }
401    
402 stdarg 1.2 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 stdarg 1.1 write(sock, query, len);
408     len = read(sock, response, 512);
409 stdarg 1.2 printf("parsing next reply, %d bytes\n", len);
410 stdarg 1.1 parse_reply(response, len);
411 stdarg 1.2 return(0);
412 stdarg 1.1 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23