Annotation of embedaddon/dhcp/common/inet.c, revision 1.1.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>