📄 arlib.c
字号:
return (ar_query_name(hname, C_IN, T_A, rptr));}/* * ar_gethostbyaddr * * Generates a query for a given IP address. */int ar_gethostbyaddr(addr, info, size)char *addr;char *info;int size;{ struct resinfo resi; register struct resinfo *rp = &resi; if (size && info) { rp->ri_ptr = (char *)malloc(size); bcopy(info, rp->ri_ptr, size); rp->ri_size = size; } else bzero((char *)rp, sizeof(resi)); ar_reinfo.re_nu_look++; return (do_query_number(rp, addr, NULL));}/* * do_query_number * * Use this to do reverse IP# lookups. */static int do_query_number(resi, numb, rptr)struct resinfo *resi;char *numb;register struct reslist *rptr;{ register unsigned char *cp; static char ipbuf[32]; /* * Generate name in the "in-addr.arpa" domain. No addings bits to this * name to get more names to query!. */ cp = (unsigned char *)numb; (void)sprintf(ipbuf,"%u.%u.%u.%u.in-addr.arpa.", (unsigned int)(cp[3]), (unsigned int)(cp[2]), (unsigned int)(cp[1]), (unsigned int)(cp[0])); if (!rptr) { rptr = ar_make_request(resi); rptr->re_type = T_PTR; rptr->re_he.h_length = sizeof(struct in_addr); bcopy(numb, (char *)&rptr->re_addr, rptr->re_he.h_length); bcopy(numb, (char *)&rptr->re_he.h_addr_list[0].s_addr, rptr->re_he.h_length); } return (ar_query_name(ipbuf, C_IN, T_PTR, rptr));}/* * ar_resent_query * * resends a query. */static int ar_resend_query(rptr)struct reslist *rptr;{ if (!rptr->re_resend) return -1; switch(rptr->re_type) { case T_PTR: ar_reinfo.re_resends++; return do_query_number(NULL, &rptr->re_addr, rptr); case T_A: ar_reinfo.re_resends++; return do_query_name(NULL, rptr->re_name, rptr); default: break; } return -1;}/* * ar_procanswer * * process an answer received from a nameserver. */static int ar_procanswer(rptr, hptr, buf, eob)struct reslist *rptr;char *buf, *eob;HEADER *hptr;{ char *cp, **alias, *s; int class, type, dlen, len, ans = 0, n, i; u_int32_t ttl, dr, *adr; struct hent *hp; cp = buf + sizeof(HEADER); adr = (u_int32_t *)rptr->re_he.h_addr_list; while (*adr) adr++; alias = rptr->re_he.h_aliases; while (*alias) alias++; hp = &rptr->re_he; /* * Skip over the original question. */ while (hptr->qdcount-- > 0) cp += dn_skipname(cp, eob) + QFIXEDSZ; /* * proccess each answer sent to us. blech. */ while (hptr->ancount-- > 0 && cp < eob) { n = dn_expand(buf, eob, cp, ar_hostbuf, sizeof(ar_hostbuf)); cp += n; if (n <= 0) return ans; ans++; /* * 'skip' past the general dns crap (ttl, class, etc) to get * the pointer to the right spot. Some of thse are actually * useful so its not a good idea to skip past in one big jump. */ type = (int)_getshort(cp); cp += sizeof(short); class = (int)_getshort(cp); cp += sizeof(short); ttl = (u_int32_t)_getlong(cp); cp += sizeof(u_int32_t); dlen = (int)_getshort(cp); cp += sizeof(short); rptr->re_type = type; switch(type) { case T_A : rptr->re_he.h_length = dlen; if (ans == 1) rptr->re_he.h_addrtype=(class == C_IN) ? AF_INET : AF_UNSPEC; if (dlen != sizeof(dr)) { h_errno = TRY_AGAIN; continue; } bcopy(cp, &dr, dlen); *adr++ = dr; *adr = 0; cp += dlen; len = strlen(ar_hostbuf); if (!rptr->re_he.h_name) { rptr->re_he.h_name = (char *)malloc(len+1); if (!rptr->re_he.h_name) break; (void)strcpy(rptr->re_he.h_name, ar_hostbuf); } break; case T_PTR : if ((n = dn_expand(buf, eob, cp, ar_hostbuf, sizeof(ar_hostbuf) )) < 0) { cp += n; continue; } cp += n; len = strlen(ar_hostbuf)+1; /* * copy the returned hostname into the host name * or alias field if there is a known hostname * already. */ if (!rptr->re_he.h_name) { rptr->re_he.h_name = (char *)malloc(len); if (!rptr->re_he.h_name) break; (void)strcpy(rptr->re_he.h_name, ar_hostbuf); } else { *alias = (char *)malloc(len); if (!*alias) return -1; (void)strcpy(*alias++, ar_hostbuf); *alias = NULL; } break; case T_CNAME : cp += dlen; if (alias >= &(rptr->re_he.h_aliases[MAXALIASES-1])) continue; n = strlen(ar_hostbuf)+1; *alias = (char *)malloc(n); if (!*alias) return -1; (void)strcpy(*alias++, ar_hostbuf); *alias = NULL; break; default : break; } } return ans;}/* * ar_answer * * Get an answer from a DNS server and process it. If a query is found to * which no answer has been given to yet, copy its 'info' structure back * to where "reip" points and return a pointer to the hostent structure. */struct hostent *ar_answer(reip, size)char *reip;int size;{ static char ar_rcvbuf[sizeof(HEADER) + MAXPACKET]; static struct hostent ar_host; register HEADER *hptr; register struct reslist *rptr = NULL; register struct hostent *hp; register char **s; unsigned long *adr; int rc, i, n, a; rc = recv(ar_resfd, ar_rcvbuf, sizeof(ar_rcvbuf), 0); if (rc <= 0) goto getres_err; ar_reinfo.re_replies++; hptr = (HEADER *)ar_rcvbuf; /* * convert things to be in the right order. */ hptr->id = ntohs(hptr->id); hptr->ancount = ntohs(hptr->ancount); hptr->arcount = ntohs(hptr->arcount); hptr->nscount = ntohs(hptr->nscount); hptr->qdcount = ntohs(hptr->qdcount); /* * response for an id which we have already received an answer for * just ignore this response. */ rptr = ar_find_id(hptr->id); if (!rptr) goto getres_err; if ((hptr->rcode != NOERROR) || (hptr->ancount == 0)) { switch (hptr->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; } ar_reinfo.re_errors++; /* ** If a bad error was returned, we stop here and dont send ** send any more (no retries granted). */ if (h_errno != TRY_AGAIN) { rptr->re_resend = 0; rptr->re_retries = 0; } goto getres_err; } a = ar_procanswer(rptr, hptr, ar_rcvbuf, ar_rcvbuf+rc); if ((rptr->re_type == T_PTR) && (_res.options & RES_CHECKPTR)) { /* * For reverse lookups on IP#'s, lookup the name that is given * for the ip# and return with that as the official result. * -avalon */ rptr->re_type = T_A; /* * Clean out the list of addresses already set, even though * there should only be one :) */ adr = (unsigned long *)rptr->re_he.h_addr_list; while (*adr) *adr++ = 0L; /* * Lookup the name that we were given for the ip# */ ar_reinfo.re_na_look++; (void)strncpy(rptr->re_name, rptr->re_he.h_name, sizeof(rptr->re_name)-1); rptr->re_he.h_name = NULL; rptr->re_retries = _res.retry; rptr->re_sends = 1; rptr->re_resend = 1; rptr->re_he.h_name = NULL; ar_reinfo.re_na_look++; (void)ar_query_name(rptr->re_name, C_IN, T_A, rptr); return NULL; } if (reip && rptr->re_rinfo.ri_ptr && size) bcopy(rptr->re_rinfo.ri_ptr, reip, MIN(rptr->re_rinfo.ri_size, size)); /* * Clean up structure from previous usage. */ hp = &ar_host;#ifdef ARLIB_DEBUG ar_dump_hostent("ar_answer: previous usage", hp);#endif if (hp->h_name) (void)free(hp->h_name); if (s = hp->h_aliases) { while (*s) (void)free(*s++); (void)free(hp->h_aliases); } if (s = hp->h_addr_list) { /* * Only free once since we allocated space for * address in one big chunk. */ (void)free(*s); (void)free(hp->h_addr_list); } bzero((char *)hp, sizeof(*hp)); /* * Setup and copy details for the structure we return a pointer to. */ hp->h_addrtype = AF_INET; hp->h_length = sizeof(struct in_addr); if(rptr->re_he.h_name) { hp->h_name = (char *)malloc(strlen(rptr->re_he.h_name)+1); if(!hp->h_name) {#ifdef ARLIB_DEBUG fprintf(stderr, "no memory for hostname\n");#endif h_errno = TRY_AGAIN; goto getres_err; } (void)strcpy(hp->h_name, rptr->re_he.h_name); }#ifdef ARLIB_DEBUG ar_dump_hostent("ar_answer: (snap) store name", hp);#endif /* * Count IP#'s. */ for (i = 0, n = 0; i < MAXADDRS; i++, n++) if (!rptr->re_he.h_addr_list[i].s_addr) break; s = hp->h_addr_list = (char **)malloc((n + 1) * sizeof(char *)); if (n) { *s = (char *)malloc(n * sizeof(struct in_addr)); if(!*s) {#ifdef ARLIB_DEBUG fprintf(stderr, "no memory for IP#'s (%d)\n", n);#endif h_errno = TRY_AGAIN; goto getres_err; } bcopy((char *)&rptr->re_he.h_addr_list[0].s_addr, *s, sizeof(struct in_addr)); s++; for (i = 1; i < n; i++, s++) { *s = hp->h_addr + i * sizeof(struct in_addr); bcopy((char *)&rptr->re_he.h_addr_list[i].s_addr, *s, sizeof(struct in_addr)); } } *s = NULL;#ifdef ARLIB_DEBUG ar_dump_hostent("ar_answer: (snap) store IP#'s", hp);#endif /* * Count CNAMEs */ for (i = 0, n = 0; i < MAXADDRS; i++, n++) if (!rptr->re_he.h_aliases[i]) break; s = hp->h_aliases = (char **)malloc((n + 1) * sizeof(char *)); if (!s) {#ifdef ARLIB_DEBUG fprintf(stderr, "no memory for aliases (%d)\n", n);#endif h_errno = TRY_AGAIN; goto getres_err; } for (i = 0; i < n; i++) { *s++ = rptr->re_he.h_aliases[i]; rptr->re_he.h_aliases[i] = NULL; } *s = NULL;#ifdef ARLIB_DEBUG ar_dump_hostent("ar_answer: (snap) store CNAMEs", hp); ar_dump_hostent("ar_answer: new one", hp);#endif if (a > 0) (void)ar_remrequest(rptr); else if (!rptr->re_sent) (void)ar_remrequest(rptr); return hp;getres_err: if (rptr) { if (reip && rptr->re_rinfo.ri_ptr && size) bcopy(rptr->re_rinfo.ri_ptr, reip, MIN(rptr->re_rinfo.ri_size, size)); if ((h_errno != TRY_AGAIN) && (_res.options & (RES_DNSRCH|RES_DEFNAMES) == (RES_DNSRCH|RES_DEFNAMES) )) if (_res.dnsrch[rptr->re_srch]) { rptr->re_retries = _res.retry; rptr->re_sends = 1; rptr->re_resend = 1; (void)ar_resend_query(rptr); rptr->re_srch++; } return NULL; } return NULL;}#ifdef ARLIB_DEBUGvoid ar_dump_hostent(prefix, hp)char *prefix;struct hostent *hp;{ register char **s; fflush(stdout); fprintf(stderr, "%s\n", prefix); fprintf(stderr, " hp %p\n", hp); fprintf(stderr, " h_name %p '%s'\n", hp->h_name, hp->h_name); if (s = hp->h_aliases) { fprintf(stderr, " h_aliases %p\n", hp->h_aliases); while (*s) { fprintf(stderr, " element %p\n", *s); s++; } } if (s = hp->h_addr_list) { fprintf(stderr, " h_addr_list %p\n", hp->h_addr_list); while (*s) { fprintf(stderr, " element %p\n", *s); s++; } } fflush(stderr);}void ar_dump_reslist(FILE* fp){ register struct reslist *rptr; int c; c = 0; for (rptr = ar_first; rptr; rptr = rptr->re_next) { fprintf(fp, "%4d [%p] %4d [%p]: %s\n", rptr->re_id, rptr, *(rptr->re_rinfo.ri_ptr), rptr->re_rinfo.ri_ptr, rptr->re_name); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -