[BACK]Return to addr.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/addr.c, Revision 1.8

1.8     ! deraadt     1: /* $OpenBSD: addr.c,v 1.7 2023/03/27 03:31:05 djm Exp $ */
1.1       dtucker     2:
                      3: /*
                      4:  * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20: #include <sys/socket.h>
                     21: #include <netinet/in.h>
                     22: #include <arpa/inet.h>
                     23:
                     24: #include <netdb.h>
                     25: #include <string.h>
                     26: #include <stdlib.h>
                     27: #include <stdio.h>
1.8     ! deraadt    28: #include <limits.h>
1.1       dtucker    29:
                     30: #include "addr.h"
                     31:
                     32: #define _SA(x) ((struct sockaddr *)(x))
                     33:
                     34: int
                     35: addr_unicast_masklen(int af)
                     36: {
                     37:        switch (af) {
                     38:        case AF_INET:
                     39:                return 32;
                     40:        case AF_INET6:
                     41:                return 128;
                     42:        default:
                     43:                return -1;
                     44:        }
                     45: }
                     46:
                     47: static inline int
                     48: masklen_valid(int af, u_int masklen)
                     49: {
                     50:        switch (af) {
                     51:        case AF_INET:
                     52:                return masklen <= 32 ? 0 : -1;
                     53:        case AF_INET6:
                     54:                return masklen <= 128 ? 0 : -1;
                     55:        default:
                     56:                return -1;
                     57:        }
                     58: }
                     59:
                     60: int
                     61: addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, socklen_t *len,
                     62:     u_int16_t port)
                     63: {
                     64:        struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
                     65:        struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
                     66:
                     67:        if (xa == NULL || sa == NULL || len == NULL)
                     68:                return -1;
                     69:
                     70:        switch (xa->af) {
                     71:        case AF_INET:
                     72:                if (*len < sizeof(*in4))
                     73:                        return -1;
                     74:                memset(sa, '\0', sizeof(*in4));
                     75:                *len = sizeof(*in4);
                     76: #ifdef SOCK_HAS_LEN
                     77:                in4->sin_len = sizeof(*in4);
                     78: #endif
                     79:                in4->sin_family = AF_INET;
                     80:                in4->sin_port = htons(port);
                     81:                memcpy(&in4->sin_addr, &xa->v4, sizeof(in4->sin_addr));
                     82:                break;
                     83:        case AF_INET6:
                     84:                if (*len < sizeof(*in6))
                     85:                        return -1;
                     86:                memset(sa, '\0', sizeof(*in6));
                     87:                *len = sizeof(*in6);
                     88: #ifdef SOCK_HAS_LEN
                     89:                in6->sin6_len = sizeof(*in6);
                     90: #endif
                     91:                in6->sin6_family = AF_INET6;
                     92:                in6->sin6_port = htons(port);
                     93:                memcpy(&in6->sin6_addr, &xa->v6, sizeof(in6->sin6_addr));
                     94:                in6->sin6_scope_id = xa->scope_id;
                     95:                break;
                     96:        default:
                     97:                return -1;
                     98:        }
                     99:        return 0;
                    100: }
                    101:
                    102: /*
                    103:  * Convert struct sockaddr to struct xaddr
                    104:  * Returns 0 on success, -1 on failure.
                    105:  */
                    106: int
                    107: addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
                    108: {
                    109:        struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
                    110:        struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
                    111:
                    112:        memset(xa, '\0', sizeof(*xa));
                    113:
                    114:        switch (sa->sa_family) {
                    115:        case AF_INET:
                    116:                if (slen < (socklen_t)sizeof(*in4))
                    117:                        return -1;
                    118:                xa->af = AF_INET;
                    119:                memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
                    120:                break;
                    121:        case AF_INET6:
                    122:                if (slen < (socklen_t)sizeof(*in6))
                    123:                        return -1;
                    124:                xa->af = AF_INET6;
                    125:                memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
                    126: #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
                    127:                xa->scope_id = in6->sin6_scope_id;
                    128: #endif
                    129:                break;
                    130:        default:
                    131:                return -1;
                    132:        }
                    133:
                    134:        return 0;
                    135: }
                    136:
                    137: int
                    138: addr_invert(struct xaddr *n)
                    139: {
                    140:        int i;
                    141:
                    142:        if (n == NULL)
                    143:                return -1;
                    144:
                    145:        switch (n->af) {
                    146:        case AF_INET:
                    147:                n->v4.s_addr = ~n->v4.s_addr;
                    148:                return 0;
                    149:        case AF_INET6:
                    150:                for (i = 0; i < 4; i++)
                    151:                        n->addr32[i] = ~n->addr32[i];
                    152:                return 0;
                    153:        default:
                    154:                return -1;
                    155:        }
                    156: }
                    157:
                    158: /*
                    159:  * Calculate a netmask of length 'l' for address family 'af' and
                    160:  * store it in 'n'.
                    161:  * Returns 0 on success, -1 on failure.
                    162:  */
                    163: int
                    164: addr_netmask(int af, u_int l, struct xaddr *n)
                    165: {
                    166:        int i;
                    167:
                    168:        if (masklen_valid(af, l) != 0 || n == NULL)
                    169:                return -1;
                    170:
                    171:        memset(n, '\0', sizeof(*n));
                    172:        switch (af) {
                    173:        case AF_INET:
                    174:                n->af = AF_INET;
                    175:                if (l == 0)
                    176:                        return 0;
                    177:                n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
                    178:                return 0;
                    179:        case AF_INET6:
                    180:                n->af = AF_INET6;
                    181:                for (i = 0; i < 4 && l >= 32; i++, l -= 32)
                    182:                        n->addr32[i] = 0xffffffffU;
                    183:                if (i < 4 && l != 0)
                    184:                        n->addr32[i] = htonl((0xffffffff << (32 - l)) &
                    185:                            0xffffffff);
                    186:                return 0;
                    187:        default:
                    188:                return -1;
                    189:        }
                    190: }
                    191:
                    192: int
                    193: addr_hostmask(int af, u_int l, struct xaddr *n)
                    194: {
                    195:        if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1)
                    196:                return -1;
                    197:        return 0;
                    198: }
                    199:
                    200: /*
                    201:  * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'.
                    202:  * Returns 0 on success, -1 on failure.
                    203:  */
                    204: int
                    205: addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
                    206: {
                    207:        int i;
                    208:
                    209:        if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
                    210:                return -1;
                    211:
                    212:        memcpy(dst, a, sizeof(*dst));
                    213:        switch (a->af) {
                    214:        case AF_INET:
                    215:                dst->v4.s_addr &= b->v4.s_addr;
                    216:                return 0;
                    217:        case AF_INET6:
                    218:                dst->scope_id = a->scope_id;
                    219:                for (i = 0; i < 4; i++)
                    220:                        dst->addr32[i] &= b->addr32[i];
                    221:                return 0;
                    222:        default:
                    223:                return -1;
                    224:        }
                    225: }
                    226:
                    227: int
1.6       djm       228: addr_or(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
                    229: {
                    230:        int i;
                    231:
                    232:        if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
                    233:                return (-1);
                    234:
                    235:        memcpy(dst, a, sizeof(*dst));
                    236:        switch (a->af) {
                    237:        case AF_INET:
                    238:                dst->v4.s_addr |= b->v4.s_addr;
                    239:                return (0);
                    240:        case AF_INET6:
                    241:                for (i = 0; i < 4; i++)
                    242:                        dst->addr32[i] |= b->addr32[i];
                    243:                return (0);
                    244:        default:
                    245:                return (-1);
                    246:        }
                    247: }
                    248:
                    249: int
1.1       dtucker   250: addr_cmp(const struct xaddr *a, const struct xaddr *b)
                    251: {
                    252:        int i;
                    253:
                    254:        if (a->af != b->af)
                    255:                return (a->af == AF_INET6 ? 1 : -1);
                    256:
                    257:        switch (a->af) {
                    258:        case AF_INET:
                    259:                /*
                    260:                 * Can't just subtract here as 255.255.255.255 - 0.0.0.0 is
                    261:                 * too big to fit into a signed int
                    262:                 */
                    263:                if (a->v4.s_addr == b->v4.s_addr)
                    264:                        return 0;
                    265:                return (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1);
1.3       dtucker   266:        case AF_INET6:
1.1       dtucker   267:                /*
                    268:                 * Do this a byte at a time to avoid the above issue and
                    269:                 * any endian problems
                    270:                 */
                    271:                for (i = 0; i < 16; i++)
                    272:                        if (a->addr8[i] - b->addr8[i] != 0)
                    273:                                return (a->addr8[i] - b->addr8[i]);
                    274:                if (a->scope_id == b->scope_id)
                    275:                        return (0);
                    276:                return (a->scope_id > b->scope_id ? 1 : -1);
                    277:        default:
                    278:                return (-1);
                    279:        }
                    280: }
                    281:
                    282: int
                    283: addr_is_all0s(const struct xaddr *a)
                    284: {
                    285:        int i;
                    286:
                    287:        switch (a->af) {
                    288:        case AF_INET:
                    289:                return (a->v4.s_addr == 0 ? 0 : -1);
1.3       dtucker   290:        case AF_INET6:
1.1       dtucker   291:                for (i = 0; i < 4; i++)
                    292:                        if (a->addr32[i] != 0)
                    293:                                return -1;
                    294:                return 0;
                    295:        default:
                    296:                return -1;
                    297:        }
                    298: }
                    299:
1.6       djm       300: /* Increment the specified address. Note, does not do overflow checking */
                    301: void
                    302: addr_increment(struct xaddr *a)
                    303: {
                    304:        int i;
                    305:        uint32_t n;
                    306:
                    307:        switch (a->af) {
                    308:        case AF_INET:
                    309:                a->v4.s_addr = htonl(ntohl(a->v4.s_addr) + 1);
                    310:                break;
                    311:        case AF_INET6:
                    312:                for (i = 0; i < 4; i++) {
                    313:                        /* Increment with carry */
                    314:                        n = ntohl(a->addr32[3 - i]) + 1;
                    315:                        a->addr32[3 - i] = htonl(n);
                    316:                        if (n != 0)
                    317:                                break;
                    318:                }
                    319:                break;
                    320:        }
                    321: }
                    322:
1.1       dtucker   323: /*
                    324:  * Test whether host portion of address 'a', as determined by 'masklen'
                    325:  * is all zeros.
1.2       dtucker   326:  * Returns 0 if host portion of address is all-zeros,
1.1       dtucker   327:  * -1 if not all zeros or on failure.
                    328:  */
                    329: int
                    330: addr_host_is_all0s(const struct xaddr *a, u_int masklen)
                    331: {
                    332:        struct xaddr tmp_addr, tmp_mask, tmp_result;
                    333:
                    334:        memcpy(&tmp_addr, a, sizeof(tmp_addr));
                    335:        if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
                    336:                return -1;
                    337:        if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1)
                    338:                return -1;
                    339:        return addr_is_all0s(&tmp_result);
1.6       djm       340: }
                    341:
                    342: #if 0
                    343: int
                    344: addr_host_to_all0s(struct xaddr *a, u_int masklen)
                    345: {
                    346:        struct xaddr tmp_mask;
                    347:
                    348:        if (addr_netmask(a->af, masklen, &tmp_mask) == -1)
                    349:                return (-1);
                    350:        if (addr_and(a, a, &tmp_mask) == -1)
                    351:                return (-1);
                    352:        return (0);
                    353: }
                    354: #endif
                    355:
                    356: int
                    357: addr_host_to_all1s(struct xaddr *a, u_int masklen)
                    358: {
                    359:        struct xaddr tmp_mask;
                    360:
                    361:        if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
                    362:                return (-1);
                    363:        if (addr_or(a, a, &tmp_mask) == -1)
                    364:                return (-1);
                    365:        return (0);
1.1       dtucker   366: }
                    367:
                    368: /*
1.2       dtucker   369:  * Parse string address 'p' into 'n'.
1.1       dtucker   370:  * Returns 0 on success, -1 on failure.
                    371:  */
                    372: int
                    373: addr_pton(const char *p, struct xaddr *n)
                    374: {
                    375:        struct addrinfo hints, *ai;
                    376:
                    377:        memset(&hints, '\0', sizeof(hints));
                    378:        hints.ai_flags = AI_NUMERICHOST;
                    379:
                    380:        if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
                    381:                return -1;
                    382:
1.4       dtucker   383:        if (ai == NULL)
1.1       dtucker   384:                return -1;
                    385:
1.4       dtucker   386:        if (ai->ai_addr == NULL) {
                    387:                freeaddrinfo(ai);
                    388:                return -1;
                    389:        }
                    390:
1.1       dtucker   391:        if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen,
                    392:            n) == -1) {
                    393:                freeaddrinfo(ai);
                    394:                return -1;
                    395:        }
                    396:
                    397:        freeaddrinfo(ai);
                    398:        return 0;
                    399: }
                    400:
                    401: int
                    402: addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, socklen_t slen)
                    403: {
                    404:        struct addrinfo hints, *ai;
                    405:
                    406:        memset(&hints, '\0', sizeof(hints));
                    407:        hints.ai_flags = AI_NUMERICHOST;
                    408:
                    409:        if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0)
                    410:                return -1;
                    411:
1.4       dtucker   412:        if (ai == NULL)
1.1       dtucker   413:                return -1;
                    414:
1.4       dtucker   415:        if (ai->ai_addr == NULL) {
                    416:                freeaddrinfo(ai);
                    417:                return -1;
                    418:        }
                    419:
1.1       dtucker   420:        if (sa != NULL) {
1.4       dtucker   421:                if (slen < ai->ai_addrlen) {
                    422:                        freeaddrinfo(ai);
1.1       dtucker   423:                        return -1;
1.4       dtucker   424:                }
1.1       dtucker   425:                memcpy(sa, &ai->ai_addr, ai->ai_addrlen);
                    426:        }
                    427:
                    428:        freeaddrinfo(ai);
                    429:        return 0;
                    430: }
                    431:
                    432: int
                    433: addr_ntop(const struct xaddr *n, char *p, size_t len)
                    434: {
                    435:        struct sockaddr_storage ss;
                    436:        socklen_t slen = sizeof(ss);
                    437:
                    438:        if (addr_xaddr_to_sa(n, _SA(&ss), &slen, 0) == -1)
                    439:                return -1;
1.4       dtucker   440:        if (p == NULL || len == 0)
1.1       dtucker   441:                return -1;
                    442:        if (getnameinfo(_SA(&ss), slen, p, len, NULL, 0,
1.7       djm       443:            NI_NUMERICHOST) != 0)
1.1       dtucker   444:                return -1;
                    445:
                    446:        return 0;
                    447: }
                    448:
                    449: /*
                    450:  * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z).
                    451:  * Return -1 on parse error, -2 on inconsistency or 0 on success.
                    452:  */
                    453: int
                    454: addr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
                    455: {
                    456:        struct xaddr tmp;
1.8     ! deraadt   457:        u_int masklen = 999;
        !           458:        char addrbuf[64], *mp;
        !           459:        const char *errstr;
1.1       dtucker   460:
                    461:        /* Don't modify argument */
                    462:        if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf))
                    463:                return -1;
                    464:
                    465:        if ((mp = strchr(addrbuf, '/')) != NULL) {
                    466:                *mp = '\0';
                    467:                mp++;
1.8     ! deraadt   468:                masklen = (u_int)strtonum(mp, 0, INT_MAX, &errstr);
        !           469:                if (errstr)
1.1       dtucker   470:                        return -1;
                    471:        }
                    472:
                    473:        if (addr_pton(addrbuf, &tmp) == -1)
                    474:                return -1;
                    475:
                    476:        if (mp == NULL)
                    477:                masklen = addr_unicast_masklen(tmp.af);
                    478:        if (masklen_valid(tmp.af, masklen) == -1)
                    479:                return -2;
                    480:        if (addr_host_is_all0s(&tmp, masklen) != 0)
                    481:                return -2;
                    482:
                    483:        if (n != NULL)
                    484:                memcpy(n, &tmp, sizeof(*n));
                    485:        if (l != NULL)
                    486:                *l = masklen;
                    487:
                    488:        return 0;
                    489: }
                    490:
                    491: int
                    492: addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen)
                    493: {
                    494:        struct xaddr tmp_mask, tmp_result;
                    495:
                    496:        if (host->af != net->af)
                    497:                return -1;
                    498:
                    499:        if (addr_netmask(host->af, masklen, &tmp_mask) == -1)
                    500:                return -1;
                    501:        if (addr_and(&tmp_result, host, &tmp_mask) == -1)
                    502:                return -1;
                    503:        return addr_cmp(&tmp_result, net);
                    504: }