[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.10.1

1.6.10.1! riz         1: /*     $NetBSD: ns_name.c,v 1.8 2009/04/12 19:43:37 christos Exp $     */
1.1       christos    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:
1.2       christos   20: #include <sys/cdefs.h>
1.1       christos   21: #ifndef lint
1.2       christos   22: #ifdef notdef
1.6.10.1! riz        23: static const char rcsid[] = "Id: ns_name.c,v 1.11 2009/01/23 19:59:16 each Exp";
1.2       christos   24: #else
1.6.10.1! riz        25: __RCSID("$NetBSD: ns_name.c,v 1.8 2009/04/12 19:43:37 christos Exp $");
1.2       christos   26: #endif
1.1       christos   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:
1.4       christos   51: #define NS_TYPE_ELT                    0x40 /*%< EDNS0 extended label type */
1.1       christos   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 *,
1.3       christos   85:                                        unsigned char **, unsigned char **,
                     86:                                        unsigned const char *);
1.1       christos   87: static int             labellen(const u_char *);
1.3       christos   88: static int             decode_bitstring(const unsigned char **,
                     89:                                         char *, const char *);
1.1       christos   90:
                     91: /* Public. */
                     92:
1.4       christos   93: /*%
1.1       christos   94:  *     Convert an encoded domain name to printable ascii as per RFC1035.
1.4       christos   95:
1.1       christos   96:  * return:
1.4       christos   97:  *\li  Number of bytes written to buffer, or -1 (with errno set)
                     98:  *
1.1       christos   99:  * notes:
1.4       christos  100:  *\li  The root is returned as "."
                    101:  *\li  All other domains are returned in non absolute form
1.1       christos  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) {
1.4       christos  130:                        errno = EMSGSIZE; /*%< XXX */
1.6.10.1! riz       131:                        return (-1);
1.1       christos  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;
1.6.10.1! riz       143:                                return (-1);
1.1       christos  144:                        }
1.3       christos  145:                        if ((m = decode_bitstring(&cp, dn, eom)) < 0)
1.1       christos  146:                        {
                    147:                                errno = EMSGSIZE;
1.6.10.1! riz       148:                                return (-1);
1.1       christos  149:                        }
                    150:                        dn += m;
                    151:                        continue;
                    152:                }
1.2       christos  153:                for (; l > 0; l--) {
1.1       christos  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:
1.4       christos  195: /*%
1.1       christos  196:  *     Convert a ascii string into an encoded domain name as per RFC1035.
1.4       christos  197:  *
1.1       christos  198:  * return:
1.4       christos  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:  *
1.1       christos  204:  * notes:
1.4       christos  205:  *\li  Enforces label and domain length limits.
1.1       christos  206:  */
1.6.10.1! riz       207: int
        !           208: ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
        !           209:        return (ns_name_pton2(src, dst, dstsiz, NULL));
        !           210: }
1.1       christos  211:
1.6.10.1! riz       212: /*
        !           213:  * ns_name_pton2(src, dst, dstsiz, *dstlen)
        !           214:  *     Convert a ascii string into an encoded domain name as per RFC1035.
        !           215:  * return:
        !           216:  *     -1 if it fails
        !           217:  *     1 if string was fully qualified
        !           218:  *     0 is string was not fully qualified
        !           219:  * side effects:
        !           220:  *     fills in *dstlen (if non-NULL)
        !           221:  * notes:
        !           222:  *     Enforces label and domain length limits.
        !           223:  */
1.1       christos  224: int
1.6.10.1! riz       225: ns_name_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen) {
1.1       christos  226:        u_char *label, *bp, *eom;
                    227:        int c, n, escaped, e = 0;
                    228:        char *cp;
                    229:
                    230:        escaped = 0;
                    231:        bp = dst;
                    232:        eom = dst + dstsiz;
                    233:        label = bp++;
                    234:
                    235:        while ((c = *src++) != 0) {
                    236:                if (escaped) {
1.4       christos  237:                        if (c == '[') { /*%< start a bit string label */
1.1       christos  238:                                if ((cp = strchr(src, ']')) == NULL) {
1.4       christos  239:                                        errno = EINVAL; /*%< ??? */
1.6.10.1! riz       240:                                        return (-1);
1.1       christos  241:                                }
1.3       christos  242:                                if ((e = encode_bitsring(&src, cp + 2,
                    243:                                                         &label, &bp, eom))
1.1       christos  244:                                    != 0) {
                    245:                                        errno = e;
1.6.10.1! riz       246:                                        return (-1);
1.1       christos  247:                                }
                    248:                                escaped = 0;
                    249:                                label = bp++;
                    250:                                if ((c = *src++) == 0)
                    251:                                        goto done;
                    252:                                else if (c != '.') {
                    253:                                        errno = EINVAL;
1.6.10.1! riz       254:                                        return  (-1);
1.1       christos  255:                                }
                    256:                                continue;
                    257:                        }
                    258:                        else if ((cp = strchr(digits, c)) != NULL) {
                    259:                                n = (cp - digits) * 100;
                    260:                                if ((c = *src++) == 0 ||
                    261:                                    (cp = strchr(digits, c)) == NULL) {
                    262:                                        errno = EMSGSIZE;
                    263:                                        return (-1);
                    264:                                }
                    265:                                n += (cp - digits) * 10;
                    266:                                if ((c = *src++) == 0 ||
                    267:                                    (cp = strchr(digits, c)) == NULL) {
                    268:                                        errno = EMSGSIZE;
                    269:                                        return (-1);
                    270:                                }
                    271:                                n += (cp - digits);
                    272:                                if (n > 255) {
                    273:                                        errno = EMSGSIZE;
                    274:                                        return (-1);
                    275:                                }
                    276:                                c = n;
                    277:                        }
                    278:                        escaped = 0;
                    279:                } else if (c == '\\') {
                    280:                        escaped = 1;
                    281:                        continue;
                    282:                } else if (c == '.') {
                    283:                        c = (bp - label - 1);
1.4       christos  284:                        if ((c & NS_CMPRSFLGS) != 0) {  /*%< Label too big. */
1.1       christos  285:                                errno = EMSGSIZE;
                    286:                                return (-1);
                    287:                        }
                    288:                        if (label >= eom) {
                    289:                                errno = EMSGSIZE;
                    290:                                return (-1);
                    291:                        }
                    292:                        *label = c;
                    293:                        /* Fully qualified ? */
                    294:                        if (*src == '\0') {
                    295:                                if (c != 0) {
                    296:                                        if (bp >= eom) {
                    297:                                                errno = EMSGSIZE;
                    298:                                                return (-1);
                    299:                                        }
                    300:                                        *bp++ = '\0';
                    301:                                }
                    302:                                if ((bp - dst) > MAXCDNAME) {
                    303:                                        errno = EMSGSIZE;
                    304:                                        return (-1);
                    305:                                }
1.6.10.1! riz       306:                                if (dstlen != NULL)
        !           307:                                        *dstlen = (bp - dst);
1.1       christos  308:                                return (1);
                    309:                        }
                    310:                        if (c == 0 || *src == '.') {
                    311:                                errno = EMSGSIZE;
                    312:                                return (-1);
                    313:                        }
                    314:                        label = bp++;
                    315:                        continue;
                    316:                }
                    317:                if (bp >= eom) {
                    318:                        errno = EMSGSIZE;
                    319:                        return (-1);
                    320:                }
                    321:                *bp++ = (u_char)c;
                    322:        }
                    323:        c = (bp - label - 1);
1.4       christos  324:        if ((c & NS_CMPRSFLGS) != 0) {          /*%< Label too big. */
1.1       christos  325:                errno = EMSGSIZE;
                    326:                return (-1);
                    327:        }
                    328:   done:
                    329:        if (label >= eom) {
                    330:                errno = EMSGSIZE;
                    331:                return (-1);
                    332:        }
                    333:        *label = c;
                    334:        if (c != 0) {
                    335:                if (bp >= eom) {
                    336:                        errno = EMSGSIZE;
                    337:                        return (-1);
                    338:                }
                    339:                *bp++ = 0;
                    340:        }
1.4       christos  341:        if ((bp - dst) > MAXCDNAME) {   /*%< src too big */
1.1       christos  342:                errno = EMSGSIZE;
                    343:                return (-1);
                    344:        }
1.6.10.1! riz       345:        if (dstlen != NULL)
        !           346:                *dstlen = (bp - dst);
1.1       christos  347:        return (0);
                    348: }
                    349:
1.4       christos  350: /*%
1.1       christos  351:  *     Convert a network strings labels into all lowercase.
1.4       christos  352:  *
1.1       christos  353:  * return:
1.4       christos  354:  *\li  Number of bytes written to buffer, or -1 (with errno set)
                    355:  *
1.1       christos  356:  * notes:
1.4       christos  357:  *\li  Enforces label and domain length limits.
1.1       christos  358:  */
                    359:
                    360: int
                    361: ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
                    362: {
                    363:        const u_char *cp;
                    364:        u_char *dn, *eom;
                    365:        u_char c;
                    366:        u_int n;
                    367:        int l;
                    368:
                    369:        cp = src;
                    370:        dn = dst;
                    371:        eom = dst + dstsiz;
                    372:
                    373:        if (dn >= eom) {
                    374:                errno = EMSGSIZE;
                    375:                return (-1);
                    376:        }
                    377:        while ((n = *cp++) != 0) {
                    378:                if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
                    379:                        /* Some kind of compression pointer. */
                    380:                        errno = EMSGSIZE;
                    381:                        return (-1);
                    382:                }
                    383:                *dn++ = n;
                    384:                if ((l = labellen(cp - 1)) < 0) {
                    385:                        errno = EMSGSIZE;
                    386:                        return (-1);
                    387:                }
                    388:                if (dn + l >= eom) {
                    389:                        errno = EMSGSIZE;
                    390:                        return (-1);
                    391:                }
1.2       christos  392:                for (; l > 0; l--) {
1.1       christos  393:                        c = *cp++;
1.6.10.1! riz       394:                        if (isascii(c) && isupper(c))
1.1       christos  395:                                *dn++ = tolower(c);
                    396:                        else
                    397:                                *dn++ = c;
                    398:                }
                    399:        }
                    400:        *dn++ = '\0';
                    401:        return (dn - dst);
                    402: }
                    403:
1.4       christos  404: /*%
1.1       christos  405:  *     Unpack a domain name from a message, source may be compressed.
1.4       christos  406:  *
1.1       christos  407:  * return:
1.4       christos  408:  *\li  -1 if it fails, or consumed octets if it succeeds.
1.1       christos  409:  */
                    410: int
                    411: ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
                    412:               u_char *dst, size_t dstsiz)
                    413: {
1.6.10.1! riz       414:        return (ns_name_unpack2(msg, eom, src, dst, dstsiz, NULL));
        !           415: }
        !           416:
        !           417: /*
        !           418:  * ns_name_unpack2(msg, eom, src, dst, dstsiz, *dstlen)
        !           419:  *     Unpack a domain name from a message, source may be compressed.
        !           420:  * return:
        !           421:  *     -1 if it fails, or consumed octets if it succeeds.
        !           422:  * side effect:
        !           423:  *     fills in *dstlen (if non-NULL).
        !           424:  */
        !           425: int
        !           426: ns_name_unpack2(const u_char *msg, const u_char *eom, const u_char *src,
        !           427:                u_char *dst, size_t dstsiz, size_t *dstlen)
        !           428: {
1.1       christos  429:        const u_char *srcp, *dstlim;
                    430:        u_char *dstp;
                    431:        int n, len, checked, l;
                    432:
                    433:        len = -1;
                    434:        checked = 0;
                    435:        dstp = dst;
                    436:        srcp = src;
                    437:        dstlim = dst + dstsiz;
                    438:        if (srcp < msg || srcp >= eom) {
                    439:                errno = EMSGSIZE;
                    440:                return (-1);
                    441:        }
                    442:        /* Fetch next label in domain name. */
                    443:        while ((n = *srcp++) != 0) {
                    444:                /* Check for indirection. */
                    445:                switch (n & NS_CMPRSFLGS) {
                    446:                case 0:
                    447:                case NS_TYPE_ELT:
                    448:                        /* Limit checks. */
                    449:                        if ((l = labellen(srcp - 1)) < 0) {
                    450:                                errno = EMSGSIZE;
1.6.10.1! riz       451:                                return (-1);
1.1       christos  452:                        }
                    453:                        if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
                    454:                                errno = EMSGSIZE;
                    455:                                return (-1);
                    456:                        }
                    457:                        checked += l + 1;
                    458:                        *dstp++ = n;
1.2       christos  459:                        memcpy(dstp, srcp, (size_t)l);
1.1       christos  460:                        dstp += l;
                    461:                        srcp += l;
                    462:                        break;
                    463:
                    464:                case NS_CMPRSFLGS:
                    465:                        if (srcp >= eom) {
                    466:                                errno = EMSGSIZE;
                    467:                                return (-1);
                    468:                        }
                    469:                        if (len < 0)
                    470:                                len = srcp - src + 1;
                    471:                        srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
1.4       christos  472:                        if (srcp < msg || srcp >= eom) {  /*%< Out of range. */
1.1       christos  473:                                errno = EMSGSIZE;
                    474:                                return (-1);
                    475:                        }
                    476:                        checked += 2;
                    477:                        /*
                    478:                         * Check for loops in the compressed name;
                    479:                         * if we've looked at the whole message,
                    480:                         * there must be a loop.
                    481:                         */
                    482:                        if (checked >= eom - msg) {
                    483:                                errno = EMSGSIZE;
                    484:                                return (-1);
                    485:                        }
                    486:                        break;
                    487:
                    488:                default:
                    489:                        errno = EMSGSIZE;
1.4       christos  490:                        return (-1);                    /*%< flag error */
1.1       christos  491:                }
                    492:        }
1.6.10.1! riz       493:        *dstp++ = 0;
        !           494:        if (dstlen != NULL)
        !           495:                *dstlen = dstp - dst;
1.1       christos  496:        if (len < 0)
                    497:                len = srcp - src;
                    498:        return (len);
                    499: }
                    500:
1.4       christos  501: /*%
1.1       christos  502:  *     Pack domain name 'domain' into 'comp_dn'.
1.4       christos  503:  *
1.1       christos  504:  * return:
1.4       christos  505:  *\li  Size of the compressed name, or -1.
                    506:  *
1.1       christos  507:  * notes:
1.4       christos  508:  *\li  'dnptrs' is an array of pointers to previous compressed names.
                    509:  *\li  dnptrs[0] is a pointer to the beginning of the message. The array
1.1       christos  510:  *     ends with NULL.
1.4       christos  511:  *\li  'lastdnptr' is a pointer to the end of the array pointed to
1.1       christos  512:  *     by 'dnptrs'.
1.4       christos  513:  *
1.1       christos  514:  * Side effects:
1.4       christos  515:  *\li  The list of pointers in dnptrs is updated for labels inserted into
1.1       christos  516:  *     the message as we compress the name.  If 'dnptr' is NULL, we don't
                    517:  *     try to compress names. If 'lastdnptr' is NULL, we don't update the
                    518:  *     list.
                    519:  */
                    520: int
                    521: ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
                    522:             const u_char **dnptrs, const u_char **lastdnptr)
                    523: {
                    524:        u_char *dstp;
                    525:        const u_char **cpp, **lpp, *eob, *msg;
                    526:        const u_char *srcp;
                    527:        int n, l, first = 1;
                    528:
                    529:        srcp = src;
                    530:        dstp = dst;
                    531:        eob = dstp + dstsiz;
                    532:        lpp = cpp = NULL;
                    533:        if (dnptrs != NULL) {
                    534:                if ((msg = *dnptrs++) != NULL) {
                    535:                        for (cpp = dnptrs; *cpp != NULL; cpp++)
1.4       christos  536:                                continue;
                    537:                        lpp = cpp;      /*%< end of list to search */
1.1       christos  538:                }
                    539:        } else
                    540:                msg = NULL;
                    541:
                    542:        /* make sure the domain we are about to add is legal */
                    543:        l = 0;
                    544:        do {
                    545:                int l0;
                    546:
                    547:                n = *srcp;
                    548:                if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
                    549:                        errno = EMSGSIZE;
                    550:                        return (-1);
                    551:                }
                    552:                if ((l0 = labellen(srcp)) < 0) {
                    553:                        errno = EINVAL;
1.6.10.1! riz       554:                        return (-1);
1.1       christos  555:                }
                    556:                l += l0 + 1;
                    557:                if (l > MAXCDNAME) {
                    558:                        errno = EMSGSIZE;
                    559:                        return (-1);
                    560:                }
                    561:                srcp += l0 + 1;
                    562:        } while (n != 0);
                    563:
                    564:        /* from here on we need to reset compression pointer array on error */
                    565:        srcp = src;
                    566:        do {
                    567:                /* Look to see if we can use pointers. */
                    568:                n = *srcp;
                    569:                if (n != 0 && msg != NULL) {
                    570:                        l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
                    571:                                    (const u_char * const *)lpp);
                    572:                        if (l >= 0) {
                    573:                                if (dstp + 1 >= eob) {
                    574:                                        goto cleanup;
                    575:                                }
1.2       christos  576:                                *dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS;
1.1       christos  577:                                *dstp++ = l % 256;
                    578:                                return (dstp - dst);
                    579:                        }
                    580:                        /* Not found, save it. */
                    581:                        if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
                    582:                            (dstp - msg) < 0x4000 && first) {
                    583:                                *cpp++ = dstp;
                    584:                                *cpp = NULL;
                    585:                                first = 0;
                    586:                        }
                    587:                }
                    588:                /* copy label to buffer */
                    589:                if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
                    590:                        /* Should not happen. */
                    591:                        goto cleanup;
                    592:                }
                    593:                n = labellen(srcp);
                    594:                if (dstp + 1 + n >= eob) {
                    595:                        goto cleanup;
                    596:                }
1.2       christos  597:                memcpy(dstp, srcp, (size_t)(n + 1));
1.1       christos  598:                srcp += n + 1;
                    599:                dstp += n + 1;
                    600:        } while (n != 0);
                    601:
                    602:        if (dstp > eob) {
                    603: cleanup:
                    604:                if (msg != NULL)
                    605:                        *lpp = NULL;
                    606:                errno = EMSGSIZE;
                    607:                return (-1);
                    608:        }
                    609:        return (dstp - dst);
                    610: }
                    611:
1.4       christos  612: /*%
1.1       christos  613:  *     Expand compressed domain name to presentation format.
1.4       christos  614:  *
1.1       christos  615:  * return:
1.4       christos  616:  *\li  Number of bytes read out of `src', or -1 (with errno set).
                    617:  *
1.1       christos  618:  * note:
1.4       christos  619:  *\li  Root domain returns as "." not "".
1.1       christos  620:  */
                    621: int
                    622: ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
                    623:                   char *dst, size_t dstsiz)
                    624: {
                    625:        u_char tmp[NS_MAXCDNAME];
                    626:        int n;
                    627:
                    628:        if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
                    629:                return (-1);
                    630:        if (ns_name_ntop(tmp, dst, dstsiz) == -1)
                    631:                return (-1);
                    632:        return (n);
                    633: }
                    634:
1.4       christos  635: /*%
1.1       christos  636:  *     Compress a domain name into wire format, using compression pointers.
1.4       christos  637:  *
1.1       christos  638:  * return:
1.4       christos  639:  *\li  Number of bytes consumed in `dst' or -1 (with errno set).
                    640:  *
1.1       christos  641:  * notes:
1.4       christos  642:  *\li  'dnptrs' is an array of pointers to previous compressed names.
                    643:  *\li  dnptrs[0] is a pointer to the beginning of the message.
                    644:  *\li  The list ends with NULL.  'lastdnptr' is a pointer to the end of the
1.1       christos  645:  *     array pointed to by 'dnptrs'. Side effect is to update the list of
                    646:  *     pointers for labels inserted into the message as we compress the name.
1.4       christos  647:  *\li  If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
1.1       christos  648:  *     is NULL, we don't update the list.
                    649:  */
                    650: int
                    651: ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
                    652:                 const u_char **dnptrs, const u_char **lastdnptr)
                    653: {
                    654:        u_char tmp[NS_MAXCDNAME];
                    655:
                    656:        if (ns_name_pton(src, tmp, sizeof tmp) == -1)
                    657:                return (-1);
1.2       christos  658:        return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr));
1.1       christos  659: }
                    660:
1.4       christos  661: /*%
1.1       christos  662:  * Reset dnptrs so that there are no active references to pointers at or
                    663:  * after src.
                    664:  */
                    665: void
                    666: ns_name_rollback(const u_char *src, const u_char **dnptrs,
                    667:                 const u_char **lastdnptr)
                    668: {
                    669:        while (dnptrs < lastdnptr && *dnptrs != NULL) {
                    670:                if (*dnptrs >= src) {
                    671:                        *dnptrs = NULL;
                    672:                        break;
                    673:                }
                    674:                dnptrs++;
                    675:        }
                    676: }
                    677:
1.4       christos  678: /*%
1.1       christos  679:  *     Advance *ptrptr to skip over the compressed name it points at.
1.4       christos  680:  *
1.1       christos  681:  * return:
1.4       christos  682:  *\li  0 on success, -1 (with errno set) on failure.
1.1       christos  683:  */
                    684: int
                    685: ns_name_skip(const u_char **ptrptr, const u_char *eom)
                    686: {
                    687:        const u_char *cp;
                    688:        u_int n;
                    689:        int l;
                    690:
                    691:        cp = *ptrptr;
                    692:        while (cp < eom && (n = *cp++) != 0) {
                    693:                /* Check for indirection. */
                    694:                switch (n & NS_CMPRSFLGS) {
1.4       christos  695:                case 0:                 /*%< normal case, n == len */
1.1       christos  696:                        cp += n;
                    697:                        continue;
1.4       christos  698:                case NS_TYPE_ELT: /*%< EDNS0 extended label */
1.1       christos  699:                        if ((l = labellen(cp - 1)) < 0) {
1.4       christos  700:                                errno = EMSGSIZE; /*%< XXX */
1.6.10.1! riz       701:                                return (-1);
1.1       christos  702:                        }
                    703:                        cp += l;
                    704:                        continue;
1.4       christos  705:                case NS_CMPRSFLGS:      /*%< indirection */
1.1       christos  706:                        cp++;
                    707:                        break;
1.4       christos  708:                default:                /*%< illegal type */
1.1       christos  709:                        errno = EMSGSIZE;
                    710:                        return (-1);
                    711:                }
                    712:                break;
                    713:        }
                    714:        if (cp > eom) {
                    715:                errno = EMSGSIZE;
                    716:                return (-1);
                    717:        }
                    718:        *ptrptr = cp;
                    719:        return (0);
                    720: }
                    721:
1.6.10.1! riz       722: /* Find the number of octets an nname takes up, including the root label.
        !           723:  * (This is basically ns_name_skip() without compression-pointer support.)
        !           724:  * ((NOTE: can only return zero if passed-in namesiz argument is zero.))
        !           725:  */
        !           726: ssize_t
        !           727: ns_name_length(ns_nname_ct nname, size_t namesiz) {
        !           728:        ns_nname_ct orig = nname;
        !           729:        u_int n;
        !           730:
        !           731:        while (namesiz-- > 0 && (n = *nname++) != 0) {
        !           732:                if ((n & NS_CMPRSFLGS) != 0) {
        !           733:                        errno = EISDIR;
        !           734:                        return (-1);
        !           735:                }
        !           736:                if (n > namesiz) {
        !           737:                        errno = EMSGSIZE;
        !           738:                        return (-1);
        !           739:                }
        !           740:                nname += n;
        !           741:                namesiz -= n;
        !           742:        }
        !           743:        return (nname - orig);
        !           744: }
        !           745:
        !           746: /* Compare two nname's for equality.  Return -1 on error (setting errno).
        !           747:  */
        !           748: int
        !           749: ns_name_eq(ns_nname_ct a, size_t as, ns_nname_ct b, size_t bs) {
        !           750:        ns_nname_ct ae = a + as, be = b + bs;
        !           751:        int ac, bc;
        !           752:
        !           753:        while (ac = *a, bc = *b, ac != 0 && bc != 0) {
        !           754:                if ((ac & NS_CMPRSFLGS) != 0 || (bc & NS_CMPRSFLGS) != 0) {
        !           755:                        errno = EISDIR;
        !           756:                        return (-1);
        !           757:                }
        !           758:                if (a + ac >= ae || b + bc >= be) {
        !           759:                        errno = EMSGSIZE;
        !           760:                        return (-1);
        !           761:                }
        !           762:                if (ac != bc || strncasecmp((const char *) ++a,
        !           763:                                            (const char *) ++b,
        !           764:                                            (size_t)ac) != 0)
        !           765:                        return (0);
        !           766:                a += ac, b += bc;
        !           767:        }
        !           768:        return (ac == 0 && bc == 0);
        !           769: }
        !           770:
        !           771: /* Is domain "A" owned by (at or below) domain "B"?
        !           772:  */
        !           773: int
        !           774: ns_name_owned(ns_namemap_ct a, int an, ns_namemap_ct b, int bn) {
        !           775:        /* If A is shorter, it cannot be owned by B. */
        !           776:        if (an < bn)
        !           777:                return (0);
        !           778:
        !           779:        /* If they are unequal before the length of the shorter, A cannot... */
        !           780:        while (bn > 0) {
        !           781:                if (a->len != b->len ||
        !           782:                    strncasecmp((const char *) a->base,
        !           783:                                (const char *) b->base, (size_t)a->len) != 0)
        !           784:                        return (0);
        !           785:                a++, an--;
        !           786:                b++, bn--;
        !           787:        }
        !           788:
        !           789:        /* A might be longer or not, but either way, B owns it. */
        !           790:        return (1);
        !           791: }
        !           792:
        !           793: /* Build an array of <base,len> tuples from an nname, top-down order.
        !           794:  * Return the number of tuples (labels) thus discovered.
        !           795:  */
        !           796: int
        !           797: ns_name_map(ns_nname_ct nname, size_t namelen, ns_namemap_t map, int mapsize) {
        !           798:        u_int n;
        !           799:        int l;
        !           800:
        !           801:        n = *nname++;
        !           802:        namelen--;
        !           803:
        !           804:        /* Root zone? */
        !           805:        if (n == 0) {
        !           806:                /* Extra data follows name? */
        !           807:                if (namelen > 0) {
        !           808:                        errno = EMSGSIZE;
        !           809:                        return (-1);
        !           810:                }
        !           811:                return (0);
        !           812:        }
        !           813:
        !           814:        /* Compression pointer? */
        !           815:        if ((n & NS_CMPRSFLGS) != 0) {
        !           816:                errno = EISDIR;
        !           817:                return (-1);
        !           818:        }
        !           819:
        !           820:        /* Label too long? */
        !           821:        if (n > namelen) {
        !           822:                errno = EMSGSIZE;
        !           823:                return (-1);
        !           824:        }
        !           825:
        !           826:        /* Recurse to get rest of name done first. */
        !           827:        l = ns_name_map(nname + n, namelen - n, map, mapsize);
        !           828:        if (l < 0)
        !           829:                return (-1);
        !           830:
        !           831:        /* Too many labels? */
        !           832:        if (l >= mapsize) {
        !           833:                errno = ENAMETOOLONG;
        !           834:                return (-1);
        !           835:        }
        !           836:
        !           837:        /* We're on our way back up-stack, store current map data. */
        !           838:        map[l].base = nname;
        !           839:        map[l].len = n;
        !           840:        return (l + 1);
        !           841: }
        !           842:
        !           843: /* Count the labels in a domain name.  Root counts, so COM. has two.  This
        !           844:  * is to make the result comparable to the result of ns_name_map().
        !           845:  */
        !           846: int
        !           847: ns_name_labels(ns_nname_ct nname, size_t namesiz) {
        !           848:        int ret = 0;
        !           849:        u_int n;
        !           850:
        !           851:        while (namesiz-- > 0 && (n = *nname++) != 0) {
        !           852:                if ((n & NS_CMPRSFLGS) != 0) {
        !           853:                        errno = EISDIR;
        !           854:                        return (-1);
        !           855:                }
        !           856:                if (n > namesiz) {
        !           857:                        errno = EMSGSIZE;
        !           858:                        return (-1);
        !           859:                }
        !           860:                nname += n;
        !           861:                namesiz -= n;
        !           862:                ret++;
        !           863:        }
        !           864:        return (ret + 1);
        !           865: }
        !           866:
1.1       christos  867: /* Private. */
                    868:
1.4       christos  869: /*%
1.1       christos  870:  *     Thinking in noninternationalized USASCII (per the DNS spec),
                    871:  *     is this characted special ("in need of quoting") ?
1.4       christos  872:  *
1.1       christos  873:  * return:
1.4       christos  874:  *\li  boolean.
1.1       christos  875:  */
                    876: static int
                    877: special(int ch) {
                    878:        switch (ch) {
1.4       christos  879:        case 0x22: /*%< '"' */
                    880:        case 0x2E: /*%< '.' */
                    881:        case 0x3B: /*%< ';' */
                    882:        case 0x5C: /*%< '\\' */
                    883:        case 0x28: /*%< '(' */
                    884:        case 0x29: /*%< ')' */
1.1       christos  885:        /* Special modifiers in zone files. */
1.4       christos  886:        case 0x40: /*%< '@' */
                    887:        case 0x24: /*%< '$' */
1.1       christos  888:                return (1);
                    889:        default:
                    890:                return (0);
                    891:        }
                    892: }
                    893:
1.4       christos  894: /*%
1.1       christos  895:  *     Thinking in noninternationalized USASCII (per the DNS spec),
                    896:  *     is this character visible and not a space when printed ?
1.4       christos  897:  *
1.1       christos  898:  * return:
1.4       christos  899:  *\li  boolean.
1.1       christos  900:  */
                    901: static int
                    902: printable(int ch) {
                    903:        return (ch > 0x20 && ch < 0x7f);
                    904: }
                    905:
1.4       christos  906: /*%
1.1       christos  907:  *     Thinking in noninternationalized USASCII (per the DNS spec),
                    908:  *     convert this character to lower case if it's upper case.
                    909:  */
                    910: static int
                    911: mklower(int ch) {
                    912:        if (ch >= 0x41 && ch <= 0x5A)
                    913:                return (ch + 0x20);
                    914:        return (ch);
                    915: }
                    916:
1.4       christos  917: /*%
1.1       christos  918:  *     Search for the counted-label name in an array of compressed names.
1.4       christos  919:  *
1.1       christos  920:  * return:
1.4       christos  921:  *\li  offset from msg if found, or -1.
                    922:  *
1.1       christos  923:  * notes:
1.4       christos  924:  *\li  dnptrs is the pointer to the first name on the list,
                    925:  *\li  not the pointer to the start of the message.
1.1       christos  926:  */
                    927: static int
                    928: dn_find(const u_char *domain, const u_char *msg,
                    929:        const u_char * const *dnptrs,
                    930:        const u_char * const *lastdnptr)
                    931: {
                    932:        const u_char *dn, *cp, *sp;
                    933:        const u_char * const *cpp;
                    934:        u_int n;
                    935:
                    936:        for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
                    937:                sp = *cpp;
                    938:                /*
                    939:                 * terminate search on:
                    940:                 * root label
                    941:                 * compression pointer
                    942:                 * unusable offset
                    943:                 */
                    944:                while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
                    945:                       (sp - msg) < 0x4000) {
                    946:                        dn = domain;
                    947:                        cp = sp;
                    948:                        while ((n = *cp++) != 0) {
                    949:                                /*
                    950:                                 * check for indirection
                    951:                                 */
                    952:                                switch (n & NS_CMPRSFLGS) {
1.4       christos  953:                                case 0:         /*%< normal case, n == len */
                    954:                                        n = labellen(cp - 1); /*%< XXX */
1.1       christos  955:                                        if (n != *dn++)
                    956:                                                goto next;
                    957:
1.2       christos  958:                                        for (; n > 0; n--)
1.1       christos  959:                                                if (mklower(*dn++) !=
                    960:                                                    mklower(*cp++))
                    961:                                                        goto next;
                    962:                                        /* Is next root for both ? */
                    963:                                        if (*dn == '\0' && *cp == '\0')
                    964:                                                return (sp - msg);
                    965:                                        if (*dn)
                    966:                                                continue;
                    967:                                        goto next;
1.4       christos  968:                                case NS_CMPRSFLGS:      /*%< indirection */
1.1       christos  969:                                        cp = msg + (((n & 0x3f) << 8) | *cp);
                    970:                                        break;
                    971:
1.4       christos  972:                                default:        /*%< illegal type */
1.1       christos  973:                                        errno = EMSGSIZE;
                    974:                                        return (-1);
                    975:                                }
                    976:                        }
                    977:  next: ;
                    978:                        sp += *sp + 1;
                    979:                }
                    980:        }
                    981:        errno = ENOENT;
                    982:        return (-1);
                    983: }
                    984:
                    985: static int
1.3       christos  986: decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
1.1       christos  987: {
1.3       christos  988:        const unsigned char *cp = *cpp;
1.1       christos  989:        char *beg = dn, tc;
                    990:        int b, blen, plen, i;
                    991:
                    992:        if ((blen = (*cp & 0xff)) == 0)
                    993:                blen = 256;
                    994:        plen = (blen + 3) / 4;
                    995:        plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
                    996:        if (dn + plen >= eom)
1.6.10.1! riz       997:                return (-1);
1.1       christos  998:
                    999:        cp++;
                   1000:        i = SPRINTF((dn, "\\[x"));
                   1001:        if (i < 0)
                   1002:                return (-1);
                   1003:        dn += i;
                   1004:        for (b = blen; b > 7; b -= 8, cp++) {
                   1005:                i = SPRINTF((dn, "%02x", *cp & 0xff));
                   1006:                if (i < 0)
                   1007:                        return (-1);
                   1008:                dn += i;
                   1009:        }
                   1010:        if (b > 4) {
                   1011:                tc = *cp++;
                   1012:                i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
                   1013:                if (i < 0)
                   1014:                        return (-1);
                   1015:                dn += i;
                   1016:        } else if (b > 0) {
                   1017:                tc = *cp++;
                   1018:                i = SPRINTF((dn, "%1x",
1.2       christos 1019:                               (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b))));
1.1       christos 1020:                if (i < 0)
                   1021:                        return (-1);
                   1022:                dn += i;
                   1023:        }
                   1024:        i = SPRINTF((dn, "/%d]", blen));
                   1025:        if (i < 0)
                   1026:                return (-1);
                   1027:        dn += i;
                   1028:
                   1029:        *cpp = cp;
1.6.10.1! riz      1030:        return (dn - beg);
1.1       christos 1031: }
                   1032:
                   1033: static int
1.3       christos 1034: encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
1.6.10.1! riz      1035:                unsigned char ** dst, unsigned const char *eom)
1.1       christos 1036: {
                   1037:        int afterslash = 0;
                   1038:        const char *cp = *bp;
1.3       christos 1039:        unsigned char *tp;
                   1040:        char c;
1.1       christos 1041:        const char *beg_blen;
                   1042:        char *end_blen = NULL;
                   1043:        int value = 0, count = 0, tbcount = 0, blen = 0;
                   1044:
                   1045:        beg_blen = end_blen = NULL;
                   1046:
                   1047:        /* a bitstring must contain at least 2 characters */
                   1048:        if (end - cp < 2)
1.6.10.1! riz      1049:                return (EINVAL);
1.1       christos 1050:
                   1051:        /* XXX: currently, only hex strings are supported */
                   1052:        if (*cp++ != 'x')
1.6.10.1! riz      1053:                return (EINVAL);
1.4       christos 1054:        if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */
1.6.10.1! riz      1055:                return (EINVAL);
1.1       christos 1056:
                   1057:        for (tp = *dst + 1; cp < end && tp < eom; cp++) {
                   1058:                switch((c = *cp)) {
1.4       christos 1059:                case ']':       /*%< end of the bitstring */
1.1       christos 1060:                        if (afterslash) {
                   1061:                                if (beg_blen == NULL)
1.6.10.1! riz      1062:                                        return (EINVAL);
1.1       christos 1063:                                blen = (int)strtol(beg_blen, &end_blen, 10);
                   1064:                                if (*end_blen != ']')
1.6.10.1! riz      1065:                                        return (EINVAL);
1.1       christos 1066:                        }
                   1067:                        if (count)
                   1068:                                *tp++ = ((value << 4) & 0xff);
1.4       christos 1069:                        cp++;   /*%< skip ']' */
1.1       christos 1070:                        goto done;
                   1071:                case '/':
                   1072:                        afterslash = 1;
                   1073:                        break;
                   1074:                default:
                   1075:                        if (afterslash) {
                   1076:                                if (!isdigit(c&0xff))
1.6.10.1! riz      1077:                                        return (EINVAL);
1.1       christos 1078:                                if (beg_blen == NULL) {
                   1079:
                   1080:                                        if (c == '0') {
                   1081:                                                /* blen never begings with 0 */
1.6.10.1! riz      1082:                                                return (EINVAL);
1.1       christos 1083:                                        }
                   1084:                                        beg_blen = cp;
                   1085:                                }
                   1086:                        } else {
                   1087:                                if (!isxdigit(c&0xff))
1.6.10.1! riz      1088:                                        return (EINVAL);
1.1       christos 1089:                                value <<= 4;
                   1090:                                value += digitvalue[(int)c];
                   1091:                                count += 4;
                   1092:                                tbcount += 4;
                   1093:                                if (tbcount > 256)
1.6.10.1! riz      1094:                                        return (EINVAL);
1.1       christos 1095:                                if (count == 8) {
                   1096:                                        *tp++ = value;
                   1097:                                        count = 0;
                   1098:                                }
                   1099:                        }
                   1100:                        break;
                   1101:                }
                   1102:        }
                   1103:   done:
                   1104:        if (cp >= end || tp >= eom)
1.6.10.1! riz      1105:                return (EMSGSIZE);
1.1       christos 1106:
                   1107:        /*
                   1108:         * bit length validation:
                   1109:         * If a <length> is present, the number of digits in the <bit-data>
                   1110:         * MUST be just sufficient to contain the number of bits specified
                   1111:         * by the <length>. If there are insignificant bits in a final
                   1112:         * hexadecimal or octal digit, they MUST be zero.
1.4       christos 1113:         * RFC2673, Section 3.2.
1.1       christos 1114:         */
                   1115:        if (blen > 0) {
                   1116:                int traillen;
                   1117:
                   1118:                if (((blen + 3) & ~3) != tbcount)
1.6.10.1! riz      1119:                        return (EINVAL);
1.4       christos 1120:                traillen = tbcount - blen; /*%< between 0 and 3 */
1.1       christos 1121:                if (((value << (8 - traillen)) & 0xff) != 0)
1.6.10.1! riz      1122:                        return (EINVAL);
1.1       christos 1123:        }
                   1124:        else
                   1125:                blen = tbcount;
                   1126:        if (blen == 256)
                   1127:                blen = 0;
                   1128:
                   1129:        /* encode the type and the significant bit fields */
                   1130:        **labelp = DNS_LABELTYPE_BITSTRING;
                   1131:        **dst = blen;
                   1132:
                   1133:        *bp = cp;
                   1134:        *dst = tp;
                   1135:
1.6.10.1! riz      1136:        return (0);
1.1       christos 1137: }
                   1138:
                   1139: static int
                   1140: labellen(const u_char *lp)
                   1141: {
                   1142:        int bitlen;
                   1143:        u_char l = *lp;
                   1144:
                   1145:        if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
                   1146:                /* should be avoided by the caller */
1.6.10.1! riz      1147:                return (-1);
1.1       christos 1148:        }
                   1149:
                   1150:        if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
                   1151:                if (l == DNS_LABELTYPE_BITSTRING) {
                   1152:                        if ((bitlen = *(lp + 1)) == 0)
                   1153:                                bitlen = 256;
1.6.10.1! riz      1154:                        return ((bitlen + 7 ) / 8 + 1);
1.1       christos 1155:                }
1.6.10.1! riz      1156:                return (-1);    /*%< unknwon ELT */
1.1       christos 1157:        }
1.6.10.1! riz      1158:        return (l);
1.1       christos 1159: }
1.4       christos 1160:
                   1161: /*! \file */

CVSweb <webmaster@jp.NetBSD.org>