[BACK]Return to ns_name.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / nameser

Annotation of src/lib/libc/nameser/ns_name.c, Revision 1.6.6.2

1.6.6.2 ! christos    1: /*     $NetBSD: ns_name.c,v 1.6 2008/06/21 20:41:48 christos Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
        !             5:  * Copyright (c) 1996,1999 by Internet Software Consortium.
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
        !            12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            13:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
        !            14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
        !            17:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            18:  */
        !            19:
        !            20: #include <sys/cdefs.h>
        !            21: #ifndef lint
        !            22: #ifdef notdef
        !            23: static const char rcsid[] = "Id: ns_name.c,v 1.10 2005/04/27 04:56:40 sra Exp";
        !            24: #else
        !            25: __RCSID("$NetBSD: ns_name.c,v 1.6 2008/06/21 20:41:48 christos Exp $");
        !            26: #endif
        !            27: #endif
        !            28:
        !            29: #include "port_before.h"
        !            30:
        !            31: #include <sys/types.h>
        !            32:
        !            33: #include <netinet/in.h>
        !            34: #include <arpa/nameser.h>
        !            35:
        !            36: #include <errno.h>
        !            37: #include <resolv.h>
        !            38: #include <string.h>
        !            39: #include <ctype.h>
        !            40: #include <stdlib.h>
        !            41: #include <limits.h>
        !            42:
        !            43: #include "port_after.h"
        !            44:
        !            45: #ifdef SPRINTF_CHAR
        !            46: # define SPRINTF(x) strlen(sprintf/**/x)
        !            47: #else
        !            48: # define SPRINTF(x) ((size_t)sprintf x)
        !            49: #endif
        !            50:
        !            51: #define NS_TYPE_ELT                    0x40 /*%< EDNS0 extended label type */
        !            52: #define DNS_LABELTYPE_BITSTRING                0x41
        !            53:
        !            54: /* Data. */
        !            55:
        !            56: static const char      digits[] = "0123456789";
        !            57:
        !            58: static const char digitvalue[256] = {
        !            59:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
        !            60:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
        !            61:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
        !            62:         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
        !            63:        -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
        !            64:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
        !            65:        -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
        !            66:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
        !            67:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        !            68:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        !            69:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        !            70:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        !            71:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        !            72:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        !            73:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        !            74:        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
        !            75: };
        !            76:
        !            77: /* Forward. */
        !            78:
        !            79: static int             special(int);
        !            80: static int             printable(int);
        !            81: static int             dn_find(const u_char *, const u_char *,
        !            82:                                const u_char * const *,
        !            83:                                const u_char * const *);
        !            84: static int             encode_bitsring(const char **, const char *,
        !            85:                                        unsigned char **, unsigned char **,
        !            86:                                        unsigned const char *);
        !            87: static int             labellen(const u_char *);
        !            88: static int             decode_bitstring(const unsigned char **,
        !            89:                                         char *, const char *);
        !            90:
        !            91: /* Public. */
        !            92:
        !            93: /*%
        !            94:  *     Convert an encoded domain name to printable ascii as per RFC1035.
        !            95:
        !            96:  * return:
        !            97:  *\li  Number of bytes written to buffer, or -1 (with errno set)
        !            98:  *
        !            99:  * notes:
        !           100:  *\li  The root is returned as "."
        !           101:  *\li  All other domains are returned in non absolute form
        !           102:  */
        !           103: int
        !           104: ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
        !           105: {
        !           106:        const u_char *cp;
        !           107:        char *dn, *eom;
        !           108:        u_char c;
        !           109:        u_int n;
        !           110:        int l;
        !           111:
        !           112:        cp = src;
        !           113:        dn = dst;
        !           114:        eom = dst + dstsiz;
        !           115:
        !           116:        while ((n = *cp++) != 0) {
        !           117:                if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
        !           118:                        /* Some kind of compression pointer. */
        !           119:                        errno = EMSGSIZE;
        !           120:                        return (-1);
        !           121:                }
        !           122:                if (dn != dst) {
        !           123:                        if (dn >= eom) {
        !           124:                                errno = EMSGSIZE;
        !           125:                                return (-1);
        !           126:                        }
        !           127:                        *dn++ = '.';
        !           128:                }
        !           129:                if ((l = labellen(cp - 1)) < 0) {
        !           130:                        errno = EMSGSIZE; /*%< XXX */
        !           131:                        return(-1);
        !           132:                }
        !           133:                if (dn + l >= eom) {
        !           134:                        errno = EMSGSIZE;
        !           135:                        return (-1);
        !           136:                }
        !           137:                if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
        !           138:                        int m;
        !           139:
        !           140:                        if (n != DNS_LABELTYPE_BITSTRING) {
        !           141:                                /* XXX: labellen should reject this case */
        !           142:                                errno = EINVAL;
        !           143:                                return(-1);
        !           144:                        }
        !           145:                        if ((m = decode_bitstring(&cp, dn, eom)) < 0)
        !           146:                        {
        !           147:                                errno = EMSGSIZE;
        !           148:                                return(-1);
        !           149:                        }
        !           150:                        dn += m;
        !           151:                        continue;
        !           152:                }
        !           153:                for (; l > 0; l--) {
        !           154:                        c = *cp++;
        !           155:                        if (special(c)) {
        !           156:                                if (dn + 1 >= eom) {
        !           157:                                        errno = EMSGSIZE;
        !           158:                                        return (-1);
        !           159:                                }
        !           160:                                *dn++ = '\\';
        !           161:                                *dn++ = (char)c;
        !           162:                        } else if (!printable(c)) {
        !           163:                                if (dn + 3 >= eom) {
        !           164:                                        errno = EMSGSIZE;
        !           165:                                        return (-1);
        !           166:                                }
        !           167:                                *dn++ = '\\';
        !           168:                                *dn++ = digits[c / 100];
        !           169:                                *dn++ = digits[(c % 100) / 10];
        !           170:                                *dn++ = digits[c % 10];
        !           171:                        } else {
        !           172:                                if (dn >= eom) {
        !           173:                                        errno = EMSGSIZE;
        !           174:                                        return (-1);
        !           175:                                }
        !           176:                                *dn++ = (char)c;
        !           177:                        }
        !           178:                }
        !           179:        }
        !           180:        if (dn == dst) {
        !           181:                if (dn >= eom) {
        !           182:                        errno = EMSGSIZE;
        !           183:                        return (-1);
        !           184:                }
        !           185:                *dn++ = '.';
        !           186:        }
        !           187:        if (dn >= eom) {
        !           188:                errno = EMSGSIZE;
        !           189:                return (-1);
        !           190:        }
        !           191:        *dn++ = '\0';
        !           192:        return (dn - dst);
        !           193: }
        !           194:
        !           195: /*%
        !           196:  *     Convert a ascii string into an encoded domain name as per RFC1035.
        !           197:  *
        !           198:  * return:
        !           199:  *
        !           200:  *\li  -1 if it fails
        !           201:  *\li  1 if string was fully qualified
        !           202:  *\li  0 is string was not fully qualified
        !           203:  *
        !           204:  * notes:
        !           205:  *\li  Enforces label and domain length limits.
        !           206:  */
        !           207:
        !           208: int
        !           209: ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
        !           210: {
        !           211:        u_char *label, *bp, *eom;
        !           212:        int c, n, escaped, e = 0;
        !           213:        char *cp;
        !           214:
        !           215:        escaped = 0;
        !           216:        bp = dst;
        !           217:        eom = dst + dstsiz;
        !           218:        label = bp++;
        !           219:
        !           220:        while ((c = *src++) != 0) {
        !           221:                if (escaped) {
        !           222:                        if (c == '[') { /*%< start a bit string label */
        !           223:                                if ((cp = strchr(src, ']')) == NULL) {
        !           224:                                        errno = EINVAL; /*%< ??? */
        !           225:                                        return(-1);
        !           226:                                }
        !           227:                                if ((e = encode_bitsring(&src, cp + 2,
        !           228:                                                         &label, &bp, eom))
        !           229:                                    != 0) {
        !           230:                                        errno = e;
        !           231:                                        return(-1);
        !           232:                                }
        !           233:                                escaped = 0;
        !           234:                                label = bp++;
        !           235:                                if ((c = *src++) == 0)
        !           236:                                        goto done;
        !           237:                                else if (c != '.') {
        !           238:                                        errno = EINVAL;
        !           239:                                        return(-1);
        !           240:                                }
        !           241:                                continue;
        !           242:                        }
        !           243:                        else if ((cp = strchr(digits, c)) != NULL) {
        !           244:                                n = (cp - digits) * 100;
        !           245:                                if ((c = *src++) == 0 ||
        !           246:                                    (cp = strchr(digits, c)) == NULL) {
        !           247:                                        errno = EMSGSIZE;
        !           248:                                        return (-1);
        !           249:                                }
        !           250:                                n += (cp - digits) * 10;
        !           251:                                if ((c = *src++) == 0 ||
        !           252:                                    (cp = strchr(digits, c)) == NULL) {
        !           253:                                        errno = EMSGSIZE;
        !           254:                                        return (-1);
        !           255:                                }
        !           256:                                n += (cp - digits);
        !           257:                                if (n > 255) {
        !           258:                                        errno = EMSGSIZE;
        !           259:                                        return (-1);
        !           260:                                }
        !           261:                                c = n;
        !           262:                        }
        !           263:                        escaped = 0;
        !           264:                } else if (c == '\\') {
        !           265:                        escaped = 1;
        !           266:                        continue;
        !           267:                } else if (c == '.') {
        !           268:                        c = (bp - label - 1);
        !           269:                        if ((c & NS_CMPRSFLGS) != 0) {  /*%< Label too big. */
        !           270:                                errno = EMSGSIZE;
        !           271:                                return (-1);
        !           272:                        }
        !           273:                        if (label >= eom) {
        !           274:                                errno = EMSGSIZE;
        !           275:                                return (-1);
        !           276:                        }
        !           277:                        *label = c;
        !           278:                        /* Fully qualified ? */
        !           279:                        if (*src == '\0') {
        !           280:                                if (c != 0) {
        !           281:                                        if (bp >= eom) {
        !           282:                                                errno = EMSGSIZE;
        !           283:                                                return (-1);
        !           284:                                        }
        !           285:                                        *bp++ = '\0';
        !           286:                                }
        !           287:                                if ((bp - dst) > MAXCDNAME) {
        !           288:                                        errno = EMSGSIZE;
        !           289:                                        return (-1);
        !           290:                                }
        !           291:                                return (1);
        !           292:                        }
        !           293:                        if (c == 0 || *src == '.') {
        !           294:                                errno = EMSGSIZE;
        !           295:                                return (-1);
        !           296:                        }
        !           297:                        label = bp++;
        !           298:                        continue;
        !           299:                }
        !           300:                if (bp >= eom) {
        !           301:                        errno = EMSGSIZE;
        !           302:                        return (-1);
        !           303:                }
        !           304:                *bp++ = (u_char)c;
        !           305:        }
        !           306:        c = (bp - label - 1);
        !           307:        if ((c & NS_CMPRSFLGS) != 0) {          /*%< Label too big. */
        !           308:                errno = EMSGSIZE;
        !           309:                return (-1);
        !           310:        }
        !           311:   done:
        !           312:        if (label >= eom) {
        !           313:                errno = EMSGSIZE;
        !           314:                return (-1);
        !           315:        }
        !           316:        *label = c;
        !           317:        if (c != 0) {
        !           318:                if (bp >= eom) {
        !           319:                        errno = EMSGSIZE;
        !           320:                        return (-1);
        !           321:                }
        !           322:                *bp++ = 0;
        !           323:        }
        !           324:        if ((bp - dst) > MAXCDNAME) {   /*%< src too big */
        !           325:                errno = EMSGSIZE;
        !           326:                return (-1);
        !           327:        }
        !           328:        return (0);
        !           329: }
        !           330:
        !           331: /*%
        !           332:  *     Convert a network strings labels into all lowercase.
        !           333:  *
        !           334:  * return:
        !           335:  *\li  Number of bytes written to buffer, or -1 (with errno set)
        !           336:  *
        !           337:  * notes:
        !           338:  *\li  Enforces label and domain length limits.
        !           339:  */
        !           340:
        !           341: int
        !           342: ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
        !           343: {
        !           344:        const u_char *cp;
        !           345:        u_char *dn, *eom;
        !           346:        u_char c;
        !           347:        u_int n;
        !           348:        int l;
        !           349:
        !           350:        cp = src;
        !           351:        dn = dst;
        !           352:        eom = dst + dstsiz;
        !           353:
        !           354:        if (dn >= eom) {
        !           355:                errno = EMSGSIZE;
        !           356:                return (-1);
        !           357:        }
        !           358:        while ((n = *cp++) != 0) {
        !           359:                if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
        !           360:                        /* Some kind of compression pointer. */
        !           361:                        errno = EMSGSIZE;
        !           362:                        return (-1);
        !           363:                }
        !           364:                *dn++ = n;
        !           365:                if ((l = labellen(cp - 1)) < 0) {
        !           366:                        errno = EMSGSIZE;
        !           367:                        return (-1);
        !           368:                }
        !           369:                if (dn + l >= eom) {
        !           370:                        errno = EMSGSIZE;
        !           371:                        return (-1);
        !           372:                }
        !           373:                for (; l > 0; l--) {
        !           374:                        c = *cp++;
        !           375:                        if (isupper(c))
        !           376:                                *dn++ = tolower(c);
        !           377:                        else
        !           378:                                *dn++ = c;
        !           379:                }
        !           380:        }
        !           381:        *dn++ = '\0';
        !           382:        return (dn - dst);
        !           383: }
        !           384:
        !           385: /*%
        !           386:  *     Unpack a domain name from a message, source may be compressed.
        !           387:  *
        !           388:  * return:
        !           389:  *\li  -1 if it fails, or consumed octets if it succeeds.
        !           390:  */
        !           391: int
        !           392: ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
        !           393:               u_char *dst, size_t dstsiz)
        !           394: {
        !           395:        const u_char *srcp, *dstlim;
        !           396:        u_char *dstp;
        !           397:        int n, len, checked, l;
        !           398:
        !           399:        len = -1;
        !           400:        checked = 0;
        !           401:        dstp = dst;
        !           402:        srcp = src;
        !           403:        dstlim = dst + dstsiz;
        !           404:        if (srcp < msg || srcp >= eom) {
        !           405:                errno = EMSGSIZE;
        !           406:                return (-1);
        !           407:        }
        !           408:        /* Fetch next label in domain name. */
        !           409:        while ((n = *srcp++) != 0) {
        !           410:                /* Check for indirection. */
        !           411:                switch (n & NS_CMPRSFLGS) {
        !           412:                case 0:
        !           413:                case NS_TYPE_ELT:
        !           414:                        /* Limit checks. */
        !           415:                        if ((l = labellen(srcp - 1)) < 0) {
        !           416:                                errno = EMSGSIZE;
        !           417:                                return(-1);
        !           418:                        }
        !           419:                        if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
        !           420:                                errno = EMSGSIZE;
        !           421:                                return (-1);
        !           422:                        }
        !           423:                        checked += l + 1;
        !           424:                        *dstp++ = n;
        !           425:                        memcpy(dstp, srcp, (size_t)l);
        !           426:                        dstp += l;
        !           427:                        srcp += l;
        !           428:                        break;
        !           429:
        !           430:                case NS_CMPRSFLGS:
        !           431:                        if (srcp >= eom) {
        !           432:                                errno = EMSGSIZE;
        !           433:                                return (-1);
        !           434:                        }
        !           435:                        if (len < 0)
        !           436:                                len = srcp - src + 1;
        !           437:                        srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
        !           438:                        if (srcp < msg || srcp >= eom) {  /*%< Out of range. */
        !           439:                                errno = EMSGSIZE;
        !           440:                                return (-1);
        !           441:                        }
        !           442:                        checked += 2;
        !           443:                        /*
        !           444:                         * Check for loops in the compressed name;
        !           445:                         * if we've looked at the whole message,
        !           446:                         * there must be a loop.
        !           447:                         */
        !           448:                        if (checked >= eom - msg) {
        !           449:                                errno = EMSGSIZE;
        !           450:                                return (-1);
        !           451:                        }
        !           452:                        break;
        !           453:
        !           454:                default:
        !           455:                        errno = EMSGSIZE;
        !           456:                        return (-1);                    /*%< flag error */
        !           457:                }
        !           458:        }
        !           459:        *dstp = '\0';
        !           460:        if (len < 0)
        !           461:                len = srcp - src;
        !           462:        return (len);
        !           463: }
        !           464:
        !           465: /*%
        !           466:  *     Pack domain name 'domain' into 'comp_dn'.
        !           467:  *
        !           468:  * return:
        !           469:  *\li  Size of the compressed name, or -1.
        !           470:  *
        !           471:  * notes:
        !           472:  *\li  'dnptrs' is an array of pointers to previous compressed names.
        !           473:  *\li  dnptrs[0] is a pointer to the beginning of the message. The array
        !           474:  *     ends with NULL.
        !           475:  *\li  'lastdnptr' is a pointer to the end of the array pointed to
        !           476:  *     by 'dnptrs'.
        !           477:  *
        !           478:  * Side effects:
        !           479:  *\li  The list of pointers in dnptrs is updated for labels inserted into
        !           480:  *     the message as we compress the name.  If 'dnptr' is NULL, we don't
        !           481:  *     try to compress names. If 'lastdnptr' is NULL, we don't update the
        !           482:  *     list.
        !           483:  */
        !           484: int
        !           485: ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
        !           486:             const u_char **dnptrs, const u_char **lastdnptr)
        !           487: {
        !           488:        u_char *dstp;
        !           489:        const u_char **cpp, **lpp, *eob, *msg;
        !           490:        const u_char *srcp;
        !           491:        int n, l, first = 1;
        !           492:
        !           493:        srcp = src;
        !           494:        dstp = dst;
        !           495:        eob = dstp + dstsiz;
        !           496:        lpp = cpp = NULL;
        !           497:        if (dnptrs != NULL) {
        !           498:                if ((msg = *dnptrs++) != NULL) {
        !           499:                        for (cpp = dnptrs; *cpp != NULL; cpp++)
        !           500:                                continue;
        !           501:                        lpp = cpp;      /*%< end of list to search */
        !           502:                }
        !           503:        } else
        !           504:                msg = NULL;
        !           505:
        !           506:        /* make sure the domain we are about to add is legal */
        !           507:        l = 0;
        !           508:        do {
        !           509:                int l0;
        !           510:
        !           511:                n = *srcp;
        !           512:                if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
        !           513:                        errno = EMSGSIZE;
        !           514:                        return (-1);
        !           515:                }
        !           516:                if ((l0 = labellen(srcp)) < 0) {
        !           517:                        errno = EINVAL;
        !           518:                        return(-1);
        !           519:                }
        !           520:                l += l0 + 1;
        !           521:                if (l > MAXCDNAME) {
        !           522:                        errno = EMSGSIZE;
        !           523:                        return (-1);
        !           524:                }
        !           525:                srcp += l0 + 1;
        !           526:        } while (n != 0);
        !           527:
        !           528:        /* from here on we need to reset compression pointer array on error */
        !           529:        srcp = src;
        !           530:        do {
        !           531:                /* Look to see if we can use pointers. */
        !           532:                n = *srcp;
        !           533:                if (n != 0 && msg != NULL) {
        !           534:                        l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
        !           535:                                    (const u_char * const *)lpp);
        !           536:                        if (l >= 0) {
        !           537:                                if (dstp + 1 >= eob) {
        !           538:                                        goto cleanup;
        !           539:                                }
        !           540:                                *dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS;
        !           541:                                *dstp++ = l % 256;
        !           542:                                return (dstp - dst);
        !           543:                        }
        !           544:                        /* Not found, save it. */
        !           545:                        if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
        !           546:                            (dstp - msg) < 0x4000 && first) {
        !           547:                                *cpp++ = dstp;
        !           548:                                *cpp = NULL;
        !           549:                                first = 0;
        !           550:                        }
        !           551:                }
        !           552:                /* copy label to buffer */
        !           553:                if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
        !           554:                        /* Should not happen. */
        !           555:                        goto cleanup;
        !           556:                }
        !           557:                n = labellen(srcp);
        !           558:                if (dstp + 1 + n >= eob) {
        !           559:                        goto cleanup;
        !           560:                }
        !           561:                memcpy(dstp, srcp, (size_t)(n + 1));
        !           562:                srcp += n + 1;
        !           563:                dstp += n + 1;
        !           564:        } while (n != 0);
        !           565:
        !           566:        if (dstp > eob) {
        !           567: cleanup:
        !           568:                if (msg != NULL)
        !           569:                        *lpp = NULL;
        !           570:                errno = EMSGSIZE;
        !           571:                return (-1);
        !           572:        }
        !           573:        return (dstp - dst);
        !           574: }
        !           575:
        !           576: /*%
        !           577:  *     Expand compressed domain name to presentation format.
        !           578:  *
        !           579:  * return:
        !           580:  *\li  Number of bytes read out of `src', or -1 (with errno set).
        !           581:  *
        !           582:  * note:
        !           583:  *\li  Root domain returns as "." not "".
        !           584:  */
        !           585: int
        !           586: ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
        !           587:                   char *dst, size_t dstsiz)
        !           588: {
        !           589:        u_char tmp[NS_MAXCDNAME];
        !           590:        int n;
        !           591:
        !           592:        if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
        !           593:                return (-1);
        !           594:        if (ns_name_ntop(tmp, dst, dstsiz) == -1)
        !           595:                return (-1);
        !           596:        return (n);
        !           597: }
        !           598:
        !           599: /*%
        !           600:  *     Compress a domain name into wire format, using compression pointers.
        !           601:  *
        !           602:  * return:
        !           603:  *\li  Number of bytes consumed in `dst' or -1 (with errno set).
        !           604:  *
        !           605:  * notes:
        !           606:  *\li  'dnptrs' is an array of pointers to previous compressed names.
        !           607:  *\li  dnptrs[0] is a pointer to the beginning of the message.
        !           608:  *\li  The list ends with NULL.  'lastdnptr' is a pointer to the end of the
        !           609:  *     array pointed to by 'dnptrs'. Side effect is to update the list of
        !           610:  *     pointers for labels inserted into the message as we compress the name.
        !           611:  *\li  If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
        !           612:  *     is NULL, we don't update the list.
        !           613:  */
        !           614: int
        !           615: ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
        !           616:                 const u_char **dnptrs, const u_char **lastdnptr)
        !           617: {
        !           618:        u_char tmp[NS_MAXCDNAME];
        !           619:
        !           620:        if (ns_name_pton(src, tmp, sizeof tmp) == -1)
        !           621:                return (-1);
        !           622:        return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr));
        !           623: }
        !           624:
        !           625: /*%
        !           626:  * Reset dnptrs so that there are no active references to pointers at or
        !           627:  * after src.
        !           628:  */
        !           629: void
        !           630: ns_name_rollback(const u_char *src, const u_char **dnptrs,
        !           631:                 const u_char **lastdnptr)
        !           632: {
        !           633:        while (dnptrs < lastdnptr && *dnptrs != NULL) {
        !           634:                if (*dnptrs >= src) {
        !           635:                        *dnptrs = NULL;
        !           636:                        break;
        !           637:                }
        !           638:                dnptrs++;
        !           639:        }
        !           640: }
        !           641:
        !           642: /*%
        !           643:  *     Advance *ptrptr to skip over the compressed name it points at.
        !           644:  *
        !           645:  * return:
        !           646:  *\li  0 on success, -1 (with errno set) on failure.
        !           647:  */
        !           648: int
        !           649: ns_name_skip(const u_char **ptrptr, const u_char *eom)
        !           650: {
        !           651:        const u_char *cp;
        !           652:        u_int n;
        !           653:        int l;
        !           654:
        !           655:        cp = *ptrptr;
        !           656:        while (cp < eom && (n = *cp++) != 0) {
        !           657:                /* Check for indirection. */
        !           658:                switch (n & NS_CMPRSFLGS) {
        !           659:                case 0:                 /*%< normal case, n == len */
        !           660:                        cp += n;
        !           661:                        continue;
        !           662:                case NS_TYPE_ELT: /*%< EDNS0 extended label */
        !           663:                        if ((l = labellen(cp - 1)) < 0) {
        !           664:                                errno = EMSGSIZE; /*%< XXX */
        !           665:                                return(-1);
        !           666:                        }
        !           667:                        cp += l;
        !           668:                        continue;
        !           669:                case NS_CMPRSFLGS:      /*%< indirection */
        !           670:                        cp++;
        !           671:                        break;
        !           672:                default:                /*%< illegal type */
        !           673:                        errno = EMSGSIZE;
        !           674:                        return (-1);
        !           675:                }
        !           676:                break;
        !           677:        }
        !           678:        if (cp > eom) {
        !           679:                errno = EMSGSIZE;
        !           680:                return (-1);
        !           681:        }
        !           682:        *ptrptr = cp;
        !           683:        return (0);
        !           684: }
        !           685:
        !           686: /* Private. */
        !           687:
        !           688: /*%
        !           689:  *     Thinking in noninternationalized USASCII (per the DNS spec),
        !           690:  *     is this characted special ("in need of quoting") ?
        !           691:  *
        !           692:  * return:
        !           693:  *\li  boolean.
        !           694:  */
        !           695: static int
        !           696: special(int ch) {
        !           697:        switch (ch) {
        !           698:        case 0x22: /*%< '"' */
        !           699:        case 0x2E: /*%< '.' */
        !           700:        case 0x3B: /*%< ';' */
        !           701:        case 0x5C: /*%< '\\' */
        !           702:        case 0x28: /*%< '(' */
        !           703:        case 0x29: /*%< ')' */
        !           704:        /* Special modifiers in zone files. */
        !           705:        case 0x40: /*%< '@' */
        !           706:        case 0x24: /*%< '$' */
        !           707:                return (1);
        !           708:        default:
        !           709:                return (0);
        !           710:        }
        !           711: }
        !           712:
        !           713: /*%
        !           714:  *     Thinking in noninternationalized USASCII (per the DNS spec),
        !           715:  *     is this character visible and not a space when printed ?
        !           716:  *
        !           717:  * return:
        !           718:  *\li  boolean.
        !           719:  */
        !           720: static int
        !           721: printable(int ch) {
        !           722:        return (ch > 0x20 && ch < 0x7f);
        !           723: }
        !           724:
        !           725: /*%
        !           726:  *     Thinking in noninternationalized USASCII (per the DNS spec),
        !           727:  *     convert this character to lower case if it's upper case.
        !           728:  */
        !           729: static int
        !           730: mklower(int ch) {
        !           731:        if (ch >= 0x41 && ch <= 0x5A)
        !           732:                return (ch + 0x20);
        !           733:        return (ch);
        !           734: }
        !           735:
        !           736: /*%
        !           737:  *     Search for the counted-label name in an array of compressed names.
        !           738:  *
        !           739:  * return:
        !           740:  *\li  offset from msg if found, or -1.
        !           741:  *
        !           742:  * notes:
        !           743:  *\li  dnptrs is the pointer to the first name on the list,
        !           744:  *\li  not the pointer to the start of the message.
        !           745:  */
        !           746: static int
        !           747: dn_find(const u_char *domain, const u_char *msg,
        !           748:        const u_char * const *dnptrs,
        !           749:        const u_char * const *lastdnptr)
        !           750: {
        !           751:        const u_char *dn, *cp, *sp;
        !           752:        const u_char * const *cpp;
        !           753:        u_int n;
        !           754:
        !           755:        for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
        !           756:                sp = *cpp;
        !           757:                /*
        !           758:                 * terminate search on:
        !           759:                 * root label
        !           760:                 * compression pointer
        !           761:                 * unusable offset
        !           762:                 */
        !           763:                while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
        !           764:                       (sp - msg) < 0x4000) {
        !           765:                        dn = domain;
        !           766:                        cp = sp;
        !           767:                        while ((n = *cp++) != 0) {
        !           768:                                /*
        !           769:                                 * check for indirection
        !           770:                                 */
        !           771:                                switch (n & NS_CMPRSFLGS) {
        !           772:                                case 0:         /*%< normal case, n == len */
        !           773:                                        n = labellen(cp - 1); /*%< XXX */
        !           774:                                        if (n != *dn++)
        !           775:                                                goto next;
        !           776:
        !           777:                                        for (; n > 0; n--)
        !           778:                                                if (mklower(*dn++) !=
        !           779:                                                    mklower(*cp++))
        !           780:                                                        goto next;
        !           781:                                        /* Is next root for both ? */
        !           782:                                        if (*dn == '\0' && *cp == '\0')
        !           783:                                                return (sp - msg);
        !           784:                                        if (*dn)
        !           785:                                                continue;
        !           786:                                        goto next;
        !           787:                                case NS_CMPRSFLGS:      /*%< indirection */
        !           788:                                        cp = msg + (((n & 0x3f) << 8) | *cp);
        !           789:                                        break;
        !           790:
        !           791:                                default:        /*%< illegal type */
        !           792:                                        errno = EMSGSIZE;
        !           793:                                        return (-1);
        !           794:                                }
        !           795:                        }
        !           796:  next: ;
        !           797:                        sp += *sp + 1;
        !           798:                }
        !           799:        }
        !           800:        errno = ENOENT;
        !           801:        return (-1);
        !           802: }
        !           803:
        !           804: static int
        !           805: decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
        !           806: {
        !           807:        const unsigned char *cp = *cpp;
        !           808:        char *beg = dn, tc;
        !           809:        int b, blen, plen, i;
        !           810:
        !           811:        if ((blen = (*cp & 0xff)) == 0)
        !           812:                blen = 256;
        !           813:        plen = (blen + 3) / 4;
        !           814:        plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
        !           815:        if (dn + plen >= eom)
        !           816:                return(-1);
        !           817:
        !           818:        cp++;
        !           819:        i = SPRINTF((dn, "\\[x"));
        !           820:        if (i < 0)
        !           821:                return (-1);
        !           822:        dn += i;
        !           823:        for (b = blen; b > 7; b -= 8, cp++) {
        !           824:                i = SPRINTF((dn, "%02x", *cp & 0xff));
        !           825:                if (i < 0)
        !           826:                        return (-1);
        !           827:                dn += i;
        !           828:        }
        !           829:        if (b > 4) {
        !           830:                tc = *cp++;
        !           831:                i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
        !           832:                if (i < 0)
        !           833:                        return (-1);
        !           834:                dn += i;
        !           835:        } else if (b > 0) {
        !           836:                tc = *cp++;
        !           837:                i = SPRINTF((dn, "%1x",
        !           838:                               (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b))));
        !           839:                if (i < 0)
        !           840:                        return (-1);
        !           841:                dn += i;
        !           842:        }
        !           843:        i = SPRINTF((dn, "/%d]", blen));
        !           844:        if (i < 0)
        !           845:                return (-1);
        !           846:        dn += i;
        !           847:
        !           848:        *cpp = cp;
        !           849:        return(dn - beg);
        !           850: }
        !           851:
        !           852: static int
        !           853: encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
        !           854:                unsigned char ** dst, unsigned const char *eom)
        !           855: {
        !           856:        int afterslash = 0;
        !           857:        const char *cp = *bp;
        !           858:        unsigned char *tp;
        !           859:        char c;
        !           860:        const char *beg_blen;
        !           861:        char *end_blen = NULL;
        !           862:        int value = 0, count = 0, tbcount = 0, blen = 0;
        !           863:
        !           864:        beg_blen = end_blen = NULL;
        !           865:
        !           866:        /* a bitstring must contain at least 2 characters */
        !           867:        if (end - cp < 2)
        !           868:                return(EINVAL);
        !           869:
        !           870:        /* XXX: currently, only hex strings are supported */
        !           871:        if (*cp++ != 'x')
        !           872:                return(EINVAL);
        !           873:        if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */
        !           874:                return(EINVAL);
        !           875:
        !           876:        for (tp = *dst + 1; cp < end && tp < eom; cp++) {
        !           877:                switch((c = *cp)) {
        !           878:                case ']':       /*%< end of the bitstring */
        !           879:                        if (afterslash) {
        !           880:                                if (beg_blen == NULL)
        !           881:                                        return(EINVAL);
        !           882:                                blen = (int)strtol(beg_blen, &end_blen, 10);
        !           883:                                if (*end_blen != ']')
        !           884:                                        return(EINVAL);
        !           885:                        }
        !           886:                        if (count)
        !           887:                                *tp++ = ((value << 4) & 0xff);
        !           888:                        cp++;   /*%< skip ']' */
        !           889:                        goto done;
        !           890:                case '/':
        !           891:                        afterslash = 1;
        !           892:                        break;
        !           893:                default:
        !           894:                        if (afterslash) {
        !           895:                                if (!isdigit(c&0xff))
        !           896:                                        return(EINVAL);
        !           897:                                if (beg_blen == NULL) {
        !           898:
        !           899:                                        if (c == '0') {
        !           900:                                                /* blen never begings with 0 */
        !           901:                                                return(EINVAL);
        !           902:                                        }
        !           903:                                        beg_blen = cp;
        !           904:                                }
        !           905:                        } else {
        !           906:                                if (!isxdigit(c&0xff))
        !           907:                                        return(EINVAL);
        !           908:                                value <<= 4;
        !           909:                                value += digitvalue[(int)c];
        !           910:                                count += 4;
        !           911:                                tbcount += 4;
        !           912:                                if (tbcount > 256)
        !           913:                                        return(EINVAL);
        !           914:                                if (count == 8) {
        !           915:                                        *tp++ = value;
        !           916:                                        count = 0;
        !           917:                                }
        !           918:                        }
        !           919:                        break;
        !           920:                }
        !           921:        }
        !           922:   done:
        !           923:        if (cp >= end || tp >= eom)
        !           924:                return(EMSGSIZE);
        !           925:
        !           926:        /*
        !           927:         * bit length validation:
        !           928:         * If a <length> is present, the number of digits in the <bit-data>
        !           929:         * MUST be just sufficient to contain the number of bits specified
        !           930:         * by the <length>. If there are insignificant bits in a final
        !           931:         * hexadecimal or octal digit, they MUST be zero.
        !           932:         * RFC2673, Section 3.2.
        !           933:         */
        !           934:        if (blen > 0) {
        !           935:                int traillen;
        !           936:
        !           937:                if (((blen + 3) & ~3) != tbcount)
        !           938:                        return(EINVAL);
        !           939:                traillen = tbcount - blen; /*%< between 0 and 3 */
        !           940:                if (((value << (8 - traillen)) & 0xff) != 0)
        !           941:                        return(EINVAL);
        !           942:        }
        !           943:        else
        !           944:                blen = tbcount;
        !           945:        if (blen == 256)
        !           946:                blen = 0;
        !           947:
        !           948:        /* encode the type and the significant bit fields */
        !           949:        **labelp = DNS_LABELTYPE_BITSTRING;
        !           950:        **dst = blen;
        !           951:
        !           952:        *bp = cp;
        !           953:        *dst = tp;
        !           954:
        !           955:        return(0);
        !           956: }
        !           957:
        !           958: static int
        !           959: labellen(const u_char *lp)
        !           960: {
        !           961:        int bitlen;
        !           962:        u_char l = *lp;
        !           963:
        !           964:        if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
        !           965:                /* should be avoided by the caller */
        !           966:                return(-1);
        !           967:        }
        !           968:
        !           969:        if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
        !           970:                if (l == DNS_LABELTYPE_BITSTRING) {
        !           971:                        if ((bitlen = *(lp + 1)) == 0)
        !           972:                                bitlen = 256;
        !           973:                        return((bitlen + 7 ) / 8 + 1);
        !           974:                }
        !           975:                return(-1);     /*%< unknwon ELT */
        !           976:        }
        !           977:        return(l);
        !           978: }
        !           979:
        !           980: /*! \file */

CVSweb <webmaster@jp.NetBSD.org>