ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/reslib.c
Revision: 7668
Committed: Wed Jul 20 17:09:49 2016 UTC (9 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 29543 byte(s)
Log Message:
- Fixed svn properties

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

Properties

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