ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/reslib.c
Revision: 912
Committed: Wed Nov 7 22:47:44 2007 UTC (17 years, 9 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/irc_reslib.c
File size: 30131 byte(s)
Log Message:
- Implemented libtool-ltdl. Only shared modules are supported currently
- Several build fixes and cleanups. ircd now builds and runs without any problems
- Added back all files to SVN that are needed to built the daemon
  I really don't want to force other people that want to test the snapshots
  or svn versions to install yyacc, lex, automake, autoconf and libtool...
  No problem having required files in svn
- Removed some automake maintainer stuff which is kinda useless for us

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     static int irc_decode_bitstring(const char **cpp, char *dn, const char *eom);
128     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     const char *);
134     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     static int irc_ns_name_ntop(const char *, char *, size_t);
140     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     }
271    
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     if (irc_ns_name_ntop((char*)tmp, dst, dstsiz) == -1)
290     return(-1);
291     return(n);
292     }
293     /*
294     * irc_ns_name_unpack(msg, eom, src, dst, dstsiz)
295     * Unpack a domain name from a message, source may be compressed.
296     * return:
297     * -1 if it fails, or consumed octets if it succeeds.
298     */
299     static int
300     irc_ns_name_unpack(const unsigned char *msg, const unsigned char *eom,
301     const unsigned char *src, unsigned char *dst,
302     size_t dstsiz)
303     {
304     const unsigned char *srcp, *dstlim;
305     unsigned char *dstp;
306     int n, len, checked, l;
307    
308     len = -1;
309     checked = 0;
310     dstp = dst;
311     srcp = src;
312     dstlim = dst + dstsiz;
313     if (srcp < msg || srcp >= eom) {
314     errno = EMSGSIZE;
315     return (-1);
316     }
317     /* Fetch next label in domain name. */
318     while ((n = *srcp++) != 0) {
319     /* Check for indirection. */
320     switch (n & NS_CMPRSFLGS) {
321     case 0:
322     case NS_TYPE_ELT:
323     /* Limit checks. */
324     if ((l = labellen(srcp - 1)) < 0) {
325     errno = EMSGSIZE;
326     return(-1);
327     }
328     if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
329     errno = EMSGSIZE;
330     return (-1);
331     }
332     checked += l + 1;
333     *dstp++ = n;
334     memcpy(dstp, srcp, l);
335     dstp += l;
336     srcp += l;
337     break;
338    
339     case NS_CMPRSFLGS:
340     if (srcp >= eom) {
341     errno = EMSGSIZE;
342     return (-1);
343     }
344     if (len < 0)
345     len = srcp - src + 1;
346     srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
347     if (srcp < msg || srcp >= eom) { /* Out of range. */
348     errno = EMSGSIZE;
349     return (-1);
350     }
351     checked += 2;
352     /*
353     * Check for loops in the compressed name;
354     * if we've looked at the whole message,
355     * there must be a loop.
356     */
357     if (checked >= eom - msg) {
358     errno = EMSGSIZE;
359     return (-1);
360     }
361     break;
362    
363     default:
364     errno = EMSGSIZE;
365     return (-1); /* flag error */
366     }
367     }
368     *dstp = '\0';
369     if (len < 0)
370     len = srcp - src;
371     return (len);
372     }
373    
374     /*
375     * irc_ns_name_ntop(src, dst, dstsiz)
376     * Convert an encoded domain name to printable ascii as per RFC1035.
377     * return:
378     * Number of bytes written to buffer, or -1 (with errno set)
379     * notes:
380     * The root is returned as "."
381     * All other domains are returned in non absolute form
382     */
383     static int
384     irc_ns_name_ntop(const char *src, char *dst, size_t dstsiz)
385     {
386     const char *cp;
387     char *dn, *eom;
388     unsigned char c;
389     unsigned int n;
390     int l;
391    
392     cp = src;
393     dn = dst;
394     eom = dst + dstsiz;
395    
396     while ((n = *cp++) != 0) {
397     if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
398     /* Some kind of compression pointer. */
399     errno = EMSGSIZE;
400     return (-1);
401     }
402     if (dn != dst) {
403     if (dn >= eom) {
404     errno = EMSGSIZE;
405     return (-1);
406     }
407     *dn++ = '.';
408     }
409     if ((l = labellen((unsigned char*)(cp - 1))) < 0) {
410     errno = EMSGSIZE; /* XXX */
411     return(-1);
412     }
413     if (dn + l >= eom) {
414     errno = EMSGSIZE;
415     return (-1);
416     }
417     if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
418     int m;
419    
420     if (n != DNS_LABELTYPE_BITSTRING) {
421     /* XXX: labellen should reject this case */
422     errno = EINVAL;
423     return(-1);
424     }
425     if ((m = irc_decode_bitstring(&cp, dn, eom)) < 0)
426     {
427     errno = EMSGSIZE;
428     return(-1);
429     }
430     dn += m;
431     continue;
432     }
433     for ((void)NULL; l > 0; l--) {
434     c = *cp++;
435     if (special(c)) {
436     if (dn + 1 >= eom) {
437     errno = EMSGSIZE;
438     return (-1);
439     }
440     *dn++ = '\\';
441     *dn++ = (char)c;
442     } else if (!printable(c)) {
443     if (dn + 3 >= eom) {
444     errno = EMSGSIZE;
445     return (-1);
446     }
447     *dn++ = '\\';
448     *dn++ = digits[c / 100];
449     *dn++ = digits[(c % 100) / 10];
450     *dn++ = digits[c % 10];
451     } else {
452     if (dn >= eom) {
453     errno = EMSGSIZE;
454     return (-1);
455     }
456     *dn++ = (char)c;
457     }
458     }
459     }
460     if (dn == dst) {
461     if (dn >= eom) {
462     errno = EMSGSIZE;
463     return (-1);
464     }
465     *dn++ = '.';
466     }
467     if (dn >= eom) {
468     errno = EMSGSIZE;
469     return (-1);
470     }
471     *dn++ = '\0';
472     return (dn - dst);
473     }
474    
475     /*
476     * Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
477     * Return the size of the compressed name or -1.
478     * 'length' is the size of the array pointed to by 'comp_dn'.
479     */
480     static int
481     irc_dn_comp(const char *src, unsigned char *dst, int dstsiz,
482     unsigned char **dnptrs, unsigned char **lastdnptr)
483     {
484     return(irc_ns_name_compress(src, dst, (size_t)dstsiz,
485     (const unsigned char **)dnptrs,
486     (const unsigned char **)lastdnptr));
487     }
488    
489     /*
490     * Skip over a compressed domain name. Return the size or -1.
491     */
492     int
493     irc_dn_skipname(const unsigned char *ptr, const unsigned char *eom) {
494     const unsigned char *saveptr = ptr;
495    
496     if (irc_ns_name_skip(&ptr, eom) == -1)
497     return(-1);
498     return(ptr - saveptr);
499     }
500    
501     /*
502     * ns_name_skip(ptrptr, eom)
503     * Advance *ptrptr to skip over the compressed name it points at.
504     * return:
505     * 0 on success, -1 (with errno set) on failure.
506     */
507     static int
508     irc_ns_name_skip(const unsigned char **ptrptr, const unsigned char *eom)
509     {
510     const unsigned char *cp;
511     unsigned int n;
512     int l;
513    
514     cp = *ptrptr;
515    
516     while (cp < eom && (n = *cp++) != 0)
517     {
518     /* Check for indirection. */
519     switch (n & NS_CMPRSFLGS)
520     {
521     case 0: /* normal case, n == len */
522     cp += n;
523     continue;
524     case NS_TYPE_ELT: /* EDNS0 extended label */
525     if ((l = labellen(cp - 1)) < 0)
526     {
527     errno = EMSGSIZE; /* XXX */
528     return(-1);
529     }
530    
531     cp += l;
532     continue;
533     case NS_CMPRSFLGS: /* indirection */
534     cp++;
535     break;
536     default: /* illegal type */
537     errno = EMSGSIZE;
538     return(-1);
539     }
540    
541     break;
542     }
543    
544     if (cp > eom)
545     {
546     errno = EMSGSIZE;
547     return (-1);
548     }
549    
550     *ptrptr = cp;
551     return(0);
552     }
553    
554     unsigned int
555     irc_ns_get16(const unsigned char *src)
556     {
557     unsigned int dst;
558    
559     IRC_NS_GET16(dst, src);
560     return(dst);
561     }
562    
563     unsigned long
564     irc_ns_get32(const unsigned char *src)
565     {
566     unsigned long dst;
567    
568     IRC_NS_GET32(dst, src);
569     return(dst);
570     }
571    
572     void
573     irc_ns_put16(unsigned int src, unsigned char *dst)
574     {
575     IRC_NS_PUT16(src, dst);
576     }
577    
578     void
579     irc_ns_put32(unsigned long src, unsigned char *dst)
580     {
581     IRC_NS_PUT32(src, dst);
582     }
583    
584     /* From ns_name.c */
585    
586     /*
587     * special(ch)
588     * Thinking in noninternationalized USASCII (per the DNS spec),
589     * is this characted special ("in need of quoting") ?
590     * return:
591     * boolean.
592     */
593     static int
594     special(int ch)
595     {
596     switch (ch)
597     {
598     case 0x22: /* '"' */
599     case 0x2E: /* '.' */
600     case 0x3B: /* ';' */
601     case 0x5C: /* '\\' */
602     case 0x28: /* '(' */
603     case 0x29: /* ')' */
604     /* Special modifiers in zone files. */
605     case 0x40: /* '@' */
606     case 0x24: /* '$' */
607     return(1);
608     default:
609     return(0);
610     }
611     }
612    
613     static int
614     labellen(const unsigned char *lp)
615     {
616     int bitlen;
617     unsigned char l = *lp;
618    
619     if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS)
620     {
621     /* should be avoided by the caller */
622     return(-1);
623     }
624    
625     if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT)
626     {
627     if (l == DNS_LABELTYPE_BITSTRING)
628     {
629     if ((bitlen = *(lp + 1)) == 0)
630     bitlen = 256;
631     return((bitlen + 7 ) / 8 + 1);
632     }
633    
634     return(-1); /* unknwon ELT */
635     }
636    
637     return(l);
638     }
639    
640    
641     /*
642     * printable(ch)
643     * Thinking in noninternationalized USASCII (per the DNS spec),
644     * is this character visible and not a space when printed ?
645     * return:
646     * boolean.
647     */
648     static int
649     printable(int ch)
650     {
651     return(ch > 0x20 && ch < 0x7f);
652     }
653    
654     static int
655     irc_decode_bitstring(const char **cpp, char *dn, const char *eom)
656     {
657     const char *cp = *cpp;
658     char *beg = dn, tc;
659     int b, blen, plen;
660    
661     if ((blen = (*cp & 0xff)) == 0)
662     blen = 256;
663     plen = (blen + 3) / 4;
664     plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
665     if (dn + plen >= eom)
666     return(-1);
667    
668     cp++;
669     dn += sprintf(dn, "\\[x");
670     for (b = blen; b > 7; b -= 8, cp++)
671     dn += sprintf(dn, "%02x", *cp & 0xff);
672     if (b > 4) {
673     tc = *cp++;
674     dn += sprintf(dn, "%02x", tc & (0xff << (8 - b)));
675     } else if (b > 0) {
676     tc = *cp++;
677     dn += sprintf(dn, "%1x",
678     ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
679     }
680     dn += sprintf(dn, "/%d]", blen);
681    
682     *cpp = cp;
683     return(dn - beg);
684     }
685    
686     /*
687     * irc_ns_name_pton(src, dst, dstsiz)
688     * Convert a ascii string into an encoded domain name as per RFC1035.
689     * return:
690     * -1 if it fails
691     * 1 if string was fully qualified
692     * 0 is string was not fully qualified
693     * notes:
694     * Enforces label and domain length limits.
695     */
696     static int
697     irc_ns_name_pton(const char *src, unsigned char *dst, size_t dstsiz)
698     {
699     unsigned char *label, *bp, *eom;
700     char *cp;
701     int c, n, escaped, e = 0;
702    
703     escaped = 0;
704     bp = dst;
705     eom = dst + dstsiz;
706     label = bp++;
707    
708    
709     while ((c = *src++) != 0) {
710     if (escaped) {
711     if (c == '[') { /* start a bit string label */
712     if ((cp = strchr(src, ']')) == NULL) {
713     errno = EINVAL; /* ??? */
714     return(-1);
715     }
716     if ((e = irc_encode_bitsring(&src,
717     cp + 2,
718     &label,
719     &bp,
720     (const char *)eom))
721     != 0) {
722     errno = e;
723     return(-1);
724     }
725     escaped = 0;
726     label = bp++;
727     if ((c = *src++) == 0)
728     goto done;
729     else if (c != '.') {
730     errno = EINVAL;
731     return(-1);
732     }
733     continue;
734     }
735     else if ((cp = strchr(digits, c)) != NULL) {
736     n = (cp - digits) * 100;
737     if ((c = *src++) == 0 ||
738     (cp = strchr(digits, c)) == NULL) {
739     errno = EMSGSIZE;
740     return (-1);
741     }
742     n += (cp - digits) * 10;
743     if ((c = *src++) == 0 ||
744     (cp = strchr(digits, c)) == NULL) {
745     errno = EMSGSIZE;
746     return (-1);
747     }
748     n += (cp - digits);
749     if (n > 255) {
750     errno = EMSGSIZE;
751     return (-1);
752     }
753     c = n;
754     }
755     escaped = 0;
756     } else if (c == '\\') {
757     escaped = 1;
758     continue;
759     } else if (c == '.') {
760     c = (bp - label - 1);
761     if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
762     errno = EMSGSIZE;
763     return (-1);
764     }
765     if (label >= eom) {
766     errno = EMSGSIZE;
767     return (-1);
768     }
769     *label = c;
770     /* Fully qualified ? */
771     if (*src == '\0') {
772     if (c != 0) {
773     if (bp >= eom) {
774     errno = EMSGSIZE;
775     return (-1);
776     }
777     *bp++ = '\0';
778     }
779     if ((bp - dst) > NS_MAXCDNAME) {
780     errno = EMSGSIZE;
781     return (-1);
782     }
783     return (1);
784     }
785     if (c == 0 || *src == '.') {
786     errno = EMSGSIZE;
787     return (-1);
788     }
789     label = bp++;
790     continue;
791     }
792     if (bp >= eom) {
793     errno = EMSGSIZE;
794     return (-1);
795     }
796     *bp++ = (unsigned char)c;
797     }
798     c = (bp - label - 1);
799     if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
800     errno = EMSGSIZE;
801     return (-1);
802     }
803     done:
804     if (label >= eom) {
805     errno = EMSGSIZE;
806     return (-1);
807     }
808     *label = c;
809     if (c != 0) {
810     if (bp >= eom) {
811     errno = EMSGSIZE;
812     return (-1);
813     }
814     *bp++ = 0;
815     }
816    
817     if ((bp - dst) > NS_MAXCDNAME)
818     { /* src too big */
819     errno = EMSGSIZE;
820     return (-1);
821     }
822    
823     return (0);
824     }
825    
826     /*
827     * irc_ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
828     * Pack domain name 'domain' into 'comp_dn'.
829     * return:
830     * Size of the compressed name, or -1.
831     * notes:
832     * 'dnptrs' is an array of pointers to previous compressed names.
833     * dnptrs[0] is a pointer to the beginning of the message. The array
834     * ends with NULL.
835     * 'lastdnptr' is a pointer to the end of the array pointed to
836     * by 'dnptrs'.
837     * Side effects:
838     * The list of pointers in dnptrs is updated for labels inserted into
839     * the message as we compress the name. If 'dnptr' is NULL, we don't
840     * try to compress names. If 'lastdnptr' is NULL, we don't update the
841     * list.
842     */
843     static int
844     irc_ns_name_pack(const unsigned char *src, unsigned char *dst, int dstsiz,
845     const unsigned char **dnptrs, const unsigned char **lastdnptr)
846     {
847     unsigned char *dstp;
848     const unsigned char **cpp, **lpp, *eob, *msg;
849     const unsigned char *srcp;
850     int n, l, first = 1;
851    
852     srcp = src;
853     dstp = dst;
854     eob = dstp + dstsiz;
855     lpp = cpp = NULL;
856     if (dnptrs != NULL) {
857     if ((msg = *dnptrs++) != NULL) {
858     for (cpp = dnptrs; *cpp != NULL; cpp++)
859     (void)NULL;
860     lpp = cpp; /* end of list to search */
861     }
862     } else
863     msg = NULL;
864    
865     /* make sure the domain we are about to add is legal */
866     l = 0;
867     do {
868     int l0;
869    
870     n = *srcp;
871     if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
872     errno = EMSGSIZE;
873     return (-1);
874     }
875     if ((l0 = labellen(srcp)) < 0) {
876     errno = EINVAL;
877     return(-1);
878     }
879     l += l0 + 1;
880     if (l > NS_MAXCDNAME) {
881     errno = EMSGSIZE;
882     return (-1);
883     }
884     srcp += l0 + 1;
885     } while (n != 0);
886    
887     /* from here on we need to reset compression pointer array on error */
888     srcp = src;
889     do {
890     /* Look to see if we can use pointers. */
891     n = *srcp;
892     if (n != 0 && msg != NULL) {
893     l = irc_dn_find(srcp, msg, (const unsigned char * const *)dnptrs,
894     (const unsigned char * const *)lpp);
895     if (l >= 0) {
896     if (dstp + 1 >= eob) {
897     goto cleanup;
898     }
899     *dstp++ = (l >> 8) | NS_CMPRSFLGS;
900     *dstp++ = l % 256;
901     return (dstp - dst);
902     }
903     /* Not found, save it. */
904     if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
905     (dstp - msg) < 0x4000 && first) {
906     *cpp++ = dstp;
907     *cpp = NULL;
908     first = 0;
909     }
910     }
911     /* copy label to buffer */
912     if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
913     /* Should not happen. */
914     goto cleanup;
915     }
916     n = labellen(srcp);
917     if (dstp + 1 + n >= eob) {
918     goto cleanup;
919     }
920     memcpy(dstp, srcp, n + 1);
921     srcp += n + 1;
922     dstp += n + 1;
923     } while (n != 0);
924    
925     if (dstp > eob) {
926     cleanup:
927     if (msg != NULL)
928     *lpp = NULL;
929     errno = EMSGSIZE;
930     return (-1);
931     }
932     return(dstp - dst);
933     }
934    
935     static int
936     irc_ns_name_compress(const char *src, unsigned char *dst, size_t dstsiz,
937     const unsigned char **dnptrs, const unsigned char **lastdnptr)
938     {
939     unsigned char tmp[NS_MAXCDNAME];
940    
941     if (irc_ns_name_pton(src, tmp, sizeof tmp) == -1)
942     return(-1);
943     return(irc_ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
944     }
945    
946     static int
947     irc_encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
948     unsigned char **dst, const char *eom)
949     {
950     int afterslash = 0;
951     const char *cp = *bp;
952     char *tp, c;
953     const char *beg_blen;
954     char *end_blen = NULL;
955     int value = 0, count = 0, tbcount = 0, blen = 0;
956    
957     beg_blen = end_blen = NULL;
958    
959     /* a bitstring must contain at least 2 characters */
960     if (end - cp < 2)
961     return(EINVAL);
962    
963     /* XXX: currently, only hex strings are supported */
964     if (*cp++ != 'x')
965     return(EINVAL);
966     if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */
967     return(EINVAL);
968    
969     for (tp = (char*)(dst + 1); cp < end && tp < eom; cp++) {
970     switch((c = *cp)) {
971     case ']': /* end of the bitstring */
972     if (afterslash) {
973     if (beg_blen == NULL)
974     return(EINVAL);
975     blen = (int)strtol(beg_blen, &end_blen, 10);
976     if (*end_blen != ']')
977     return(EINVAL);
978     }
979     if (count)
980     *tp++ = ((value << 4) & 0xff);
981     cp++; /* skip ']' */
982     goto done;
983     case '/':
984     afterslash = 1;
985     break;
986     default:
987     if (afterslash) {
988     if (!isdigit(c&0xff))
989     return(EINVAL);
990     if (beg_blen == NULL) {
991    
992     if (c == '0') {
993     /* blen never begings with 0 */
994     return(EINVAL);
995     }
996     beg_blen = cp;
997     }
998     } else {
999     if (!isxdigit(c&0xff))
1000     return(EINVAL);
1001     value <<= 4;
1002     value += digitvalue[(int)c];
1003     count += 4;
1004     tbcount += 4;
1005     if (tbcount > 256)
1006     return(EINVAL);
1007     if (count == 8) {
1008     *tp++ = value;
1009     count = 0;
1010     }
1011     }
1012     break;
1013     }
1014     }
1015     done:
1016     if (cp >= end || tp >= eom)
1017     return(EMSGSIZE);
1018    
1019     /*
1020     * bit length validation:
1021     * If a <length> is present, the number of digits in the <bit-data>
1022     * MUST be just sufficient to contain the number of bits specified
1023     * by the <length>. If there are insignificant bits in a final
1024     * hexadecimal or octal digit, they MUST be zero.
1025     * RFC 2673, Section 3.2.
1026     */
1027     if (blen > 0) {
1028     int traillen;
1029    
1030     if (((blen + 3) & ~3) != tbcount)
1031     return(EINVAL);
1032     traillen = tbcount - blen; /* between 0 and 3 */
1033     if (((value << (8 - traillen)) & 0xff) != 0)
1034     return(EINVAL);
1035     }
1036     else
1037     blen = tbcount;
1038     if (blen == 256)
1039     blen = 0;
1040    
1041     /* encode the type and the significant bit fields */
1042     **labelp = DNS_LABELTYPE_BITSTRING;
1043     **dst = blen;
1044    
1045     *bp = cp;
1046     *dst = (unsigned char*)tp;
1047    
1048     return(0);
1049     }
1050    
1051     /*
1052     * dn_find(domain, msg, dnptrs, lastdnptr)
1053     * Search for the counted-label name in an array of compressed names.
1054     * return:
1055     * offset from msg if found, or -1.
1056     * notes:
1057     * dnptrs is the pointer to the first name on the list,
1058     * not the pointer to the start of the message.
1059     */
1060     static int
1061     irc_dn_find(const unsigned char *domain, const unsigned char *msg,
1062     const unsigned char * const *dnptrs,
1063     const unsigned char * const *lastdnptr)
1064     {
1065     const unsigned char *dn, *cp, *sp;
1066     const unsigned char * const *cpp;
1067     unsigned int n;
1068    
1069     for (cpp = dnptrs; cpp < lastdnptr; cpp++)
1070     {
1071     sp = *cpp;
1072     /*
1073     * terminate search on:
1074     * root label
1075     * compression pointer
1076     * unusable offset
1077     */
1078     while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
1079     (sp - msg) < 0x4000) {
1080     dn = domain;
1081     cp = sp;
1082     while ((n = *cp++) != 0) {
1083     /*
1084     * check for indirection
1085     */
1086     switch (n & NS_CMPRSFLGS) {
1087     case 0: /* normal case, n == len */
1088     n = labellen(cp - 1); /* XXX */
1089    
1090     if (n != *dn++)
1091     goto next;
1092    
1093     for ((void)NULL; n > 0; n--)
1094     if (mklower(*dn++) !=
1095     mklower(*cp++))
1096     goto next;
1097     /* Is next root for both ? */
1098     if (*dn == '\0' && *cp == '\0')
1099     return (sp - msg);
1100     if (*dn)
1101     continue;
1102     goto next;
1103     case NS_CMPRSFLGS: /* indirection */
1104     cp = msg + (((n & 0x3f) << 8) | *cp);
1105     break;
1106    
1107     default: /* illegal type */
1108     errno = EMSGSIZE;
1109     return (-1);
1110     }
1111     }
1112     next: ;
1113     sp += *sp + 1;
1114     }
1115     }
1116     errno = ENOENT;
1117     return (-1);
1118     }
1119    
1120     /*
1121     * * Thinking in noninternationalized USASCII (per the DNS spec),
1122     * * convert this character to lower case if it's upper case.
1123     * */
1124     static int
1125     mklower(int ch)
1126     {
1127     if (ch >= 0x41 && ch <= 0x5A)
1128     return(ch + 0x20);
1129    
1130     return(ch);
1131     }
1132    
1133     /* From resolv/mkquery.c */
1134    
1135     /*
1136     * Form all types of queries.
1137     * Returns the size of the result or -1.
1138     */
1139     int
1140     irc_res_mkquery(
1141     const char *dname, /* domain name */
1142     int class, int type, /* class and type of query */
1143     unsigned char *buf, /* buffer to put query */
1144     int buflen) /* size of buffer */
1145     {
1146     HEADER *hp;
1147     unsigned char *cp;
1148     int n;
1149     unsigned char *dnptrs[20], **dpp, **lastdnptr;
1150    
1151     /*
1152     * Initialize header fields.
1153     */
1154     if ((buf == NULL) || (buflen < HFIXEDSZ))
1155     return (-1);
1156     memset(buf, 0, HFIXEDSZ);
1157     hp = (HEADER *) buf;
1158    
1159     hp->id = 0;
1160     hp->opcode = QUERY;
1161     hp->rd = 1; /* recurse */
1162     hp->rcode = NO_ERRORS;
1163     cp = buf + HFIXEDSZ;
1164     buflen -= HFIXEDSZ;
1165     dpp = dnptrs;
1166     *dpp++ = buf;
1167     *dpp++ = NULL;
1168     lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
1169    
1170     if ((buflen -= QFIXEDSZ) < 0)
1171     return (-1);
1172     if ((n = irc_dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
1173     return (-1);
1174    
1175     cp += n;
1176     buflen -= n;
1177     IRC_NS_PUT16(type, cp);
1178     IRC_NS_PUT16(class, cp);
1179     hp->qdcount = htons(1);
1180    
1181     return (cp - buf);
1182     }

Properties

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