[packages] mtr: update to 0.80
[openwrt/svn-archive/archive.git] / net / mtr / patches / 501-dns.patch
1 --- a/dns.c
2 +++ b/dns.c
3 @@ -880,6 +880,507 @@ void restell(char *s)
4 fputs("\r",stderr);
5 }
6
7 +#ifdef __UCLIBC__
8 +
9 +static const char digits[] = "0123456789";
10 +#define __set_errno(e) (errno = (e))
11 +
12 +#define NS_PUT16(s, cp) do { \
13 + register u_int16_t t_s = (u_int16_t)(s); \
14 + register u_char *t_cp = (u_char *)(cp); \
15 + *t_cp++ = t_s >> 8; \
16 + *t_cp = t_s; \
17 + (cp) += NS_INT16SZ; \
18 +} while (0)
19 +
20 +
21 +
22 +#define NS_PUT32(l, cp) do { \
23 + register u_int32_t t_l = (u_int32_t)(l); \
24 + register u_char *t_cp = (u_char *)(cp); \
25 + *t_cp++ = t_l >> 24; \
26 + *t_cp++ = t_l >> 16; \
27 + *t_cp++ = t_l >> 8; \
28 + *t_cp = t_l; \
29 + (cp) += NS_INT32SZ; \
30 +} while (0)
31 +
32 +
33 +void
34 +ns_put16(u_int src, u_char *dst) {
35 + NS_PUT16(src, dst);
36 +}
37 +
38 +void
39 +ns_put32(u_long src, u_char *dst) {
40 + NS_PUT32(src, dst);
41 +}
42 +
43 +void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
44 +void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
45 +
46 +int
47 +mklower(int ch) {
48 + if (ch >= 0x41 && ch <= 0x5A)
49 + return (ch + 0x20);
50 + return (ch);
51 +}
52 +
53 +
54 +static int
55 +dn_find(const u_char *domain, const u_char *msg,
56 + const u_char * const *dnptrs,
57 + const u_char * const *lastdnptr)
58 +{
59 + const u_char *dn, *cp, *sp;
60 + const u_char * const *cpp;
61 + u_int n;
62 +
63 + for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
64 + sp = *cpp;
65 + /*
66 + * terminate search on:
67 + * root label
68 + * compression pointer
69 + * unusable offset
70 + */
71 + while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
72 + (sp - msg) < 0x4000) {
73 + dn = domain;
74 + cp = sp;
75 + while ((n = *cp++) != 0) {
76 + /*
77 + * check for indirection
78 + */
79 + switch (n & NS_CMPRSFLGS) {
80 + case 0: /* normal case, n == len */
81 + if (n != *dn++)
82 + goto next;
83 + for ((void)NULL; n > 0; n--)
84 + if (mklower(*dn++) !=
85 + mklower(*cp++))
86 + goto next;
87 + /* Is next root for both ? */
88 + if (*dn == '\0' && *cp == '\0')
89 + return (sp - msg);
90 + if (*dn)
91 + continue;
92 + goto next;
93 +
94 + case NS_CMPRSFLGS: /* indirection */
95 + cp = msg + (((n & 0x3f) << 8) | *cp);
96 + break;
97 +
98 + default: /* illegal type */
99 + __set_errno (EMSGSIZE);
100 + return (-1);
101 + }
102 + }
103 + next:
104 + sp += *sp + 1;
105 + }
106 + }
107 + __set_errno (ENOENT);
108 + return (-1);
109 +}
110 +
111 +
112 +int
113 +ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
114 + const u_char **dnptrs, const u_char **lastdnptr)
115 +{
116 + u_char *dstp;
117 + const u_char **cpp, **lpp, *eob, *msg;
118 + const u_char *srcp;
119 + int n, l, first = 1;
120 +
121 + srcp = src;
122 + dstp = dst;
123 + eob = dstp + dstsiz;
124 + lpp = cpp = NULL;
125 + if (dnptrs != NULL) {
126 + if ((msg = *dnptrs++) != NULL) {
127 + for (cpp = dnptrs; *cpp != NULL; cpp++)
128 + (void)NULL;
129 + lpp = cpp; /* end of list to search */
130 + }
131 + } else
132 + msg = NULL;
133 +
134 + /* make sure the domain we are about to add is legal */
135 + l = 0;
136 + do {
137 + n = *srcp;
138 + if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) {
139 + __set_errno (EMSGSIZE);
140 + return (-1);
141 + }
142 + if (n == 0x41)
143 + n = *++srcp / 8;
144 + l += n + 1;
145 + if (l > MAXCDNAME) {
146 + __set_errno (EMSGSIZE);
147 + return (-1);
148 + }
149 + srcp += n + 1;
150 + } while (n != 0);
151 +
152 + /* from here on we need to reset compression pointer array on error */
153 + srcp = src;
154 + do {
155 + /* Look to see if we can use pointers. */
156 + n = *srcp;
157 + if (n != 0 && n != 0x41 && msg != NULL) {
158 + l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
159 + (const u_char * const *)lpp);
160 + if (l >= 0) {
161 + if (dstp + 1 >= eob) {
162 + goto cleanup;
163 + }
164 + *dstp++ = (l >> 8) | NS_CMPRSFLGS;
165 + *dstp++ = l % 256;
166 + return (dstp - dst);
167 + }
168 + /* Not found, save it. */
169 + if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
170 + (dstp - msg) < 0x4000 && first) {
171 + *cpp++ = dstp;
172 + *cpp = NULL;
173 + first = 0;
174 + }
175 + }
176 + /* copy label to buffer */
177 + if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) { /* Should not happen. */
178 + goto cleanup;
179 + }
180 + if (n == 0x41) {
181 + n = *++srcp / 8;
182 + if (dstp + 1 >= eob)
183 + goto cleanup;
184 + *dstp++ = 0x41;
185 + }
186 + if (dstp + 1 + n >= eob) {
187 + goto cleanup;
188 + }
189 + memcpy(dstp, srcp, n + 1);
190 + srcp += n + 1;
191 + dstp += n + 1;
192 + } while (n != 0);
193 +
194 + if (dstp > eob) {
195 +cleanup:
196 + if (msg != NULL)
197 + *lpp = NULL;
198 + __set_errno (EMSGSIZE);
199 + return (-1);
200 + }
201 + return (dstp - dst);
202 +}
203 +
204 +
205 +int
206 +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
207 + u_char *label, *bp, *eom;
208 + int c, n, escaped;
209 + char *cp;
210 +
211 + escaped = 0;
212 + bp = dst;
213 + eom = dst + dstsiz;
214 + label = bp++;
215 +
216 + while ((c = *src++) != 0) {
217 + if (escaped) {
218 + if ((cp = strchr(digits, c)) != NULL) {
219 + n = (cp - digits) * 100;
220 + if ((c = *src++) == 0 ||
221 + (cp = strchr(digits, c)) == NULL) {
222 + __set_errno (EMSGSIZE);
223 + return (-1);
224 + }
225 + n += (cp - digits) * 10;
226 + if ((c = *src++) == 0 ||
227 + (cp = strchr(digits, c)) == NULL) {
228 + __set_errno (EMSGSIZE);
229 + return (-1);
230 + }
231 + n += (cp - digits);
232 + if (n > 255) {
233 + __set_errno (EMSGSIZE);
234 + return (-1);
235 + }
236 + c = n;
237 + } else if (c == '[' && label == bp - 1 && *src == 'x') {
238 + /* Theoretically we would have to handle \[o
239 + as well but we do not since we do not need
240 + it internally. */
241 + *label = 0x41;
242 + label = bp++;
243 + ++src;
244 + while (isxdigit (*src)) {
245 + n = *src > '9' ? *src - 'a' + 10 : *src - '0';
246 + ++src;
247 + if (! isxdigit(*src)) {
248 + __set_errno (EMSGSIZE);
249 + return (-1);
250 + }
251 + n <<= 4;
252 + n += *src > '9' ? *src - 'a' + 10 : *src - '0';
253 + if (bp + 1 >= eom) {
254 + __set_errno (EMSGSIZE);
255 + return (-1);
256 + }
257 + *bp++ = n;
258 + ++src;
259 + }
260 + *label = (bp - label - 1) * 8;
261 + if (*src++ != ']' || *src++ != '.') {
262 + __set_errno (EMSGSIZE);
263 + return (-1);
264 + }
265 + escaped = 0;
266 + label = bp++;
267 + if (bp >= eom) {
268 + __set_errno (EMSGSIZE);
269 + return (-1);
270 + }
271 + continue;
272 + }
273 + escaped = 0;
274 + } else if (c == '\\') {
275 + escaped = 1;
276 + continue;
277 + } else if (c == '.') {
278 + c = (bp - label - 1);
279 + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
280 + __set_errno (EMSGSIZE);
281 + return (-1);
282 + }
283 + if (label >= eom) {
284 + __set_errno (EMSGSIZE);
285 + return (-1);
286 + }
287 + *label = c;
288 + /* Fully qualified ? */
289 + if (*src == '\0') {
290 + if (c != 0) {
291 + if (bp >= eom) {
292 + __set_errno (EMSGSIZE);
293 + return (-1);
294 + }
295 + *bp++ = '\0';
296 + }
297 + if ((bp - dst) > MAXCDNAME) {
298 + __set_errno (EMSGSIZE);
299 + return (-1);
300 + }
301 + return (1);
302 + }
303 + if (c == 0 || *src == '.') {
304 + __set_errno (EMSGSIZE);
305 + return (-1);
306 + }
307 + label = bp++;
308 + continue;
309 + }
310 + if (bp >= eom) {
311 + __set_errno (EMSGSIZE);
312 + return (-1);
313 + }
314 + *bp++ = (u_char)c;
315 + }
316 + c = (bp - label - 1);
317 + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
318 + __set_errno (EMSGSIZE);
319 + return (-1);
320 + }
321 + if (label >= eom) {
322 + __set_errno (EMSGSIZE);
323 + return (-1);
324 + }
325 + *label = c;
326 + if (c != 0) {
327 + if (bp >= eom) {
328 + __set_errno (EMSGSIZE);
329 + return (-1);
330 + }
331 + *bp++ = 0;
332 + }
333 + if ((bp - dst) > MAXCDNAME) { /* src too big */
334 + __set_errno (EMSGSIZE);
335 + return (-1);
336 + }
337 + return (0);
338 +}
339 +
340 +
341 +
342 +int
343 +ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
344 + const u_char **dnptrs, const u_char **lastdnptr)
345 +{
346 + u_char tmp[NS_MAXCDNAME];
347 +
348 + if (ns_name_pton(src, tmp, sizeof tmp) == -1)
349 + return (-1);
350 + return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
351 +}
352 +
353 +
354 +int
355 +dn_comp(const char *src, u_char *dst, int dstsiz,
356 + u_char **dnptrs, u_char **lastdnptr)
357 +{
358 + return (ns_name_compress(src, dst, (size_t)dstsiz,
359 + (const u_char **)dnptrs,
360 + (const u_char **)lastdnptr));
361 +}
362 +
363 +
364 +
365 +
366 +int
367 +res_nmkquery(res_state statp,
368 + int op, /* opcode of query */
369 + const char *dname, /* domain name */
370 + int class, int type, /* class and type of query */
371 + const u_char *data, /* resource record data */
372 + int datalen, /* length of data */
373 + const u_char *newrr_in, /* new rr for modify or append */
374 + u_char *buf, /* buffer to put query */
375 + int buflen) /* size of buffer */
376 +{
377 + register HEADER *hp;
378 + register u_char *cp;
379 + register int n;
380 + u_char *dnptrs[20], **dpp, **lastdnptr;
381 +
382 +#ifdef DEBUG
383 + if (statp->options & RES_DEBUG)
384 + printf(";; res_nmkquery(%s, %s, %s, %s)\n",
385 + _res_opcodes[op], dname, p_class(class), p_type(type));
386 +#endif
387 + /*
388 + * Initialize header fields.
389 + */
390 + if ((buf == NULL) || (buflen < HFIXEDSZ))
391 + return (-1);
392 + memset(buf, 0, HFIXEDSZ);
393 + hp = (HEADER *) buf;
394 + /* We randomize the IDs every time. The old code just
395 + incremented by one after the initial randomization which
396 + still predictable if the application does multiple
397 + requests. */
398 +#if 0
399 + hp->id = htons(++statp->id);
400 +#else
401 + hp->id = htons(statp->id);
402 + int randombits;
403 + do
404 + {
405 +#ifdef RANDOM_BITS
406 + RANDOM_BITS (randombits);
407 +#else
408 + struct timeval tv;
409 + gettimeofday (&tv, NULL);
410 + randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
411 +#endif
412 + }
413 + while ((randombits & 0xffff) == 0);
414 + statp->id = (statp->id + randombits) & 0xffff;
415 +#endif
416 + hp->opcode = op;
417 + hp->rd = (statp->options & RES_RECURSE) != 0;
418 + hp->rcode = NOERROR;
419 + cp = buf + HFIXEDSZ;
420 + buflen -= HFIXEDSZ;
421 + dpp = dnptrs;
422 + *dpp++ = buf;
423 + *dpp++ = NULL;
424 + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
425 + /*
426 + * perform opcode specific processing
427 + */
428 + switch (op) {
429 + case QUERY: /*FALLTHROUGH*/
430 + case NS_NOTIFY_OP:
431 + if ((buflen -= QFIXEDSZ) < 0)
432 + return (-1);
433 + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
434 + return (-1);
435 + cp += n;
436 + buflen -= n;
437 + __putshort(type, cp);
438 + cp += INT16SZ;
439 + __putshort(class, cp);
440 + cp += INT16SZ;
441 + hp->qdcount = htons(1);
442 + if (op == QUERY || data == NULL)
443 + break;
444 + /*
445 + * Make an additional record for completion domain.
446 + */
447 + buflen -= RRFIXEDSZ;
448 + n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
449 + if (n < 0)
450 + return (-1);
451 + cp += n;
452 + buflen -= n;
453 + __putshort(T_NULL, cp);
454 + cp += INT16SZ;
455 + __putshort(class, cp);
456 + cp += INT16SZ;
457 + __putlong(0, cp);
458 + cp += INT32SZ;
459 + __putshort(0, cp);
460 + cp += INT16SZ;
461 + hp->arcount = htons(1);
462 + break;
463 +
464 + case IQUERY:
465 + /*
466 + * Initialize answer section
467 + */
468 + if (buflen < 1 + RRFIXEDSZ + datalen)
469 + return (-1);
470 + *cp++ = '\0'; /* no domain name */
471 + __putshort(type, cp);
472 + cp += INT16SZ;
473 + __putshort(class, cp);
474 + cp += INT16SZ;
475 + __putlong(0, cp);
476 + cp += INT32SZ;
477 + __putshort(datalen, cp);
478 + cp += INT16SZ;
479 + if (datalen) {
480 + memcpy(cp, data, datalen);
481 + cp += datalen;
482 + }
483 + hp->ancount = htons(1);
484 + break;
485 +
486 + default:
487 + return (-1);
488 + }
489 + return (cp - buf);
490 +}
491 +
492 +int
493 +res_mkquery(int op, /* opcode of query */
494 + const char *dname, /* domain name */
495 + int class, int type, /* class and type of query */
496 + const u_char *data, /* resource record data */
497 + int datalen, /* length of data */
498 + const u_char *newrr_in, /* new rr for modify or append */
499 + u_char *buf, /* buffer to put query */
500 + int buflen) /* size of buffer */
501 +{
502 + return (res_nmkquery(&_res, op, dname, class, type,
503 + data, datalen,
504 + newrr_in, buf, buflen));
505 +}
506 +
507 +#endif
508
509 void dorequest(char *s,int type,word id)
510 {