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