ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/reslib.c
Revision: 3297
Committed: Fri Apr 11 16:08:55 2014 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/src/irc_reslib.c
File size: 29410 byte(s)
Log Message:
- Made irc_nscount an unsigned type

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

Properties

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