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

1.1       misho       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: 
1.1.1.3 ! misho      31: #include "common.h"
1.1       misho      32: 
1.1.1.2   misho      33: #ifndef HAVE_GETHOSTBYNAME2
                     34: struct hostent *
                     35: gethostbyname2(const char *name, int af)
                     36: {
                     37:         return gethostbyname(name);
                     38: }
                     39: #endif
                     40: 
1.1       misho      41: char *
1.1.1.2   misho      42: libnet_addr2name4(uint32_t in, uint8_t use_name)
1.1       misho      43: {
                     44:        #define HOSTNAME_SIZE 512
                     45:     static char hostname[HOSTNAME_SIZE+1], hostname2[HOSTNAME_SIZE+1];
1.1.1.2   misho      46:     static uint16_t which;
                     47:     uint8_t *p;
1.1       misho      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: 
1.1.1.2   misho      70:         p = (uint8_t *)&in;
1.1       misho      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
1.1.1.2   misho      86: libnet_addr2name4_r(uint32_t in, uint8_t use_name, char *hostname,
1.1       misho      87:         int hostname_len)
                     88: {
1.1.1.2   misho      89:     uint8_t *p;
1.1       misho      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:     {
1.1.1.2   misho     101:         p = (uint8_t *)&in;
1.1       misho     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: 
1.1.1.2   misho     112: uint32_t
1.1.1.3 ! misho     113: libnet_name2addr4(libnet_t *l, const char *host_name, uint8_t use_name)
1.1       misho     114: {
                    115:     struct in_addr addr;
                    116:     struct hostent *host_ent; 
1.1.1.2   misho     117:     uint32_t m;
1.1.1.3 ! misho     118:     uint32_t val;
1.1       misho     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,
1.1.1.3 ! misho     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:                         );
1.1       misho     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,
1.1.1.3 ! misho     154:                     "%s(): expecting dots and decimals", __func__);
1.1       misho     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,
1.1.1.3 ! misho     176:                             "%s(): value greater than 255", __func__);
1.1       misho     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
1.1.1.2   misho     196: libnet_addr2name6_r(struct libnet_in6_addr addr, uint8_t use_name,
1.1       misho     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: 
1.1.1.2   misho     231: int
                    232: libnet_in6_is_error(struct libnet_in6_addr addr)
                    233: {
                    234:     return 0 == memcmp(&addr, &in6addr_error, sizeof(addr));
                    235: }
                    236: 
1.1       misho     237: struct libnet_in6_addr
1.1.1.2   misho     238: libnet_name2addr6(libnet_t *l, const char *host_name, uint8_t use_name)
1.1       misho     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,
1.1.1.3 ! misho     252:                 "%s(): can't resolve IPv6 addresses", __func__);
1.1       misho     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, 
1.1.1.3 ! misho     262:                 "%s(): %s", __func__, strerror(errno));
1.1       misho     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:     {
1.1.1.2   misho     279: #if defined(__WIN32__) /* Silence Win32 warning */
                    280:         if (l)
1.1       misho     281:         {        
                    282:                snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     283:                 "%s(): can't resolve IPv6 addresses.", __func__);
1.1       misho     284:         }
                    285:         return (in6addr_error);
1.1.1.2   misho     286: #else
1.1       misho     287:         if(!inet_pton(AF_INET6, host_name, &addr))
                    288:         {
                    289:             if (l)
                    290:             {
                    291:                 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     292:                     "%s(): invalid IPv6 address", __func__);
1.1       misho     293:             }
                    294:             return (in6addr_error);
                    295:         }
                    296:         return (addr);
1.1.1.2   misho     297: #endif
1.1       misho     298:     }
                    299: }
                    300: 
1.1.1.2   misho     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,
1.1.1.3 ! misho     319:                 "%s(): getifaddrs(): %s", __func__, strerror(errno));
1.1.1.2   misho     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
1.1       misho     348: struct libnet_in6_addr
                    349: libnet_get_ipaddr6(libnet_t *l)
                    350: {
                    351:     snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho     352:            "%s(): not yet Implemented", __func__);
1.1       misho     353:     return (in6addr_error);
                    354: }
1.1.1.2   misho     355: #endif /* WIN32 */
1.1       misho     356: 
                    357: #if !defined(__WIN32__)
1.1.1.2   misho     358: uint32_t
1.1       misho     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,
1.1.1.3 ! misho     375:                 "%s(): socket(): %s", __func__, strerror(errno));
1.1       misho     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,
1.1.1.3 ! misho     398:                 "%s(): ioctl(): %s", __func__, strerror(errno));
1.1       misho     399:         close(fd);
                    400:         return (-1);
                    401:     }
                    402:     close(fd);
                    403:     return (sin->sin_addr.s_addr);
                    404: }
                    405: #else
                    406: #include <Packet32.h>
1.1.1.2   misho     407: uint32_t
1.1       misho     408: libnet_get_ipaddr4(libnet_t *l)
                    409: {
1.1.1.3 ! misho     410:     long npflen = 1;
1.1       misho     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: 
1.1.1.2   misho     425: uint8_t *
                    426: libnet_hex_aton(const char *s, int *len)
1.1       misho     427: {
1.1.1.2   misho     428:     uint8_t *buf;
1.1       misho     429:     int i;
                    430:     int32_t l;
1.1.1.2   misho     431:     char *pp;
1.1       misho     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:     {
1.1.1.2   misho     452:         l = strtol(s, &pp, 16);
1.1       misho     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:         }
1.1.1.2   misho     465:         buf[i] = (uint8_t)l;
1.1       misho     466:         s = pp + 1;
                    467:     }
                    468:     /* return int8_tacter after the octets ala strtol(3) */
                    469:     (*len)++;
                    470:     return (buf);
                    471: }
                    472: 
1.1.1.3 ! misho     473: /**
        !           474:  * Local Variables:
        !           475:  *  indent-tabs-mode: nil
        !           476:  *  c-file-style: "stroustrup"
        !           477:  * End:
        !           478:  */

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