/nslook.c
C | 424 lines | 362 code | 41 blank | 21 comment | 71 complexity | dde1f98656014a6c02525586cde351a6 MD5 | raw file
- /*
- * nslook.c - simple, concise address and host name lookup. Actually
- * this is just a front end to getaddrinfo()/getnameinfo().
- */
- #define __USE_GNU
- #define __USE_POSIX /* and still no AI_IDN... */
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sysexits.h>
- #include <errno.h>
- #include "version.h" /* for VERSION */
- #define F_SHORT 0
- #define F_LONG 1
- #define F_MEDIUM 2
- #define F_AIDUMP 3 /* extensive struct addrinfo dump */
- #define MAXDOMAINNAMELEN 255 /* according to RFC 1034 */
- char *progname;
- int show_usage = 0; /* show usage if non-zero */
- int reverse = 0; /* do reverse mapping */
- int canonical_name = 0; /* look for canonical name */
- int format = F_SHORT; /* output format */
- char *input = NULL; /* file to take input from */
- int one_result = 0; /* show one result only (for scripts) */
- int resolve_v4 = 1; /* resolve to IPv4 addresses */
- int resolve_v6 = 1; /* resolve to IPv6 addresses */
- int had_errors = 0; /* non-zero if errors were seen */
- char *ip_dotted(unsigned long *addrp); /* Return dotted decimal notation. */
- void usage(void);
- void do_lookup (char *astring);
- int lookup_address(char *astring);
- void lookup_name(char *name);
- const char *get_ipaddr(struct sockaddr *sa, socklen_t salen);
- const char *get_hostname(struct addrinfo *ai);
- void dump_addrinfo(struct addrinfo *ai);
- const char *ptr_or(char *ptr, char *alt);
- void display_result(char *name, const char *ipaddr, struct addrinfo *ai);
- const char *str_ai_flags(int ai_flags);
- const char *str_ai_family(int ai_family);
- const char *str_ai_socktype(int ai_socktype);
- const char *str_ai_protocol(int ai_protocol);
- int main(int argc, char **argv)
- {
- int opt; /* option character */
- char *cp;
- FILE *in;
- char buffer[2048]; /* hope this won't break */
- progname = argv[0];
- if ((cp = strrchr(progname, '/'))) {
- progname = cp + 1;
- }
- while ((opt = getopt(argc, argv, "146clmrf:xV")) != -1) {
- switch (opt) {
- case '1':
- one_result = 1;
- break;
- case 'x':
- format = F_AIDUMP;
- break;
- case '4':
- resolve_v6 = 0;
- break;
- case '6':
- resolve_v4 = 0;
- break;
- case 'l': /* long */
- format = F_LONG;
- break;
- case 'm': /* medium output format */
- format = F_MEDIUM;
- break;
- case 'f': /* read arguments from file or stdin */
- input = optarg;
- break;
- case 'r': /* normal and reverse mapping */
- reverse = 1;
- break;
- case 'c': /* canonical name */
- canonical_name = 1;
- break;
- case 'V': /* print version */
- puts(VERSION);
- exit(0);
- break;
- case '?': /* give usage message */
- show_usage++;
- break;
- }
- }
- if (show_usage || optind > argc || (input == NULL && optind >= argc)) {
- usage();
- exit(EX_USAGE);
- }
- if (input) {
- if (strcmp(input, "-")) {
- if ((in = fopen(input, "r")) == NULL) {
- fprintf(stderr, "%s: cannot open %s: %s\n",
- progname, input, strerror(errno));
- }
- } else {
- in = stdin;
- }
- while (fscanf(in, "%s", buffer) != EOF) {
- do_lookup(buffer);
- }
- } else {
- while (optind < argc) {
- do_lookup(argv[optind++]);
- }
- }
- return had_errors ? EX_NOHOST : EX_OK;
- }
- void do_lookup (char *astring)
- {
- if (!lookup_address(astring)) {
- lookup_name(astring);
- }
- }
- /* Try to interpret the argument string as an IPv4 or IPv6 address, look it up,
- * and show the result. If the argument string does not contain the textual
- * representation of an IP address, return 0, otherwise 1.
- *
- */
- int lookup_address(char *astring)
- {
- int isv6addr = 0;
- struct sockaddr *sa_ptr; /* points to sa_v4 or sa_v6 */
- socklen_t salen; /* length of *sa_ptr */
- char hostname[MAXDOMAINNAMELEN+1]; /* host name buffer */
- int error; /* ... of getnameinfo() */
- /* 1st try: parse string into v4 address */
- struct in_addr v4addr;
- struct in6_addr v6addr;
-
- memset(&v4addr, 0, sizeof(v4addr));
- if (!inet_pton(AF_INET, astring, &v4addr)) {
- memset(&v6addr, 0, sizeof(v6addr));
- if (!inet_pton(AF_INET6, astring, &v6addr)) {
- /* not an IPv6 address either, so return failure */
- return 0;
- } else {
- isv6addr = 1;
- }
- }
- if (isv6addr) {
- struct sockaddr_in6 sa_v6;
- memset(&sa_v6, 0, sizeof(sa_v6));
- sa_v6.sin6_family = AF_INET6;
- memcpy(&sa_v6.sin6_addr, &v6addr, sizeof(v6addr));
- sa_ptr = (struct sockaddr *) &sa_v6;
- salen = sizeof(sa_v6);
- } else {
- struct sockaddr_in sa_v4;
- memset(&sa_v4, 0, sizeof(sa_v4));
- sa_v4.sin_family = AF_INET;
- memcpy(&sa_v4.sin_addr, &v4addr, sizeof(v4addr));
- sa_ptr = (struct sockaddr *) &sa_v4;
- salen = sizeof(sa_v4);
- }
- error = getnameinfo(sa_ptr, salen, hostname, sizeof(hostname),
- NULL, 0, 0);
- if (error) {
- fprintf(stderr, "%s: %s: %s\n",
- progname, astring, gai_strerror(error));
- had_errors++;
- return 0;
- }
-
- if (canonical_name) {
- puts(hostname);
- } else {
- const char *ipaddr = get_ipaddr(sa_ptr, salen);
- switch (format) {
- case F_LONG:
- printf("hostname: %s\n", hostname);
- printf("ip address: %s\n", ipaddr);
- break;
- case F_MEDIUM:
- printf("%-39s %s\n", ipaddr, hostname);
- break;
- case F_SHORT:
- puts(hostname);
- break;
- }
- }
- return 1;
- }
- /* Look up the argument hostname and display the result(s) as requested by the
- * user.
- */
- void lookup_name(char *name)
- {
- int error;
- struct addrinfo hints;
- struct addrinfo *ai_result;
- memset(&hints, 0, sizeof(hints));
- if (!resolve_v4) {
- hints.ai_family = AF_INET6;
- } else if (!resolve_v6) {
- hints.ai_family = AF_INET;
- } else {
- hints.ai_family = AF_UNSPEC;
- }
- if (canonical_name) {
- hints.ai_flags |= AI_CANONNAME;
- }
- /* try to find host entry */
- error = getaddrinfo(name, NULL, &hints, &ai_result);
- if (error) {
- fprintf(stderr, "%s: %s: %s\n",
- progname, name, gai_strerror(error));
- had_errors++;
- return;
- }
- if (canonical_name && format == F_SHORT) {
- puts(ai_result->ai_canonname);
- } else {
- const char *prev_ipaddr = "";
- if (format == F_LONG) {
- printf("query: %s\n", name);
- }
- while (ai_result) {
- const char *ipaddr = get_ipaddr(ai_result->ai_addr,
- ai_result->ai_addrlen);
- if (strcmp(ipaddr, prev_ipaddr) || format == F_AIDUMP) {
- display_result(name, ipaddr, ai_result);
- }
- if (one_result) {
- return;
- }
- prev_ipaddr = strdup(ipaddr);
- ai_result = ai_result->ai_next;
- }
- }
- }
- void display_result(char *name, const char *ipaddr, struct addrinfo *ai)
- {
- char *hostname = ai->ai_canonname;
- switch (format) {
- case F_LONG:
- if (hostname) {
- printf("hostname: %s\n",
- hostname);
- }
- printf("ip address: %s\n", ipaddr);
- if (reverse) {
- printf("reverse: %s\n",
- get_hostname(ai));
- }
- break;
- case F_MEDIUM:
- if (!hostname) {
- hostname = name;
- }
- printf("%-39s %s\n", ipaddr, hostname);
- break;
- case F_SHORT:
- printf("%s\n", ipaddr);
- break;
- case F_AIDUMP:
- dump_addrinfo(ai);
- }
- }
- void dump_addrinfo(struct addrinfo *ai)
- {
- printf("%-13s 0x%x %s\n", "ai_flags:",
- ai->ai_flags, str_ai_flags(ai->ai_flags));
- printf("%-13s %s\n", "ai_family:", str_ai_family(ai->ai_family));
- printf("%-13s %s\n", "ai_socktype:", str_ai_socktype(ai->ai_socktype));
- printf("%-13s %s\n", "ai_protocol:", str_ai_protocol(ai->ai_protocol));
- printf("%-13s %d\n", "ai_addrlen:", ai->ai_addrlen);
- printf("%-13s %s\n", "ai_addr:",
- get_ipaddr(ai->ai_addr, ai->ai_addrlen));
- printf("%-13s %s\n", "ai_canonname:", ptr_or(ai->ai_canonname, 0));
- printf("%-13s %p\n\n", "ai_next:", ptr_or((char *) ai->ai_next, 0));
- }
- const char *str_ai_flags(int ai_flags)
- {
- static char buf[300];
- buf[0] = 0;
-
- if (ai_flags & AI_V4MAPPED) strcat(buf, " AI_V4MAPPED");
- if (ai_flags & AI_ADDRCONFIG) strcat(buf, " AI_ADDRCONFIG");
- if (ai_flags & AI_NUMERICHOST) strcat(buf, " AI_NUMERICHOST");
- if (ai_flags & AI_PASSIVE) strcat(buf, " AI_PASSIVE");
- if (ai_flags & AI_NUMERICSERV) strcat(buf, " AI_NUMERICSERV");
- if (ai_flags & AI_CANONNAME) strcat(buf, " AI_CANONNAME");
- if (ai_flags & AI_ALL) strcat(buf, " AI_ALL");
- #ifdef AI_IDN
- if (ai_flags & AI_IDN) strcat(buf, " AI_IDN");
- if (ai_flags & AI_CANONIDN) strcat(buf, " AI_CANONIDN");
- if (ai_flags & AI_IDN_ALLOW_UNASSIGNED) {
- strcat(buf, " AI_IDN_ALLOW_UNASSIGNED");
- }
- if (ai_flags & AI_IDN_USE_STD3_ASCII_RULES) {
- strcat(buf, " AI_IDN_USE_STD3_ASCII_RULES");
- }
- #endif /* AI_IDN */
- return buf;
- }
- const char *str_ai_family(int ai_family)
- {
- static char buf[100];
- switch (ai_family) {
- case AF_INET: return "AF_INET";
- case AF_INET6: return "AF_INET6";
- case AF_UNSPEC: return "AF_UNSPEC";
- default:
- snprintf(buf, 100, "unknown (%d)", ai_family);
- return buf;
- }
- }
- const char *str_ai_socktype(int ai_socktype)
- {
- static char buf[100];
- switch (ai_socktype) {
- case SOCK_STREAM: return "SOCK_STREAM";
- case SOCK_DGRAM: return "SOCK_DGRAM";
- case SOCK_RAW: return "SOCK_RAW";
- case 0: return "0";
- default:
- snprintf(buf, 100, "unknown (%d)", ai_socktype);
- return buf;
- }
- }
- const char *str_ai_protocol(int ai_protocol)
- {
- static char buf[100];
- struct protoent *pe = getprotobynumber(ai_protocol);
- if (pe) {
- return pe->p_name;
- } else {
- snprintf(buf, 100, "unknown (%d)", ai_protocol);
- return buf;
- }
- }
- const char *ptr_or(char *ptr, char *alt)
- {
- if (ptr) {
- return ptr;
- } else if (alt) {
- return alt;
- } else {
- return "<null>";
- }
- }
- void usage(void)
- {
- fprintf(stderr, "\
- Usage: %s [-146clmrx] hostname ...\n\
- %s [-146clmrx] IP-address ...\n\
- %s [-146clmrx] -f file\n",
- progname, progname, progname);
- }
- /* return IP address string of a sockaddr.
- */
- const char *get_ipaddr(struct sockaddr *sa, socklen_t salen)
- {
- static char buffer[256];
- if (getnameinfo(sa, salen, buffer, sizeof(buffer), NULL, 0,
- NI_NUMERICHOST) == 0)
- {
- return buffer;
- }
- return "unknown";
- }
- /* return host name of a sockaddr, NULL if no hostname associated with the
- * address or if reverse lookup is disabled
- */
- const char *get_hostname(struct addrinfo *ai)
- {
- static char name[MAXDOMAINNAMELEN+1];
- if (!getnameinfo(ai->ai_addr, ai->ai_addrlen, name, sizeof(name),
- NULL, 0, NI_NAMEREQD))
- {
- return name;
- }
- return "(none)";
- }
- /* EOF */