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 *)∈
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 *)∈
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>