ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/irc_reslib.c
Revision: 993
Committed: Thu Aug 20 10:44:18 2009 UTC (16 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/irc_reslib.c
File size: 29854 byte(s)
Log Message:
- update irc_reslib.c to latest libbind 6.0

File Contents

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

Properties

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