ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/reslib.c
Revision: 1011
Committed: Fri Sep 18 10:14:09 2009 UTC (15 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/irc_reslib.c
File size: 29796 byte(s)
Log Message:
- move list manipulation routines from tools.c to list.c
- mem_frob() goes to memory.c
- sort out redundant/unneeded header includes

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 michael 1011 #include "ircd_defs.h"
85 michael 998 #include "irc_res.h"
86     #include "irc_reslib.h"
87 adx 30 #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    
100     static const char digitvalue[256] = {
101     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
102     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
103     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
104     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
105     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
106     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
107     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
108     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
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,
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, /*256*/
117     };
118    
119     static int parse_resvconf(void);
120     static void add_nameserver(char *arg);
121    
122     static const char digits[] = "0123456789";
123     static int labellen(const unsigned char *lp);
124     static int special(int ch);
125     static int printable(int ch);
126 michael 993 static int irc_decode_bitstring(const unsigned char **cpp, char *dn, const char *eom);
127 adx 30 static int irc_ns_name_compress(const char *src, unsigned char *dst, size_t dstsiz,
128     const unsigned char **dnptrs, const unsigned char **lastdnptr);
129     static int irc_dn_find(const unsigned char *, const unsigned char *, const unsigned char * const *,
130     const unsigned char * const *);
131     static int irc_encode_bitsring(const char **, const char *, unsigned char **, unsigned char **,
132 michael 993 const unsigned char *);
133 adx 30 static int irc_ns_name_uncompress(const unsigned char *, const unsigned char *,
134     const unsigned char *, char *, size_t);
135     static int irc_ns_name_unpack(const unsigned char *, const unsigned char *,
136     const unsigned char *, unsigned char *,
137     size_t);
138 michael 993 static int irc_ns_name_ntop(const unsigned char *, char *, size_t);
139 adx 30 static int irc_ns_name_skip(const unsigned char **, const unsigned char *);
140     static int mklower(int ch);
141    
142     int
143     irc_res_init(void)
144     {
145     irc_nscount = 0;
146 michael 996 memset(irc_nsaddr_list, 0, sizeof(irc_nsaddr_list));
147    
148 adx 30 return parse_resvconf();
149     }
150    
151     /* parse_resvconf()
152     *
153     * inputs - NONE
154     * output - -1 if failure 0 if success
155     * side effects - fills in irc_nsaddr_list
156     */
157     static int
158     parse_resvconf(void)
159     {
160     char *p;
161     char *opt;
162     char *arg;
163     char input[MAXLINE];
164     FBFILE *file;
165    
166 michael 912 /* XXX "/etc/resolv.conf" should be from a define in config.h perhaps
167 adx 30 * for cygwin support etc. this hardcodes it to unix for now -db
168     */
169     if ((file = fbopen("/etc/resolv.conf", "r")) == NULL)
170 michael 708 return -1;
171 adx 30
172 michael 708 while (fbgets(input, sizeof(input), file) != NULL)
173 adx 30 {
174     /* blow away any newline */
175     if ((p = strpbrk(input, "\r\n")) != NULL)
176     *p = '\0';
177    
178 michael 708 p = input;
179 adx 30
180     /* skip until something thats not a space is seen */
181     while (IsSpace(*p))
182 michael 708 ++p;
183    
184 adx 30 /* if at this point, have a '\0' then continue */
185     if (*p == '\0')
186     continue;
187    
188 michael 708 /* Ignore comment lines immediately */
189     if (*p == ';' || *p == '#')
190     continue;
191    
192 adx 30 /* skip until a space is found */
193 michael 708 opt = p;
194     while (!IsSpace(*p) && *p)
195     ++p;
196    
197     if (*p == '\0')
198     continue; /* no arguments?.. ignore this line */
199    
200 adx 30 /* blow away the space character */
201     *p++ = '\0';
202    
203     /* skip these spaces that are before the argument */
204     while (IsSpace(*p))
205 michael 708 ++p;
206    
207 adx 30 /* Now arg should be right where p is pointing */
208     arg = p;
209 michael 708
210 adx 30 if ((p = strpbrk(arg, " \t")) != NULL)
211     *p = '\0'; /* take the first word */
212    
213 michael 995 if (irccmp(opt, "nameserver") == 0)
214 adx 30 add_nameserver(arg);
215     }
216    
217     fbclose(file);
218 michael 708 return 0;
219 adx 30 }
220    
221     /* add_nameserver()
222     *
223     * input - either an IPV4 address in dotted quad
224     * or an IPV6 address in : format
225     * output - NONE
226     * side effects - entry in irc_nsaddr_list is filled in as needed
227     */
228     static void
229     add_nameserver(char *arg)
230     {
231     struct addrinfo hints, *res;
232     /* Done max number of nameservers? */
233     if ((irc_nscount) >= IRCD_MAXNS)
234     return;
235    
236     memset(&hints, 0, sizeof(hints));
237     hints.ai_family = PF_UNSPEC;
238     hints.ai_socktype = SOCK_DGRAM;
239     hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
240    
241     if (irc_getaddrinfo(arg, "domain", &hints, &res))
242     return;
243    
244     if (res == NULL)
245     return;
246    
247     memcpy(&irc_nsaddr_list[irc_nscount].ss, res->ai_addr, res->ai_addrlen);
248     irc_nsaddr_list[irc_nscount].ss_len = res->ai_addrlen;
249     irc_nscount++;
250     irc_freeaddrinfo(res);
251     }
252    
253     /*
254     * Expand compressed domain name 'comp_dn' to full domain name.
255     * 'msg' is a pointer to the begining of the message,
256     * 'eomorig' points to the first location after the message,
257     * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
258     * Return size of compressed name or -1 if there was an error.
259     */
260     int
261     irc_dn_expand(const unsigned char *msg, const unsigned char *eom,
262     const unsigned char *src, char *dst, int dstsiz)
263     {
264     int n = irc_ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
265    
266     if (n > 0 && dst[0] == '.')
267     dst[0] = '\0';
268     return(n);
269 michael 993 } /*2*/
270 adx 30
271     /*
272     * irc_ns_name_uncompress(msg, eom, src, dst, dstsiz)
273     * Expand compressed domain name to presentation format.
274     * return:
275     * Number of bytes read out of `src', or -1 (with errno set).
276     * note:
277     * Root domain returns as "." not "".
278     */
279     static int
280     irc_ns_name_uncompress(const unsigned char *msg, const unsigned char *eom,
281     const unsigned char *src, char *dst, size_t dstsiz)
282     {
283     unsigned char tmp[NS_MAXCDNAME];
284     int n;
285    
286     if ((n = irc_ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
287     return(-1);
288 michael 993 if (irc_ns_name_ntop(tmp, dst, dstsiz) == -1)
289 adx 30 return(-1);
290     return(n);
291 michael 993 } /*2*/
292    
293 adx 30 /*
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 michael 993 } /*2*/
373 adx 30
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 michael 993 irc_ns_name_ntop(const unsigned char *src, char *dst, size_t dstsiz)
385 adx 30 {
386 michael 993 const unsigned char *cp;
387 adx 30 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 michael 993 if ((l = labellen((cp - 1))) < 0) {
410 adx 30 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 michael 993 } /*2*/
474 adx 30
475     /*
476     * Skip over a compressed domain name. Return the size or -1.
477     */
478     int
479     irc_dn_skipname(const unsigned char *ptr, const unsigned char *eom) {
480     const unsigned char *saveptr = ptr;
481    
482     if (irc_ns_name_skip(&ptr, eom) == -1)
483     return(-1);
484     return(ptr - saveptr);
485 michael 993 } /*2*/
486 adx 30
487     /*
488     * ns_name_skip(ptrptr, eom)
489     * Advance *ptrptr to skip over the compressed name it points at.
490     * return:
491     * 0 on success, -1 (with errno set) on failure.
492     */
493     static int
494     irc_ns_name_skip(const unsigned char **ptrptr, const unsigned char *eom)
495     {
496     const unsigned char *cp;
497     unsigned int n;
498     int l;
499    
500     cp = *ptrptr;
501    
502     while (cp < eom && (n = *cp++) != 0)
503     {
504     /* Check for indirection. */
505     switch (n & NS_CMPRSFLGS)
506     {
507     case 0: /* normal case, n == len */
508     cp += n;
509     continue;
510     case NS_TYPE_ELT: /* EDNS0 extended label */
511     if ((l = labellen(cp - 1)) < 0)
512     {
513     errno = EMSGSIZE; /* XXX */
514     return(-1);
515     }
516    
517     cp += l;
518     continue;
519     case NS_CMPRSFLGS: /* indirection */
520     cp++;
521     break;
522     default: /* illegal type */
523     errno = EMSGSIZE;
524     return(-1);
525     }
526    
527     break;
528     }
529    
530     if (cp > eom)
531     {
532     errno = EMSGSIZE;
533     return (-1);
534     }
535    
536     *ptrptr = cp;
537     return(0);
538 michael 993 } /*2*/
539 adx 30
540     unsigned int
541     irc_ns_get16(const unsigned char *src)
542     {
543     unsigned int dst;
544    
545     IRC_NS_GET16(dst, src);
546     return(dst);
547     }
548    
549     unsigned long
550     irc_ns_get32(const unsigned char *src)
551     {
552     unsigned long dst;
553    
554     IRC_NS_GET32(dst, src);
555     return(dst);
556     }
557    
558     void
559     irc_ns_put16(unsigned int src, unsigned char *dst)
560     {
561     IRC_NS_PUT16(src, dst);
562     }
563    
564     void
565     irc_ns_put32(unsigned long src, unsigned char *dst)
566     {
567     IRC_NS_PUT32(src, dst);
568     }
569    
570     /* From ns_name.c */
571    
572     /*
573     * special(ch)
574     * Thinking in noninternationalized USASCII (per the DNS spec),
575     * is this characted special ("in need of quoting") ?
576     * return:
577     * boolean.
578     */
579     static int
580     special(int ch)
581     {
582     switch (ch)
583     {
584     case 0x22: /* '"' */
585     case 0x2E: /* '.' */
586     case 0x3B: /* ';' */
587     case 0x5C: /* '\\' */
588     case 0x28: /* '(' */
589     case 0x29: /* ')' */
590     /* Special modifiers in zone files. */
591     case 0x40: /* '@' */
592     case 0x24: /* '$' */
593     return(1);
594     default:
595     return(0);
596     }
597 michael 993 } /*2*/
598 adx 30
599     static int
600     labellen(const unsigned char *lp)
601     {
602     int bitlen;
603     unsigned char l = *lp;
604    
605     if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS)
606     {
607     /* should be avoided by the caller */
608     return(-1);
609     }
610    
611     if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT)
612     {
613     if (l == DNS_LABELTYPE_BITSTRING)
614     {
615     if ((bitlen = *(lp + 1)) == 0)
616     bitlen = 256;
617     return((bitlen + 7 ) / 8 + 1);
618     }
619    
620     return(-1); /* unknwon ELT */
621     }
622    
623     return(l);
624 michael 993 } /*2*/
625 adx 30
626    
627     /*
628     * printable(ch)
629     * Thinking in noninternationalized USASCII (per the DNS spec),
630     * is this character visible and not a space when printed ?
631     * return:
632     * boolean.
633     */
634     static int
635     printable(int ch)
636     {
637     return(ch > 0x20 && ch < 0x7f);
638 michael 993 } /*2*/
639 adx 30
640     static int
641 michael 993 irc_decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
642 adx 30 {
643 michael 993 const unsigned char *cp = *cpp;
644 adx 30 char *beg = dn, tc;
645     int b, blen, plen;
646    
647     if ((blen = (*cp & 0xff)) == 0)
648     blen = 256;
649     plen = (blen + 3) / 4;
650     plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
651     if (dn + plen >= eom)
652     return(-1);
653    
654     cp++;
655     dn += sprintf(dn, "\\[x");
656     for (b = blen; b > 7; b -= 8, cp++)
657     dn += sprintf(dn, "%02x", *cp & 0xff);
658     if (b > 4) {
659     tc = *cp++;
660     dn += sprintf(dn, "%02x", tc & (0xff << (8 - b)));
661     } else if (b > 0) {
662     tc = *cp++;
663     dn += sprintf(dn, "%1x",
664     ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
665     }
666     dn += sprintf(dn, "/%d]", blen);
667    
668     *cpp = cp;
669     return(dn - beg);
670 michael 993 } /*2*/
671 adx 30
672     /*
673     * irc_ns_name_pton(src, dst, dstsiz)
674     * Convert a ascii string into an encoded domain name as per RFC1035.
675     * return:
676     * -1 if it fails
677     * 1 if string was fully qualified
678     * 0 is string was not fully qualified
679     * notes:
680     * Enforces label and domain length limits.
681     */
682     static int
683     irc_ns_name_pton(const char *src, unsigned char *dst, size_t dstsiz)
684     {
685     unsigned char *label, *bp, *eom;
686     char *cp;
687     int c, n, escaped, e = 0;
688    
689     escaped = 0;
690     bp = dst;
691     eom = dst + dstsiz;
692     label = bp++;
693    
694    
695     while ((c = *src++) != 0) {
696     if (escaped) {
697     if (c == '[') { /* start a bit string label */
698     if ((cp = strchr(src, ']')) == NULL) {
699     errno = EINVAL; /* ??? */
700     return(-1);
701     }
702     if ((e = irc_encode_bitsring(&src,
703     cp + 2,
704     &label,
705     &bp,
706 michael 993 eom))
707 adx 30 != 0) {
708     errno = e;
709     return(-1);
710     }
711     escaped = 0;
712     label = bp++;
713     if ((c = *src++) == 0)
714     goto done;
715     else if (c != '.') {
716     errno = EINVAL;
717     return(-1);
718     }
719     continue;
720     }
721     else if ((cp = strchr(digits, c)) != NULL) {
722     n = (cp - digits) * 100;
723     if ((c = *src++) == 0 ||
724     (cp = strchr(digits, c)) == NULL) {
725     errno = EMSGSIZE;
726     return (-1);
727     }
728     n += (cp - digits) * 10;
729     if ((c = *src++) == 0 ||
730     (cp = strchr(digits, c)) == NULL) {
731     errno = EMSGSIZE;
732     return (-1);
733     }
734     n += (cp - digits);
735     if (n > 255) {
736     errno = EMSGSIZE;
737     return (-1);
738     }
739     c = n;
740     }
741     escaped = 0;
742     } else if (c == '\\') {
743     escaped = 1;
744     continue;
745     } else if (c == '.') {
746     c = (bp - label - 1);
747     if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
748     errno = EMSGSIZE;
749     return (-1);
750     }
751     if (label >= eom) {
752     errno = EMSGSIZE;
753     return (-1);
754     }
755     *label = c;
756     /* Fully qualified ? */
757     if (*src == '\0') {
758     if (c != 0) {
759     if (bp >= eom) {
760     errno = EMSGSIZE;
761     return (-1);
762     }
763     *bp++ = '\0';
764     }
765     if ((bp - dst) > NS_MAXCDNAME) {
766     errno = EMSGSIZE;
767     return (-1);
768     }
769     return (1);
770     }
771     if (c == 0 || *src == '.') {
772     errno = EMSGSIZE;
773     return (-1);
774     }
775     label = bp++;
776     continue;
777     }
778     if (bp >= eom) {
779     errno = EMSGSIZE;
780     return (-1);
781     }
782     *bp++ = (unsigned char)c;
783     }
784     c = (bp - label - 1);
785     if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
786     errno = EMSGSIZE;
787     return (-1);
788     }
789     done:
790     if (label >= eom) {
791     errno = EMSGSIZE;
792     return (-1);
793     }
794     *label = c;
795     if (c != 0) {
796     if (bp >= eom) {
797     errno = EMSGSIZE;
798     return (-1);
799     }
800     *bp++ = 0;
801     }
802    
803     if ((bp - dst) > NS_MAXCDNAME)
804     { /* src too big */
805     errno = EMSGSIZE;
806     return (-1);
807     }
808    
809     return (0);
810 michael 993 } /*2*/
811 adx 30
812     /*
813     * irc_ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
814     * Pack domain name 'domain' into 'comp_dn'.
815     * return:
816     * Size of the compressed name, or -1.
817     * notes:
818     * 'dnptrs' is an array of pointers to previous compressed names.
819     * dnptrs[0] is a pointer to the beginning of the message. The array
820     * ends with NULL.
821     * 'lastdnptr' is a pointer to the end of the array pointed to
822     * by 'dnptrs'.
823     * Side effects:
824     * The list of pointers in dnptrs is updated for labels inserted into
825     * the message as we compress the name. If 'dnptr' is NULL, we don't
826     * try to compress names. If 'lastdnptr' is NULL, we don't update the
827     * list.
828     */
829     static int
830     irc_ns_name_pack(const unsigned char *src, unsigned char *dst, int dstsiz,
831     const unsigned char **dnptrs, const unsigned char **lastdnptr)
832     {
833     unsigned char *dstp;
834     const unsigned char **cpp, **lpp, *eob, *msg;
835     const unsigned char *srcp;
836     int n, l, first = 1;
837    
838     srcp = src;
839     dstp = dst;
840     eob = dstp + dstsiz;
841     lpp = cpp = NULL;
842     if (dnptrs != NULL) {
843     if ((msg = *dnptrs++) != NULL) {
844     for (cpp = dnptrs; *cpp != NULL; cpp++)
845     (void)NULL;
846     lpp = cpp; /* end of list to search */
847     }
848     } else
849     msg = NULL;
850    
851     /* make sure the domain we are about to add is legal */
852     l = 0;
853     do {
854     int l0;
855    
856     n = *srcp;
857     if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
858     errno = EMSGSIZE;
859     return (-1);
860     }
861     if ((l0 = labellen(srcp)) < 0) {
862     errno = EINVAL;
863     return(-1);
864     }
865     l += l0 + 1;
866     if (l > NS_MAXCDNAME) {
867     errno = EMSGSIZE;
868     return (-1);
869     }
870     srcp += l0 + 1;
871     } while (n != 0);
872    
873     /* from here on we need to reset compression pointer array on error */
874     srcp = src;
875     do {
876     /* Look to see if we can use pointers. */
877     n = *srcp;
878     if (n != 0 && msg != NULL) {
879     l = irc_dn_find(srcp, msg, (const unsigned char * const *)dnptrs,
880     (const unsigned char * const *)lpp);
881     if (l >= 0) {
882     if (dstp + 1 >= eob) {
883     goto cleanup;
884     }
885     *dstp++ = (l >> 8) | NS_CMPRSFLGS;
886     *dstp++ = l % 256;
887     return (dstp - dst);
888     }
889     /* Not found, save it. */
890     if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
891     (dstp - msg) < 0x4000 && first) {
892     *cpp++ = dstp;
893     *cpp = NULL;
894     first = 0;
895     }
896     }
897     /* copy label to buffer */
898     if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
899     /* Should not happen. */
900     goto cleanup;
901     }
902     n = labellen(srcp);
903     if (dstp + 1 + n >= eob) {
904     goto cleanup;
905     }
906     memcpy(dstp, srcp, n + 1);
907     srcp += n + 1;
908     dstp += n + 1;
909     } while (n != 0);
910    
911     if (dstp > eob) {
912     cleanup:
913     if (msg != NULL)
914     *lpp = NULL;
915     errno = EMSGSIZE;
916     return (-1);
917     }
918     return(dstp - dst);
919 michael 993 } /*2*/
920 adx 30
921     static int
922     irc_ns_name_compress(const char *src, unsigned char *dst, size_t dstsiz,
923     const unsigned char **dnptrs, const unsigned char **lastdnptr)
924     {
925     unsigned char tmp[NS_MAXCDNAME];
926    
927     if (irc_ns_name_pton(src, tmp, sizeof tmp) == -1)
928     return(-1);
929     return(irc_ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
930     }
931    
932     static int
933     irc_encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
934 michael 993 unsigned char **dst, const unsigned char *eom)
935 adx 30 {
936     int afterslash = 0;
937     const char *cp = *bp;
938 michael 993 unsigned char *tp;
939     char c;
940 adx 30 const char *beg_blen;
941     char *end_blen = NULL;
942     int value = 0, count = 0, tbcount = 0, blen = 0;
943    
944     beg_blen = end_blen = NULL;
945    
946     /* a bitstring must contain at least 2 characters */
947     if (end - cp < 2)
948     return(EINVAL);
949    
950     /* XXX: currently, only hex strings are supported */
951     if (*cp++ != 'x')
952     return(EINVAL);
953     if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */
954     return(EINVAL);
955    
956 michael 993 for (tp = *dst + 1; cp < end && tp < eom; cp++) {
957 adx 30 switch((c = *cp)) {
958     case ']': /* end of the bitstring */
959     if (afterslash) {
960     if (beg_blen == NULL)
961     return(EINVAL);
962     blen = (int)strtol(beg_blen, &end_blen, 10);
963     if (*end_blen != ']')
964     return(EINVAL);
965     }
966     if (count)
967     *tp++ = ((value << 4) & 0xff);
968     cp++; /* skip ']' */
969     goto done;
970     case '/':
971     afterslash = 1;
972     break;
973     default:
974     if (afterslash) {
975     if (!isdigit(c&0xff))
976     return(EINVAL);
977     if (beg_blen == NULL) {
978    
979     if (c == '0') {
980     /* blen never begings with 0 */
981     return(EINVAL);
982     }
983     beg_blen = cp;
984     }
985     } else {
986     if (!isxdigit(c&0xff))
987     return(EINVAL);
988     value <<= 4;
989     value += digitvalue[(int)c];
990     count += 4;
991     tbcount += 4;
992     if (tbcount > 256)
993     return(EINVAL);
994     if (count == 8) {
995     *tp++ = value;
996     count = 0;
997     }
998     }
999     break;
1000     }
1001     }
1002     done:
1003     if (cp >= end || tp >= eom)
1004     return(EMSGSIZE);
1005    
1006     /*
1007     * bit length validation:
1008     * If a <length> is present, the number of digits in the <bit-data>
1009     * MUST be just sufficient to contain the number of bits specified
1010     * by the <length>. If there are insignificant bits in a final
1011     * hexadecimal or octal digit, they MUST be zero.
1012     * RFC 2673, Section 3.2.
1013     */
1014     if (blen > 0) {
1015     int traillen;
1016    
1017     if (((blen + 3) & ~3) != tbcount)
1018     return(EINVAL);
1019     traillen = tbcount - blen; /* between 0 and 3 */
1020     if (((value << (8 - traillen)) & 0xff) != 0)
1021     return(EINVAL);
1022     }
1023     else
1024     blen = tbcount;
1025     if (blen == 256)
1026     blen = 0;
1027    
1028     /* encode the type and the significant bit fields */
1029     **labelp = DNS_LABELTYPE_BITSTRING;
1030     **dst = blen;
1031    
1032     *bp = cp;
1033 michael 993 *dst = tp;
1034 adx 30
1035     return(0);
1036 michael 993 } /*2*/
1037 adx 30
1038     /*
1039     * dn_find(domain, msg, dnptrs, lastdnptr)
1040     * Search for the counted-label name in an array of compressed names.
1041     * return:
1042     * offset from msg if found, or -1.
1043     * notes:
1044     * dnptrs is the pointer to the first name on the list,
1045     * not the pointer to the start of the message.
1046     */
1047     static int
1048     irc_dn_find(const unsigned char *domain, const unsigned char *msg,
1049     const unsigned char * const *dnptrs,
1050     const unsigned char * const *lastdnptr)
1051     {
1052     const unsigned char *dn, *cp, *sp;
1053     const unsigned char * const *cpp;
1054     unsigned int n;
1055    
1056     for (cpp = dnptrs; cpp < lastdnptr; cpp++)
1057     {
1058     sp = *cpp;
1059     /*
1060     * terminate search on:
1061     * root label
1062     * compression pointer
1063     * unusable offset
1064     */
1065     while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
1066     (sp - msg) < 0x4000) {
1067     dn = domain;
1068     cp = sp;
1069     while ((n = *cp++) != 0) {
1070     /*
1071     * check for indirection
1072     */
1073     switch (n & NS_CMPRSFLGS) {
1074     case 0: /* normal case, n == len */
1075     n = labellen(cp - 1); /* XXX */
1076    
1077     if (n != *dn++)
1078     goto next;
1079    
1080     for ((void)NULL; n > 0; n--)
1081     if (mklower(*dn++) !=
1082     mklower(*cp++))
1083     goto next;
1084     /* Is next root for both ? */
1085     if (*dn == '\0' && *cp == '\0')
1086     return (sp - msg);
1087     if (*dn)
1088     continue;
1089     goto next;
1090     case NS_CMPRSFLGS: /* indirection */
1091     cp = msg + (((n & 0x3f) << 8) | *cp);
1092     break;
1093    
1094     default: /* illegal type */
1095     errno = EMSGSIZE;
1096     return (-1);
1097     }
1098     }
1099     next: ;
1100     sp += *sp + 1;
1101     }
1102     }
1103     errno = ENOENT;
1104     return (-1);
1105 michael 993 } /*2*/
1106 adx 30
1107     /*
1108     * * Thinking in noninternationalized USASCII (per the DNS spec),
1109     * * convert this character to lower case if it's upper case.
1110     * */
1111     static int
1112     mklower(int ch)
1113     {
1114     if (ch >= 0x41 && ch <= 0x5A)
1115     return(ch + 0x20);
1116    
1117     return(ch);
1118 michael 993 } /*2*/
1119 adx 30
1120     /* From resolv/mkquery.c */
1121    
1122     /*
1123     * Form all types of queries.
1124     * Returns the size of the result or -1.
1125     */
1126     int
1127     irc_res_mkquery(
1128     const char *dname, /* domain name */
1129     int class, int type, /* class and type of query */
1130     unsigned char *buf, /* buffer to put query */
1131     int buflen) /* size of buffer */
1132     {
1133     HEADER *hp;
1134     unsigned char *cp;
1135     int n;
1136     unsigned char *dnptrs[20], **dpp, **lastdnptr;
1137    
1138     /*
1139     * Initialize header fields.
1140     */
1141     if ((buf == NULL) || (buflen < HFIXEDSZ))
1142     return (-1);
1143     memset(buf, 0, HFIXEDSZ);
1144     hp = (HEADER *) buf;
1145    
1146     hp->id = 0;
1147     hp->opcode = QUERY;
1148     hp->rd = 1; /* recurse */
1149     hp->rcode = NO_ERRORS;
1150     cp = buf + HFIXEDSZ;
1151     buflen -= HFIXEDSZ;
1152     dpp = dnptrs;
1153     *dpp++ = buf;
1154     *dpp++ = NULL;
1155     lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
1156    
1157     if ((buflen -= QFIXEDSZ) < 0)
1158     return (-1);
1159 michael 993 if ((n = irc_ns_name_compress(dname, cp, buflen, (const unsigned char **)dnptrs,
1160     (const unsigned char **)lastdnptr)) < 0)
1161 adx 30 return (-1);
1162    
1163     cp += n;
1164     buflen -= n;
1165     IRC_NS_PUT16(type, cp);
1166     IRC_NS_PUT16(class, cp);
1167     hp->qdcount = htons(1);
1168    
1169     return (cp - buf);
1170     }

Properties

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