Annotation of embedaddon/libpdel/net/if_iface.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (c) 2001-2002 Packet Design, LLC.
        !             4:  * All rights reserved.
        !             5:  * 
        !             6:  * Subject to the following obligations and disclaimer of warranty,
        !             7:  * use and redistribution of this software, in source or object code
        !             8:  * forms, with or without modifications are expressly permitted by
        !             9:  * Packet Design; provided, however, that:
        !            10:  * 
        !            11:  *    (i)  Any and all reproductions of the source or object code
        !            12:  *         must include the copyright notice above and the following
        !            13:  *         disclaimer of warranties; and
        !            14:  *    (ii) No rights are granted, in any manner or form, to use
        !            15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
        !            16:  *         on advertising, endorsements, or otherwise except as such
        !            17:  *         appears in the above copyright notice or in the software.
        !            18:  * 
        !            19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
        !            20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
        !            21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
        !            22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
        !            23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
        !            24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
        !            25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
        !            26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
        !            27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
        !            28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
        !            29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
        !            30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
        !            31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
        !            32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
        !            33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
        !            35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
        !            36:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            37:  *
        !            38:  * Author: Archie Cobbs <archie@freebsd.org>
        !            39:  */
        !            40: 
        !            41: #include <sys/types.h>
        !            42: #include <sys/param.h>
        !            43: #include <sys/socket.h>
        !            44: #include <sys/sysctl.h>
        !            45: #include <sys/sockio.h>
        !            46: 
        !            47: #include <net/if.h>
        !            48: #include <net/if_dl.h>
        !            49: #include <net/route.h>
        !            50: 
        !            51: #include <netinet/in.h>
        !            52: #include <arpa/inet.h>
        !            53: 
        !            54: #include <stdio.h>
        !            55: #include <stdlib.h>
        !            56: #include <stdarg.h>
        !            57: #include <unistd.h>
        !            58: #include <string.h>
        !            59: #include <errno.h>
        !            60: #include <err.h>
        !            61: 
        !            62: #include "structs/structs.h"
        !            63: #include "structs/type/array.h"
        !            64: 
        !            65: #include "util/typed_mem.h"
        !            66: #include "net/if_util.h"
        !            67: 
        !            68: #define ROUNDUP(a) \
        !            69:        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
        !            70: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
        !            71: 
        !            72: static struct  if_msghdr *if_find(const char *ifname,
        !            73:                        u_char **bufp, const char *mtype);
        !            74: static int     if_info(u_char **bufp, const char *mtype);
        !            75: 
        !            76: /*
        !            77:  * Get list of IP addresses and netmasks configured on an interface.
        !            78:  */
        !            79: int
        !            80: if_get_ip_addrs(const char *ifname, struct in_addr **iplistp,
        !            81:        struct in_addr **nmlistp, const char *mtype)
        !            82: {
        !            83:        struct if_msghdr *ifm;
        !            84:        struct ifa_msghdr *ifam;
        !            85:        struct in_addr *iplist = NULL;
        !            86:        struct in_addr *nmlist = NULL;
        !            87:        int errno_save;
        !            88:        int num = 0;
        !            89:        u_char *buf;
        !            90: 
        !            91:        /* Find interface info */
        !            92:        if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
        !            93:                return (-1);
        !            94: 
        !            95:        /* Search for first IP address */
        !            96:        for (ifam = (struct ifa_msghdr *)(void *)
        !            97:              ((u_char *)ifm + ifm->ifm_msglen);
        !            98:            ifam->ifam_type == RTM_NEWADDR;
        !            99:            ifam = (struct ifa_msghdr *)(void *)
        !           100:              ((u_char *)ifam + ifam->ifam_msglen))
        !           101:                num++;
        !           102: 
        !           103:        /* Allocate arrays */
        !           104:        if ((iplist = MALLOC(mtype, num * sizeof(*iplist))) == NULL
        !           105:            || (nmlist = MALLOC(mtype, num * sizeof(*nmlist))) == NULL) {
        !           106:                errno_save = errno;
        !           107:                FREE(mtype, iplist);                            /* ok if NULL */
        !           108:                FREE(TYPED_MEM_TEMP, buf);
        !           109:                errno = errno_save;
        !           110:                return (-1);
        !           111:        }
        !           112: 
        !           113:        /* Search for IP address/netmask combinations */
        !           114:        num = 0;
        !           115:        for (ifam = (struct ifa_msghdr *)(void *)
        !           116:             ((u_char *)ifm + ifm->ifm_msglen);
        !           117:            ifam->ifam_type == RTM_NEWADDR;
        !           118:            ifam = (struct ifa_msghdr *)(void *)
        !           119:              ((u_char *)ifam + ifam->ifam_msglen)) {
        !           120:                char *cp = (char *)(ifam + 1);
        !           121:                int need = RTA_IFA | RTA_NETMASK;
        !           122:                int i;
        !           123: 
        !           124:                /* Find IP address and netmask, if any */
        !           125:                if ((ifam->ifam_addrs & need) != need)
        !           126:                        continue;
        !           127:                for (i = 1; i != 0 && need != 0; i <<= 1) {
        !           128:                        if ((ifam->ifam_addrs & i) == 0)
        !           129:                                continue;
        !           130:                        if (i == RTA_IFA
        !           131:                            && ((struct sockaddr *)(void *)cp)->sa_family
        !           132:                              == AF_INET) {
        !           133:                                iplist[num] = ((struct sockaddr_in *)
        !           134:                                    (void *)cp)->sin_addr;
        !           135:                        } else if (i == RTA_NETMASK) {
        !           136:                                nmlist[num] = ((struct sockaddr_in *)
        !           137:                                    (void *)cp)->sin_addr;
        !           138:                        }
        !           139:                        need &= ~i;
        !           140:                        ADVANCE(cp, (struct sockaddr *)cp);
        !           141:                }
        !           142:                if (need == 0)
        !           143:                        num++;
        !           144:        }
        !           145: 
        !           146:        /* Done */
        !           147:        FREE(TYPED_MEM_TEMP, buf);
        !           148:        *iplistp = iplist;
        !           149:        *nmlistp = nmlist;
        !           150:        return (num);
        !           151: }
        !           152: 
        !           153: /*
        !           154:  * Get the first IP address on an interface.
        !           155:  */
        !           156: int
        !           157: if_get_ip_addr(const char *ifname, struct in_addr *ipp, struct in_addr *nmp)
        !           158: {
        !           159:        struct in_addr *iplist;
        !           160:        struct in_addr *nmlist;
        !           161:        int nip;
        !           162: 
        !           163:        if ((nip = if_get_ip_addrs(ifname,
        !           164:            &iplist, &nmlist, TYPED_MEM_TEMP)) == -1)
        !           165:                return (-1);
        !           166:        if (nip == 0) {
        !           167:                FREE(TYPED_MEM_TEMP, iplist);
        !           168:                FREE(TYPED_MEM_TEMP, nmlist);
        !           169:                errno = ENOENT;
        !           170:                return (-1);
        !           171:        }
        !           172:        if (ipp != NULL)
        !           173:                *ipp = iplist[0];
        !           174:        if (nmp != NULL)
        !           175:                *nmp = nmlist[0];
        !           176:        FREE(TYPED_MEM_TEMP, iplist);
        !           177:        FREE(TYPED_MEM_TEMP, nmlist);
        !           178:        return (0);
        !           179: }
        !           180: 
        !           181: /*
        !           182:  * Get the flags associated with an interface.
        !           183:  */
        !           184: int
        !           185: if_get_flags(const char *ifname)
        !           186: {
        !           187:        struct if_msghdr *ifm;
        !           188:        u_char *buf;
        !           189:        int rtn;
        !           190: 
        !           191:        if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
        !           192:                return (-1);
        !           193:        rtn = ifm->ifm_flags;
        !           194:        FREE(TYPED_MEM_TEMP, buf);
        !           195:        return (rtn);
        !           196: }
        !           197: 
        !           198: /*
        !           199:  * Set the flags associated with an interface.
        !           200:  */
        !           201: int
        !           202: if_set_flags(const char *ifname, int flags)
        !           203: {
        !           204:        struct ifreq ifr;
        !           205:        int r;
        !           206:        int s;
        !           207: 
        !           208:        if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
        !           209:                return (-1);
        !           210:        memset(&ifr, 0, sizeof(ifr));
        !           211:        strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
        !           212:        ifr.ifr_flags = flags;
        !           213:        r = ioctl(s, SIOCSIFFLAGS, (char *)&ifr);
        !           214:        (void)close(s);
        !           215:        return (r);
        !           216: }
        !           217: 
        !           218: /*
        !           219:  * Get the MTU associated with an interface.
        !           220:  */
        !           221: int
        !           222: if_get_mtu(const char *ifname)
        !           223: {
        !           224:        struct if_msghdr *ifm;
        !           225:        u_char *buf;
        !           226:        int rtn;
        !           227: 
        !           228:        if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
        !           229:                return (-1);
        !           230:        rtn = ifm->ifm_data.ifi_mtu;
        !           231:        FREE(TYPED_MEM_TEMP, buf);
        !           232:        return (rtn);
        !           233: }
        !           234: 
        !           235: /*
        !           236:  * Set the MTU associated with an interface.
        !           237:  */
        !           238: int
        !           239: if_set_mtu(const char *ifname, u_int mtu)
        !           240: {
        !           241:        struct ifreq ifr;
        !           242:        int r;
        !           243:        int s;
        !           244: 
        !           245:        if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
        !           246:                return (-1);
        !           247:        memset(&ifr, 0, sizeof(ifr));
        !           248:        strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
        !           249:        ifr.ifr_mtu = mtu;
        !           250:        r = ioctl(s, SIOCSIFMTU, (char *)&ifr);
        !           251:        (void)close(s);
        !           252:        return (r);
        !           253: }
        !           254: 
        !           255: /*
        !           256:  * Get the interface type.
        !           257:  */
        !           258: int
        !           259: if_get_type(const char *ifname)
        !           260: {
        !           261:        struct if_msghdr *ifm;
        !           262:        u_char *buf;
        !           263:        int rtn;
        !           264: 
        !           265:        if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
        !           266:                return (-1);
        !           267:        rtn = ifm->ifm_data.ifi_type;
        !           268:        FREE(TYPED_MEM_TEMP, buf);
        !           269:        return (rtn);
        !           270: }
        !           271: 
        !           272: /*
        !           273:  * Get the link address for an interface.
        !           274:  */
        !           275: int
        !           276: if_get_link_addr(const char *ifname,
        !           277:        struct sockaddr_dl **sdlp, const char *mtype)
        !           278: {
        !           279:        struct if_msghdr *ifm;
        !           280:        struct sockaddr_dl *sdl;
        !           281:        int errno_save;
        !           282:        u_char *buf;
        !           283: 
        !           284:        if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
        !           285:                return (-1);
        !           286:        sdl = (struct sockaddr_dl *)(ifm + 1);
        !           287:        if ((*sdlp = MALLOC(mtype, sdl->sdl_len)) == NULL) {
        !           288:                errno_save = errno;
        !           289:                FREE(TYPED_MEM_TEMP, buf);
        !           290:                errno = errno_save;
        !           291:                return (-1);
        !           292:        }
        !           293:        memcpy(*sdlp, sdl, sdl->sdl_len);
        !           294:        FREE(TYPED_MEM_TEMP, buf);
        !           295:        return (0);
        !           296: }
        !           297: 
        !           298: /*
        !           299:  * Gets the names of all system interfaces.
        !           300:  */
        !           301: int
        !           302: if_get_list(char ***listp, const char *mtype)
        !           303: {
        !           304:        char **list = NULL;
        !           305:        int errno_save;
        !           306:        int num = 0;
        !           307:        u_char *buf;
        !           308:        u_char *ptr;
        !           309:        int len;
        !           310: 
        !           311:        /* Get raw data from kernel */
        !           312:        if ((len = if_info(&buf, TYPED_MEM_TEMP)) == -1)
        !           313:                return (-1);
        !           314: 
        !           315:        /* Scan interfaces */
        !           316:        for (ptr = buf;
        !           317:            ptr < buf + len;
        !           318:            ptr += ((struct if_msghdr *)(void *)ptr)->ifm_msglen) {
        !           319:                struct if_msghdr *const ifm = (struct if_msghdr *)(void *)ptr;
        !           320: 
        !           321:                /* Sanity check version */
        !           322:                if (ifm->ifm_version != RTM_VERSION) {
        !           323:                        errno = EIO;
        !           324:                        goto fail;
        !           325:                }
        !           326: 
        !           327:                /* Next interface? */
        !           328:                if (ifm->ifm_type == RTM_IFINFO) {
        !           329:                        struct sockaddr_dl *const sdl
        !           330:                            = (struct sockaddr_dl *)(ifm + 1);
        !           331:                        char nbuf[IF_NAMESIZE + 1];
        !           332:                        void *new_list;
        !           333: 
        !           334:                        /* Get name */
        !           335:                        if (sdl->sdl_nlen > sizeof(nbuf) - 1)
        !           336:                                continue;
        !           337:                        memcpy(nbuf, sdl->sdl_data, sdl->sdl_nlen);
        !           338:                        nbuf[sdl->sdl_nlen] = '\0';
        !           339: 
        !           340:                        /* Add name to list */
        !           341:                        if ((new_list = REALLOC(mtype, list,
        !           342:                            (num + 1) * sizeof(*list))) == NULL)
        !           343:                                goto fail;
        !           344:                        list = new_list;
        !           345:                        if ((list[num] = STRDUP(mtype, nbuf)) == NULL)
        !           346:                                goto fail;
        !           347:                        num++;
        !           348:                }
        !           349:        }
        !           350: 
        !           351:        /* Done */
        !           352:        FREE(TYPED_MEM_TEMP, buf);
        !           353:        *listp = list;
        !           354:        return (num);
        !           355: 
        !           356: fail:
        !           357:        errno_save = errno;
        !           358:        while (num > 0)
        !           359:                FREE(mtype, list[--num]);
        !           360:        FREE(mtype, list);
        !           361:        FREE(TYPED_MEM_TEMP, buf);
        !           362:        errno = errno_save;
        !           363:        return (-1);
        !           364: }
        !           365: 
        !           366: /*
        !           367:  * Get the flags or type associated with an interface.
        !           368:  * Caller must free *bufp.
        !           369:  *
        !           370:  * Returns -1 and sets errno if there was a problem.
        !           371:  */
        !           372: static struct if_msghdr *
        !           373: if_find(const char *ifname, u_char **bufp, const char *mtype)
        !           374: {
        !           375:        u_char *buf;
        !           376:        u_char *ptr;
        !           377:        size_t len;
        !           378: 
        !           379:        /* Get raw data from kernel */
        !           380:        if ((len = if_info(&buf, mtype)) == -1)
        !           381:                return (NULL);
        !           382: 
        !           383:        /* Scan for desired interface */
        !           384:        for (ptr = buf;
        !           385:            ptr < buf + len;
        !           386:            ptr += ((struct if_msghdr *)(void *)ptr)->ifm_msglen) {
        !           387:                struct if_msghdr *const ifm = (struct if_msghdr *)(void *)ptr;
        !           388:                struct sockaddr_dl *sdl;
        !           389: 
        !           390:                /* Sanity check version */
        !           391:                if (ifm->ifm_version != RTM_VERSION) {
        !           392:                        FREE(mtype, buf);
        !           393:                        errno = EIO;
        !           394:                        return (NULL);
        !           395:                }
        !           396: 
        !           397:                /* Next interface or previous interface address? */
        !           398:                if (ifm->ifm_type != RTM_IFINFO)
        !           399:                        continue;
        !           400: 
        !           401:                /* Compare interface name */
        !           402:                sdl = (struct sockaddr_dl *)(ifm + 1);
        !           403:                if (strlen(ifname) != sdl->sdl_nlen ||
        !           404:                    strncmp(ifname, sdl->sdl_data, sdl->sdl_nlen) != 0)
        !           405:                        continue;
        !           406: 
        !           407:                /* Found it */
        !           408:                *bufp = buf;
        !           409:                return (ifm);
        !           410:        }
        !           411: 
        !           412:        /* Not found */
        !           413:        FREE(mtype, buf);
        !           414:        errno = ENOENT;
        !           415:        return (NULL);
        !           416: }
        !           417: 
        !           418: /*
        !           419:  * Get the interface list. Caller must free *bufp.
        !           420:  */
        !           421: static int
        !           422: if_info(u_char **bufp, const char *mtype)
        !           423: {
        !           424:        int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 };
        !           425:        size_t length;
        !           426:        u_char *buf;
        !           427: 
        !           428:        if (sysctl(mib, 6, NULL, &length, NULL, 0) == -1)
        !           429:                return (-1);
        !           430:        length += 256;
        !           431:        if ((buf = MALLOC(mtype, length)) == NULL)
        !           432:                return (-1);
        !           433:        if (sysctl(mib, 6, buf, &length, NULL, 0) == -1)
        !           434:                return (-1);
        !           435:        *bufp = buf;
        !           436:        return (length);
        !           437: }
        !           438: 

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