📄 host.c
字号:
/* return overall result */ return(excode);}/*** PROCESS_NAME -- Process a single command line argument** ------------------------------------------------------**** Returns:** EX_OK if information was obtained successfully.** Appropriate exit code otherwise.**** Wrapper for execute_name() to hide administrative tasks.*/intprocess_name(name)input char *name; /* command line argument */{ int result; /* result status of action taken */ static int save_querytype; static bool save_reverse; static bool firstname = TRUE; /* separate subsequent pieces of output */ if (!firstname && (verbose || debug || checkmode)) printf("\n");/* * Some global variables are redefined further on. Save their initial * values in the first pass, and restore them during subsequent passes. */ if (firstname) { save_querytype = querytype; save_reverse = reverse; firstname = FALSE; } else { querytype = save_querytype; reverse = save_reverse; }/* * Do the real work. */ result = execute_name(name); return(result);}/*** EXECUTE_NAME -- Process a single command line argument** ------------------------------------------------------**** Returns:** EX_OK if information was obtained successfully.** Appropriate exit code otherwise.**** Outputs:** Defines queryname appropriately.**** Side effects:** May redefine querytype and reverse if necessary.*/intexecute_name(name)input char *name; /* command line argument */{ ipaddr_t addr; /* explicit address of query */ bool result; /* result status of action taken */ /* check for nonsense input name */ if (strlength(name) > MAXDNAME) { errmsg("Query name %s too long", name); return(EX_USAGE); }/* * Analyze name and type to be queried about. * In regular mode, the querytype is used to formulate the nameserver * query, and any response is filtered out when processing the answer. * In listmode, the querytype is used to filter out the proper records. */ queryname = name; if (queryname[0] == '\0') queryname = "."; if (sameword(queryname, ".")) addr = NOT_DOTTED_QUAD; else addr = inet_addr(queryname); /* invert dotted quad if so requested */ if ((addr != NOT_DOTTED_QUAD) && reverse) { queryname = in_addr_arpa(queryname); if (queryname == NULL) { errmsg("Invalid dotted quad %s", name); return(EX_USAGE); } addr = NOT_DOTTED_QUAD; } else reverse = FALSE; /* set querytype for regular mode if unspecified */ if ((querytype == T_NONE) && !listmode) { if ((addr != NOT_DOTTED_QUAD) || reverse) querytype = T_PTR; else querytype = T_A; } /* cannot have dotted quad in listmode */ if (listmode && (addr != NOT_DOTTED_QUAD)) { errmsg("Invalid query name %s", queryname); return(EX_USAGE); } /* must have regular name or dotted quad in addrmode */ if (addrmode && reverse) { errmsg("Invalid query name %s", queryname); return(EX_USAGE); } /* show what we are going to query about */ if (verbose) show_types(queryname, querytype, queryclass);/* * All set. Perform requested function. */ result = execute(addr); return(result ? EX_OK : EX_UNAVAILABLE);}/*** EXECUTE -- Perform the requested function** -----------------------------------------**** Returns:** TRUE if information was obtained successfully.** FALSE otherwise.**** The whole environment has been set up and checked.*/boolexecute(addr)input ipaddr_t addr; /* explicit address of query */{ struct hostent *hp; char newnamebuf[MAXDNAME+1]; char *newname = NULL; /* name to which CNAME is aliased */ int ncnames = 0; /* count of CNAMEs in chain */ bool result; /* result status of action taken *//* * Special mode to check reverse mappings of host addresses. */ if (addrmode) { if (addr == NOT_DOTTED_QUAD) result = check_addr(queryname); else result = check_name(addr); return(result); }/* * Special mode to list contents of specified zone. */ if (listmode) { result = list_zone(queryname); return(result); }/* * Regular mode to query about specified host. */ result = FALSE; h_errno = TRY_AGAIN; /* retry until positive result or permanent failure */ while (result == FALSE && h_errno == TRY_AGAIN) { /* reset before each query */ realname = NULL; if (addr == NOT_DOTTED_QUAD) { /* reset CNAME indicator */ cname = NULL; /* lookup the name in question */ if (newname == NULL) result = get_hostinfo(queryname); else result = get_hostinfo(newname); /* recurse on CNAMEs, but not too deep */ if (cname && (querytype != T_CNAME)) { newname = strcpy(newnamebuf, cname); if (++ncnames > 5) { errmsg("Possible CNAME loop"); return(FALSE); } result = FALSE; h_errno = TRY_AGAIN; continue; } } else { hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); if (hp != NULL) { print_host("Name", hp); result = TRUE; } } /* only retry if so requested */ if (!waitmode) break; } /* use actual name if available */ if (realname != NULL) queryname = realname; /* explain the reason of a failure */ if (result == FALSE) ns_error(queryname, querytype, queryclass); return(result);}/*** SET_SERVER -- Override default nameserver with explicit server** --------------------------------------------------------------**** Returns:** None.** Aborts the program if an unknown host was given.**** Side effects:** The global variable server is set to indicate** that an explicit server is being used.**** The default nameserver addresses in the resolver database** which are initialized by res_init() from /etc/resolv.conf** are replaced with the (possibly multiple) addresses of an** explicitly named server host. If a dotted quad is given,** only that single address will be used.*/voidset_server(name)input char *name; /* name of server to be queried */{ register int i; struct hostent *hp; struct in_addr inaddr; ipaddr_t addr; /* explicit address of server */ /* check for nonsense input name */ if (strlength(name) > MAXDNAME) { errmsg("Server name %s too long", name); exit(EX_USAGE); } addr = inet_addr(name); inaddr.s_addr = addr; if (addr == NOT_DOTTED_QUAD) { /* lookup all of its addresses; this must not fail */ hp = gethostbyname(name); if (hp == NULL) { ns_error(name, T_A, C_IN); errmsg("Error in looking up server name"); exit(EX_NOHOST); } for (i = 0; i < MAXNS && hp->h_addr_list[i]; i++) { nslist(i).sin_family = AF_INET; nslist(i).sin_port = htons(NAMESERVER_PORT); nslist(i).sin_addr = incopy(hp->h_addr_list[i]); } _res.nscount = i; } else { /* lookup the name, but use only the given address */ hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); nslist(0).sin_family = AF_INET; nslist(0).sin_port = htons(NAMESERVER_PORT); nslist(0).sin_addr = inaddr; _res.nscount = 1; } if (hp != NULL) { server = strcpy(serverbuf, hp->h_name); print_host("Server", hp); } else { server = strcpy(serverbuf, inet_ntoa(inaddr)); printf("Server: %s\n\n", server); }}/*** FATAL -- Abort program when illegal option encountered** ------------------------------------------------------**** Returns:** Aborts after issuing error message.*/void /*VARARGS1*/fatal(fmt, a, b, c, d)input char *fmt; /* format of message */input char *a, *b, *c, *d; /* optional arguments */{ (void) fprintf(stderr, fmt, a, b, c, d); (void) fprintf(stderr, "\n"); exit(EX_USAGE);}/*** ERRMSG -- Issue error message to error output** ---------------------------------------------**** Returns:** None.**** Side effects:** Increments the global error count.*/void /*VARARGS1*/errmsg(fmt, a, b, c, d)input char *fmt; /* format of message */input char *a, *b, *c, *d; /* optional arguments */{ (void) fprintf(stderr, fmt, a, b, c, d); (void) fprintf(stderr, "\n"); /* flag an error */ Errors++;}/*** GET_HOSTINFO -- Principal routine to query about given name** -----------------------------------------------------------**** Returns:** TRUE if requested info was obtained successfully.** FALSE otherwise.**** This is the equivalent of the resolver module res_search().**** In this program RES_DEFNAMES is always on, and RES_DNSRCH** is off by default. This means that single names without dot** are always, and only, tried within the own default domain,** and compound names are assumed to be already fully qualified.**** The default BIND behaviour can be simulated by turning on** RES_DNSRCH with -R. The given name, whether or not compound,** is then first tried within the possible search domains.**** Note. In the latter case, the search terminates in case the** specified name exists but does not have the desired type.** The BIND behaviour is to continue the search. This can be** simulated with the undocumented option -B.*/boolget_hostinfo(name)input char *name; /* name to query about */{ register char **domain; register char *cp; int dot; /* number of dots in query name */ bool result; /* result status of action taken */ char oldnamebuf[2*MAXDNAME+2]; char *oldname; /* saved actual name when NO_DATA */ int nodata = 0; /* NO_DATA status during DNSRCH */ int nquery = 0; /* number of extra search queries *//* * Single dot means root zone. */ if (sameword(name, ".")) { result = get_domaininfo(name, (char *)NULL); return(result); }/* * Count number of dots. Move to the end of the name. */ for (dot = 0, cp = name; *cp != '\0'; cp++) if (*cp == '.') dot++;/* * Check for aliases of single name. * Note that the alias is supposed to be fully qualified. */ if (dot == 0 && (cp = hostalias(name)) != NULL) { if (verbose) printf("Aliased to \"%s\"\n", cp); result = get_domaininfo(cp, (char *)NULL); return(result); }/* * Trailing dot means absolute (fully qualified) address. */ if (dot != 0 && cp[-1] == '.') { cp[-1] = '\0'; result = get_domaininfo(name, (char *)NULL); cp[-1] = '.'; return(result); }/* * Append own default domain and other search domains if appropriate. */ if ((dot == 0 && bitset(RES_DEFNAMES, _res.options)) || (dot != 0 && bitset(RES_DNSRCH, _res.options))) { for (domain = _res.dnsrch; *domain; domain++) { result = get_domaininfo(name, *domain); if (result) return(result); /* keep count of extra search queries */ nquery++; /* in case nameserver not present */ if (errno == ECONNREFUSED) return(FALSE); /* if no further search desired (single name) */ if (!bitset(RES_DNSRCH, _res.options)) break; /* if name exists but has not requested type */ if (h_errno == NO_DATA || h_errno == NO_RREC) { if (bindcompat) { /* remember status and search up */ oldname = strcpy(oldnamebuf, realname); nodata = h_errno; continue; } return(FALSE); } /* retry only if name does not exist at all */ if (h_errno != HOST_NOT_FOUND && h_errno != NO_HOST) break; } }/* * Single name lookup failed. */ if (dot == 0) { /* unclear what actual name should be */ if (nquery != 1) realname = NULL; /* restore nodata status from search */ if (bindcompat && nodata) { realname = strcpy(realnamebuf, oldname); h_errno = nodata; } /* set status in case we never queried */ if (!bitset(RES_DEFNAMES, _res.options)) h_errno = HOST_NOT_FOUND; return(FALSE); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -