Annotation of libelwix/src/net.c, revision 1.16.2.1

1.1       misho       1: /*************************************************************************
                      2: * (C) 2013 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
                      3: *  by Michael Pounov <misho@elwix.org>
                      4: *
                      5: * $Author: misho $
1.16.2.1! misho       6: * $Id: net.c,v 1.16 2016/08/02 12:03:56 misho Exp $
1.1       misho       7: *
                      8: **************************************************************************
                      9: The ELWIX and AITNET software is distributed under the following
                     10: terms:
                     11: 
                     12: All of the documentation and software included in the ELWIX and AITNET
                     13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
                     14: 
1.16.2.1! misho      15: Copyright 2004 - 2017
1.1       misho      16:        by Michael Pounov <misho@elwix.org>.  All rights reserved.
                     17: 
                     18: Redistribution and use in source and binary forms, with or without
                     19: modification, are permitted provided that the following conditions
                     20: are met:
                     21: 1. Redistributions of source code must retain the above copyright
                     22:    notice, this list of conditions and the following disclaimer.
                     23: 2. Redistributions in binary form must reproduce the above copyright
                     24:    notice, this list of conditions and the following disclaimer in the
                     25:    documentation and/or other materials provided with the distribution.
                     26: 3. All advertising materials mentioning features or use of this software
                     27:    must display the following acknowledgement:
                     28: This product includes software developed by Michael Pounov <misho@elwix.org>
                     29: ELWIX - Embedded LightWeight unIX and its contributors.
                     30: 4. Neither the name of AITNET nor the names of its contributors
                     31:    may be used to endorse or promote products derived from this software
                     32:    without specific prior written permission.
                     33: 
                     34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
                     35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     44: SUCH DAMAGE.
                     45: */
                     46: #include "global.h"
                     47: 
                     48: 
1.13      misho      49: #ifndef __linux__
1.6       misho      50: static char hexlist[] = "0123456789abcdef";
1.16.2.1! misho      51: 
        !            52: #ifndef HAVE_LINK_ADDR
        !            53: void
        !            54: link_addr(const char *addr, struct sockaddr_dl *sdl)
        !            55: {
        !            56:        char *cp = sdl->sdl_data;
        !            57:        char *cplim = sdl->sdl_len + (char *)sdl;
        !            58:        int byte = 0, state = NAMING, new;
        !            59: 
        !            60:        bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
        !            61:        sdl->sdl_family = AF_LINK;
        !            62:        do {
        !            63:                state &= ~LETTER;
        !            64:                if ((*addr >= '0') && (*addr <= '9')) {
        !            65:                        new = *addr - '0';
        !            66:                } else if ((*addr >= 'a') && (*addr <= 'f')) {
        !            67:                        new = *addr - 'a' + 10;
        !            68:                } else if ((*addr >= 'A') && (*addr <= 'F')) {
        !            69:                        new = *addr - 'A' + 10;
        !            70:                } else if (*addr == 0) {
        !            71:                        state |= END;
        !            72:                } else if (state == NAMING &&
        !            73:                           (((*addr >= 'A') && (*addr <= 'Z')) ||
        !            74:                           ((*addr >= 'a') && (*addr <= 'z'))))
        !            75:                        state |= LETTER;
        !            76:                else
        !            77:                        state |= DELIM;
        !            78:                addr++;
        !            79:                switch (state /* | INPUT */) {
        !            80:                case NAMING | DIGIT:
        !            81:                case NAMING | LETTER:
        !            82:                        *cp++ = addr[-1];
        !            83:                        continue;
        !            84:                case NAMING | DELIM:
        !            85:                        state = RESET;
        !            86:                        sdl->sdl_nlen = cp - sdl->sdl_data;
        !            87:                        continue;
        !            88:                case GOTTWO | DIGIT:
        !            89:                        *cp++ = byte;
        !            90:                        /* FALLTHROUGH */
        !            91:                case RESET | DIGIT:
        !            92:                        state = GOTONE;
        !            93:                        byte = new;
        !            94:                        continue;
        !            95:                case GOTONE | DIGIT:
        !            96:                        state = GOTTWO;
        !            97:                        byte = new + (byte << 4);
        !            98:                        continue;
        !            99:                default: /* | DELIM */
        !           100:                        state = RESET;
        !           101:                        *cp++ = byte;
        !           102:                        byte = 0;
        !           103:                        continue;
        !           104:                case GOTONE | END:
        !           105:                case GOTTWO | END:
        !           106:                        *cp++ = byte;
        !           107:                        /* FALLTHROUGH */
        !           108:                case RESET | END:
        !           109:                        break;
        !           110:                }
        !           111:                break;
        !           112:        } while (cp < cplim);
        !           113:        sdl->sdl_alen = cp - LLADDR(sdl);
        !           114:        new = cp - (char *)sdl;
        !           115:        if (new > sizeof(*sdl))
        !           116:                sdl->sdl_len = new;
        !           117:        return;
        !           118: }
        !           119: #endif
        !           120: 
1.6       misho     121: 
                    122: /*
                    123:  * e_link_ntoa() - String ethernet address from link address
                    124:  *
                    125:  * @sdl = link address
                    126:  * return: =NULL error or !=NULL ethernet address, should be e_free()
                    127:  */
                    128: char *
                    129: e_link_ntoa(const struct sockaddr_dl *sdl)
                    130: {
                    131:        static char obuf[64];
                    132:        char *out = obuf;
                    133:        int i;
                    134:        u_char *in = (u_char*) LLADDR(sdl);
                    135:        u_char *inlim = in + sdl->sdl_alen;
                    136:        int firsttime = 1;
                    137: 
                    138:        if (sdl->sdl_nlen) {
                    139:                memcpy(obuf, sdl->sdl_data, sdl->sdl_nlen);
                    140:                out += sdl->sdl_nlen;
                    141:                if (sdl->sdl_alen)
                    142:                        *out++ = '!';
                    143:        }
                    144: 
                    145:        while (in < inlim) {
                    146:                if (firsttime)
                    147:                        firsttime ^= firsttime;
                    148:                else
                    149:                        *out++ = ':';
1.8       misho     150: 
1.6       misho     151:                i = *in++;
                    152:                if (i > 0xf) {
                    153:                        out[1] = hexlist[i & 0xf];
                    154:                        i >>= 4;
1.8       misho     155:                } else {
                    156:                        out[1] = hexlist[i];
                    157:                        i = 0;
                    158:                }
1.6       misho     159: 
                    160:                out[0] = hexlist[i];
                    161:                out += 2;
                    162:        }
                    163: 
                    164:        *out = 0;
                    165:        return obuf;
                    166: }
                    167: 
1.1       misho     168: /*
1.11      misho     169:  * e_link_addr() - String ethernet address to link address
                    170:  *
                    171:  * @mac = ethernet address
                    172:  * @sdl = link address
                    173:  * return: -1 error or 0 ok
                    174:  */
                    175: int
                    176: e_link_addr(const char *mac, struct sockaddr_dl * __restrict sdl)
                    177: {
                    178:        if (!mac || !sdl)
                    179:                return -1;
                    180:        if (!sdl->sdl_len)
                    181:                sdl->sdl_len = sizeof(struct sockaddr_dl);
                    182: 
                    183:        link_addr(mac, sdl);
                    184:        return 0;
                    185: }
1.13      misho     186: #endif
1.11      misho     187: 
                    188: /*
1.1       misho     189:  * e_ether_ntoa() - Convert ethernet address to string
                    190:  *
                    191:  * @n = ethernet address structure, like struct ether_addr
                    192:  * @a = string
                    193:  * @len = string length
                    194:  * return: NULL error or !=NULL string a
                    195:  */
1.2       misho     196: char *
1.7       misho     197: e_ether_ntoa(const ether_addr_t * __restrict n, char * __restrict a, int len)
1.1       misho     198: {
                    199:        if (!n || !a)
                    200:                return NULL;
                    201: 
                    202:        memset(a, 0, len);
1.8       misho     203:        if (snprintf(a, len, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 
1.11      misho     204:                        n->octet[0], n->octet[1], 
                    205:                        n->octet[2], n->octet[3], 
                    206:                        n->octet[4], n->octet[5]) < 17)
1.1       misho     207:                return NULL;
                    208: 
                    209:        return a;
                    210: }
                    211: 
                    212: /*
                    213:  * e_ether_aton() - Convert string to ethernet address
                    214:  *
                    215:  * @a = string
                    216:  * @e = ethernet address structure, like struct ether_addr
                    217:  * return: NULL error or !=NULL ethernet address structure
                    218:  */
1.7       misho     219: ether_addr_t *
                    220: e_ether_aton(const char *a, ether_addr_t * __restrict e)
1.1       misho     221: {                       
                    222:        int i;
                    223: 
                    224:        if (!a || !e)
                    225:                return NULL;
                    226: 
1.8       misho     227:        i = sscanf(a, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", 
1.11      misho     228:                        &e->octet[0], 
                    229:                        &e->octet[1], 
                    230:                        &e->octet[2], 
                    231:                        &e->octet[3], 
                    232:                        &e->octet[4], 
                    233:                        &e->octet[5]);
1.1       misho     234:        if (i != 6)
                    235:                return NULL;
                    236: 
                    237:        return e;
                    238: }
                    239: 
                    240: /*
                    241:  * e_n2port() - Extract port from network structure
                    242:  *
                    243:  * @addr = Address
                    244:  * return: 0 not supported family type or port number
                    245:  */
1.2       misho     246: u_short
1.1       misho     247: e_n2port(sockaddr_t * __restrict addr)
                    248: {
                    249:        u_short port = 0;
                    250: 
                    251:        if (!addr)
                    252:                return port;
                    253: 
                    254:        switch (addr->sa.sa_family) {
                    255:                case AF_INET:
                    256:                        return ntohs(addr->sin.sin_port);
                    257:                case AF_INET6:
                    258:                        return ntohs(addr->sin6.sin6_port);
                    259:                default:
                    260:                        break;
                    261:        }
                    262: 
                    263:        return port;
                    264: }
                    265: 
                    266: /*
                    267:  * e_n2addr() - Extract address from network structure
                    268:  *
                    269:  * @addr = Address
                    270:  * @val = Value for store string address
                    271:  * return: NULL error or !=NULL string address from val
                    272:  */
                    273: const char *
                    274: e_n2addr(sockaddr_t * __restrict addr, ait_val_t * __restrict val)
                    275: {
1.13      misho     276: #ifndef __linux__
                    277:        char *s;
                    278: #endif
                    279:        char str[INET6_ADDRSTRLEN] = { 0 };
1.1       misho     280:        const char *ret = NULL;
                    281: 
                    282:        if (!addr || !val)
                    283:                return ret;
                    284: 
                    285:        AIT_INIT_VAL(val);
                    286:        switch (addr->sa.sa_family) {
                    287:                case AF_INET:
                    288:                        if (!inet_ntop(AF_INET, &addr->sin.sin_addr, str, INET_ADDRSTRLEN)) {
                    289:                                LOGERR;
                    290:                                return ret;
                    291:                        } else
                    292:                                ret = str;
                    293:                        break;
                    294:                case AF_INET6:
                    295:                        if (!inet_ntop(AF_INET6, &addr->sin6.sin6_addr, str, INET6_ADDRSTRLEN)) {
                    296:                                LOGERR;
                    297:                                return ret;
                    298:                        } else
                    299:                                ret = str;
                    300:                        break;
                    301:                case AF_LOCAL:
                    302:                        ret = addr->sun.sun_path;
                    303:                        break;
1.13      misho     304: #ifndef __linux__
1.5       misho     305:                case AF_LINK:
1.6       misho     306:                        if (!(s = e_link_ntoa(&addr->sdl))) {
1.5       misho     307:                                LOGERR;
                    308:                                return ret;
                    309:                        } else
                    310:                                ret = s;
                    311:                        break;
1.13      misho     312: #endif
1.1       misho     313:                default:
                    314:                        elwix_SetErr(EPROTONOSUPPORT, "Unsuported address family %d", 
                    315:                                        addr->sa.sa_family);
                    316:                        return ret;
                    317:        }
                    318: 
                    319:        AIT_SET_STR(val, ret);
                    320:        return (const char*) AIT_GET_STR(val);
                    321: }
                    322: 
                    323: /*
                    324:  * e_gethostbyname() - Get host and port and make network structure
                    325:  *
                    326:  * @psHost = Hostname
                    327:  * @port = Port
                    328:  * @addr = Network address structure
1.15      misho     329:  * return: 0 is error or >0 length of network structure
1.1       misho     330:  */
1.14      misho     331: socklen_t 
1.1       misho     332: e_gethostbyname(const char *psHost, u_short port, sockaddr_t * __restrict addr)
                    333: {
                    334:        struct hostent *host = NULL;
                    335: 
                    336:        if (!psHost || !addr)
1.14      misho     337:                return 0;
1.1       misho     338: 
                    339:        if (*psHost != '/') {
                    340:                /* resolver */
1.10      misho     341:                host = gethostbyname2(psHost, !strchr(psHost, ':') ? AF_INET : AF_INET6);
1.1       misho     342:                if (!host) {
                    343:                        elwix_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
1.14      misho     344:                        return 0;
1.1       misho     345:                } else {
                    346:                        memset(addr, 0, sizeof(sockaddr_t));
                    347:                        addr->sa.sa_family = host->h_addrtype;
                    348:                }
                    349:        } else {
                    350:                memset(addr, 0, sizeof(sockaddr_t));
                    351:                addr->sa.sa_family = AF_LOCAL;
                    352:        }
                    353:                
                    354: 
                    355:        switch (addr->sa.sa_family) {
                    356:                case AF_INET:
1.13      misho     357: #ifndef __linux__
1.1       misho     358:                        addr->sin.sin_len = sizeof(struct sockaddr_in);
1.13      misho     359: #endif
1.1       misho     360:                        addr->sin.sin_family = AF_INET;
                    361:                        addr->sin.sin_port = htons(port);
                    362:                        memcpy(&addr->sin.sin_addr, host->h_addr, sizeof addr->sin.sin_addr);
1.14      misho     363:                        return sizeof addr->sin;
1.1       misho     364:                case AF_INET6:
1.13      misho     365: #ifndef __linux__
1.1       misho     366:                        addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
1.13      misho     367: #endif
1.1       misho     368:                        addr->sin6.sin6_family = AF_INET6;
                    369:                        addr->sin6.sin6_port = htons(port);
                    370:                        memcpy(&addr->sin6.sin6_addr, host->h_addr, sizeof addr->sin6.sin6_addr);
1.14      misho     371:                        return sizeof addr->sin6;
1.1       misho     372:                case AF_LOCAL:
1.13      misho     373: #ifndef __linux__
1.1       misho     374:                        addr->sun.sun_len = sizeof(struct sockaddr_un);
1.13      misho     375: #endif
1.1       misho     376:                        addr->sun.sun_family = AF_LOCAL;
                    377:                        memset(addr->sun.sun_path, 0, sizeof addr->sun.sun_path);
                    378:                        snprintf(addr->sun.sun_path, sizeof addr->sun.sun_path, "%s-%hu", psHost, port);
1.14      misho     379:                        return sizeof addr->sun;
1.1       misho     380:                default:
                    381:                        elwix_SetErr(EPROTONOSUPPORT, "Unsuported address family %d", addr->sa.sa_family);
                    382:                        break;
                    383:        }
                    384: 
1.14      misho     385:        return 0;
1.15      misho     386: }
                    387: 
                    388: /*
                    389:  * e_addrlen() - Get address length from network structure
                    390:  *
                    391:  * @addr = address
                    392:  * return: 0 is error or >0 length of network structure
                    393:  */
                    394: socklen_t
                    395: e_addrlen(const sockaddr_t *addr)
                    396: {
                    397:        if (!addr)
                    398:                return 0;
                    399: 
                    400:        switch (addr->sa.sa_family) {
                    401:                case AF_INET:
                    402:                        return sizeof addr->sin;
                    403:                case AF_INET6:
                    404:                        return sizeof addr->sin6;
                    405:                case AF_LOCAL:
                    406:                        return sizeof addr->sun;
                    407: #ifndef __linux__
                    408:                case AF_LINK:
                    409:                        return sizeof addr->sdl;
                    410: #endif
                    411:        }
                    412: 
1.16      misho     413:        return E_SOCKADDR_MAX;
1.1       misho     414: }
                    415: 
                    416: /*
                    417:  * e_addrcmp() - Compare network addresses
                    418:  *
                    419:  * @a = 1st address
                    420:  * @b = 2nd address
                    421:  * @p = compare and ports, if family is AF_INET or AF_INET6
                    422:  * return: 0 is equal or !=0 is different
                    423:  */
                    424: int
                    425: e_addrcmp(sockaddr_t * __restrict a, sockaddr_t * __restrict b, int p)
                    426: {
                    427:        if (a && b && a->sa.sa_family == b->sa.sa_family)
                    428:                switch (a->sa.sa_family) {
                    429:                        case AF_LOCAL:
                    430:                                return strcmp(a->sun.sun_path, b->sun.sun_path);
                    431:                        case AF_INET:
                    432:                                if (p && (a->sin.sin_port - b->sin.sin_port))
                    433:                                        return (int) !!(a->sin.sin_port - b->sin.sin_port);
                    434:                                else
                    435:                                        return memcmp(&a->sin.sin_addr, &b->sin.sin_addr, 
                    436:                                                        sizeof a->sin.sin_addr);
                    437:                        case AF_INET6:
                    438:                                if (p && (a->sin6.sin6_port - b->sin6.sin6_port))
                    439:                                        return (int) !!(a->sin6.sin6_port - b->sin6.sin6_port);
                    440:                                else
                    441:                                        return memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr, 
                    442:                                                        sizeof a->sin6.sin6_addr);
1.13      misho     443: #ifndef __linux__
1.1       misho     444:                        case AF_LINK:
                    445:                                return memcmp(&a->sdl.sdl_data, &b->sdl.sdl_data, 
                    446:                                                sizeof a->sdl.sdl_data);
1.13      misho     447: #endif
1.11      misho     448:                        case AF_UNSPEC:
                    449:                                return memcmp(a, b, sizeof(sockaddr_t));
1.1       misho     450:                }
                    451: 
                    452:        return (int) !!(a - b);
                    453: }
                    454: 
                    455: /*
                    456:  * e_usleep() - usleep() replacement for ELWIX
                    457:  *
                    458:  * @usec = microseconds for sleep
                    459:  * return: -1 interrupted by signal or 0 ok
                    460:  */
1.2       misho     461: int
1.1       misho     462: e_usleep(u_int usec)
                    463: {
                    464:        struct timeval tv = { (time_t) (usec / 1000000), (long) (usec % 1000000) };
                    465: 
                    466:        return select(0, NULL, NULL, NULL, &tv);
                    467: }
1.3       misho     468: 
                    469: /*
                    470:  * e_innet() - Test address match in network
                    471:  *
                    472:  * @net = network
                    473:  * @addr = address
                    474:  * return: -1 error, 0 match or 1 not match
                    475:  */
                    476: int
                    477: e_innet(netaddr_t * __restrict net, inaddr_t * __restrict addr)
                    478: {
                    479:        register int i;
                    480:        int ret = 0;
                    481: 
                    482:        if (!net || !addr)
                    483:                return -1;
                    484: 
                    485:        switch (net->addr.sa.sa_family) {
                    486:                case AF_INET:
                    487:                        for (i = 0; i < sizeof(struct in_addr); i++) {
                    488:                                ret = ((caddr_t) &net->addr.sin.sin_addr.s_addr)[i] & 
                    489:                                        net->mask.in.s4_addr[i];
                    490:                                ret -= addr->in.s4_addr[i] & net->mask.in.s4_addr[i];
                    491:                                if (ret)
                    492:                                        break;
                    493:                        }
                    494:                        break;
                    495:                case AF_INET6:
                    496:                        for (i = 0; i < sizeof(struct in6_addr); i++) {
                    497:                                ret = net->addr.sin6.sin6_addr.s6_addr[i] & 
                    498:                                        net->mask.in6.s6_addr[i];
                    499:                                ret -= addr->in6.s6_addr[i] & net->mask.in6.s6_addr[i];
                    500:                                if (ret)
                    501:                                        break;
                    502:                        }
                    503:                        break;
                    504:                default:
                    505:                        return -1;
                    506:        }
                    507: 
                    508:        return !!ret;
                    509: }
1.4       misho     510: 
                    511: /*
                    512:  * e_getnet() - Get network from string
                    513:  *
                    514:  * @net = Network string (format: <net[/cidr]>)
                    515:  * return: NULL error or !=NULL network should be e_free()
                    516:  */
                    517: netaddr_t *
                    518: e_getnet(const char *net)
                    519: {
                    520:        netaddr_t *n;
                    521:        char *str, *wrk;
                    522:        struct hostent *host;
                    523: 
                    524:        n = e_malloc(sizeof(netaddr_t));
                    525:        if (!n) {
                    526:                LOGERR;
                    527:                return NULL;
                    528:        } else
                    529:                memset(n, 0, sizeof(netaddr_t));
                    530:        str = e_strdup(net);
                    531:        if (!str) {
                    532:                LOGERR;
                    533:                e_free(n);
                    534:                return NULL;
                    535:        }
                    536:        wrk = strchr(str, '/');
                    537:        if (wrk)
                    538:                *wrk++ = 0;
                    539: 
                    540:        host = gethostbyname2(str, strchr(str, ':') ? AF_INET6 : AF_INET);
                    541:        if (!host) {
                    542:                elwix_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
                    543:                e_free(str);
                    544:                e_free(n);
                    545:                return NULL;
                    546:        }
                    547:        switch (host->h_addrtype) {
                    548:                case AF_INET:
1.13      misho     549: #ifndef __linux__
1.4       misho     550:                        n->addr.sin.sin_len = sizeof(struct sockaddr_in);
1.13      misho     551: #endif
1.4       misho     552:                        n->addr.sin.sin_family = host->h_addrtype;
                    553:                        memcpy(&n->addr.sin.sin_addr, host->h_addr, sizeof n->addr.sin.sin_addr);
                    554:                        if (wrk)
                    555:                                n->mask.in.s_addr = E_CIDRMASK(strtol(wrk, NULL, 10));
                    556:                        else
                    557:                                n->mask.in.s_addr = 0xFFFFFFFF;
                    558:                        break;
                    559:                case AF_INET6:
1.13      misho     560: #ifndef __linux__
1.4       misho     561:                        n->addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
1.13      misho     562: #endif
1.4       misho     563:                        n->addr.sin6.sin6_family = host->h_addrtype;
                    564:                        memcpy(&n->addr.sin6.sin6_addr, host->h_addr, sizeof n->addr.sin6.sin6_addr);
                    565:                        /* TODO: should support ipv6 mask */
                    566:                        break;
                    567:                default:
                    568:                        elwix_SetErr(EINVAL, "Unsupported family #%d", host->h_addrtype);
                    569:                        e_free(str);
                    570:                        e_free(n);
                    571:                        return NULL;
                    572:        }
                    573: 
                    574:        e_free(str);
                    575:        return n;
                    576: }
1.7       misho     577: 
                    578: /*
                    579:  * e_ether_addr() - Get or set ethernet address from interface name
                    580:  *
                    581:  * @ifname = interface name
1.13      misho     582:  * @addr = if addr is !=NULL then set new ethernet address
                    583:  * return: NULL error or !=NULL get current ethernet address should be e_free()
1.7       misho     584:  */
                    585: ether_addr_t *
                    586: e_ether_addr(const char *ifname, ether_addr_t * __restrict addr)
                    587: {
                    588:        ether_addr_t *a = NULL;
                    589:        struct ifaddrs *p, *ifa = NULL;
1.13      misho     590:        struct ifreq req;
                    591:        int s;
                    592:        sockaddr_t sa = E_SOCKADDR_INIT;
1.7       misho     593: 
1.13      misho     594:        memset(&req, 0, sizeof req);
1.7       misho     595:        if (!ifname)
                    596:                return NULL;
                    597: 
                    598:        getifaddrs(&ifa);
1.13      misho     599:        for (p = ifa; p && p->ifa_name; p = p->ifa_next) {
                    600: #ifndef __linux__
1.7       misho     601:                if (p->ifa_name && !strcmp(p->ifa_name, ifname) && p->ifa_addr && 
                    602:                                p->ifa_addr->sa_family == AF_LINK) {
1.13      misho     603:                        a = e_malloc(sizeof(ether_addr_t));
                    604:                        if (a)
                    605:                                memcpy(a, LLADDR((struct sockaddr_dl*) p->ifa_addr), 
                    606:                                                sizeof(ether_addr_t));
                    607: 
                    608:                        /* should set mac address */
                    609:                        if (addr && (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) > 0) {
                    610:                                strlcpy(req.ifr_name, ifname, sizeof req.ifr_name);
                    611:                                sa.sa.sa_family = AF_LINK;
                    612:                                sa.sa.sa_len = sizeof(ether_addr_t);
                    613:                                memcpy(sa.sa.sa_data, addr, sizeof(ether_addr_t));
                    614:                                req.ifr_ifru.ifru_addr = sa.sa;
                    615:                                ioctl(s, SIOCSIFLLADDR, &req);
                    616:                                close(s);
                    617:                        }
1.7       misho     618:                        break;
                    619:                }
1.13      misho     620: #else
                    621:                if (p->ifa_name && !strcmp(p->ifa_name, ifname)) {
                    622:                        s = socket(AF_INET, SOCK_DGRAM, 0);
                    623:                        if (s == -1)
                    624:                                break;
                    625:                        strlcpy(req.ifr_name, ifname, sizeof req.ifr_name);
                    626:                        if (!ioctl(s, SIOCGIFHWADDR, &req)) {
                    627:                                a = e_malloc(sizeof(ether_addr_t));
                    628:                                if (a)
                    629:                                        memcpy(a, req.ifr_addr.sa_data, sizeof(ether_addr_t));
                    630: 
                    631:                                /* should set mac address */
                    632:                                if (addr) {
                    633:                                        memset(&req, 0, sizeof req);
                    634:                                        strlcpy(req.ifr_name, ifname, sizeof req.ifr_name);
                    635:                                        sa.sa.sa_family = ARPHRD_ETHER;
                    636:                                        memcpy(sa.sa.sa_data, addr, sizeof(ether_addr_t));
                    637:                                        req.ifr_hwaddr = sa.sa;
                    638:                                        ioctl(s, SIOCSIFHWADDR, &req);
                    639:                                }
                    640:                        }
                    641:                        close(s);
                    642:                        break;
                    643:                }
                    644: #endif
                    645:        }
1.7       misho     646:        freeifaddrs(ifa);
                    647: 
                    648:        return a;
                    649: }
1.11      misho     650: 
                    651: /*
                    652:  * e_get1stiface() - Get first interface of host
                    653:  *
                    654:  * @szIface = interface string buffer
                    655:  * @iflen = size of interface buffer
                    656:  * return: -1 error or 0 ok
                    657:  */
                    658: int
                    659: e_get1stiface(char *szIface, int iflen)
                    660: {
                    661:        struct ifaddrs *ifa;
                    662: 
                    663:        if (!szIface || !iflen)
                    664:                return -1;
                    665: 
                    666:        getifaddrs(&ifa);
                    667:        strlcpy(szIface, ifa->ifa_name, iflen);
                    668:        freeifaddrs(ifa);
                    669:        return 0;
                    670: }
                    671: 
1.13      misho     672: #ifndef __linux__
1.11      misho     673: /*
                    674:  * e_getifacebyname() - Get interface and make network structure
                    675:  *
                    676:  * @psIface = Interface, if =NULL first interface
                    677:  * @addr = Network address structure
                    678:  * return: NULL error or !=NULL network structure
                    679:  */
                    680: sockaddr_t *
                    681: e_getifacebyname(const char *psIface, sockaddr_t * __restrict addr)
                    682: {
                    683:        char szIface[64] = { [0 ... 63] = 0 };
                    684:        struct ifaddrs *p, *ifa = NULL;
                    685: 
                    686:        if (!addr)
                    687:                return NULL;
                    688: 
                    689:        memset(addr, 0, sizeof(sockaddr_t));
                    690:        getifaddrs(&ifa);
                    691:        strlcpy(szIface, psIface ? psIface : ifa->ifa_name, sizeof szIface);
1.13      misho     692:        for (p = ifa; p && p->ifa_name; p = p->ifa_next)
1.11      misho     693:                if (p->ifa_name && !strcmp(p->ifa_name, szIface) && p->ifa_addr && 
                    694:                                p->ifa_addr->sa_family == AF_LINK) {
                    695:                        memcpy(&addr->sdl, p->ifa_addr, sizeof(struct sockaddr_dl));
                    696:                        break;
                    697:                }
                    698:        freeifaddrs(ifa);
                    699: 
                    700:        return addr;
                    701: }
                    702: 
                    703: /*
                    704:  * e_getlinkbyname() - Get host ethernet address and make network structure
                    705:  *
                    706:  * @psHost = Host ethernet address
                    707:  * @addr = Network address structure
                    708:  * return: NULL error or !=NULL network structure
                    709:  */
                    710: sockaddr_t *
                    711: e_getlinkbyname(const char *psHost, sockaddr_t * __restrict addr)
                    712: {
                    713:        ait_val_t v;
                    714:        sockaddr_t *a = addr;
                    715: 
                    716:        if (!psHost || !addr)
                    717:                return NULL;
                    718:        else
                    719:                memset(addr, 0, sizeof(sockaddr_t));
                    720: 
                    721:        AIT_INIT_VAL2(&v, string);
                    722:        if (!strchr(psHost, '.'))
                    723:                AIT_SET_STR(&v, ":");
                    724:        AIT_SET_STRCAT(&v, psHost);
                    725: 
                    726:        addr->sdl.sdl_len = sizeof(struct sockaddr_dl);
                    727:        if (e_link_addr(AIT_GET_STR(&v), &addr->sdl))
                    728:                a = NULL;
                    729: 
                    730:        AIT_FREE_VAL(&v);
                    731:        return a;
                    732: }
                    733: 
                    734: /*
                    735:  * e_getlinkbyether() - Get ethernet address and make network structure
                    736:  *
                    737:  * @mac = Ethernet address
                    738:  * @idx = Interface index
                    739:  * @type = Interface type
                    740:  * @iface = Interface name
                    741:  * @addr = Network address structure
                    742:  * return: NULL error or !=NULL network structure
                    743:  */
                    744: sockaddr_t *
                    745: e_getlinkbyether(const ether_addr_t * __restrict mac, u_short idx, u_char type, 
                    746:                const char *iface, sockaddr_t * __restrict addr)
                    747: {
                    748:        sockaddr_t *a = addr;
                    749: 
                    750:        if (!addr)
                    751:                return NULL;
                    752:        else
                    753:                memset(addr, 0, sizeof(sockaddr_t));
                    754: 
                    755:        addr->sdl.sdl_len = sizeof(struct sockaddr_dl);
                    756:        addr->sdl.sdl_family = AF_LINK;
                    757:        addr->sdl.sdl_index = idx;
                    758:        addr->sdl.sdl_type = type;
                    759:        if (iface && *iface) {
                    760:                addr->sdl.sdl_nlen = strlen(iface);
                    761:                memcpy(addr->sdl.sdl_data, iface, addr->sdl.sdl_nlen);
                    762:        }
                    763:        addr->sdl.sdl_alen = sizeof(ether_addr_t);
                    764:        memcpy(LLADDR(&addr->sdl), mac, addr->sdl.sdl_alen);
                    765: 
                    766:        return a;
                    767: }
1.13      misho     768: #endif

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