ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/reslib.c
Revision: 3852
Committed: Thu Jun 5 13:12:45 2014 UTC (11 years, 2 months ago) by michael
Content type: text/x-csrc
File size: 29615 byte(s)
Log Message:
- reslib.c: style corrections

File Contents

# Content
1 /*
2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
32 *
33 * Permission to use, copy, modify, and distribute this software for any
34 * purpose with or without fee is hereby granted, provided that the above
35 * copyright notice and this permission notice appear in all copies, and that
36 * the name of Digital Equipment Corporation not be used in advertising or
37 * publicity pertaining to distribution of the document or software without
38 * specific, written prior permission.
39 *
40 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
41 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
42 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
43 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 * SOFTWARE.
48 */
49
50 /*
51 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
52 *
53 * Permission to use, copy, modify, and distribute this software for any
54 * purpose with or without fee is hereby granted, provided that the above
55 * copyright notice and this permission notice appear in all copies.
56 *
57 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
58 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
60 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
61 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
62 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
63 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
64 * SOFTWARE.
65 */
66
67 /* Original copyright ISC as above.
68 * Code modified specifically for ircd use from the following orginal files
69 * in bind ...
70 *
71 * res_comp.c
72 * ns_name.c
73 * ns_netint.c
74 * res_init.c
75 *
76 * - Dianora
77 */
78
79 #include "stdinc.h"
80 #include "ircd_defs.h"
81 #include "res.h"
82 #include "reslib.h"
83 #include "irc_string.h"
84
85 #define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */
86 #define DNS_LABELTYPE_BITSTRING 0x41
87 #define MAXLINE 128
88
89 /* $Id$ */
90
91 struct irc_ssaddr irc_nsaddr_list[IRCD_MAXNS];
92 unsigned int irc_nscount = 0;
93
94 static const char digits[] = "0123456789";
95 static const char digitvalue[256] = {
96 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
97 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
98 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
99 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
100 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
101 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
102 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
103 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
104 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
105 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
106 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
107 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
108 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
109 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
110 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
111 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
112 };
113
114 static int labellen(const unsigned char *lp);
115 static int special(int ch);
116 static int printable(int ch);
117 static int irc_decode_bitstring(const unsigned char **cpp, char *dn, const char *eom);
118 static int irc_ns_name_compress(const char *src, unsigned char *dst, size_t dstsiz,
119 const unsigned char **dnptrs, const unsigned char **lastdnptr);
120 static int irc_dn_find(const unsigned char *, const unsigned char *, const unsigned char * const *,
121 const unsigned char * const *);
122 static int irc_encode_bitsring(const char **, const char *, unsigned char **, unsigned char **,
123 const unsigned char *);
124 static int irc_ns_name_uncompress(const unsigned char *, const unsigned char *,
125 const unsigned char *, char *, size_t);
126 static int irc_ns_name_unpack(const unsigned char *, const unsigned char *,
127 const unsigned char *, unsigned char *,
128 size_t);
129 static int irc_ns_name_ntop(const unsigned char *, char *, size_t);
130 static int irc_ns_name_skip(const unsigned char **, const unsigned char *);
131 static int mklower(int ch);
132
133
134 /* add_nameserver()
135 *
136 * input - either an IPV4 address in dotted quad
137 * or an IPV6 address in : format
138 * output - NONE
139 * side effects - entry in irc_nsaddr_list is filled in as needed
140 */
141 static void
142 add_nameserver(const char *arg)
143 {
144 struct addrinfo hints, *res;
145
146 /* Done max number of nameservers? */
147 if (irc_nscount >= IRCD_MAXNS)
148 return;
149
150 memset(&hints, 0, sizeof(hints));
151 hints.ai_family = PF_UNSPEC;
152 hints.ai_socktype = SOCK_DGRAM;
153 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
154
155 if (getaddrinfo(arg, "domain", &hints, &res))
156 return;
157
158 if (res == NULL)
159 return;
160
161 memcpy(&irc_nsaddr_list[irc_nscount].ss, res->ai_addr, res->ai_addrlen);
162 irc_nsaddr_list[irc_nscount++].ss_len = res->ai_addrlen;
163 freeaddrinfo(res);
164 }
165
166 /* parse_resvconf()
167 *
168 * inputs - NONE
169 * output - -1 if failure 0 if success
170 * side effects - fills in irc_nsaddr_list
171 */
172 static void
173 parse_resvconf(void)
174 {
175 char *p;
176 char *opt;
177 char *arg;
178 char input[MAXLINE];
179 FILE *file;
180
181 /* XXX "/etc/resolv.conf" should be from a define in config.h perhaps
182 * for cygwin support etc. this hardcodes it to unix for now -db
183 */
184 if ((file = fopen("/etc/resolv.conf", "r")) == NULL)
185 return;
186
187 while (fgets(input, sizeof(input), file))
188 {
189 /* blow away any newline */
190 if ((p = strpbrk(input, "\r\n")))
191 *p = '\0';
192
193 p = input;
194
195 /* skip until something thats not a space is seen */
196 while (IsSpace(*p))
197 ++p;
198
199 /* if at this point, have a '\0' then continue */
200 if (*p == '\0')
201 continue;
202
203 /* Ignore comment lines immediately */
204 if (*p == ';' || *p == '#')
205 continue;
206
207 /* skip until a space is found */
208 opt = p;
209 while (!IsSpace(*p) && *p)
210 ++p;
211
212 if (*p == '\0')
213 continue; /* no arguments?.. ignore this line */
214
215 /* blow away the space character */
216 *p++ = '\0';
217
218 /* skip these spaces that are before the argument */
219 while (IsSpace(*p))
220 ++p;
221
222 /* Now arg should be right where p is pointing */
223 arg = p;
224
225 if ((p = strpbrk(arg, " \t")))
226 *p = '\0'; /* take the first word */
227
228 if (!strcasecmp(opt, "nameserver"))
229 add_nameserver(arg);
230 }
231
232 fclose(file);
233 }
234
235 void
236 irc_res_init(void)
237 {
238 irc_nscount = 0;
239 memset(irc_nsaddr_list, 0, sizeof(irc_nsaddr_list));
240
241 parse_resvconf();
242
243 if (!irc_nscount)
244 add_nameserver("127.0.0.1");
245 }
246
247 /*
248 * Expand compressed domain name 'comp_dn' to full domain name.
249 * 'msg' is a pointer to the begining of the message,
250 * 'eomorig' points to the first location after the message,
251 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
252 * Return size of compressed name or -1 if there was an error.
253 */
254 int
255 irc_dn_expand(const unsigned char *msg, const unsigned char *eom,
256 const unsigned char *src, char *dst, int dstsiz)
257 {
258 int n = irc_ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
259
260 if (n > 0 && dst[0] == '.')
261 dst[0] = '\0';
262 return n;
263 }
264
265 /*
266 * irc_ns_name_uncompress(msg, eom, src, dst, dstsiz)
267 * Expand compressed domain name to presentation format.
268 * return:
269 * Number of bytes read out of `src', or -1 (with errno set).
270 * note:
271 * Root domain returns as "." not "".
272 */
273 static int
274 irc_ns_name_uncompress(const unsigned char *msg, const unsigned char *eom,
275 const unsigned char *src, char *dst, size_t dstsiz)
276 {
277 unsigned char tmp[NS_MAXCDNAME];
278 int n;
279
280 if ((n = irc_ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
281 return -1;
282 if (irc_ns_name_ntop(tmp, dst, dstsiz) == -1)
283 return -1;
284 return n;
285 }
286
287 /*
288 * irc_ns_name_unpack(msg, eom, src, dst, dstsiz)
289 * Unpack a domain name from a message, source may be compressed.
290 * return:
291 * -1 if it fails, or consumed octets if it succeeds.
292 */
293 static int
294 irc_ns_name_unpack(const unsigned char *msg, const unsigned char *eom,
295 const unsigned char *src, unsigned char *dst,
296 size_t dstsiz)
297 {
298 const unsigned char *srcp, *dstlim;
299 unsigned char *dstp;
300 int n, len, checked, l;
301
302 len = -1;
303 checked = 0;
304 dstp = dst;
305 srcp = src;
306 dstlim = dst + dstsiz;
307
308 if (srcp < msg || srcp >= eom)
309 {
310 errno = EMSGSIZE;
311 return -1;
312 }
313
314 /* Fetch next label in domain name. */
315 while ((n = *srcp++) != 0)
316 {
317 /* Check for indirection. */
318 switch (n & NS_CMPRSFLGS)
319 {
320 case 0:
321 case NS_TYPE_ELT:
322 /* Limit checks. */
323 if ((l = labellen(srcp - 1)) < 0)
324 {
325 errno = EMSGSIZE;
326 return -1;
327 }
328
329 if (dstp + l + 1 >= dstlim || srcp + l >= eom)
330 {
331 errno = EMSGSIZE;
332 return -1;
333 }
334
335 checked += l + 1;
336 *dstp++ = n;
337 memcpy(dstp, srcp, l);
338
339 dstp += l;
340 srcp += l;
341 break;
342
343 case NS_CMPRSFLGS:
344 if (srcp >= eom)
345 {
346 errno = EMSGSIZE;
347 return -1;
348 }
349
350 if (len < 0)
351 len = srcp - src + 1;
352 srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
353
354 if (srcp < msg || srcp >= eom)
355 {
356 /* Out of range. */
357 errno = EMSGSIZE;
358 return -1;
359 }
360
361 checked += 2;
362
363 /*
364 * Check for loops in the compressed name;
365 * if we've looked at the whole message,
366 * there must be a loop.
367 */
368 if (checked >= eom - msg)
369 {
370 errno = EMSGSIZE;
371 return -1;
372 }
373
374 break;
375
376 default:
377 errno = EMSGSIZE;
378 return -1; /* Flag error */
379 }
380 }
381
382 *dstp = '\0';
383
384 if (len < 0)
385 len = srcp - src;
386
387 return len;
388 }
389
390 /*
391 * irc_ns_name_ntop(src, dst, dstsiz)
392 * Convert an encoded domain name to printable ascii as per RFC1035.
393 * return:
394 * Number of bytes written to buffer, or -1 (with errno set)
395 * notes:
396 * The root is returned as "."
397 * All other domains are returned in non absolute form
398 */
399 static int
400 irc_ns_name_ntop(const unsigned char *src, char *dst, size_t dstsiz)
401 {
402 const unsigned char *cp;
403 char *dn, *eom;
404 unsigned char c;
405 unsigned int n;
406 int l;
407
408 cp = src;
409 dn = dst;
410 eom = dst + dstsiz;
411
412 while ((n = *cp++) != 0) {
413 if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
414 /* Some kind of compression pointer. */
415 errno = EMSGSIZE;
416 return (-1);
417 }
418 if (dn != dst) {
419 if (dn >= eom) {
420 errno = EMSGSIZE;
421 return (-1);
422 }
423 *dn++ = '.';
424 }
425 if ((l = labellen((cp - 1))) < 0) {
426 errno = EMSGSIZE; /* XXX */
427 return(-1);
428 }
429 if (dn + l >= eom) {
430 errno = EMSGSIZE;
431 return (-1);
432 }
433 if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
434 int m;
435
436 if (n != DNS_LABELTYPE_BITSTRING) {
437 /* XXX: labellen should reject this case */
438 errno = EINVAL;
439 return(-1);
440 }
441 if ((m = irc_decode_bitstring(&cp, dn, eom)) < 0)
442 {
443 errno = EMSGSIZE;
444 return(-1);
445 }
446 dn += m;
447 continue;
448 }
449 for ((void)NULL; l > 0; l--) {
450 c = *cp++;
451 if (special(c)) {
452 if (dn + 1 >= eom) {
453 errno = EMSGSIZE;
454 return (-1);
455 }
456 *dn++ = '\\';
457 *dn++ = (char)c;
458 } else if (!printable(c)) {
459 if (dn + 3 >= eom) {
460 errno = EMSGSIZE;
461 return (-1);
462 }
463 *dn++ = '\\';
464 *dn++ = digits[c / 100];
465 *dn++ = digits[(c % 100) / 10];
466 *dn++ = digits[c % 10];
467 } else {
468 if (dn >= eom) {
469 errno = EMSGSIZE;
470 return (-1);
471 }
472 *dn++ = (char)c;
473 }
474 }
475 }
476 if (dn == dst) {
477 if (dn >= eom) {
478 errno = EMSGSIZE;
479 return (-1);
480 }
481 *dn++ = '.';
482 }
483 if (dn >= eom) {
484 errno = EMSGSIZE;
485 return (-1);
486 }
487 *dn++ = '\0';
488 return (dn - dst);
489 } /*2*/
490
491 /*
492 * Skip over a compressed domain name. Return the size or -1.
493 */
494 int
495 irc_dn_skipname(const unsigned char *ptr, const unsigned char *eom)
496 {
497 const unsigned char *saveptr = ptr;
498
499 if (irc_ns_name_skip(&ptr, eom) == -1)
500 return -1;
501 return ptr - saveptr;
502 }
503
504 /*
505 * ns_name_skip(ptrptr, eom)
506 * Advance *ptrptr to skip over the compressed name it points at.
507 * return:
508 * 0 on success, -1 (with errno set) on failure.
509 */
510 static int
511 irc_ns_name_skip(const unsigned char **ptrptr, const unsigned char *eom)
512 {
513 const unsigned char *cp;
514 unsigned int n;
515 int l;
516
517 cp = *ptrptr;
518
519 while (cp < eom && (n = *cp++) != 0)
520 {
521 /* Check for indirection. */
522 switch (n & NS_CMPRSFLGS)
523 {
524 case 0: /* Normal case, n == len */
525 cp += n;
526 continue;
527 case NS_TYPE_ELT: /* EDNS0 extended label */
528 if ((l = labellen(cp - 1)) < 0)
529 {
530 errno = EMSGSIZE; /* XXX */
531 return -1;
532 }
533
534 cp += l;
535 continue;
536 case NS_CMPRSFLGS: /* Indirection */
537 cp++;
538 break;
539 default: /* Illegal type */
540 errno = EMSGSIZE;
541 return -1;
542 }
543
544 break;
545 }
546
547 if (cp > eom)
548 {
549 errno = EMSGSIZE;
550 return -1;
551 }
552
553 *ptrptr = cp;
554 return 0;
555 }
556
557 unsigned int
558 irc_ns_get16(const unsigned char *src)
559 {
560 unsigned int dst;
561
562 IRC_NS_GET16(dst, src);
563 return dst;
564 }
565
566 unsigned long
567 irc_ns_get32(const unsigned char *src)
568 {
569 unsigned long dst;
570
571 IRC_NS_GET32(dst, src);
572 return dst;
573 }
574
575 void
576 irc_ns_put16(unsigned int src, unsigned char *dst)
577 {
578 IRC_NS_PUT16(src, dst);
579 }
580
581 void
582 irc_ns_put32(unsigned long src, unsigned char *dst)
583 {
584 IRC_NS_PUT32(src, dst);
585 }
586
587 /* From ns_name.c */
588
589 /*
590 * special(ch)
591 * Thinking in noninternationalized USASCII (per the DNS spec),
592 * is this characted special ("in need of quoting") ?
593 * return:
594 * boolean.
595 */
596 static int
597 special(int ch)
598 {
599 switch (ch)
600 {
601 case 0x22: /* '"' */
602 case 0x2E: /* '.' */
603 case 0x3B: /* ';' */
604 case 0x5C: /* '\\' */
605 case 0x28: /* '(' */
606 case 0x29: /* ')' */
607 /* Special modifiers in zone files. */
608 case 0x40: /* '@' */
609 case 0x24: /* '$' */
610 return 1;
611 default:
612 return 0;
613 }
614 }
615
616 static int
617 labellen(const unsigned char *lp)
618 {
619 int bitlen;
620 unsigned char l = *lp;
621
622 if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS)
623 {
624 /* Should be avoided by the caller */
625 return -1;
626 }
627
628 if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT)
629 {
630 if (l == DNS_LABELTYPE_BITSTRING)
631 {
632 if ((bitlen = *(lp + 1)) == 0)
633 bitlen = 256;
634 return (bitlen + 7 ) / 8 + 1;
635 }
636
637 return -1; /* Unknwon ELT */
638 }
639
640 return l;
641 }
642
643
644 /*
645 * printable(ch)
646 * Thinking in noninternationalized USASCII (per the DNS spec),
647 * is this character visible and not a space when printed ?
648 * return:
649 * boolean.
650 */
651 static int
652 printable(int ch)
653 {
654 return ch > 0x20 && ch < 0x7f;
655 }
656
657 static int
658 irc_decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
659 {
660 const unsigned char *cp = *cpp;
661 char *beg = dn, tc;
662 int b, blen, plen;
663
664 if ((blen = (*cp & 0xff)) == 0)
665 blen = 256;
666 plen = (blen + 3) / 4;
667 plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
668 if (dn + plen >= eom)
669 return(-1);
670
671 cp++;
672 dn += sprintf(dn, "\\[x");
673 for (b = blen; b > 7; b -= 8, cp++)
674 dn += sprintf(dn, "%02x", *cp & 0xff);
675 if (b > 4) {
676 tc = *cp++;
677 dn += sprintf(dn, "%02x", tc & (0xff << (8 - b)));
678 } else if (b > 0) {
679 tc = *cp++;
680 dn += sprintf(dn, "%1x",
681 ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
682 }
683 dn += sprintf(dn, "/%d]", blen);
684
685 *cpp = cp;
686 return(dn - beg);
687 } /*2*/
688
689 /*
690 * irc_ns_name_pton(src, dst, dstsiz)
691 * Convert a ascii string into an encoded domain name as per RFC1035.
692 * return:
693 * -1 if it fails
694 * 1 if string was fully qualified
695 * 0 is string was not fully qualified
696 * notes:
697 * Enforces label and domain length limits.
698 */
699 static int
700 irc_ns_name_pton(const char *src, unsigned char *dst, size_t dstsiz)
701 {
702 unsigned char *label, *bp, *eom;
703 char *cp;
704 int c, n, escaped, e = 0;
705
706 escaped = 0;
707 bp = dst;
708 eom = dst + dstsiz;
709 label = bp++;
710
711
712 while ((c = *src++) != 0) {
713 if (escaped) {
714 if (c == '[') { /* start a bit string label */
715 if ((cp = strchr(src, ']')) == NULL) {
716 errno = EINVAL; /* ??? */
717 return(-1);
718 }
719 if ((e = irc_encode_bitsring(&src,
720 cp + 2,
721 &label,
722 &bp,
723 eom))
724 != 0) {
725 errno = e;
726 return(-1);
727 }
728 escaped = 0;
729 label = bp++;
730 if ((c = *src++) == 0)
731 goto done;
732 else if (c != '.') {
733 errno = EINVAL;
734 return(-1);
735 }
736 continue;
737 }
738 else if ((cp = strchr(digits, c)) != NULL) {
739 n = (cp - digits) * 100;
740 if ((c = *src++) == 0 ||
741 (cp = strchr(digits, c)) == NULL) {
742 errno = EMSGSIZE;
743 return (-1);
744 }
745 n += (cp - digits) * 10;
746 if ((c = *src++) == 0 ||
747 (cp = strchr(digits, c)) == NULL) {
748 errno = EMSGSIZE;
749 return (-1);
750 }
751 n += (cp - digits);
752 if (n > 255) {
753 errno = EMSGSIZE;
754 return (-1);
755 }
756 c = n;
757 }
758 escaped = 0;
759 } else if (c == '\\') {
760 escaped = 1;
761 continue;
762 } else if (c == '.') {
763 c = (bp - label - 1);
764 if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
765 errno = EMSGSIZE;
766 return (-1);
767 }
768 if (label >= eom) {
769 errno = EMSGSIZE;
770 return (-1);
771 }
772 *label = c;
773 /* Fully qualified ? */
774 if (*src == '\0') {
775 if (c != 0) {
776 if (bp >= eom) {
777 errno = EMSGSIZE;
778 return (-1);
779 }
780 *bp++ = '\0';
781 }
782 if ((bp - dst) > NS_MAXCDNAME) {
783 errno = EMSGSIZE;
784 return (-1);
785 }
786 return (1);
787 }
788 if (c == 0 || *src == '.') {
789 errno = EMSGSIZE;
790 return (-1);
791 }
792 label = bp++;
793 continue;
794 }
795 if (bp >= eom) {
796 errno = EMSGSIZE;
797 return (-1);
798 }
799 *bp++ = (unsigned char)c;
800 }
801 c = (bp - label - 1);
802 if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
803 errno = EMSGSIZE;
804 return (-1);
805 }
806 done:
807 if (label >= eom) {
808 errno = EMSGSIZE;
809 return (-1);
810 }
811 *label = c;
812 if (c != 0) {
813 if (bp >= eom) {
814 errno = EMSGSIZE;
815 return (-1);
816 }
817 *bp++ = 0;
818 }
819
820 if ((bp - dst) > NS_MAXCDNAME)
821 { /* src too big */
822 errno = EMSGSIZE;
823 return (-1);
824 }
825
826 return (0);
827 } /*2*/
828
829 /*
830 * irc_ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
831 * Pack domain name 'domain' into 'comp_dn'.
832 * return:
833 * Size of the compressed name, or -1.
834 * notes:
835 * 'dnptrs' is an array of pointers to previous compressed names.
836 * dnptrs[0] is a pointer to the beginning of the message. The array
837 * ends with NULL.
838 * 'lastdnptr' is a pointer to the end of the array pointed to
839 * by 'dnptrs'.
840 * Side effects:
841 * The list of pointers in dnptrs is updated for labels inserted into
842 * the message as we compress the name. If 'dnptr' is NULL, we don't
843 * try to compress names. If 'lastdnptr' is NULL, we don't update the
844 * list.
845 */
846 static int
847 irc_ns_name_pack(const unsigned char *src, unsigned char *dst, int dstsiz,
848 const unsigned char **dnptrs, const unsigned char **lastdnptr)
849 {
850 unsigned char *dstp;
851 const unsigned char **cpp, **lpp, *eob, *msg;
852 const unsigned char *srcp;
853 int n, l, first = 1;
854
855 srcp = src;
856 dstp = dst;
857 eob = dstp + dstsiz;
858 lpp = cpp = NULL;
859
860 if (dnptrs != NULL)
861 {
862 if ((msg = *dnptrs++))
863 {
864 for (cpp = dnptrs; *cpp != NULL; cpp++)
865 ;
866 lpp = cpp; /* End of list to search */
867 }
868 }
869 else
870 msg = NULL;
871
872 /* Make sure the domain we are about to add is legal */
873 l = 0;
874 do
875 {
876 int l0;
877
878 n = *srcp;
879 if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS)
880 {
881 errno = EMSGSIZE;
882 return -1;
883 }
884
885 if ((l0 = labellen(srcp)) < 0)
886 {
887 errno = EINVAL;
888 return -1;
889 }
890
891 l += l0 + 1;
892 if (l > NS_MAXCDNAME)
893 {
894 errno = EMSGSIZE;
895 return -1;
896 }
897
898 srcp += l0 + 1;
899 } while (n != 0);
900
901 /* From here on we need to reset compression pointer array on error */
902 srcp = src;
903 do
904 {
905 /* Look to see if we can use pointers. */
906 n = *srcp;
907
908 if (n != 0 && msg != NULL)
909 {
910 l = irc_dn_find(srcp, msg, (const unsigned char *const *)dnptrs,
911 (const unsigned char *const *)lpp);
912
913 if (l >= 0)
914 {
915 if (dstp + 1 >= eob)
916 goto cleanup;
917
918 *dstp++ = (l >> 8) | NS_CMPRSFLGS;
919 *dstp++ = l % 256;
920 return dstp - dst;
921 }
922
923 /* Not found, save it. */
924 if (lastdnptr != NULL && cpp < lastdnptr - 1 && (dstp - msg) < 0x4000 && first)
925 {
926 *cpp++ = dstp;
927 *cpp = NULL;
928 first = 0;
929 }
930 }
931
932 /* Copy label to buffer */
933 if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS)
934 goto cleanup; /* Should not happen. */
935
936 n = labellen(srcp);
937 if (dstp + 1 + n >= eob)
938 goto cleanup;
939
940 memcpy(dstp, srcp, n + 1);
941 srcp += n + 1;
942 dstp += n + 1;
943 } while (n != 0);
944
945 if (dstp > eob)
946 {
947 cleanup:
948 if (msg != NULL)
949 *lpp = NULL;
950 errno = EMSGSIZE;
951 return -1;
952 }
953
954 return dstp - dst;
955 }
956
957 static int
958 irc_ns_name_compress(const char *src, unsigned char *dst, size_t dstsiz,
959 const unsigned char **dnptrs, const unsigned char **lastdnptr)
960 {
961 unsigned char tmp[NS_MAXCDNAME];
962
963 if (irc_ns_name_pton(src, tmp, sizeof tmp) == -1)
964 return -1;
965 return irc_ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr);
966 }
967
968 static int
969 irc_encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
970 unsigned char **dst, const unsigned char *eom)
971 {
972 int afterslash = 0;
973 const char *cp = *bp;
974 unsigned char *tp;
975 char c;
976 const char *beg_blen;
977 char *end_blen = NULL;
978 int value = 0, count = 0, tbcount = 0, blen = 0;
979
980 beg_blen = end_blen = NULL;
981
982 /* a bitstring must contain at least 2 characters */
983 if (end - cp < 2)
984 return(EINVAL);
985
986 /* XXX: currently, only hex strings are supported */
987 if (*cp++ != 'x')
988 return(EINVAL);
989 if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */
990 return(EINVAL);
991
992 for (tp = *dst + 1; cp < end && tp < eom; cp++) {
993 switch((c = *cp)) {
994 case ']': /* end of the bitstring */
995 if (afterslash) {
996 if (beg_blen == NULL)
997 return(EINVAL);
998 blen = (int)strtol(beg_blen, &end_blen, 10);
999 if (*end_blen != ']')
1000 return(EINVAL);
1001 }
1002 if (count)
1003 *tp++ = ((value << 4) & 0xff);
1004 cp++; /* skip ']' */
1005 goto done;
1006 case '/':
1007 afterslash = 1;
1008 break;
1009 default:
1010 if (afterslash) {
1011 if (!isdigit(c&0xff))
1012 return(EINVAL);
1013 if (beg_blen == NULL) {
1014
1015 if (c == '0') {
1016 /* blen never begings with 0 */
1017 return(EINVAL);
1018 }
1019 beg_blen = cp;
1020 }
1021 } else {
1022 if (!isxdigit(c&0xff))
1023 return(EINVAL);
1024 value <<= 4;
1025 value += digitvalue[(int)c];
1026 count += 4;
1027 tbcount += 4;
1028 if (tbcount > 256)
1029 return(EINVAL);
1030 if (count == 8) {
1031 *tp++ = value;
1032 count = 0;
1033 }
1034 }
1035 break;
1036 }
1037 }
1038 done:
1039 if (cp >= end || tp >= eom)
1040 return(EMSGSIZE);
1041
1042 /*
1043 * bit length validation:
1044 * If a <length> is present, the number of digits in the <bit-data>
1045 * MUST be just sufficient to contain the number of bits specified
1046 * by the <length>. If there are insignificant bits in a final
1047 * hexadecimal or octal digit, they MUST be zero.
1048 * RFC 2673, Section 3.2.
1049 */
1050 if (blen > 0) {
1051 int traillen;
1052
1053 if (((blen + 3) & ~3) != tbcount)
1054 return(EINVAL);
1055 traillen = tbcount - blen; /* between 0 and 3 */
1056 if (((value << (8 - traillen)) & 0xff) != 0)
1057 return(EINVAL);
1058 }
1059 else
1060 blen = tbcount;
1061 if (blen == 256)
1062 blen = 0;
1063
1064 /* encode the type and the significant bit fields */
1065 **labelp = DNS_LABELTYPE_BITSTRING;
1066 **dst = blen;
1067
1068 *bp = cp;
1069 *dst = tp;
1070
1071 return(0);
1072 } /*2*/
1073
1074 /*
1075 * dn_find(domain, msg, dnptrs, lastdnptr)
1076 * Search for the counted-label name in an array of compressed names.
1077 * return:
1078 * offset from msg if found, or -1.
1079 * notes:
1080 * dnptrs is the pointer to the first name on the list,
1081 * not the pointer to the start of the message.
1082 */
1083 static int
1084 irc_dn_find(const unsigned char *domain, const unsigned char *msg,
1085 const unsigned char * const *dnptrs,
1086 const unsigned char * const *lastdnptr)
1087 {
1088 const unsigned char *dn, *cp, *sp;
1089 const unsigned char * const *cpp;
1090 unsigned int n;
1091
1092 for (cpp = dnptrs; cpp < lastdnptr; cpp++)
1093 {
1094 sp = *cpp;
1095 /*
1096 * terminate search on:
1097 * root label
1098 * compression pointer
1099 * unusable offset
1100 */
1101 while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
1102 (sp - msg) < 0x4000) {
1103 dn = domain;
1104 cp = sp;
1105 while ((n = *cp++) != 0) {
1106 /*
1107 * check for indirection
1108 */
1109 switch (n & NS_CMPRSFLGS) {
1110 case 0: /* normal case, n == len */
1111 n = labellen(cp - 1); /* XXX */
1112
1113 if (n != *dn++)
1114 goto next;
1115
1116 for ((void)NULL; n > 0; n--)
1117 if (mklower(*dn++) !=
1118 mklower(*cp++))
1119 goto next;
1120 /* Is next root for both ? */
1121 if (*dn == '\0' && *cp == '\0')
1122 return (sp - msg);
1123 if (*dn)
1124 continue;
1125 goto next;
1126 case NS_CMPRSFLGS: /* indirection */
1127 cp = msg + (((n & 0x3f) << 8) | *cp);
1128 break;
1129
1130 default: /* illegal type */
1131 errno = EMSGSIZE;
1132 return (-1);
1133 }
1134 }
1135 next: ;
1136 sp += *sp + 1;
1137 }
1138 }
1139 errno = ENOENT;
1140 return (-1);
1141 } /*2*/
1142
1143 /*
1144 * * Thinking in noninternationalized USASCII (per the DNS spec),
1145 * * convert this character to lower case if it's upper case.
1146 * */
1147 static int
1148 mklower(int ch)
1149 {
1150 if (ch >= 0x41 && ch <= 0x5A)
1151 return(ch + 0x20);
1152
1153 return(ch);
1154 } /*2*/
1155
1156 /* From resolv/mkquery.c */
1157
1158 /*
1159 * Form all types of queries.
1160 * Returns the size of the result or -1.
1161 */
1162 int
1163 irc_res_mkquery(
1164 const char *dname, /* domain name */
1165 int class, int type, /* class and type of query */
1166 unsigned char *buf, /* buffer to put query */
1167 int buflen) /* size of buffer */
1168 {
1169 HEADER *hp;
1170 unsigned char *cp;
1171 int n;
1172 const unsigned char *dnptrs[20], **dpp, **lastdnptr;
1173
1174 /*
1175 * Initialize header fields.
1176 */
1177 if ((buf == NULL) || (buflen < HFIXEDSZ))
1178 return (-1);
1179 memset(buf, 0, HFIXEDSZ);
1180 hp = (HEADER *) buf;
1181
1182 hp->id = 0;
1183 hp->opcode = QUERY;
1184 hp->rd = 1; /* recurse */
1185 hp->rcode = NO_ERRORS;
1186 cp = buf + HFIXEDSZ;
1187 buflen -= HFIXEDSZ;
1188 dpp = dnptrs;
1189 *dpp++ = buf;
1190 *dpp++ = NULL;
1191 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
1192
1193 if ((buflen -= QFIXEDSZ) < 0)
1194 return (-1);
1195 if ((n = irc_ns_name_compress(dname, cp, buflen, dnptrs,
1196 lastdnptr)) < 0)
1197 return (-1);
1198
1199 cp += n;
1200 buflen -= n;
1201 IRC_NS_PUT16(type, cp);
1202 IRC_NS_PUT16(class, cp);
1203 hp->qdcount = htons(1);
1204
1205 return (cp - buf);
1206 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision