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/>.
28 #include <net/packet.h>
30 #include <net/socket.h>
32 dns_cache_t dns_cache_list
;
36 unsigned short dns_trans
= NULL
;
38 #define DEFAULT_DNS_ADDRESS NET_IPV4_TO_ADDR (192,168,0,1)
41 int dns_cache_add (char *hostname
, unsigned char len
, void *ip
, unsigned char type
);
44 unsigned dns_addr (net_ipv4 dns
)
51 net_ipv4
dns_addr_get ()
56 int dns_send_request (char *hostname
, void *ip
, unsigned char type
)
68 if ((sock
= socket (AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1) {
69 DPRINT (DBG_NET
| DBG_DNS
, "Cant create socket");
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");
85 unsigned short len
= strlen (hostname
);
87 proto_dns_t
*dns
= (proto_dns_t
*) kmalloc (sizeof (proto_dns_t
)+len
+7);
93 dns
->trans
= swap16 (dns_trans
++);
94 dns
->flags
= swap16 (0x0100);
95 dns
->question
= swap16 (1);
100 char *dns_
= (char *) dns
;
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));
114 memcpy (name_coded
+1, hostname
, len
);
115 name_coded
[len
+1] = '\0';
122 if (name_coded
[i
] == '.' || name_coded
[i
] == '\0') {
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);
143 int ret
= send (sock
, (char *) dns
, sizeof (proto_dns_t
)+len
+6, 0);
148 /* receive response from dns server */
149 ret
= recv (sock
, buf
, 512, 0);
156 /* dns server send respond */
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
);
166 /* walk trough whole answer list */
168 next
+= sizeof (proto_dns_answer_t
) + swap16 (dns_answer
->dlen
);
170 if (!dns_answer
->type
|| !dns_answer
->aclass
) {
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
);
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
);
186 dns_answer
= (proto_dns_answer_t
*) ((char *) dns_answer
+ next
);
198 memcpy (ip
, target
, type
);
205 int dns_cache_add (char *hostname
, unsigned char len
, void *ip
, unsigned char type
)
207 if (!ip
|| !hostname
)
214 for (cache
= dns_cache_list
.next
; cache
!= &dns_cache_list
; cache
= cache
->next
) {
215 if (!strcmp (cache
->hostname
, hostname
))
219 /* alloc and init context */
220 cache
= (dns_cache_t
*) kmalloc (sizeof (dns_cache_t
));
227 cache
->ip
= kmalloc (type
);
234 memcpy (cache
->ip
, ip
, type
);
238 cache
->hostname
= (char *) kmalloc (sizeof (char) * (len
+ 1));
240 if (!cache
->hostname
) {
246 memcpy (cache
->hostname
, hostname
, len
);
247 cache
->hostname
[len
] = '\0';
250 cache
->next
= &dns_cache_list
;
251 cache
->prev
= dns_cache_list
.prev
;
252 cache
->prev
->next
= cache
;
253 cache
->next
->prev
= cache
;
258 int dns_cache_get (char *hostname
, void *ip
, unsigned char type
)
260 if (!ip
|| !hostname
)
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
);
276 unsigned init_net_proto_dns ()
278 dns_cache_list
.next
= &dns_cache_list
;
279 dns_cache_list
.prev
= &dns_cache_list
;
283 dns_addr (DEFAULT_DNS_ADDRESS
);