r26401: Don't cache interfaces context in libnetif.
[samba.git] / source4 / web_server / web_server.c
index d8e41a1ff1e768d17f0ad47e60d374765bf18324..0fdb0bfb4ffa521c3fe88cbeaa306d3cf7a5960e 100644 (file)
@@ -7,7 +7,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "lib/events/events.h"
 #include "system/filesys.h"
 #include "system/network.h"
-#include "netif/netif.h"
+#include "lib/socket/netif.h"
 #include "lib/tls/tls.h"
+#include "param/param.h"
 
 /* don't allow connections to hang around forever */
-#define HTTP_TIMEOUT 30
+#define HTTP_TIMEOUT 120
 
 /*
   destroy a web connection
 */
-static int websrv_destructor(void *ptr)
+static int websrv_destructor(struct websrv_context *web)
 {
-       struct websrv_context *web = talloc_get_type(ptr, struct websrv_context);
        if (web->output.fd != -1) {
                close(web->output.fd);
        }
@@ -76,17 +75,17 @@ static void websrv_recv(struct stream_connection *conn, uint16_t flags)
        DATA_BLOB b;
 
        /* not the most efficient http parser ever, but good enough for us */
-       status = tls_socket_recv(web->tls, buf, sizeof(buf), &nread);
+       status = socket_recv(conn->socket, buf, sizeof(buf), &nread);
        if (NT_STATUS_IS_ERR(status)) goto failed;
        if (!NT_STATUS_IS_OK(status)) return;
 
-       status = data_blob_append(web, &web->input.partial, buf, nread);
-       if (!NT_STATUS_IS_OK(status)) goto failed;
+       if (!data_blob_append(web, &web->input.partial, buf, nread))
+               goto failed;
 
        /* parse any lines that are available */
        b = web->input.partial;
        while (!web->input.end_of_headers &&
-              (p=memchr(b.data, '\n', b.length))) {
+              (p=(uint8_t *)memchr(b.data, '\n', b.length))) {
                const char *line = (const char *)b.data;
                *p = 0;
                if (p != b.data && p[-1] == '\r') {
@@ -123,7 +122,7 @@ static void websrv_recv(struct stream_connection *conn, uint16_t flags)
                 while inside http_process_input(), but we must not
                 destroy the stack variables being used by that
                 rendering process when we handle the timeout. */
-               talloc_reference(web->task, web);
+               if (!talloc_reference(web->task, web)) goto failed;
                http_process_input(web);
                talloc_unlink(web->task, web);
        }
@@ -149,7 +148,7 @@ static void websrv_send(struct stream_connection *conn, uint16_t flags)
        b.data += web->output.nsent;
        b.length -= web->output.nsent;
 
-       status = tls_socket_send(web->tls, &b, &nsent);
+       status = socket_send(conn->socket, &b, &nsent);
        if (NT_STATUS_IS_ERR(status)) {
                stream_terminate_connection(web->conn, "socket_send: failed");
                return;
@@ -183,8 +182,6 @@ static void websrv_send(struct stream_connection *conn, uint16_t flags)
 
        if (web->output.content.length == web->output.nsent && 
            web->output.fd == -1) {
-               talloc_free(web->tls);
-               web->tls = NULL;
                stream_terminate_connection(web->conn, "websrv_send: finished sending");
        }
 }
@@ -197,6 +194,7 @@ static void websrv_accept(struct stream_connection *conn)
        struct task_server *task = talloc_get_type(conn->private, struct task_server);
        struct esp_data *edata = talloc_get_type(task->private, struct esp_data);
        struct websrv_context *web;
+       struct socket_context *tls_socket;
 
        web = talloc_zero(conn, struct websrv_context);
        if (web == NULL) goto failed;
@@ -211,9 +209,17 @@ static void websrv_accept(struct stream_connection *conn)
                        timeval_current_ofs(HTTP_TIMEOUT, 0),
                        websrv_timeout, web);
 
-       web->tls = tls_init_server(edata->tls_params, conn->socket, 
-                                  conn->event.fde, "GPHO", True);
-       if (web->tls == NULL) goto failed;
+       /* Overwrite the socket with a (possibly) TLS socket */
+       tls_socket = tls_init_server(edata->tls_params, conn->socket, 
+                                    conn->event.fde, "GPHO");
+       /* We might not have TLS, or it might not have initilised */
+       if (tls_socket) {
+               talloc_unlink(conn, conn->socket);
+               talloc_steal(conn, tls_socket);
+               conn->socket = tls_socket;
+       } else {
+               DEBUG(3, ("TLS not available for web_server connections\n"));
+       }
 
        return;
 
@@ -235,29 +241,37 @@ static const struct stream_server_ops web_stream_ops = {
 static void websrv_task_init(struct task_server *task)
 {
        NTSTATUS status;
-       uint16_t port = lp_web_port();
+       uint16_t port = lp_web_port(task->lp_ctx);
        const struct model_ops *model_ops;
 
+       task_server_set_title(task, "task[websrv]");
+
        /* run the web server as a single process */
        model_ops = process_model_byname("single");
        if (!model_ops) goto failed;
 
-       if (lp_interfaces() && lp_bind_interfaces_only()) {
-               int num_interfaces = iface_count();
+       if (lp_interfaces(task->lp_ctx) && lp_bind_interfaces_only(task->lp_ctx)) {
+               int num_interfaces;
                int i;
+               struct interface *ifaces;
+
+               load_interfaces(lp_interfaces(task->lp_ctx), &ifaces);
+
+               num_interfaces = iface_count(ifaces);
                for(i = 0; i < num_interfaces; i++) {
-                       const char *address = iface_n_ip(i);
+                       const char *address = iface_n_ip(ifaces, i);
                        status = stream_setup_socket(task->event_ctx, model_ops, 
                                                     &web_stream_ops, 
                                                     "ipv4", address, 
-                                                    &port, task);
+                                                    &port, lp_socket_options(task->lp_ctx), 
+                                                    task);
                        if (!NT_STATUS_IS_OK(status)) goto failed;
                }
        } else {
                status = stream_setup_socket(task->event_ctx, model_ops, 
                                             &web_stream_ops, 
-                                            "ipv4", lp_socket_address(), 
-                                            &port, task);
+                                            "ipv4", lp_socket_address(task->lp_ctx), 
+                                            &port, lp_socket_options(task->lp_ctx), task);
                if (!NT_STATUS_IS_OK(status)) goto failed;
        }
 
@@ -278,6 +292,7 @@ failed:
   listening on all configured sockets
 */
 static NTSTATUS websrv_init(struct event_context *event_context, 
+                           struct loadparm_context *lp_ctx,
                            const struct model_ops *model_ops)
 {      
        return task_server_startup(event_context, model_ops, websrv_task_init);