int main(int argc, char * argv[]) { uid_t nobody, nogrp; memset(conns, 0, sizeof conns); memset(&G, 0, sizeof G); FD_ZERO(&G.readfds); FD_SET(0, &G.readfds); if (argv[1]) { if (argv[1][0] == '-') { if (argv[1][1] == 'V') { printversion('.'); return 0; } else { fdprintf(2, "%s: invalid option -- %c\n", argv[0], argv[1][1]); fdprintf(2, "Usage: %s [-V] " IU_IN_USAGESTR "\n", argv[0]); return 1; } } else { SET_IU(argv[1], argc - 1); } } else { SET_IU(nobodystr, 1); } #ifndef DEBUG close(1); /* not debugging, openlog() hopefully uses fd 1. */ #else close(3); /* debugging, TRACE uses fd 1, openlog() hopefully fd 3 */ #endif openlog("identd", LOG_CONS, LOG_DAEMON); { struct passwd * pw = getpwnam(nobodystr); if (pw) { nobody = pw->pw_uid; nogrp = pw->pw_gid; } else { syslog(LOG_CRIT, "Cannot find user `nobody': %s", strerrno()); return -1; } } if (inetbind(getport()) < 0) { return -1; } /* */ { int i; for (i = FCS; i < MAXCONNS + FCS; i++) { close(i); } } #ifdef DEBUG #ifndef LOG_PERROR #define LOG_PERROR 0 #endif openlog("identd", LOG_PERROR, LOG_DAEMON); #else /* not DEBUG */ godaemon(); openlog("identd", 0, LOG_DAEMON); close(2); signal(SIGHUP, SIG_IGN); #endif /* DEBUG */ signal(SIGPIPE, SIG_IGN); /* connection closed when writing (raises ???) */ writepid(nobody, nogrp); setegid(nogrp); setgid(nogrp); setuid(nobody); seteuid(nobody); { int i; for (i = 0; i < 4; i++) { char * id = (char)NULL; unsigned int rv = 0; switch (i) { case 0: rv = (unsigned int)getegid(); id = "egid"; break; case 1: rv = (unsigned int)getgid(); id = "gid"; break; case 2: rv = (unsigned int)geteuid(); id = "euid"; break; case 3: rv = (unsigned int)getuid(); id = "uid"; break; } if (rv == 0) { syslog(LOG_ERR, "Can not drop all root privileges (%s) !!! %s !!!", id, strerrno()); delpidfile(); return -1; } } } while (2) { fd_set rfds = G.readfds; struct timeval tv = { 15, 0 }; int i; int tim = time(NULL); TRACE(("calling select(): n = %d, rfds = 0x%x\n\n", G.conncnt + FCS, *(int *)&rfds)); select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); for (i = G.conncnt - 1; i >= 0; i--) { int s = i + FCS; if (FD_ISSET(s, &rfds)) { char * buf = conns[i].buf; unsigned int len = conns[i].len; unsigned int l; TRACE(("data socket fd_isset %d\n", s)); if ((int)(l = read(s, buf + len, sizeof conns[0].buf - len)) > 0) { if (checkInput(buf, len, l)) { reply(s, buf); goto deleteconn; } else if (len + l >= sizeof conns[0].buf) { replyError(s, "X-INVALID-REQUEST"); goto deleteconn; } else { conns[i].len += l; } } else { goto deleteconn; } conns[i].lasttime = tim; continue; deleteconn: deleteConn(s); } else { /* implement as time_after() in linux kernel sources ... */ if (conns[i].lasttime + MAXIDLETIME <= tim) { replyError(s, "X-TIMEOUT"); deleteConn(s); } } } if (FD_ISSET(0, &rfds)) { int s = accept(0, NULL, 0); TRACE(("server socket fd_isset, %d accepted\n", s)); if (s < 0) { if (errno != EINTR) /* EINTR */ { syslog(LOG_ERR, "accept: %s", strerrno()); } } else { if (G.conncnt == MAXCONNS) { i = closeOldest(); } else { i = G.conncnt++; } if (s != i + FCS) { movesocket(s, i + FCS); } FD_SET(i + FCS, &G.readfds); conns[i].len = 0; conns[i].lasttime = time(NULL); } } } }
int fakeidentd_main(int argc, char **argv) { memset(conns, 0, sizeof(conns)); memset(&G, 0, sizeof(G)); FD_ZERO(&G.readfds); FD_SET(0, &G.readfds); /* handle -b <ip> parameter */ bb_getopt_ulflags(argc, argv, "b:", &bind_ip_address); /* handle optional REPLY STRING */ if (optind < argc) G.identuser = argv[optind]; else G.identuser = nobodystr; /* daemonize and have the parent return */ if (godaemon() == 0) return 0; /* main loop where we process all events and never exit */ while (1) { fd_set rfds = G.readfds; struct timeval tv = { 15, 0 }; int i; int tim = time(NULL); select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); for (i = G.conncnt - 1; i >= 0; i--) { int s = i + FCS; if (FD_ISSET(s, &rfds)) { char *buf = conns[i].buf; unsigned int len = conns[i].len; unsigned int l; if ((l = read(s, buf + len, sizeof(conns[0].buf) - len)) > 0) { if (checkInput(buf, len, l)) { reply(s, buf); goto deleteconn; } else if (len + l >= sizeof(conns[0].buf)) { replyError(s, "X-INVALID-REQUEST"); goto deleteconn; } else { conns[i].len += l; } } else { goto deleteconn; } conns[i].lasttime = tim; continue; deleteconn: deleteConn(s); } else { /* implement as time_after() in linux kernel sources ... */ if (conns[i].lasttime + MAXIDLETIME <= tim) { replyError(s, "X-TIMEOUT"); deleteConn(s); } } } if (FD_ISSET(0, &rfds)) { int s = accept(0, NULL, 0); if (s < 0) { if (errno != EINTR) /* EINTR */ syslog(LOG_ERR, "accept: %s", strerror(errno)); } else { if (G.conncnt == MAXCONNS) i = closeOldest(); else i = G.conncnt++; movefd(s, i + FCS); /* move if not already there */ FD_SET(i + FCS, &G.readfds); conns[i].len = 0; conns[i].lasttime = time(NULL); } } } /* end of while(1) */ return 0; }
int main(int argc, char **argv) { char program_name[FILENAME_MAX_CHARS]; char config_file[FILENAME_MAX_CHARS]; int syslog; int loglevel; int logfacility; char c; int recoveryport; int error; int daemon_mode = 0; // init program_name and default config file strncpy(program_name, argv[0], FILENAME_MAX_CHARS); strncpy(config_file, DEFAULT_CONFIGFILE, FILENAME_MAX_CHARS); // init default log settings syslog = DEFAULT_USE_SYSLOG; loglevel = DEFAULT_LOG_LEVEL; logfacility = DEFAULT_LOG_FACILITY; // allow the user to set a special port for login recovery recoveryport = 0; //save start time for uptime calculation in status messages bgpmon_start_time = time(NULL); // parse command line while ((c = getopt (argc, argv, "dl:c:f:hsr:")) != -1) { switch (c) { case 'c': strncpy(config_file, optarg, FILENAME_MAX_CHARS); break; case 'l': loglevel = atoi(optarg); break; case 'f': logfacility = atoi(optarg); break; case 's': syslog = 1; break; case 'r': recoveryport = atoi(optarg); break; case 'd': daemon_mode = 1; break; case 'h': case '?': default : usage( argv[0] ); break; } } // if optind is less than the number of arguments from the command line (argc), then there // is something in the argument string that isn't preceded by valid switch (-c, -l, etc) if(optind<argc) { usage(argv[0]); } // initilaze log module if (init_log (program_name, syslog, loglevel, logfacility) ) { fprintf (stderr, "Failed to initialize log functions!\n"); exit(1); } #ifdef DEBUG debug (__FUNCTION__, "Successfully initialized log module."); #endif log_msg("BGPmon starting up\n"); /* Turn into daemon if daemon_mode is set. */ if (daemon_mode){ godaemon(RUN_DIR,PID_FILE); } char scratchdir[FILENAME_MAX_CHARS]; sprintf(scratchdir,"%s/%s",RUN_DIR,"bgpmon"); // initialize login interface if (initLoginControlSettings(config_file, scratchdir, recoveryport) ) { log_fatal("Unable to initialize login interface"); }; #ifdef DEBUG debug (__FUNCTION__, "Successfully initialized login module."); #endif // initialize acl if(initACLSettings()) { log_fatal("Unable to initialize ACL settings"); }; #ifdef DEBUG debug (__FUNCTION__, "Successfully initialized acl module."); #endif // initialize the queue information if (initQueueSettings() ) { log_fatal("Unable to initialize queue settings"); }; #ifdef DEBUG debug (__FUNCTION__, "Successfully initialized queue settings."); #endif // initialize clients control settings if (initClientsControlSettings() ) { log_fatal("Unable to initialize client settings"); }; #ifdef DEBUG debug (__FUNCTION__, "Successfully initialized client settings."); #endif // initialize clients control settings if (initMrtControlSettings() ) { log_fatal("Unable to initialize mrt settings"); }; #ifdef DEBUG debug (__FUNCTION__, "Successfully initialized mrt settings."); #endif // initialize chains settings if (initChainsSettings() ) { log_fatal("Unable to initialize chain settings"); }; // initialize the periodic settings if (initPeriodicSettings() ) { log_fatal("Unable to initialize periodic settings"); }; #ifdef DEBUG debug (__FUNCTION__, "Successfully initialized periodic settings."); #endif // read in the configuration file and change // all relevant settings based on config file if (readConfigFile(config_file) ) { // if the configuration file is not readable, remove the // configuration file and backup a copy backupConfigFile(LoginSettings.configFile, LoginSettings.scratchDir); saveConfigFile(LoginSettings.configFile); log_err("Corrupt Configuration File Moved to %s. New configuration file written.", LoginSettings.scratchDir); } /* * Block signals in initial thread. New threads will * inherit this signal mask. All the signals will be handled * in a dedicated thread */ sigfillset ( &signalSet ); pthread_sigmask ( SIG_BLOCK, &signalSet, NULL ); // launch the signal handling thread #ifdef DEBUG debug(__FUNCTION__, "Creating signal thread..."); #endif pthread_t sighandlerThreadID; if ((error = pthread_create(&sighandlerThreadID, NULL, sigHandler, config_file)) > 0 ) log_fatal("Failed to create signal handler thread: %s\n", strerror(error)); #ifdef DEBUG debug(__FUNCTION__, "Created signal thread!"); #endif // create the system queues #ifdef DEBUG debug(__FUNCTION__, "Creating queues..."); #endif /*create the peer queue*/ peerQueue = createQueue(copyBMF, sizeOfBMF, PEER_QUEUE_NAME, strlen(PEER_QUEUE_NAME), FALSE); /*create the label queue*/ labeledQueue = createQueue(copyBMF, sizeOfBMF, LABEL_QUEUE_NAME, strlen(LABEL_QUEUE_NAME), FALSE); /*create the xml queue*/ xmlUQueue = createQueue(copyXML, sizeOfXML, XML_U_QUEUE_NAME, strlen(XML_U_QUEUE_NAME), TRUE); xmlRQueue = createQueue(copyXML, sizeOfXML, XML_R_QUEUE_NAME, strlen(XML_R_QUEUE_NAME), TRUE); #ifdef DEBUG debug(__FUNCTION__, "Created queues!"); #endif // launch the peering thread #ifdef DEBUG debug(__FUNCTION__, "Creating peering thread..."); #endif launchAllPeers(); #ifdef DEBUG debug(__FUNCTION__, "Created peering thread!"); #endif // launch the labeling thread #ifdef DEBUG debug(__FUNCTION__, "Creating labeling thread..."); #endif launchLabelingThread(); #ifdef DEBUG debug(__FUNCTION__, "Created labeling thread!"); #endif // launch the xml thread #ifdef DEBUG debug(__FUNCTION__, "Creating xml thread..."); #endif launchXMLThread(); #ifdef DEBUG debug(__FUNCTION__, "Created xml thread!"); #endif // launch the clients control thread #ifdef DEBUG debug(__FUNCTION__, "Creating clients control thread..."); #endif launchClientsControlThread(); #ifdef DEBUG debug(__FUNCTION__, "Created clients control thread!"); #endif // launch the mrt control thread #ifdef DEBUG debug(__FUNCTION__, "Creating mrt control thread..."); #endif launchMrtControlThread(); #ifdef DEBUG debug(__FUNCTION__, "Created mrt control thread!"); #endif // launch the configured chains thread #ifdef DEBUG debug(__FUNCTION__, "Creating threads for each configured chain..."); #endif launchAllChainsThreads(); #ifdef DEBUG debug(__FUNCTION__, "Created threads for each configured chain!"); #endif // launch the login thread #ifdef DEBUG debug(__FUNCTION__, "Creating login thread..."); #endif launchLoginControlThread(); #ifdef DEBUG debug(__FUNCTION__, "Created login thread!"); #endif // launch the periodic thread #ifdef DEBUG debug(__FUNCTION__, "Creating periodic thread..."); #endif LaunchPeriodicThreads(); #ifdef DEBUG debug(__FUNCTION__, "Created periodic thread!"); #endif // write BGPMON_START message into the Peer Queue BMF bmf = createBMF(0, BMF_TYPE_BGPMON_START); QueueWriter qw = createQueueWriter(peerQueue); writeQueue(qw, bmf); destroyQueueWriter(qw); // periodically check on the state of each thread time_t threadtime; time_t currenttime; char currenttime_extended[64]; memset(currenttime_extended, 0, 64); char threadtime_extended[64]; memset(threadtime_extended, 0, 64); struct tm * current_tm = NULL; struct tm * thread_tm = NULL; int *chainIDs; long *clientIDs; long *mrtIDs; int clientcount, chaincount, mrtcount, i; while ( TRUE ) { // get the current running time to compare the threads // last exection time to currenttime = time(NULL); sleep(THREAD_CHECK_INTERVAL); current_tm = localtime(¤ttime); strftime(currenttime_extended, sizeof(currenttime_extended), "%Y-%m-%dT%H:%M:%SZ", current_tm); // CLI MODULE // check the cli listener threadtime = getLoginControlLastAction(); if (difftime(currenttime, threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("CLI Module is idle: current time = %s, last thread time = %s", currenttime_extended, threadtime_extended); //closeBgpmon(config_file); } // check the individual cli threads for updates int clicount = 0; long * cliIDs = NULL; clicount = getActiveCliIds(&cliIDs); if(clicount != -1) { for ( i=0; i<clicount; i++) { threadtime = getCliLastAction(cliIDs[i]); if ( difftime(currenttime, threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("Cli %d is idle: current time = %s, last cli %d thread time = %s", cliIDs[i], currenttime_extended, cliIDs[i], threadtime_extended); } } free(cliIDs); } // CLIENTS MODULE // Clients Module threadtime = getClientsControlLastAction(); thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); if (difftime(currenttime, threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("Clients Module is idle: current time = %s, last control thread time = %s", currenttime_extended, threadtime_extended); //closeBgpmon(config_file); } // UPDATE clients clientcount = getActiveClientsIDs(&clientIDs, CLIENT_LISTENER_UPDATA); if(clientcount != -1) { for (i = 0; i < clientcount; i++) { threadtime = getClientLastAction(clientIDs[i], CLIENT_LISTENER_UPDATA); if (difftime(currenttime, threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("Updates Client %d is idle: current time = %s, last client %d thread time = %s", clientIDs[i], currenttime_extended, clientIDs[i], threadtime_extended); } } free(clientIDs); } // RIB clients clientcount = getActiveClientsIDs(&clientIDs, CLIENT_LISTENER_RIB); if(clientcount != -1) { for (i = 0; i < clientcount; i++) { threadtime = getClientLastAction(clientIDs[i], CLIENT_LISTENER_RIB); if (difftime(currenttime,threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("RIB Client %d is idle: current time = %s, last client %d thread time = %s", clientIDs[i], currenttime_extended, clientIDs[i], threadtime_extended); } } free(clientIDs); } // PEER MODULE for (i=0; i < MAX_SESSION_IDS; i++) { if( Sessions[i] != NULL && getSessionState(Sessions[i]->sessionID) == stateEstablished) { threadtime = getSessionLastActionTime(i); if (difftime(currenttime,threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("Peering session %d is idle: current time = %s, last client %d thread time = %s",Sessions[i]->sessionID, currenttime_extended, Sessions[i]->sessionID, threadtime_extended); //closeBgpmon(config_file); } } } // LABELING MODULE threadtime = getLabelThreadLastActionTime(); if (difftime(currenttime,threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("Labeling module is idle: current time = %s, last control thread time = %s", currenttime_extended, threadtime_extended); //closeBgpmon(config_file); } // XML MODULE threadtime = getXMLThreadLastAction(); if (difftime(currenttime,threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("XML module is idle: current time = %s, last control thread time = %s", currenttime_extended, threadtime_extended); //closeBgpmon(config_file); } // QUAGGA MODULE // mrt listener threadtime = getMrtControlLastAction(); if (difftime(currenttime,threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("MRT module is idle: current time = %s, last control thread time = %s", currenttime_extended, threadtime_extended); //closeBgpmon(config_file); } // mrt connections mrtcount = getActiveMrtsIDs(&mrtIDs); if(mrtcount != -1) { for (i = 0; i < mrtcount; i++) { threadtime = getMrtLastAction(mrtIDs[i]); if (difftime(currenttime,threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("MRT client %d is idle: current time = %s, last client %d thread time = %s",mrtIDs[i], currenttime_extended, mrtIDs[i], threadtime_extended); } } free(mrtIDs); } // CHAIN MODULE chaincount = getActiveChainsIDs(&chainIDs); if(chaincount != -1) { for (i = 0; i < chaincount; i++) { threadtime = getChainLastAction(chainIDs[i]); if (difftime(currenttime,threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("BGPmon chain %ld is idle: current time = %s, last client %ld thread time = %s", chainIDs[i], currenttime_extended, chainIDs[i], threadtime_extended); } } free(chainIDs); } // PERIODIC MODULE // route refresh threadtime = getPeriodicRouteRefreshThreadLastActionTime(); if (difftime(currenttime,threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("Route Refresh module is idle: current time = %s, last control thread time = %s", currenttime_extended, threadtime_extended); //closeBgpmon(config_file); } // status message threadtime = getPeriodicStatusMessageThreadLastActionTime(); if (difftime(currenttime,threadtime) > THREAD_DEAD_INTERVAL) { thread_tm = localtime(&threadtime); strftime(threadtime_extended, sizeof(threadtime_extended), "%Y-%m-%dT%H:%M:%SZ", thread_tm); log_warning("Status Messages module is idle: current time = %s, last control thread time = %s", currenttime_extended, threadtime_extended); //closeBgpmon(config_file); } } // should never get here log_err( "main: unexpectedly finished"); return(0); }