summaryrefslogtreecommitdiffstats
path: root/source/wrepld/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/wrepld/server.c')
-rw-r--r--source/wrepld/server.c757
1 files changed, 0 insertions, 757 deletions
diff --git a/source/wrepld/server.c b/source/wrepld/server.c
deleted file mode 100644
index 14d3e730f47..00000000000
--- a/source/wrepld/server.c
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Main SMB server routines
- Copyright (C) Jean François Micouleau 1998-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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- 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.
-*/
-
-#include "includes.h"
-#include "wins_repl.h"
-
-extern fstring global_myworkgroup;
-extern pstring global_myname;
-
-extern pstring user_socket_options;
-
-extern WINS_OWNER *global_wins_table;
-extern int partner_count;
-
-extern fd_set *listen_set;
-extern int listen_number;
-extern int *sock_array;
-
-extern TALLOC_CTX *mem_ctx;
-
-int wins_port = 42;
-
-/****************************************************************************
- when exiting, take the whole family
-****************************************************************************/
-static void *dflt_sig(void)
-{
- exit_server("caught signal");
- return NULL;
-}
-
-/****************************************************************************
- reload the services file
- **************************************************************************/
-BOOL reload_services(BOOL test)
-{
- BOOL ret;
-
- if (lp_loaded()) {
- pstring fname;
- pstrcpy(fname,lp_configfile());
- if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
- pstrcpy(dyn_CONFIGFILE,fname);
- test = False;
- }
- }
-
- reopen_logs();
-
- if (test && !lp_file_list_changed())
- return(True);
-
- ret = lp_load(dyn_CONFIGFILE,False,False,True);
-
-
- /* perhaps the config filename is now set */
- if (!test)
- reload_services(True);
-
- reopen_logs();
-
- load_interfaces();
-
- return(ret);
-}
-
-/****************************************************************************
- Catch a sighup.
-****************************************************************************/
-
-VOLATILE sig_atomic_t reload_after_sighup = False;
-
-static void sig_hup(int sig)
-{
- BlockSignals(True,SIGHUP);
- DEBUG(0,("Got SIGHUP\n"));
-
- sys_select_signal();
- reload_after_sighup = True;
- BlockSignals(False,SIGHUP);
-}
-
-#if DUMP_CORE
-/*******************************************************************
-prepare to dump a core file - carefully!
-********************************************************************/
-static BOOL dump_core(void)
-{
- char *p;
- pstring dname;
- pstrcpy(dname,lp_logfile());
- if ((p=strrchr_m(dname,'/'))) *p=0;
- pstrcat(dname,"/corefiles");
- mkdir(dname,0700);
- sys_chown(dname,getuid(),getgid());
- chmod(dname,0700);
- if (chdir(dname)) return(False);
- umask(~(0700));
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
- {
- struct rlimit rlp;
- getrlimit(RLIMIT_CORE, &rlp);
- rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
- setrlimit(RLIMIT_CORE, &rlp);
- getrlimit(RLIMIT_CORE, &rlp);
- DEBUG(3,("Core limits now %d %d\n",
- (int)rlp.rlim_cur,(int)rlp.rlim_max));
- }
-#endif
-#endif
-
-
- DEBUG(0,("Dumping core in %s\n",dname));
- abort();
- return(True);
-}
-#endif
-
-/****************************************************************************
-exit the server
-****************************************************************************/
-void exit_server(char *reason)
-{
- static int firsttime=1;
-
- if (!firsttime)
- exit(0);
- firsttime = 0;
-
- DEBUG(2,("Closing connections\n"));
-
- if (!reason) {
- int oldlevel = DEBUGLEVEL;
- DEBUGLEVEL = 10;
- DEBUGLEVEL = oldlevel;
- DEBUG(0,("===============================================================\n"));
-#if DUMP_CORE
- if (dump_core()) return;
-#endif
- }
-
- DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
- exit(0);
-}
-
-/****************************************************************************
- initialise connect, service and file structs
-****************************************************************************/
-static void init_structs(void )
-{
- /*
- * Set the machine NETBIOS name if not already
- * set from the config file.
- */
-
- if (!*global_myname) {
- char *p;
- fstrcpy( global_myname, myhostname() );
- p = strchr_m( global_myname, '.' );
- if (p)
- *p = 0;
- }
-
- strupper( global_myname );
-}
-
-/****************************************************************************
-usage on the program
-****************************************************************************/
-static void usage(char *pname)
-{
-
- d_printf("Usage: %s [-DaioPh?V] [-d debuglevel] [-l log basename] [-p port]\n", pname);
- d_printf(" [-O socket options] [-s services file]\n");
- d_printf("\t-D Become a daemon (default)\n");
- d_printf("\t-a Append to log file (default)\n");
- d_printf("\t-i Run interactive (not a daemon)\n" );
- d_printf("\t-o Overwrite log file, don't append\n");
- d_printf("\t-h Print usage\n");
- d_printf("\t-? Print usage\n");
- d_printf("\t-V Print version\n");
- d_printf("\t-d debuglevel Set the debuglevel\n");
- d_printf("\t-l log basename. Basename for log/debug files\n");
- d_printf("\t-p port Listen on the specified port\n");
- d_printf("\t-O socket options Socket options\n");
- d_printf("\t-s services file. Filename of services file\n");
- d_printf("\n");
-}
-
-/****************************************************************************
- Create an fd_set containing all the sockets in the subnet structures,
- plus the broadcast sockets.
-***************************************************************************/
-
-static BOOL create_listen_fdset(void)
-{
- int i;
- int num_interfaces = iface_count();
- int s;
-
- listen_set = (fd_set *)malloc(sizeof(fd_set));
- if(listen_set == NULL) {
- DEBUG(0,("create_listen_fdset: malloc fail !\n"));
- return True;
- }
-
-#ifdef HAVE_ATEXIT
- {
- static int atexit_set;
- if(atexit_set == 0) {
- atexit_set=1;
- }
- }
-#endif
-
- FD_ZERO(listen_set);
-
- if(lp_interfaces() && lp_bind_interfaces_only()) {
- /* We have been given an interfaces line, and been
- told to only bind to those interfaces. Create a
- socket per interface and bind to only these.
- */
-
- if(num_interfaces > FD_SETSIZE) {
- DEBUG(0,("create_listen_fdset: Too many interfaces specified to bind to. Number was %d max can be %d\n", num_interfaces, FD_SETSIZE));
- return False;
- }
-
- /* Now open a listen socket for each of the interfaces. */
- for(i = 0; i < num_interfaces; i++) {
- struct in_addr *ifip = iface_n_ip(i);
-
- if(ifip == NULL) {
- DEBUG(0,("create_listen_fdset: interface %d has NULL IP address !\n", i));
- continue;
- }
- s = open_socket_in(SOCK_STREAM, wins_port, 0, ifip->s_addr, True);
- if(s == -1)
- return False;
-
- /* ready to listen */
- set_socket_options(s,"SO_KEEPALIVE");
- set_socket_options(s,user_socket_options);
-
- if (listen(s, 5) == -1) {
- DEBUG(5,("listen: %s\n",strerror(errno)));
- close(s);
- return False;
- }
- add_fd_to_sock_array(s);
- FD_SET(s, listen_set);
- }
- } else {
- /* Just bind to 0.0.0.0 - accept connections from anywhere. */
- num_interfaces = 1;
-
- /* open an incoming socket */
- s = open_socket_in(SOCK_STREAM, wins_port, 0, interpret_addr(lp_socket_address()),True);
- if (s == -1)
- return(False);
-
- /* ready to listen */
- set_socket_options(s,"SO_KEEPALIVE");
- set_socket_options(s,user_socket_options);
-
- if (listen(s, 5) == -1) {
- DEBUG(0,("create_listen_fdset: listen: %s\n", strerror(errno)));
- close(s);
- return False;
- }
-
- add_fd_to_sock_array(s);
- FD_SET(s, listen_set);
- }
-
- return True;
-}
-
-/*******************************************************************
- read a packet from a socket and parse it, returning a packet ready
- to be used or put on the queue. This assumes a UDP socket
- ******************************************************************/
-static struct wins_packet_struct *read_wins_packet(int fd, int timeout)
-{
- struct wins_packet_struct *p;
- GENERIC_PACKET *q;
- struct BUFFER inbuf;
- ssize_t len=0;
- size_t total=0;
- ssize_t ret;
- BOOL ok = False;
-
- inbuf.buffer=NULL;
- inbuf.length=0;
- inbuf.offset=0;
-
- if(!grow_buffer(&inbuf, 4))
- return NULL;
-
- ok = (read(fd, inbuf.buffer,4) == 4);
- if (!ok)
- return NULL;
- len = smb_len(inbuf.buffer);
-
- if (len<=0)
- return NULL;
-
- if(!grow_buffer(&inbuf, len))
- return NULL;
-
- while (total < len) {
- ret = read(fd, inbuf.buffer + total + 4, len - total);
- if (ret == 0) {
- DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(len - total), strerror(errno) ));
- return NULL;
- }
- if (ret == -1) {
- DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(len - total), strerror(errno) ));
- return NULL;
- }
- total += ret;
- }
-
- q = (GENERIC_PACKET *)talloc(mem_ctx, sizeof(GENERIC_PACKET));
- p = (struct wins_packet_struct *)talloc(mem_ctx, sizeof(*p));
- if (q==NULL || p==NULL)
- return NULL;
-
- decode_generic_packet(&inbuf, q);
-
- q->fd=fd;
-
- p->next = NULL;
- p->prev = NULL;
- p->stop_packet = False;
- p->timestamp = time(NULL);
- p->fd = fd;
- p->packet=q;
-
- return p;
-}
-
-static struct wins_packet_struct *packet_queue = NULL;
-
-/*******************************************************************
- Queue a packet into a packet queue
-******************************************************************/
-static void queue_packet(struct wins_packet_struct *packet)
-{
- struct wins_packet_struct *p;
-
- if (!packet_queue) {
- packet->prev = NULL;
- packet->next = NULL;
- packet_queue = packet;
- return;
- }
-
- /* find the bottom */
- for (p=packet_queue;p->next;p=p->next)
- ;
-
- p->next = packet;
- packet->next = NULL;
- packet->prev = p;
-}
-
-/****************************************************************************
- Listens for NMB or DGRAM packets, and queues them.
- return True if the socket is dead
-***************************************************************************/
-static BOOL listen_for_wins_packets(void)
-{
- int num_interfaces = iface_count();
- fd_set fds;
- int i, num, s, new_s;
- struct timeval timeout;
-
- if(listen_set == NULL) {
- if(!create_listen_fdset()) {
- DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n"));
- return True;
- }
- }
-
- memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));
-
- timeout.tv_sec = NMBD_SELECT_LOOP;
- timeout.tv_usec = 0;
-
- /* Prepare for the select - allow certain signals. */
-
- BlockSignals(False, SIGTERM);
-
- num = sys_select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
-
- /* We can only take signals when we are in the select - block them again here. */
-
- BlockSignals(True, SIGTERM);
-
- if(num == -1)
- return False;
-
- for (; num > 0; num--) {
- s = -1;
- /* check the sockets we are only listening on, waiting to accept */
- for (i=0; i<num_interfaces; i++) {
- struct sockaddr addr;
- socklen_t in_addrlen = sizeof(addr);
-
- if(FD_ISSET(sock_array[i], &fds)) {
- s = sock_array[i];
- /* Clear this so we don't look at it again. */
- FD_CLR(sock_array[i], &fds);
-
- /* accept and add the new socket to the listen set */
- new_s=accept(s, &addr, &in_addrlen);
-
- if (new_s < 0)
- continue;
-
- DEBUG(5,("listen_for_wins_packets: new connection, old: %d, new : %d\n", s, new_s));
-
- set_socket_options(new_s, "SO_KEEPALIVE");
- set_socket_options(new_s, user_socket_options);
- FD_SET(new_s, listen_set);
- add_fd_to_sock_array(new_s);
- }
- }
-
- /*
- * check for the sockets we are waiting data from
- * either client sending datas
- * or reply to our requests
- */
- for (i=num_interfaces; i<listen_number; i++) {
- if(FD_ISSET(sock_array[i], &fds)) {
- struct wins_packet_struct *packet = read_wins_packet(sock_array[i], timeout.tv_sec);
- if (packet) {
- packet->fd = sock_array[i];
- queue_packet(packet);
- }
- DEBUG(2,("listen_for_wins_packets: some data on fd %d\n", sock_array[i]));
- FD_CLR(sock_array[i], &fds);
- break;
- }
-
- }
-
- }
-
- return False;
-}
-
-
-/*******************************************************************
- Run elements off the packet queue till its empty
-******************************************************************/
-
-static void run_wins_packet_queue(void)
-{
- struct wins_packet_struct *p;
-
- while ((p = packet_queue)) {
- packet_queue = p->next;
- if (packet_queue)
- packet_queue->prev = NULL;
- p->next = p->prev = NULL;
-
- construct_reply(p);
-
- /* if it was a stop assoc, close the connection */
- if (p->stop_packet) {
- FD_CLR(p->fd, listen_set);
- remove_fd_from_sock_array(p->fd);
- close(p->fd);
- }
- }
-}
-
-/**************************************************************************** **
- The main select loop.
- **************************************************************************** */
-static void process(void)
-{
-
- while( True ) {
- time_t t = time(NULL);
-
- /* check for internal messages */
- message_dispatch();
-
- if(listen_for_wins_packets())
- return;
-
- run_wins_packet_queue();
-
- run_pull_replication(t);
-
- run_push_replication(t);
-
- /*
- * Reload the services file if we got a sighup.
- */
-
- if(reload_after_sighup) {
- reload_services( True );
- reopen_logs();
- reload_after_sighup = False;
- }
-
- /* free temp memory */
- talloc_destroy_pool(mem_ctx);
-
- /* free up temp memory */
- lp_talloc_free();
- }
-} /* process */
-
-/****************************************************************************
- main program
-****************************************************************************/
- int main(int argc,char *argv[])
-{
- extern BOOL append_log;
- extern char *optarg;
- /* shall I run as a daemon */
- BOOL is_daemon = False;
- BOOL interactive = False;
- BOOL specified_logfile = False;
- int opt;
- pstring logfile;
-
-#ifdef HAVE_SET_AUTH_PARAMETERS
- set_auth_parameters(argc,argv);
-#endif
-
- /* this is for people who can't start the program correctly */
- while (argc > 1 && (*argv[1] != '-')) {
- argv++;
- argc--;
- }
-
- while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?Vaiof:")) )
- switch (opt) {
- case 'O':
- pstrcpy(user_socket_options,optarg);
- break;
-
- case 's':
- pstrcpy(dyn_CONFIGFILE,optarg);
- break;
-
- case 'l':
- specified_logfile = True;
- slprintf(logfile, sizeof(logfile)-1, "%s/log.wrepld", optarg);
- lp_set_logfile(logfile);
- break;
-
- case 'a':
- append_log = True;
- break;
-
- case 'i':
- interactive = True;
- break;
-
- case 'o':
- append_log = False;
- break;
-
- case 'D':
- is_daemon = True;
- break;
-
- case 'd':
- if (*optarg == 'A')
- DEBUGLEVEL = 10000;
- else
- DEBUGLEVEL = atoi(optarg);
- break;
-
- case 'p':
- wins_port = atoi(optarg);
- break;
-
- case 'h':
- case '?':
- usage(argv[0]);
- exit(0);
- break;
-
- case 'V':
- d_printf("Version %s\n",VERSION);
- exit(0);
- break;
- default:
- DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
- usage(argv[0]);
- exit(1);
- }
-
-#ifdef HAVE_SETLUID
- /* needed for SecureWare on SCO */
- setluid(0);
-#endif
-
- sec_init();
-
- load_case_tables();
-
- append_log = True;
-
- if(!specified_logfile) {
- slprintf(logfile, sizeof(logfile)-1, "%s/log.wrepld",
- dyn_LOGFILEBASE);
- lp_set_logfile(logfile);
- }
-
- set_remote_machine_name("wrepld");
-
- setup_logging(argv[0],interactive);
-
- /* we want to re-seed early to prevent time delays causing
- client problems at a later date. (tridge) */
- generate_random_buffer(NULL, 0, False);
-
- /* make absolutely sure we run as root - to handle cases where people
- are crazy enough to have it setuid */
-
- gain_root_privilege();
- gain_root_group_privilege();
-
- fault_setup((void (*)(void *))exit_server);
- CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig);
-
- /* we are never interested in SIGPIPE */
- BlockSignals(True,SIGPIPE);
-
-#if defined(SIGFPE)
- /* we are never interested in SIGFPE */
- BlockSignals(True,SIGFPE);
-#endif
-
-#if defined(SIGUSR2)
- /* We are no longer interested in USR2 */
- BlockSignals(True,SIGUSR2);
-#endif
-
- /* POSIX demands that signals are inherited. If the invoking process has
- * these signals masked, we will have problems, as we won't recieve them. */
- BlockSignals(False, SIGHUP);
- BlockSignals(False, SIGUSR1);
-
- /* we want total control over the permissions on created files,
- so set our umask to 0 */
- umask(0);
-
- reopen_logs();
-
- DEBUG(1,( "wrepld version %s started.\n", VERSION));
- DEBUGADD(1,( "Copyright Andrew Tridgell and the Samba Team 1992-2002\n"));
-
- DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
- (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));
-
- if (sizeof(uint16) < 2 || sizeof(uint32) < 4) {
- DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
- exit(1);
- }
-
- /*
- * Do this before reload_services.
- */
-
- if (!reload_services(False))
- return(-1);
-
- init_structs();
-
-#ifdef WITH_PROFILE
- if (!profile_setup(False)) {
- DEBUG(0,("ERROR: failed to setup profiling\n"));
- return -1;
- }
-#endif
-
- fstrcpy(global_myworkgroup, lp_workgroup());
-
- CatchSignal(SIGHUP,SIGNAL_CAST sig_hup);
-
- DEBUG(3,( "loaded services\n"));
-
- if (!is_daemon && !is_a_socket(0)) {
- DEBUG(0,("standard input is not a socket, assuming -D option\n"));
- is_daemon = True;
- }
-
- if (is_daemon && !interactive) {
- DEBUG( 3, ( "Becoming a daemon.\n" ) );
- become_daemon();
- }
-
-#if HAVE_SETPGID
- /*
- * If we're interactive we want to set our own process group for
- * signal management.
- */
- if (interactive)
- setpgid( (pid_t)0, (pid_t)0);
-#endif
-
- if (!directory_exist(lp_lockdir(), NULL)) {
- mkdir(lp_lockdir(), 0755);
- }
-
- if (is_daemon) {
- pidfile_create("wrepld");
- }
-
- if (!message_init()) {
- exit(1);
- }
-
- /* Initialise the memory context */
- mem_ctx=talloc_init_named("wins repl talloc ctx");
-
- /* initialise the global partners table */
- partner_count=init_wins_partner_table();
-
- /* We can only take signals in the select. */
- BlockSignals( True, SIGTERM );
-
- process();
-
- exit_server("normal exit");
- return(0);
-}