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

📄 getaddrinfo.c

📁 ecos实时嵌入式操作系统
💻 C
字号:
//==========================================================================////      lib/getaddrinfo.c////      getaddrinfo(), freeaddrinfo(), gai_strerror(), getnameinfo()////==========================================================================//####ECOSPDCOPYRIGHTBEGIN####//// Copyright (C) 2000, 2001, 2002 Red Hat, Inc.// All Rights Reserved.//// Permission is granted to use, copy, modify and redistribute this// file.////####ECOSPDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    gthomas// Contributors: gthomas// Date:         2002-03-05// Purpose:      // Description:  //              ////####DESCRIPTIONEND####////==========================================================================#include <sys/param.h>#include <sys/socket.h>           // PF_xxx#include <netinet/in.h>           // IPPROTO_xx#include <net/netdb.h>#include <errno.h>#include <cyg/infra/cyg_ass.h>extern int  sprintf(char *, const char *, ...);extern long strtol(const char *, char **, int);extern void *malloc(size_t);extern void *calloc(int, size_t);extern void free(void *);// This routine is the real meat of the host->address translationstatic int_getaddr(struct addrinfo *ai, const char *node,          const struct addrinfo *hints, int family, int port){    switch (family) {    case AF_INET:    {        struct sockaddr_in *sa;        sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));        ai->ai_addr = (struct sockaddr *)sa;        ai->ai_addrlen = sizeof(*sa);        if (ai->ai_addr == (struct sockaddr *)NULL) {            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);            return EAI_MEMORY;        }        sa->sin_family = AF_INET;        sa->sin_len = sizeof(*sa);        sa->sin_port = htons(port);        if (node == (char *)NULL) {            if (hints->ai_flags & AI_PASSIVE) {                sa->sin_addr.s_addr = htonl(INADDR_ANY);            } else {                sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK);            }        } else {            // For now, only numeric "presentation" addresses supported            if (!inet_pton(AF_INET, (char *)node, (char *)&sa->sin_addr.s_addr)) {            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);                return EAI_FAIL;  // Couldn't resolve name            }        }    }    break;#ifdef CYGPKG_NET_INET6    case AF_INET6:    {        struct sockaddr_in6 *sa;        sa = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));        ai->ai_addr = (struct sockaddr *)sa;        ai->ai_addrlen = sizeof(*sa);        if (ai->ai_addr == (struct sockaddr *)NULL) {            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);            return EAI_MEMORY;        }        sa->sin6_family = AF_INET6;        sa->sin6_len = sizeof(*sa);        sa->sin6_port = htons(port);        if (node == (char *)NULL) {            if (hints->ai_flags & AI_PASSIVE) {                sa->sin6_addr = in6addr_any;            } else {                sa->sin6_addr = in6addr_loopback;            }        } else {            // For now, only numeric "presentation" addresses supported            if (!inet_pton(AF_INET6, (char *)node, (char *)&sa->sin6_addr)) {            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);                return EAI_FAIL;  // Couldn't resolve name            }        }    }    break;#endif    }    return EAI_NONE;}int   getaddrinfo(const char *nodename, const char *servname,            const struct addrinfo *hints, struct addrinfo **res){    struct addrinfo dflt_hints;    struct protoent *proto = (struct protoent *)NULL;    struct addrinfo *ai;    char *protoname;    int port = 0;    int family;    int err;    if (hints == (struct addrinfo *)NULL) {        dflt_hints.ai_flags = 0;  // No special flags        dflt_hints.ai_family = PF_UNSPEC;        dflt_hints.ai_socktype = 0;        dflt_hints.ai_protocol = 0;        hints = &dflt_hints;    }    // Prevalidate parameters    if ((nodename == (char *)NULL) && (servname == (char *)NULL)) {            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);        return EAI_NONAME;    }    switch (hints->ai_family) {    case PF_UNSPEC:    case PF_INET:        family = AF_INET;        break;#ifdef CYGPKG_NET_INET6    case PF_INET6:        family = AF_INET6;        break;#endif    default:            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);        return EAI_FAMILY;    }    // Allocate the first/primary result    *res = ai = (struct addrinfo *)calloc(1, sizeof(struct addrinfo));    if (ai == (struct addrinfo *)NULL) {            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);        return EAI_MEMORY;    }    // Handle request    if (hints->ai_protocol != 0) {        proto = getprotobynumber(hints->ai_protocol);    }    ai->ai_family = family;    if (servname != (char *)NULL) {        switch (hints->ai_socktype) {        case 0:        case SOCK_STREAM:            protoname = "tcp";            ai->ai_socktype = SOCK_STREAM;            break;        case SOCK_DGRAM:            protoname = "udp";            ai->ai_socktype = SOCK_DGRAM;            break;        default:            freeaddrinfo(ai);            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);            return EAI_SOCKTYPE;        }        // See if this is just a port #        if ((port = strtol(servname, 0, 0)) > 0) {            ai->ai_socktype = hints->ai_socktype;            if (hints->ai_socktype == 0) {                // Need to have complete binding type/port                freeaddrinfo(ai);            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);                return EAI_SERVICE;            }        } else {            struct servent *serv = (struct servent *)NULL;            serv = getservbyname(servname, protoname);            if (serv == (struct servent *)NULL) {                if (hints->ai_socktype == 0) {                    protoname = "udp";                    serv = getservbyname(servname, protoname);                }            }            if (serv == (struct servent *)NULL) {                freeaddrinfo(ai);            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);                return EAI_SERVICE;            }            port = ntohs(serv->s_port);              }        proto = getprotobyname(protoname);        if (hints->ai_protocol && (hints->ai_protocol != proto->p_proto)) {            freeaddrinfo(ai);            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);            return EAI_SOCKTYPE;        }        ai->ai_protocol = proto->p_proto;    }    // Iterate through address types and create addresses    // Note: this does not handle the case where a given service can be    // handled via multiple protocols, e.g. http/tcp & http/udp    err = _getaddr(ai, nodename, hints, family, port);    if (err != EAI_NONE) {        freeaddrinfo(ai);        return err;    }#ifdef CYGPKG_NET_INET6    if (hints->ai_family == PF_UNSPEC) {        // Add IPv6 address as well        struct addrinfo *nai = (struct addrinfo *)calloc(1, sizeof(struct addrinfo));        if (nai == (struct addrinfo *)NULL) {            freeaddrinfo(ai);            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);            return EAI_MEMORY;        }        ai->ai_next = nai;        nai->ai_family = PF_INET6;        nai->ai_socktype = ai->ai_socktype;        nai->ai_protocol = ai->ai_protocol;        err = _getaddr(nai, nodename, hints, AF_INET6, port);        if (err != EAI_NONE) {            freeaddrinfo(*res);            return err;        }    }#endif    // Note: null nodename is the same as 'localhost'    if (nodename == (char *)NULL) {        nodename = (const char *)"localhost";    }    if (hints->ai_flags & AI_CANONNAME) {        // Hack - until host name handling is more complete        ai = *res;  // Canonical name is only in primary record        ai->ai_canonname = malloc(strlen(nodename)+1);        if (ai->ai_canonname) {            strcpy(ai->ai_canonname, nodename);        }    }    if (hints->ai_flags & AI_PASSIVE) {        // Incomplete addressing - used for bind/listen    } else {        // Complete addressing - used for connect/send/...    }    return EAI_NONE;  // No errors}void  freeaddrinfo(struct addrinfo *ai){    struct addrinfo *next = ai;    while ((ai = next) != (struct addrinfo *)NULL) {        if (ai->ai_canonname) free(ai->ai_canonname);        if (ai->ai_addr) free(ai->ai_addr);        next = ai->ai_next;        free(ai);    }}char *gai_strerror(int err){    switch (err) {    case EAI_NONE:        return "EAI - no error";    case EAI_AGAIN:        return "EAI - temporary failure in name resolution";    case EAI_BADFLAGS:        return "EAI - invalid flags";    case EAI_FAIL:        return "EAI - non-recoverable failure in name resolution";    case EAI_FAMILY:        return "EAI - family not supported";    case EAI_MEMORY:        return "EAI - memory allocation failure";    case EAI_NONAME:        return "EAI - hostname nor servname provided, or not known";    case EAI_SERVICE:        return "EAI - servname not supported for socket type";    case EAI_SOCKTYPE:        return "EAI - socket type not supported";    case EAI_SYSTEM:        return "EAI - system error";    case EAI_BADHINTS:        return "EAI - inconsistent hints";    case EAI_PROTOCOL:        return "EAI - bad protocol";    default:        return "EAI - unknown error";    }}// Set of flags implemented#define NI_MASK (NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM)int getnameinfo (const struct sockaddr *sa, socklen_t salen,              char *host, socklen_t hostlen,              char *serv, socklen_t servlen,              unsigned int flags){    int port;    char *s;    struct servent *se;    if ((flags & ~NI_MASK) != 0) {        return EAI_BADFLAGS;    }    switch (sa->sa_family) {    case PF_INET:#ifdef CYGPKG_NET_INET6    case PF_INET6:#endif        if (host != (char *)NULL) {            s = _inet_ntop((struct sockaddr *)sa, host, hostlen);            if (!s) {                return EAI_FAIL;            }        }        if (serv != (char *)NULL) {            port = _inet_port((struct sockaddr *)sa);            if (!port) {                return EAI_FAIL;            }            se = (struct servent *)NULL;            if ((flags & NI_NUMERICSERV) == 0) {                if ((flags & NI_DGRAM) == 0) {                    se = getservbyport(port, "tcp");                }                if (se == (struct servent *)NULL) {                    se = getservbyport(port, "ucp");                }            }            if (se != (struct servent *)NULL) {                sprintf(serv, "%s/%s", se->s_name, se->s_proto);            } else {                sprintf(serv, "%d", port);            }        }        break;    default:        return EAI_FAMILY;    }    return EAI_NONE;}

⌨️ 快捷键说明

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