#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
void usage(void) {
printf("%s", "colloquy.resolver [-h | -i address -p port]\n");
}
int doBind(char* address, int port) {
struct hostent* host;
struct sockaddr_in bindaddr;
int sock, one = 1;
if ((host = gethostbyname(address)) == NULL) {
fprintf(stderr, "%s", "+++ Unable to resolve bind host.\n");
exit(1);
}
sock = socket(PF_INET, SOCK_STREAM, 0);
bindaddr.sin_family = AF_INET;
bindaddr.sin_addr.s_addr = *((unsigned long*)(host->h_addr));
bindaddr.sin_port = htons(port);
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if (bind(sock, (struct sockaddr*)&bindaddr, sizeof(bindaddr)) == -1) {
close(sock);
fprintf(stderr, "Unable to bind (%s)\n", strerror(errno));
exit(1);
}
listen(sock, 1);
return sock;
}
void loop(char* address, int port) {
int stillOK = 1;
int serv = doBind(address, port);
int sock = accept(serv, NULL, 0);
char recvBuff[1024]; /* recv bytes into here */
int recvLen = 0; /* how many bytes in recvBuff are used */
int recvBytes;
char replyBuff[4096];
int replyBytes;
struct hostent* hp;
struct in_addr addr;
if (sock < 0)
return;
do {
/* first of all, try to receive a whole line of text...
*/
recvBytes = recv(sock, recvBuff + recvLen, 1, 0);
if (recvBytes == -1) {
if (errno == EINTR)
continue;
fprintf(stderr, "+++ '%s' while reading from socket\n", strerror(errno));
exit(1);
}
if (recvBytes == 0) {
fprintf(stderr, "+++ %s\n", "Didn't receive anything!");
exit(1);
}
if (recvBytes == 1 && recvBuff[recvLen] == '\n') {
/* we've got a whole line! yay!
*/
recvBuff[recvLen] = '\0';
if (inet_aton(recvBuff, &addr))
hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
else
hp = gethostbyname(recvBuff);
if (hp == NULL) {
/* erm - there was an error.
*/
if (snprintf(replyBuff, 4096, "%s %s\n", recvBuff, recvBuff) == -1)
strcpy(replyBuff, "");
} else {
/* yay! send the reply.
*/
if (snprintf(replyBuff, 4096, "%s %s\n", recvBuff, hp->h_name) == -1)
strcpy(replyBuff, "");
}
replyBytes = send(sock, replyBuff, strlen(replyBuff), 0);
if (replyBytes == -1) {
fprintf(stderr, "+++ %s\n", "Couldn't send data back to talker!");
exit(1);
}
recvLen = 0;
} else
if (recvLen == 1024)
recvLen = 0; /* it's too long - just throw it away. */
else
recvLen++;
} while (stillOK);
}
int main(int argc, char** argv) {
static char opts[] = "i:p:h";
/* i: IP address to bind to
* p: Port to bind to
* h show help
*/
int o;
char* address = NULL;
int port = 0;
while ((o = getopt(argc, argv, opts)) != -1) {
switch (o) {
case 'i':
address = strdup(optarg);
break;
case 'p':
port = atoi(optarg);
break;
case 'h':
usage();
exit(0);
}
}
if (address == NULL || port == 0) {
usage();
exit(1);
}
loop(address, port);
free(address);
return 0;
}