Annotation of embedaddon/dhcp/minires/ns_name.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2004,2009 by Internet Systems Consortium, Inc. ("ISC")
        !             3:  * Copyright (c) 1996-2003 by Internet Software Consortium
        !             4:  *
        !             5:  * Permission to use, copy, modify, and distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
        !            10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            11:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
        !            12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
        !            15:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            16:  *
        !            17:  *   Internet Systems Consortium, Inc.
        !            18:  *   950 Charter Street
        !            19:  *   Redwood City, CA 94063
        !            20:  *   <info@isc.org>
        !            21:  *   https://www.isc.org/
        !            22:  */
        !            23: 
        !            24: #ifndef lint
        !            25: static const char rcsid[] = "$Id: ns_name.c,v 1.2.786.3 2009-07-24 22:04:52 sar Exp $";
        !            26: #endif
        !            27: 
        !            28: #include <sys/types.h>
        !            29: 
        !            30: #include <netinet/in.h>
        !            31: #include <sys/socket.h>
        !            32: 
        !            33: #include <errno.h>
        !            34: #include <string.h>
        !            35: #include <ctype.h>
        !            36: 
        !            37: #include "minires/minires.h"
        !            38: #include "arpa/nameser.h"
        !            39: 
        !            40: /* Data. */
        !            41: 
        !            42: static const char      digits[] = "0123456789";
        !            43: 
        !            44: /* Forward. */
        !            45: 
        !            46: static int             special(int);
        !            47: static int             printable(int);
        !            48: static int             dn_find(const u_char *, const u_char *,
        !            49:                                const u_char * const *,
        !            50:                                const u_char * const *);
        !            51: 
        !            52: /* Public. */
        !            53: 
        !            54: /*
        !            55:  * ns_name_ntop(src, dst, dstsiz)
        !            56:  *     Convert an encoded domain name to printable ascii as per RFC1035.
        !            57:  * return:
        !            58:  *     Number of bytes written to buffer, or -1 (with errno set)
        !            59:  * notes:
        !            60:  *     The root is returned as "."
        !            61:  *     All other domains are returned in non absolute form
        !            62:  */
        !            63: int
        !            64: ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
        !            65:        const u_char *cp;
        !            66:        char *dn, *eom;
        !            67:        u_char c;
        !            68:        u_int n;
        !            69: 
        !            70:        cp = src;
        !            71:        dn = dst;
        !            72:        eom = dst + dstsiz;
        !            73: 
        !            74:        if (dn >= eom) {
        !            75:                errno = EMSGSIZE;
        !            76:                return (-1);
        !            77:        }
        !            78: 
        !            79:        while ((n = *cp++) != 0) {
        !            80:                if ((n & NS_CMPRSFLGS) != 0) {
        !            81:                        /* Some kind of compression pointer. */
        !            82:                        errno = EMSGSIZE;
        !            83:                        return (-1);
        !            84:                }
        !            85:                if (dn != dst) {
        !            86:                        if (dn >= eom) {
        !            87:                                errno = EMSGSIZE;
        !            88:                                return (-1);
        !            89:                        }
        !            90:                        *dn++ = '.';
        !            91:                }
        !            92:                if (dn + n >= eom) {
        !            93:                        errno = EMSGSIZE;
        !            94:                        return (-1);
        !            95:                }
        !            96:                for ((void)NULL; n > 0; n--) {
        !            97:                        c = *cp++;
        !            98:                        if (special(c)) {
        !            99:                                if (dn + 1 >= eom) {
        !           100:                                        errno = EMSGSIZE;
        !           101:                                        return (-1);
        !           102:                                }
        !           103:                                *dn++ = '\\';
        !           104:                                *dn++ = (char)c;
        !           105:                        } else if (!printable(c)) {
        !           106:                                if (dn + 3 >= eom) {
        !           107:                                        errno = EMSGSIZE;
        !           108:                                        return (-1);
        !           109:                                }
        !           110:                                *dn++ = '\\';
        !           111:                                *dn++ = digits[c / 100];
        !           112:                                *dn++ = digits[(c % 100) / 10];
        !           113:                                *dn++ = digits[c % 10];
        !           114:                        } else {
        !           115:                                if (dn >= eom) {
        !           116:                                        errno = EMSGSIZE;
        !           117:                                        return (-1);
        !           118:                                }
        !           119:                                *dn++ = (char)c;
        !           120:                        }
        !           121:                }
        !           122:        }
        !           123:        if (dn == dst) {
        !           124:                if (dn >= eom) {
        !           125:                        errno = EMSGSIZE;
        !           126:                        return (-1);
        !           127:                }
        !           128:                *dn++ = '.';
        !           129:        }
        !           130:        if (dn >= eom) {
        !           131:                errno = EMSGSIZE;
        !           132:                return (-1);
        !           133:        }
        !           134:        *dn++ = '\0';
        !           135:        return (dn - dst);
        !           136: }
        !           137: 
        !           138: /*
        !           139:  * ns_name_pton(src, dst, dstsiz)
        !           140:  *     Convert a ascii string into an encoded domain name as per RFC1035.
        !           141:  * return:
        !           142:  *     -1 if it fails
        !           143:  *     1 if string was fully qualified
        !           144:  *     0 is string was not fully qualified
        !           145:  * notes:
        !           146:  *     Enforces label and domain length limits.
        !           147:  */
        !           148: 
        !           149: int
        !           150: ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
        !           151:        u_char *label, *bp, *eom;
        !           152:        int c, n, escaped;
        !           153:        char *cp;
        !           154: 
        !           155:        escaped = 0;
        !           156:        bp = dst;
        !           157:        eom = dst + dstsiz;
        !           158:        label = bp++;
        !           159: 
        !           160:        while ((c = *src++) != 0) {
        !           161:                if (escaped) {
        !           162:                        if ((cp = strchr(digits, c)) != NULL) {
        !           163:                                n = (cp - digits) * 100;
        !           164:                                if ((c = *src++) == 0 ||
        !           165:                                    (cp = strchr(digits, c)) == NULL) {
        !           166:                                        errno = EMSGSIZE;
        !           167:                                        return (-1);
        !           168:                                }
        !           169:                                n += (cp - digits) * 10;
        !           170:                                if ((c = *src++) == 0 ||
        !           171:                                    (cp = strchr(digits, c)) == NULL) {
        !           172:                                        errno = EMSGSIZE;
        !           173:                                        return (-1);
        !           174:                                }
        !           175:                                n += (cp - digits);
        !           176:                                if (n > 255) {
        !           177:                                        errno = EMSGSIZE;
        !           178:                                        return (-1);
        !           179:                                }
        !           180:                                c = n;
        !           181:                        }
        !           182:                        escaped = 0;
        !           183:                } else if (c == '\\') {
        !           184:                        escaped = 1;
        !           185:                        continue;
        !           186:                } else if (c == '.') {
        !           187:                        c = (bp - label - 1);
        !           188:                        if ((c & NS_CMPRSFLGS) != 0) {  /* Label too big. */
        !           189:                                errno = EMSGSIZE;
        !           190:                                return (-1);
        !           191:                        }
        !           192:                        if (label >= eom) {
        !           193:                                errno = EMSGSIZE;
        !           194:                                return (-1);
        !           195:                        }
        !           196:                        *label = c;
        !           197:                        /* Fully qualified ? */
        !           198:                        if (*src == '\0') {
        !           199:                                if (c != 0) {
        !           200:                                        if (bp >= eom) {
        !           201:                                                errno = EMSGSIZE;
        !           202:                                                return (-1);
        !           203:                                        }
        !           204:                                        *bp++ = '\0';
        !           205:                                }
        !           206:                                if ((bp - dst) > MAXCDNAME) {
        !           207:                                        errno = EMSGSIZE;
        !           208:                                        return (-1);
        !           209:                                }
        !           210:                                return (1);
        !           211:                        }
        !           212:                        if (c == 0 || *src == '.') {
        !           213:                                errno = EMSGSIZE;
        !           214:                                return (-1);
        !           215:                        }
        !           216:                        label = bp++;
        !           217:                        continue;
        !           218:                }
        !           219:                if (bp >= eom) {
        !           220:                        errno = EMSGSIZE;
        !           221:                        return (-1);
        !           222:                }
        !           223:                *bp++ = (u_char)c;
        !           224:        }
        !           225:        c = (bp - label - 1);
        !           226:        if ((c & NS_CMPRSFLGS) != 0) {          /* Label too big. */
        !           227:                errno = EMSGSIZE;
        !           228:                return (-1);
        !           229:        }
        !           230:        if (label >= eom) {
        !           231:                errno = EMSGSIZE;
        !           232:                return (-1);
        !           233:        }
        !           234:        *label = c;
        !           235:        if (c != 0) {
        !           236:                if (bp >= eom) {
        !           237:                        errno = EMSGSIZE;
        !           238:                        return (-1);
        !           239:                }
        !           240:                *bp++ = 0;
        !           241:        }
        !           242:        if ((bp - dst) > MAXCDNAME) {   /* src too big */
        !           243:                errno = EMSGSIZE;
        !           244:                return (-1);
        !           245:        }
        !           246:        return (0);
        !           247: }
        !           248: 
        !           249: /*
        !           250:  * ns_name_ntol(src, dst, dstsiz)
        !           251:  *     Convert a network strings labels into all lowercase.
        !           252:  * return:
        !           253:  *     Number of bytes written to buffer, or -1 (with errno set)
        !           254:  * notes:
        !           255:  *     Enforces label and domain length limits.
        !           256:  */
        !           257: 
        !           258: int
        !           259: ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) {
        !           260:        const u_char *cp;
        !           261:        u_char *dn, *eom;
        !           262:        u_char c;
        !           263:        u_int n;
        !           264: 
        !           265:        cp = src;
        !           266:        dn = dst;
        !           267:        eom = dst + dstsiz;
        !           268: 
        !           269:        if (dn >= eom) {
        !           270:                errno = EMSGSIZE;
        !           271:                return (-1);
        !           272:        }
        !           273:        while ((n = *cp++) != 0) {
        !           274:                if ((n & NS_CMPRSFLGS) != 0) {
        !           275:                        /* Some kind of compression pointer. */
        !           276:                        errno = EMSGSIZE;
        !           277:                        return (-1);
        !           278:                }
        !           279:                *dn++ = n;
        !           280:                if (dn + n >= eom) {
        !           281:                        errno = EMSGSIZE;
        !           282:                        return (-1);
        !           283:                }
        !           284:                for ((void)NULL; n > 0; n--) {
        !           285:                        c = *cp++;
        !           286:                        if (isupper(c))
        !           287:                                *dn++ = tolower(c);
        !           288:                        else
        !           289:                                *dn++ = c;
        !           290:                }
        !           291:        }
        !           292:        *dn++ = '\0';
        !           293:        return (dn - dst);
        !           294: }
        !           295: 
        !           296: /*
        !           297:  * ns_name_unpack(msg, eom, src, dst, dstsiz)
        !           298:  *     Unpack a domain name from a message, source may be compressed.
        !           299:  * return:
        !           300:  *     -1 if it fails, or consumed octets if it succeeds.
        !           301:  */
        !           302: int
        !           303: ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
        !           304:               u_char *dst, size_t dstsiz)
        !           305: {
        !           306:        const u_char *srcp, *dstlim;
        !           307:        u_char *dstp;
        !           308:        unsigned n;
        !           309:        int len;
        !           310:        int checked;
        !           311: 
        !           312:        len = -1;
        !           313:        checked = 0;
        !           314:        dstp = dst;
        !           315:        srcp = src;
        !           316:        dstlim = dst + dstsiz;
        !           317:        if (srcp < msg || srcp >= eom) {
        !           318:                errno = EMSGSIZE;
        !           319:                return (-1);
        !           320:        }
        !           321:        /* Fetch next label in domain name. */
        !           322:        while ((n = *srcp++) != 0) {
        !           323:                /* Check for indirection. */
        !           324:                switch (n & NS_CMPRSFLGS) {
        !           325:                case 0:
        !           326:                        /* Limit checks. */
        !           327:                        if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
        !           328:                                errno = EMSGSIZE;
        !           329:                                return (-1);
        !           330:                        }
        !           331:                        checked += n + 1;
        !           332:                        *dstp++ = n;
        !           333:                        memcpy(dstp, srcp, n);
        !           334:                        dstp += n;
        !           335:                        srcp += n;
        !           336:                        break;
        !           337: 
        !           338:                case NS_CMPRSFLGS:
        !           339:                        if (srcp >= eom) {
        !           340:                                errno = EMSGSIZE;
        !           341:                                return (-1);
        !           342:                        }
        !           343:                        if (len < 0)
        !           344:                                len = srcp - src + 1;
        !           345:                        srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
        !           346:                        if (srcp < msg || srcp >= eom) {  /* Out of range. */
        !           347:                                errno = EMSGSIZE;
        !           348:                                return (-1);
        !           349:                        }
        !           350:                        checked += 2;
        !           351:                        /*
        !           352:                         * Check for loops in the compressed name;
        !           353:                         * if we've looked at the whole message,
        !           354:                         * there must be a loop.
        !           355:                         */
        !           356:                        if (checked >= eom - msg) {
        !           357:                                errno = EMSGSIZE;
        !           358:                                return (-1);
        !           359:                        }
        !           360:                        break;
        !           361: 
        !           362:                default:
        !           363:                        errno = EMSGSIZE;
        !           364:                        return (-1);                    /* flag error */
        !           365:                }
        !           366:        }
        !           367:        *dstp = '\0';
        !           368:        if (len < 0)
        !           369:                len = srcp - src;
        !           370:        return (len);
        !           371: }
        !           372: 
        !           373: /*
        !           374:  * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
        !           375:  *     Pack domain name 'domain' into 'comp_dn'.
        !           376:  * return:
        !           377:  *     Size of the compressed name, or -1.
        !           378:  * notes:
        !           379:  *     'dnptrs' is an array of pointers to previous compressed names.
        !           380:  *     dnptrs[0] is a pointer to the beginning of the message. The array
        !           381:  *     ends with NULL.
        !           382:  *     'lastdnptr' is a pointer to the end of the array pointed to
        !           383:  *     by 'dnptrs'.
        !           384:  * Side effects:
        !           385:  *     The list of pointers in dnptrs is updated for labels inserted into
        !           386:  *     the message as we compress the name.  If 'dnptr' is NULL, we don't
        !           387:  *     try to compress names. If 'lastdnptr' is NULL, we don't update the
        !           388:  *     list.
        !           389:  */
        !           390: int
        !           391: ns_name_pack(const u_char *src, u_char *dst, unsigned dstsiz,
        !           392:             const u_char **dnptrs, const u_char **lastdnptr)
        !           393: {
        !           394:        u_char *dstp;
        !           395:        const u_char **cpp, **lpp, *eob, *msg;
        !           396:        const u_char *srcp;
        !           397:        unsigned n;
        !           398:        int l;
        !           399: 
        !           400:        srcp = src;
        !           401:        dstp = dst;
        !           402:        eob = dstp + dstsiz;
        !           403:        lpp = cpp = NULL;
        !           404:        if (dnptrs != NULL) {
        !           405:                if ((msg = *dnptrs++) != NULL) {
        !           406:                        for (cpp = dnptrs; *cpp != NULL; cpp++)
        !           407:                                (void)NULL;
        !           408:                        lpp = cpp;      /* end of list to search */
        !           409:                }
        !           410:        } else
        !           411:                msg = NULL;
        !           412: 
        !           413:        /* make sure the domain we are about to add is legal */
        !           414:        l = 0;
        !           415:        do {
        !           416:                n = *srcp;
        !           417:                if ((n & NS_CMPRSFLGS) != 0) {
        !           418:                        errno = EMSGSIZE;
        !           419:                        return (-1);
        !           420:                }
        !           421:                l += n + 1;
        !           422:                if (l > MAXCDNAME) {
        !           423:                        errno = EMSGSIZE;
        !           424:                        return (-1);
        !           425:                }
        !           426:                srcp += n + 1;
        !           427:        } while (n != 0);
        !           428: 
        !           429:        /* from here on we need to reset compression pointer array on error */
        !           430:        srcp = src;
        !           431:        do {
        !           432:                /* Look to see if we can use pointers. */
        !           433:                n = *srcp;
        !           434:                if (n != 0 && msg != NULL) {
        !           435:                        l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
        !           436:                                    (const u_char * const *)lpp);
        !           437:                        if (l >= 0) {
        !           438:                                if (dstp + 1 >= eob) {
        !           439:                                        goto cleanup;
        !           440:                                }
        !           441:                                *dstp++ = (l >> 8) | NS_CMPRSFLGS;
        !           442:                                *dstp++ = l % 256;
        !           443:                                return (dstp - dst);
        !           444:                        }
        !           445:                        /* Not found, save it. */
        !           446:                        if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
        !           447:                            (dstp - msg) < 0x4000) {
        !           448:                                *cpp++ = dstp;
        !           449:                                *cpp = NULL;
        !           450:                        }
        !           451:                }
        !           452:                /* copy label to buffer */
        !           453:                if (n & NS_CMPRSFLGS) {         /* Should not happen. */
        !           454:                        goto cleanup;
        !           455:                }
        !           456:                if (dstp + 1 + n >= eob) {
        !           457:                        goto cleanup;
        !           458:                }
        !           459:                memcpy(dstp, srcp, n + 1);
        !           460:                srcp += n + 1;
        !           461:                dstp += n + 1;
        !           462:        } while (n != 0);
        !           463: 
        !           464:        if (dstp > eob) {
        !           465: cleanup:
        !           466:                if (msg != NULL)
        !           467:                        *lpp = NULL;
        !           468:                errno = EMSGSIZE;
        !           469:                return (-1);
        !           470:        } 
        !           471:        return (dstp - dst);
        !           472: }
        !           473: 
        !           474: /*
        !           475:  * ns_name_uncompress(msg, eom, src, dst, dstsiz)
        !           476:  *     Expand compressed domain name to presentation format.
        !           477:  * return:
        !           478:  *     Number of bytes read out of `src', or -1 (with errno set).
        !           479:  * note:
        !           480:  *     Root domain returns as "." not "".
        !           481:  */
        !           482: int
        !           483: ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
        !           484:                   char *dst, size_t dstsiz)
        !           485: {
        !           486:        u_char tmp[NS_MAXCDNAME];
        !           487:        int n;
        !           488:        
        !           489:        if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
        !           490:                return (-1);
        !           491:        if (ns_name_ntop(tmp, dst, dstsiz) == -1)
        !           492:                return (-1);
        !           493:        return (n);
        !           494: }
        !           495: 
        !           496: /*
        !           497:  * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
        !           498:  *     Compress a domain name into wire format, using compression pointers.
        !           499:  * return:
        !           500:  *     Number of bytes consumed in `dst' or -1 (with errno set).
        !           501:  * notes:
        !           502:  *     'dnptrs' is an array of pointers to previous compressed names.
        !           503:  *     dnptrs[0] is a pointer to the beginning of the message.
        !           504:  *     The list ends with NULL.  'lastdnptr' is a pointer to the end of the
        !           505:  *     array pointed to by 'dnptrs'. Side effect is to update the list of
        !           506:  *     pointers for labels inserted into the message as we compress the name.
        !           507:  *     If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
        !           508:  *     is NULL, we don't update the list.
        !           509:  */
        !           510: int
        !           511: ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
        !           512:                 const u_char **dnptrs, const u_char **lastdnptr)
        !           513: {
        !           514:        u_char tmp[NS_MAXCDNAME];
        !           515: 
        !           516:        if (ns_name_pton(src, tmp, sizeof tmp) == -1)
        !           517:                return (-1);
        !           518:        return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
        !           519: }
        !           520: 
        !           521: /*
        !           522:  * ns_name_skip(ptrptr, eom)
        !           523:  *     Advance *ptrptr to skip over the compressed name it points at.
        !           524:  * return:
        !           525:  *     0 on success, -1 (with errno set) on failure.
        !           526:  */
        !           527: int
        !           528: ns_name_skip(const u_char **ptrptr, const u_char *eom) {
        !           529:        const u_char *cp;
        !           530:        u_int n;
        !           531: 
        !           532:        cp = *ptrptr;
        !           533:        while (cp < eom && (n = *cp++) != 0) {
        !           534:                /* Check for indirection. */
        !           535:                switch (n & NS_CMPRSFLGS) {
        !           536:                case 0:                 /* normal case, n == len */
        !           537:                        cp += n;
        !           538:                        continue;
        !           539:                case NS_CMPRSFLGS:      /* indirection */
        !           540:                        cp++;
        !           541:                        break;
        !           542:                default:                /* illegal type */
        !           543:                        errno = EMSGSIZE;
        !           544:                        return (-1);
        !           545:                }
        !           546:                break;
        !           547:        }
        !           548:        if (cp > eom) {
        !           549:                errno = EMSGSIZE;
        !           550:                return (-1);
        !           551:        }
        !           552:        *ptrptr = cp;
        !           553:        return (0);
        !           554: }
        !           555: 
        !           556: /* Private. */
        !           557: 
        !           558: /*
        !           559:  * special(ch)
        !           560:  *     Thinking in noninternationalized USASCII (per the DNS spec),
        !           561:  *     is this characted special ("in need of quoting") ?
        !           562:  * return:
        !           563:  *     boolean.
        !           564:  */
        !           565: static int
        !           566: special(int ch) {
        !           567:        switch (ch) {
        !           568:        case 0x22: /* '"' */
        !           569:        case 0x2E: /* '.' */
        !           570:        case 0x3B: /* ';' */
        !           571:        case 0x5C: /* '\\' */
        !           572:        /* Special modifiers in zone files. */
        !           573:        case 0x40: /* '@' */
        !           574:        case 0x24: /* '$' */
        !           575:                return (1);
        !           576:        default:
        !           577:                return (0);
        !           578:        }
        !           579: }
        !           580: 
        !           581: /*
        !           582:  * printable(ch)
        !           583:  *     Thinking in noninternationalized USASCII (per the DNS spec),
        !           584:  *     is this character visible and not a space when printed ?
        !           585:  * return:
        !           586:  *     boolean.
        !           587:  */
        !           588: static int
        !           589: printable(int ch) {
        !           590:        return (ch > 0x20 && ch < 0x7f);
        !           591: }
        !           592: 
        !           593: /*
        !           594:  *     Thinking in noninternationalized USASCII (per the DNS spec),
        !           595:  *     convert this character to lower case if it's upper case.
        !           596:  */
        !           597: static int
        !           598: mklower(int ch) {
        !           599:        if (ch >= 0x41 && ch <= 0x5A)
        !           600:                return (ch + 0x20);
        !           601:        return (ch);
        !           602: }
        !           603: 
        !           604: /*
        !           605:  * dn_find(domain, msg, dnptrs, lastdnptr)
        !           606:  *     Search for the counted-label name in an array of compressed names.
        !           607:  * return:
        !           608:  *     offset from msg if found, or -1.
        !           609:  * notes:
        !           610:  *     dnptrs is the pointer to the first name on the list,
        !           611:  *     not the pointer to the start of the message.
        !           612:  */
        !           613: static int
        !           614: dn_find(const u_char *domain, const u_char *msg,
        !           615:        const u_char * const *dnptrs,
        !           616:        const u_char * const *lastdnptr)
        !           617: {
        !           618:        const u_char *dn, *cp, *sp;
        !           619:        const u_char * const *cpp;
        !           620:        u_int n;
        !           621: 
        !           622:        for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
        !           623:                dn = domain;
        !           624:                sp = cp = *cpp;
        !           625:                while ((n = *cp++) != 0) {
        !           626:                        /*
        !           627:                         * check for indirection
        !           628:                         */
        !           629:                        switch (n & NS_CMPRSFLGS) {
        !           630:                        case 0:                 /* normal case, n == len */
        !           631:                                if (n != *dn++)
        !           632:                                        goto next;
        !           633:                                for ((void)NULL; n > 0; n--)
        !           634:                                        if (mklower(*dn++) != mklower(*cp++))
        !           635:                                                goto next;
        !           636:                                /* Is next root for both ? */
        !           637:                                if (*dn == '\0' && *cp == '\0')
        !           638:                                        return (sp - msg);
        !           639:                                if (*dn)
        !           640:                                        continue;
        !           641:                                goto next;
        !           642: 
        !           643:                        case NS_CMPRSFLGS:      /* indirection */
        !           644:                                cp = msg + (((n & 0x3f) << 8) | *cp);
        !           645:                                break;
        !           646: 
        !           647:                        default:        /* illegal type */
        !           648:                                errno = EMSGSIZE;
        !           649:                                return (-1);
        !           650:                        }
        !           651:                }
        !           652:  next: ;
        !           653:        }
        !           654:        errno = ENOENT;
        !           655:        return (-1);
        !           656: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>