#if defined(HAVE_CONFIG_H) #include "../hdrfiles/config.h" #endif #include "../hdrfiles/includes.h" /* #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/time.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <signal.h> #if defined(SOL_SYS) || defined(LINUX_SYS) || defined(WINDOWS) #include <string.h> #else #include <strings.h> #endif */ #include "../hdrfiles/osdefs.h" #include "../hdrfiles/constants.h" #include "../hdrfiles/protos.h" #include "../hdrfiles/resolver_clipon.h" extern char mess[ARR_SIZE+25]; extern fd_set readmask; /* bitmap read set */ extern fd_set writemask; /* bitmap write set */ int resolver_toclient_pipes[2]; int resolver_toserver_pipes[2]; int resolver_clipon_pid=-1; int init_resolver_clipon(void) { int ret,i=0; fd_set fds; struct timeval timeout; char namebuffer[256]; char resolver_binary[256]; char readbuf[256]; sprintf(namebuffer,"Resolver clip-on for %s",SYSTEM_NAME); if (pipe(resolver_toclient_pipes) == -1) { write_log(SYSTEMLOG,YESTIME,"Couldn't create resolver clip-on client pipes %s\n",get_error()); write_log(RESOLVELOG,YESTIME,"TALKER: Couldn't create resolver clip-on client pipes %s\n",get_error()); cleanup_resolver(); return 0; } if (pipe(resolver_toserver_pipes) == -1) { write_log(SYSTEMLOG,YESTIME,"Couldn't create resolver clip-on server pipes %s\n",get_error()); write_log(RESOLVELOG,YESTIME,"TALKER: Couldn't create resolver clip-on server pipes %s\n",get_error()); cleanup_resolver(); return 0; } ret = fork(); switch(ret) { case -1: /* error */ write_log(SYSTEMLOG,YESTIME,"Bad resolver clip-on fork: %s\n",get_error()); write_log(RESOLVELOG,YESTIME,"TALKER: Bad resolver clip-on fork: %s\n",get_error()); cleanup_resolver(); return 0; case 0: /* child */ CLOSE(FROM_CLIENT_READ); /* close read to client */ CLOSE(FROM_CLIENT_WRITE); /* close write to server */ CLOSE(0); dup(FROM_SERVER_READ); /* dupe read to server */ CLOSE(FROM_SERVER_READ); CLOSE(1); dup(FROM_SERVER_WRITE); /* dupe write to server */ CLOSE(FROM_SERVER_WRITE); /* Close all user sockets in this child before */ /* we do anything. otherwise, if we get killed */ /* and restart while users are online, users */ /* that logoff will have their connection hang */ /* right at the very end because they will have */ /* multiple sockets open. */ for (i=0;i<MAX_USERS;++i) { if (ustr[i].sock != -1) { queue_flush(i); SHUTDOWN(ustr[i].sock, 2); while (CLOSE(ustr[i].sock) == -1 && errno == EINTR) ; /* empty while */ FD_CLR(ustr[i].sock,&readmask); FD_CLR(ustr[i].sock,&writemask); } } /* this method MAY change */ snprintf(resolver_binary,256,"./%s",RESOLVER_BINARY); execlp(resolver_binary, namebuffer, 0); write_log(SYSTEMLOG,YESTIME,"Failed to exec resolver clip-on binary %s %s\n",resolver_binary,get_error()); write_log(RESOLVELOG,YESTIME,"TALKER: Failed to exec resolver clip-on binary %s %s\n",resolver_binary,get_error()); cleanup_resolver(); return 0; default: /* parent */ resolver_clipon_pid = ret; CLOSE(FROM_SERVER_READ); CLOSE(FROM_SERVER_WRITE); FROM_SERVER_READ = FROM_SERVER_WRITE = -1; if (MY_FCNTL(FROM_CLIENT_READ, MY_F_SETFL, NBLOCK_CMD)==SOCKET_ERROR) { write_log(RESOLVELOG,YESTIME,"TALKER: Can't set resolver read socket non-blocking: %s\n",get_error()); cleanup_resolver(); return 0; } if (MY_FCNTL(FROM_CLIENT_WRITE, MY_F_SETFL, NBLOCK_CMD)==SOCKET_ERROR) { write_log(RESOLVELOG,YESTIME,"TALKER: Can't set resolver write socket non-blocking: %s\n",get_error()); cleanup_resolver(); return 0; } } /* end of switch */ FD_ZERO(&fds); FD_SET(FROM_CLIENT_READ, &fds); timeout.tv_sec = 15; timeout.tv_usec = 0; while (-1 == (ret = select(FD_SETSIZE, &fds, 0, 0, &timeout))) { if (errno == EINTR || errno == EAGAIN) { continue; } write_log(RESOLVELOG,YESTIME,"TALKER: select() timed out waiting for server: %s\n",get_error()); kill_resolver_clipon(); return 0; } if (FD_ISSET(FROM_CLIENT_READ, &fds)) { ret = read(FROM_CLIENT_READ, readbuf, sizeof(readbuf)); readbuf[ret] = '\0'; write_log(RESOLVELOG,YESTIME,"TALKER: Read from clip-on: \"%s\"\n",readbuf); if (strcmp(readbuf, RESOLVER_SERVER_CONNECT_MSG)) { ret = read(FROM_CLIENT_READ, readbuf, sizeof(readbuf)); readbuf[ret] = '\0'; write_log(RESOLVELOG,YESTIME,"TALKER: Read2 from clip-on: \"%s\"\n",readbuf); write_log(SYSTEMLOG,YESTIME,"Bad resolver clip-on connect message!\n"); write_log(RESOLVELOG,YESTIME,"TALKER: Bad resolver clip-on connect message!\n"); kill_resolver_clipon(); return 0; } write_log(SYSTEMLOG,YESTIME,"Resolver clipon running\n"); write_log(RESOLVELOG,YESTIME,"TALKER: Resolver clipon running\n"); FD_ZERO(&fds); return 1; } /* end of if read FD_ISSET */ return 0; } /* end of init_resolver_clipon */ void kill_resolver_clipon(void) { int status; if (resolver_clipon_pid != -1) { CLOSE(FROM_CLIENT_READ); CLOSE(FROM_CLIENT_WRITE); FROM_CLIENT_READ = FROM_CLIENT_WRITE = -1; FROM_SERVER_READ = FROM_SERVER_WRITE = -1; write_log(SYSTEMLOG,YESTIME,"Killing resolver clip-on\n"); write_log(RESOLVELOG,YESTIME,"TALKER: Killing resolver clip-on\n"); kill(resolver_clipon_pid, SIGTERM); waitpid(-1, &status, WNOHANG); resolver_clipon_pid = -1; } } void send_resolver_request(int user, char *site, char *bad) { int bytes; char sendbuf[1000]; if (user==-1) snprintf(sendbuf,999,"%s",RESOLVER_CLIENT_SEND_SUSPEND); else if (user==-2) snprintf(sendbuf,999,"%s",RESOLVER_CLIENT_SEND_RESUME); else snprintf(sendbuf,999,"%s %d %s %s",RESOLVER_CLIENT_SEND_REQUEST,user,site,bad); write_log(RESOLVELOG,YESTIME,"TALKER: send_resolver_request: Send to server \"%s\"\n",sendbuf); bytes = write(FROM_CLIENT_WRITE,sendbuf,strlen(sendbuf)); if (bytes < strlen(sendbuf)) { sprintf(mess,"Client failed to write resolver request %d:%d",bytes,(int)strlen(sendbuf)); write_str(user,mess); /* Restart and try to write again */ kill_resolver_clipon(); sleep(2); init_resolver_clipon(); bytes = write(FROM_CLIENT_WRITE,sendbuf,strlen(sendbuf)); return; } /* end of bad write */ else { /* write_str(user,"Wrote resolver request"); */ } /* end of else good write */ } void read_resolver_reply(void) { int i; int bytes; int userfind; char site[21]; char host[64]; char readbuf[256]; bytes = read(FROM_CLIENT_READ, readbuf, sizeof(readbuf)); readbuf[bytes] = '\0'; if (bytes <= 0) { /* resolver probably died, let's try to restart */ kill_resolver_clipon(); sleep(2); init_resolver_clipon(); return; } #if defined(RESOLVER_DEBUG) write_log(RESOLVELOG,YESTIME,"TALKER: read_resolver_reply: \nRead from server: %d bytes \"%s\"\n",bytes,readbuf); #endif while (strlen(readbuf)) { /* dont write to log if just checkpoint */ while (!strncmp(readbuf,RESOLVER_SERVER_SEND_CHECKPOINT,strlen(RESOLVER_SERVER_SEND_CHECKPOINT))) { remove_first(readbuf); /* write_log(RESOLVELOG,YESTIME,"TALKER: read_resolver_reply: stripped: now %s\n",readbuf); */ } /* just a checkpoint */ if (!strlen(readbuf)) return; sscanf(readbuf,"%d",&userfind); remove_first(readbuf); sscanf(readbuf,"%s ",site); remove_first(readbuf); sscanf(readbuf,"%s ",host); remove_first(readbuf); if (!strcmp(host,"*")) strcpy(host,SYS_LOOK_FAILED); /* find user that should have this hostname */ for (i=0;i<MAX_USERS;++i) { if (userfind==i && ustr[i].sock!=-1 && !strcmp(ustr[i].site,site)) { strncpy(ustr[i].net_name,host,64); if (resolve_names==2) { del_from_resolver_cache(i); add_to_resolver_cache(i); } write_log(RESOLVELOG,YESTIME,"TALKER: Copied %s to user %d %s\n",host,i,ustr[i].name); /* sprintf(readbuf,"Your resolve result came back as %s",ustr[i].net_name); write_str(i,readbuf); */ /*-----------------------------------*/ /* Check for totally restricted host */ /*-----------------------------------*/ if (check_restriction(i, ANY, THEIR_HOST) == 1) { write_log(BANLOG,YESTIME,"MAIN: Connection attempt, RESTRICTed host %s:%s:sck#%d:slt#%d\n", ustr[i].site,ustr[i].net_name,ustr[i].sock,i); user_quit(i,1); } break; } /* if match */ } /* user for loop */ } /* readbuf while loop */ } void cleanup_resolver(void) { CLOSE(FROM_CLIENT_READ); CLOSE(FROM_CLIENT_WRITE); CLOSE(FROM_SERVER_READ); CLOSE(FROM_SERVER_WRITE); FROM_CLIENT_READ = FROM_CLIENT_WRITE = -1; FROM_SERVER_READ = FROM_SERVER_WRITE = -1; resolver_clipon_pid = -1; }