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

📄 getaddrinfo.c

📁 使用最广泛的radius的linux的源码
💻 C
字号:
/* * These functions are defined and used only if the configure * cannot detect the standard getaddrinfo(), freeaddrinfo(), * gai_strerror() and getnameinfo(). This avoids sprinkling of ifdefs. * * FIXME: getaddrinfo() & getnameinfo() should *        return all IPv4 addresses provided by DNS lookup. */#include	<freeradius-devel/ident.h>RCSID("$Id: getaddrinfo.c,v 1.12 2007/12/15 19:40:30 aland Exp $")#include	<freeradius-devel/libradius.h>#include	<ctype.h>#include 	<sys/param.h>#ifndef HAVE_GETNAMEINFO#undef LOCAL_GETHOSTBYNAMERSTYLE#ifndef GETHOSTBYNAMERSTYLE#define LOCAL_GETHOSTBYNAMERSTYLE 1#elif (GETHOSTBYNAMERSTYLE != SYSVSTYLE) && (GETHOSTBYNAMERSTYLE != GNUSTYLE)#define LOCAL_GETHOSTBYNAMERSTYLE 1#endif /* GETHOSTBYNAMERSTYLE */#endif#ifndef HAVE_GETADDRINFO#undef LOCAL_GETHOSTBYADDRR#ifndef GETHOSTBYADDRRSTYLE#define LOCAL_GETHOSTBYADDRR 1#elif (GETHOSTBYADDRRSTYLE != SYSVSTYLE) && (GETHOSTBYADDRRSTYLE != GNUSTYLE)#define LOCAL_GETHOSTBYADDRR 1#endif /* GETHOSTBYADDRRSTYLE */#endif#ifdef HAVE_PTHREAD_H#include	<pthread.h>/* Thread safe DNS lookups *//* *	FIXME: There are some systems that use the same hostent *	structure to return for gethostbyname() & gethostbyaddr(), if *	that is the case then use only one mutex instead of separate *	mutexes */#ifdef LOCAL_GETHOSTBYNAMERSTYLEstatic int fr_hostbyname = 0;static pthread_mutex_t fr_hostbyname_mutex;#endif#ifdef LOCAL_GETHOSTBYNAMERSTYLEstatic int fr_hostbyaddr = 0;static pthread_mutex_t fr_hostbyaddr_mutex;#endif#endif/* * gethostbyaddr() & gethostbyname() return hostent structure * To make these functions thread safe, we need to * copy the data and not pointers * * struct hostent { *    char    *h_name;        * official name of host * *    char    **h_aliases;    * alias list * *    int     h_addrtype;     * host address type * *    int     h_length;       * length of address * *    char    **h_addr_list;  * list of addresses * * } * This struct contains 3 pointers as members. * The data from these pointers is copied into a buffer. * The buffer is formatted as below to store the data *  --------------------------------------------------------------- * | h_name\0alias_array\0h_aliases\0..\0addr_array\0h_addr_list\0 | *  --------------------------------------------------------------- */#if defined(LOCAL_GETHOSTBYNAMER) || defined(LOCAL_GETHOSTBYADDRR)#define BUFFER_OVERFLOW 255static int copy_hostent(struct hostent *from, struct hostent *to,			char *buffer, int buflen, int *error){    int i, len;    char *ptr = buffer;    *error = 0;    to->h_addrtype = from->h_addrtype;    to->h_length = from->h_length;    to->h_name = (char *)ptr;    /* copy hostname to buffer */    len=strlen(from->h_name)+1;    strcpy(ptr, from->h_name);    ptr += len;    /* copy aliases to buffer */    to->h_aliases = (char**)ptr;    for(i = 0; from->h_aliases[i]; i++);    ptr += (i+1) * sizeof(char *);    for(i = 0; from->h_aliases[i]; i++) {       len = strlen(from->h_aliases[i])+1;       if ((ptr-buffer)+len < buflen) {           to->h_aliases[i] = ptr;	       strcpy(ptr, from->h_aliases[i]);           ptr += len;       } else {           *error = BUFFER_OVERFLOW;           return *error;       }    }    to->h_aliases[i] = NULL;    /* copy addr_list to buffer */    to->h_addr_list = (char**)ptr;    for(i = 0; (int *)from->h_addr_list[i] != 0; i++);    ptr += (i+1) * sizeof(int *);    for(i = 0; (int *)from->h_addr_list[i] != 0; i++) {       len = sizeof(int);       if ((ptr-buffer)+len < buflen) {           to->h_addr_list[i] = ptr;           memcpy(ptr, from->h_addr_list[i], len);           ptr += len;       } else {           *error = BUFFER_OVERFLOW;            return *error;       }    }    to->h_addr_list[i] = 0;    return *error;}#endif /* (LOCAL_GETHOSTBYNAMER == 1) || (LOCAL_GETHOSTBYADDRR == 1) */#ifdef LOCAL_GETHOSTBYNAMERSTYLEstatic struct hostent *gethostbyname_r(const char *hostname, struct hostent *result,           char *buffer, int buflen, int *error){    struct hostent *hp;#ifdef HAVE_PTHREAD_H    if (fr_hostbyname == 0) {    	pthread_mutex_init(&fr_hostbyname_mutex, NULL);	fr_hostbyname = 1;    }    pthread_mutex_lock(&fr_hostbyname_mutex);#endif    hp = gethostbyname(hostname);    if ((!hp) || (hp->h_addrtype != AF_INET) || (hp->h_length != 4)) {	 *error = h_errno;         hp = NULL;    } else {         copy_hostent(hp, result, buffer, buflen, error);         hp = result;    }#ifdef HAVE_PTHREAD_H    pthread_mutex_unlock(&fr_hostbyname_mutex);#endif    return hp;}#endif /* GETHOSTBYNAMERSTYLE */#ifdef LOCAL_GETHOSTBYADDRRstatic struct hostent *gethostbyaddr_r(const char *addr, int len, int type, struct hostent *result,		char *buffer, int buflen, int *error){    struct hostent *hp;#ifdef HAVE_PTHREAD_H    if (fr_hostbyaddr == 0) {    	pthread_mutex_init(&fr_hostbyaddr_mutex, NULL);	fr_hostbyaddr = 1;    }    pthread_mutex_lock(&fr_hostbyaddr_mutex);#endif    hp = gethostbyaddr(addr, len, type);    if ((!hp) || (hp->h_addrtype != AF_INET) || (hp->h_length != 4)) {	 *error = h_errno;         hp = NULL;    } else {	 copy_hostent(hp, result, buffer, buflen, error);         hp = result;    }#ifdef HAVE_PTHREAD_H    pthread_mutex_unlock(&fr_hostbyaddr_mutex);#endif    return hp;}#endif /* GETHOSTBYADDRRSTYLE *//* * Mar  8, 2000 by Hajimu UMEMOTO <ume@mahoroba.org> * * Below code is based on ssh-1.2.27-IPv6-1.5 written by * KIKUCHI Takahiro <kick@kyoto.wide.ad.jp> */#ifndef HAVE_GETADDRINFOstatic struct addrinfo *malloc_ai(int port, u_long addr, int socktype, int proto){    struct addrinfo *ai;    ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) +                                   sizeof(struct sockaddr_in));    if (ai) {        memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));        ai->ai_addr = (struct sockaddr *)(ai + 1);        ai->ai_addrlen = sizeof(struct sockaddr_in);#ifdef HAVE_SOCKADDR_SA_LEN        ai->ai_addr->sa_len = sizeof(struct sockaddr_in);#endif        ai->ai_addr->sa_family = ai->ai_family = AF_INET;        ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;        ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;        ai->ai_socktype = socktype;        ai->ai_protocol = proto;        return ai;    } else {        return NULL;    }}const char *gai_strerror(int ecode){    switch (ecode) {    case EAI_MEMORY:        return "memory allocation failure.";    case EAI_FAMILY:        return "ai_family not supported.";    case EAI_NONAME:        return "hostname nor servname provided, or not known.";    case EAI_SERVICE:        return "servname not supported for ai_socktype.";    default:        return "unknown error.";    }}voidfreeaddrinfo(struct addrinfo *ai){    struct addrinfo *next;    if (ai->ai_canonname)        free(ai->ai_canonname);    do {        next = ai->ai_next;        free(ai);    } while ((ai = next) != NULL);}intgetaddrinfo(const char *hostname, const char *servname,            const struct addrinfo *hints, struct addrinfo **res){    struct addrinfo *cur, *prev = NULL;    struct hostent *hp;    struct hostent result;    struct in_addr in;    int i, port = 0, socktype, proto;    int error;    char buffer[2048];    if (hints && hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC)        return EAI_FAMILY;    socktype = (hints && hints->ai_socktype) ? hints->ai_socktype                                             : SOCK_STREAM;    if (hints && hints->ai_protocol)        proto = hints->ai_protocol;    else {        switch (socktype) {        case SOCK_DGRAM:            proto = IPPROTO_UDP;            break;        case SOCK_STREAM:            proto = IPPROTO_TCP;            break;        default:            proto = 0;            break;        }    }    if (servname) {        if (isdigit((int)*servname))            port = htons(atoi(servname));        else {            struct servent *se;            const char *pe_proto;            switch (socktype) {            case SOCK_DGRAM:                pe_proto = "udp";                break;            case SOCK_STREAM:                pe_proto = "tcp";                break;            default:                pe_proto = NULL;                break;            }            if ((se = getservbyname(servname, pe_proto)) == NULL)                return EAI_SERVICE;            port = se->s_port;        }    }    if (!hostname) {        if (hints && hints->ai_flags & AI_PASSIVE)            *res = malloc_ai(port, htonl(0x00000000), socktype, proto);        else            *res = malloc_ai(port, htonl(0x7f000001), socktype, proto);        if (*res)            return 0;        else            return EAI_MEMORY;    }    /* Numeric IP Address */    if (inet_aton(hostname, &in)) {        *res = malloc_ai(port, in.s_addr, socktype, proto);        if (*res)            return 0;        else            return EAI_MEMORY;    }    if (hints && hints->ai_flags & AI_NUMERICHOST)        return EAI_NONAME;    /* DNS Lookup */#ifdef GETHOSTBYNAMERSTYLE#if GETHOSTBYNAMERSTYLE == SYSVSTYLE    hp = gethostbyname_r(hostname, &result, buffer, sizeof(buffer), &error);#elif GETHOSTBYNAMERSTYLE == GNUSTYLE    if (gethostbyname_r(hostname, &result, buffer,         sizeof(buffer), &hp, &error) != 0) {		hp = NULL;	}#else    hp = gethostbyname_r(hostname, &result, buffer, sizeof(buffer), &error);#endif#else    hp = gethostbyname_r(hostname, &result, buffer, sizeof(buffer), &error);#endif    if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {        for (i = 0; hp->h_addr_list[i]; i++) {            if ((cur = malloc_ai(port,                                ((struct in_addr *)hp->h_addr_list[i])->s_addr,                                socktype, proto)) == NULL) {                if (*res)                    freeaddrinfo(*res);                return EAI_MEMORY;            }            if (prev)                prev->ai_next = cur;            else                *res = cur;            prev = cur;        }        if (hints && hints->ai_flags & AI_CANONNAME && *res) {            if (((*res)->ai_canonname = strdup(hp->h_name)) == NULL) {                freeaddrinfo(*res);                return EAI_MEMORY;            }        }        return 0;    }    return EAI_NONAME;}#endif /* HAVE_GETADDRINFO */#ifndef HAVE_GETNAMEINFOintgetnameinfo(const struct sockaddr *sa, socklen_t salen,		char *host, size_t hostlen,		char *serv, size_t servlen,		unsigned int flags){    const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;    struct hostent *hp;    struct hostent result;    char tmpserv[16];    char buffer[2048];    int error;    if (serv) {        snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));        if (strlen(tmpserv) > servlen)            return EAI_MEMORY;        else            strcpy(serv, tmpserv);    }    if (host) {        if (flags & NI_NUMERICHOST) {            /*  No Reverse DNS lookup */            if (flags & NI_NAMEREQD)                return EAI_NONAME;            if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)                return EAI_MEMORY;            else {                strcpy(host, inet_ntoa(sin->sin_addr));                return 0;            }        } else {        /*  Reverse DNS lookup required */#ifdef GETHOSTBYADDRRSTYLE#if GETHOSTBYADDRRSTYLE == SYSVSTYLE            hp = gethostbyaddr_r((const char *)&sin->sin_addr,                               salen, AF_INET,			       &result, buffer, sizeof(buffer), &error);#elif GETHOSTBYADDRRSTYLE == GNUSTYLE            if (gethostbyaddr_r((const char *)&sin->sin_addr,                               salen, AF_INET,				    &result, buffer, sizeof(buffer),				    &hp, &error) != 0) {			hp = NULL;	     }#else            hp = gethostbyaddr_r((const char *)&sin->sin_addr,                               salen, AF_INET,			       &result, buffer, sizeof(buffer), &error);#endif#else            hp = gethostbyaddr_r((const char *)&sin->sin_addr,                               salen, AF_INET,			       &result, buffer, sizeof(buffer), &error);#endif            if (hp)                if (strlen(hp->h_name) >= hostlen)                    return EAI_MEMORY;                else {                    strcpy(host, hp->h_name);                    return 0;                }            else if (flags & NI_NAMEREQD)                return EAI_NONAME;            else if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)                return EAI_MEMORY;            else {                strcpy(host, inet_ntoa(sin->sin_addr));                return 0;            }        }    }    return 0;}#endif /* HAVE_GETNAMEINFO */

⌨️ 快捷键说明

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