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

1.5     ! djm         1: /* $OpenBSD: addr.c,v 1.4 2021/10/22 10:51:57 dtucker 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>
                     28:
                     29: #include "addr.h"
                     30:
                     31: #define _SA(x) ((struct sockaddr *)(x))
                     32:
                     33: int
                     34: addr_unicast_masklen(int af)
                     35: {
                     36:        switch (af) {
                     37:        case AF_INET:
                     38:                return 32;
                     39:        case AF_INET6:
                     40:                return 128;
                     41:        default:
                     42:                return -1;
                     43:        }
                     44: }
                     45:
                     46: static inline int
                     47: masklen_valid(int af, u_int masklen)
                     48: {
                     49:        switch (af) {
                     50:        case AF_INET:
                     51:                return masklen <= 32 ? 0 : -1;
                     52:        case AF_INET6:
                     53:                return masklen <= 128 ? 0 : -1;
                     54:        default:
                     55:                return -1;
                     56:        }
                     57: }
                     58:
                     59: int
                     60: addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, socklen_t *len,
                     61:     u_int16_t port)
                     62: {
                     63:        struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
                     64:        struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
                     65:
                     66:        if (xa == NULL || sa == NULL || len == NULL)
                     67:                return -1;
                     68:
                     69:        switch (xa->af) {
                     70:        case AF_INET:
                     71:                if (*len < sizeof(*in4))
                     72:                        return -1;
                     73:                memset(sa, '\0', sizeof(*in4));
                     74:                *len = sizeof(*in4);
                     75: #ifdef SOCK_HAS_LEN
                     76:                in4->sin_len = sizeof(*in4);
                     77: #endif
                     78:                in4->sin_family = AF_INET;
                     79:                in4->sin_port = htons(port);
                     80:                memcpy(&in4->sin_addr, &xa->v4, sizeof(in4->sin_addr));
                     81:                break;
                     82:        case AF_INET6:
                     83:                if (*len < sizeof(*in6))
                     84:                        return -1;
                     85:                memset(sa, '\0', sizeof(*in6));
                     86:                *len = sizeof(*in6);
                     87: #ifdef SOCK_HAS_LEN
                     88:                in6->sin6_len = sizeof(*in6);
                     89: #endif
                     90:                in6->sin6_family = AF_INET6;
                     91:                in6->sin6_port = htons(port);
                     92:                memcpy(&in6->sin6_addr, &xa->v6, sizeof(in6->sin6_addr));
                     93:                in6->sin6_scope_id = xa->scope_id;
                     94:                break;
                     95:        default:
                     96:                return -1;
                     97:        }
                     98:        return 0;
                     99: }
                    100:
                    101: /*
                    102:  * Convert struct sockaddr to struct xaddr
                    103:  * Returns 0 on success, -1 on failure.
                    104:  */
                    105: int
                    106: addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
                    107: {
                    108:        struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
                    109:        struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
                    110:
                    111:        memset(xa, '\0', sizeof(*xa));
                    112:
                    113:        switch (sa->sa_family) {
                    114:        case AF_INET:
                    115:                if (slen < (socklen_t)sizeof(*in4))
                    116:                        return -1;
                    117:                xa->af = AF_INET;
                    118:                memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
                    119:                break;
                    120:        case AF_INET6:
                    121:                if (slen < (socklen_t)sizeof(*in6))
                    122:                        return -1;
                    123:                xa->af = AF_INET6;
                    124:                memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
                    125: #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
                    126:                xa->scope_id = in6->sin6_scope_id;
                    127: #endif
                    128:                break;
                    129:        default:
                    130:                return -1;
                    131:        }
                    132:
                    133:        return 0;
                    134: }
                    135:
                    136: int
                    137: addr_invert(struct xaddr *n)
                    138: {
                    139:        int i;
                    140:
                    141:        if (n == NULL)
                    142:                return -1;
                    143:
                    144:        switch (n->af) {
                    145:        case AF_INET:
                    146:                n->v4.s_addr = ~n->v4.s_addr;
                    147:                return 0;
                    148:        case AF_INET6:
                    149:                for (i = 0; i < 4; i++)
                    150:                        n->addr32[i] = ~n->addr32[i];
                    151:                return 0;
                    152:        default:
                    153:                return -1;
                    154:        }
                    155: }
                    156:
                    157: /*
                    158:  * Calculate a netmask of length 'l' for address family 'af' and
                    159:  * store it in 'n'.
                    160:  * Returns 0 on success, -1 on failure.
                    161:  */
                    162: int
                    163: addr_netmask(int af, u_int l, struct xaddr *n)
                    164: {
                    165:        int i;
                    166:
                    167:        if (masklen_valid(af, l) != 0 || n == NULL)
                    168:                return -1;
                    169:
                    170:        memset(n, '\0', sizeof(*n));
                    171:        switch (af) {
                    172:        case AF_INET:
                    173:                n->af = AF_INET;
                    174:                if (l == 0)
                    175:                        return 0;
                    176:                n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
                    177:                return 0;
                    178:        case AF_INET6:
                    179:                n->af = AF_INET6;
                    180:                for (i = 0; i < 4 && l >= 32; i++, l -= 32)
                    181:                        n->addr32[i] = 0xffffffffU;
                    182:                if (i < 4 && l != 0)
                    183:                        n->addr32[i] = htonl((0xffffffff << (32 - l)) &
                    184:                            0xffffffff);
                    185:                return 0;
                    186:        default:
                    187:                return -1;
                    188:        }
                    189: }
                    190:
                    191: int
                    192: addr_hostmask(int af, u_int l, struct xaddr *n)
                    193: {
                    194:        if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1)
                    195:                return -1;
                    196:        return 0;
                    197: }
                    198:
                    199: /*
                    200:  * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'.
                    201:  * Returns 0 on success, -1 on failure.
                    202:  */
                    203: int
                    204: addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
                    205: {
                    206:        int i;
                    207:
                    208:        if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
                    209:                return -1;
                    210:
                    211:        memcpy(dst, a, sizeof(*dst));
                    212:        switch (a->af) {
                    213:        case AF_INET:
                    214:                dst->v4.s_addr &= b->v4.s_addr;
                    215:                return 0;
                    216:        case AF_INET6:
                    217:                dst->scope_id = a->scope_id;
                    218:                for (i = 0; i < 4; i++)
                    219:                        dst->addr32[i] &= b->addr32[i];
                    220:                return 0;
                    221:        default:
                    222:                return -1;
                    223:        }
                    224: }
                    225:
                    226: int
                    227: addr_cmp(const struct xaddr *a, const struct xaddr *b)
                    228: {
                    229:        int i;
                    230:
                    231:        if (a->af != b->af)
                    232:                return (a->af == AF_INET6 ? 1 : -1);
                    233:
                    234:        switch (a->af) {
                    235:        case AF_INET:
                    236:                /*
                    237:                 * Can't just subtract here as 255.255.255.255 - 0.0.0.0 is
                    238:                 * too big to fit into a signed int
                    239:                 */
                    240:                if (a->v4.s_addr == b->v4.s_addr)
                    241:                        return 0;
                    242:                return (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1);
1.3       dtucker   243:        case AF_INET6:
1.1       dtucker   244:                /*
                    245:                 * Do this a byte at a time to avoid the above issue and
                    246:                 * any endian problems
                    247:                 */
                    248:                for (i = 0; i < 16; i++)
                    249:                        if (a->addr8[i] - b->addr8[i] != 0)
                    250:                                return (a->addr8[i] - b->addr8[i]);
                    251:                if (a->scope_id == b->scope_id)
                    252:                        return (0);
                    253:                return (a->scope_id > b->scope_id ? 1 : -1);
                    254:        default:
                    255:                return (-1);
                    256:        }
                    257: }
                    258:
                    259: int
                    260: addr_is_all0s(const struct xaddr *a)
                    261: {
                    262:        int i;
                    263:
                    264:        switch (a->af) {
                    265:        case AF_INET:
                    266:                return (a->v4.s_addr == 0 ? 0 : -1);
1.3       dtucker   267:        case AF_INET6:
1.1       dtucker   268:                for (i = 0; i < 4; i++)
                    269:                        if (a->addr32[i] != 0)
                    270:                                return -1;
                    271:                return 0;
                    272:        default:
                    273:                return -1;
                    274:        }
                    275: }
                    276:
                    277: /*
                    278:  * Test whether host portion of address 'a', as determined by 'masklen'
                    279:  * is all zeros.
1.2       dtucker   280:  * Returns 0 if host portion of address is all-zeros,
1.1       dtucker   281:  * -1 if not all zeros or on failure.
                    282:  */
                    283: int
                    284: addr_host_is_all0s(const struct xaddr *a, u_int masklen)
                    285: {
                    286:        struct xaddr tmp_addr, tmp_mask, tmp_result;
                    287:
                    288:        memcpy(&tmp_addr, a, sizeof(tmp_addr));
                    289:        if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
                    290:                return -1;
                    291:        if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1)
                    292:                return -1;
                    293:        return addr_is_all0s(&tmp_result);
                    294: }
                    295:
                    296: /*
1.2       dtucker   297:  * Parse string address 'p' into 'n'.
1.1       dtucker   298:  * Returns 0 on success, -1 on failure.
                    299:  */
                    300: int
                    301: addr_pton(const char *p, struct xaddr *n)
                    302: {
                    303:        struct addrinfo hints, *ai;
                    304:
                    305:        memset(&hints, '\0', sizeof(hints));
                    306:        hints.ai_flags = AI_NUMERICHOST;
                    307:
                    308:        if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
                    309:                return -1;
                    310:
1.4       dtucker   311:        if (ai == NULL)
1.1       dtucker   312:                return -1;
                    313:
1.4       dtucker   314:        if (ai->ai_addr == NULL) {
                    315:                freeaddrinfo(ai);
                    316:                return -1;
                    317:        }
                    318:
1.1       dtucker   319:        if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen,
                    320:            n) == -1) {
                    321:                freeaddrinfo(ai);
                    322:                return -1;
                    323:        }
                    324:
                    325:        freeaddrinfo(ai);
                    326:        return 0;
                    327: }
                    328:
                    329: int
                    330: addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, socklen_t slen)
                    331: {
                    332:        struct addrinfo hints, *ai;
                    333:
                    334:        memset(&hints, '\0', sizeof(hints));
                    335:        hints.ai_flags = AI_NUMERICHOST;
                    336:
                    337:        if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0)
                    338:                return -1;
                    339:
1.4       dtucker   340:        if (ai == NULL)
1.1       dtucker   341:                return -1;
                    342:
1.4       dtucker   343:        if (ai->ai_addr == NULL) {
                    344:                freeaddrinfo(ai);
                    345:                return -1;
                    346:        }
                    347:
1.1       dtucker   348:        if (sa != NULL) {
1.4       dtucker   349:                if (slen < ai->ai_addrlen) {
                    350:                        freeaddrinfo(ai);
1.1       dtucker   351:                        return -1;
1.4       dtucker   352:                }
1.1       dtucker   353:                memcpy(sa, &ai->ai_addr, ai->ai_addrlen);
                    354:        }
                    355:
                    356:        freeaddrinfo(ai);
                    357:        return 0;
                    358: }
                    359:
                    360: int
                    361: addr_ntop(const struct xaddr *n, char *p, size_t len)
                    362: {
                    363:        struct sockaddr_storage ss;
                    364:        socklen_t slen = sizeof(ss);
                    365:
                    366:        if (addr_xaddr_to_sa(n, _SA(&ss), &slen, 0) == -1)
                    367:                return -1;
1.4       dtucker   368:        if (p == NULL || len == 0)
1.1       dtucker   369:                return -1;
                    370:        if (getnameinfo(_SA(&ss), slen, p, len, NULL, 0,
                    371:            NI_NUMERICHOST) == -1)
                    372:                return -1;
                    373:
                    374:        return 0;
                    375: }
                    376:
                    377: /*
                    378:  * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z).
                    379:  * Return -1 on parse error, -2 on inconsistency or 0 on success.
                    380:  */
                    381: int
                    382: addr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
                    383: {
                    384:        struct xaddr tmp;
                    385:        long unsigned int masklen = 999;
                    386:        char addrbuf[64], *mp, *cp;
                    387:
                    388:        /* Don't modify argument */
                    389:        if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf))
                    390:                return -1;
                    391:
                    392:        if ((mp = strchr(addrbuf, '/')) != NULL) {
                    393:                *mp = '\0';
                    394:                mp++;
                    395:                masklen = strtoul(mp, &cp, 10);
1.5     ! djm       396:                if (*mp < '0' || *mp > '9' || *cp != '\0' || masklen > 128)
1.1       dtucker   397:                        return -1;
                    398:        }
                    399:
                    400:        if (addr_pton(addrbuf, &tmp) == -1)
                    401:                return -1;
                    402:
                    403:        if (mp == NULL)
                    404:                masklen = addr_unicast_masklen(tmp.af);
                    405:        if (masklen_valid(tmp.af, masklen) == -1)
                    406:                return -2;
                    407:        if (addr_host_is_all0s(&tmp, masklen) != 0)
                    408:                return -2;
                    409:
                    410:        if (n != NULL)
                    411:                memcpy(n, &tmp, sizeof(*n));
                    412:        if (l != NULL)
                    413:                *l = masklen;
                    414:
                    415:        return 0;
                    416: }
                    417:
                    418: int
                    419: addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen)
                    420: {
                    421:        struct xaddr tmp_mask, tmp_result;
                    422:
                    423:        if (host->af != net->af)
                    424:                return -1;
                    425:
                    426:        if (addr_netmask(host->af, masklen, &tmp_mask) == -1)
                    427:                return -1;
                    428:        if (addr_and(&tmp_result, host, &tmp_mask) == -1)
                    429:                return -1;
                    430:        return addr_cmp(&tmp_result, net);
                    431: }