/* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** File : ProcessManager.cc ** Author : Su LI & Jing Yang ** Date : 11/02 ** Description: Main module of the alternative project. ** Upon receiving a message from the original ** server indication a possible attacks, the program ** performs the following the tasks: ** 1. Kick off a script to update the DNS server with ** a new IP of the alternative gateway. ** 2. Start up a gateway program as a proxy server that ** acts as a gateway between the real web server and ** clients (ip-over-IP). ** ** Copyright (C) Check with the author, 2000-2010. All ** Rights reserved. ** ** ** Revision List: ** YY-MM BY DESCRIPTION ** **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "comm_msgdefs.h" void ast_func(int sig) { char *rtn_name = "ast_func()"; switch (sig) { case SIGUSR1: shutDown(); printf("ast_func(), Got signal USR...exited...Main Server is Down\n"); break; case SIGINT: shutDown(); printf("ast_func(), Got signal SIGINT...exited...Main Server is Down\n"); } exit(0); } bool processData(void *data_in, int sockfd) { char *rtn_name = "processData()"; MsgHeader *rcvd_data = (MsgHeader *) data_in; AckNack_Msg ack_data; MsgHeader hdr; char msgbuf[250]; char buf[80]; int len; if (rcvd_data->msg_type == SVR) { memset(msgbuf, '\0', sizeof(msgbuf)); sprintf(msgbuf, "%s, Received message(%d)\n", rtn_name, rcvd_data->msg); logIt(msgbuf, INFO); /* send ack/nack message */ ack_data.status = SUCCESS; hdr.msg_type = ACK; hdr.msg = OK; sprintf(buf, "%.1d:%.1d:%.1d",hdr.msg_type, hdr.msg, ack_data.status); if (Send(sockfd, buf, strlen(buf)) == -1) { memset(msgbuf, '\0', sizeof(msgbuf)); sprintf(msgbuf, "%s, failed to send Ack/Nack message\n", rtn_name); logIt(msgbuf, ERROR); } } if (rcvd_data->msg == ATTACK) return true; else return false; } void startProcesses() { /***call update DNS script and start up IP_OVER_IP Server **/ system("./start_DNS_IPOVERIP_Svr.sh"); } void initialize() { char *rtn_name = "initialize()"; char buf[100]; char msgbuf[150]; int len, report_intval; infoLog = (INFO_LOG *)malloc(sizeof(INFO_LOG)); errLog = (ERR_LOG *)malloc(sizeof(ERR_LOG)); /**Set new file flag**/ errLog->newfile = 1; errLog->num_of_rec = 0; errLog->seq = 0; memset(errLog->datebase, '\0', sizeof(errLog->datebase)); memset(errLog->filename, '\0', sizeof(errLog->filename)); infoLog->newfile = 1; infoLog->num_of_rec = 0; infoLog->seq = 0; memset(infoLog->datebase, '\0', sizeof(infoLog->datebase)); memset(infoLog->filename, '\0', sizeof(infoLog->filename)); } void main() { int sockfd, i; int newsockfd; char *rtn_name="main()"; struct sockaddr_in serveraddr; struct sockaddr_in clientaddr; socklen_t clientaddrlen = sizeof(clientaddr); struct hostent *he; char *ip; fd_set rset, xset; struct timeval timeout; int nfds, ret; int reuse_addr_onoff = 1; char msgbuf[150]; int reload_flag=0; timeout.tv_sec = 10; timeout.tv_usec = 0; MsgHeader hdr; /*signal(SIGUSR1, reload);*/ signal(SIGINT, ast_func); signal(SIGCHLD, SIG_IGN); printf("TEST ok"); /* initialize now */ initialize(); printf("TEST ok1"); /* Create a socket for the communications */ memset(msgbuf, '\0', sizeof(msgbuf)); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket_create"); exit(1); } /* set SO_REUSEADD option to the created socket */ else if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr_onoff, sizeof(reuse_addr_onoff)) < 0) { sprintf(msgbuf, "%s, setsockopt() failed, errno (%d), %s\n",rtn_name, errno, strerror(errno)); logIt(msgbuf, ERROR); exit(1); } bzero((char *) &serveraddr, sizeof(struct sockaddr_in)); serveraddr.sin_family = AF_INET; /* * IFADDRANY signifies any attached interface adapter on the system. * all numbers are to be converted to the network format using * appropriate macros. See htonl(3), htons(3), ntohl(3), ntohs(3). * */ serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(port_num); /* Bind the address to this socket to make it 'known' */ memset(msgbuf, '\0', sizeof(msgbuf)); if ( bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_in)) < 0) { perror("socket_bind"); sprintf(msgbuf, "%s bind() fails, exit ..", rtn_name); logIt(msgbuf, ERROR); exit(2); } /* * Specify how many pending connections can be maintained, till * we finish accept processing. This will govern the success rate * of connections while we spend time in housekeeping (from the * time of one "accept" to next "accept") * To get a better success rate (when a lot of clients are * bombarding the server with connect requests), use larger * values. OS implementation limits it some ceiling number. * On OSF/1 at the time of writing this example it is 8, but * don't count on it. * */ listen(sockfd, 8); memset(msgbuf, '\0', sizeof(msgbuf)); sprintf(msgbuf, "main(), main svr is up running at port:%d", port_num); logIt(msgbuf, INFO); printf("TEST ok"); while(1) { FD_ZERO(&rset); FD_SET(sockfd, &rset); if (select(sockfd+1, &rset, NULL,NULL, &timeout)) {/*data avalialiable*/ if ((newsockfd = accept(sockfd, (struct sockaddr *) &clientaddr, &clientaddrlen)) < 0) { if (errno == EINTR) { printf("Bye...\n"); } else { perror("socket_accept"); printf("Bye...\n"); } memset(msgbuf, '\0', sizeof(msgbuf)); sprintf(msgbuf, "%s accept() fails", rtn_name); logIt(msgbuf, ALARM); } else if (!(ip = inet_ntoa(clientaddr.sin_addr))) { memset(msgbuf, '\0', sizeof(msgbuf)); sprintf(msgbuf, "%s inet_ntoa() failed, errno (%d), %s\n", rtn_name, errno, strerror(errno)); logIt(msgbuf, ALARM); /* close the connection */ close(newsockfd); newsockfd=-1; } if (Receive(newsockfd, hdrStr, sizeof(hdrStr)-1)) { sscanf(hdrStr, "%d:%d", &hdr.msg_type, &hdr.msg); /**process Data**/ if (processData((void *)&hdr, newsockfd)) { /**DO the real things here**/ startProcesses(); } } else { memset(msgbuf, '\0', sizeof(msgbuf)); sprintf(msgbuf, "%s Receive zero length data", rtn_name); logIt(msgbuf, ERROR); shutdown(newsockfd, SHUT_RDWR); close(newsockfd); } } /*if Select*/ } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Function Name: Receive // // Parameter List: // Socket: Socket descriptor from which messages are received // Buffer: Pointer to a buffer into which the messages are placed. // BytesToRead: total number of bytes to read // Flags: allowable values are: // MSG_PEEK : any data returned to caller is treated as if it // had not been read. // MSG_OOB: Receive out-of-band data. Valid for TCP SOCK_STREAM // sockets only (invalid for AF_UNIX sockets). // MSG_PEEK | MSG_OOB: valid for TCP SOCKET_STREAM sockets. // 0 : no flags specified. // // Description: The routine will receive data in the specified buffer using // the TCP protocol. A connection must have previously been established // before calling this routine. // // Note: This routine is designed to correctly handle blocking mode // calls. If a caller is executing in nonblocking mode, the caller must // determine how to handle an unexpected return value from this function. // For a complete description of the behavioral differences between // blocking and nonblocking mode, see the man page description for recv(). // // Blocking mode exhibits the following behavior: // a) if no data is available to be received, // the receive call will BLOCK. // Further, this function stays in a while loop until all the requested // data has been received if called in blocking mode. // Notable change that recv returning -1 and EINTR would stay in loop also // // // Return Value: // BytesToRead: The requested number of bytes to read were received. // -1 : The recv() function was unsuccessful. The caller // should access errno to determine the actual error. // 0 : This value will only be returned if the caller is in // nonblocking mode previously enabled by setting the // O_NDELAY flag using the fcntl function AND there is // no data available to be received. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int Receive(int sockfd, void *buffer, int bytesToRead) { char msgbuf[150]; char *rtn_name = "BaseSocket::Receive()"; int bytesRead, bytesLeftToRead = bytesToRead, currentByte = 0; if ((sockfd > 0) && buffer && (bytesToRead > 0)) { while (bytesLeftToRead) { /* try to send over TCP/IP net */ bytesRead = recv(sockfd, (char *)buffer, bytesToRead, 0); if (bytesRead > 0) { bytesLeftToRead -= bytesRead; currentByte += bytesRead; } else if (bytesRead < 0) { if (errno != EAGAIN) { memset(msgbuf, '\0', sizeof(msgbuf)); sprintf(msgbuf, "%s, recv() failed, errno (%d), %s\n", rtn_name, errno, strerror(errno)); logIt(msgbuf, ERROR); return (-1); } } else /* this may indicate a conn shutdown */ break; } } return (currentByte); } int Read(int sockfd, void *buffer, int bytesToRead) { char msgbuf[150]; char *rtn_name = "BaseSocket::Receive()"; int bytesRead, bytesLeftToRead = bytesToRead, currentByte = 0; if ((sockfd > 0) && buffer && (bytesToRead > 0)) { while (bytesLeftToRead) { /* try to send over TCP/IP net */ bytesRead = read(sockfd, (char *)buffer, bytesToRead); if (bytesRead > 0) { bytesLeftToRead -= bytesRead; currentByte += bytesRead; } else if (bytesRead < 0) { if (errno != EAGAIN) { memset(msgbuf, '\0', sizeof(msgbuf)); sprintf(msgbuf, "%s, recv() failed, errno (%d), %s\n", rtn_name, errno, strerror(errno)); logIt(msgbuf, ERROR); return (-1); } } else /* this may indicate a conn shutdown */ break; } } return (currentByte); } int Send(int sockfd, void *buf, int bytesToSend) { char msgbuf[150]; char *rtn_name = "BaseSocket::Send()"; int bytesSent, bytesLeftToSend, currentByte = 0; int ret = 0; if (buf && (bytesToSend > 0)) { bytesLeftToSend = bytesToSend; /* Put message header in front of the actual message. * While receiving the data, internal engine will strip * off this header and will give the actual data to the * user */ while (bytesLeftToSend) { /* try to send over TCP/IP net */ bytesSent = send(sockfd, (char *)buf, bytesLeftToSend, 0); if (bytesSent > 0) { bytesLeftToSend -= bytesSent; currentByte += bytesSent; } else if (bytesSent < 0) { if (errno != EAGAIN) { memset(msgbuf, '\0', sizeof(msgbuf)); sprintf(msgbuf, "%s, send() failed, errno (%d), %s\n", rtn_name, errno, strerror(errno)); logIt(msgbuf, ERROR); ret = -1; break; } } else /* this may indicate a conn shutdown */ break; } } return (ret); } void getCurrTimeString(char *format, char *res, int len, int msec_flag) { char msgbuf[55]; struct timeval tval; struct tm *ptm; if (res && format) { res[0] = 0; if (gettimeofday(&tval, NULL) < 0) { memset(msgbuf, '\0', sizeof(msgbuf)); logIt("getCurrTimeString() failed to get gettimeofday ..", ERROR); } else { ptm = localtime(&tval.tv_sec); if (ptm) { strftime(res, len, format, ptm); if (msec_flag) sprintf(res+strlen(res), ".%.3d", tval.tv_usec/1000); } } } } void logIt(char *Str, int flag) { char cmd[200]; if (flag == INFO) { if (infoLog->newfile || isMidNight(flag) || infoLog->num_of_rec >= MaxLogRecPerFile) { if(!openFile(INFO)) return; } /**output rec into a log file**/ if (infoLog->infoLogFp) fclose(infoLog->infoLogFp); infoLog->infoLogFp= fopen(infoLog->path, "a+"); if (infoLog->infoLogFp != NULL) { fprintf (infoLog->infoLogFp, "%s: %s\n", getTime(), Str); infoLog->num_of_rec++; fclose(infoLog->infoLogFp); } } else if (flag == ERROR || flag == ALARM) { if (errLog->newfile || isMidNight(flag) || errLog->num_of_rec >= MaxLogRecPerFile) { if(!openFile(flag)) return; } /**output rec into a log file**/ if (errLog->errLogFp) fclose(errLog->errLogFp); errLog->errLogFp= fopen(errLog->path, "a+"); if (errLog->errLogFp != NULL) { fprintf (errLog->errLogFp, "%s: %s\n", getTime(), Str); infoLog->num_of_rec++; fclose(errLog->errLogFp); } if (flag == ALARM) { sprintf(cmd, "mailx -s %s %s < %s", "Alert!!! SVR goes down", "sli@cs.uccs.edu", "svr_alarm.txt"); system(cmd); } } } int openFile(int fileType) { int ret = 1; if (fileType == INFO) { if (infoLog->infoLogFp) fclose(infoLog->infoLogFp); memset(infoLog->filename, '\0', sizeof(infoLog->filename)); strcpy(infoLog->filename,getFileName(fileType)); memset(infoLog->path, '\0', sizeof(infoLog->path)); sprintf(infoLog->path, "%s/%s\0",log_dir,infoLog->filename); infoLog->infoLogFp= fopen(infoLog->path, "w+"); if (infoLog->infoLogFp == NULL) return -1; infoLog->newfile = 0; infoLog->seq++; } else if (fileType == ERROR || fileType == ALARM) { if (errLog->errLogFp) fclose(errLog->errLogFp); memset(errLog->path, '\0', sizeof(errLog->path)); memset(errLog->filename, '\0', sizeof(errLog->filename)); strcpy(errLog->filename,getFileName(fileType)); memset(errLog->path, '\0', sizeof(errLog->path)); sprintf(errLog->path, "%s/%s\0",log_dir,errLog->filename); errLog->errLogFp= fopen(errLog->path, "w+"); if (errLog->errLogFp == NULL) return -1; errLog->newfile = 0; errLog->seq++; } return ret; } char *getFileName(int fileType) { static char tempStr[100]; char *tem; int ret = 1; memset(tempStr, '\0', sizeof(tempStr)); tem = getTime(); if (fileType == INFO) { infoLog->seq++; if (infoLog->seq > 9999) infoLog->seq = 0; sprintf(tempStr, "SIVR_INFO.%s.%d.log\0", tem,infoLog->seq); strncpy(infoLog->datebase, tem,8); } else if (fileType == ERROR || fileType == ALARM) { errLog->seq++; if (errLog->seq > 9999) errLog->seq = 0; sprintf(tempStr, "SIVR_ERROR.%s.%d.log\0", tem,errLog->seq); strncpy(errLog->datebase, tem,8); } return (tempStr); } char *getTime() { static char TimeStr[80]; time_t CurrentTime; struct tm *st_time = NULL; time( &CurrentTime); st_time = localtime (&CurrentTime); sprintf(TimeStr, "%04d%02d%02d%02d%02d%02d", st_time->tm_year+1900, st_time->tm_mon+1, st_time->tm_mday, st_time->tm_hour, st_time->tm_min, st_time->tm_sec); return TimeStr; } int isMidNight(int fileType) { char curr_date[9]; int ret = 0; /* get the current date */ getCurrTimeString("%Y%m%d", curr_date, sizeof(curr_date), 0); /* compare */ if (fileType == INFO) { if (strcmp(infoLog->datebase, curr_date)) { ret = 1; infoLog->seq = 0; } } else { if (strcmp(errLog->datebase, curr_date)) { ret = 1; errLog->seq = 0; } } return (ret); } void shutDown() { printf("\nshutdown(), the ERS_RPT_SVR is going down"); logIt("shutdown(), the ERS_RPT_SVR is going down", INFO); free(infoLog); free(errLog); exit(0); }