/* * NAME: dnsbot.c * DESCRIPTION: perform DNS lookups */ # include <stdio.h> # include <string.h> # include <sys/types.h> # include <sys/socket.h> # include <netinet/in.h> # include <arpa/inet.h> # include <netdb.h> # include <memory.h> # include <errno.h> # include <ctype.h> /* * NAME: fatal() * DESCRIPTION: an unrecoverable error has occured */ static fatal(msg, arg) char *msg, *arg; { if (*msg == '*') { fprintf(stderr, msg + 1, arg); perror((char *) 0); } else { fprintf(stderr, msg, arg); fprintf(stderr, "\n"); } exit(1); } /* * NAME: resolv->name2addr() * DESCRIPTION: translate hostname to IP address */ static int resolv_name2addr(hostname, ipaddr) char *hostname; struct in_addr *ipaddr; { struct hostent *host; host = gethostbyname(hostname); if (! host) return 0; memcpy(&ipaddr->s_addr, host->h_addr, host->h_length); return 1; } /* * NAME: resolv->addr2name() * DESCRIPTION: translate IP address to hostname */ static int resolv_addr2name(ipaddr, hostname) struct in_addr ipaddr; char **hostname; { struct hostent *host; host = gethostbyaddr((char *) &ipaddr, sizeof(ipaddr), AF_INET); if (! host) return 0; *hostname = host->h_name; return 1; } /* * NAME: resolv->ip2str() * DESCRIPTION: convert IP address to dotted quad */ static char *resolv_ip2str(ipaddr) struct in_addr ipaddr; { return inet_ntoa(ipaddr); } /* * NAME: resolv->str2ip() * DESCRIPTION: convert dotted quad to IP address */ static struct in_addr resolv_str2ip(str) char *str; { struct in_addr ipaddr; ipaddr.s_addr = inet_addr(str); return ipaddr; } /* * NAME: resolv->addr() * DESCRIPTION: return the IP address of a hostname or dotted quad string */ static int resolv_addr(host, ipaddr) char *host; struct in_addr *ipaddr; { int x; if (sscanf(host, "%d.%d.%d.%d", &x, &x, &x, &x) == 4) { *ipaddr = resolv_str2ip(host); return 1; } else return resolv_name2addr(host, ipaddr); } /* * NAME: dgd->open() * DESCRIPTION: open a connection to DGD */ static int dgd_open(host, port) char *host; unsigned short port; { int fd; struct sockaddr_in addr; if (! resolv_addr(host, &addr.sin_addr)) fatal("Cannot resolve host address: %s", host); addr.sin_family = AF_INET; addr.sin_port = htons(port); while (1) { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) fatal("*Cannot open socket: "); if (connect(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr)) >= 0) break; if (errno != ECONNREFUSED) fatal("*Cannot connect to %s: ", host); close(fd); sleep(10); } return fd; } /* * NAME: bot->handle() * DESCRIPTION: do the work specified by the command and argument */ static char *bot_handle(command, arg) char *command; char *arg; { static char answer[256]; struct in_addr ipaddr; char *str; if (strcasecmp(command, "ADDR?") == 0) { if (resolv_name2addr(arg, &ipaddr)) { if (! resolv_addr2name(ipaddr, &str)) str = arg; sprintf(answer, "HOST %s = %s = %s", arg, str, resolv_ip2str(ipaddr)); } else sprintf(answer, "NOADDR %s", arg); return answer; } else if (strcasecmp(command, "NAME?") == 0) { ipaddr = resolv_str2ip(arg); if (resolv_addr2name(ipaddr, &str)) sprintf(answer, "HOST %s = %s = %s", str, str, arg); else sprintf(answer, "NONAME %s", arg); return answer; } return 0; } /* * NAME: main() * DESCRIPTION: control entry */ int main(argc, argv) int argc; char *argv[]; { int debug, fd, n; FILE *input, *output; char line[128], *str; struct in_addr ipaddr; if (argc > 1 && strcmp(argv[1], "-d") == 0) { debug = 1; --argc, ++argv; } else debug = 0; if (argc != 3) fatal("Usage: %s [-d] host port", argv[0]); fd = dgd_open(argv[1], atoi(argv[2])); if (debug) { printf("Connected to %s\n", argv[1]); fflush(stdout); } while (n = fread(line, 1, sizeof(line), stdin)) write(fd, line, n); fclose(stdin); input = fdopen(fd, "r"); output = fdopen(fd, "w"); while (fgets(line, sizeof(line), input)) { char *command, *arg, *answer; if (debug) { printf("%s", line); fflush(stdout); } command = strtok(line, " \t\r\n"); if (! command) continue; arg = strtok((char *) 0, " \t\r\n"); if (! arg) continue; answer = bot_handle(command, arg); if (answer) { fprintf(output, "%s\r\n", answer); fflush(output); if (debug) { printf(">> %s\n", answer); fflush(stdout); } } } close(fd); return 0; }