/[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.1 - (show annotations) (download) (as text)
Fri Aug 9 23:48:18 2002 UTC (17 years, 7 months ago) by stdarg
Branch: MAIN
File MIME type: text/x-chdr
* beginning of a small caching dns stub resolver, ipv4 and ipv6

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 typedef struct {
8 char *host;
9 char *ip;
10 int expiration;
11 } dns_entry_t;
12
13 typedef struct {
14 unsigned short id;
15 unsigned short flags;
16 unsigned short question_count;
17 unsigned short answer_count;
18 unsigned short ns_count;
19 unsigned short ar_count;
20 } dns_header_t;
21
22 typedef struct {
23 /* char name[]; */
24 unsigned short type;
25 unsigned short class;
26 int ttl;
27 unsigned short rdlength;
28 /* char rdata[]; */
29 } dns_rr_t;
30
31 static int query_id = 1;
32 static dns_header_t _dns_header = {0};
33 static dns_entry_t *dns_cache = NULL;
34 static int dns_cache_len;
35
36 static char **nameservers = NULL;
37
38 /* Read in ~/.hosts and /etc/hosts and ~/.resolv.conf and /etc/resolv.conf */
39 int dns_init()
40 {
41 _dns_header.flags = htons(1 << 8 | 1 << 7);
42 _dns_header.question_count = htons(1);
43 return(0);
44 }
45
46 static char *search_cache_by_host(char *host)
47 {
48 int i;
49 for (i = 0; i < dns_cache_len; i++) {
50 if (!strcasecmp(dns_cache[i].host, host)) return(dns_cache[i].ip);
51 }
52 return(NULL);
53 }
54
55 static char *search_cache_by_ip(char *ip)
56 {
57 int i;
58 for (i = 0; i < dns_cache_len; i++) {
59 if (!strcasecmp(dns_cache[i].ip, ip)) return(dns_cache[i].host);
60 }
61 return(NULL);
62 }
63
64 static void add_cache_entry(char *host, char *ip, int expires)
65 {
66 dns_cache = (dns_entry_t *)realloc(dns_cache, (dns_cache_len+1) * sizeof(dns_entry_t));
67 dns_cache[dns_cache_len].host = strdup(host);
68 dns_cache[dns_cache_len].ip = strdup(ip);
69 dns_cache[dns_cache_len].expires = expires;
70 dns_cache_len++;
71 }
72
73 static int make_header(char *buf, int id)
74 {
75 _dns_header.id = htons(id);
76 memcpy(buf, &_dns_header, 12);
77 return(12);
78 }
79
80 static int cut_host(char *host, char *query)
81 {
82 char *period, *orig;
83 int len;
84
85 orig = query;
86 while (period = strchr(host, '.')) {
87 len = period - host;
88 if (len > 63) return(-1);
89 *query++ = len;
90 memcpy(query, host, len);
91 query += len;
92 host = period+1;
93 }
94 len = strlen(host);
95 if (len) {
96 *query++ = len;
97 memcpy(query, host, len);
98 query += len;
99 }
100 *query++ = 0;
101 return(query-orig);
102 }
103
104 static int make_query(char *host, int type, unsigned char *buf)
105 {
106 int len = 0;
107 int ns_type = 0;
108
109 if (type == IPV4_QUERY) ns_type = 1; /* IPv4 */
110 else if (type == IPV6_QUERY) ns_type = 28; /* IPv6 */
111 else if (type == REVERSE_QUERY) ns_type = 12; /* PTR (reverse lookup) */
112 else return(0);
113
114 len = make_header(buf, query_id++);
115 len += cut_host(host, buf + len);
116 buf[len] = 0; len++; buf[len] = ns_type; len++;
117 buf[len] = 0; len++; buf[len] = 1; len++;
118 return(len);
119 }
120
121 static int skip_name(unsigned char *ptr, char *end)
122 {
123 int len;
124 unsigned char *start = ptr;
125
126 while ((len = *ptr++) > 0) {
127 if (len > 63) {
128 ptr++;
129 break;
130 }
131 else {
132 ptr += len;
133 }
134 }
135 return(ptr - start);
136 }
137
138 static int got_answer(int id, char *answer)
139 {
140 int i;
141
142 for (i = 0; i < nquestions; i++) {
143 if (questions[i].id == id) break;
144 }
145 if (i == nquestions) break;
146
147 }
148
149 static void parse_reply(unsigned char *response, int nbytes)
150 {
151 dns_header_t header;
152 dns_rr_t reply;
153 char result[512];
154 unsigned char *ptr, *end;
155 int i;
156
157 ptr = response;
158 memcpy(&header, ptr, 12);
159 ptr += 12;
160
161 header.id = ntohs(header.id);
162 header.question_count = ntohs(header.question_count);
163 header.answer_count = ntohs(header.answer_count);
164
165 /* Pass over the question. */
166 ptr += skip_name(ptr, end);
167 ptr += 4;
168 /* End of question. */
169
170 for (i = 0; i < header.answer_count; i++) {
171 result[0] = 0;
172 /* Read in the answer. */
173 ptr += skip_name(ptr, end);
174 memcpy(&reply, ptr, 10);
175 reply.type = ntohs(reply.type);
176 reply.rdlength = ntohs(reply.rdlength);
177 ptr += 10;
178 if (reply.type == 1) {
179 printf("ipv4 reply\n");
180 inet_ntop(AF_INET, ptr, result, 512);
181 if (got_answer(header.id, result)) break;
182 }
183 else if (reply.type == 28) {
184 printf("ipv6 reply\n");
185 inet_ntop(AF_INET6, ptr, result, 512);
186 if (got_answer(header.id, result)) break;
187 }
188 else if (reply.type == 12) {
189 char *placeholder;
190 int len, dot;
191
192 printf("reverse-lookup reply\n");
193 placeholder = ptr;
194 result[0] = 0;
195 while ((len = *ptr++) != 0) {
196 if (len > 63) {
197 ptr++;
198 break;
199 }
200 else {
201 dot = ptr[len];
202 ptr[len] = 0;
203 strcat(result, ptr);
204 strcat(result, ".");
205 ptr[len] = dot;
206 ptr += len;
207 }
208 }
209 if (strlen(result)) {
210 result[strlen(result)-1] = 0;
211 got_answer(header.id, result);
212 }
213 ptr = placeholder;
214 }
215 ptr += reply.rdlength;
216 }
217 got_answer(header.id, NULL);
218 }
219
220 main (int argc, char *argv[])
221 {
222 unsigned char query[512], response[512], *ptr, buf[512];
223 int i, len, sock;
224 struct sockaddr_in server;
225 dns_header_t header;
226 dns_rr_t reply;
227 unsigned long addr;
228
229 if (argc != 4) {
230 printf("usage: %s <dns ip> <host> <type>\n", argv[0]);
231 printf(" <type> can be 1 (ipv4), 2 (ipv4), or 3 (reverse lookup)\n");
232 return(0);
233 }
234
235 server.sin_family = AF_INET;
236 server.sin_port = htons(53);
237 server.sin_addr.s_addr = inet_addr(argv[1]);
238
239 dns_init();
240 len = make_query(argv[2], atoi(argv[3]), query);
241
242 sock = socket(AF_INET, SOCK_DGRAM, 0);
243
244 if (sock < 0) {
245 perror("socket");
246 return(1);
247 }
248
249 connect(sock, &server, sizeof(server));
250 write(sock, query, len);
251 len = read(sock, response, 512);
252 parse_reply(response, len);
253 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23