/*
* 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;
}