Annotation of embedaddon/libnet/src/libnet_resolve.c, revision 1.1.1.2

1.1       misho       1: /*
1.1.1.2 ! misho       2:  *  $Id: libnet_resolve.c,v 1.21 2004/11/09 07:05:07 mike Exp $
1.1       misho       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: 
1.1.1.2 ! misho      42: #ifndef HAVE_GETHOSTBYNAME2
        !            43: struct hostent *
        !            44: gethostbyname2(const char *name, int af)
        !            45: {
        !            46:         return gethostbyname(name);
        !            47: }
        !            48: #endif
        !            49: 
1.1       misho      50: char *
1.1.1.2 ! misho      51: libnet_addr2name4(uint32_t in, uint8_t use_name)
1.1       misho      52: {
                     53:        #define HOSTNAME_SIZE 512
                     54:     static char hostname[HOSTNAME_SIZE+1], hostname2[HOSTNAME_SIZE+1];
1.1.1.2 ! misho      55:     static uint16_t which;
        !            56:     uint8_t *p;
1.1       misho      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: 
1.1.1.2 ! misho      79:         p = (uint8_t *)&in;
1.1       misho      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
1.1.1.2 ! misho      95: libnet_addr2name4_r(uint32_t in, uint8_t use_name, char *hostname,
1.1       misho      96:         int hostname_len)
                     97: {
1.1.1.2 ! misho      98:     uint8_t *p;
1.1       misho      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:     {
1.1.1.2 ! misho     110:         p = (uint8_t *)&in;
1.1       misho     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: 
1.1.1.2 ! misho     121: uint32_t
        !           122: libnet_name2addr4(libnet_t *l, char *host_name, uint8_t use_name)
1.1       misho     123: {
                    124:     struct in_addr addr;
                    125:     struct hostent *host_ent; 
1.1.1.2 ! misho     126:     uint32_t m;
        !           127:     uint val;
1.1       misho     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,
1.1.1.2 ! misho     137:                         "%s(): %s\n", __func__, hstrerror(h_errno));
1.1       misho     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
1.1.1.2 ! misho     198: libnet_addr2name6_r(struct libnet_in6_addr addr, uint8_t use_name,
1.1       misho     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: 
1.1.1.2 ! misho     233: int
        !           234: libnet_in6_is_error(struct libnet_in6_addr addr)
        !           235: {
        !           236:     return 0 == memcmp(&addr, &in6addr_error, sizeof(addr));
        !           237: }
        !           238: 
1.1       misho     239: struct libnet_in6_addr
1.1.1.2 ! misho     240: libnet_name2addr6(libnet_t *l, const char *host_name, uint8_t use_name)
1.1       misho     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:     {
1.1.1.2 ! misho     281: #if defined(__WIN32__) /* Silence Win32 warning */
        !           282:         if (l)
1.1       misho     283:         {        
                    284:                snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
                    285:                 "%s(): can't resolve IPv6 addresses.\n", __func__);
                    286:         }
                    287:         return (in6addr_error);
1.1.1.2 ! misho     288: #else
1.1       misho     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);
1.1.1.2 ! misho     299: #endif
1.1       misho     300:     }
                    301: }
                    302: 
1.1.1.2 ! misho     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
1.1       misho     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: }
1.1.1.2 ! misho     357: #endif /* WIN32 */
1.1       misho     358: 
                    359: #if !defined(__WIN32__)
1.1.1.2 ! misho     360: uint32_t
1.1       misho     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>
1.1.1.2 ! misho     409: uint32_t
1.1       misho     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: 
1.1.1.2 ! misho     428: uint8_t *
        !           429: libnet_hex_aton(const char *s, int *len)
1.1       misho     430: {
1.1.1.2 ! misho     431:     uint8_t *buf;
1.1       misho     432:     int i;
                    433:     int32_t l;
1.1.1.2 ! misho     434:     char *pp;
1.1       misho     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:     {
1.1.1.2 ! misho     455:         l = strtol(s, &pp, 16);
1.1       misho     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:         }
1.1.1.2 ! misho     468:         buf[i] = (uint8_t)l;
1.1       misho     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>