📄 getaddrinfo.c
字号:
if (pai->ai_flags & AI_CANONNAME) { if (get_canonname(pai, res, cname) != 0) { freeaddrinfo(res0); goto again; } } } return res0;}/*ARGSUSED*/static int_files_getaddrinfo(rv, cb_data, ap) void *rv; void *cb_data; va_list ap;{ const char *name; const struct addrinfo *pai; struct addrinfo sentinel, *cur; struct addrinfo *p; name = va_arg(ap, char *); pai = va_arg(ap, struct addrinfo *); memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; _sethtent(); while ((p = _gethtent(name, pai)) != NULL) { cur->ai_next = p; while (cur && cur->ai_next) cur = cur->ai_next; } _endhtent(); *((struct addrinfo **)rv) = sentinel.ai_next; if (sentinel.ai_next == NULL) return NS_NOTFOUND; return NS_SUCCESS;}#ifdef YPstatic char *__ypdomain;/*ARGSUSED*/static struct addrinfo *_yphostent(line, pai) char *line; const struct addrinfo *pai;{ struct addrinfo sentinel, *cur; struct addrinfo hints, *res, *res0; int error; char *p = line; const char *addr, *canonname; char *nextline; char *cp; addr = canonname = NULL; memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel;nextline: /* terminate line */ cp = strchr(p, '\n'); if (cp) { *cp++ = '\0'; nextline = cp; } else nextline = NULL; cp = strpbrk(p, " \t"); if (cp == NULL) { if (canonname == NULL) return (NULL); else goto done; } *cp++ = '\0'; addr = p; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (!canonname) canonname = cp; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; } hints = *pai; hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(addr, NULL, &hints, &res0); if (error == 0) { for (res = res0; res; res = res->ai_next) { /* cover it up */ res->ai_flags = pai->ai_flags; if (pai->ai_flags & AI_CANONNAME) (void)get_canonname(pai, res, canonname); } } else res0 = NULL; if (res0) { cur->ai_next = res0; while (cur && cur->ai_next) cur = cur->ai_next; } if (nextline) { p = nextline; goto nextline; }done: return sentinel.ai_next;}/*ARGSUSED*/static int_yp_getaddrinfo(rv, cb_data, ap) void *rv; void *cb_data; va_list ap;{ struct addrinfo sentinel, *cur; struct addrinfo *ai = NULL; static char *__ypcurrent; int __ypcurrentlen, r; const char *name; const struct addrinfo *pai; name = va_arg(ap, char *); pai = va_arg(ap, const struct addrinfo *); memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; if (!__ypdomain) { if (_yp_check(&__ypdomain) == 0) return NS_UNAVAIL; } if (__ypcurrent) free(__ypcurrent); __ypcurrent = NULL; /* hosts.byname is only for IPv4 (Solaris8) */ if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { r = yp_match(__ypdomain, "hosts.byname", name, (int)strlen(name), &__ypcurrent, &__ypcurrentlen); if (r == 0) { struct addrinfo ai4; ai4 = *pai; ai4.ai_family = AF_INET; ai = _yphostent(__ypcurrent, &ai4); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } } } /* ipnodes.byname can hold both IPv4/v6 */ r = yp_match(__ypdomain, "ipnodes.byname", name, (int)strlen(name), &__ypcurrent, &__ypcurrentlen); if (r == 0) { ai = _yphostent(__ypcurrent, pai); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } } if (sentinel.ai_next == NULL) { h_errno = HOST_NOT_FOUND; return NS_NOTFOUND; } *((struct addrinfo **)rv) = sentinel.ai_next; return NS_SUCCESS;}#endif/* resolver logic */extern const char *__hostalias(const char *);extern int h_errno;/* * Formulate a normal query, send, and await answer. * Returned answer is placed in supplied buffer "answer". * Perform preliminary check of answer, returning success only * if no error is indicated and the answer count is nonzero. * Return the size of the response on success, -1 on error. * Error number is left in h_errno. * * Caller must parse answer and determine whether it answers the question. */static intres_queryN(name, target) const char *name; /* domain name */ struct res_target *target;{ u_char buf[MAXPACKET]; HEADER *hp; int n; struct res_target *t; int rcode; int ancount; rcode = NOERROR; ancount = 0; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (-1); } for (t = target; t; t = t->next) { int class, type; u_char *answer; int anslen; hp = (HEADER *)(void *)t->answer; hp->rcode = NOERROR; /* default */ /* make it easier... */ class = t->qclass; type = t->qtype; answer = t->answer; anslen = t->anslen;#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query(%s, %d, %d)\n", name, class, type);#endif n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, buf, sizeof(buf)); if (n > 0 && (_res.options & RES_USE_EDNS0) != 0) n = res_opt(n, buf, sizeof(buf), anslen); if (n <= 0) {#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query: mkquery failed\n");#endif h_errno = NO_RECOVERY; return (n); } n = res_send(buf, n, answer, anslen);#if 0 if (n < 0) {#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query: send error\n");#endif h_errno = TRY_AGAIN; return (n); }#endif if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { rcode = hp->rcode; /* record most recent error */#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; rcode = %d, ancount=%d\n", hp->rcode, ntohs(hp->ancount));#endif continue; } ancount += ntohs(hp->ancount); t->n = n; } if (ancount == 0) { switch (rcode) { case NXDOMAIN: h_errno = HOST_NOT_FOUND; break; case SERVFAIL: h_errno = TRY_AGAIN; break; case NOERROR: h_errno = NO_DATA; break; case FORMERR: case NOTIMP: case REFUSED: default: h_errno = NO_RECOVERY; break; } return (-1); } return (ancount);}/* * Formulate a normal query, send, and retrieve answer in supplied buffer. * Return the size of the response on success, -1 on error. * If enabled, implement search rules until answer or unrecoverable failure * is detected. Error code, if any, is left in h_errno. */static intres_searchN(name, target) const char *name; /* domain name */ struct res_target *target;{ const char *cp, * const *domain; HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/ u_int dots; int trailing_dot, ret, saved_herrno; int got_nodata = 0, got_servfail = 0, tried_as_is = 0; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (-1); } errno = 0; h_errno = HOST_NOT_FOUND; /* default, if we never query */ dots = 0; for (cp = name; *cp; cp++) dots += (*cp == '.'); trailing_dot = 0; if (cp > name && *--cp == '.') trailing_dot++; /* * if there aren't any dots, it could be a user-level alias */ if (!dots && (cp = __hostalias(name)) != NULL) return (res_queryN(cp, target)); /* * If there are dots in the name already, let's just give it a try * 'as is'. The threshold can be set with the "ndots" option. */ saved_herrno = -1; if (dots >= _res.ndots) { ret = res_querydomainN(name, NULL, target); if (ret > 0) return (ret); saved_herrno = h_errno; tried_as_is++; } /* * We do at least one level of search if * - there is no dot and RES_DEFNAME is set, or * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ if ((!dots && (_res.options & RES_DEFNAMES)) || (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { int done = 0; for (domain = (const char * const *)_res.dnsrch; *domain && !done; domain++) { ret = res_querydomainN(name, *domain, target); if (ret > 0) return (ret); /* * If no server present, give up. * If name isn't found in this domain, * keep trying higher domains in the search list * (if that's enabled). * On a NO_DATA error, keep trying, otherwise * a wildcard entry of another type could keep us * from finding this entry higher in the domain. * If we get some other error (negative answer or * server failure), then stop searching up, * but try the input name below in case it's * fully-qualified. */ if (errno == ECONNREFUSED) { h_errno = TRY_AGAIN; return (-1); } switch (h_errno) { case NO_DATA: got_nodata++; /* FALLTHROUGH */ case HOST_NOT_FOUND: /* keep trying */ break; case TRY_AGAIN: if (hp->rcode == SERVFAIL) { /* try next search element, if any */ got_servfail++; break; } /* FALLTHROUGH */ default: /* anything else implies that we're done */ done++; } /* * if we got here for some reason other than DNSRCH, * we only wanted one iteration of the loop, so stop. */ if (!(_res.options & RES_DNSRCH)) done++; } } /* * if we have not already tried the name "as is", do that now. * note that we do this regardless of how many dots were in the * name or whether it ends with a dot. */ if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) { ret = res_querydomainN(name, NULL, target); if (ret > 0) return (ret); } /* * 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. */static intres_querydomainN(name, domain, target) const char *name, *domain; struct res_target *target;{ char nbuf[MAXDNAME]; const char *longname = nbuf; size_t n, d; if ((_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)\n", name, domain?domain:"<Nil>");#endif if (domain == NULL) { /* * Check for trailing '.'; * copy without '.' if present. */ n = strlen(name); if (n >= MAXDNAME) { 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 + d + 1 >= MAXDNAME) { h_errno = NO_RECOVERY; return (-1); } sprintf(nbuf, "%s.%s", name, domain); } return (res_queryN(longname, target));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -