Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* vim:ts=4
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <signal.h>
- #include <sys/socket.h>
- #include <pthread.h>
- #include <sys/types.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- const char *VERSION = "Nagios Proxy (http://madebyryan.blogspot.com/) Build: " __DATE__ " at " __TIME__;
- #define NSCA_PORT 5667
- /*
- #define DEBUGA 1
- */
- void listen_mode(void);
- void broadcast_mode(void);
- void *listen_thread(void *socket_int);
- void *pipeout_thread(void *NotUsed);
- void *broadcast_thread(void *socket_int);
- int broadcast_connect(void);
- void *proxy_health_thread(void *NotUsed);
- static void print_timestamp(FILE *output);
- void queue_add(const char *buffer);
- const char *queue_remove(void);
- int sock;
- struct sockaddr_in bindaddr;
- int is_listenmode = 1;
- char *destination;
- pthread_mutex_t queue_mutex;
- int main(int argc, char **argv)
- {
- pthread_t thread;
- int rv;
- destination = argv[1];
- if (argc == 1)
- is_listenmode = 1;
- else
- is_listenmode = 0;
- signal(SIGPIPE, SIG_IGN);
- print_timestamp(stderr);
- fprintf(stderr, "Startup in %s mode\n", is_listenmode ? "LISTEN" : "BROADCAST");
- rv = pthread_create(&thread, NULL, proxy_health_thread, NULL);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Creating health thread failed: %d\n", rv);
- } else {
- rv = pthread_detach(thread);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to detach health thread: %d\n", rv);
- }
- }
- /*
- * Setup listening socket
- */
- if (is_listenmode)
- listen_mode();
- else
- broadcast_mode();
- return 0;
- }
- void listen_mode(void)
- {
- pthread_t thread;
- int i, client, rv;
- socklen_t addrlen;
- struct sockaddr_in clientaddr;
- pthread_mutex_init(&queue_mutex, NULL);
- rv = pthread_create(&thread, NULL, pipeout_thread, NULL);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Creating pipeout thread failed: %d\n", rv);
- } else {
- rv = pthread_detach(thread);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to detach pipeout thread: %d\n", rv);
- }
- }
- sock = socket(PF_INET, SOCK_STREAM, 0);
- if (sock == -1) {
- print_timestamp(stderr);
- fprintf(stderr, "failed to create socket at %s:%d\n",
- __FILE__, __LINE__);
- exit(0);
- }
- i = 1;
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i)) < 0) {
- print_timestamp(stderr);
- fprintf(stderr, "setsockopt failed: %s\n", strerror(errno));
- }
- memset(&bindaddr, 0, sizeof(struct sockaddr_in));
- bindaddr.sin_family = PF_INET;
- bindaddr.sin_port = htons(NSCA_PORT);
- bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(sock, (struct sockaddr *)&bindaddr,
- sizeof(struct sockaddr_in)) == -1) {
- print_timestamp(stderr);
- fprintf(stderr, "bind failed: %s", strerror(errno));
- exit(1);
- }
- if (listen(sock, 5) == -1) {
- print_timestamp(stderr);
- fprintf(stderr, "listen failed: %s\n", strerror(errno));
- exit(0);
- }
- while (1) {
- addrlen = sizeof(struct sockaddr_in);
- memset(&clientaddr, 0, sizeof(struct sockaddr));
- client = accept(sock, (struct sockaddr *)&clientaddr, &addrlen);
- if (client == -1) {
- print_timestamp(stderr);
- fprintf(stderr, "accept failed: %s\n", strerror(errno));
- } else {
- rv = pthread_create(&thread, NULL, listen_thread, (void *)client);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Creating listen thread failed: %d\n", rv);
- close(sock);
- } else {
- rv = pthread_detach(thread);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to detach listen thread: %d\n", rv);
- }
- }
- }
- }
- }
- void broadcast_mode(void)
- {
- FILE *input;
- char buffer[16342], *retstr;
- int i, rv;
- pthread_t thread;
- input = fopen("nagios-remote.cmd", "r");
- if (input == NULL) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to open nagios-remote.cmd\n");
- exit(1);
- }
- rv = pthread_create(&thread, NULL, broadcast_thread, NULL);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Creating broadcast thread failed: %d\n", rv);
- } else {
- rv = pthread_detach(thread);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to detach broadcast thread: %d\n", rv);
- }
- }
- while (1) {
- retstr = fgets(buffer, 16342, input);
- if (retstr == NULL) {
- clearerr(input);
- usleep(1000);
- continue;
- }
- i = strlen(buffer);
- buffer[i] = 0;
- /*
- * Skip obviously wrong plugin output, helps buggy installs
- * add everything else for processing
- */
- if (strstr(buffer, "/bin/ping") == NULL)
- queue_add(buffer);
- }
- }
- void *broadcast_thread(void *socket_int)
- {
- int sock, sendret;
- const char *data;
- restart_broadcast:
- do {
- sock = broadcast_connect();
- if (sock == -1)
- usleep(1000);
- } while (sock == -1);
- do {
- data = queue_remove();
- while (data == NULL) {
- usleep(1000);
- data = queue_remove();
- }
- sendret = send(sock, data, strlen(data), 0);
- if (sendret == -1) {
- print_timestamp(stderr);
- fprintf(stderr, "Disconnected : %s\n", strerror(errno));
- goto restart_broadcast;
- }
- } while (1);
- }
- void *listen_thread(void *socket_int)
- {
- int client;
- char buffer[16348], *endofbuffer;
- int datalen, datapos;
- struct sockaddr_in peer;
- socklen_t peerlen;
- char *inetret;
- char clientname[64];
- client = (int)socket_int;
- datapos = 0;
- buffer[0] = 0;
- peerlen = sizeof(struct sockaddr_in);
- if (getpeername(client, (struct sockaddr *)&peer, &peerlen) == -1) {
- snprintf(clientname, 1024, "Unknown");
- } else {
- inetret = inet_ntoa(peer.sin_addr);
- strncpy(clientname, inetret, 64);
- }
- do {
- datalen = recv(client, buffer+datapos, 16348-datapos, 0);
- if (datalen > 0) {
- datapos += datalen;
- buffer[datapos] = 0;
- }
- if (datalen <= 0) {
- if (errno != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Client (%s) Disconnected %d: %s\n", clientname,
- errno, strerror(errno));
- }
- close(client);
- return NULL;
- }
- while ((endofbuffer = strchr(buffer, '\n')) != NULL) {
- *endofbuffer = 0;
- queue_add(buffer);
- #ifdef DEBUGA
- print_timestamp(stderr);
- fprintf(stderr, "--- buffer: '%s'\n datapos(%d) endofbuffer(%d)\n", buffer, datapos, endofbuffer-buffer);
- #endif
- memmove(buffer, endofbuffer+1, datapos - (endofbuffer-buffer));
- datapos -= (endofbuffer-buffer)+1;
- }
- } while(1);
- }
- void *pipeout_thread(void *NotUsed)
- {
- const char *data;
- FILE *dataout;
- int do_len;
- #ifdef DEBUGA
- int se_len;
- #endif
- dataout = fopen("nagios.cmd", "w");
- if (dataout == NULL) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to open nagios.cmd for output\n");
- exit(1);
- }
- do {
- data = queue_remove();
- while (data == NULL) {
- if(dataout != NULL)
- fclose(dataout);
- dataout = NULL;
- usleep(1000);
- data = queue_remove();
- }
- restart_outwrite:
- if (dataout == NULL) {
- dataout = fopen("nagios.cmd", "w");
- if (dataout == NULL) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to open nagios.cmd for output\n");
- exit(1);
- }
- }
- do_len = fprintf(dataout, "[%lu] %s\n", time(NULL), data);
- /*se_len = fprintf(stderr, "[%u] %s\n", time(NULL), data);
- printf("Wrote dataout(%d) stderr(%d)\n", do_len, se_len);*/
- if (do_len == 0) {
- fclose(dataout);
- dataout = NULL;
- goto restart_outwrite;
- }
- } while (1);
- }
- int queue_head = 0, queue_tail = 0;
- int queue_size = 0;
- int queue_additions = 0, queue_bytes = 0;
- char queue_data[4096][1024];
- void queue_add(const char *buffer)
- {
- int is_added = 0;
- int slen, rv;
- #ifdef DEBUGA
- fprintf(stderr, "Adding(%d): \"%s\"\n", queue_size, buffer);
- #endif
- rv = pthread_mutex_lock(&queue_mutex);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to lock mutex in queue_add(): %d\n", rv);
- return;
- }
- if ((queue_tail+1) % 4096 != queue_head) {
- slen = strlen(buffer);
- memcpy(queue_data[queue_tail], buffer, slen+1);
- ++queue_tail;
- queue_tail %= 4096;
- is_added = 1;
- ++queue_size;
- ++queue_additions;
- queue_bytes += slen;
- }
- rv = pthread_mutex_unlock(&queue_mutex);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to unlock mutex in queue_add(): %d\n", rv);
- }
- }
- const char *queue_remove(void)
- {
- const char *retstr;
- int rv;
- rv = pthread_mutex_lock(&queue_mutex);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to lock mutex in queue_remove(): %d\n", rv);
- return NULL;
- }
- if (queue_head != queue_tail) {
- retstr = queue_data[queue_head];
- ++queue_head;
- queue_head %= 4096;
- --queue_size;
- #ifdef DEBUGA
- fprintf(stderr, "Removing(%d): \"%s\"\n", queue_size, retstr);
- #endif
- } else
- retstr = NULL;
- rv = pthread_mutex_unlock(&queue_mutex);
- if (rv != 0) {
- print_timestamp(stderr);
- fprintf(stderr, "Failed to unlock mutex in queue_remove(): %d\n", rv);
- }
- return retstr;
- }
- int broadcast_connect(void)
- {
- int i, sock, client;
- restart_connection:
- sock = socket(PF_INET, SOCK_STREAM, 0);
- if (sock == -1) {
- print_timestamp(stderr);
- fprintf(stderr, "failed to create socket at %s:%d\n", __FILE__,
- __LINE__);
- exit(0);
- }
- i = 1;
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i)) < 0) {
- print_timestamp(stderr);
- fprintf(stderr, "setsockopt failed: %s\n", strerror(errno));
- }
- memset(&bindaddr, 0, sizeof(struct sockaddr_in));
- bindaddr.sin_family = PF_INET;
- bindaddr.sin_port = htons(NSCA_PORT);
- bindaddr.sin_addr.s_addr = inet_addr(destination);
- client = connect(sock, (struct sockaddr *)&bindaddr, sizeof(struct sockaddr_in));
- if (client == -1) {
- print_timestamp(stderr);
- fprintf(stderr, "connect failed: %s:%d - %s\n", destination, NSCA_PORT,
- strerror(errno));
- close(sock);
- usleep(1000);
- goto restart_connection;
- }
- return sock;
- }
- void *proxy_health_thread(void *NotUsed)
- {
- char hostname[128];
- char buffer[1024];
- gethostname(hostname, 128);
- do {
- usleep(20000000);
- snprintf(buffer, 1024, "PROCESS_SERVICE_CHECK_RESULT;nagios_proxy;%s;0;%0.2f svc_chk/sec %0.2fKB/sec\n", hostname, queue_additions/20.0f, queue_bytes/1024.0f/20.0f);
- #ifdef DEBUGA
- fprintf(stderr, "%s", buffer);
- #endif
- if (queue_additions == 0) {
- print_timestamp(stderr);
- fprintf(stderr, "No check results in 20 seconds, "
- "assuming error state, terminating\n");
- exit(1);
- }
- queue_add(buffer);
- queue_additions = 0;
- queue_bytes = 0;
- } while(1);
- }
- static void print_timestamp(FILE *output)
- {
- time_t now;
- struct tm *ltm;
- char timestr[1024], *timeasc;
- now = time(NULL);
- ltm = localtime(&now);
- timeasc = asctime(ltm);
- strcpy(timestr, timeasc);
- timestr[strlen(timestr)-1] = 0;
- fprintf(output, "[%s] ", timestr);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement