ei_resolve.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 632 行 · 第 1/2 页
C
632 行
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ *//* * Interface functions to different versions of gethostbyname */#ifdef VXWORKS#include <vxWorks.h>#include <stdio.h>#include <semLib.h>#include <hostLib.h>#include <string.h>#include <sys/socket.h>#include <errno.h>#include <symLib.h>#include <sysSymTbl.h>#elif __WIN32__#include <winsock2.h>#include <windows.h>#include <winbase.h>#else /* unix of some kind */#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <stdlib.h>#include <string.h>#include <errno.h>#endif /* common to all platforms */#include "eidef.h"#include "ei_resolve.h"#include "ei_locking.h"#ifdef HAVE_GETHOSTBYNAME_Rvoid ei_init_resolve(void){ return; /* Do nothing */}#else /* !HAVE_GETHOSTBYNAME_R *//* we have our own in that case *//* Make sure this semaphore has been initialized somewhere first. This * should probably be done from 'erl'_init() but we do it in the first * call to gethostbyname_r() or gethostbyaddr_r(). *//* FIXME we don't want globals here, but maybe ok? */#ifdef _REENTRANTstatic ei_mutex_t *ei_gethost_sem = NULL;#endif /* _REENTRANT */static int ei_resolve_initialized = 0;#ifndef __WIN32__int h_errno;#endif#ifdef DEBUG#define DEBUGF(X) fprintf X#else#define DEBUGF(X) /* Nothing */#endif#ifdef VXWORKS/* FIXME problem for threaded ? */static struct hostent *(*sens_gethostbyname)(const char *name, char *, int) = NULL;static struct hostent *(*sens_gethostbyaddr)(const char *addr, char *, int) = NULL;#endif#ifdef VXWORKSstatic int verify_dns_configuration(void);#endif/* * If we find SENS resolver, use the functions found there, i.e. * resolvGetHostByName() and resolvGetHostByAddr(). Otherwise we use * our own, which are just wrappers around hostGetByName() and * hostGetByAddr(). Here we look up the functions. */void ei_init_resolve(void){#ifdef VXWORKS void *sym; SYM_TYPE symtype; if (symFindByName(sysSymTbl,"resolvGetHostByName", (char **)&sym,&symtype) == OK && verify_dns_configuration()) { sens_gethostbyname = sym; DEBUGF((stderr,"found SENS resolver - using it for gethostbyname()\n")); if (symFindByName(sysSymTbl,"resolvGetHostByAddr", (char **)&sym,&symtype) == OK) { sens_gethostbyaddr = sym; DEBUGF((stderr,"found SENS resolver - " "using it for gethostbyaddr()\n")); } else { DEBUGF((stderr,"SENS resolver not found - " "using default gethostbyaddr()\n")); } } else { DEBUGF((stderr,"SENS resolver not found - " "using default gethostbyname()\n")); }#endif /* VXWORKS */#ifdef _REENTRANT ei_gethost_sem = ei_mutex_create();#endif /* _REENTRANT */ ei_resolve_initialized = 1;}#ifdef VXWORKS/*** Function to verify the DNS configuration on VwXorks SENS.** Actually configures to a default value if unconfigured...*/static int verify_dns_configuration(void) { /* FIXME problem for threaded ? */ static char resolv_params[200]; /* Enough for a RESOLV_PARAMS_S struct */ void (*rpg)(char *); STATUS (*rps)(char *); SYM_TYPE dummy; if (!(symFindByName(sysSymTbl,"resolvParamsGet", (char **) &rpg, &dummy) == OK && symFindByName(sysSymTbl,"resolvParamsSet", (char **) &rps, &dummy) == OK)) return -1; (*rpg)(resolv_params); if (*resolv_params == '\0') { /* It exists, but is not configured, ei_connect would fail if we left it this way... The best we can do is to configure it to use the local host database on the card, as a fallback */ *resolv_params = (char) 1; DEBUGF((stderr,"Trying to fix up DNS configuration.\n")); if (((*rps)(resolv_params)) != OK) return -1; } return 0;}#endif /* * Copy the contents of one struct hostent to another, i.e. don't just * copy the pointers, copy all the data and create new pointers, etc. * User must provide a secondary buffer to which the host data can be copied. * * Returns 0 on success or -1 if buffer is too small for host data *//* a couple of helpers * align: increment buf until it is dword-aligned, reduce len by same amount. * advance: increment buf by n bytes, reduce len by same amount . */#define align_buf(buf,len) for (;(((unsigned)buf)&0x3); (buf)++, len--)#define advance_buf(buf,len,n) ((buf)+=(n),(len)-=(n))/* "and now the tricky part..." */static int copy_hostent(struct hostent *dest, struct hostent *src, char *buffer, int buflen){ char **pptr; int len; /* fix initial buffer alignment */ align_buf(buffer, buflen); /* copy the data into our buffer... */ /* first the easy ones! */ dest->h_length = src->h_length; dest->h_addrtype = src->h_addrtype; /* h_name */ dest->h_name = buffer; len = strlen(src->h_name); if (buflen < len+1) return -1; memmove((char *)dest->h_name,src->h_name,len); buffer[len] = (char)0; advance_buf(buffer,buflen,len+1); /* traverse alias list, collecting the pointers */ align_buf(buffer, buflen); pptr = (char **)buffer; dest->h_aliases = pptr; /* save head of pointer array */ while (*(src->h_aliases)) { if (buflen < sizeof(*pptr)) return -1; *pptr = *src->h_aliases; advance_buf(buffer,buflen,sizeof(*pptr)); src->h_aliases++; pptr++; } if (buflen < sizeof(*pptr)) return -1; *pptr = NULL; advance_buf(buffer,buflen,sizeof(*pptr)); /* go back to saved position & transfer the alias data */ pptr = dest->h_aliases; while (*pptr) { len = strlen(*pptr); if (buflen < len+1) return -1; memmove(buffer,*pptr,len); /* copy data to local buffer */ buffer[len] = (char)0; *pptr = buffer; /* point to own copy now */ advance_buf(buffer,buflen,len+1); pptr++; } /* traverse address list, collecting the pointers */ align_buf(buffer, buflen); pptr = (char **)buffer; dest->h_addr_list = pptr; /* save head of pointer array */ while (*(src->h_addr_list)) { if (buflen < sizeof(*pptr)) return -1; *pptr = *src->h_addr_list; advance_buf(buffer,buflen,sizeof(*pptr)); src->h_addr_list++; pptr++; } if (buflen < sizeof(*pptr)) return -1; *pptr = NULL; advance_buf(buffer,buflen,sizeof(*pptr)); /* go back to saved position & transfer the addresses */ /* align_buf(buffer, buflen); */ pptr = dest->h_addr_list; while (*pptr) { len = src->h_length; if (buflen < len+1) return -1; memmove(buffer,*pptr,len); /* copy data to local buffer */ buffer[len]=(char)0; /* not sure if termination is necessary */ *pptr = buffer; /* point to own copy now */ advance_buf(buffer,buflen,len+1); pptr++; } if (buflen < 0) return -1; return 0;}/* This function is a pseudo-reentrant version of gethostbyname(). It * uses locks to serialize the call to the regular (non-reentrant) * gethostbyname() and then copies the data into the user-provided * buffers. It's not pretty but it works. * * name - name of host to look up * hostp - user-supplied structure for returning host entry * buffer - user-supplied buffer: storage for the copied host data * buflen - length of user-supplied buffer * h_errnop - buffer for return status * * Returns values as for gethostbyname(). Additionally, sets * errno=ERANGE and returns NULL if buffer is too small for host data. */static struct hostent *my_gethostbyname_r(const char *name, struct hostent *hostp, char *buffer, int buflen, int *h_errnop){ struct hostent dest; struct hostent *src; struct hostent *rval = NULL; /* FIXME this should have been done in 'erl'_init()? */ if (!ei_resolve_initialized) ei_init_resolve(); #ifdef _REENTRANT /* === BEGIN critical section === */ if (ei_mutex_lock(ei_gethost_sem,0) != 0) { *h_errnop = NO_RECOVERY; return NULL; }#endif /* _REENTRANT */ /* lookup the data */ if ((src = ei_gethostbyname(name))) { /* copy to caller's buffer */ if (!copy_hostent(&dest,src,buffer,buflen)) { /* success */ *hostp = dest; *h_errnop = 0; rval = hostp; } else { /* failure - buffer size */#ifdef __WIN32__ SetLastError(ERROR_INSUFFICIENT_BUFFER);#else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?