⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getipnode.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1999-2003  Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *//* $Id: getipnode.c,v 1.30.2.5 2003/10/09 07:32:55 marka Exp $ */#include <config.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <lwres/lwres.h>#include <lwres/net.h>#include <lwres/netdb.h>	/* XXX #include <netdb.h> */#include "assert_p.h"#ifndef INADDRSZ#define INADDRSZ 4#endif#ifndef IN6ADDRSZ#define IN6ADDRSZ 16#endif#ifdef LWRES_PLATFORM_NEEDIN6ADDRANYLIBLWRES_EXTERNAL_DATA const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;#endif#ifndef IN6_IS_ADDR_V4COMPATstatic const unsigned char in6addr_compat[12] = {        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \                                 ((x)->s6_addr[12] != 0 || \                                  (x)->s6_addr[13] != 0 || \                                  (x)->s6_addr[14] != 0 || \                                   ((x)->s6_addr[15] != 0 && \                                    (x)->s6_addr[15] != 1)))#endif#ifndef IN6_IS_ADDR_V4MAPPED#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))#endifstatic const unsigned char in6addr_mapped[12] = {        0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0xff, 0xff};/*** ***	Forward declarations. ***/static intscan_interfaces(int *, int *);static struct hostent *copyandmerge(struct hostent *, struct hostent *, int, int *);static struct hostent *hostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src);static struct hostent *hostfromname(lwres_gabnresponse_t *name, int af);/*** ***	Public functions. ***//* *	AI_V4MAPPED + AF_INET6 *	If no IPv6 address then a query for IPv4 and map returned values. * *	AI_ALL + AI_V4MAPPED + AF_INET6 *	Return IPv6 and IPv4 mapped. * *	AI_ADDRCONFIG *	Only return IPv6 / IPv4 address if there is an interface of that *	type active. */struct hostent *lwres_getipnodebyname(const char *name, int af, int flags, int *error_num) {	int have_v4 = 1, have_v6 = 1;	struct in_addr in4;	struct in6_addr in6;	struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL;	int v4 = 0, v6 = 0;	int tmp_err;	lwres_context_t *lwrctx = NULL;	lwres_gabnresponse_t *by = NULL;	int n;	/*	 * If we care about active interfaces then check.	 */	if ((flags & AI_ADDRCONFIG) != 0)		if (scan_interfaces(&have_v4, &have_v6) == -1) {			*error_num = NO_RECOVERY;			return (NULL);		}	/* Check for literal address. */	if ((v4 = lwres_net_pton(AF_INET, name, &in4)) != 1)		v6 = lwres_net_pton(AF_INET6, name, &in6);	/*	 * Impossible combination?	 */	if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||	    (af == AF_INET && v6 == 1) ||	    (have_v4 == 0 && v4 == 1) ||	    (have_v6 == 0 && v6 == 1) ||	    (have_v4 == 0 && af == AF_INET) ||	    (have_v6 == 0 && af == AF_INET6 &&	     (((flags & AI_V4MAPPED) != 0 && have_v4) ||	      (flags & AI_V4MAPPED) == 0))) {		*error_num = HOST_NOT_FOUND;		return (NULL);	}	/*	 * Literal address?	 */	if (v4 == 1 || v6 == 1) {		char *addr_list[2];		char *aliases[1];		char mappedname[sizeof("::ffff:123.123.123.123")];		union {			const char *const_name;			char *deconst_name;		} u;		u.const_name = name;		if (v4 == 1 && af == AF_INET6) {			strcpy(mappedname, "::ffff:");			lwres_net_ntop(AF_INET, (char *)&in4,				       mappedname + sizeof("::ffff:") - 1,				       sizeof(mappedname) - sizeof("::ffff:")				       + 1);			he.h_name = mappedname;		} else			he.h_name = u.deconst_name;		he.h_addr_list = addr_list;		he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;		he.h_addr_list[1] = NULL;		he.h_aliases = aliases;		he.h_aliases[0] = NULL;		he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ;		he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6;		return (copyandmerge(&he, NULL, af, error_num));	}	n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);	if (n != 0) {		*error_num = NO_RECOVERY;		goto cleanup;	}	(void) lwres_conf_parse(lwrctx, lwres_resolv_conf);	tmp_err = NO_RECOVERY;	if (have_v6 && af == AF_INET6) {		n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by);		if (n == 0) {			he1 = hostfromname(by, AF_INET6);			lwres_gabnresponse_free(lwrctx, &by);			if (he1 == NULL) {				*error_num = NO_RECOVERY;				goto cleanup;			}		} else {			tmp_err = HOST_NOT_FOUND;		}	}	if (have_v4 &&	    ((af == AF_INET) ||	     (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 &&	      (he1 == NULL || (flags & AI_ALL) != 0)))) {		n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by);		if (n == 0) {			he2 = hostfromname(by, AF_INET);			lwres_gabnresponse_free(lwrctx, &by);			if (he2 == NULL) {				*error_num = NO_RECOVERY;				goto cleanup;			}		} else if (he1 == NULL) {			if (n == LWRES_R_NOTFOUND)				*error_num = HOST_NOT_FOUND;			else				*error_num = NO_RECOVERY;			goto cleanup;		}	} else		*error_num = tmp_err;	he3 = copyandmerge(he1, he2, af, error_num); cleanup:	if (he1 != NULL)		lwres_freehostent(he1);	if (he2 != NULL)		lwres_freehostent(he2);	if (lwrctx != NULL) {		lwres_conf_clear(lwrctx);		lwres_context_destroy(&lwrctx);	}	return (he3);}struct hostent *lwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) {	struct hostent *he1, *he2;	lwres_context_t *lwrctx = NULL;	lwres_gnbaresponse_t *by = NULL;	lwres_result_t n;	union {		const void *konst;		struct in6_addr *in6;	} u;	/*	 * Sanity checks.	 */	if (src == NULL) {		*error_num = NO_RECOVERY;		return (NULL);	}	switch (af) {	case AF_INET:		if (len != (unsigned int)INADDRSZ) {			*error_num = NO_RECOVERY;			return (NULL);		}		break;	case AF_INET6:		if (len != (unsigned int)IN6ADDRSZ) {			*error_num = NO_RECOVERY;			return (NULL);		}		break;	default:		*error_num = NO_RECOVERY;		return (NULL);	}	/*	 * The de-"const"-ing game is done because at least one	 * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_*	 * macros in such a way that they discard the const with	 * internal casting, and gcc ends up complaining.  Rather	 * than replacing their own (possibly optimized) definitions	 * with our own, cleanly discarding the const is the easiest	 * thing to do.	 */	u.konst = src;	/*	 * Look up IPv4 and IPv4 mapped/compatible addresses.	 */	if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(u.in6)) ||	    (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(u.in6)) ||	    (af == AF_INET)) {		const unsigned char *cp = src;		if (af == AF_INET6)			cp += 12;		n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);		if (n == LWRES_R_SUCCESS)			(void) lwres_conf_parse(lwrctx, lwres_resolv_conf);		if (n == LWRES_R_SUCCESS)			n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4,						INADDRSZ, cp, &by);		if (n != LWRES_R_SUCCESS) {			lwres_conf_clear(lwrctx);			lwres_context_destroy(&lwrctx);			if (n == LWRES_R_NOTFOUND)				*error_num = HOST_NOT_FOUND;			else				*error_num = NO_RECOVERY;			return (NULL);		}		he1 = hostfromaddr(by, AF_INET, cp);		lwres_gnbaresponse_free(lwrctx, &by);		lwres_conf_clear(lwrctx);		lwres_context_destroy(&lwrctx);		if (af != AF_INET6)			return (he1);		/*		 * Convert from AF_INET to AF_INET6.		 */		he2 = copyandmerge(he1, NULL, af, error_num);		lwres_freehostent(he1);		if (he2 == NULL)			return (NULL);		/*		 * Restore original address.		 */		memcpy(he2->h_addr, src, len);		return (he2);	}	/*	 * Lookup IPv6 address.	 */	if (memcmp(src, &in6addr_any, IN6ADDRSZ) == 0) {		*error_num = HOST_NOT_FOUND;		return (NULL);	}	n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);	if (n == LWRES_R_SUCCESS)		(void) lwres_conf_parse(lwrctx, lwres_resolv_conf);	if (n == LWRES_R_SUCCESS)		n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ,					src, &by);	if (n != 0) {		*error_num = HOST_NOT_FOUND;		return (NULL);	}	he1 = hostfromaddr(by, AF_INET6, src);	lwres_gnbaresponse_free(lwrctx, &by);	if (he1 == NULL)		*error_num = NO_RECOVERY;	lwres_context_destroy(&lwrctx);	return (he1);}voidlwres_freehostent(struct hostent *he) {	char **cpp;	int names = 1;	int addresses = 1;	free(he->h_name);	cpp = he->h_addr_list;	while (*cpp != NULL) {		free(*cpp);		*cpp = NULL;		cpp++;		addresses++;	}	cpp = he->h_aliases;	while (*cpp != NULL) {		free(*cpp);		cpp++;		names++;	}	free(he->h_aliases);	free(he->h_addr_list);	free(he);}/* * Private *//* * Scan the interface table and set have_v4 and have_v6 depending * upon whether there are IPv4 and IPv6 interface addresses. * * Returns: *	0 on success *	-1 on failure. */static intscan_interfaces(int *have_v4, int *have_v6) {#if 1	*have_v4 = *have_v6 = 1;	return (0);#else	struct ifconf ifc;	struct ifreq ifreq;	struct in_addr in4;	struct in6_addr in6;	char *buf = NULL, *cp, *cplim;	static int bufsiz = 4095;	int s, cpsize, n;	/*	 * Set to zero.  Used as loop terminators below.	 */	*have_v4 = *have_v6 = 0;	/*	 * Get interface list from system.	 */	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)		goto err_ret;	/*	 * Grow buffer until large enough to contain all interface	 * descriptions.	 */	for (;;) {		buf = malloc(bufsiz);		if (buf == NULL)			goto err_ret;		ifc.ifc_len = bufsiz;		ifc.ifc_buf = buf;#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF		/*		 * This is a fix for IRIX OS in which the call to ioctl with		 * the flag SIOCGIFCONF may not return an entry for all the		 * interfaces like most flavors of Unix.		 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -