File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_resolve.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 11:54:42 2013 UTC (11 years ago) by misho
Branches: libnet, MAIN
CVS tags: v1_1_6p5, v1_1_6p4, v1_1_6p0, v1_1_6, HEAD
1.1.6

    1: /*
    2:  *  $Id: libnet_resolve.c,v 1.1.1.2 2013/07/22 11:54:42 misho Exp $
    3:  *
    4:  *  libnet
    5:  *  libnet_resolve.c - various name resolution type routines
    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: 
   42: #ifndef HAVE_GETHOSTBYNAME2
   43: struct hostent *
   44: gethostbyname2(const char *name, int af)
   45: {
   46:         return gethostbyname(name);
   47: }
   48: #endif
   49: 
   50: char *
   51: libnet_addr2name4(uint32_t in, uint8_t use_name)
   52: {
   53: 	#define HOSTNAME_SIZE 512
   54:     static char hostname[HOSTNAME_SIZE+1], hostname2[HOSTNAME_SIZE+1];
   55:     static uint16_t which;
   56:     uint8_t *p;
   57: 
   58:     struct hostent *host_ent = NULL;
   59:     struct in_addr addr;
   60: 
   61:     /*
   62:      *  Swap to the other buffer.  We swap static buffers to avoid having to
   63:      *  pass in a int8_t *.  This makes the code that calls this function more
   64:      *  intuitive, but makes this function ugly.  This function is seriously
   65:      *  non-reentrant.  For threaded applications (or for signal handler code)
   66:      *  use host_lookup_r().
   67:      */
   68:     which++;
   69:     
   70:     if (use_name == LIBNET_RESOLVE)
   71:     {
   72: 		addr.s_addr = in;
   73:         host_ent = gethostbyaddr((int8_t *)&addr, sizeof(struct in_addr), AF_INET);
   74:         /* if this fails, we silently ignore the error and move to plan b! */
   75:     }
   76:     if (!host_ent)
   77:     {
   78: 
   79:         p = (uint8_t *)&in;
   80:    		snprintf(((which % 2) ? hostname : hostname2), HOSTNAME_SIZE,
   81:                  "%d.%d.%d.%d",
   82:                  (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
   83:     }
   84:     else if (use_name == LIBNET_RESOLVE)
   85:     {
   86: 		char *ptr = ((which % 2) ? hostname : hostname2);
   87: 		strncpy(ptr, host_ent->h_name, HOSTNAME_SIZE);
   88: 		ptr[HOSTNAME_SIZE] = '\0';
   89: 	
   90:     }
   91:     return (which % 2) ? (hostname) : (hostname2);
   92: }
   93: 
   94: void
   95: libnet_addr2name4_r(uint32_t in, uint8_t use_name, char *hostname,
   96:         int hostname_len)
   97: {
   98:     uint8_t *p;
   99:     struct hostent *host_ent = NULL;
  100:     struct in_addr addr;
  101: 
  102:     if (use_name == LIBNET_RESOLVE)
  103:     {   
  104: 		addr.s_addr = in;
  105:         host_ent = gethostbyaddr((int8_t *)&addr, sizeof(struct in_addr),
  106:                 AF_INET);
  107:     }
  108:     if (!host_ent)
  109:     {
  110:         p = (uint8_t *)&in;
  111:         snprintf(hostname, hostname_len, "%d.%d.%d.%d",
  112:                 (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
  113:     }
  114:     else
  115:     {
  116:         strncpy(hostname, host_ent->h_name, hostname_len - 1);
  117: 		hostname[sizeof(hostname) - 1] = '\0';
  118:     }
  119: }
  120: 
  121: uint32_t
  122: libnet_name2addr4(libnet_t *l, char *host_name, uint8_t use_name)
  123: {
  124:     struct in_addr addr;
  125:     struct hostent *host_ent; 
  126:     uint32_t m;
  127:     uint val;
  128:     int i;
  129: 
  130:     if (use_name == LIBNET_RESOLVE)
  131:     {
  132: 		if ((addr.s_addr = inet_addr(host_name)) == -1)
  133:         {
  134:             if (!(host_ent = gethostbyname(host_name)))
  135:             {
  136:                 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  137:                         "%s(): %s\n", __func__, hstrerror(h_errno));
  138:                 /* XXX - this is actually 255.255.255.255 */
  139:                 return (-1);
  140:             }
  141:             memcpy(&addr.s_addr, host_ent->h_addr, host_ent->h_length);
  142:         }
  143:         /* network byte order */
  144:         return (addr.s_addr);
  145:     }
  146:     else
  147:     {
  148:         /*
  149:          *  We only want dots 'n decimals.
  150:          */
  151:         if (!isdigit(host_name[0]))
  152:         {
  153:             if (l)
  154:             {
  155:                 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  156:                     "%s(): expecting dots and decimals\n", __func__);
  157:             }
  158:             /* XXX - this is actually 255.255.255.255 */
  159:             return (-1);
  160:         }
  161: 
  162:         m = 0;
  163:         for (i = 0; i < 4; i++)
  164:         {
  165:             m <<= 8;
  166:             if (*host_name)
  167:             {
  168:                 val = 0;
  169:                 while (*host_name && *host_name != '.')
  170:                 {   
  171:                     val *= 10;
  172:                     val += *host_name - '0';
  173:                     if (val > 255)
  174:                     {
  175:                         if (l)
  176:                         {
  177:                             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  178:                             "%s(): value greater than 255\n", __func__);
  179:                         }
  180:                         /* XXX - this is actually 255.255.255.255 */
  181:                         return (-1);
  182:                     }
  183:                     host_name++;
  184:                 }
  185:                 m |= val;
  186:                 if (*host_name)
  187:                 {
  188:                     host_name++;
  189:                 }
  190:             }
  191:         }
  192:         /* host byte order */
  193:        return (ntohl(m));
  194:     }
  195: }
  196: 
  197: void
  198: libnet_addr2name6_r(struct libnet_in6_addr addr, uint8_t use_name,
  199:             char *host_name, int host_name_len)
  200: {
  201:     struct hostent *host_ent = NULL;
  202: 
  203:     if (use_name == LIBNET_RESOLVE)
  204:     {    
  205: #ifdef HAVE_SOLARIS 
  206: #ifdef HAVE_SOLARIS_IPV6
  207:         host_ent = getipnodebyaddr((int8_t *)&addr, sizeof(struct in_addr),
  208:                 AF_INET6, NULL);
  209: #else
  210:         /* XXX - Gah!  Can't report error! */
  211:         host_ent = NULL;
  212: #endif
  213: #else
  214:         host_ent = gethostbyaddr((int8_t *)&addr, sizeof(struct in_addr),
  215:                 AF_INET6);
  216: #endif
  217:     }
  218:     if (!host_ent)
  219:     {
  220: #if !defined(__WIN32__) /* Silence Win32 warning */
  221:         inet_ntop(AF_INET6, &addr, host_name, host_name_len);
  222: #endif
  223:     }
  224:     else
  225:     {
  226:         strncpy(host_name, host_ent->h_name, host_name_len -1);
  227: 		host_name[sizeof(host_name) - 1] = '\0';
  228:     }
  229: }
  230: 
  231: const struct libnet_in6_addr in6addr_error = IN6ADDR_ERROR_INIT;
  232: 
  233: int
  234: libnet_in6_is_error(struct libnet_in6_addr addr)
  235: {
  236:     return 0 == memcmp(&addr, &in6addr_error, sizeof(addr));
  237: }
  238: 
  239: struct libnet_in6_addr
  240: libnet_name2addr6(libnet_t *l, const char *host_name, uint8_t use_name)
  241: {
  242: #if !defined (__WIN32__)
  243:     struct libnet_in6_addr addr;
  244:     struct hostent *host_ent; 
  245: #endif
  246:    
  247:     if (use_name == LIBNET_RESOLVE)
  248:     {
  249: #ifdef __WIN32__
  250:         /* XXX - we don't support this yet */
  251:         if (l)
  252:         {        
  253:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  254:                 "%s(): can't resolve IPv6 addresses\n", __func__);
  255:         }
  256:         return (in6addr_error);
  257: #else
  258: #ifdef HAVE_SOLARIS 
  259: #ifdef HAVE_SOLARIS_IPV6
  260:         if (!(host_ent = getipnodebyname((int8_t *)&addr,
  261:                 sizeof(struct in_addr), AF_INET6, NULL)))
  262: #else
  263:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, 
  264:                 "%s(): %s\n", __func__, strerror(errno));
  265:         return (in6addr_error);
  266: #endif
  267: #else
  268:         if (!(host_ent = gethostbyname2(host_name, AF_INET6)))
  269: #endif
  270:         {
  271:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  272:                     "%s(): %s", __func__, strerror(errno));
  273:             return (in6addr_error);
  274:         }
  275:         memcpy(&addr, host_ent->h_addr, host_ent->h_length);
  276:         return (addr);
  277: #endif  /* !__WIN32__ */
  278:     }
  279:     else
  280:     {
  281: #if defined(__WIN32__) /* Silence Win32 warning */
  282:         if (l)
  283:         {        
  284:                snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  285:                 "%s(): can't resolve IPv6 addresses.\n", __func__);
  286:         }
  287:         return (in6addr_error);
  288: #else
  289:         if(!inet_pton(AF_INET6, host_name, &addr))
  290:         {
  291:             if (l)
  292:             {
  293:                 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  294:                     "%s(): invalid IPv6 address\n", __func__);
  295:             }
  296:             return (in6addr_error);
  297:         }
  298:         return (addr);
  299: #endif
  300:     }
  301: }
  302: 
  303: #ifdef HAVE_GETIFADDRS
  304: 
  305: #include <ifaddrs.h>
  306: 
  307: struct libnet_in6_addr
  308: libnet_get_ipaddr6(libnet_t *l)
  309: {
  310:     struct ifaddrs *ifaddr, *p;
  311:     struct libnet_in6_addr addr;
  312: 
  313:     if (l == NULL)
  314:     {
  315:         return (in6addr_error);
  316:     }
  317: 
  318:     if (getifaddrs(&ifaddr) != 0)
  319:     {
  320:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  321:                 "%s(): getifaddrs(): %s\n", __func__, strerror(errno));
  322:         return (in6addr_error);
  323:     }
  324: 
  325:     if (l->device == NULL)
  326:     {
  327:         if (libnet_select_device(l) == -1)
  328:         {
  329:             /* error msg set in libnet_select_device() */
  330:             return (in6addr_error);
  331:         }
  332:     }
  333: 
  334:     for (p = ifaddr; p != NULL; p = p->ifa_next)
  335:     {
  336:         if ((strcmp(p->ifa_name, l->device) == 0) && (p->ifa_addr != NULL) &&
  337:                 (p->ifa_addr->sa_family == AF_INET6))
  338:         {
  339:             memcpy(&addr.__u6_addr,
  340:                     ((struct sockaddr_in6*)p->ifa_addr)->sin6_addr.s6_addr, 16);
  341:             freeifaddrs(ifaddr);
  342:             return (addr);
  343:         }
  344:     }
  345: 
  346:     freeifaddrs(ifaddr);
  347:     return (in6addr_error);
  348: }
  349: #else
  350: struct libnet_in6_addr
  351: libnet_get_ipaddr6(libnet_t *l)
  352: {
  353:     snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  354:            "%s(): not yet Implemented\n", __func__);
  355:     return (in6addr_error);
  356: }
  357: #endif /* WIN32 */
  358: 
  359: #if !defined(__WIN32__)
  360: uint32_t
  361: libnet_get_ipaddr4(libnet_t *l)
  362: {
  363:     struct ifreq ifr;
  364:     register struct sockaddr_in *sin;
  365:     int fd;
  366: 
  367:     if (l == NULL)
  368:     {
  369:         return (-1);
  370:     }
  371: 
  372:     /* create dummy socket to perform an ioctl upon */
  373:     fd = socket(PF_INET, SOCK_DGRAM, 0);
  374:     if (fd == -1)
  375:     {
  376:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  377:                 "%s(): socket(): %s\n", __func__, strerror(errno));
  378:         return (-1);
  379:     }
  380: 
  381:     sin = (struct sockaddr_in *)&ifr.ifr_addr;
  382: 
  383:     if (l->device == NULL)
  384:     {
  385:         if (libnet_select_device(l) == -1)
  386:         {
  387:             /* error msg set in libnet_select_device() */
  388:             close(fd);
  389:             return (-1);
  390:         }
  391:     }
  392:     strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) -1);
  393: 	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
  394: 	
  395:     ifr.ifr_addr.sa_family = AF_INET;
  396: 
  397:     if (ioctl(fd, SIOCGIFADDR, (int8_t*) &ifr) < 0)
  398:     {
  399:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  400:                 "%s(): ioctl(): %s\n", __func__, strerror(errno));
  401:         close(fd);
  402:         return (-1);
  403:     }
  404:     close(fd);
  405:     return (sin->sin_addr.s_addr);
  406: }
  407: #else
  408: #include <Packet32.h>
  409: uint32_t
  410: libnet_get_ipaddr4(libnet_t *l)
  411: {
  412:     long npflen = 0;
  413:     struct sockaddr_in sin;
  414:     struct npf_if_addr ipbuff;
  415: 
  416:     memset(&sin,0,sizeof(sin));
  417:     memset(&ipbuff,0,sizeof(ipbuff));
  418: 
  419:     npflen = sizeof(ipbuff);
  420:     if (PacketGetNetInfoEx(l->device, &ipbuff, &npflen))
  421:     {
  422:         sin = *(struct sockaddr_in *)&ipbuff.IPAddress;
  423:     }
  424:     return (sin.sin_addr.s_addr);
  425: }
  426: #endif /* WIN32 */
  427: 
  428: uint8_t *
  429: libnet_hex_aton(const char *s, int *len)
  430: {
  431:     uint8_t *buf;
  432:     int i;
  433:     int32_t l;
  434:     char *pp;
  435:         
  436:     while (isspace(*s))
  437:     {
  438:         s++;
  439:     }
  440:     for (i = 0, *len = 0; s[i]; i++)
  441:     {
  442:         if (s[i] == ':')
  443:         {
  444:             (*len)++;
  445:         }
  446:     }
  447:     buf = malloc(*len + 1);
  448:     if (buf == NULL)
  449:     {
  450:         return (NULL);
  451:     }
  452:     /* expect len hex octets separated by ':' */
  453:     for (i = 0; i < *len + 1; i++)
  454:     {
  455:         l = strtol(s, &pp, 16);
  456:         if (pp == s || l > 0xff || l < 0)
  457:         {
  458:             *len = 0;
  459:             free(buf);
  460:             return (NULL);
  461:         }
  462:         if (!(*pp == ':' || (i == *len && (isspace(*pp) || *pp == '\0'))))
  463:         {
  464:             *len = 0;
  465:             free(buf);
  466:             return (NULL);
  467:         }
  468:         buf[i] = (uint8_t)l;
  469:         s = pp + 1;
  470:     }
  471:     /* return int8_tacter after the octets ala strtol(3) */
  472:     (*len)++;
  473:     return (buf);
  474: }
  475: 
  476: /* EOF */

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