[monit-dev] Monit control via unix socket

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[monit-dev] Monit control via unix socket

Andea Bonomi
Hello,
I have developed a patch for interacting with monit not only through
tcp/ip but also via socket.
We use monit to start/stop all the services in our linux-based network
products. Sometimes, reconfiguring the system
the network is not available, so some services are not started/restarted.
(Yes, also the loopback interface sometimes is not available...)
With this patch is it possible  to specify a unix socket to be used for
the comunication between the monitor clients and the server.
The unix socket is (obviously) only local and can be used only my the root.
An example of configuration for (monitrc) is the following:

set httpd port 2812 and
       use address localhost
       unixsocket "/var/run/monit.sock"

Here we enable the httpd server on port 2812 on localhost and also on
the socke named "/var/run/monit.sock".

I hope this feature could be useful to someone.
Thank you for the good job on monit!
Cheers,
Andrea

--
--
:: e n d i a n
:: security with passion

:: Andrea Bonomi
:: Senior Software Engineer



Index: src/http/engine.c
===================================================================
--- src/http/engine.c    (revision 396)
+++ src/http/engine.c    (working copy)
@@ -129,6 +129,8 @@
    unsigned long mask;
  };

+static int myUnixServerSocket= 0;
+static volatile int stoppedUnix= FALSE;

  /* --------------------------------------------------------------
Prototypes */

@@ -656,7 +658,7 @@
      goto error;
    }

-  if(! authenticate(in.sin_addr)) {
+  if((in.sin_family != AF_UNIX) && (! authenticate(in.sin_addr))) {
      goto error;
    }

@@ -688,3 +690,61 @@

  }

+
+
+/* ------------------------------------------------------------- Unix
Socket */
+
+
+/**
+ * Start the HTTPD server on unix socket
+ * @param backlog The maximum length of the incomming connection queue
+ * @param bindAddr the socket path the server will bind to
+ */
+void start_httpd_unix(int backlog, char *socketPath) {
+
+  Socket_T S= NULL;
+
+  stoppedUnix= Run.stopped;
+
+  if((myUnixServerSocket= create_server_socket(0, backlog, socketPath))
< 0) {
+
+    LogError("http server: Could not create a server socket at %s -- %s\n",
+    socketPath, STRERROR);
+
+    LogError("monit HTTP server not available\n");
+
+    if(Run.init) {
+
+      sleep(1);
+      kill_daemon(SIGTERM);
+
+    }
+
+  } else {
+
+    while(! stoppedUnix) {
+
+      if(!(S= socket_producer(myUnixServerSocket, 0, NULL))) {
+           continue;
+      }
+
+      http_processor(S);
+
+    }
+
+    close_socket(myUnixServerSocket);
+
+  }
+
+}
+
+
+/**
+ * Stop the HTTPD server on unix socket
+ */
+void stop_httpd_unix() {
+
+  stoppedUnix = TRUE;
+
+}
+
Index: src/http/engine.h
===================================================================
--- src/http/engine.h    (revision 396)
+++ src/http/engine.h    (working copy)
@@ -53,5 +53,7 @@
  int has_hosts_allow();
  void destroy_hosts_allow();

+void start_httpd_unix(int backlog, char *socketPath);
+void stop_httpd_unix();

  #endif
Index: src/http.c
===================================================================
--- src/http.c    (revision 396)
+++ src/http.c    (working copy)
@@ -62,9 +62,11 @@

  /* Private prototypes */
  static void *thread_wrapper(void *arg);
+static void *thread_wrapper_unix(void *arg);

  /* The HTTP Thread */
  static pthread_t thread;
+static pthread_t threadUnix;

  static volatile int running = FALSE;

@@ -130,6 +132,17 @@
        LogInfo("%s HTTP server stopped\n", prog);
        running = FALSE;
      }
+
+    if (Run.bind_path) {
+      LogInfo("Shutting down %s server on %s\n", prog, Run.bind_path);
+      stop_httpd_unix();
+      if( (status= pthread_join(threadUnix, NULL)) != 0) {
+        LogError("%s: Failed to stop the server on %s. Thread error --
%s.\n",
+            prog, Run.bind_path, strerror(status));
+      } else {
+        LogInfo("%s server on %s stopped\n", prog, Run.bind_path);
+      }
+    }
      break;

    case START_HTTP:
@@ -142,6 +155,15 @@
        LogInfo("%s HTTP server started\n", prog);
        running = TRUE;
      }
+    if (Run.bind_path) {
+      LogInfo("Starting %s server at %s\n", prog, Run.bind_path);
+      if( (status= pthread_create(&threadUnix, NULL,
thread_wrapper_unix, NULL)) != 0) {
+        LogError("%s: Failed to create the server on %s. Thread error
-- %s.\n",
+          prog, Run.bind_path, strerror(status));
+      } else {
+        LogInfo("%s server on %s started\n", prog, Run.bind_path);
+      }
+    }
      break;

    default:
@@ -171,4 +193,17 @@

  }

+static void *thread_wrapper_unix(void *arg) {
+
+  sigset_t ns;
+
+  /* Block collective signals in the http thread. The http server is
+   * taken down gracefully by signaling the main monit thread */
+  set_signal_block(&ns, NULL);
+  start_httpd_unix(1024, Run.bind_path);
+
+  return NULL;
+
+}
+

Index: src/control.c
===================================================================
--- src/control.c    (revision 396)
+++ src/control.c    (working copy)
@@ -105,7 +105,7 @@
      return FALSE;
    }

-  s = socket_new(Run.bind_addr ? Run.bind_addr : "localhost",
Run.httpdport, SOCKET_TCP, Run.httpdssl, NET_TIMEOUT);
+  s = socket_new(Run.bind_path?Run.bind_path:Run.bind_addr ?
Run.bind_addr : "localhost", Run.httpdport, SOCKET_TCP, Run.httpdssl,
NET_TIMEOUT);
    if (!s) {
      LogError("%s: Cannot connect to the monit daemon. Did you start it
with http support?\n", prog);
      return FALSE;
Index: src/status.c
===================================================================
--- src/status.c    (revision 396)
+++ src/status.c    (working copy)
@@ -90,7 +90,7 @@
      return status;
    }

-  if(!(sock= socket_new(Run.bind_addr?Run.bind_addr:"localhost",
Run.httpdport,
+  if(!(sock=
socket_new(Run.bind_path?Run.bind_path:Run.bind_addr?Run.bind_addr:"localhost",
Run.httpdport,
                          SOCKET_TCP, Run.httpdssl, NET_TIMEOUT))) {
      LogError("%s: error connecting to the monit daemon\n", prog);
      return status;
Index: src/p.y
===================================================================
--- src/p.y    (revision 396)
+++ src/p.y    (working copy)
@@ -693,6 +693,7 @@
                  ;

  bindaddress     : ADDRESS STRING { Run.bind_addr = $2; }
+                | UNIXSOCKET PATH { Run.bind_path = $2; }
                  ;

  pemfile         : PEMFILE PATH {
Index: src/net.c
===================================================================
--- src/net.c    (revision 396)
+++ src/net.c    (working copy)
@@ -370,7 +370,44 @@
    int status;
    int flag = 1;
    struct sockaddr_in myaddr;
+
+  if((bindAddr) && (strlen(bindAddr) > 0) && (bindAddr[0] == '/')) { /*
UNIX socket */
+    struct sockaddr_un serveraddr;

+    LogInfo("Starting %s HTTP server on socket %s\n", prog, bindAddr);
+
+    if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+      LogError("%s: Cannot create unix socket -- %s\n", prog, STRERROR);
+      return -1;
+    }
+
+    memset(&serveraddr, 0, sizeof(serveraddr));
+    serveraddr.sun_family = AF_UNIX;
+    strcpy(serveraddr.sun_path, bindAddr);
+
+    if(! set_noblock(s))
+      goto error;
+
+    if(fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
+      LogError("%s: Cannot set close on exec option -- %s\n", prog,
STRERROR);
+      goto error;
+    }
+
+    unlink(bindAddr); /* Remove any old socket */
+    if(bind(s, (struct sockaddr *)&serveraddr, sizeof(struct
sockaddr_in)) < 0) {
+      LogError("%s: Cannot bind -- %s\n", prog, STRERROR);
+      goto error;
+    }
+    chmod(bindAddr, 0600);
+
+    if(listen(s, backlog) < 0) {
+      LogError("%s: Cannot listen -- %s\n", prog, STRERROR);
+      goto error;
+    }
+
+    return s;
+  }
+
    if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
      LogError("%s: Cannot create socket -- %s\n", prog, STRERROR);
      return -1;
Index: src/socket.c
===================================================================
--- src/socket.c    (revision 396)
+++ src/socket.c    (working copy)
@@ -169,6 +169,32 @@
    }
    ASSERT(timeout>0);

+  if ((host) && (strlen(host) >0) && (host[0] == '/')) {
+    if((s= create_unix_socket(host, timeout)) != -1) {
+
+      Socket_T S= NULL;
+
+      NEW(S);
+      S->socket= s;
+      S->length= 0;
+      S->offset= 0;
+      S->port= port;
+      S->type= proto;
+      S->timeout= timeout;
+      S->host= xstrdup(host);
+      S->connection_type= TYPE_LOCAL;
+
+      if(ssl.use_ssl && !socket_switch2ssl(S, ssl)) {
+        socket_free(&S);
+        return NULL;
+      }
+
+      return S;
+    }
+
+    return NULL;
+  }
+
    if((s= create_socket(host, port, proto, timeout)) != -1) {

      Socket_T S= NULL;
Index: src/monit.h
===================================================================
--- src/monit.h    (revision 396)
+++ src/monit.h    (working copy)
@@ -828,6 +828,7 @@
    int  facility;              /** The facility to use when running
openlog() */
    int  doprocess;                 /**< TRUE if process status engine
is used */
    char *bind_addr;                  /**< The address monit http will
bind to */
+  char *bind_path;        /**< The unix socket path  monit http will
bind to */
    volatile int  doreload;    /**< TRUE if a monit daemon should
reinitialize */
    volatile int  dowakeup;  /**< TRUE if a monit daemon was wake up by
signal */
    int  doaction;             /**< TRUE if some service(s) has action
pending */


_______________________________________________
monit-dev mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/monit-dev