Annotation of embedaddon/dhcp/common/inet.c, revision 1.1

1.1     ! misho       1: /* inet.c
        !             2: 
        !             3:    Subroutines to manipulate internet addresses and ports in a safely portable
        !             4:    way... */
        !             5: 
        !             6: /*
        !             7:  * Copyright (c) 2011 by Internet Systems Consortium, Inc. ("ISC")
        !             8:  * Copyright (c) 2007-2009 by Internet Systems Consortium, Inc. ("ISC")
        !             9:  * Copyright (c) 2004,2005 by Internet Systems Consortium, Inc. ("ISC")
        !            10:  * Copyright (c) 1995-2003 by Internet Software Consortium
        !            11:  *
        !            12:  * Permission to use, copy, modify, and distribute this software for any
        !            13:  * purpose with or without fee is hereby granted, provided that the above
        !            14:  * copyright notice and this permission notice appear in all copies.
        !            15:  *
        !            16:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
        !            17:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            18:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
        !            19:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            20:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            21:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
        !            22:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            23:  *
        !            24:  *   Internet Systems Consortium, Inc.
        !            25:  *   950 Charter Street
        !            26:  *   Redwood City, CA 94063
        !            27:  *   <info@isc.org>
        !            28:  *   https://www.isc.org/
        !            29:  *
        !            30:  * This software has been written for Internet Systems Consortium
        !            31:  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
        !            32:  * To learn more about Internet Systems Consortium, see
        !            33:  * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
        !            34:  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
        !            35:  * ``http://www.nominum.com''.
        !            36:  */
        !            37: 
        !            38: #include "dhcpd.h"
        !            39: 
        !            40: /* Return just the network number of an internet address... */
        !            41: 
        !            42: struct iaddr subnet_number (addr, mask)
        !            43:        struct iaddr addr;
        !            44:        struct iaddr mask;
        !            45: {
        !            46:        int i;
        !            47:        struct iaddr rv;
        !            48: 
        !            49:        if (addr.len > sizeof(addr.iabuf))
        !            50:                log_fatal("subnet_number():%s:%d: Invalid addr length.", MDL);
        !            51:        if (addr.len != mask.len)
        !            52:                log_fatal("subnet_number():%s:%d: Addr/mask length mismatch.",
        !            53:                          MDL);
        !            54: 
        !            55:        rv.len = 0;
        !            56: 
        !            57:        /* Both addresses must have the same length... */
        !            58:        if (addr.len != mask.len)
        !            59:                return rv;
        !            60: 
        !            61:        rv.len = addr.len;
        !            62:        for (i = 0; i < rv.len; i++)
        !            63:                rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i];
        !            64:        return rv;
        !            65: }
        !            66: 
        !            67: /* Combine a network number and a integer to produce an internet address.
        !            68:    This won't work for subnets with more than 32 bits of host address, but
        !            69:    maybe this isn't a problem. */
        !            70: 
        !            71: struct iaddr ip_addr (subnet, mask, host_address)
        !            72:        struct iaddr subnet;
        !            73:        struct iaddr mask;
        !            74:        u_int32_t host_address;
        !            75: {
        !            76:        int i, j, k;
        !            77:        u_int32_t swaddr;
        !            78:        struct iaddr rv;
        !            79:        unsigned char habuf [sizeof swaddr];
        !            80: 
        !            81:        if (subnet.len > sizeof(subnet.iabuf))
        !            82:                log_fatal("ip_addr():%s:%d: Invalid addr length.", MDL);
        !            83:        if (subnet.len != mask.len)
        !            84:                log_fatal("ip_addr():%s:%d: Addr/mask length mismatch.",
        !            85:                          MDL);
        !            86: 
        !            87:        swaddr = htonl (host_address);
        !            88:        memcpy (habuf, &swaddr, sizeof swaddr);
        !            89: 
        !            90:        /* Combine the subnet address and the host address.   If
        !            91:           the host address is bigger than can fit in the subnet,
        !            92:           return a zero-length iaddr structure. */
        !            93:        rv = subnet;
        !            94:        j = rv.len - sizeof habuf;
        !            95:        for (i = sizeof habuf - 1; i >= 0; i--) {
        !            96:                if (mask.iabuf [i + j]) {
        !            97:                        if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
        !            98:                                rv.len = 0;
        !            99:                                return rv;
        !           100:                        }
        !           101:                        for (k = i - 1; k >= 0; k--) {
        !           102:                                if (habuf [k]) {
        !           103:                                        rv.len = 0;
        !           104:                                        return rv;
        !           105:                                }
        !           106:                        }
        !           107:                        rv.iabuf [i + j] |= habuf [i];
        !           108:                        break;
        !           109:                } else
        !           110:                        rv.iabuf [i + j] = habuf [i];
        !           111:        }
        !           112:                
        !           113:        return rv;
        !           114: }
        !           115: 
        !           116: /* Given a subnet number and netmask, return the address on that subnet
        !           117:    for which the host portion of the address is all ones (the standard
        !           118:    broadcast address). */
        !           119: 
        !           120: struct iaddr broadcast_addr (subnet, mask)
        !           121:        struct iaddr subnet;
        !           122:        struct iaddr mask;
        !           123: {
        !           124:        int i;
        !           125:        struct iaddr rv;
        !           126: 
        !           127:        if (subnet.len > sizeof(subnet.iabuf))
        !           128:                log_fatal("broadcast_addr():%s:%d: Invalid addr length.", MDL);
        !           129:        if (subnet.len != mask.len)
        !           130:                log_fatal("broadcast_addr():%s:%d: Addr/mask length mismatch.",
        !           131:                          MDL);
        !           132: 
        !           133:        if (subnet.len != mask.len) {
        !           134:                rv.len = 0;
        !           135:                return rv;
        !           136:        }
        !           137: 
        !           138:        for (i = 0; i < subnet.len; i++) {
        !           139:                rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
        !           140:        }
        !           141:        rv.len = subnet.len;
        !           142: 
        !           143:        return rv;
        !           144: }
        !           145: 
        !           146: u_int32_t host_addr (addr, mask)
        !           147:        struct iaddr addr;
        !           148:        struct iaddr mask;
        !           149: {
        !           150:        int i;
        !           151:        u_int32_t swaddr;
        !           152:        struct iaddr rv;
        !           153: 
        !           154:        if (addr.len > sizeof(addr.iabuf))
        !           155:                log_fatal("host_addr():%s:%d: Invalid addr length.", MDL);
        !           156:        if (addr.len != mask.len)
        !           157:                log_fatal("host_addr():%s:%d: Addr/mask length mismatch.",
        !           158:                          MDL);
        !           159: 
        !           160:        rv.len = 0;
        !           161: 
        !           162:        /* Mask out the network bits... */
        !           163:        rv.len = addr.len;
        !           164:        for (i = 0; i < rv.len; i++)
        !           165:                rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i];
        !           166: 
        !           167:        /* Copy out up to 32 bits... */
        !           168:        memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
        !           169: 
        !           170:        /* Swap it and return it. */
        !           171:        return ntohl (swaddr);
        !           172: }
        !           173: 
        !           174: int addr_eq (addr1, addr2)
        !           175:        struct iaddr addr1, addr2;
        !           176: {
        !           177:        if (addr1.len > sizeof(addr1.iabuf))
        !           178:                log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL);
        !           179: 
        !           180:        if (addr1.len != addr2.len)
        !           181:                return 0;
        !           182:        return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
        !           183: }
        !           184: 
        !           185: /* addr_match 
        !           186:  *
        !           187:  * compares an IP address against a network/mask combination
        !           188:  * by ANDing the IP with the mask and seeing whether the result
        !           189:  * matches the masked network value.
        !           190:  */
        !           191: int
        !           192: addr_match(addr, match)
        !           193:        struct iaddr *addr;
        !           194:        struct iaddrmatch *match;
        !           195: {
        !           196:         int i;
        !           197: 
        !           198:        if (addr->len != match->addr.len)
        !           199:                return 0;
        !           200:        
        !           201:        i = 0;
        !           202:        for (i = 0 ; i < addr->len ; i++) {
        !           203:                if ((addr->iabuf[i] & match->mask.iabuf[i]) !=
        !           204:                                                        match->addr.iabuf[i])
        !           205:                        return 0;
        !           206:        }
        !           207:        return 1;
        !           208: }
        !           209: 
        !           210: /* 
        !           211:  * Compares the addresses a1 and a2.
        !           212:  *
        !           213:  * If a1 < a2, returns -1.
        !           214:  * If a1 == a2, returns 0.
        !           215:  * If a1 > a2, returns 1.
        !           216:  *
        !           217:  * WARNING: if a1 and a2 differ in length, returns 0.
        !           218:  */
        !           219: int
        !           220: addr_cmp(const struct iaddr *a1, const struct iaddr *a2) {
        !           221:        int i;
        !           222: 
        !           223:        if (a1->len != a2->len) {
        !           224:                return 0;
        !           225:        }
        !           226: 
        !           227:        for (i=0; i<a1->len; i++) {
        !           228:                if (a1->iabuf[i] < a2->iabuf[i]) {
        !           229:                        return -1;
        !           230:                }
        !           231:                if (a1->iabuf[i] > a2->iabuf[i]) {
        !           232:                        return 1;
        !           233:                }
        !           234:        }
        !           235: 
        !           236:        return 0;
        !           237: }
        !           238: 
        !           239: /*
        !           240:  * Performs a bitwise-OR of two addresses.
        !           241:  *
        !           242:  * Returns 1 if the result is non-zero, or 0 otherwise.
        !           243:  *
        !           244:  * WARNING: if a1 and a2 differ in length, returns 0.
        !           245:  */
        !           246: int 
        !           247: addr_or(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
        !           248:        int i;
        !           249:        int all_zero;
        !           250: 
        !           251:        if (a1->len != a2->len) {
        !           252:                return 0;
        !           253:        }
        !           254: 
        !           255:        all_zero = 1;
        !           256: 
        !           257:        result->len = a1->len;
        !           258:        for (i=0; i<a1->len; i++) {
        !           259:                result->iabuf[i] = a1->iabuf[i] | a2->iabuf[i];
        !           260:                if (result->iabuf[i] != 0) {
        !           261:                        all_zero = 0;
        !           262:                }
        !           263:        }
        !           264: 
        !           265:        return !all_zero;
        !           266: }
        !           267: 
        !           268: /*
        !           269:  * Performs a bitwise-AND of two addresses.
        !           270:  *
        !           271:  * Returns 1 if the result is non-zero, or 0 otherwise.
        !           272:  *
        !           273:  * WARNING: if a1 and a2 differ in length, returns 0.
        !           274:  */
        !           275: int 
        !           276: addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
        !           277:        int i;
        !           278:        int all_zero;
        !           279: 
        !           280:        if (a1->len != a2->len) {
        !           281:                return 0;
        !           282:        }
        !           283: 
        !           284:        all_zero = 1;
        !           285: 
        !           286:        result->len = a1->len;
        !           287:        for (i=0; i<a1->len; i++) {
        !           288:                result->iabuf[i] = a1->iabuf[i] & a2->iabuf[i];
        !           289:                if (result->iabuf[i] != 0) {
        !           290:                        all_zero = 0;
        !           291:                }
        !           292:        }
        !           293: 
        !           294:        return !all_zero;
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * Check if a bitmask of the given length is valid for the address.
        !           299:  * This is not the case if any bits longer than the bitmask are 1.
        !           300:  *
        !           301:  * So, this is valid:
        !           302:  *
        !           303:  * 127.0.0.0/8
        !           304:  *
        !           305:  * But this is not:
        !           306:  *
        !           307:  * 127.0.0.1/8
        !           308:  *
        !           309:  * Because the final ".1" would get masked out by the /8.
        !           310:  */
        !           311: isc_boolean_t
        !           312: is_cidr_mask_valid(const struct iaddr *addr, int bits) {
        !           313:        int zero_bits;
        !           314:        int zero_bytes;
        !           315:        int i;
        !           316:        char byte;
        !           317:        int shift_bits;
        !           318: 
        !           319:        /*
        !           320:         * Check our bit boundaries.
        !           321:         */
        !           322:        if (bits < 0) {
        !           323:                return ISC_FALSE;
        !           324:        }
        !           325:        if (bits > (addr->len * 8)) {
        !           326:                return ISC_FALSE;
        !           327:        }
        !           328: 
        !           329:        /*
        !           330:         * Figure out how many low-order bits need to be zero.
        !           331:         */
        !           332:        zero_bits = (addr->len * 8) - bits;
        !           333:        zero_bytes = zero_bits / 8;
        !           334: 
        !           335:        /* 
        !           336:         * Check to make sure the low-order bytes are zero.
        !           337:         */
        !           338:        for (i=1; i<=zero_bytes; i++) {
        !           339:                if (addr->iabuf[addr->len-i] != 0) {
        !           340:                        return ISC_FALSE;
        !           341:                }
        !           342:        }
        !           343: 
        !           344:        /* 
        !           345:         * Look to see if any bits not in right-hand bytes are 
        !           346:         * non-zero, by making a byte that has these bits set to zero 
        !           347:         * comparing to the original byte. If these two values are 
        !           348:         * equal, then the right-hand bits are zero, and we are 
        !           349:         * happy.
        !           350:         */
        !           351:        shift_bits = zero_bits % 8;
        !           352:        if (shift_bits == 0) return ISC_TRUE;
        !           353:        byte = addr->iabuf[addr->len-zero_bytes-1];
        !           354:        return (((byte >> shift_bits) << shift_bits) == byte);
        !           355: }
        !           356: 
        !           357: /*
        !           358:  * range2cidr
        !           359:  *
        !           360:  * Converts a range of IP addresses to a set of CIDR networks.
        !           361:  *
        !           362:  * Examples: 
        !           363:  *  192.168.0.0 - 192.168.0.255 = 192.168.0.0/24
        !           364:  *  10.0.0.0 - 10.0.1.127 = 10.0.0.0/24, 10.0.1.0/25
        !           365:  *  255.255.255.32 - 255.255.255.255 = 255.255.255.32/27, 255.255.255.64/26,
        !           366:  *                                    255.255.255.128/25
        !           367:  */
        !           368: isc_result_t 
        !           369: range2cidr(struct iaddrcidrnetlist **result, 
        !           370:           const struct iaddr *lo, const struct iaddr *hi) {
        !           371:        struct iaddr addr;
        !           372:        struct iaddr mask;
        !           373:        int bit;
        !           374:        struct iaddr end_addr;
        !           375:        struct iaddr dummy;
        !           376:        int ofs, val;
        !           377:        struct iaddrcidrnetlist *net;
        !           378:        int tmp;
        !           379: 
        !           380:        if (result == NULL) {
        !           381:                return ISC_R_INVALIDARG;
        !           382:        }
        !           383:        if (*result != NULL) {
        !           384:                return ISC_R_INVALIDARG;
        !           385:        }
        !           386:        if ((lo == NULL) || (hi == NULL) || (lo->len != hi->len)) {
        !           387:                return ISC_R_INVALIDARG;
        !           388:        }
        !           389: 
        !           390:        /*
        !           391:         * Put our start and end in the right order, if reversed.
        !           392:         */
        !           393:        if (addr_cmp(lo, hi) > 0) {
        !           394:                const struct iaddr *tmp;
        !           395:                tmp = lo;
        !           396:                lo = hi;
        !           397:                hi = tmp;
        !           398:        }
        !           399: 
        !           400:        /*
        !           401:         * Theory of operation:
        !           402:         *
        !           403:         * -------------------
        !           404:         * Start at the low end, and keep trying larger networks
        !           405:         * until we get one that is too big (explained below).
        !           406:         *
        !           407:         * We keep a "mask", which is the ones-complement of a 
        !           408:         * normal netmask. So, a /23 has a netmask of 255.255.254.0,
        !           409:         * and a mask of 0.0.1.255.
        !           410:         *
        !           411:         * We know when a network is too big when we bitwise-AND the 
        !           412:         * mask with the starting address and we get a non-zero 
        !           413:         * result, like this:
        !           414:         *
        !           415:         *    addr: 192.168.1.0, mask: 0.0.1.255
        !           416:         *    bitwise-AND: 0.0.1.0
        !           417:         * 
        !           418:         * A network is also too big if the bitwise-OR of the mask
        !           419:         * with the starting address is larger than the end address,
        !           420:         * like this:
        !           421:         *
        !           422:         *    start: 192.168.1.0, mask: 0.0.1.255, end: 192.168.0.255
        !           423:         *    bitwise-OR: 192.168.1.255 
        !           424:         *
        !           425:         * -------------------
        !           426:         * Once we have found a network that is too big, we add the 
        !           427:         * appropriate CIDR network to our list of found networks.
        !           428:         *
        !           429:         * We then use the next IP address as our low address, and
        !           430:         * begin the process of searching for a network that is 
        !           431:         * too big again, starting with an empty mask.
        !           432:         */
        !           433:        addr = *lo;
        !           434:        bit = 0;
        !           435:        memset(&mask, 0, sizeof(mask));
        !           436:        mask.len = addr.len;
        !           437:        while (addr_cmp(&addr, hi) <= 0) {
        !           438:                /*
        !           439:                 * Bitwise-OR mask with (1 << bit)
        !           440:                 */
        !           441:                ofs = addr.len - (bit / 8) - 1;
        !           442:                val = 1 << (bit % 8);
        !           443:                if (ofs >= 0) {
        !           444:                        mask.iabuf[ofs] |= val;
        !           445:                }
        !           446: 
        !           447:                /* 
        !           448:                 * See if we're too big, and save this network if so.
        !           449:                 */
        !           450:                addr_or(&end_addr, &addr, &mask);
        !           451:                if ((ofs < 0) ||
        !           452:                    (addr_cmp(&end_addr, hi) > 0) || 
        !           453:                    addr_and(&dummy, &addr, &mask)) {
        !           454:                        /*
        !           455:                         * Add a new prefix to our list.
        !           456:                         */
        !           457:                        net = dmalloc(sizeof(*net), MDL);
        !           458:                        if (net == NULL) {
        !           459:                                while (*result != NULL) {
        !           460:                                        net = (*result)->next;
        !           461:                                        dfree(*result, MDL);
        !           462:                                        *result = net;
        !           463:                                }
        !           464:                                return ISC_R_NOMEMORY;
        !           465:                        }
        !           466:                        net->cidrnet.lo_addr = addr;
        !           467:                        net->cidrnet.bits = (addr.len * 8) - bit;
        !           468:                        net->next = *result;
        !           469:                        *result = net;
        !           470: 
        !           471:                        /* 
        !           472:                         * Figure out our new starting address, 
        !           473:                         * by adding (1 << bit) to our previous
        !           474:                         * starting address.
        !           475:                         */
        !           476:                        tmp = addr.iabuf[ofs] + val;
        !           477:                        while ((ofs >= 0) && (tmp > 255)) {
        !           478:                                addr.iabuf[ofs] = tmp - 256;
        !           479:                                ofs--;
        !           480:                                tmp = addr.iabuf[ofs] + 1;
        !           481:                        }
        !           482:                        if (ofs < 0) {
        !           483:                                /* Gone past last address, we're done. */
        !           484:                                break;
        !           485:                        }
        !           486:                        addr.iabuf[ofs] = tmp;
        !           487: 
        !           488:                        /*
        !           489:                         * Reset our bit and mask.
        !           490:                         */
        !           491:                        bit = 0;
        !           492:                        memset(mask.iabuf, 0, sizeof(mask.iabuf));
        !           493:                        memset(end_addr.iabuf, 0, sizeof(end_addr.iabuf));
        !           494:                } else {
        !           495:                        /*
        !           496:                         * If we're not too big, increase our network size.
        !           497:                         */
        !           498:                        bit++;
        !           499:                }
        !           500:        }
        !           501: 
        !           502:        /*
        !           503:         * We're done.
        !           504:         */
        !           505:        return ISC_R_SUCCESS;
        !           506: }
        !           507: 
        !           508: /*
        !           509:  * Free a list of CIDR networks, such as returned from range2cidr().
        !           510:  */
        !           511: isc_result_t
        !           512: free_iaddrcidrnetlist(struct iaddrcidrnetlist **result) {
        !           513:        struct iaddrcidrnetlist *p;
        !           514: 
        !           515:        if (result == NULL) {
        !           516:                return ISC_R_INVALIDARG;
        !           517:        }
        !           518:        if (*result == NULL) {
        !           519:                return ISC_R_INVALIDARG;
        !           520:        }
        !           521: 
        !           522:        while (*result != NULL) {
        !           523:                p = *result;
        !           524:                *result = p->next;
        !           525:                dfree(p, MDL);
        !           526:        }
        !           527: 
        !           528:        return ISC_R_SUCCESS;
        !           529: }
        !           530: 
        !           531: /* piaddr() turns an iaddr structure into a printable address. */
        !           532: /* XXX: should use a const pointer rather than passing the structure */
        !           533: const char *
        !           534: piaddr(const struct iaddr addr) {
        !           535:        static char
        !           536:                pbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
        !           537:                         /* "255.255.255.255" */
        !           538: 
        !           539:        /* INSIST((addr.len == 0) || (addr.len == 4) || (addr.len == 16)); */
        !           540: 
        !           541:        if (addr.len == 0) {
        !           542:                return "<null address>";
        !           543:        }
        !           544:        if (addr.len == 4) {
        !           545:                return inet_ntop(AF_INET, addr.iabuf, pbuf, sizeof(pbuf));
        !           546:        } 
        !           547:        if (addr.len == 16) {
        !           548:                return inet_ntop(AF_INET6, addr.iabuf, pbuf, sizeof(pbuf));
        !           549:        }
        !           550: 
        !           551:        log_fatal("piaddr():%s:%d: Invalid address length %d.", MDL,
        !           552:                  addr.len);
        !           553:        /* quell compiler warnings */
        !           554:        return NULL;
        !           555: }
        !           556: 
        !           557: /* piaddrmask takes an iaddr structure mask, determines the bitlength of
        !           558:  * the mask, and then returns the printable CIDR notation of the two.
        !           559:  */
        !           560: char *
        !           561: piaddrmask(struct iaddr *addr, struct iaddr *mask) {
        !           562:        int mw;
        !           563:        unsigned int oct, bit;
        !           564: 
        !           565:        if ((addr->len != 4) && (addr->len != 16))
        !           566:                log_fatal("piaddrmask():%s:%d: Address length %d invalid",
        !           567:                          MDL, addr->len);
        !           568:        if (addr->len != mask->len)
        !           569:                log_fatal("piaddrmask():%s:%d: Address and mask size mismatch",
        !           570:                          MDL);
        !           571: 
        !           572:        /* Determine netmask width in bits. */
        !           573:        for (mw = (mask->len * 8) ; mw > 0 ; ) {
        !           574:                oct = (mw - 1) / 8;
        !           575:                bit = 0x80 >> ((mw - 1) % 8);
        !           576:                if (!mask->iabuf[oct])
        !           577:                        mw -= 8;
        !           578:                else if (mask->iabuf[oct] & bit)
        !           579:                        break;
        !           580:                else
        !           581:                        mw--;
        !           582:        }
        !           583: 
        !           584:        if (mw < 0)
        !           585:                log_fatal("Impossible condition at %s:%d.", MDL);
        !           586: 
        !           587:        return piaddrcidr(addr, mw);
        !           588: }
        !           589: 
        !           590: /* Format an address and mask-length into printable CIDR notation. */
        !           591: char *
        !           592: piaddrcidr(const struct iaddr *addr, unsigned int bits) {
        !           593:        static char
        !           594:            ret[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128")];
        !           595:                    /* "255.255.255.255/32" */
        !           596: 
        !           597:        /* INSIST(addr != NULL); */
        !           598:        /* INSIST((addr->len == 4) || (addr->len == 16)); */
        !           599:        /* INSIST(bits <= (addr->len * 8)); */
        !           600: 
        !           601:        if (bits > (addr->len * 8))
        !           602:                return NULL;
        !           603: 
        !           604:        sprintf(ret, "%s/%d", piaddr(*addr), bits);
        !           605: 
        !           606:        return ret;
        !           607: }
        !           608: 
        !           609: /* Validate that the string represents a valid port number and
        !           610:  * return it in network byte order
        !           611:  */
        !           612: 
        !           613: u_int16_t
        !           614: validate_port(char *port) {
        !           615:        long local_port = 0;
        !           616:        long lower = 1;
        !           617:        long upper = 65535;
        !           618:        char *endptr;
        !           619: 
        !           620:        errno = 0;
        !           621:        local_port = strtol(port, &endptr, 10);
        !           622:        
        !           623:        if ((*endptr != '\0') || (errno == ERANGE) || (errno == EINVAL))
        !           624:                log_fatal ("Invalid port number specification: %s", port);
        !           625: 
        !           626:        if (local_port < lower || local_port > upper)
        !           627:                log_fatal("Port number specified is out of range (%ld-%ld).",
        !           628:                          lower, upper);
        !           629: 
        !           630:        return htons((u_int16_t)local_port);
        !           631: }

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