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