File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_if_addr.c
Revision 1.1.1.2.2.1: download - view: text, annotated - select for diffs - revision graph
Tue Oct 18 13:11:47 2016 UTC (7 years, 8 months ago) by misho
Branches: v1_1_6p0
CVS tags: v1_1_6p4
Diff to: branchpoint 1.1.1.2: preferred, unified
adds 3 new patches

    1: /*
    2:  *  $Id: libnet_if_addr.c,v 1.1.1.2.2.1 2016/10/18 13:11:47 misho 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, char *dev,
  113: register char *errbuf)
  114: {
  115:     register struct libnet_ifaddr_list *al;
  116:     struct ifreq *ifr, *lifr, *pifr, nifr;
  117:     char 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: #ifdef HAVE_LINUX_PROCFS
  158: 	fclose(fp);
  159: #endif
  160: 	return(-1);
  161:     }
  162: 
  163:     pifr = NULL;
  164:     lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
  165:     
  166:     al = ifaddrlist;
  167:     nipaddr = 0;
  168: 
  169: #ifdef HAVE_LINUX_PROCFS
  170:     while (fgets(buf, sizeof(buf), fp))
  171:     {
  172: 	if ((p = strchr(buf, ':')) == NULL)
  173:         {
  174:             continue;
  175:         }
  176:         *p = '\0';
  177:         for(p = buf; *p == ' '; p++) ;
  178: 	
  179:         strncpy(nifr.ifr_name, p, sizeof(nifr.ifr_name) - 1);
  180:         nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
  181: 	
  182: #else /* !HAVE_LINUX_PROCFS */
  183: 
  184:     for (ifr = ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr))
  185:     {
  186: 	/* XXX LINUX SOLARIS ifalias */
  187: 	if((p = strchr(ifr->ifr_name, ':')))
  188:         {
  189:             *p='\0';
  190:         }
  191: 	if (pifr && strcmp(ifr->ifr_name, pifr->ifr_name) == 0)
  192:         {
  193:             continue;
  194:         }
  195: 	strncpy(nifr.ifr_name, ifr->ifr_name, sizeof(nifr.ifr_name) - 1);
  196: 	nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
  197: #endif
  198: 
  199:         /* save device name */
  200:         strncpy(device, nifr.ifr_name, sizeof(device) - 1);
  201:         device[sizeof(device) - 1] = '\0';
  202: 
  203:         if (ioctl(fd, SIOCGIFFLAGS, &nifr) < 0)
  204:         {
  205:             pifr = ifr;
  206:             continue;
  207: 	}
  208:         if ((nifr.ifr_flags & IFF_UP) == 0)
  209: 	{
  210:             pifr = ifr;
  211:             continue;	
  212: 	}
  213: 
  214:         if (dev == NULL && LIBNET_ISLOOPBACK(&nifr))
  215: 	{
  216:             pifr = ifr;
  217:             continue;
  218: 	}
  219: 	
  220:         strncpy(nifr.ifr_name, device, sizeof(device) - 1);
  221:         nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0';
  222:         if (ioctl(fd, SIOCGIFADDR, (int8_t *)&nifr) < 0)
  223:         {
  224:             if (errno != EADDRNOTAVAIL)
  225:             {
  226:                 snprintf(errbuf, LIBNET_ERRBUF_SIZE,
  227:                         "%s(): SIOCGIFADDR: dev=%s: %s\n", __func__, device,
  228:                         strerror(errno));
  229:                 close(fd);
  230: #ifdef HAVE_LINUX_PROCFS
  231:                 fclose(fp);
  232: #endif
  233:                 return (-1);
  234: 	    }
  235:             else /* device has no IP address => set to 0 */
  236:             {
  237:                 al->addr = 0;
  238:             }
  239:         }
  240:         else
  241:         {
  242:             al->addr = ((struct sockaddr_in *)&nifr.ifr_addr)->sin_addr.s_addr;
  243:         }
  244:         
  245:         free(al->device);
  246:         al->device = NULL;
  247: 
  248:         if ((al->device = strdup(device)) == NULL)
  249:         {
  250:             snprintf(errbuf, LIBNET_ERRBUF_SIZE, 
  251:                     "%s(): strdup not enough memory\n", __func__);
  252: #ifdef HAVE_LINUX_PROCFS
  253:             fclose(fp);
  254: #endif
  255:             return(-1);
  256:         }
  257: 
  258:         ++al;
  259:         ++nipaddr;
  260: 
  261: #ifndef HAVE_LINUX_PROCFS
  262:         pifr = ifr;
  263: #endif
  264: 
  265:     } /* while|for */
  266: 	
  267: #ifdef HAVE_LINUX_PROCFS
  268:     if (ferror(fp))
  269:     {
  270:         snprintf(errbuf, LIBNET_ERRBUF_SIZE,
  271:                 "%s(): ferror: %s\n", __func__, strerror(errno));
  272: 	fclose(fp);
  273: 	return (-1);
  274:     }
  275:     fclose(fp);
  276: #endif
  277: 
  278:     *ipaddrp = ifaddrlist;
  279:     return (nipaddr);
  280: }
  281: #else
  282: /* From tcptraceroute, convert a numeric IP address to a string */
  283: #define IPTOSBUFFERS    12
  284: static int8_t *iptos(uint32_t in)
  285: {
  286:     static int8_t output[IPTOSBUFFERS][ 3 * 4 + 3 + 1];
  287:     static int16_t which;
  288:     uint8_t *p;
  289: 
  290:     p = (uint8_t *)&in;
  291:     which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
  292:     snprintf(output[which], IPTOSBUFFERS, "%d.%d.%d.%d", 
  293:             p[0], p[1], p[2], p[3]);
  294:     return output[which];
  295: }
  296: 
  297: int
  298: libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev,
  299: register char *errbuf)
  300: {
  301:     int nipaddr = 0;    int i = 0;
  302: 
  303:     static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR];
  304:     pcap_if_t *alldevs;
  305:     pcap_if_t *d;
  306:     int8_t err[PCAP_ERRBUF_SIZE];
  307: 
  308:     /* Retrieve the interfaces list */
  309:     if (pcap_findalldevs(&alldevs, err) == -1)
  310:     {
  311:         snprintf(errbuf, LIBNET_ERRBUF_SIZE, 
  312:                 "%s(): error in pcap_findalldevs: %s\n", __func__, err);
  313:         return (-1);
  314:     }
  315: 
  316:     /* Scan the list printing every entry */
  317: 	for (d = alldevs; d; d = d->next)
  318:     {
  319: 		if((!d->addresses) || (d->addresses->addr->sa_family != AF_INET))
  320:             continue;
  321:         if(d->flags & PCAP_IF_LOOPBACK)
  322:             continue;
  323:     
  324: 		/* XXX - strdup */
  325:         ifaddrlist[i].device = strdup(d->name);
  326:         ifaddrlist[i].addr = (uint32_t)
  327:                 strdup(iptos(((struct sockaddr_in *)
  328:                 d->addresses->addr)->sin_addr.s_addr));
  329:         ++i;
  330:         ++nipaddr;
  331:     }
  332: 
  333:     pcap_freealldevs(alldevs);
  334: 
  335:     *ipaddrp = ifaddrlist;
  336:     return (nipaddr);
  337: }
  338: #endif /* __WIN32__ */
  339: 
  340: int
  341: libnet_select_device(libnet_t *l)
  342: {
  343:     int c, i;
  344:     struct libnet_ifaddr_list *address_list, *al;
  345:     uint32_t addr;
  346: 
  347: 
  348:     if (l == NULL)
  349:     { 
  350:         return (-1);
  351:     }
  352: 
  353:     if (l->device && !isdigit(l->device[0]))
  354:     {
  355: #if !(__WIN32__)
  356: 	if (libnet_check_iface(l) < 0)
  357: 	{
  358:             /* err msg set in libnet_check_iface() */
  359: 	    return (-1);
  360: 	}
  361: #endif
  362: 	return (1);
  363:     }
  364: 
  365:     /*
  366:      *  Number of interfaces.
  367:      */
  368:     c = libnet_ifaddrlist(&address_list, l->device, l->err_buf);
  369:     if (c < 0)
  370:     {
  371:         /* err msg set in libnet_ifaddrlist() */
  372:         return (-1);
  373:     }
  374:     else if (c == 0)
  375:     {
  376:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  377:                 "%s(): no network interface found\n", __func__);
  378:         return (-1);
  379:     }
  380: 	
  381:     al = address_list;
  382:     if (l->device)
  383:     {
  384:         /*
  385:          *  Then we have an IP address in l->device => do lookup
  386:          */
  387: 	addr = libnet_name2addr4(l, l->device, 0);
  388: 
  389:         for (i = c; i; --i, ++address_list)
  390:         {
  391:             if (((addr == -1) && !(strncmp(l->device, address_list->device,
  392:                    strlen(l->device)))) || 
  393:                     (address_list->addr == addr))
  394:             {
  395:                 /* free the "user supplied device" - see libnet_init() */
  396:                 free(l->device);
  397:                 l->device =  strdup(address_list->device);
  398:                 goto good;
  399:             }
  400:         }
  401:         if (i <= 0)
  402:         {
  403:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  404:                     "%s(): can't find interface for IP %s\n", __func__,
  405:                     l->device);
  406: 	    goto bad;
  407:         }
  408:     }
  409:     else
  410:     {
  411:         l->device = strdup(address_list->device);
  412:     }
  413: 
  414: good:
  415:     for (i = 0; i < c; i++)
  416:     {
  417:         free(al[i].device);
  418:         al[i].device = NULL;
  419:     }
  420:     return (1);
  421: 
  422: bad:
  423:     for (i = 0; i < c; i++)
  424:     {
  425:         free(al[i].device);
  426:         al[i].device = NULL;
  427:     }
  428:     return (-1);
  429: }
  430: 
  431: /* EOF */

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