Annotation of embedaddon/libnet/src/libnet_resolve.c, revision 1.1.1.1
1.1 misho 1: /*
2: * $Id: libnet_resolve.c,v 1.20 2004/03/04 20:52:26 kkuehl 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: char *
43: libnet_addr2name4(u_int32_t in, u_int8_t use_name)
44: {
45: #define HOSTNAME_SIZE 512
46: static char hostname[HOSTNAME_SIZE+1], hostname2[HOSTNAME_SIZE+1];
47: static u_int16_t which;
48: u_int8_t *p;
49:
50: struct hostent *host_ent = NULL;
51: struct in_addr addr;
52:
53: /*
54: * Swap to the other buffer. We swap static buffers to avoid having to
55: * pass in a int8_t *. This makes the code that calls this function more
56: * intuitive, but makes this function ugly. This function is seriously
57: * non-reentrant. For threaded applications (or for signal handler code)
58: * use host_lookup_r().
59: */
60: which++;
61:
62: if (use_name == LIBNET_RESOLVE)
63: {
64: addr.s_addr = in;
65: host_ent = gethostbyaddr((int8_t *)&addr, sizeof(struct in_addr), AF_INET);
66: /* if this fails, we silently ignore the error and move to plan b! */
67: }
68: if (!host_ent)
69: {
70:
71: p = (u_int8_t *)∈
72: snprintf(((which % 2) ? hostname : hostname2), HOSTNAME_SIZE,
73: "%d.%d.%d.%d",
74: (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
75: }
76: else if (use_name == LIBNET_RESOLVE)
77: {
78: char *ptr = ((which % 2) ? hostname : hostname2);
79: strncpy(ptr, host_ent->h_name, HOSTNAME_SIZE);
80: ptr[HOSTNAME_SIZE] = '\0';
81:
82: }
83: return (which % 2) ? (hostname) : (hostname2);
84: }
85:
86: void
87: libnet_addr2name4_r(u_int32_t in, u_int8_t use_name, char *hostname,
88: int hostname_len)
89: {
90: u_int8_t *p;
91: struct hostent *host_ent = NULL;
92: struct in_addr addr;
93:
94: if (use_name == LIBNET_RESOLVE)
95: {
96: addr.s_addr = in;
97: host_ent = gethostbyaddr((int8_t *)&addr, sizeof(struct in_addr),
98: AF_INET);
99: }
100: if (!host_ent)
101: {
102: p = (u_int8_t *)∈
103: snprintf(hostname, hostname_len, "%d.%d.%d.%d",
104: (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
105: }
106: else
107: {
108: strncpy(hostname, host_ent->h_name, hostname_len - 1);
109: hostname[sizeof(hostname) - 1] = '\0';
110: }
111: }
112:
113: u_int32_t
114: libnet_name2addr4(libnet_t *l, char *host_name, u_int8_t use_name)
115: {
116: struct in_addr addr;
117: struct hostent *host_ent;
118: u_int32_t m;
119: u_int val;
120: int i;
121:
122: if (use_name == LIBNET_RESOLVE)
123: {
124: if ((addr.s_addr = inet_addr(host_name)) == -1)
125: {
126: if (!(host_ent = gethostbyname(host_name)))
127: {
128: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
129: "%s(): %s\n", __func__, strerror(errno));
130: /* XXX - this is actually 255.255.255.255 */
131: return (-1);
132: }
133: memcpy(&addr.s_addr, host_ent->h_addr, host_ent->h_length);
134: }
135: /* network byte order */
136: return (addr.s_addr);
137: }
138: else
139: {
140: /*
141: * We only want dots 'n decimals.
142: */
143: if (!isdigit(host_name[0]))
144: {
145: if (l)
146: {
147: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
148: "%s(): expecting dots and decimals\n", __func__);
149: }
150: /* XXX - this is actually 255.255.255.255 */
151: return (-1);
152: }
153:
154: m = 0;
155: for (i = 0; i < 4; i++)
156: {
157: m <<= 8;
158: if (*host_name)
159: {
160: val = 0;
161: while (*host_name && *host_name != '.')
162: {
163: val *= 10;
164: val += *host_name - '0';
165: if (val > 255)
166: {
167: if (l)
168: {
169: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
170: "%s(): value greater than 255\n", __func__);
171: }
172: /* XXX - this is actually 255.255.255.255 */
173: return (-1);
174: }
175: host_name++;
176: }
177: m |= val;
178: if (*host_name)
179: {
180: host_name++;
181: }
182: }
183: }
184: /* host byte order */
185: return (ntohl(m));
186: }
187: }
188:
189: void
190: libnet_addr2name6_r(struct libnet_in6_addr addr, u_int8_t use_name,
191: char *host_name, int host_name_len)
192: {
193: struct hostent *host_ent = NULL;
194:
195: if (use_name == LIBNET_RESOLVE)
196: {
197: #ifdef HAVE_SOLARIS
198: #ifdef HAVE_SOLARIS_IPV6
199: host_ent = getipnodebyaddr((int8_t *)&addr, sizeof(struct in_addr),
200: AF_INET6, NULL);
201: #else
202: /* XXX - Gah! Can't report error! */
203: host_ent = NULL;
204: #endif
205: #else
206: host_ent = gethostbyaddr((int8_t *)&addr, sizeof(struct in_addr),
207: AF_INET6);
208: #endif
209: }
210: if (!host_ent)
211: {
212: #if !defined(__WIN32__) /* Silence Win32 warning */
213: inet_ntop(AF_INET6, &addr, host_name, host_name_len);
214: #endif
215: }
216: else
217: {
218: strncpy(host_name, host_ent->h_name, host_name_len -1);
219: host_name[sizeof(host_name) - 1] = '\0';
220: }
221: }
222:
223: const struct libnet_in6_addr in6addr_error = IN6ADDR_ERROR_INIT;
224:
225: struct libnet_in6_addr
226: libnet_name2addr6(libnet_t *l, char *host_name, u_int8_t use_name)
227: {
228: #if !defined (__WIN32__)
229: struct libnet_in6_addr addr;
230: struct hostent *host_ent;
231: #endif
232:
233: if (use_name == LIBNET_RESOLVE)
234: {
235: #ifdef __WIN32__
236: /* XXX - we don't support this yet */
237: if (l)
238: {
239: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
240: "%s(): can't resolve IPv6 addresses\n", __func__);
241: }
242: return (in6addr_error);
243: #else
244: #ifdef HAVE_SOLARIS
245: #ifdef HAVE_SOLARIS_IPV6
246: if (!(host_ent = getipnodebyname((int8_t *)&addr,
247: sizeof(struct in_addr), AF_INET6, NULL)))
248: #else
249: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
250: "%s(): %s\n", __func__, strerror(errno));
251: return (in6addr_error);
252: #endif
253: #else
254: if (!(host_ent = gethostbyname2(host_name, AF_INET6)))
255: #endif
256: {
257: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
258: "%s(): %s", __func__, strerror(errno));
259: return (in6addr_error);
260: }
261: memcpy(&addr, host_ent->h_addr, host_ent->h_length);
262: return (addr);
263: #endif /* !__WIN32__ */
264: }
265: else
266: {
267: #if defined(__WIN32__) /* Silence Win32 warning */
268: if (l)
269: {
270: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
271: "%s(): can't resolve IPv6 addresses.\n", __func__);
272: }
273: return (in6addr_error);
274: #else
275: if(!inet_pton(AF_INET6, host_name, &addr))
276: {
277: if (l)
278: {
279: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
280: "%s(): invalid IPv6 address\n", __func__);
281: }
282: return (in6addr_error);
283: }
284: return (addr);
285: #endif
286: }
287: }
288:
289: struct libnet_in6_addr
290: libnet_get_ipaddr6(libnet_t *l)
291: {
292: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
293: "%s(): not yet Implemented\n", __func__);
294: return (in6addr_error);
295: }
296:
297: #if !defined(__WIN32__)
298: u_int32_t
299: libnet_get_ipaddr4(libnet_t *l)
300: {
301: struct ifreq ifr;
302: register struct sockaddr_in *sin;
303: int fd;
304:
305: if (l == NULL)
306: {
307: return (-1);
308: }
309:
310: /* create dummy socket to perform an ioctl upon */
311: fd = socket(PF_INET, SOCK_DGRAM, 0);
312: if (fd == -1)
313: {
314: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
315: "%s(): socket(): %s\n", __func__, strerror(errno));
316: return (-1);
317: }
318:
319: sin = (struct sockaddr_in *)&ifr.ifr_addr;
320:
321: if (l->device == NULL)
322: {
323: if (libnet_select_device(l) == -1)
324: {
325: /* error msg set in libnet_select_device() */
326: close(fd);
327: return (-1);
328: }
329: }
330: strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) -1);
331: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
332:
333: ifr.ifr_addr.sa_family = AF_INET;
334:
335: if (ioctl(fd, SIOCGIFADDR, (int8_t*) &ifr) < 0)
336: {
337: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
338: "%s(): ioctl(): %s\n", __func__, strerror(errno));
339: close(fd);
340: return (-1);
341: }
342: close(fd);
343: return (sin->sin_addr.s_addr);
344: }
345: #else
346: #include <Packet32.h>
347: u_int32_t
348: libnet_get_ipaddr4(libnet_t *l)
349: {
350: long npflen = 0;
351: struct sockaddr_in sin;
352: struct npf_if_addr ipbuff;
353:
354: memset(&sin,0,sizeof(sin));
355: memset(&ipbuff,0,sizeof(ipbuff));
356:
357: npflen = sizeof(ipbuff);
358: if (PacketGetNetInfoEx(l->device, &ipbuff, &npflen))
359: {
360: sin = *(struct sockaddr_in *)&ipbuff.IPAddress;
361: }
362: return (sin.sin_addr.s_addr);
363: }
364: #endif /* WIN32 */
365:
366: u_int8_t *
367: libnet_hex_aton(int8_t *s, int *len)
368: {
369: u_int8_t *buf;
370: int i;
371: int32_t l;
372: int8_t *pp;
373:
374: while (isspace(*s))
375: {
376: s++;
377: }
378: for (i = 0, *len = 0; s[i]; i++)
379: {
380: if (s[i] == ':')
381: {
382: (*len)++;
383: }
384: }
385: buf = malloc(*len + 1);
386: if (buf == NULL)
387: {
388: return (NULL);
389: }
390: /* expect len hex octets separated by ':' */
391: for (i = 0; i < *len + 1; i++)
392: {
393: l = strtol(s, (char **)&pp, 16);
394: if (pp == s || l > 0xff || l < 0)
395: {
396: *len = 0;
397: free(buf);
398: return (NULL);
399: }
400: if (!(*pp == ':' || (i == *len && (isspace(*pp) || *pp == '\0'))))
401: {
402: *len = 0;
403: free(buf);
404: return (NULL);
405: }
406: buf[i] = (u_int8_t)l;
407: s = pp + 1;
408: }
409: /* return int8_tacter after the octets ala strtol(3) */
410: (*len)++;
411: return (buf);
412: }
413:
414: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>