#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; }