Add very old versions (for history).
[opsoft_archive.git] / silentbob / silentbob-1.4.1 / gclib / src / dns_low.cxx
blobd0c2eff2d438e2e1dccb4c8718c4a0ae8ee152f8
1 /*
2 * (c) Oleg Puchinin 2006
3 * graycardinalster@gmail.com
5 */
7 #include <gclib.h>
8 #include <dns.h>
9 #include <gclib_c.h>
11 extern int dns_last_id;
13 char * __name2dns (char *name, int *len)
15 char * d_buf;
16 char * ptr;
17 DList * list;
18 __dlist_entry_t * one;
20 list = new DList;
21 Dsplit (name, ".", list);
22 d_buf = CNEW (char, 70);
23 ptr = d_buf;
25 one = list->get_head ();
26 while (one) {
27 buf_W8 (&ptr, strlen (one->data));
28 buf_WS (&ptr, one->data);
29 one = one->next;
32 buf_W8 (&ptr, 0);
33 delete list;
34 if (len)
35 *len = ptr - d_buf;
36 return d_buf;
39 inline char * __ddup (char * ptr, unsigned char ch)
41 char *S = CNEW (char, ch+2);
42 memcpy (S, ptr, ch);
43 S[ch] = '.';
44 S[ch+1] = '\0';
45 return S;
48 char * __dns_rd_chunk (DPBuf * p, char ** ptr, char * done)
50 char * ret;
51 unsigned char ch;
53 if (! p->check (*ptr, 1))
54 return NULL;
56 ch = buf_R8 (ptr);
57 if (! ch) {
58 *done = -1;
59 return NULL;
62 if (ch & 0xc0) {
63 ret = NULL;
64 --(*ptr);
65 } else {
66 if (! p->check (*ptr, ch))
67 return NULL;
68 ret = __ddup (*ptr, ch);
69 (*ptr) += ch;
72 return ret;
75 char * __dns_resp_domain (DPBuf * p, char * domain, char **domain_end)
77 unsigned char ch;
78 uint16_t offset;
79 char * ptr;
80 char buf[128];
81 char *S;
82 char done = 0;
83 bool d_try = true;
84 int n = 20;
86 if (! p || ! domain)
87 return NULL;
89 buf[0] = 0;
90 memset (buf, 0, 128);
91 ptr = domain;
93 drd_try:
94 while (true) {
95 S = __dns_rd_chunk (p, &ptr, &done);
96 if (done || ! S)
97 break;
99 strcat (buf, S);
100 DROP (S);
103 if ((domain_end != NULL) & d_try)
104 *domain_end = ptr;
106 if (! done) {
107 if (! p->check (ptr, 2))
108 return NULL;
110 if (! --n)
111 return NULL;
113 ch = buf_R8 (&ptr);
114 offset = (ch &= ~0xc0) << 8;
115 offset += buf_R8 (&ptr);
116 d_try = false;
117 ptr = &p->begin[offset];
118 goto drd_try;
121 if (domain_end && ! d_try)
122 *domain_end += 2;
124 chop (buf);
125 if (strlen (buf) > 0)
126 return strdup (buf);
127 else
128 return NULL;
131 char * make_dns_pkt (uint16_t id, uint16_t flags, uint16_t d_type,
132 uint16_t d_class, char * domain, int *len)
134 char * pkt;
135 char * ptr;
136 char * dns_name;
137 int dns_len;
138 struct dns_header hdr;
140 pkt = CNEW (char, 512);
141 ptr = pkt;
142 memset (&hdr, 0, sizeof (struct dns_header));
143 hdr.id = htons (id);
144 hdr.flags = htons (flags);
145 hdr.nr = htons (1);
146 buf_Wstruct (&ptr, &hdr);
148 dns_name = __name2dns (domain, &dns_len);
149 memcpy (ptr, dns_name, dns_len);
150 DROP (dns_name);
151 ptr += dns_len;
153 buf_W16 (&ptr, htons (d_type)); // "A"
154 buf_W16 (&ptr, htons (d_class)); // Internet
156 if (len)
157 *len = ptr-pkt;
159 return pkt;
162 DList * dns_resp_split (dns_header *hdr, char *pkt, int len)
164 dns_header *query_hdr;
165 dns_rheader *res_hdr = NULL;
166 dns_reply *reply = NULL;
167 char * d_end;
168 char * d_name;
169 uint16_t dr_type;
170 uint16_t dr_class;
171 DPBuf * p = NULL;
172 char * ptr;
173 DList * ret;
175 p = new DPBuf (pkt, len);
176 query_hdr = (dns_header *) p->rd (pkt, sizeof (dns_header));
177 if (! p->ok)
178 goto drs_out;
180 if (query_hdr->id != hdr->id)
181 goto drs_out;
183 ptr = &p->begin[sizeof (dns_header)];
184 d_name = __dns_resp_domain (p, ptr, &d_end);
185 if (d_name == NULL)
186 goto drs_out;
188 DROP (d_name);
189 ptr = d_end;
191 if (! p->check (ptr, 4))
192 goto drs_out;
194 dr_type = htons (buf_R16 (&ptr));
195 dr_class = htons (buf_R16 (&ptr));
197 reply = NULL;
198 ret = new DList;
200 while (true) {
201 reply = CNEW (dns_reply, 1);
202 memset (reply, 0, sizeof (dns_reply));
204 reply->domain = __dns_resp_domain (p, ptr, &d_end);
205 if (! reply->domain)
206 break;
208 ptr = d_end;
209 res_hdr = NULL;
211 if (! p->check (ptr, sizeof (struct dns_rheader)))
212 break;
214 res_hdr = buf_Rstruct (&ptr, dns_rheader);
215 reply->TTL = htonl (res_hdr->TTL);
216 reply->data_len = htons (res_hdr->len);
217 reply->dr_type = htons (res_hdr->dr_type);
218 reply->dr_class = htons (res_hdr->dr_class);
219 if (! p->check (ptr, reply->data_len))
220 goto drs_out;
222 reply->pkt_data_ptr = ptr;
223 reply->data = buf_RD (&ptr, reply->data_len);
224 ret->add_tail (LPCHAR (reply));
227 delete p;
228 return ret;
230 drs_out:
231 if (reply) {
232 DROP (reply->domain);
233 DROP (reply);
234 DROP (reply->data);
237 DROP (res_hdr);
238 delete p;
239 return NULL;
243 void dns_resp_clean (DList * list)
245 __dlist_entry_t *one;
246 dns_reply * reply;
248 if (! list)
249 return;
251 while ((one = list->get_head ()) && one) {
252 reply = (dns_reply *) one->data;
253 DROP (reply->domain);
254 DROP (reply->data);
255 DROP (reply);
256 list->rm (one);
258 delete list;
261 dns_reply * dns_scan (DList *list, uint16_t dr_type, uint16_t dr_class)
263 __dlist_entry_t * one;
264 dns_reply *Ret = NULL;
265 dns_reply *reply = NULL;
267 if (! list)
268 return NULL;
270 one = list->get_head ();
271 if (! one)
272 return NULL;
274 while (one) {
275 reply = (dns_reply *) one->data;
276 if (reply->dr_type == dr_type && reply->dr_class == dr_class) {
277 Ret = reply;
278 break;
280 one = one->next;
283 return Ret;