📄 getaddrinfo.c
字号:
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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -