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

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

CVSweb <webmaster@jp.NetBSD.org>