Fixed ZDE build - missing header file
[ZeXOS.git] / kernel / core / net / dns.c
blobb5c4f19e6f091bf5ecdc355be44ddf6c6d683293
1 /*
2 * ZeX/OS
3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <system.h>
22 #include <string.h>
23 #include <dev.h>
24 #include <net/eth.h>
25 #include <net/net.h>
26 #include <net/if.h>
27 #include <net/ip.h>
28 #include <net/packet.h>
29 #include <net/dns.h>
30 #include <net/socket.h>
32 dns_cache_t dns_cache_list;
34 net_ipv4 dns_ip;
36 unsigned short dns_trans = NULL;
38 #define DEFAULT_DNS_ADDRESS NET_IPV4_TO_ADDR (192,168,0,1)
40 /* prototype */
41 int dns_cache_add (char *hostname, unsigned char len, void *ip, unsigned char type);
44 unsigned dns_addr (net_ipv4 dns)
46 dns_ip = dns;
48 return 1;
51 net_ipv4 dns_addr_get ()
53 return dns_ip;
56 int dns_send_request (char *hostname, void *ip, unsigned char type)
58 if (!ip || !hostname)
59 return -1;
61 if (!type)
62 return 0;
64 int sock = 0;
65 int err = 0;
67 /* Create a socket */
68 if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
69 DPRINT (DBG_NET | DBG_DNS, "Cant create socket");
70 return -1;
73 sockaddr_in serverSock;
75 serverSock.sin_family = AF_INET;
76 serverSock.sin_port = htons (DEFAULT_DNS_PORT);
77 memcpy (&(serverSock.sin_addr), &dns_ip, sizeof (net_ipv4));
79 /* Lets connect to dns server */
80 if (connect (sock, (sockaddr *) &serverSock, sizeof (serverSock)) == -1) {
81 DPRINT (DBG_NET | DBG_DNS, "Connection cant be estabilished");
82 return -1;
85 unsigned short len = strlen (hostname);
87 proto_dns_t *dns = (proto_dns_t *) kmalloc (sizeof (proto_dns_t)+len+7);
89 if (!dns)
90 return -1;
92 /* dns header */
93 dns->trans = swap16 (dns_trans ++);
94 dns->flags = swap16 (0x0100);
95 dns->question = swap16 (1);
96 dns->answer = 0;
97 dns->auth = 0;
98 dns->add = 0;
100 char *dns_ = (char *) dns;
102 /* dns queries */
103 // correct - dsl.cz : 03 64 73 6c 02 63 7a 00
104 // incorrect - dsl.cz : 06 64 73 6c 2e 63 7a 00
106 unsigned short dtype = (type == sizeof (net_ipv6) ? swap16 (0x1c) : swap16 (1));
107 unsigned short class = swap16 (1);
109 char *name_coded = (char *) kmalloc (sizeof (char) * (len + 2));
111 if (!name_coded)
112 return -1;
114 memcpy (name_coded+1, hostname, len);
115 name_coded[len+1] = '\0';
117 unsigned i = 1;
118 unsigned y = 0;
119 unsigned z = 0;
121 while (i < len+2) {
122 if (name_coded[i] == '.' || name_coded[i] == '\0') {
123 if (y == 0)
124 name_coded[0] = i-1;
125 else
126 name_coded[y] = z-1;
128 y = i;
129 z = 0;
132 i ++;
133 z ++;
136 /* setup dns query */
137 memcpy (dns_+12, name_coded, len+2);
138 memcpy (dns_+14+len, (char *) &dtype, 2);
139 memcpy (dns_+16+len, (char *) &class, 2);
141 kfree (name_coded);
143 int ret = send (sock, (char *) dns, sizeof (proto_dns_t)+len+6, 0);
145 /* it is not done */
146 char buf[512];
148 /* receive response from dns server */
149 ret = recv (sock, buf, 512, 0);
151 char target[32];
153 if (type >= 32)
154 return 0;
156 /* dns server send respond */
157 if (ret) {
158 proto_dns_t *dns_res = (proto_dns_t *) buf;
160 /* ipv4 and ipv6 capable */
161 if (type == 4 || type == 16) {
162 if (dns_res->flags == 0x8081) { /* all is ok, no error */
163 proto_dns_answer_t *dns_answer = (proto_dns_answer_t *) ((char *) buf + 18 + len);
164 unsigned next = 0;
166 /* walk trough whole answer list */
167 for (;;) {
168 next += sizeof (proto_dns_answer_t) + swap16 (dns_answer->dlen);
170 if (!dns_answer->type || !dns_answer->aclass) {
171 err ++;
172 break;
175 if (type == 16 && dns_answer->type == 0x1c00) { /* is it AAAA answer ? */
176 memcpy (&target, (void *) dns_answer + sizeof (proto_dns_answer_t), type);
178 dns_cache_add (hostname, len, (void *) target, type);
179 break;
180 } else if (type == 4 && dns_answer->type == 0x100) { /* is it A answer ? */
181 memcpy (&target, (void *) dns_answer + sizeof (proto_dns_answer_t), type);
183 dns_cache_add (hostname, len, (void *) target, type);
184 break;
185 } else
186 dns_answer = (proto_dns_answer_t *) ((char *) dns_answer + next);
188 } else
189 err ++;
190 } else
191 err ++;
194 sclose (sock);
196 kfree (dns);
198 memcpy (ip, target, type);
200 return err ? 0 : 1;
204 /* DNS Cache */
205 int dns_cache_add (char *hostname, unsigned char len, void *ip, unsigned char type)
207 if (!ip || !hostname)
208 return -1;
210 if (!type)
211 return 0;
213 dns_cache_t *cache;
214 for (cache = dns_cache_list.next; cache != &dns_cache_list; cache = cache->next) {
215 if (!strcmp (cache->hostname, hostname))
216 return 0;
219 /* alloc and init context */
220 cache = (dns_cache_t *) kmalloc (sizeof (dns_cache_t));
222 if (!cache)
223 return 0;
225 cache->type = type;
227 cache->ip = kmalloc (type);
229 if (!cache->ip) {
230 kfree (cache);
231 return 0;
234 memcpy (cache->ip, ip, type);
236 cache->len = len;
238 cache->hostname = (char *) kmalloc (sizeof (char) * (len + 1));
240 if (!cache->hostname) {
241 kfree (cache->ip);
242 kfree (cache);
243 return 0;
246 memcpy (cache->hostname, hostname, len);
247 cache->hostname[len] = '\0';
249 /* add into list */
250 cache->next = &dns_cache_list;
251 cache->prev = dns_cache_list.prev;
252 cache->prev->next = cache;
253 cache->next->prev = cache;
255 return 1;
258 int dns_cache_get (char *hostname, void *ip, unsigned char type)
260 if (!ip || !hostname)
261 return -1;
263 dns_cache_t *cache;
265 for (cache = dns_cache_list.next; cache != &dns_cache_list; cache = cache->next) {
266 if (cache->type == type)
267 if (!strcmp (cache->hostname, hostname)) {
268 memcpy (ip, cache->ip, cache->type);
269 return 1;
273 return 0;
276 unsigned init_net_proto_dns ()
278 dns_cache_list.next = &dns_cache_list;
279 dns_cache_list.prev = &dns_cache_list;
281 dns_trans = 1024;
283 dns_addr (DEFAULT_DNS_ADDRESS);
285 return 1;