Annotation of embedaddon/libnet/src/libnet_if_addr.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *  $Id: libnet_if_addr.c,v 1.22 2004/03/04 20:51:07 kkuehl Exp $
        !             3:  *
        !             4:  *  libnet
        !             5:  *  libnet_if_addr.c - interface selection code
        !             6:  *
        !             7:  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
        !             8:  *  All rights reserved.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            29:  * SUCH DAMAGE.
        !            30:  *
        !            31:  */
        !            32: 
        !            33: #if (HAVE_CONFIG_H)
        !            34: #include "../include/config.h"
        !            35: #endif
        !            36: #if (!(_WIN32) || (__CYGWIN__)) 
        !            37: #include "../include/libnet.h"
        !            38: #else
        !            39: #include "../include/win32/libnet.h"
        !            40: #endif
        !            41: #ifdef HAVE_SYS_SOCKIO_H
        !            42: #include <sys/sockio.h>
        !            43: #endif
        !            44: #include "../include/ifaddrlist.h"
        !            45: 
        !            46: #define MAX_IPADDR 512
        !            47: 
        !            48: #if !(__WIN32__)
        !            49: 
        !            50: /*
        !            51:  * By testing if we can retrieve the FLAGS of an iface
        !            52:  * we can know if it exists or not and if it is up.
        !            53:  */
        !            54: int 
        !            55: libnet_check_iface(libnet_t *l)
        !            56: {
        !            57:     struct ifreq ifr;
        !            58:     int fd, res;
        !            59: 
        !            60:     fd = socket(AF_INET, SOCK_DGRAM, 0);
        !            61:     if (fd < 0)
        !            62:     {
        !            63:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s() socket: %s\n", __func__,
        !            64:                 strerror(errno));
        !            65:         return (-1);
        !            66:     }
        !            67: 
        !            68:     strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) -1);
        !            69:     ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
        !            70:     
        !            71:     res = ioctl(fd, SIOCGIFFLAGS, (int8_t *)&ifr);
        !            72: 
        !            73:     if (res < 0)
        !            74:     {
        !            75:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s() ioctl: %s\n", __func__,
        !            76:                 strerror(errno));
        !            77:     }
        !            78:     else
        !            79:     {
        !            80:         if ((ifr.ifr_flags & IFF_UP) == 0)
        !            81:         {
        !            82:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): %s is down\n",
        !            83:                     __func__, l->device);
        !            84:            res = -1;
        !            85:         }
        !            86:     }
        !            87:     close(fd);
        !            88:     return (res);
        !            89: }
        !            90: 
        !            91: 
        !            92: /*
        !            93:  *  Return the interface list
        !            94:  */
        !            95: 
        !            96: #ifdef HAVE_SOCKADDR_SA_LEN
        !            97: #define NEXTIFR(i) \
        !            98: ((struct ifreq *)((u_char *)&i->ifr_addr + i->ifr_addr.sa_len))
        !            99: #else
        !           100: #define NEXTIFR(i) (i + 1)
        !           101: #endif
        !           102: 
        !           103: #ifndef BUFSIZE
        !           104: #define BUFSIZE 2048
        !           105: #endif
        !           106: 
        !           107: #ifdef HAVE_LINUX_PROCFS
        !           108: #define PROC_DEV_FILE "/proc/net/dev"
        !           109: #endif
        !           110: 
        !           111: int
        !           112: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, int8_t *dev,
        !           113: register int8_t *errbuf)
        !           114: {
        !           115:     register struct libnet_ifaddr_list *al;
        !           116:     struct ifreq *ifr, *lifr, *pifr, nifr;
        !           117:     int8_t device[sizeof(nifr.ifr_name)];
        !           118:     static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
        !           119:     
        !           120:     char *p;
        !           121:     struct ifconf ifc;
        !           122:     struct ifreq ibuf[MAX_IPADDR];
        !           123:     register int fd, nipaddr;
        !           124:     
        !           125: #ifdef HAVE_LINUX_PROCFS
        !           126:     FILE *fp;
        !           127:     char buf[2048];
        !           128: #endif
        !           129:     
        !           130:     fd = socket(AF_INET, SOCK_DGRAM, 0);
        !           131:     if (fd < 0)
        !           132:     {
        !           133:        snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): socket error: %s\n",
        !           134:                 __func__, strerror(errno));
        !           135:        return (-1);
        !           136:     }
        !           137: 
        !           138: #ifdef HAVE_LINUX_PROCFS
        !           139:     if ((fp = fopen(PROC_DEV_FILE, "r")) == NULL)
        !           140:     {
        !           141:        snprintf(errbuf, LIBNET_ERRBUF_SIZE,
        !           142:                 "%s(): fopen(proc_dev_file) failed: %s\n",  __func__,
        !           143:                 strerror(errno));
        !           144:        return (-1);
        !           145:     }
        !           146: #endif
        !           147: 
        !           148:     memset(&ifc, 0, sizeof(ifc));
        !           149:     ifc.ifc_len = sizeof(ibuf);
        !           150:     ifc.ifc_buf = (caddr_t)ibuf;
        !           151: 
        !           152:     if(ioctl(fd, SIOCGIFCONF, &ifc) < 0)
        !           153:     {
        !           154:        snprintf(errbuf, LIBNET_ERRBUF_SIZE,
        !           155:                 "%s(): ioctl(SIOCGIFCONF) error: %s\n", 
        !           156:                 __func__, strerror(errno));
        !           157:        return(-1);
        !           158:     }
        !           159: 
        !           160:     pifr = NULL;
        !           161:     lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
        !           162:     
        !           163:     al = ifaddrlist;
        !           164:     nipaddr = 0;
        !           165: 
        !           166: #ifdef HAVE_LINUX_PROCFS
        !           167:     while (fgets(buf, sizeof(buf), fp))
        !           168:     {
        !           169:        if ((p = strchr(buf, ':')) == NULL)
        !           170:         {
        !           171:             continue;
        !           172:         }
        !           173:         *p = '\0';
        !           174:         for(p = buf; *p == ' '; p++) ;
        !           175:        
        !           176:         strncpy(nifr.ifr_name, p, sizeof(nifr.ifr_name) - 1);
        !           177:         nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
        !           178:        
        !           179: #else /* !HAVE_LINUX_PROCFS */
        !           180: 
        !           181:     for (ifr = ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr))
        !           182:     {
        !           183:        /* XXX LINUX SOLARIS ifalias */
        !           184:        if((p = strchr(ifr->ifr_name, ':')))
        !           185:         {
        !           186:             *p='\0';
        !           187:         }
        !           188:        if (pifr && strcmp(ifr->ifr_name, pifr->ifr_name) == 0)
        !           189:         {
        !           190:             continue;
        !           191:         }
        !           192:        strncpy(nifr.ifr_name, ifr->ifr_name, sizeof(nifr.ifr_name) - 1);
        !           193:        nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
        !           194: #endif
        !           195: 
        !           196:         /* save device name */
        !           197:         strncpy(device, nifr.ifr_name, sizeof(device) - 1);
        !           198:         device[sizeof(device) - 1] = '\0';
        !           199: 
        !           200:         if (ioctl(fd, SIOCGIFFLAGS, &nifr) < 0)
        !           201:         {
        !           202:             pifr = ifr;
        !           203:             continue;
        !           204:        }
        !           205:         if ((nifr.ifr_flags & IFF_UP) == 0)
        !           206:        {
        !           207:             pifr = ifr;
        !           208:             continue;  
        !           209:        }
        !           210: 
        !           211:         if (dev == NULL && LIBNET_ISLOOPBACK(&nifr))
        !           212:        {
        !           213:             pifr = ifr;
        !           214:             continue;
        !           215:        }
        !           216:        
        !           217:         strncpy(nifr.ifr_name, device, sizeof(device) - 1);
        !           218:         nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
        !           219:         if (ioctl(fd, SIOCGIFADDR, (int8_t *)&nifr) < 0)
        !           220:         {
        !           221:             if (errno != EADDRNOTAVAIL)
        !           222:             {
        !           223:                 snprintf(errbuf, LIBNET_ERRBUF_SIZE,
        !           224:                         "%s(): SIOCGIFADDR: dev=%s: %s\n", __func__, device,
        !           225:                         strerror(errno));
        !           226:                 close(fd);
        !           227:                 return (-1);
        !           228:            }
        !           229:             else /* device has no IP address => set to 0 */
        !           230:             {
        !           231:                 al->addr = 0;
        !           232:             }
        !           233:         }
        !           234:         else
        !           235:         {
        !           236:             al->addr = ((struct sockaddr_in *)&nifr.ifr_addr)->sin_addr.s_addr;
        !           237:         }
        !           238: 
        !           239:         if ((al->device = strdup(device)) == NULL)
        !           240:         {
        !           241:             snprintf(errbuf, LIBNET_ERRBUF_SIZE, 
        !           242:                     "%s(): strdup not enough memory\n", __func__);
        !           243:             return(-1);
        !           244:         }
        !           245: 
        !           246:         ++al;
        !           247:         ++nipaddr;
        !           248: 
        !           249: #ifndef HAVE_LINUX_PROCFS
        !           250:         pifr = ifr;
        !           251: #endif
        !           252: 
        !           253:     } /* while|for */
        !           254:        
        !           255: #ifdef HAVE_LINUX_PROCFS
        !           256:     if (ferror(fp))
        !           257:     {
        !           258:         snprintf(errbuf, LIBNET_ERRBUF_SIZE,
        !           259:                 "%s(): ferror: %s\n", __func__, strerror(errno));
        !           260:        return (-1);
        !           261:     }
        !           262:     fclose(fp);
        !           263: #endif
        !           264: 
        !           265:     *ipaddrp = ifaddrlist;
        !           266:     return (nipaddr);
        !           267: }
        !           268: #else
        !           269: /* From tcptraceroute, convert a numeric IP address to a string */
        !           270: #define IPTOSBUFFERS    12
        !           271: static int8_t *iptos(u_int32_t in)
        !           272: {
        !           273:     static int8_t output[IPTOSBUFFERS][ 3 * 4 + 3 + 1];
        !           274:     static int16_t which;
        !           275:     u_int8_t *p;
        !           276: 
        !           277:     p = (u_int8_t *)&in;
        !           278:     which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
        !           279:     snprintf(output[which], IPTOSBUFFERS, "%d.%d.%d.%d", 
        !           280:             p[0], p[1], p[2], p[3]);
        !           281:     return output[which];
        !           282: }
        !           283: 
        !           284: int
        !           285: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, int8_t *dev,
        !           286: register int8_t *errbuf)
        !           287: {
        !           288:     int nipaddr = 0;    int i = 0;
        !           289: 
        !           290:     static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
        !           291:     pcap_if_t *alldevs;
        !           292:     pcap_if_t *d;
        !           293:     int8_t err[PCAP_ERRBUF_SIZE];
        !           294: 
        !           295:     /* Retrieve the interfaces list */
        !           296:     if (pcap_findalldevs(&alldevs, err) == -1)
        !           297:     {
        !           298:         snprintf(errbuf, LIBNET_ERRBUF_SIZE, 
        !           299:                 "%s(): error in pcap_findalldevs: %s\n", __func__, err);
        !           300:         return (-1);
        !           301:     }
        !           302: 
        !           303:     /* Scan the list printing every entry */
        !           304:        for (d = alldevs; d; d = d->next)
        !           305:     {
        !           306:                if((!d->addresses) || (d->addresses->addr->sa_family != AF_INET))
        !           307:             continue;
        !           308:         if(d->flags & PCAP_IF_LOOPBACK)
        !           309:             continue;
        !           310:     
        !           311:                /* XXX - strdup */
        !           312:         ifaddrlist[i].device = strdup(d->name);
        !           313:         ifaddrlist[i].addr = (u_int32_t)
        !           314:                 strdup(iptos(((struct sockaddr_in *)
        !           315:                 d->addresses->addr)->sin_addr.s_addr));
        !           316:         ++i;
        !           317:         ++nipaddr;
        !           318:     }
        !           319: 
        !           320:     *ipaddrp = ifaddrlist;
        !           321:     return (nipaddr);
        !           322: }
        !           323: #endif /* __WIN32__ */
        !           324: 
        !           325: int
        !           326: libnet_select_device(libnet_t *l)
        !           327: {
        !           328:     int c, i;
        !           329:     int8_t err_buf[LIBNET_ERRBUF_SIZE];
        !           330:     struct libnet_ifaddr_list *address_list, *al;
        !           331:     u_int32_t addr;
        !           332: 
        !           333: 
        !           334:     if (l == NULL)
        !           335:     { 
        !           336:         return (-1);
        !           337:     }
        !           338: 
        !           339:     if (l->device && !isdigit(l->device[0]))
        !           340:     {
        !           341: #if !(__WIN32__)
        !           342:        if (libnet_check_iface(l) < 0)
        !           343:        {
        !           344:             /* err msg set in libnet_check_iface() */
        !           345:            return (-1);
        !           346:        }
        !           347: #endif
        !           348:        return (1);
        !           349:     }
        !           350: 
        !           351:     /*
        !           352:      *  Number of interfaces.
        !           353:      */
        !           354:     c = libnet_ifaddrlist(&address_list, l->device, err_buf);
        !           355:     if (c < 0)
        !           356:     {
        !           357:         /* err msg set in libnet_ifaddrlist() */
        !           358:         return (-1);
        !           359:     }
        !           360:     else if (c == 0)
        !           361:     {
        !           362:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
        !           363:                 "%s(): no network interface found\n", __func__);
        !           364:         return (-1);
        !           365:     }
        !           366:        
        !           367:     al = address_list;
        !           368:     if (l->device)
        !           369:     {
        !           370:         /*
        !           371:          *  Then we have an IP address in l->device => do lookup
        !           372:          */
        !           373:        addr = libnet_name2addr4(l, l->device, 0);
        !           374: 
        !           375:         for (i = c; i; --i, ++address_list)
        !           376:         {
        !           377:             if (((addr == -1) && !(strncmp(l->device, address_list->device,
        !           378:                    strlen(l->device)))) || 
        !           379:                     (address_list->addr == addr))
        !           380:             {
        !           381:                 /* free the "user supplied device" - see libnet_init() */
        !           382:                 free(l->device);
        !           383:                 l->device =  strdup(address_list->device);
        !           384:                 goto good;
        !           385:             }
        !           386:         }
        !           387:         if (i <= 0)
        !           388:         {
        !           389:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
        !           390:                     "%s(): can't find interface for IP %s\n", __func__,
        !           391:                     l->device);
        !           392:            goto bad;
        !           393:         }
        !           394:     }
        !           395:     else
        !           396:     {
        !           397:         l->device = strdup(address_list->device);
        !           398:     }
        !           399: 
        !           400: good:
        !           401:     for (i = 0; i < c; i++)
        !           402:     {
        !           403:         free(al[i].device);
        !           404:     }
        !           405:     return (1);
        !           406: 
        !           407: bad:
        !           408:     for (i = 0; i < c; i++)
        !           409:     {
        !           410:         free(al[i].device);
        !           411:     }
        !           412:     return (-1);
        !           413: }
        !           414: 
        !           415: /* EOF */

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