/************************************************** * DNS Server 1.0 (C) 1997, Giancarlo Castrataro * **************************************************/ #include "dns-serv.h" #include "../../include/MACHINE.H" #include <errno.h> #include <sys/time.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <ctype.h> #include <signal.h> #ifdef _OLD_LINUX_ extern char *sys_errlist[]; #else #include <errno.h> #endif static FILE *logfp; int daemonize(void); char host_ip[100]; int main() { int main_sock, i, fd, numavail; fd_set input_set, output_set; struct hostent *h; int fdused; FILE *fp; for (i = 0 ; i < MAX_CONNECT ; i++) init_conn(i); if (daemonize() == -1) { printf("Could not daemonize the Server.\n"); return; } if ((main_sock = makesock()) == -1) return; width = main_sock + 1; while (1) { FD_ZERO(&input_set); FD_ZERO(&output_set); FD_SET(main_sock, &input_set); for (i = 0 ; i < width ; i++) { if (fdesc(i) != -1) { FD_SET(fdesc(i), &input_set); if (output(i)) FD_SET(fdesc(i), &output_set); } } numavail = select(width, &input_set, &output_set, NULL, NULL); for (fd = 0 ; numavail > 0 ; fd++) { fdused = 0; if (FD_ISSET(fd, &input_set)) { if (fd == main_sock) new_conn(main_sock); else read_packet(fd); numavail--; } if (FD_ISSET(fd, &output_set)) { write_packet(fd); numavail--; } } } } void init_conn(int i) { output(i) = False; fdesc(i) = -1; *readbuff(i) = *writebuff(i) = 0; readpos(i) = readbuff(i); writepos(i) = writebuff(i); } int makesock(void) { int sock; char opt = 1; struct sockaddr_in sin; struct hostent *h; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("Unable to create socket.\n"); return(-1); } setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (!(h = gethostbyname(_HOSTNAME_))) { fprintf(stderr, "Unable to bind to your hostname. Run configure.\n"); return -2; } sin.sin_family = AF_INET; sin.sin_port = htons (SERVER_PORT); bcopy (h->h_addr_list[0], &(sin.sin_addr), h->h_length); if (bind(sock, (struct sockaddr *) &sin, sizeof (sin)) == -1) { printf("\nerror in bind: %s.\n", sys_errlist[errno]); return(-1); } listen(sock, 5); return(sock); } void write_packet(int fd) { int num_wrote; conn = find_index(fd); num_wrote = write(fd, writepos(conn), strlen(writepos(conn)) + 1); writepos(conn) += num_wrote; if (*(writepos(conn) - 1) == 0) { *writebuff(conn) = 0; writepos(conn) = writebuff(conn); output(conn) = False; } } int escapechars(int conn) { char buff[READLEN * 2]; char *p, *b; for (p = connects[conn].readbuff, b = buff ; *p ; p++, b++) { if (*p != '%') *b = *p; else { *b++ = '%'; *b = '%'; } } *b = 0; if (strlen(buff) > READLEN) return(-1); else { strcpy(connects[conn].readbuff, buff); return(0); } } int ht_pos(char *s) { char *ptr; int sum = 0; for (ptr = s ; *ptr ; ptr++) sum += *ptr; return(sum % HT_SIZE); } void ht_add(char *ip_addr, char *hostname) { ht_elem *elem; ht_elem *nelem; int i; i = ht_pos(ip_addr); nelem = malloc(sizeof(ht_elem)); nelem->next = NULL; nelem->ip_addr = COPY(ip_addr); nelem->hostname = COPY(hostname); if (!htable[i]) htable[i] = nelem; else { elem = htable[i]; while ((elem = elem->next)); elem = nelem; } } char *match(char *token, ht_elem *start) { ht_elem *elem; elem = start; while (elem) { if (!strcmp(elem->ip_addr, token)) return(elem->hostname); else elem = elem->next; } return(NULL); } char *ht_lookup(char *token) { int i; i = ht_pos(token); return(match(token, htable[i])); } void read_packet(int fd) { int num_read, plrnum; unsigned long int inetnum; struct hostent *h; char ip_addr[16] = "\0"; char *rslt; conn = find_index(fd); num_read = read(fd, readpos(conn), (100 - (readpos(conn) - readbuff(conn)))); readpos(conn) += num_read; if (num_read < 1) { end_conn(fd); return; } if (*(readpos(conn) - 1) == 0) { readpos(conn) = readbuff(conn); if (escapechars(conn) == -1) return; plrnum = -1; sscanf(readbuff(conn), "%d%s", &plrnum, ip_addr); if (!*ip_addr || plrnum == -1) return; else { if (!(rslt = ht_lookup(ip_addr))) { inetnum = inet_addr(ip_addr); h = gethostbyaddr((char *) &inetnum, sizeof(inetnum), AF_INET); if (h) { rslt = (char *) h->h_name; ht_add(ip_addr, rslt); } else rslt = ip_addr; } sprintf(writebuff(conn), "%-3d%-96s", plrnum, rslt); output(conn) = True; } } } int find_index(int fd) { int i; for (i = 0 ; i < MAX_CONNECT ; i++) if (fdesc(i) == fd) return(i); return(-1); } int find_new_index(int fd) { int i; for (i = 0 ; i < MAX_CONNECT ; i++) if (fdesc(i) == -1) { fdesc(i) = fd; return(i); } return(-1); } void new_conn(int mainfd) { int i, fd, sin_len; struct sockaddr_in sin; struct hostent *h; bzero ((char *) &sin, sizeof (struct sockaddr_in)); sin_len = sizeof (struct sockaddr_in); if ((fd = accept (mainfd, (struct sockaddr *) &sin, &sin_len)) < 0) { perror("accept()"); return; } if (fcntl (fd, F_SETFL, FNDELAY) == -1) { perror("fcntl()"); return; } if ((i = find_new_index(fd)) == -1) return; h = gethostbyaddr((char *)&sin.sin_addr, sizeof(sin.sin_addr), AF_INET); if (!h) end_conn(fd); else if (strcmp(h->h_name, _HOSTNAME_) && strcmp(h->h_name, _IPNAME_)) end_conn(fd); else if (fd >= width) width = fd + 1; } void end_conn(int fd) { char buff[200]; int mud; if (fd >= width) width = fd; close(fd); mud = find_index(fd); init_conn(mud); } /************************************************************************** ** Signal Handler routines. **************************************************************************/ void remove_connections(void) { int i; for (i = 0; i < width; i++) { if (fdesc(i) != -1) close(fdesc(i)); } } void ee_handler(int sig) { remove_connections(); exit(0); } void abort_handler(int sig) { char message[255]; int i; remove_connections(); exit(0); } void set_sighandlers(void) { signal(SIGALRM,SIG_IGN); signal(SIGSEGV,ee_handler); signal(SIGBUS,ee_handler); signal(SIGABRT,abort_handler); signal(SIGQUIT,abort_handler); signal(SIGINT,abort_handler); } int daemonize(void) { int pid; set_sighandlers(); switch((pid = fork())) { case 0 : break; case -1: perror("Deamonize()"); return -1; default: fflush(stdout); fflush(stderr); exit(0); /* Die silently */ } return 0; }