📄 resolver.c
字号:
#ifndef lintstatic char *rcsid = "$Id: resolver.c,v 1.1.1.1 2003/06/04 00:27:12 marka Exp $";#endif/* * Copyright (c) 2001 Japan Network Information Center. All rights reserved. * * By using this file, you agree to the terms and conditions set forth bellow. * * LICENSE TERMS AND CONDITIONS * * The following License Terms and Conditions apply, unless a different * license is obtained from Japan Network Information Center ("JPNIC"), * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, * Chiyoda-ku, Tokyo 101-0047, Japan. * * 1. Use, Modification and Redistribution (including distribution of any * modified or derived work) in source and/or binary forms is permitted * under this License Terms and Conditions. * * 2. Redistribution of source code must retain the copyright notices as they * appear in each source code file, this License Terms and Conditions. * * 3. Redistribution in binary form must reproduce the Copyright Notice, * this License Terms and Conditions, in the documentation and/or other * materials provided with the distribution. For the purposes of binary * distribution the "Copyright Notice" refers to the following language: * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved." * * 4. The name of JPNIC may not be used to endorse or promote products * derived from this Software without specific prior written approval of * JPNIC. * * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */#include <config.h>#include <stdio.h>#include <stddef.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <errno.h>#include <idn/api.h>#include <idn/log.h>#include <idn/logmacro.h>#include <idn/debug.h>#ifdef FOR_RUNIDN/* * This file is specially compiled for runidn. * runidn replaces existing resolver functions dynamically with ones * with IDN processing (encoding conversion and normalization). * So entry names must be same as the system's one. */#include "stub.h"#define ENTRY(name) name#define REAL(name) idn_stub_ ## name#else/* * For normal use. All the entry names are prefixed with "idn_resolver_". * <idn/resolver.h> has bunch of #defines to substitute the standard * name resolver functions with ones provided here. */#include "resolver.h"#undef gethostbyname#undef gethostbyname2#undef gethostbyaddr#undef gethostbyname_r#undef gethostbyname2_r#undef gethostbyaddr_r#undef getipnodebyname#undef getipnodebyaddr#undef getaddrinfo#undef getnameinfo#define ENTRY(name) idn_resolver_ ## name#define REAL(name) name#endif#define IDN_NAME_SIZE 512#define IDN_HOSTBUF_SIZE 2048typedef union { char *dummy_for_alignment; char data[IDN_HOSTBUF_SIZE];} hostbuf_t;typedef struct obj_lock { void *key; struct obj_lock *next;} obj_lock_t;#define OBJLOCKHASH_SIZE 127static obj_lock_t *obj_lock_hash[OBJLOCKHASH_SIZE];/* * This variable is to prevent IDN processing occuring more than once for * a single name resolution. This will happen if some resolver function * is implemented using another function (e.g. gethostbyname() implemented * using gethostbyname2()). * No, using the static variable is not a correct thing to do for a multi- * threading environment, but I don't think of a better solution.. */static int idn_isprocessing = 0;static int obj_hash(void *key);static int obj_islocked(void *key);static void obj_lock(void *key);static void obj_unlock(void *key);static struct hostent *copy_decode_hostent_static(struct hostent *hp, struct hostent *newhp, char *buf, size_t buflen, int *errp);static char *decode_name_dynamic(const char *name);static struct hostent *copy_decode_hostent_dynamic(struct hostent *hp, int *errp);static void free_copied_hostent(struct hostent *hp);#ifdef HAVE_GETADDRINFOstatic struct addrinfo *copy_decode_addrinfo_dynamic(struct addrinfo *aip);#endif#ifdef HAVE_FREEADDRINFOstatic void free_copied_addrinfo(struct addrinfo *aip);#endif/* * Object locking facility. */static intobj_hash(void *key) { /* * Hash function for obj_*. * 'key' is supposed to be an address. */ unsigned long v = (unsigned long)key; return ((v >> 3) % OBJLOCKHASH_SIZE);}static intobj_islocked(void *key){ /* * Check if the object specified by 'key' is locked. * Return 1 if so, 0 otherwise. */ int h = obj_hash(key); obj_lock_t *olp = obj_lock_hash[h]; while (olp != NULL) { if (olp->key == key) return (1); olp = olp->next; } return (0);}static voidobj_lock(void *key){ /* * Lock an object specified by 'key'. */ int h = obj_hash(key); obj_lock_t *olp; olp = malloc(sizeof(obj_lock_t)); if (olp != NULL) { olp->key = key; olp->next = obj_lock_hash[h]; obj_lock_hash[h] = olp; }}static voidobj_unlock(void *key){ /* * Unlock an object specified by 'key'. */ int h = obj_hash(key); obj_lock_t *olp, *olp0; olp = obj_lock_hash[h]; olp0 = NULL; while (olp != NULL) { if (olp->key == key) { if (olp0 == NULL) obj_lock_hash[h] = olp->next; else olp0->next = olp->next; free(olp); return; } olp0 = olp; olp = olp->next; }}static struct hostent *copy_decode_hostent_static(struct hostent *hp, struct hostent *newhp, char *buf, size_t buflen, int *errp){ /* * Copy "struct hostent" data referenced by 'hp' to 'newhp'. * It's a deep-copy, meaning all the data referenced by 'hp' are * also copied. They are copied into 'buf', whose length is 'buflen'. * The domain names ('hp->h_name' and 'hp->h_aliases') are * decoded from ACE to the local encoding before they are copied. * If 'buf' is too small to hold all the data, NULL will be * returned and '*errp' is set to NO_RECOVERY. */ int naliases = 0; int naddrs = 0; if (hp == NULL) return (NULL); *newhp = *hp; if (hp->h_aliases != NULL) { /* * Allocate aliase table in 'buf'. */ size_t sz; while (hp->h_aliases[naliases] != NULL) naliases++; newhp->h_aliases = (char **)buf; sz = sizeof(char *) * (naliases + 1); if (buflen < sz) goto overflow; buf += sz; buflen -= sz; } if (hp->h_addr_list != NULL) { /* * Allocate address table in 'buf'. */ size_t sz; int i; while (hp->h_addr_list[naddrs] != NULL) naddrs++; newhp->h_addr_list = (char **)buf; sz = sizeof(char *) * (naddrs + 1); if (buflen < sz) goto overflow; buf += sz; buflen -= sz; /* * Copy the addresses. */ sz = hp->h_length * naddrs; if (buflen < sz) goto overflow; for (i = 0; i < naddrs; i++) { newhp->h_addr_list[i] = buf; memcpy(buf, hp->h_addr_list[i], hp->h_length); buf += hp->h_length; } newhp->h_addr_list[naddrs] = NULL; buf += sz; buflen -= sz; } if (hp->h_name != NULL) { /* * Decode the name in h_name. */ idn_result_t r; size_t slen; idn_enable(1); idn_nameinit(1); r = idn_decodename(IDN_DECODE_APP, hp->h_name, buf, buflen); switch (r) { case idn_success: newhp->h_name = buf; break; default: /* Copy hp->h_name verbatim. */ if (strlen(hp->h_name) + 1 <= buflen) { newhp->h_name = buf; strcpy(buf, hp->h_name); break; } /* falllthrough */ case idn_buffer_overflow: goto overflow; } slen = strlen(buf) + 1; buf += slen; buflen -= slen; } if (hp->h_aliases != NULL) { /* * Decode the names in h_aliases. */ char **aliases = hp->h_aliases; char **newaliases = newhp->h_aliases; int i; for (i = 0; i < naliases; i++) { idn_result_t r; size_t slen; idn_enable(1); idn_nameinit(1); r = idn_decodename(IDN_DECODE_APP, aliases[i], buf, buflen); switch (r) { case idn_success: newaliases[i] = buf; break; default: /* Copy hp->h_name verbatim. */ if (strlen(aliases[i]) + 1 <= buflen) { newaliases[i] = buf; strcpy(buf, aliases[i]); break; } /* falllthrough */ case idn_buffer_overflow: goto overflow; } slen = strlen(buf) + 1; buf += slen; buflen -= slen; } newaliases[naliases] = NULL; } return (newhp); overflow: *errp = NO_RECOVERY; return (NULL);}static char *decode_name_dynamic(const char *name) { idn_result_t r; char buf[IDN_NAME_SIZE]; char *s; idn_enable(1); idn_nameinit(1); r = idn_decodename(IDN_DECODE_APP, name, buf, sizeof(buf)); if (r == idn_success) { name = buf; } s = malloc(strlen(name) + 1); if (s == NULL) return (NULL); else return (strcpy(s, name));} static struct hostent *copy_decode_hostent_dynamic(struct hostent *hp, int *errp) { /* * Make a deep-copy of the data referenced by 'hp', and return * a pointer to the copied data. * All the data are dynamically allocated using malloc(). * The domain names ('hp->h_name' and 'hp->h_aliases') are * decoded from ACE to the local encoding before they are copied. * If malloc() fails, NULL will be returned and '*errp' is set to * NO_RECOVERY. */ struct hostent *newhp; char **pp; size_t alloc_size; int naliases = 0; int naddrs = 0; int i; if (hp == NULL) return (NULL); if (hp->h_aliases != NULL) { while (hp->h_aliases[naliases] != NULL) naliases++; } if (hp->h_addr_list != NULL) { while (hp->h_addr_list[naddrs] != NULL) naddrs++; } alloc_size = sizeof(struct hostent) + sizeof(char *) * (naliases + 1) + sizeof(char *) * (naddrs + 1) + hp->h_length * naddrs; if ((newhp = malloc(alloc_size)) == NULL) { return (hp); } memset(newhp, 0, alloc_size); pp = (char **)(newhp + 1); if (hp->h_name != NULL) { newhp->h_name = decode_name_dynamic(hp->h_name); if (newhp->h_name == NULL) goto alloc_fail; } newhp->h_addrtype = hp->h_addrtype; newhp->h_length = hp->h_length; if (hp->h_aliases != NULL) { newhp->h_aliases = pp; for (i = 0; i < naliases; i++) { newhp->h_aliases[i] = decode_name_dynamic(hp->h_aliases[i]); if (newhp->h_aliases[i] == NULL) goto alloc_fail; } newhp->h_aliases[naliases] = NULL; pp += naliases + 1; } if (hp->h_addr_list != NULL) { char *p; newhp->h_addr_list = pp; pp += naddrs + 1; p = (char *)pp; for (i = 0; i < naddrs; i++) { newhp->h_addr_list[i] = p; memcpy(p, hp->h_addr_list[i], hp->h_length); p += hp->h_length; } newhp->h_addr_list[naddrs] = NULL; } return (newhp); alloc_fail: free_copied_hostent(hp); *errp = NO_RECOVERY; return (NULL);}static voidfree_copied_hostent(struct hostent *hp) { /* * Free all the memory allocated by copy_decode_hostent_dynamic(). */ if (hp->h_name != NULL) free(hp->h_name); if (hp->h_aliases != NULL) { char **pp = hp->h_aliases; while (*pp != NULL) free(*pp++); } free(hp);}#ifdef HAVE_GETNAMEINFOstatic struct addrinfo *copy_decode_addrinfo_dynamic(struct addrinfo *aip) { struct addrinfo *newaip; if (aip == NULL) return (NULL); newaip = malloc(sizeof(struct addrinfo) + aip->ai_addrlen); if (newaip == NULL) return (NULL); *newaip = *aip; newaip->ai_addr = (struct sockaddr *)(newaip + 1); memcpy(newaip->ai_addr, aip->ai_addr, aip->ai_addrlen); if (newaip->ai_canonname != NULL) newaip->ai_canonname = decode_name_dynamic(aip->ai_canonname); newaip->ai_next = copy_decode_addrinfo_dynamic(aip->ai_next); return (newaip);}#endif#ifdef HAVE_FREEADDRINFOstatic voidfree_copied_addrinfo(struct addrinfo *aip) { while (aip != NULL) { struct addrinfo *next = aip->ai_next; if (aip->ai_canonname != NULL) free(aip->ai_canonname); free(aip); aip = next; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -