Merge from HEAD:
[tprouty/samba.git] / source / nsswitch / winbindd.c
index a937f06639eabd1abd60b2cc9a2f738229baf126..b70a4dd3b4039fda8b8989930f803cb626b1288e 100644 (file)
@@ -3,7 +3,7 @@
 
    Winbind daemon for ntdom nss module
 
-   Copyright (C) by Tim Potter 2000, 2001
+   Copyright (C) by Tim Potter 2000-2002
    Copyright (C) Andrew Tridgell 2002
    
    This program is free software; you can redistribute it and/or modify
 
 #include "winbindd.h"
 
-/* List of all connected clients */
-
-static struct winbindd_cli_state *client_list;
-static int num_clients;
 BOOL opt_nocache = False;
 BOOL opt_dual_daemon = False;
 
@@ -62,6 +58,25 @@ static BOOL reload_services_file(BOOL test)
        return(ret);
 }
 
+/*******************************************************************
+ Print out all talloc memory info.
+********************************************************************/
+
+void return_all_talloc_info(int msg_type, pid_t src_pid, void *buf, size_t len)
+{
+       TALLOC_CTX *ctx = talloc_init("info context");
+       char *info = NULL;
+
+       if (!ctx)
+               return;
+
+       info = talloc_describe_all(ctx);
+       if (info)
+               DEBUG(10,(info));
+       message_send_pid(src_pid, MSG_TALLOC_USAGE, info, info ? strlen(info) + 1: 0, True);
+       talloc_destroy(ctx);
+}
+
 #if DUMP_CORE
 
 /**************************************************************************** **
@@ -121,11 +136,11 @@ static void winbindd_status(void)
 
        /* Print client state information */
        
-       DEBUG(0, ("\t%d clients currently active\n", num_clients));
+       DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
        
-       if (DEBUGLEVEL >= 2 && num_clients) {
+       if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
                DEBUG(2, ("\tclient list:\n"));
-               for(tmp = client_list; tmp; tmp = tmp->next) {
+               for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
                        DEBUG(2, ("\t\tpid %d, sock %d, rbl %d, wbl %d\n",
                                  tmp->pid, tmp->sock, tmp->read_buf_len, 
                                  tmp->write_buf_len));
@@ -189,18 +204,10 @@ static void sighup_handler(int signum)
        sys_select_signal();
 }
 
-/* Create winbindd socket */
-
-static int create_sock(void)
-{
-       return create_pipe_sock( WINBINDD_SOCKET_DIR,
-                                WINBINDD_SOCKET_NAME, 0755);
-}
-
 struct dispatch_table {
        enum winbindd_cmd cmd;
        enum winbindd_result (*fn)(struct winbindd_cli_state *state);
-       char *winbindd_cmd_name;
+       const char *winbindd_cmd_name;
 };
 
 static struct dispatch_table dispatch_table[] = {
@@ -257,6 +264,7 @@ static struct dispatch_table dispatch_table[] = {
        { WINBINDD_INFO, winbindd_info, "INFO" },
        { WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" },
        { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
+       { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
 
        /* WINS functions */
 
@@ -303,7 +311,7 @@ static void process_request(struct winbindd_cli_state *state)
 
 /* Process a new connection by adding it to the client connection list */
 
-static void new_connection(int accept_sock)
+static void new_connection(int listen_sock)
 {
        struct sockaddr_un sunaddr;
        struct winbindd_cli_state *state;
@@ -315,7 +323,7 @@ static void new_connection(int accept_sock)
        len = sizeof(sunaddr);
 
        do {
-               sock = accept(accept_sock, (struct sockaddr *)&sunaddr, &len);
+               sock = accept(listen_sock, (struct sockaddr *)&sunaddr, &len);
        } while (sock == -1 && errno == EINTR);
 
        if (sock == -1)
@@ -334,8 +342,7 @@ static void new_connection(int accept_sock)
        
        /* Add to connection list */
        
-       DLIST_ADD(client_list, state);
-       num_clients++;
+       winbindd_add_client(state);
 }
 
 /* Remove a client connection from client connection list */
@@ -362,9 +369,8 @@ static void remove_client(struct winbindd_cli_state *state)
                
                /* Remove from list and free */
                
-               DLIST_REMOVE(client_list, state);
+               winbindd_remove_client(state);
                SAFE_FREE(state);
-               num_clients--;
        }
 }
 
@@ -376,7 +382,7 @@ void winbind_process_packet(struct winbindd_cli_state *state)
        /* Process request */
        
        /* Ensure null termination of entire request */
-       state->request.domain[sizeof(state->request.domain)-1]='\0';
+       state->request.null_term = '\0';
 
        state->pid = state->request.pid;
        
@@ -401,13 +407,9 @@ void winbind_client_read(struct winbindd_cli_state *state)
     
        /* Read data */
 
-       do {
-
-               n = read(state->sock, state->read_buf_len + 
-                        (char *)&state->request, 
-                        sizeof(state->request) - state->read_buf_len);
-
-       } while (n == -1 && errno == EINTR);
+       n = sys_read(state->sock, state->read_buf_len + 
+                (char *)&state->request, 
+                sizeof(state->request) - state->read_buf_len);
        
        DEBUG(10,("client_read: read %d bytes. Need %d more for a full request.\n", n, sizeof(state->request) - n - state->read_buf_len ));
 
@@ -453,9 +455,7 @@ static void client_write(struct winbindd_cli_state *state)
                        state->write_buf_len;
        }
        
-       do {
-               num_written = write(state->sock, data, state->write_buf_len);
-       } while (num_written == -1 && errno == EINTR);
+       num_written = sys_write(state->sock, data, state->write_buf_len);
        
        DEBUG(10,("client_write: wrote %d bytes.\n", num_written ));
 
@@ -513,20 +513,24 @@ static void client_write(struct winbindd_cli_state *state)
    simultaneous connections while remaining impervious to many denial of
    service attacks. */
 
-static void process_loop(int accept_sock)
+static void process_loop(void)
 {
        /* We'll be doing this a lot */
 
        while (1) {
                struct winbindd_cli_state *state;
                fd_set r_fds, w_fds;
-               int maxfd = accept_sock, selret;
+               int maxfd, listen_sock, selret;
                struct timeval timeout;
 
                /* Handle messages */
 
                message_dispatch();
 
+               /* rescan the trusted domains list. This must be done
+                  regularly to cope with transitive trusts */
+               rescan_trusted_domains();
+
                /* Free up temporary memory */
 
                lp_talloc_free();
@@ -534,9 +538,18 @@ static void process_loop(int accept_sock)
 
                /* Initialise fd lists for select() */
 
+               listen_sock = open_winbindd_socket();
+
+               if (listen_sock == -1) {
+                       perror("open_winbind_socket");
+                       exit(1);
+               }
+
+               maxfd = listen_sock;
+
                FD_ZERO(&r_fds);
                FD_ZERO(&w_fds);
-               FD_SET(accept_sock, &r_fds);
+               FD_SET(listen_sock, &r_fds);
 
                timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
                timeout.tv_usec = 0;
@@ -547,7 +560,7 @@ static void process_loop(int accept_sock)
 
                /* Set up client readers and writers */
 
-               state = client_list;
+               state = winbindd_client_list();
 
                while (state) {
 
@@ -603,12 +616,13 @@ static void process_loop(int accept_sock)
                                dual_select(&w_fds);
                        }
 
-                       if (FD_ISSET(accept_sock, &r_fds))
-                               new_connection(accept_sock);
+                       if (FD_ISSET(listen_sock, &r_fds))
+                               new_connection(listen_sock);
             
                        /* Process activity on client connections */
             
-                       for (state = client_list; state; state = state->next) {
+                       for (state = winbindd_client_list(); state; 
+                            state = state->next) {
                 
                                /* Data available for reading */
                 
@@ -662,7 +676,9 @@ static void process_loop(int accept_sock)
 
                if (do_sighup) {
 
-                       /* Flush winbindd cache */
+                       DEBUG(3, ("got SIGHUP\n"));
+                        /* Flush various caches */
 
                        flush_caches();
                        reload_services_file(True);
@@ -680,34 +696,29 @@ static void process_loop(int accept_sock)
 /*
   these are split out from the main winbindd for use by the background daemon
  */
-int winbind_setup_common(void)
+BOOL winbind_setup_common(void)
 {
-       load_interfaces();
+       load_interfaces();
 
        if (!secrets_init()) {
 
                DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
-               return 1;
-
+               return False;
        }
 
        namecache_enable();     /* Enable netbios namecache */
 
-       /* Get list of domains we look up requests for.  This includes the
-          domain which we are a member of as well as any trusted
-          domains. */ 
-
-       init_domain_list();
+       /* Check winbindd parameters are valid */
 
        ZERO_STRUCT(server_state);
 
-       /* Winbind daemon initialisation */
-
        if (!winbindd_param_init())
-               return 1;
+               return False;
+
+       /* Winbind daemon initialisation */
 
        if (!winbindd_idmap_init())
-               return 1;
+               return False;
 
        /* Unblock all signals we are interested in as they may have been
           blocked by the parent process. */
@@ -730,7 +741,7 @@ int winbind_setup_common(void)
        CatchSignal(SIGUSR2, sigusr2_handler);         /* Debugging sigs */
        CatchSignal(SIGHUP, sighup_handler);
 
-       return 0;
+       return True;
 }
 
 
@@ -742,6 +753,8 @@ struct winbindd_state server_state;   /* Server state information */
 static void usage(void)
 {
        printf("Usage: winbindd [options]\n");
+        printf("\t-F                daemon in foreground mode\n");
+        printf("\t-S                log to stdout\n");
        printf("\t-i                interactive mode\n");
        printf("\t-B                dual daemon mode\n");
        printf("\t-n                disable cacheing\n");
@@ -753,12 +766,10 @@ static void usage(void)
  int main(int argc, char **argv)
 {
        extern BOOL AllowDebugChange;
-       extern pstring global_myname;
-       extern fstring global_myworkgroup;
-       extern BOOL append_log;
        pstring logfile;
-       int accept_sock;
        BOOL interactive = False;
+       BOOL Fork = True;
+       BOOL log_stdout = False;
        int opt;
 
        /* glibc (?) likes to print "User defined signal 1" and exit if a
@@ -769,11 +780,6 @@ static void usage(void)
 
        fault_setup((void (*)(void *))fault_quit );
 
-       /* Append to log file by default as we are a single process daemon
-          program. */
-
-       append_log = True;
-
        snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE);
        lp_set_logfile(logfile);
 
@@ -788,12 +794,20 @@ static void usage(void)
 
        /* Initialise samba/rpc client stuff */
 
-       while ((opt = getopt(argc, argv, "id:s:nhB")) != EOF) {
+       while ((opt = getopt(argc, argv, "FSid:s:nhB")) != EOF) {
                switch (opt) {
 
+               case 'F':
+                       Fork = False;
+                       break;
+               case 'S':
+                       log_stdout = True;
+                       break;
                        /* Don't become a daemon */
                case 'i':
                        interactive = True;
+                       log_stdout = True;
+                       Fork = False;
                        break;
 
                        /* dual daemon system */
@@ -827,9 +841,15 @@ static void usage(void)
                }
        }
 
+       if (log_stdout && Fork) {
+               printf("Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n");
+               usage();
+               exit(1);
+       }
+
        snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE);
        lp_set_logfile(logfile);
-       setup_logging("winbindd", interactive);
+       setup_logging("winbindd", log_stdout);
        reopen_logs();
 
        DEBUG(1, ("winbindd version %s started.\n", VERSION ) );
@@ -842,19 +862,14 @@ static void usage(void)
 
        /* Setup names. */
 
-       if (!*global_myname) {
-               char *p;
+       if (!init_names())
+               exit(1);
 
-               fstrcpy(global_myname, myhostname());
-               p = strchr(global_myname, '.');
-               if (p)
-                       *p = 0;
+       if (!interactive) {
+               become_daemon(Fork);
+               pidfile_create("winbindd");
        }
 
-        fstrcpy(global_myworkgroup, lp_workgroup());
-
-       if (!interactive)
-               become_daemon();
 
 #if HAVE_SETPGID
        /*
@@ -865,12 +880,12 @@ static void usage(void)
                setpgid( (pid_t)0, (pid_t)0);
 #endif
 
-       if (opt_dual_daemon) {
-               do_dual_daemon();
+       if (!winbind_setup_common()) {
+               return 1;
        }
 
-       if (winbind_setup_common() != 0) {
-               return 1;
+       if (opt_dual_daemon) {
+               do_dual_daemon();
        }
 
        /* Initialise messaging system */
@@ -881,21 +896,11 @@ static void usage(void)
        }
 
        register_msg_pool_usage();
-
-       /* Create UNIX domain socket */
-       
-       if ((accept_sock = create_sock()) == -1) {
-               DEBUG(0, ("failed to create socket\n"));
-               return 1;
-       }
-
-       /* Only create the pidfile when we're ready to receive requests. */
-       if (!interactive)
-               pidfile_create("winbindd");
+       message_register(MSG_REQ_TALLOC_USAGE, return_all_talloc_info);
 
        /* Loop waiting for requests */
 
-       process_loop(accept_sock);
+       process_loop();
 
        uni_group_cache_shutdown();
        return 0;