File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_resolve.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:14:23 2012 UTC (12 years, 5 months ago) by misho
Branches: libnet, MAIN
CVS tags: v1_1_2_1, HEAD
libnet

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

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