📄 resolv.c
字号:
/* * if we got here, we didn't satisfy the search. * if we did an initial full query, return that query's h_errno * (note that we wouldn't be here if that query had succeeded). * else if we ever got a nodata, send that back as the reason. * else send back meaningless h_errno, that being the one from * the last DNSRCH we did. */ if (saved_herrno != -1) h_errno = saved_herrno; else if (got_nodata) h_errno = NO_DATA; else if (got_servfail) h_errno = TRY_AGAIN; return (-1);}/* * Perform a call on res_query on the concatenation of name and domain, * removing a trailing dot from name if domain is NULL. */int res_querydomain(name, domain, class, type, answer, anslen) const char *name, *domain; int class, type; /* class and type of query */ u_char *answer; /* buffer to put answer */ int anslen; /* size of answer */{ char nbuf[MAXDNAME]; const char *longname = nbuf; size_t n, d; if ((!name || !answer) || ((_res.options & RES_INIT) == 0 && res_init() == -1)) { h_errno = NETDB_INTERNAL; return (-1); }#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_querydomain(%s, %s, %d, %d)\n", name, domain?domain:"<Nil>", class, type);#endif if (domain == NULL) { /* * Check for trailing '.'; * copy without '.' if present. */ n = strlen(name); if (n + 1 > sizeof(nbuf)) { h_errno = NO_RECOVERY; return (-1); } if (n > 0 && name[--n] == '.') { strncpy(nbuf, name, n); nbuf[n] = '\0'; } else longname = name; } else { n = strlen(name); d = strlen(domain); if (n + 1 + d + 1 > sizeof(nbuf)) { h_errno = NO_RECOVERY; return (-1); } snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); } return (res_query(longname, class, type, answer, anslen));}/* res_mkquery *//* res_send *//* dn_comp *//* dn_expand */#endif#ifdef L_gethostbyaddrstruct hostent *gethostbyaddr (const void *addr, socklen_t len, int type){ static struct hostent h; static char buf[#ifndef __UCLIBC_HAS_IPV6__ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +#else sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +#endif /* __UCLIBC_HAS_IPV6__ */ sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */]; struct hostent *hp; gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno); return hp;}#endif#ifdef L_read_etc_hosts_rvoid __open_etc_hosts(FILE **fp){ if ((*fp = fopen("/etc/hosts", "r")) == NULL) { *fp = fopen("/etc/config/hosts", "r"); } return;}int __read_etc_hosts_r(FILE * fp, const char * name, int type, enum etc_hosts_action action, struct hostent * result_buf, char * buf, size_t buflen, struct hostent ** result, int * h_errnop){ struct in_addr *in=NULL; struct in_addr **addr_list=NULL;#ifdef __UCLIBC_HAS_IPV6__ struct in6_addr *in6=NULL; struct in6_addr **addr_list6=NULL;#endif /* __UCLIBC_HAS_IPV6__ */ char *cp; char **alias; int aliases, i; int ret=HOST_NOT_FOUND; if (buflen < sizeof(char *)*(ALIAS_DIM)) return ERANGE; alias=(char **)buf; buf+=sizeof(char **)*(ALIAS_DIM); buflen-=sizeof(char **)*(ALIAS_DIM); if (action!=GETHOSTENT) {#ifdef __UCLIBC_HAS_IPV6__ char *p=buf; size_t len=buflen;#endif /* __UCLIBC_HAS_IPV6__ */ *h_errnop=NETDB_INTERNAL; if (buflen < sizeof(*in)) return ERANGE; in=(struct in_addr*)buf; buf+=sizeof(*in); buflen-=sizeof(*in); if (buflen < sizeof(*addr_list)*2) return ERANGE; addr_list=(struct in_addr **)buf; buf+=sizeof(*addr_list)*2; buflen-=sizeof(*addr_list)*2;#ifdef __UCLIBC_HAS_IPV6__ if (len < sizeof(*in6)) return ERANGE; in6=(struct in6_addr*)p; p+=sizeof(*in6); len-=sizeof(*in6); if (len < sizeof(*addr_list6)*2) return ERANGE; addr_list6=(struct in6_addr**)p; p+=sizeof(*addr_list6)*2; len-=sizeof(*addr_list6)*2; if (len < buflen) { buflen=len; buf=p; }#endif /* __UCLIBC_HAS_IPV6__ */ if (buflen < 80) return ERANGE; __open_etc_hosts(&fp); if (fp == NULL) { result=NULL; return errno; } } *h_errnop=HOST_NOT_FOUND; while (fgets(buf, buflen, fp)) { if ((cp = strchr(buf, '#'))) *cp = '\0'; DPRINTF("Looking at: %s\n", buf); aliases = 0; cp = buf; while (*cp) { while (*cp && isspace(*cp)) *cp++ = '\0'; if (!*cp) continue; if (aliases < (2+MAX_ALIASES)) alias[aliases++] = cp; while (*cp && !isspace(*cp)) cp++; } alias[aliases] = 0; if (aliases < 2) continue; /* syntax error really */ if (action==GETHOSTENT) { /* Return whatever the next entry happens to be. */ break; } else if (action==GET_HOSTS_BYADDR) { if (strcmp(name, alias[0]) != 0) continue; } else { /* GET_HOSTS_BYNAME */ for (i = 1; i < aliases; i++) if (strcasecmp(name, alias[i]) == 0) break; if (i >= aliases) continue; } if (type == AF_INET && inet_pton(AF_INET, alias[0], in) > 0) { DPRINTF("Found INET\n"); addr_list[0] = in; addr_list[1] = 0; result_buf->h_name = alias[1]; result_buf->h_addrtype = AF_INET; result_buf->h_length = sizeof(*in); result_buf->h_addr_list = (char**) addr_list; result_buf->h_aliases = alias + 2; *result=result_buf; ret=NETDB_SUCCESS;#ifdef __UCLIBC_HAS_IPV6__ } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], in6) > 0) { DPRINTF("Found INET6\n"); addr_list6[0] = in6; addr_list6[1] = 0; result_buf->h_name = alias[1]; result_buf->h_addrtype = AF_INET6; result_buf->h_length = sizeof(*in6); result_buf->h_addr_list = (char**) addr_list6; result_buf->h_aliases = alias + 2; *result=result_buf; ret=NETDB_SUCCESS;#endif /* __UCLIBC_HAS_IPV6__ */ } else { DPRINTF("Error\n"); ret=TRY_AGAIN; break; /* bad ip address */ } if (action!=GETHOSTENT) { fclose(fp); } return ret; } if (action!=GETHOSTENT) { fclose(fp); } return ret;}#endif#ifdef L_gethostent#ifdef __UCLIBC_HAS_THREADS__static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;# define LOCK __pthread_mutex_lock(&mylock)# define UNLOCK __pthread_mutex_unlock(&mylock);#else# define LOCK# define UNLOCK#endifstatic int __stay_open;static FILE * __gethostent_fp;void endhostent (void){ LOCK; __stay_open = 0; if (__gethostent_fp) { fclose(__gethostent_fp); } UNLOCK;}void sethostent (int stay_open){ LOCK; __stay_open = stay_open; UNLOCK;}int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen, struct hostent **result, int *h_errnop){ int ret; LOCK; if (__gethostent_fp == NULL) { __open_etc_hosts(&__gethostent_fp); if (__gethostent_fp == NULL) { UNLOCK; *result=NULL; return 0; } } ret = __read_etc_hosts_r(__gethostent_fp, NULL, AF_INET, GETHOSTENT, result_buf, buf, buflen, result, h_errnop); if (__stay_open==0) { fclose(__gethostent_fp); } UNLOCK; return(ret);}struct hostent *gethostent (void){ static struct hostent h; static char buf[#ifndef __UCLIBC_HAS_IPV6__ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +#else sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +#endif /* __UCLIBC_HAS_IPV6__ */ sizeof(char *)*(ALIAS_DIM) + 80/*namebuffer*/ + 2/* margin */]; struct hostent *host; LOCK; gethostent_r(&h, buf, sizeof(buf), &host, &h_errno); UNLOCK; return(host);}#endif#ifdef L_get_hosts_byname_rint __get_hosts_byname_r(const char * name, int type, struct hostent * result_buf, char * buf, size_t buflen, struct hostent ** result, int * h_errnop){ return(__read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME, result_buf, buf, buflen, result, h_errnop));}#endif#ifdef L_get_hosts_byaddr_rint __get_hosts_byaddr_r(const char * addr, int len, int type, struct hostent * result_buf, char * buf, size_t buflen, struct hostent ** result, int * h_errnop){#ifndef __UCLIBC_HAS_IPV6__ char ipaddr[INET_ADDRSTRLEN];#else char ipaddr[INET6_ADDRSTRLEN];#endif /* __UCLIBC_HAS_IPV6__ */ switch (type) { case AF_INET: if (len != sizeof(struct in_addr)) return 0; break;#ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: if (len != sizeof(struct in6_addr)) return 0; break;#endif /* __UCLIBC_HAS_IPV6__ */ default: return 0; } inet_ntop(type, addr, ipaddr, sizeof(ipaddr)); return(__read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR, result_buf, buf, buflen, result, h_errnop));}#endif#ifdef L_getnameinfo#ifndef min# define min(x,y) (((x) > (y)) ? (y) : (x))#endif /* min */int getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, unsigned int flags){ int serrno = errno; int ok = 0; struct hostent *h = NULL; char domain[256]; if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM)) return EAI_BADFLAGS; if (sa == NULL || addrlen < sizeof (sa_family_t)) return EAI_FAMILY; switch (sa->sa_family) { case AF_LOCAL: break; case AF_INET: if (addrlen < sizeof (struct sockaddr_in)) return EAI_FAMILY; break;#ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: if (addrlen < sizeof (struct sockaddr_in6)) return EAI_FAMILY; break;#endif /* __UCLIBC_HAS_IPV6__ */ default: return EAI_FAMILY; } if (host != NULL && hostlen > 0) switch (sa->sa_family) { case AF_INET:#ifdef __UCLIBC_HAS_IPV6__ case AF_INET6:#endif /* __UCLIBC_HAS_IPV6__ */ if (!(flags & NI_NUMERICHOST)) {#ifdef __UCLIBC_HAS_IPV6__ if (sa->sa_family == AF_INET6) h = gethostbyaddr ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr), sizeof(struct in6_addr), AF_INET6); else#endif /* __UCLIBC_HAS_IPV6__ */ h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr), sizeof(struct in_addr), AF_INET); if (h) { char *c; if ((flags & NI_NOFQDN) && (getdomainname (domain, sizeof(domain)) == 0) && (c = strstr (h->h_name, domain)) && (c != h->h_name) && (*(--c) == '.')) { strncpy (host, h->h_name, min(hostlen, (size_t) (c - h->h_name))); host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0'; ok = 1; } else { strncpy (host, h->h_name, hostlen); ok = 1; } } } if (!ok) { if (flags & NI_NAMEREQD) { errno = serrno; return EAI_NONAME; } else { const char *c;#ifdef __UCLIBC_HAS_IPV6__ if (sa->sa_family == AF_INET6) { const struct sockaddr_in6 *sin6p; sin6p = (const struct sockaddr_in6 *) sa; c = inet_ntop (AF_INET6, (const void *) &sin6p->sin6_addr, host, hostlen);#if 0/* Does scope id need to be supported? */ uint32_t scopeid; scopeid = sin6p->sin6_scope_id; if (scopeid != 0) { /* Buffer is >= IFNAMSIZ+1. */ char scopebuf[IFNAMSIZ + 1]; char *scopeptr; int ni_numericscope = 0; size_t real_hostlen = __strnlen (host, hostlen); size_t scopelen = 0; scopebuf[0] = SCOPE_DELIMITER; scopebuf[1] = '\0'; scopeptr = &scopebuf[1]; if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) { if (if_indextoname (scopeid, scopeptr) == NULL) ++ni_numericscope; else scopelen = strlen (scopebuf); } else { ++ni_numericscope; } if (ni_numericscope) scopelen = 1 + snprintf (scopeptr, (scopebuf + sizeof scopebuf - scopeptr), "%u", scopeid); if (real_hostlen + scopelen + 1 > hostlen) return EAI_SYSTEM; memcpy (host + real_hostlen, scopebuf, scopelen + 1); }#endif } else#endif /* __UCLIBC_HAS_IPV6__ */ c = inet_ntop (AF_INET, (const void *) &(((const struct sockaddr_in *) sa)->sin_addr), host, hostlen); if (c == NULL) { errno = serrno; return EAI_SYSTEM; } } ok = 1; } break; case AF_LOCAL: if (!(flags & NI_NUMERICHOST)) { struct utsname utsname; if (!uname (&utsname)) { strncpy (host, utsname.nodename, hostlen); break; }; }; if (flags & NI_NAMEREQD) { errno = serrno; return EAI_NONAME; } strncpy (host, "localhost", hostlen); break; default: return EAI_FAMILY; } if (serv && (servlen > 0)) { switch (sa->sa_family) { case AF_INET:#ifdef __UCLIBC_HAS_IPV6__ case AF_INET6:#endif /* __UCLIBC_HAS_IPV6__ */ if (!(flags & NI_NUMERICSERV)) { struct servent *s; s = getservbyport (((const struct sockaddr_in *) sa)->sin_port, ((flags & NI_DGRAM) ? "udp" : "tcp")); if (s) { strncpy (serv, s->s_name, servlen); break; } } snprintf (serv, servlen, "%d", ntohs (((const struct sockaddr_in *) sa)->sin_port)); break; case AF_LOCAL: strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen); break; } } if (host && (hostlen > 0)) host[hostlen-1] = 0; if (serv && (servlen > 0)) serv[servlen-1] = 0; errno = serrno; return 0;}#endif#ifdef L_gethostbyname_rint gethostbyname_r(const char * name, struct hostent * result_buf, char * buf, size_t buflen, struct hostent ** result, int * h_errnop){ struct in_addr *in; struct in_addr **addr_list; char **alias; unsigned char *packet; struct resolv_answer a; int i; int nest = 0; int __nameserversXX; char ** __nameserverXX; __open_nameservers(); *result=NULL; if (!name) return EINVAL; /* do /etc/hosts first */ { int old_errno = errno; /* Save the old errno and reset errno */ __set_errno(0); /* to check for missing /etc/hosts. */ if ((i=__get_hosts_byname_r(name, AF_INET, result_buf, buf, buflen, result, h_errnop))==0) return i; switch (*h_errnop) { case HOST_NOT_FOUND: case NO_ADDRESS: break; case NETDB_INTERNAL: if (errno == ENOENT) { break; } /* else fall through */ default: return i; } __set_errno(old_errno); } DPRINTF("Nothing found in /etc/hosts\n"); *h_errnop = NETDB_INTERNAL; if (buflen < sizeof(*in)) return ERANGE; in=(struct in_addr*)buf; buf+=sizeof(*in); buflen-=sizeof(*in); if (buflen < sizeof(*addr_list)*2) return ERANGE; addr_list=(struct in_addr**)buf; buf+=sizeof(*addr_list)*2; buflen-=sizeof(*addr_list)*2; addr_list[0] = in; addr_list[1] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -