File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_resolve.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:11:38 2023 UTC (9 months, 1 week ago) by misho
Branches: libnet, MAIN
CVS tags: v1_2p1, HEAD
Version 1.2p1

    1: /*
    2:  *  libnet
    3:  *  libnet_resolve.c - various name resolution type routines
    4:  *
    5:  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
    6:  *  All rights reserved.
    7:  *
    8:  * Redistribution and use in source and binary forms, with or without
    9:  * modification, are permitted provided that the following conditions
   10:  * are met:
   11:  * 1. Redistributions of source code must retain the above copyright
   12:  *    notice, this list of conditions and the following disclaimer.
   13:  * 2. Redistributions in binary form must reproduce the above copyright
   14:  *    notice, this list of conditions and the following disclaimer in the
   15:  *    documentation and/or other materials provided with the distribution.
   16:  *
   17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27:  * SUCH DAMAGE.
   28:  *
   29:  */
   30: 
   31: #include "common.h"
   32: 
   33: #ifndef HAVE_GETHOSTBYNAME2
   34: struct hostent *
   35: gethostbyname2(const char *name, int af)
   36: {
   37:         return gethostbyname(name);
   38: }
   39: #endif
   40: 
   41: char *
   42: libnet_addr2name4(uint32_t in, uint8_t use_name)
   43: {
   44: 	#define HOSTNAME_SIZE 512
   45:     static char hostname[HOSTNAME_SIZE+1], hostname2[HOSTNAME_SIZE+1];
   46:     static uint16_t which;
   47:     uint8_t *p;
   48: 
   49:     struct hostent *host_ent = NULL;
   50:     struct in_addr addr;
   51: 
   52:     /*
   53:      *  Swap to the other buffer.  We swap static buffers to avoid having to
   54:      *  pass in a int8_t *.  This makes the code that calls this function more
   55:      *  intuitive, but makes this function ugly.  This function is seriously
   56:      *  non-reentrant.  For threaded applications (or for signal handler code)
   57:      *  use host_lookup_r().
   58:      */
   59:     which++;
   60:     
   61:     if (use_name == LIBNET_RESOLVE)
   62:     {
   63: 		addr.s_addr = in;
   64:         host_ent = gethostbyaddr((int8_t *)&addr, sizeof(struct in_addr), AF_INET);
   65:         /* if this fails, we silently ignore the error and move to plan b! */
   66:     }
   67:     if (!host_ent)
   68:     {
   69: 
   70:         p = (uint8_t *)&in;
   71:    		snprintf(((which % 2) ? hostname : hostname2), HOSTNAME_SIZE,
   72:                  "%d.%d.%d.%d",
   73:                  (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
   74:     }
   75:     else if (use_name == LIBNET_RESOLVE)
   76:     {
   77: 		char *ptr = ((which % 2) ? hostname : hostname2);
   78: 		strncpy(ptr, host_ent->h_name, HOSTNAME_SIZE);
   79: 		ptr[HOSTNAME_SIZE] = '\0';
   80: 	
   81:     }
   82:     return (which % 2) ? (hostname) : (hostname2);
   83: }
   84: 
   85: void
   86: libnet_addr2name4_r(uint32_t in, uint8_t use_name, char *hostname,
   87:         int hostname_len)
   88: {
   89:     uint8_t *p;
   90:     struct hostent *host_ent = NULL;
   91:     struct in_addr addr;
   92: 
   93:     if (use_name == LIBNET_RESOLVE)
   94:     {   
   95: 		addr.s_addr = in;
   96:         host_ent = gethostbyaddr((int8_t *)&addr, sizeof(struct in_addr),
   97:                 AF_INET);
   98:     }
   99:     if (!host_ent)
  100:     {
  101:         p = (uint8_t *)&in;
  102:         snprintf(hostname, hostname_len, "%d.%d.%d.%d",
  103:                 (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
  104:     }
  105:     else
  106:     {
  107:         strncpy(hostname, host_ent->h_name, hostname_len - 1);
  108: 		hostname[sizeof(hostname) - 1] = '\0';
  109:     }
  110: }
  111: 
  112: uint32_t
  113: libnet_name2addr4(libnet_t *l, const char *host_name, uint8_t use_name)
  114: {
  115:     struct in_addr addr;
  116:     struct hostent *host_ent; 
  117:     uint32_t m;
  118:     uint32_t val;
  119:     int i;
  120: 
  121:     if (use_name == LIBNET_RESOLVE)
  122:     {
  123: 		if ((addr.s_addr = inet_addr(host_name)) == -1)
  124:         {
  125:             if (!(host_ent = gethostbyname(host_name)))
  126:             {
  127:                 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  128:                         "%s(): %s", __func__,
  129: #if (_WIN32)
  130:                             "gethostbyname failure"
  131: #else
  132:                             /* FIXME doesn't exist on windows, needs WSAGetLastError()/FormatMessage */
  133:                             hstrerror(h_errno)
  134: #endif
  135:                         );
  136:                 /* XXX - this is actually 255.255.255.255 */
  137:                 return (-1);
  138:             }
  139:             memcpy(&addr.s_addr, host_ent->h_addr, host_ent->h_length);
  140:         }
  141:         /* network byte order */
  142:         return (addr.s_addr);
  143:     }
  144:     else
  145:     {
  146:         /*
  147:          *  We only want dots 'n decimals.
  148:          */
  149:         if (!isdigit(host_name[0]))
  150:         {
  151:             if (l)
  152:             {
  153:                 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  154:                     "%s(): expecting dots and decimals", __func__);
  155:             }
  156:             /* XXX - this is actually 255.255.255.255 */
  157:             return (-1);
  158:         }
  159: 
  160:         m = 0;
  161:         for (i = 0; i < 4; i++)
  162:         {
  163:             m <<= 8;
  164:             if (*host_name)
  165:             {
  166:                 val = 0;
  167:                 while (*host_name && *host_name != '.')
  168:                 {   
  169:                     val *= 10;
  170:                     val += *host_name - '0';
  171:                     if (val > 255)
  172:                     {
  173:                         if (l)
  174:                         {
  175:                             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  176:                             "%s(): value greater than 255", __func__);
  177:                         }
  178:                         /* XXX - this is actually 255.255.255.255 */
  179:                         return (-1);
  180:                     }
  181:                     host_name++;
  182:                 }
  183:                 m |= val;
  184:                 if (*host_name)
  185:                 {
  186:                     host_name++;
  187:                 }
  188:             }
  189:         }
  190:         /* host byte order */
  191:        return (ntohl(m));
  192:     }
  193: }
  194: 
  195: void
  196: libnet_addr2name6_r(struct libnet_in6_addr addr, uint8_t use_name,
  197:             char *host_name, int host_name_len)
  198: {
  199:     struct hostent *host_ent = NULL;
  200: 
  201:     if (use_name == LIBNET_RESOLVE)
  202:     {    
  203: #ifdef HAVE_SOLARIS 
  204: #ifdef HAVE_SOLARIS_IPV6
  205:         host_ent = getipnodebyaddr((int8_t *)&addr, sizeof(struct in_addr),
  206:                 AF_INET6, NULL);
  207: #else
  208:         /* XXX - Gah!  Can't report error! */
  209:         host_ent = NULL;
  210: #endif
  211: #else
  212:         host_ent = gethostbyaddr((int8_t *)&addr, sizeof(struct in_addr),
  213:                 AF_INET6);
  214: #endif
  215:     }
  216:     if (!host_ent)
  217:     {
  218: #if !defined(__WIN32__) /* Silence Win32 warning */
  219:         inet_ntop(AF_INET6, &addr, host_name, host_name_len);
  220: #endif
  221:     }
  222:     else
  223:     {
  224:         strncpy(host_name, host_ent->h_name, host_name_len -1);
  225: 		host_name[sizeof(host_name) - 1] = '\0';
  226:     }
  227: }
  228: 
  229: const struct libnet_in6_addr in6addr_error = IN6ADDR_ERROR_INIT;
  230: 
  231: int
  232: libnet_in6_is_error(struct libnet_in6_addr addr)
  233: {
  234:     return 0 == memcmp(&addr, &in6addr_error, sizeof(addr));
  235: }
  236: 
  237: struct libnet_in6_addr
  238: libnet_name2addr6(libnet_t *l, const char *host_name, uint8_t use_name)
  239: {
  240: #if !defined (__WIN32__)
  241:     struct libnet_in6_addr addr;
  242:     struct hostent *host_ent; 
  243: #endif
  244:    
  245:     if (use_name == LIBNET_RESOLVE)
  246:     {
  247: #ifdef __WIN32__
  248:         /* XXX - we don't support this yet */
  249:         if (l)
  250:         {        
  251:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  252:                 "%s(): can't resolve IPv6 addresses", __func__);
  253:         }
  254:         return (in6addr_error);
  255: #else
  256: #ifdef HAVE_SOLARIS 
  257: #ifdef HAVE_SOLARIS_IPV6
  258:         if (!(host_ent = getipnodebyname((int8_t *)&addr,
  259:                 sizeof(struct in_addr), AF_INET6, NULL)))
  260: #else
  261:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, 
  262:                 "%s(): %s", __func__, strerror(errno));
  263:         return (in6addr_error);
  264: #endif
  265: #else
  266:         if (!(host_ent = gethostbyname2(host_name, AF_INET6)))
  267: #endif
  268:         {
  269:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  270:                     "%s(): %s", __func__, strerror(errno));
  271:             return (in6addr_error);
  272:         }
  273:         memcpy(&addr, host_ent->h_addr, host_ent->h_length);
  274:         return (addr);
  275: #endif  /* !__WIN32__ */
  276:     }
  277:     else
  278:     {
  279: #if defined(__WIN32__) /* Silence Win32 warning */
  280:         if (l)
  281:         {        
  282:                snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  283:                 "%s(): can't resolve IPv6 addresses.", __func__);
  284:         }
  285:         return (in6addr_error);
  286: #else
  287:         if(!inet_pton(AF_INET6, host_name, &addr))
  288:         {
  289:             if (l)
  290:             {
  291:                 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  292:                     "%s(): invalid IPv6 address", __func__);
  293:             }
  294:             return (in6addr_error);
  295:         }
  296:         return (addr);
  297: #endif
  298:     }
  299: }
  300: 
  301: #ifdef HAVE_GETIFADDRS
  302: 
  303: #include <ifaddrs.h>
  304: 
  305: struct libnet_in6_addr
  306: libnet_get_ipaddr6(libnet_t *l)
  307: {
  308:     struct ifaddrs *ifaddr, *p;
  309:     struct libnet_in6_addr addr;
  310: 
  311:     if (l == NULL)
  312:     {
  313:         return (in6addr_error);
  314:     }
  315: 
  316:     if (getifaddrs(&ifaddr) != 0)
  317:     {
  318:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  319:                 "%s(): getifaddrs(): %s", __func__, strerror(errno));
  320:         return (in6addr_error);
  321:     }
  322: 
  323:     if (l->device == NULL)
  324:     {
  325:         if (libnet_select_device(l) == -1)
  326:         {
  327:             /* error msg set in libnet_select_device() */
  328:             return (in6addr_error);
  329:         }
  330:     }
  331: 
  332:     for (p = ifaddr; p != NULL; p = p->ifa_next)
  333:     {
  334:         if ((strcmp(p->ifa_name, l->device) == 0) && (p->ifa_addr != NULL) &&
  335:                 (p->ifa_addr->sa_family == AF_INET6))
  336:         {
  337:             memcpy(&addr.__u6_addr,
  338:                     ((struct sockaddr_in6*)p->ifa_addr)->sin6_addr.s6_addr, 16);
  339:             freeifaddrs(ifaddr);
  340:             return (addr);
  341:         }
  342:     }
  343: 
  344:     freeifaddrs(ifaddr);
  345:     return (in6addr_error);
  346: }
  347: #else
  348: struct libnet_in6_addr
  349: libnet_get_ipaddr6(libnet_t *l)
  350: {
  351:     snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  352:            "%s(): not yet Implemented", __func__);
  353:     return (in6addr_error);
  354: }
  355: #endif /* WIN32 */
  356: 
  357: #if !defined(__WIN32__)
  358: uint32_t
  359: libnet_get_ipaddr4(libnet_t *l)
  360: {
  361:     struct ifreq ifr;
  362:     register struct sockaddr_in *sin;
  363:     int fd;
  364: 
  365:     if (l == NULL)
  366:     {
  367:         return (-1);
  368:     }
  369: 
  370:     /* create dummy socket to perform an ioctl upon */
  371:     fd = socket(PF_INET, SOCK_DGRAM, 0);
  372:     if (fd == -1)
  373:     {
  374:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  375:                 "%s(): socket(): %s", __func__, strerror(errno));
  376:         return (-1);
  377:     }
  378: 
  379:     sin = (struct sockaddr_in *)&ifr.ifr_addr;
  380: 
  381:     if (l->device == NULL)
  382:     {
  383:         if (libnet_select_device(l) == -1)
  384:         {
  385:             /* error msg set in libnet_select_device() */
  386:             close(fd);
  387:             return (-1);
  388:         }
  389:     }
  390:     strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) -1);
  391: 	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
  392: 	
  393:     ifr.ifr_addr.sa_family = AF_INET;
  394: 
  395:     if (ioctl(fd, SIOCGIFADDR, (int8_t*) &ifr) < 0)
  396:     {
  397:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  398:                 "%s(): ioctl(): %s", __func__, strerror(errno));
  399:         close(fd);
  400:         return (-1);
  401:     }
  402:     close(fd);
  403:     return (sin->sin_addr.s_addr);
  404: }
  405: #else
  406: #include <Packet32.h>
  407: uint32_t
  408: libnet_get_ipaddr4(libnet_t *l)
  409: {
  410:     long npflen = 1;
  411:     struct sockaddr_in sin;
  412:     struct npf_if_addr ipbuff;
  413: 
  414:     memset(&sin,0,sizeof(sin));
  415:     memset(&ipbuff,0,sizeof(ipbuff));
  416: 
  417:     if (PacketGetNetInfoEx(l->device, &ipbuff, &npflen))
  418:     {
  419:         sin = *(struct sockaddr_in *)&ipbuff.IPAddress;
  420:     }
  421:     return (sin.sin_addr.s_addr);
  422: }
  423: #endif /* WIN32 */
  424: 
  425: uint8_t *
  426: libnet_hex_aton(const char *s, int *len)
  427: {
  428:     uint8_t *buf;
  429:     int i;
  430:     int32_t l;
  431:     char *pp;
  432:         
  433:     while (isspace(*s))
  434:     {
  435:         s++;
  436:     }
  437:     for (i = 0, *len = 0; s[i]; i++)
  438:     {
  439:         if (s[i] == ':')
  440:         {
  441:             (*len)++;
  442:         }
  443:     }
  444:     buf = malloc(*len + 1);
  445:     if (buf == NULL)
  446:     {
  447:         return (NULL);
  448:     }
  449:     /* expect len hex octets separated by ':' */
  450:     for (i = 0; i < *len + 1; i++)
  451:     {
  452:         l = strtol(s, &pp, 16);
  453:         if (pp == s || l > 0xff || l < 0)
  454:         {
  455:             *len = 0;
  456:             free(buf);
  457:             return (NULL);
  458:         }
  459:         if (!(*pp == ':' || (i == *len && (isspace(*pp) || *pp == '\0'))))
  460:         {
  461:             *len = 0;
  462:             free(buf);
  463:             return (NULL);
  464:         }
  465:         buf[i] = (uint8_t)l;
  466:         s = pp + 1;
  467:     }
  468:     /* return int8_tacter after the octets ala strtol(3) */
  469:     (*len)++;
  470:     return (buf);
  471: }
  472: 
  473: /**
  474:  * Local Variables:
  475:  *  indent-tabs-mode: nil
  476:  *  c-file-style: "stroustrup"
  477:  * End:
  478:  */

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