sync'ing up for 3.0alpha20 release
[kai/samba.git] / source3 / nsswitch / winbindd.c
index a2313d6f7366e4a927cef127423e52963f67f744..bb4a1b78ec5509aec5fa40e0468b6e6e30c064a1 100644 (file)
@@ -4,6 +4,7 @@
    Winbind daemon for ntdom nss module
 
    Copyright (C) by Tim Potter 2000, 2001
+   Copyright (C) Andrew Tridgell 2002
    
    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
 
 /* List of all connected clients */
 
-struct winbindd_cli_state *client_list;
+static struct winbindd_cli_state *client_list;
 static int num_clients;
-BOOL opt_nocache;
+BOOL opt_nocache = False;
+BOOL opt_dual_daemon = False;
 
 /* Reload configuration */
 
@@ -221,6 +223,7 @@ static struct dispatch_table dispatch_table[] = {
        { WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" },
        { WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" },
        { WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" },
+       { WINBINDD_GETGRLST, winbindd_getgrent, "GETGRLST" },
 
        /* PAM auth functions */
 
@@ -255,6 +258,11 @@ static struct dispatch_table dispatch_table[] = {
        { WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" },
        { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
 
+       /* WINS functions */
+
+       { WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" },
+       { WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" },
+
        /* End of list */
 
        { WINBINDD_NUM_CMDS, NULL, "NONE" }
@@ -360,12 +368,16 @@ static void remove_client(struct winbindd_cli_state *state)
        }
 }
 
+
 /* Process a complete received packet from a client */
 
-static void process_packet(struct winbindd_cli_state *state)
+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->pid = state->request.pid;
        
        process_request(state);
@@ -374,11 +386,16 @@ static void process_packet(struct winbindd_cli_state *state)
        
        state->read_buf_len = 0;
        state->write_buf_len = sizeof(struct winbindd_response);
+
+       /* we might need to send it to the dual daemon */
+       if (opt_dual_daemon) {
+               dual_send_request(state);
+       }
 }
 
 /* Read some data from a client connection */
 
-static void client_read(struct winbindd_cli_state *state)
+void winbind_client_read(struct winbindd_cli_state *state)
 {
        int n;
     
@@ -506,6 +523,10 @@ static void process_loop(int accept_sock)
                int maxfd = accept_sock, selret;
                struct timeval timeout;
 
+               /* Handle messages */
+
+               message_dispatch();
+
                /* Free up temporary memory */
 
                lp_talloc_free();
@@ -520,6 +541,10 @@ static void process_loop(int accept_sock)
                timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
                timeout.tv_usec = 0;
 
+               if (opt_dual_daemon) {
+                       maxfd = dual_select_setup(&w_fds, maxfd);
+               }
+
                /* Set up client readers and writers */
 
                state = client_list;
@@ -574,6 +599,10 @@ static void process_loop(int accept_sock)
 
                if (selret > 0) {
 
+                       if (opt_dual_daemon) {
+                               dual_select(&w_fds);
+                       }
+
                        if (FD_ISSET(accept_sock, &r_fds))
                                new_connection(accept_sock);
             
@@ -587,7 +616,7 @@ static void process_loop(int accept_sock)
                     
                                        /* Read data */
                     
-                                       client_read(state);
+                                       winbind_client_read(state);
 
                                        /* 
                                         * If we have the start of a
@@ -599,8 +628,8 @@ static void process_loop(int accept_sock)
 
                                        if (state->read_buf_len >= sizeof(uint32)
                                            && *(uint32 *) &state->request != sizeof(state->request)) {
-                                               DEBUG(0,("process_loop: Invalid request size (%d) send, should be (%d)\n",
-                                                               *(uint32 *) &state->request, sizeof(state->request)));
+                                               DEBUG(0,("process_loop: Invalid request size from pid %d: %d bytes sent, should be %d\n",
+                                                               state->request.pid, *(uint32 *) &state->request, sizeof(state->request)));
 
                                                remove_client(state);
                                                break;
@@ -611,7 +640,7 @@ static void process_loop(int accept_sock)
                     
                                        if (state->read_buf_len == 
                                            sizeof(state->request)) {
-                                               process_packet(state);
+                                               winbind_process_packet(state);
                                        }
                                }
                 
@@ -622,6 +651,10 @@ static void process_loop(int accept_sock)
                        }
                }
 
+#if 0
+               winbindd_check_cache_size(time(NULL));
+#endif
+
                /* Check signal handling things */
 
                if (do_sigterm)
@@ -643,6 +676,64 @@ 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)
+{
+       load_interfaces();
+
+       if (!secrets_init()) {
+
+               DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
+               return 1;
+
+       }
+
+       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();
+
+       ZERO_STRUCT(server_state);
+
+       /* Winbind daemon initialisation */
+
+       if (!winbindd_param_init())
+               return 1;
+
+       if (!winbindd_idmap_init())
+               return 1;
+
+       /* Unblock all signals we are interested in as they may have been
+          blocked by the parent process. */
+
+       BlockSignals(False, SIGINT);
+       BlockSignals(False, SIGQUIT);
+       BlockSignals(False, SIGTERM);
+       BlockSignals(False, SIGUSR1);
+       BlockSignals(False, SIGUSR2);
+       BlockSignals(False, SIGHUP);
+
+       /* Setup signal handlers */
+       
+       CatchSignal(SIGINT, termination_handler);      /* Exit on these sigs */
+       CatchSignal(SIGQUIT, termination_handler);
+       CatchSignal(SIGTERM, termination_handler);
+
+       CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
+
+       CatchSignal(SIGUSR2, sigusr2_handler);         /* Debugging sigs */
+       CatchSignal(SIGHUP, sighup_handler);
+
+       return 0;
+}
+
+
 /* Main function */
 
 struct winbindd_state server_state;   /* Server state information */
@@ -652,13 +743,14 @@ static void usage(void)
 {
        printf("Usage: winbindd [options]\n");
        printf("\t-i                interactive mode\n");
+       printf("\t-B                dual daemon mode\n");
        printf("\t-n                disable cacheing\n");
        printf("\t-d level          set debug level\n");
        printf("\t-s configfile     choose smb.conf location\n");
        printf("\t-h                show this help message\n");
 }
 
-int main(int argc, char **argv)
+ int main(int argc, char **argv)
 {
        extern BOOL AllowDebugChange;
        extern pstring global_myname;
@@ -670,8 +762,9 @@ int main(int argc, char **argv)
        int opt;
 
        /* glibc (?) likes to print "User defined signal 1" and exit if a
-          SIGUSR2 is received before a handler is installed */
+          SIGUSR[12] is received before a handler is installed */
 
+       CatchSignal(SIGUSR1, SIG_IGN);
        CatchSignal(SIGUSR2, SIG_IGN);
 
        fault_setup((void (*)(void *))fault_quit );
@@ -695,7 +788,7 @@ int main(int argc, char **argv)
 
        /* Initialise samba/rpc client stuff */
 
-       while ((opt = getopt(argc, argv, "id:s:nh")) != EOF) {
+       while ((opt = getopt(argc, argv, "id:s:nhB")) != EOF) {
                switch (opt) {
 
                        /* Don't become a daemon */
@@ -703,6 +796,11 @@ int main(int argc, char **argv)
                        interactive = True;
                        break;
 
+                       /* dual daemon system */
+               case 'B':
+                       opt_dual_daemon = True;
+                       break;
+
                        /* disable cacheing */
                case 'n':
                        opt_nocache = True;
@@ -742,8 +840,6 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       pidfile_create("winbindd");
-
        /* Setup names. */
 
        if (!*global_myname) {
@@ -757,8 +853,11 @@ int main(int argc, char **argv)
 
         fstrcpy(global_myworkgroup, lp_workgroup());
 
-       if (!interactive)
+       if (!interactive) {
                become_daemon();
+               pidfile_create("winbindd");
+       }
+
 
 #if HAVE_SETPGID
        /*
@@ -769,46 +868,22 @@ int main(int argc, char **argv)
                setpgid( (pid_t)0, (pid_t)0);
 #endif
 
-       load_interfaces();
-
-       secrets_init();
-
-       /* 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();
-
-       ZERO_STRUCT(server_state);
-
-       /* Winbind daemon initialisation */
-
-       if (!winbindd_param_init())
-               return 1;
+       if (opt_dual_daemon) {
+               do_dual_daemon();
+       }
 
-       if (!winbindd_idmap_init())
+       if (winbind_setup_common() != 0) {
                return 1;
+       }
 
-       /* Unblock all signals we are interested in as they may have been
-          blocked by the parent process. */
-
-       BlockSignals(False, SIGINT);
-       BlockSignals(False, SIGQUIT);
-       BlockSignals(False, SIGTERM);
-       BlockSignals(False, SIGUSR2);
-       BlockSignals(False, SIGHUP);
-
-       /* Setup signal handlers */
-       
-       CatchSignal(SIGINT, termination_handler);      /* Exit on these sigs */
-       CatchSignal(SIGQUIT, termination_handler);
-       CatchSignal(SIGTERM, termination_handler);
+       /* Initialise messaging system */
 
-       CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
-       CatchSignal(SIGUSR1, SIG_IGN);                 /* Samba messages */
+       if (!message_init()) {
+               DEBUG(0, ("unable to initialise messaging system\n"));
+               exit(1);
+       }
 
-       CatchSignal(SIGUSR2, sigusr2_handler);         /* Debugging sigs */
-       CatchSignal(SIGHUP, sighup_handler);
+       register_msg_pool_usage();
 
        /* Create UNIX domain socket */