getaddrinfo.c

来自「eCos操作系统源码」· C语言 代码 · 共 528 行 · 第 1/2 页

C
528
字号
    return EAI_NONE;#else    return (numeric_node_addr(ai, node, hints, port));#endif}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;    char *endptr;    int port = 0;    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)) {        return EAI_NONAME;    }    switch (hints->ai_family) {    case PF_UNSPEC:    case PF_INET:        break;#ifdef CYGPKG_NET_INET6    case PF_INET6:        break;#endif    default:        return EAI_FAMILY;    }    // Allocate the first/primary result    *res = ai = alloc_addrinfo(NULL);    if (ai == (struct addrinfo *)NULL) {        return EAI_MEMORY;    }    // Handle request    if (hints->ai_protocol != 0) {        proto = getprotobynumber(hints->ai_protocol);    }        // Note: this does not handle the case where a given service can be    // handled via multiple protocols, e.g. http/tcp & http/udp    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);            return EAI_SOCKTYPE;        }        // See if this is just a port #        if (((port = strtol(servname, &endptr, 0)) >= 0) &&            (endptr > servname)) {            ai->ai_socktype = hints->ai_socktype;            if (hints->ai_socktype == 0) {                // Need to have complete binding type/port                freeaddrinfo(ai);                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";                    ai->ai_socktype = SOCK_DGRAM;                        serv = getservbyname(servname, protoname);                }            }            if (serv == (struct servent *)NULL) {                freeaddrinfo(ai);                return EAI_SERVICE;            }            port = ntohs(serv->s_port);          }        proto = getprotobyname(protoname);        if (hints->ai_protocol && (hints->ai_protocol != proto->p_proto)) {            freeaddrinfo(ai);            return EAI_SOCKTYPE;        }        ai->ai_protocol = proto->p_proto;    }        if (nodename) {        if (hints->ai_flags & AI_NUMERICHOST) {            err = numeric_node_addr(ai, nodename, hints, port);        } else {            err = with_node_addr(ai, nodename, hints, port );        }    } else {        err = no_node_addr(ai, hints, port);    }        if (err != EAI_NONE) {        freeaddrinfo(ai);        return err;    }    if ((hints->ai_flags & AI_CANONNAME) && !nodename) {        ai->ai_canonname = malloc(strlen("localhost")+1);        if (ai->ai_canonname) {            strcpy(ai->ai_canonname, "localhost");        } else {            freeaddrinfo(ai);            return EAI_MEMORY;        }    }        /* The DNS code may have filled in the official address. If not       and we have been asked for it, return an error */    if ((hints->ai_flags & AI_CANONNAME) & !ai->ai_canonname) {        freeaddrinfo(ai);        return EAI_FAIL;    }    return EAI_NONE;  // No errors}// The canonname will probably point to the same memory in each// addrinfo in the linked list. Don't free it multiple times.void  freeaddrinfo(struct addrinfo *ai){    struct addrinfo *next = ai;    char * last_canonname = NULL;    while ((ai = next) != (struct addrinfo *)NULL) {        if ((ai->ai_canonname) &&             (ai->ai_canonname != last_canonname)) {             free(ai->ai_canonname);            last_canonname = 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;    int error;    int numeric = (flags & NI_NUMERICHOST);    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) {            if ( !numeric) {                error = EAI_NONAME;#ifdef CYGPKG_NS_DNS_BUILD                error = -cyg_dns_getnameinfo(sa, host,hostlen);#endif                if ((error == EAI_NONAME) && (flags & NI_NAMEREQD)) {                    return EAI_NONAME;                }                // If lookup failed, try it as numeric address                numeric = !(error == EAI_NONE);            }            if (numeric) {                s = _inet_ntop((struct sockaddr *)sa, host, hostlen);                if (!s) {                    return EAI_FAIL;                }            }            if (!numeric && flags & NI_NOFQDN) {                s = index(host, '.');                if (s) {                    *s = '\0';                }            }        }            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(htons(port), "tcp");                }                if (se == (struct servent *)NULL) {                    se = getservbyport(htons(port), "udp");                }            }            if (se != (struct servent *)NULL) {                diag_snprintf(serv,servlen, "%s/%s", se->s_name, se->s_proto);            } else {                diag_snprintf(serv,servlen, "%d", port);            }        }        break;    default:        return EAI_FAMILY;    }    return EAI_NONE;}

⌨️ 快捷键说明

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