/* This is a C Proxy server for a News NNTP application. It is compiled with: cc -I/usr/include -L/usr/lib -lsocket -lnsl -O5 -s -o ServerProxy ServerProxy.c */ #include #include #include #include #include #include #include #include #include #include const char SERVICE[20] = "nntp"; const char SERVERNAME[20] = "news.com"; const int PROXYPORT = 559; const int MAXBUF = 256; static int iProxySock; static int iClientSock; static int iServerSock; void startTCPServer(); void processComm(); static void readBulk(char *cInMessage, const char *cRequest); void catchInt(int iSignal); void logMessage(const char *cLogMsg); void logError(const char *cErrorMsg, int iErrorNum); void startTCPServer() { int iSock, iRc, iFlags, iSockSize; struct sockaddr_in sSockAddr; struct servent *sService; struct hostent *sHost; if ((iSock = socket(PF_INET, SOCK_STREAM, 0)) <= 0) { shutdown(iSock, 2); close(iSock); logError("ERROR: Can't Create Server Socket", iSock); } iFlags = 1; if (setsockopt(iSock, SOL_SOCKET, SO_REUSEADDR, &iFlags, sizeof(iFlags)) < 0) { shutdown(iSock, 2); close(iSock); logError("ERROR: Can't Set Socket", iSock); } bzero((char *) &sSockAddr, sizeof(sSockAddr)); sSockAddr.sin_family = PF_INET; sSockAddr.sin_addr.s_addr = htonl(INADDR_ANY); sSockAddr.sin_port = htons(PROXYPORT); iSockSize = sizeof(sSockAddr); if ((iRc = bind(iSock, (struct sockaddr *) &sSockAddr, iSockSize)) < 0) { shutdown(iSock, 2); close(iSock); logError("ERROR: Can't Bind Proxy Server", iRc); } iProxySock = iSock; if ((iRc = listen(iProxySock, SOMAXCONN)) < 0) { logError("ERROR: Can't Listen Proxy Server", iRc); } logMessage("INFO: Proxy Started Accepting Requests"); bzero((char *) &sSockAddr, sizeof(sSockAddr)); iSockSize = sizeof(sSockAddr); if ((iClientSock = accept(iProxySock, (struct sockaddr *) &sSockAddr, &iSockSize)) <= 0) { logError("ERROR: Can't Accept Client", iClientSock); } if ((iSock = socket(PF_INET, SOCK_STREAM, 0)) <= 0) { logError("ERROR: Can't Create Server Socket", iSock); } if ((sService = getservbyname(SERVICE, "tcp")) == NULL) { logError("ERROR: Can't Get Service", 0); } if ((sHost = gethostbyname(SERVERNAME)) == NULL) { logError("ERROR: Can't Get Host Info", 0); } bzero((char *) &sSockAddr, sizeof(sSockAddr)); bcopy(sHost->h_addr, (char *) &sSockAddr.sin_addr, sHost->h_length); sSockAddr.sin_family = PF_INET; sSockAddr.sin_port = sService->s_port; iSockSize = sizeof(sSockAddr); if ((iRc = connect(iSock, (struct sockaddr *) &sSockAddr, iSockSize)) < 0) { logError("ERROR: Can't Connect To Server", iRc); } iServerSock = iSock; if ( (iFlags = fcntl(iServerSock, F_GETFL, 0)) < 0 ) { logError("ERROR: Can't Get Server Control", iFlags); } if ( fcntl(iServerSock, F_SETFL, iFlags|O_NONBLOCK) < 0 ) { logError("ERROR: Can't Set Server Control", iFlags); } if ( (iFlags = fcntl(iClientSock, F_GETFL, 0)) < 0 ) { logError("ERROR: Can't Get Client Control", iFlags); } if ( fcntl(iClientSock, F_SETFL, iFlags|O_NONBLOCK) < 0 ) { logError("ERROR: Can't Set Client Control", iFlags); } logMessage("INFO: Connected To Client"); } void processComm() { const char cARTICLE[8] = "ARTICLE "; const char cXOVER[6] = "XOVER "; char *cMessage; int iMsgSize, iQuitFlag, iRc; cMessage = (char *)malloc(MAXBUF); iMsgSize = MAXBUF; logMessage("INFO: Started Listening For Requests"); iQuitFlag = 0; while (iQuitFlag == 0) { bzero((char *) cMessage, iMsgSize); iRc = recv(iServerSock, cMessage, iMsgSize, 0); if (iRc >= 1) { iRc = send(iClientSock, cMessage, iRc, 0); if (iRc < 0) { logError("ERROR: Send To Client", iRc); } } bzero((char *) cMessage, iMsgSize); iRc = recv(iClientSock, cMessage, iMsgSize, 0); if (iRc >= 1) { iRc = send(iServerSock, cMessage, iRc, 0); if (iRc < 0) { logError("ERROR: Send To Server", iRc); } } if (! strncmp(cMessage, cARTICLE, sizeof(cARTICLE)) ) { readBulk(cMessage, cARTICLE); } if (! strncmp(cMessage, cXOVER, sizeof(cXOVER)) ) { readBulk(cMessage, cXOVER); } sleep(1); } free(cMessage); } static void readBulk(char *cInMessage, const char *cRequest) { const char cENDMSG[5] = "\r\n.\r\n"; const int iTRUE = 1; const int iFALSE = 0; const int iFLAG = 0; const double dSLEEP = .1; char *cMessage; int iMsgSize, iQuitFlag, iRc; cMessage = (char *)malloc(MAXBUF); iMsgSize = MAXBUF; bzero((char *) cMessage, iMsgSize); sprintf((char *) cMessage, "INFO: Processing %s", cRequest); logMessage(cMessage); bzero((char *) cMessage, iMsgSize); strcpy(cMessage, cInMessage); iQuitFlag = 0; while (iQuitFlag == iFALSE) { if (strstr(cMessage, cENDMSG) != NULL) { iQuitFlag = iTRUE; } bzero((char *) cMessage, iMsgSize); iRc = recv(iServerSock, cMessage, iMsgSize, iFLAG); if (iRc >= iTRUE) { iRc = send(iClientSock, cMessage, iRc, iFLAG); } sleep(dSLEEP); } free(cMessage); } void logMessage(const char *cLogMsg) { printf("%s\n", cLogMsg); } void logError(const char *cErrorMsg, int iErrorNum) { char *cMessage; int iMsgSize; cMessage = (char *)malloc(MAXBUF); iMsgSize = MAXBUF; printf("%s : %d : %d\n", cErrorMsg, iErrorNum, errno); bzero((char *) cMessage, iMsgSize); strcpy(cMessage, "QUIT\r\n"); send(iServerSock, cMessage, iMsgSize, 0); fflush(stderr); fflush(stdout); shutdown(iClientSock, 2); shutdown(iServerSock, 2); shutdown(iProxySock, 2); close(iClientSock); close(iServerSock); close(iProxySock); free(cMessage); exit(-1); } void catchInt(int iSignal) { (void) signal(SIGINT, catchInt); logError("ERROR: Signal Interupt", iSignal); } void main() { (void) signal(SIGINT, catchInt); startTCPServer(); processComm(); logError("Closing Connection", 0); }