Ejemplo n.º 1
0
Archivo: sigyn.c Proyecto: alyx/sigyn
int main(int argc, char *argv[])
{
    me.ev = mowgli_eventloop_create();

    signals_init();

    parse_commandline_options(argc, argv);

    me.config = mowgli_config_file_load(config_file);

    if(me.config == NULL)
        sigyn_fatal("Cannot load configuration file.");
    logger_init(me.config->entries);
    config_check(me.config);

    me.uplink.line = new_conn(me.uplink.hostname, me.uplink.port, me.uplink.ssl, read_irc, NULL);
    if (me.uplink.line == NULL)
        sigyn_fatal("Connection to uplink failed.");
    me.uplink.connected = true;

    loadmodules(me.config->entries);

    sigyn_introduce_client(me.client->nick, me.client->user, NULL);
    if (should_fork)
        daemonise(SYSCONFDIR "/sigyn.pid");
    mowgli_eventloop_run(me.ev);

    sigyn_cleanup();
    return EXIT_SUCCESS;
}
Ejemplo n.º 2
0
int server(struct conf *conf, const char *conffile,
	struct lock *lock, int generate_ca_only)
{
	int ret=0;
	int rfd=-1; // normal client port
	// Only close and reopen listening sockets if the ports changed.
	// Otherwise you get an "unable to bind listening socket on port X"
	// error, and the server stops.
	char *oldport=NULL;
	char *oldstatusport=NULL;

	//return champ_test(conf);

	if(ca_server_setup(conf)) return 1;
	if(generate_ca_only)
	{
		logp("The '-g' command line option was given. Exiting now.\n");
		return 0;
	}

	if(conf->forking && conf->daemon)
	{
		if(daemonise() || relock(lock)) return 1;
	}

	ssl_load_globals();

	while(!ret && !gentleshutdown)
	{
		ret=run_server(conf, conffile,
			&rfd, oldport, oldstatusport);
		if(ret) break;
		if(hupreload && !gentleshutdown)
		{
			if(oldport) free(oldport);
			if(oldstatusport) free(oldstatusport);
			oldport=strdup(conf->port);
			oldstatusport=conf->status_port?
				strdup(conf->status_port):NULL;
			if(reload(conf, conffile,
				0, // Not first time.
				conf->max_children,
				conf->max_status_children,
				0)) // Not JSON output.
					ret=1;
		}
		hupreload=0;
	}
	close_fd(&rfd);
	close_fd(&sfd);
	if(oldport) free(oldport);
	if(oldstatusport) free(oldstatusport);

	// The signal handler stuff sets up chlds. Need to free them.
	chlds_free();

// FIX THIS: Have an enum for a return value, so that it is more obvious what
// is happening, like client.c does.
	return ret;
}
Ejemplo n.º 3
0
int main ( int argc, char **argv ) {
    struct hijack_options options;
    struct hijack_listener listener;
    struct sigaction sa;

    /* Parse command-line options */
    if ( parse_options ( argc, argv, &options ) < 0 )
        exit ( 1 );

    /* Set up syslog connection */
    openlog ( basename ( argv[0] ), LOG_PID, LOG_DAEMON );

    /* Set up listening socket */
    if ( open_listener ( options.interface, &listener ) < 0 )
        exit ( 1 );

    /* Daemonise on demand */
    if ( options.daemonise ) {
        if ( daemonise ( options.interface ) < 0 )
            exit ( 1 );
    }

    /* Avoid creating zombies */
    memset ( &sa, 0, sizeof ( sa ) );
    sa.sa_handler = SIG_IGN;
    sa.sa_flags = SA_RESTART | SA_NOCLDWAIT;
    if ( sigaction ( SIGCHLD, &sa, NULL ) < 0 ) {
        logmsg ( LOG_ERR, "Could not set SIGCHLD handler: %s",
                 strerror ( errno ) );
        exit ( 1 );
    }

    /* Set 'signalled' flag on SIGINT or SIGHUP */
    sa.sa_handler = flag_signalled;
    sa.sa_flags = SA_RESTART | SA_RESETHAND;
    if ( sigaction ( SIGINT, &sa, NULL ) < 0 ) {
        logmsg ( LOG_ERR, "Could not set SIGINT handler: %s",
                 strerror ( errno ) );
        exit ( 1 );
    }
    if ( sigaction ( SIGHUP, &sa, NULL ) < 0 ) {
        logmsg ( LOG_ERR, "Could not set SIGHUP handler: %s",
                 strerror ( errno ) );
        exit ( 1 );
    }

    /* Listen for hijackers */
    if ( listen_for_hijackers ( &listener, options.interface ) < 0 )
        exit ( 1 );

    close_listener ( &listener );

    return 0;
}
Ejemplo n.º 4
0
Archivo: main.c Proyecto: EmisFR/burp
int server(struct conf **confs, const char *conffile,
	struct lock *lock, int generate_ca_only)
{
	enum serret ret=SERVER_ERROR;
	int rfds[LISTEN_SOCKETS]; // Sockets for clients to connect to.
	int sfds[LISTEN_SOCKETS]; // Status server sockets.

	//return champ_test(confs);

	init_fds(rfds);
	init_fds(sfds);

	if(ca_server_setup(confs)) goto error;
	if(generate_ca_only)
	{
		logp("The '-g' command line option was given. Exiting now.\n");
		goto end;
	}

	if(get_int(confs[OPT_FORK]) && get_int(confs[OPT_DAEMON]))
	{
		if(daemonise() || relock(lock)) goto error;
	}

	ssl_load_globals();

	while(!gentleshutdown)
	{
		if(run_server(confs, conffile, rfds, sfds))
			goto error;

		if(hupreload && !gentleshutdown)
		{
			if(reload(confs, conffile,
				0, // Not first time.
				get_int(confs[OPT_MAX_CHILDREN]),
				get_int(confs[OPT_MAX_STATUS_CHILDREN])))
					goto error;
		}
		hupreload=0;
	}

end:
	ret=SERVER_OK;
error:
	close_fds(rfds);
	close_fds(sfds);

// FIX THIS: Have an enum for a return value, so that it is more obvious what
// is happening, like client.c does.
	return ret;
}
Ejemplo n.º 5
0
Archivo: wansd.c Proyecto: stolf/WAND
int main(int argc,char **argv)
{
  int sock = socket(PF_INET, SOCK_DGRAM, 0);
  struct sockaddr_in address;
  int errors=0;
  
  if (sock<0) {
    perror("socket");
    return 1;
  };
  
  address.sin_family = AF_INET;
  address.sin_port = htons(44444);
  address.sin_addr.s_addr = htonl(INADDR_ANY);
  if (bind(sock,(struct sockaddr *)&address,sizeof(address))<0) {
    perror("bind");
    return 1;
  }
  
  signal(SIGUSR1, printlist);
  
  daemonise(argv[0]);
  put_pid("wansd");
  openlog(argv[0],LOG_PID,LOG_DAEMON);
  syslog(LOG_NOTICE,"%s started.",argv[0]);
  
  for (;;) {
    int addrlen=sizeof(address);
    char buffer[65536];
    int data=recvfrom(sock,(void *)buffer,sizeof(buffer),0,
		      (struct sockaddr *)&address,&addrlen);
    if (data<0) {
      errors++;
      sleep(1);
      if (errors>10) {
	syslog(LOG_ERR,"recvfrom: %m\n");
	syslog(LOG_ERR,"Too many errors, bailing.\n");
	return 1;
      }
    } else {
      errors=0;
    }
    buffer[sizeof(buffer)-1]='\0';
    sendupdate(sock,dopacket(buffer,data,address));
  };
  return 0;
}
Ejemplo n.º 6
0
/* ARGSUSED */
static void
handle_exit_timeout(__unused void *arg)
{
	int timeout;

	syslog(LOG_ERR, "timed out");
	if (!(options & DHCPCD_IPV4) || !(options & DHCPCD_TIMEOUT_IPV4LL)) {
		if (options & DHCPCD_MASTER) {
			daemonise();
			return;
		} else
			exit(EXIT_FAILURE);
	}
	options &= ~DHCPCD_TIMEOUT_IPV4LL;
	timeout = (PROBE_NUM * PROBE_MAX) + (PROBE_WAIT * 2);
	syslog(LOG_WARNING, "allowing %d seconds for IPv4LL timeout", timeout);
	eloop_timeout_add_sec(timeout, handle_exit_timeout, NULL);
}
Ejemplo n.º 7
0
/* ARGSUSED */
static void
handle_exit_timeout(__unused void *arg)
{
	int timeout;

	syslog(LOG_ERR, "timed out");
	if (!(options & DHCPCD_IPV4) || !(options & DHCPCD_TIMEOUT_IPV4LL)) {
		if (options & DHCPCD_MASTER) {
			/* We've timed out, so remove the waitip requirements.
			 * If the user doesn't like this they can always set
			 * an infinite timeout. */
			options &=
			    ~(DHCPCD_WAITIP | DHCPCD_WAITIP4 | DHCPCD_WAITIP6);
			daemonise();
			return;
		} else
			exit(EXIT_FAILURE);
	}
	options &= ~DHCPCD_TIMEOUT_IPV4LL;
	timeout = (PROBE_NUM * PROBE_MAX) + (PROBE_WAIT * 2);
	syslog(LOG_WARNING, "allowing %d seconds for IPv4LL timeout", timeout);
	eloop_timeout_add_sec(timeout, handle_exit_timeout, NULL);
}
Ejemplo n.º 8
0
int main(int argc, char **argv)
{
        int err;

        server_init();

        parse_arguments(argc, argv);

        log_set_file(logFile);

        if (nodaemon == 0) {
                err = daemonise();
                if (err != 0) exit(1);

                err = writePidFile(pidFile);
                if (err != 0) exit(1);

                err = drop_privileges();
                if (err != 0) exit(1);
        }

        err = signalisation();
        if (err != 0) exit(1);

        serverSocket = openServerSocket(NULL, port);
        if (serverSocket == -1) exit(1);

        log_info("Server ready for connections");

        request_t req;
        response_t resp;

        memset(&req, 0, sizeof(request_t));
        memset(&resp, 0, sizeof(response_t));
                        
        while (serverSocket != -1) {

                int client = serverSocketAccept(serverSocket);
                if (client == -1) {
                        continue;
                }

                int r = parseRequest(client, &req, &resp);
                if (r != 0) {
                        clientPrintf(client, "HTTP/1.1 %03d\r\n", resp.status);
                        closeClient(client);
                        continue;
                }

                log_info("Request: %s", req.path);

                if (1) {
                        list_t* l = req.args;
                        while (l) {
                                pair_t* p = (pair_t*) l->data;
                                log_debug("args[]: %s = %s", p->name, p->value);
                                l = l->next;
                        }
                        l = req.headers;
                        while (l) {
                                pair_t* p = (pair_t*) l->data;
                                log_debug("headers[]: '%s': '%s'", p->name, p->value);
                                l = l->next;
                        }
                }

                server_handle_request(&req, &resp);

                // Debug printf
                
                if (resp.status != 0) {
                        clientPrintf(client, 
                                     "HTTP/1.1 %03d\r\n"
                                     "Content-Length: %d\r\n"
                                     "Content-Type: %s\r\n"
                                     "\r\n", 
                                     resp.status, resp.length, resp.content_type);

                        clientWrite(client, resp.body, resp.length);
                        
                } else {
                        log_err("main.c, request status == 0, request not handle!");
                }

                closeClient(client);
                
                request_clear(&req);
                response_clear(&resp);
        }

        removePidFile(pidFile); 

        return 0;
}
Ejemplo n.º 9
0
int main(int argc, char *argv[])
{
	dhcpctl_handle conn = NULL;
	char *conffile=NULL;
	char ch;
	
	name = strdup("OMAPI");
	    
	openlog("dhcparpd", LOG_PID, LOG_DAEMON);

	/* Parse Commandline Options */
	while((ch = getopt(argc, argv, "c:dh")) != -1) {
		switch(ch){
			case 'c':
				conffile = strdup(optarg);
				break;
			case 'd':
				do_daemonise=0;
				break;
			case 'h':
				usage(argv[0]);
				return 0;
			default:
				fprintf(stderr, "Unknown option '%c'!", ch);
				usage(argv[0]);
				return 1;
		}
	}

	/* Try a default configfile if non specified */
	if (conffile==NULL) {
		conffile = strdup("/etc/dhcparpd.conf");
	}
	if (parse_config(config,conffile)) {
		fprintf(stderr,"Unable to parse configfile: %s\n", 
				conffile);
		return 1;
	}
	free(conffile);

	/* Daemonise */
	if (do_daemonise) {
		daemonise(argv[0]);
		put_pid(pidfile);
	}
	
	parse_mappings();

	conn = dhcpd_connect(servername, port, name, key);

	if (!conn) {
		Log(LOG_CRIT, "failed to connect to dhcp server");
		return 1;
	}

	arp_init(interface,conn);

	init_event();
	init_netlink();

	if (pcap_init(interface))
		return 1;

        Log(LOG_NOTICE, "Ready for action! Lets Go...");
	run();

	return 0;
}
Ejemplo n.º 10
0
int ParseArgs(int argc, char *argv[], Settings *settings,
	      Complaints *complaints)
{
    static const struct option options[] =
    {
	{ "help",  no_argument, NULL, 'h' },
	{ "no-audio", no_argument, NULL, 'a' },
	{ "no-daemon", no_argument, NULL, 'd' },
	{ "no-mserver", no_argument, NULL, 'm' },
	{ "no-optical", no_argument, NULL, 'o' },
	{ "no-receiver", no_argument, NULL, 'r' },
	{ "no-broadcast", no_argument, NULL, 'b' },
	{ "assimilate-receiver", no_argument, NULL, 11 },
	{ "web", required_argument, NULL, 'w' },
	{ "nfs", required_argument, NULL, 1 },
	{ "arf", required_argument, NULL, 2 },
	{ "dbfile", required_argument, NULL, 'f' },
	{ "threads", required_argument, NULL, 't' },
	{ "channels", required_argument, NULL, 'c' },
	{ "timer-db", required_argument, NULL, 3 },
	{ NULL, 0, NULL, 0 }
    };

    memset(settings, '\0', sizeof(settings));
    settings->flags = AUDIO | MEDIA_SERVER | RECEIVER | DVB | CD | LOCAL_DB;
    settings->database_file = DEFAULT_DB_FILE;
    settings->timer_database_file = DEFAULT_TIMER_DB_FILE;
    settings->web_root = DEFAULT_WEB_DIR;
    settings->receiver_software_server = NULL;
    settings->receiver_arf_file = DEFAULT_ARF_FILE;
    settings->dvb_channels_file = DEFAULT_CHANNELS_CONF;
    settings->nthreads = 32;

    bool explicit_port = false;
    bool do_daemon = true;

    int option_index;
    int option;
    while ((option = getopt_long(argc, argv, "abrdhmot:f:l:c:p:", options,
				 &option_index))
	   != -1)
    {
	switch (option)
	{
	case 'h':
	    Usage(stdout);
	    exit(0);
	    return 0;
	case 'd':
	    do_daemon = false;
	    break;
	case 't':
	    settings->nthreads = (unsigned int)strtoul(optarg, NULL, 10);
	    break;
	case 'p':
	    settings->web_port = (unsigned short)strtoul(optarg, NULL, 10);
	    explicit_port = true;
	    break;
	case 'f':
	    settings->database_file = optarg;
	    break;
	case 'w':
	    settings->web_root = optarg;
	    break;
	case 'c':
	    settings->dvb_channels_file = optarg;
	    break;
	case 'a':
	    settings->flags &= ~AUDIO;
	    break;
	case 'm':
	    settings->flags &= ~MEDIA_SERVER;
	    break;
	case 'o':
	    settings->flags &= ~CD;
	    break;
	case 'r':
	    settings->flags &= ~RECEIVER;
	    break;
	case 'b':
	    settings->flags &= ~DVB;
	    break;
	case 1:
	    settings->receiver_software_server = optarg;
	    break;
	case 2:
	    settings->receiver_arf_file = optarg;
	    break;
	case 3:
	    settings->timer_database_file = optarg;
	    break;
	case 11:
	    settings->flags |= ASSIMILATE_RECEIVER;
	    settings->flags &= ~RECEIVER;
	    break;
	default:
	    Usage(stderr);
	    exit(1);
	    return 0;
	}
    }

    switch ((int)(argc-optind)) // How many more arguments?
    {
    case 2:
	settings->media_root = argv[optind];
	settings->flac_root  = argv[optind+1];
	break;
    case 1:
	settings->media_root = argv[optind];
	settings->flac_root  = "";
	break;
    case 0:
	// No music directory given -- disable all file ops
	settings->flags &= ~LOCAL_DB;
	break;
    default:
	Usage(stderr);
	exit(1);
	return 1;
    }

    if ((settings->flags & (LOCAL_DB | DVB | ASSIMILATE_RECEIVER)) == 0)
    {
	// Nothing to serve
	settings->flags &= ~MEDIA_SERVER;
	settings->flags &= ~RECEIVER;
    }

    if ((settings->flags & (AUDIO | RECEIVER | MEDIA_SERVER | CD)) == 0)
    {
	complaints->Complain(LOG_WARNING, "No protocols to serve; exiting\n");
	return 0;
    }

    if (!explicit_port)
    {
	if (settings->flags & RECEIVER)
	    settings->web_port = DEFAULT_WEB_PORT;
	else
	    settings->web_port = 0;
    }

    if (do_daemon)
	daemonise();

    return 0;
}
Ejemplo n.º 11
0
int main(int argc, char *argv[])
{
	daemonise();	

	return 0;
}
Ejemplo n.º 12
0
/* This state machine is based on the one from udhcpc
   written by Russ Dill */
int dhcp_run (options_t *options)
{
  interface_t *iface;
  int mode = SOCKET_CLOSED;
  int state = STATE_INIT;
  struct timeval tv;
  int xid = 0;
  long timeout = 0;
  fd_set rset;
  int maxfd;
  int retval;
  dhcpmessage_t message;
  dhcp_t *dhcp;
  int type = DHCP_DISCOVER;
  int last_type = DHCP_DISCOVER;
  bool daemonised = false;
  unsigned long start = 0;
  unsigned long last_send = 0;
  int sig;
  unsigned char *buffer = NULL;
  int buffer_len = 0;
  int buffer_pos = 0;

  if (! options || (iface = (read_interface (options->interface,
					     options->metric))) == NULL)
    return -1;

  /* Remove all existing addresses.
     After all, we ARE a DHCP client whose job it is to configure the
     interface. We only do this on start, so persistent addresses can be added
     afterwards by the user if needed. */
  flush_addresses (iface->name);

  dhcp = xmalloc (sizeof (dhcp_t));
  memset (dhcp, 0, sizeof (dhcp_t));

  strcpy (dhcp->classid, options->classid);
  if (options->clientid[0])
    strcpy (dhcp->clientid, options->clientid);
  else
    sprintf (dhcp->clientid, "%s", ether_ntoa (&iface->ethernet_address));

  if (options->requestaddress.s_addr != 0)
    dhcp->address.s_addr = options->requestaddress.s_addr;

  signal_setup ();

  while (1)
    {
      if (timeout > 0 || (options->timeout == 0 &&
			  (state != STATE_INIT || xid)))
	{
	  if (options->timeout == 0 || dhcp->leasetime == -1)
	    {
	      logger (LOG_DEBUG, "waiting on select for infinity");
	      maxfd = signal_fd_set (&rset, iface->fd);
	      retval = select (maxfd + 1, &rset, NULL, NULL, NULL);
	    }
	  else
	    {
	      /* Resend our message if we're getting loads of packets
		 that aren't for us. This mainly happens on Linux as it
		 doesn't have a nice BPF filter. */
	      if (iface->fd > -1 && uptime () - last_send >= TIMEOUT_MINI)
		SEND_MESSAGE (last_type);

	      logger (LOG_DEBUG, "waiting on select for %d seconds",
		      timeout);
	      /* If we're waiting for a reply, then we re-send the last
		 DHCP request periodically in-case of a bad line */
	      retval = 0;
	      while (timeout > 0 && retval == 0)
		{
		  if (iface->fd == -1)
		    tv.tv_sec = SELECT_MAX;
		  else
		    tv.tv_sec = TIMEOUT_MINI;
		  if (timeout < tv.tv_sec)
		    tv.tv_sec = timeout;
		  tv.tv_usec = 0;
		  start = uptime ();
		  maxfd = signal_fd_set (&rset, iface->fd);
		  retval = select (maxfd + 1, &rset, NULL, NULL, &tv);
		  timeout -= uptime () - start;
		  if (retval == 0 && iface->fd != -1 && timeout > 0)
		    SEND_MESSAGE (last_type);
		}
	    }
	}
      else
	retval = 0;

      /* We should always handle our signals first */
      if (retval > 0 && (sig = signal_read (&rset)))
	{
	  switch (sig)
	    {
	    case SIGINT:
	      logger (LOG_INFO, "receieved SIGINT, stopping");
	      retval = 0;
	      goto eexit;

	    case SIGTERM:
	      logger (LOG_INFO, "receieved SIGTERM, stopping");
	      retval = 0;
	      goto eexit;

	    case SIGALRM:

	      logger (LOG_INFO, "receieved SIGALRM, renewing lease");
	      switch (state)
		{
		case STATE_BOUND:
		case STATE_RENEWING:
		case STATE_REBINDING:
		  state = STATE_RENEW_REQUESTED;
		  break;
		case STATE_RENEW_REQUESTED:
		case STATE_REQUESTING:
		case STATE_RELEASED:
		  state = STATE_INIT;
		  break;
		}

	      timeout = 0;
	      xid = 0;
	      break;

	    case SIGHUP:
	      if (state == STATE_BOUND || state == STATE_RENEWING
		  || state == STATE_REBINDING)
		{
		  logger (LOG_INFO, "received SIGHUP, releasing lease");
		  SOCKET_MODE (SOCKET_OPEN);
		  xid = random_xid ();
		  if ((open_socket (iface, false)) >= 0)
		    SEND_MESSAGE (DHCP_RELEASE);
		  SOCKET_MODE (SOCKET_CLOSED);
		  unlink (iface->infofile);
		}
	      else
		logger (LOG_ERR,
			"receieved SIGUP, but no we have lease to release");
	      retval = 0;
	      goto eexit;

	    default:
	      logger (LOG_ERR,
		      "received signal %d, but don't know what to do with it",
		      sig);
	    }
	}
      else if (retval == 0) /* timed out */
	{
	  switch (state)
	    {
	    case STATE_INIT:
	      if (iface->previous_address.s_addr != 0)
		{
		  logger (LOG_ERR, "lost lease");
		  xid = 0;
		  SOCKET_MODE (SOCKET_CLOSED);
		  if (! options->persistent)
		    {
		      free_dhcp (dhcp);
		      memset (dhcp, 0, sizeof (dhcp_t));
		      configure (options, iface, dhcp);
		    }
		  if (! daemonised)
		    {
		      retval = -1;
		      goto eexit;
		    }
		  break;
		}

	      if (xid == 0)
		xid = random_xid ();
	      else
		{
		  logger (LOG_ERR, "timed out");
		  if (! daemonised)
		    {
		      retval = -1;
		      goto eexit;
		    }
		}

	      SOCKET_MODE (SOCKET_OPEN);
	      timeout = options->timeout;
	      iface->start_uptime = uptime ();
	      if (dhcp->address.s_addr == 0)
		{
		  logger (LOG_INFO, "broadcasting for a lease");
		  SEND_MESSAGE (DHCP_DISCOVER);
		}
	      else
		{
		  logger (LOG_INFO, "broadcasting for a lease of %s",
			  inet_ntoa (dhcp->address));
		  SEND_MESSAGE (DHCP_REQUEST);
		  state = STATE_REQUESTING;
		}

	      break;
	    case STATE_BOUND:
	    case STATE_RENEW_REQUESTED:
	      state = STATE_RENEWING;
	      xid = random_xid ();
	    case STATE_RENEWING:
	      iface->start_uptime = uptime ();
	      logger (LOG_INFO, "renewing lease of %s", inet_ntoa
		      (dhcp->address));
	      SOCKET_MODE (SOCKET_OPEN);
	      SEND_MESSAGE (DHCP_REQUEST);
	      timeout = dhcp->rebindtime - dhcp->renewaltime;
	      state = STATE_REBINDING;
	      break;
	    case STATE_REBINDING:
	      logger (LOG_ERR, "lost lease, attemping to rebind");
	      SOCKET_MODE (SOCKET_OPEN);
	      SEND_MESSAGE (DHCP_DISCOVER);
	      timeout = dhcp->leasetime - dhcp->rebindtime;
	      state = STATE_INIT;
	      break;
	    case STATE_REQUESTING:
	      logger (LOG_ERR, "timed out");
	      if (! daemonised)
		goto eexit;

	      state = STATE_INIT;
	      SOCKET_MODE (SOCKET_CLOSED);
	      timeout = 0;
	      xid = 0;
	      free_dhcp (dhcp);
	      memset (dhcp, 0, sizeof (dhcp_t));
	      break;

	    case STATE_RELEASED:
	      dhcp->leasetime = -1;
	      break;
	    }
	}
      else if (retval > 0 && mode != SOCKET_CLOSED && FD_ISSET(iface->fd, &rset))
	{

	  /* Allocate our buffer space for BPF.
	     We cannot do this until we have opened our socket as we don't
	     know how much of a buffer we need until then. */
	  if (! buffer)
	    buffer = xmalloc (iface->buffer_length);
	  buffer_len = iface->buffer_length;
	  buffer_pos = -1;

	  /* We loop through until our buffer is empty.
	     The benefit is that if we get >1 DHCP packet in our buffer and
	     the first one fails for any reason, we can use the next. */

	  memset (&message, 0, sizeof (struct dhcpmessage_t));
	  int valid = 0;
	  struct dhcp_t *new_dhcp;
	  new_dhcp = xmalloc (sizeof (dhcp_t));

	  while (buffer_pos != 0)
	    {
	      if (get_packet (iface, (unsigned char *) &message, buffer,
			      &buffer_len, &buffer_pos) < 0)
		break;

	      if (xid != message.xid)
		{
		  logger (LOG_ERR,
			  "ignoring packet with xid %d as it's not ours (%d)",
			  message.xid, xid);
		  continue;
		}

	      logger (LOG_DEBUG, "got a packet with xid %d", message.xid);
	      memset (new_dhcp, 0, sizeof (dhcp_t));
	      if ((type = parse_dhcpmessage (new_dhcp, &message)) < 0)
		{
		  logger (LOG_ERR, "failed to parse packet");
		  free_dhcp (new_dhcp);
		  continue;
		}

	      /* If we got here then the DHCP packet is valid and appears to
		 be for us, so let's clear the buffer as we don't care about
		 any more DHCP packets at this point. */
	      valid = 1;
	      break;
	    }

	  /* No packets for us, so wait until we get one */
	  if (! valid)
	    {
	      free (new_dhcp);
	      continue;
	    }

	  /* new_dhcp is now our master DHCP message */
	  free_dhcp (dhcp);
	  free (dhcp);
	  dhcp = new_dhcp;
	  new_dhcp = NULL;

	  /* We should restart on a NAK */
	  if (type == DHCP_NAK)
	    {
	      logger (LOG_INFO, "received NAK: %s", dhcp->message);
	      state = STATE_INIT;
	      timeout = 0;
	      xid = 0;
	      free_dhcp (dhcp);
	      memset (dhcp, 0, sizeof (dhcp_t));
	      configure (options, iface, dhcp);
	      continue;
	    }

	  switch (state)
	    {
	    case STATE_INIT:
	      if (type == DHCP_OFFER)
		{
		  logger (LOG_INFO, "offered lease of %s",
			  inet_ntoa (dhcp->address));

		  SEND_MESSAGE (DHCP_REQUEST);
		  state = STATE_REQUESTING;
		}
	      break;

	    case STATE_RENEW_REQUESTED:
	    case STATE_REQUESTING:
	    case STATE_RENEWING:
	    case STATE_REBINDING:
	      if (type == DHCP_ACK)
		{
		  SOCKET_MODE (SOCKET_CLOSED);
		  if (options->doarp && iface->previous_address.s_addr !=
		      dhcp->address.s_addr)
		    {
		      if (arp_check (iface, dhcp->address))
			{
			  SOCKET_MODE (SOCKET_OPEN);
			  SEND_MESSAGE (DHCP_DECLINE);
			  SOCKET_MODE (SOCKET_CLOSED);
			  free_dhcp (dhcp);
			  memset (dhcp, 0, sizeof (dhcp));
			  if (daemonised)
			    configure (options, iface, dhcp);

			  xid = 0;
			  state = STATE_INIT;
			  /* RFC 2131 says that we should wait for 10 seconds
			     before doing anything else */
			  sleep (10);
			  continue;
			}
		    }

		  if (! dhcp->leasetime)
		    {
		      dhcp->leasetime = DEFAULT_TIMEOUT;
		      logger(LOG_INFO,
			     "no lease time supplied, assuming %d seconds",
			     dhcp->leasetime);
		    }

		  if (! dhcp->renewaltime) 
		    {
		      dhcp->renewaltime = dhcp->leasetime / 2;
		      logger (LOG_INFO,
			      "no renewal time supplied, assuming %d seconds",
			      dhcp->renewaltime);
		    }

		  if (! dhcp->rebindtime)
		    {
		      dhcp->rebindtime = (dhcp->leasetime * 0x7) >> 3;
		      logger (LOG_INFO,
			      "no rebind time supplied, assuming %d seconds",
			      dhcp->rebindtime);
		    }

		  if (dhcp->leasetime == -1)
		    logger (LOG_INFO, "leased %s for infinity",
			    inet_ntoa (dhcp->address));
		  else
		    logger (LOG_INFO, "leased %s for %u seconds",
			    inet_ntoa (dhcp->address),
			    dhcp->leasetime, dhcp->renewaltime);

		  state = STATE_BOUND;
		  timeout = dhcp->renewaltime;
		  xid = 0;

		  if (configure (options, iface, dhcp) < 0 && ! daemonised)
		    {
		      retval = -1;
		      goto eexit;
		    }

		  if (! daemonised)
		    {
		      if ((daemonise (options->pidfile)) < 0 )
			{
			  retval = -1;
			  goto eexit;
			}
		      daemonised = true;
		    }
		}
	      else if (type == DHCP_OFFER)
		logger (LOG_INFO, "got subsequent offer of %s, ignoring ",
			inet_ntoa (dhcp->address));
	      else
		logger (LOG_ERR,
			"no idea what to do with DHCP type %d at this point",
			type);
	      break;
	    }
Ejemplo n.º 13
0
int
main(int argc, char **argv)
{
    struct sockaddr_in6 sin6;
    int rc, fd, i, opt;
    time_t expiry_time, source_expiry_time, kernel_dump_time;
    const char **config_files = NULL;
    int num_config_files = 0;
    void *vrc;
    unsigned int seed;
    struct interface *ifp;

    gettime(&now);

    rc = read_random_bytes(&seed, sizeof(seed));
    if(rc < 0) {
        perror("read(random)");
        seed = 42;
    }

    seed ^= (now.tv_sec ^ now.tv_usec);
    srandom(seed);

    parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL);
    protocol_port = 6696;
    change_smoothing_half_life(4);
    has_ipv6_subtrees = kernel_has_ipv6_subtrees();

    while(1) {
        opt = getopt(argc, argv,
                     "m:p:h:H:i:k:A:sruS:d:g:G:lwz:M:t:T:c:C:DL:I:V");
        if(opt < 0)
            break;

        switch(opt) {
        case 'm':
            rc = parse_address(optarg, protocol_group, NULL);
            if(rc < 0)
                goto usage;
            if(protocol_group[0] != 0xff) {
                fprintf(stderr,
                        "%s is not a multicast address\n", optarg);
                goto usage;
            }
            if(protocol_group[1] != 2) {
                fprintf(stderr,
                        "Warning: %s is not a link-local multicast address\n",
                        optarg);
            }
            break;
        case 'p':
            protocol_port = parse_nat(optarg);
            if(protocol_port <= 0 || protocol_port > 0xFFFF)
                goto usage;
            break;
        case 'h':
            default_wireless_hello_interval = parse_thousands(optarg);
            if(default_wireless_hello_interval <= 0 ||
               default_wireless_hello_interval > 0xFFFF * 10)
                goto usage;
            break;
        case 'H':
            default_wired_hello_interval = parse_thousands(optarg);
            if(default_wired_hello_interval <= 0 ||
               default_wired_hello_interval > 0xFFFF * 10)
                goto usage;
            break;
        case 'k':
            kernel_metric = parse_nat(optarg);
            if(kernel_metric < 0 || kernel_metric > 0xFFFF)
                goto usage;
            break;
        case 'A':
            allow_duplicates = parse_nat(optarg);
            if(allow_duplicates < 0 || allow_duplicates > 0xFFFF)
                goto usage;
            break;
        case 's':
            split_horizon = 0;
            break;
        case 'r':
            random_id = 1;
            break;
        case 'u':
            keep_unfeasible = 1;
            break;
        case 'S':
            state_file = optarg;
            break;
        case 'd':
            debug = parse_nat(optarg);
            if(debug < 0)
                goto usage;
            break;
        case 'g':
        case 'G':
            if(opt == 'g')
                local_server_write = 0;
            else
                local_server_write = 1;
            if(optarg[0] == '/') {
                local_server_port = -1;
                free(local_server_path);
                local_server_path = strdup(optarg);
            } else {
                local_server_port = parse_nat(optarg);
                free(local_server_path);
                local_server_path = NULL;
                if(local_server_port <= 0 || local_server_port > 0xFFFF)
                    goto usage;
            }
            break;
        case 'l':
            link_detect = 1;
            break;
        case 'w':
            all_wireless = 1;
            break;
        case 'z':
            {
                char *comma;
                diversity_kind = (int)strtol(optarg, &comma, 0);
                if(*comma == '\0')
                    diversity_factor = 128;
                else if(*comma == ',')
                    diversity_factor = parse_nat(comma + 1);
                else
                    goto usage;
                if(diversity_factor <= 0 || diversity_factor > 256)
                    goto usage;
            }
            break;
        case 'M': {
            int l = parse_nat(optarg);
            if(l < 0 || l > 3600)
                goto usage;
            change_smoothing_half_life(l);
            break;
        }
        case 't':
            export_table = parse_nat(optarg);
            if(export_table < 0 || export_table > 0xFFFF)
                goto usage;
            break;
        case 'T':
            if(add_import_table(parse_nat(optarg)))
                goto usage;
            break;
        case 'c':
            config_files = realloc(config_files,
                                   (num_config_files + 1) * sizeof(char*));
            if(config_files == NULL) {
                fprintf(stderr, "Couldn't allocate config file.\n");
                exit(1);
            }
            config_files[num_config_files++] = optarg;
            break;
        case 'C':
            rc = parse_config_from_string(optarg, strlen(optarg), NULL);
            if(rc != CONFIG_ACTION_DONE) {
                fprintf(stderr,
                        "Couldn't parse configuration from command line.\n");
                exit(1);
            }
            break;
        case 'D':
            do_daemonise = 1;
            break;
        case 'L':
            logfile = optarg;
            break;
        case 'I':
            pidfile = optarg;
            break;
        case 'V':
            fprintf(stderr, "%s\n", BABELD_VERSION);
            exit(0);
            break;
        default:
            goto usage;
        }
    }

    if(num_config_files == 0) {
        if(access("/etc/babeld.conf", F_OK) >= 0) {
            config_files = malloc(sizeof(char*));
            if(config_files == NULL) {
                fprintf(stderr, "Couldn't allocate config file.\n");
                exit(1);
            }
            config_files[num_config_files++] = "/etc/babeld.conf";
        }
    }

    for(i = 0; i < num_config_files; i++) {
        int line;
        rc = parse_config_from_file(config_files[i], &line);
        if(rc < 0) {
            fprintf(stderr,
                    "Couldn't parse configuration from file %s "
                    "(error at line %d).\n",
                    config_files[i], line);
            exit(1);
        }
    }

    free(config_files);

    if(default_wireless_hello_interval <= 0)
        default_wireless_hello_interval = 4000;
    default_wireless_hello_interval = MAX(default_wireless_hello_interval, 5);

    if(default_wired_hello_interval <= 0)
        default_wired_hello_interval = 4000;
    default_wired_hello_interval = MAX(default_wired_hello_interval, 5);

    resend_delay = 2000;
    resend_delay = MIN(resend_delay, default_wireless_hello_interval / 2);
    resend_delay = MIN(resend_delay, default_wired_hello_interval / 2);
    resend_delay = MAX(resend_delay, 20);

    if(do_daemonise) {
        if(logfile == NULL)
            logfile = "/var/log/babeld.log";
    }

    rc = reopen_logfile();
    if(rc < 0) {
        perror("reopen_logfile()");
        exit(1);
    }

    fd = open("/dev/null", O_RDONLY);
    if(fd < 0) {
        perror("open(null)");
        exit(1);
    }

    rc = dup2(fd, 0);
    if(rc < 0) {
        perror("dup2(null, 0)");
        exit(1);
    }

    close(fd);

    if(do_daemonise) {
        rc = daemonise();
        if(rc < 0) {
            perror("daemonise");
            exit(1);
        }
    }

    if(pidfile && pidfile[0] != '\0') {
        int pfd, len;
        char buf[100];

        len = snprintf(buf, 100, "%lu", (unsigned long)getpid());
        if(len < 0 || len >= 100) {
            perror("snprintf(getpid)");
            exit(1);
        }

        pfd = open(pidfile, O_WRONLY | O_CREAT | O_EXCL, 0644);
        if(pfd < 0) {
            char buf[40];
            snprintf(buf, 40, "creat(%s)", pidfile);
            buf[39] = '\0';
            perror(buf);
            exit(1);
        }

        rc = write(pfd, buf, len);
        if(rc < len) {
            perror("write(pidfile)");
            goto fail_pid;
        }

        close(pfd);
    }

    rc = kernel_setup(1);
    if(rc < 0) {
        fprintf(stderr, "kernel_setup failed.\n");
        goto fail_pid;
    }

    rc = kernel_setup_socket(1);
    if(rc < 0) {
        fprintf(stderr, "kernel_setup_socket failed.\n");
        kernel_setup(0);
        goto fail_pid;
    }

    rc = finalise_config();
    if(rc < 0) {
        fprintf(stderr, "Couldn't finalise configuration.\n");
        goto fail;
    }

    for(i = optind; i < argc; i++) {
        vrc = add_interface(argv[i], NULL);
        if(vrc == NULL)
            goto fail;
    }

    if(interfaces == NULL) {
        fprintf(stderr, "Eek... asked to run on no interfaces!\n");
        goto fail;
    }

    if(!have_id && !random_id) {
        /* We use all available interfaces here, since this increases the
           chances of getting a stable router-id in case the set of Babel
           interfaces changes. */

        for(i = 1; i < 256; i++) {
            char buf[IF_NAMESIZE], *ifname;
            unsigned char eui[8];
            ifname = if_indextoname(i, buf);
            if(ifname == NULL)
                continue;
            rc = if_eui64(ifname, i, eui);
            if(rc < 0)
                continue;
            memcpy(myid, eui, 8);
            have_id = 1;
            break;
        }
    }

    if(!have_id) {
        if(!random_id)
            fprintf(stderr,
                    "Warning: couldn't find router id -- "
                    "using random value.\n");
        rc = read_random_bytes(myid, 8);
        if(rc < 0) {
            perror("read(random)");
            goto fail;
        }
        /* Clear group and global bits */
        myid[0] &= ~3;
    }

    myseqno = (random() & 0xFFFF);

    fd = open(state_file, O_RDONLY);
    if(fd < 0 && errno != ENOENT)
        perror("open(babel-state)");
    rc = unlink(state_file);
    if(fd >= 0 && rc < 0) {
        perror("unlink(babel-state)");
        /* If we couldn't unlink it, it's probably stale. */
        close(fd);
        fd = -1;
    }
    if(fd >= 0) {
        char buf[100];
        int s;
        rc = read(fd, buf, 99);
        if(rc < 0) {
            perror("read(babel-state)");
        } else {
            buf[rc] = '\0';
            rc = sscanf(buf, "%d\n", &s);
            if(rc == 1 && s >= 0 && s <= 0xFFFF) {
                myseqno = seqno_plus(s, 1);
            } else {
                fprintf(stderr, "Couldn't parse babel-state.\n");
            }
        }
        close(fd);
        fd = -1;
    }

    protocol_socket = babel_socket(protocol_port);
    if(protocol_socket < 0) {
        perror("Couldn't create link local socket");
        goto fail;
    }

    if(local_server_port >= 0) {
        local_server_socket = tcp_server_socket(local_server_port, 1);
        if(local_server_socket < 0) {
            perror("local_server_socket");
            goto fail;
        }
    } else if(local_server_path) {
        local_server_socket = unix_server_socket(local_server_path);
        if(local_server_socket < 0) {
            perror("local_server_socket");
            goto fail;
        }
    }

    init_signals();
    rc = resize_receive_buffer(1500);
    if(rc < 0)
        goto fail;
    if(receive_buffer == NULL)
        goto fail;

    check_interfaces();

    rc = check_xroutes(0);
    if(rc < 0)
        fprintf(stderr, "Warning: couldn't check exported routes.\n");
    rc = check_rules();
    if(rc < 0)
        fprintf(stderr, "Warning: couldn't check rules.\n");

    kernel_routes_changed = 0;
    kernel_rules_changed = 0;
    kernel_link_changed = 0;
    kernel_addr_changed = 0;
    kernel_dump_time = now.tv_sec + roughly(30);
    schedule_neighbours_check(5000, 1);
    schedule_interfaces_check(30000, 1);
    expiry_time = now.tv_sec + roughly(30);
    source_expiry_time = now.tv_sec + roughly(300);

    /* Make some noise so that others notice us, and send retractions in
       case we were restarted recently */
    FOR_ALL_INTERFACES(ifp) {
        if(!if_up(ifp))
            continue;
        /* Apply jitter before we send the first message. */
        usleep(roughly(10000));
        gettime(&now);
        send_hello(ifp);
        send_wildcard_retraction(ifp);
    }

    FOR_ALL_INTERFACES(ifp) {
        if(!if_up(ifp))
            continue;
        usleep(roughly(10000));
        gettime(&now);
        send_hello(ifp);
        send_wildcard_retraction(ifp);
        send_self_update(ifp);
        send_request(ifp, NULL, 0, NULL, 0);
        flushupdates(ifp);
        flushbuf(ifp);
    }

    debugf("Entering main loop.\n");

    while(1) {
        struct timeval tv;
        fd_set readfds;

        gettime(&now);

        tv = check_neighbours_timeout;
        timeval_min(&tv, &check_interfaces_timeout);
        timeval_min_sec(&tv, expiry_time);
        timeval_min_sec(&tv, source_expiry_time);
        timeval_min_sec(&tv, kernel_dump_time);
        timeval_min(&tv, &resend_time);
        FOR_ALL_INTERFACES(ifp) {
            if(!if_up(ifp))
                continue;
            timeval_min(&tv, &ifp->flush_timeout);
            timeval_min(&tv, &ifp->hello_timeout);
            timeval_min(&tv, &ifp->update_timeout);
            timeval_min(&tv, &ifp->update_flush_timeout);
        }
        timeval_min(&tv, &unicast_flush_timeout);
        FD_ZERO(&readfds);
        if(timeval_compare(&tv, &now) > 0) {
            int maxfd = 0;
            timeval_minus(&tv, &tv, &now);
            FD_SET(protocol_socket, &readfds);
            maxfd = MAX(maxfd, protocol_socket);
            if(kernel_socket < 0) kernel_setup_socket(1);
            if(kernel_socket >= 0) {
                FD_SET(kernel_socket, &readfds);
                maxfd = MAX(maxfd, kernel_socket);
            }
            if(local_server_socket >= 0 &&
               num_local_sockets < MAX_LOCAL_SOCKETS) {
                FD_SET(local_server_socket, &readfds);
                maxfd = MAX(maxfd, local_server_socket);
            }
            for(i = 0; i < num_local_sockets; i++) {
                FD_SET(local_sockets[i].fd, &readfds);
                maxfd = MAX(maxfd, local_sockets[i].fd);
            }
            rc = select(maxfd + 1, &readfds, NULL, NULL, &tv);
            if(rc < 0) {
                if(errno != EINTR) {
                    perror("select");
                    sleep(1);
                }
                rc = 0;
                FD_ZERO(&readfds);
            }
        }

        gettime(&now);

        if(exiting)
            break;

        if(kernel_socket >= 0 && FD_ISSET(kernel_socket, &readfds)) {
            struct kernel_filter filter = {0};
            filter.route = kernel_route_notify;
            filter.addr = kernel_addr_notify;
            filter.link = kernel_link_notify;
            filter.rule = kernel_rule_notify;
            kernel_callback(&filter);
        }

        if(FD_ISSET(protocol_socket, &readfds)) {
            rc = babel_recv(protocol_socket,
                            receive_buffer, receive_buffer_size,
                            (struct sockaddr*)&sin6, sizeof(sin6));
            if(rc < 0) {
                if(errno != EAGAIN && errno != EINTR) {
                    perror("recv");
                    sleep(1);
                }
            } else {
                FOR_ALL_INTERFACES(ifp) {
                    if(!if_up(ifp))
                        continue;
                    if(ifp->ifindex == sin6.sin6_scope_id) {
                        parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
                                     receive_buffer, rc);
                        VALGRIND_MAKE_MEM_UNDEFINED(receive_buffer,
                                                    receive_buffer_size);
                        break;
                    }
                }
            }
        }

        if(local_server_socket >= 0 && FD_ISSET(local_server_socket, &readfds))
           accept_local_connections();

        i = 0;
        while(i < num_local_sockets) {
            if(FD_ISSET(local_sockets[i].fd, &readfds)) {
                rc = local_read(&local_sockets[i]);
                if(rc <= 0) {
                    if(rc < 0) {
                        if(errno == EINTR || errno == EAGAIN)
                            continue;
                        perror("read(local_socket)");
                    }
                    local_socket_destroy(i);
                }
            }
            i++;
        }

        if(reopening) {
            kernel_dump_time = now.tv_sec;
            check_neighbours_timeout = now;
            expiry_time = now.tv_sec;
            rc = reopen_logfile();
            if(rc < 0) {
                perror("reopen_logfile");
                break;
            }
            reopening = 0;
        }

        if(kernel_link_changed || kernel_addr_changed) {
            check_interfaces();
            kernel_link_changed = 0;
        }

        if(kernel_routes_changed || kernel_addr_changed ||
           kernel_rules_changed || now.tv_sec >= kernel_dump_time) {
            rc = check_xroutes(1);
            if(rc < 0)
                fprintf(stderr, "Warning: couldn't check exported routes.\n");
            rc = check_rules();
            if(rc < 0)
                fprintf(stderr, "Warning: couldn't check rules.\n");
            kernel_routes_changed = kernel_rules_changed =
                kernel_addr_changed = 0;
            if(kernel_socket >= 0)
                kernel_dump_time = now.tv_sec + roughly(300);
            else
                kernel_dump_time = now.tv_sec + roughly(30);
        }

        if(timeval_compare(&check_neighbours_timeout, &now) < 0) {
            int msecs;
            msecs = check_neighbours();
            /* Multiply by 3/2 to allow neighbours to expire. */
            msecs = MAX(3 * msecs / 2, 10);
            schedule_neighbours_check(msecs, 1);
        }

        if(timeval_compare(&check_interfaces_timeout, &now) < 0) {
            check_interfaces();
            schedule_interfaces_check(30000, 1);
        }

        if(now.tv_sec >= expiry_time) {
            expire_routes();
            expire_resend();
            expiry_time = now.tv_sec + roughly(30);
        }

        if(now.tv_sec >= source_expiry_time) {
            expire_sources();
            source_expiry_time = now.tv_sec + roughly(300);
        }

        FOR_ALL_INTERFACES(ifp) {
            if(!if_up(ifp))
                continue;
            if(timeval_compare(&now, &ifp->hello_timeout) >= 0)
                send_hello(ifp);
            if(timeval_compare(&now, &ifp->update_timeout) >= 0)
                send_update(ifp, 0, NULL, 0, NULL, 0);
            if(timeval_compare(&now, &ifp->update_flush_timeout) >= 0)
                flushupdates(ifp);
        }

        if(resend_time.tv_sec != 0) {
            if(timeval_compare(&now, &resend_time) >= 0)
                do_resend();
        }

        if(unicast_flush_timeout.tv_sec != 0) {
            if(timeval_compare(&now, &unicast_flush_timeout) >= 0)
                flush_unicast(1);
        }

        FOR_ALL_INTERFACES(ifp) {
            if(!if_up(ifp))
                continue;
            if(ifp->flush_timeout.tv_sec != 0) {
                if(timeval_compare(&now, &ifp->flush_timeout) >= 0)
                    flushbuf(ifp);
            }
        }

        if(UNLIKELY(debug || dumping)) {
            dump_tables(stdout);
            dumping = 0;
        }
    }
Ejemplo n.º 14
0
int main(int argc, char *argv[])
{
  FILE *fp;

#if USING_DMALLOC
  dmalloc_debug(1);
#endif

	/* start the clock (which is used by the Logit fnc) */
  (void) refetch_ticker();
  GetArgs(argc, argv);
  if (conf_file_read(confname)) {
    Logit("Failed to read config file \"%s\"", confname);
    strcpy(confname, "./nngs.cnf");
    conf_file_write(confname);
    Logit("Created \"%s\"", confname);
  }
  Logit("Starting %s (%s %s) From: %s"
  , conffile.version_string, conffile.compile_date, conffile.compile_time, confname);
  if (daemonise()) {
    Logit("Failed to daemonise, giving up");
    main_exit(1);
  }
  conf_file_write("written.cnf");
  signal(SIGTERM, TerminateServer);
  signal(SIGINT, TerminateServer);
#if 0
  signal(SIGPIPE, SIG_IGN);
#else
  signal(SIGPIPE, BrokenPipe);
#endif
  signal(SIGCHLD, reapchild);
  mink_init();
  startuptime = time(NULL);
  srand(startuptime);
  read_ban_ip_list();
  if (!all_the_internets() ) {
    fprintf(stderr, "Network initialize failed on ports %s.\n"
    , conffile.server_ports);
    main_exit(1);
  }
  player_high = 0;
  game_high = 0;
  bytes_sent = 0;
  bytes_received = 0;

#ifdef SGI
  /*mallopt(100, 1);*/  /* Turn on malloc(3X) debugging (Irix only) */
#endif
  command_init();
  EmoteInit(conffile.emotes_file);
  help_init();
  /*Logit("commands_init()");*/
  commands_init();
  /*Logit("channel_init()");*/
  channel_init();
  /*Logit("player_array_init()");*/
  player_array_init();
  player_init();
  ladder_init(NUM_LADDERS);
  Ladder9 = ladder_new(LADDERSIZE);
  Ladder19 = ladder_new(LADDERSIZE);

  completed_games = 0;
  num_logins = num_logouts = new_players = 0;

  num_9 = 0;
  fp = xyfopen(FILENAME_LADDER9, "r");
  if (fp) {
    num_9 = ladder_load(fp, Ladder9);
    Logit("%d players loaded from file %s", num_9, filename() );
    fclose(fp);
  }

  num_19 = 0;
  fp = xyfopen(FILENAME_LADDER19, "r");
  if (fp) {
    num_19 = ladder_load(fp, Ladder19);
    Logit("%d players loaded from file %s", num_19, filename() );
    fclose(fp);
  }

  /* mink_init();*/
  if (conffile.admin_name) create_admin_account(conffile.admin_name );
  Logit("Server up and running.");
  main_event_loop();
  Logit("Closing down.");
  net_closeAll();
  main_exit(0);
  return 0;
}
Ejemplo n.º 15
0
int main(int argc, char **argv)
{
    int err;

    parseArguments(argc, argv);

    if (nodaemon == 0) {
        err = daemonise();
        if (err != 0) exit(1);

        err = writePidFile(pidFile);
        if (err != 0) exit(1);
    }

    err = signalisation();
    if (err != 0) exit(1);

    serverSocket = openServerSocket(port);
    if (serverSocket == -1) exit(1);

    request_t req;
    response_t resp;
    output_t output;

    memset(&output, 0, sizeof(output_t));

    while (serverSocket != -1) {

        memset(&req, 0, sizeof(request_t));
        memset(&resp, 0, sizeof(response_t));

        int client = serverSocketAccept(serverSocket);
        if (client == -1)
            continue;


        int r = parseRequest(client, &req, &resp);
        if (r != 0) {
            clientPrintf(client, "HTTP/1.1 %03d\r\n", resp.status);
            closeClient(client);
            continue;
        }

        if (1) {
            printf("path: %s\n", req.path);
            for (int i =0; i < req.num_args; i++)
                printf("arg[%d]: %s = %s\n", i, req.names[i], req.values[i]);
        }

        const char* cmdline = findCommand(req.path);

        if (cmdline == NULL) {
            log_warn("Daemon: Invalid path: '%s'\n", req.path);
            clientPrint(client, "HTTP/1.1 404\r\n");
            closeClient(client);
            continue;
        }

        if (execute(&output, cmdline) != 0) {
            clientPrint(client, "HTTP/1.1 500\r\n"); // Internal server error
            closeClient(client);
            continue;
        }

        if ((output.count > 8) && (strncmp(output.buf, "HTTP/1.1", 8) == 0)) {
            clientWrite(client, output.buf, output.count);
        } else {
            clientPrintf(client, "HTTP/1.1 200\r\nContent-Length: %d\r\n\r\n",
                         output.count);
            clientWrite(client, output.buf, output.count);
        }

        closeClient(client);

        output_clear(&output);
        if (req.path) free(req.path);
    }

    removePidFile(pidFile);

    return 0;
}
Ejemplo n.º 16
0
/**
 * rtevald_parser main function.
 *
 * @param argc
 * @param argv
 *
 * @return Returns the result of the process_submission_queue() function.
 */
int main(int argc, char **argv) {
        eurephiaVALUES *config = NULL, *prgargs = NULL;
        char xsltfile[2050], *reportdir = NULL;
	xsltStylesheet *xslt = NULL;
	dbconn *dbc = NULL;
        pthread_t **threads = NULL;
        pthread_attr_t **thread_attrs = NULL;
	pthread_mutex_t mtx_sysreg = PTHREAD_MUTEX_INITIALIZER;
	pthread_mutex_t mtx_thrcnt = PTHREAD_MUTEX_INITIALIZER;
	threadData_t **thrdata = NULL;
	struct mq_attr msgq_attr;
	mqd_t msgq = 0;
	int i,rc, mq_init = 0, max_threads = 0, started_threads = 0, activethreads = 0;
	unsigned int max_report_size = 0;

	// Initialise XML and XSLT libraries
	xsltInit();
	xmlInitParser();

	prgargs = parse_arguments(argc, argv);
	if( prgargs == NULL ) {
		fprintf(stderr, "** ERROR **  Failed to parse program arguments\n");
		rc = 2;
		goto exit;
	}

	// Setup a log context
	logctx = init_log(eGet_value(prgargs, "log"), eGet_value(prgargs, "loglevel"));
	if( !logctx ) {
		fprintf(stderr, "** ERROR **  Could not setup a log context\n");
		eFree_values(prgargs);
		rc = 2;
		goto exit;
	}

	// Fetch configuration
        config = read_config(logctx, prgargs, "xmlrpc_parser");
	eFree_values(prgargs); // read_config() copies prgargs into config, we don't need prgargs anymore

	// Daemonise process if requested
	if( atoi_nullsafe(eGet_value(config, "daemon")) == 1 ) {
		if( daemonise(logctx) < 1 ) {
			rc = 3;
			goto exit;
		}
	}


	// Parse XSLT template
	snprintf(xsltfile, 512, "%s/%s", eGet_value(config, "xsltpath"), XMLPARSER_XSL);
	writelog(logctx, LOG_DEBUG, "Parsing XSLT file: %s", xsltfile);
        xslt = xsltParseStylesheetFile((xmlChar *) xsltfile);
	if( !xslt ) {
		writelog(logctx, LOG_EMERG, "Could not parse XSLT template: %s", xsltfile);
		rc = 2;
		goto exit;
	}

	// Open a POSIX MQ
	writelog(logctx, LOG_DEBUG, "Preparing POSIX MQ queue: /rteval_parsequeue");
	memset(&msgq, 0, sizeof(mqd_t));
	msgq_attr.mq_maxmsg = get_mqueue_msg_max(logctx);
	msgq_attr.mq_msgsize = sizeof(parseJob_t);
	msgq_attr.mq_flags = O_NONBLOCK;
	msgq = mq_open("/rteval_parsequeue", O_RDWR | O_CREAT, 0600, &msgq_attr);
	if( msgq < 0 ) {
		writelog(logctx, LOG_EMERG,
			 "Could not open message queue: %s", strerror(errno));
		rc = 2;
		goto exit;
	}
	mq_init = 1;

	// Get the number of worker threads
	max_threads = atoi_nullsafe(eGet_value(config, "threads"));
	if( max_threads == 0 ) {
		max_threads = 4;
	}

	// Get a database connection for the main thread
        dbc = db_connect(config, max_threads, logctx);
        if( !dbc ) {
		rc = 4;
		goto exit;
        }

	// Prepare all threads
	threads = calloc(max_threads + 1, sizeof(pthread_t *));
	thread_attrs = calloc(max_threads + 1, sizeof(pthread_attr_t *));
	thrdata = calloc(max_threads + 1, sizeof(threadData_t *));
	assert( (threads != NULL) && (thread_attrs != NULL) && (thrdata != NULL) );

	reportdir = eGet_value(config, "reportdir");
	writelog(logctx, LOG_INFO, "Starting %i worker threads", max_threads);
	max_report_size = defaultIntValue(atoi_nullsafe(eGet_value(config, "max_report_size")), 1024*1024);
	for( i = 0; i < max_threads; i++ ) {
		// Prepare thread specific data
		thrdata[i] = malloc_nullsafe(logctx, sizeof(threadData_t));
		if( !thrdata[i] ) {
			writelog(logctx, LOG_EMERG,
				 "Could not allocate memory for thread data");
			rc = 2;
			goto exit;
		}

		// Get a database connection for the thread
		thrdata[i]->dbc = db_connect(config, i, logctx);
		if( !thrdata[i]->dbc ) {
			writelog(logctx, LOG_EMERG,
				"Could not connect to the database for thread %i", i);
			rc = 2;
			shutdown = 1;
			goto exit;
		}

		thrdata[i]->shutdown = &shutdown;
		thrdata[i]->threadcount = &activethreads;
		thrdata[i]->mtx_thrcnt = &mtx_thrcnt;
		thrdata[i]->id = i;
		thrdata[i]->msgq = msgq;
		thrdata[i]->mtx_sysreg = &mtx_sysreg;
		thrdata[i]->xslt = xslt;
		thrdata[i]->destdir = reportdir;
		thrdata[i]->max_report_size = max_report_size;

		thread_attrs[i] = malloc_nullsafe(logctx, sizeof(pthread_attr_t));
		if( !thread_attrs[i] ) {
			writelog(logctx, LOG_EMERG,
				"Could not allocate memory for thread attributes");
			rc = 2;
			goto exit;
		}
		pthread_attr_init(thread_attrs[i]);
		pthread_attr_setdetachstate(thread_attrs[i], PTHREAD_CREATE_JOINABLE);

		threads[i] = malloc_nullsafe(logctx, sizeof(pthread_t));
		if( !threads[i] ) {
			writelog(logctx, LOG_EMERG,
				"Could not allocate memory for pthread_t");
			rc = 2;
			goto exit;
		}
	}

	// Setup signal catching
	signal(SIGINT,  sigcatch);
	signal(SIGTERM, sigcatch);
	signal(SIGHUP,  SIG_IGN);
	signal(SIGUSR1, sigcatch);
	signal(SIGUSR2, SIG_IGN);

	// Start the threads
	for( i = 0; i < max_threads; i++ ) {
		int thr_rc = pthread_create(threads[i], thread_attrs[i], parsethread, thrdata[i]);
		if( thr_rc < 0 ) {
			writelog(logctx, LOG_EMERG,
				 "** ERROR **  Failed to start thread %i: %s",
				 i, strerror(thr_rc));
			rc = 3;
			goto exit;
		}
		started_threads++;
	}

	// Main routine
	//
	// checks the submission queue and puts unprocessed records on the POSIX MQ
	// to be parsed by one of the threads
	//
	sleep(3); // Allow at least a few parser threads to settle down first before really starting
	writelog(logctx, LOG_DEBUG, "Starting submission queue checker");
	rc = process_submission_queue(dbc, msgq, &activethreads);
	writelog(logctx, LOG_DEBUG, "Submission queue checker shut down");

 exit:
	// Clean up all threads
	for( i = 0; i < max_threads; i++ ) {
		// Wait for all threads to exit
		if( (i < started_threads) && threads && threads[i] ) {
			void *thread_rc;
			int j_rc;

			if( (j_rc = pthread_join(*threads[i], &thread_rc)) != 0 ) {
				writelog(logctx, LOG_CRIT,
					 "Failed to join thread %i: %s",
					 i, strerror(j_rc));
			}
			pthread_attr_destroy(thread_attrs[i]);
		}
		if( threads ) {
			free_nullsafe(threads[i]);
		}
		if( thread_attrs ) {
			free_nullsafe(thread_attrs[i]);
		}

		// Disconnect threads database connection
		if( thrdata && thrdata[i] ) {
			db_disconnect(thrdata[i]->dbc);
			free_nullsafe(thrdata[i]);
		}
	}
	free_nullsafe(thrdata);
	free_nullsafe(threads);
	free_nullsafe(thread_attrs);

	// Close message queue
	if( mq_init == 1 ) {
		errno = 0;
		if( mq_close(msgq) < 0 ) {
			writelog(logctx, LOG_CRIT, "Failed to close message queue: %s",
				 strerror(errno));
		}
		errno = 0;
		if( mq_unlink("/rteval_parsequeue") < 0 ) {
			writelog(logctx, LOG_ALERT, "Failed to remove the message queue: %s",
				 strerror(errno));
		}
	}

	// Disconnect from database, main thread connection
	db_disconnect(dbc);

	// Free up the rest
	eFree_values(config);
	xsltFreeStylesheet(xslt);
	xmlCleanupParser();
	xsltCleanupGlobals();

	writelog(logctx, LOG_EMERG, "rteval-parserd is stopped");
	close_log(logctx);
	return rc;
}
Ejemplo n.º 17
0
Archivo: main.c Proyecto: bioboy/ebbnc2
int main(int argc, char** argv)
{
#ifndef CONF_EMBEDDED
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <config file>\n", argv[0]);
        return 1;
    }
#else
    if (argc != 1) {
        fprintf(stderr, "Usage: %s\n", argv[0]);
        fprintf(stderr, "Built with an embedded conf.\n");
        return 1;
    }

    char* key = getpass("Password: "******"Password is required to load embedded conf.\n");
        return 1;
    }
#endif

    hline();
    printf("%s %s by %s\n", EBBNC_PROGRAM, EBBNC_VERSION, EBBNC_AUTHOR);
    hline();
    atexit(hline);

    printf("Initialising signals ..\n");
    InitialiseSignals();

    printf("Loading config file ..\n");

#ifndef CONF_EMBEDDED
    Config* config = Config_loadFile(argv[1]);
#else
    Config* config = Config_loadEmbedded(key);
#endif
    if (!config) { return 1; }

    if (config->pidFile) {
        printf("Checking if bouncer already running ..\n");
        int ret = isAlreadyRunning(config->pidFile);
        if (ret < 0) {
            fprintf(stderr, "Unable to check if already running: %s\n", strerror(errno));
            Config_free(&config);
            return 1;
        }

        if (ret != 0) {
            fprintf(stderr, "Bouncer already running!\n");
            Config_free(&config);
            return 1;
        }
    }

    printf("Initialising listening sockets ..\n");
    Server* servers = Server_listenAll(config);
    if (!servers) {
        Config_free(&config);
        return 1;
    }

    printf("Forking into background ..\n");
    pid_t pid = daemonise();
    if (pid < 0) {
        fprintf(stderr, "Failed to fork into background.\n");
        Server_freeList(&servers);
        Config_free(&config);
        return 1;
    }

    if (pid > 0) {
        printf("Bouncer running as PID #%i\n", pid);
        if (config->pidFile) {
            printf("Creating PID file at %s ..\n", config->pidFile);
            if (!createPIDFile(config->pidFile, pid)) {
                // this goes to /dev/null at the moment
                // this error is not fatal
                fprintf(stderr, "Failed to create PID file. This is only a warning.\n");
            }
        }

        hline();
        _exit(0);
    }

    printf("Waiting for connections ..\n");
    Server_loop(servers);

    Server_freeList(&servers);
    Config_free(&config);

    return 0;

    (void) argc;
}
Ejemplo n.º 18
0
int main(int argc, char ** argv)
{
    interactive_signals();

    if (loadConfig(argc, argv, true) < 0) {
        // Fatal error loading config file
        return EXIT_CONFIG_ERROR;
    }

    if (daemon_flag) {
        int pid = daemonise();
        if (pid == -1) {
            return EXIT_FORK_ERROR;
        } else if (pid > 0) {
            return EXIT_SUCCESS;
        }
    }

    // If we are a daemon logging to syslog, we need to set it up.
    initLogger();

    // Initialise the persistance subsystem. If we have been built with
    // database support, this will open the various databases used to
    // store server data.
    if (database_flag) {
        Persistence * p = Persistence::instance();
        int dbstatus = p->init();
        if (dbstatus < 0) {
            database_flag = false;
            log(ERROR, "Error opening database. Database disabled.");
            if (dbstatus == DATABASE_TABERR) {
                log(INFO, "Database connection established, "
                          "but unable to create required tables.");
                log(INFO, "Please ensure that any obsolete database "
                          "tables have been removed.");
            } else {
                log(INFO, "Unable to connect to the RDBMS.");
                log(INFO, "Please ensure that the RDBMS is running, "
                          "the cyphesis database exists and is accessible "
                          "to the user running cyphesis.");
            }
            log(INFO, String::compose("To disable this message please run:\n\n"
                                      "    cyconfig --%1:usedatabase=false\n\n"
                                      "to permanently disable database usage.",
                                      instance));
        }
    }

    // If the restricted flag is set in the config file, then we
    // don't allow connecting users to create accounts. Accounts must
    // be created manually by the server administrator.
    if (readConfigItem("cyphesis","restricted", restricted_flag) == 0) {
        if (restricted_flag) {
            log(INFO, "Setting restricted mode.");
        }
    }

    readConfigItem("cyphesis","inittime", timeoffset);

    std::string mserver("metaserver.worldforge.org");
    readConfigItem("cyphesis", "metaserver", mserver);

    std::string serverName;
    if (readConfigItem("cyphesis","servername", serverName) != 0) {
        serverName = get_hostname();
    }

    std::string serverHostname("localhost");
    readConfigItem("slave","server", serverHostname);
    
    // Start up the python subsystem.
    init_python_api();

    { // scope for CommServer

    // Create commserver instance that will handle connections from clients.
    // The commserver will create the other server related objects, and the
    // world object pair (World + WorldRouter), and initialise the admin
    // account. The primary ruleset name is passed in so it
    // can be stored and queried by clients.
    WorldRouter world;

    // This ID is currently generated every time, but should perhaps be
    // persistent in future.
    std::string server_id, lobby_id;
    long int_id, lobby_int_id;

    if (((int_id = newId(server_id)) < 0) ||
        ((lobby_int_id = newId(lobby_id)) < 0)) {
        log(CRITICAL, "Unable to get server IDs from Database");
        return EXIT_DATABASE_ERROR;
    }

    ServerRouting server(world, ruleset, serverName,
                         server_id, int_id,
                         lobby_id, lobby_int_id);

    CommServer commServer(server);

    // This is where we should restore the database, before
    // the listen sockets are open. Unlike earlier code, we are
    // attempting to construct the internal state from the database,
    // not creating a new world using the contents of the database as a
    // template

    CommUnixListener * listener = new CommUnixListener(commServer,
          *new CommClientFactory<SlaveClientConnection>());
    if (listener->setup(slave_socket_name) != 0) {
        log(ERROR, "Could not create listen socket. Init failed.");
        return EXIT_SOCKET_ERROR;
    }
    commServer.addSocket(listener);

    std::string master_id;
    if (newId(master_id) < 0) {
        log(CRITICAL, "Unable to get master ID from Database");
        return EXIT_DATABASE_ERROR;
    }

    CommMaster * master = new CommMaster(commServer);
    if (master->connect(serverHostname) != 0) {
        log(ERROR, "Could not connect to master. Init failed.");
        return EXIT_SOCKET_ERROR;
    }
    master->setup(new Master(*master, commServer.m_server, master_id));
    commServer.addSocket(master);

    log(INFO, "Running");

    // Inform things that want to know that we are running.
    running();

    // Loop until the exit flag is set. The exit flag can be set anywhere in
    // the code easily.
    while (!exit_flag) {
        try {
            commServer.poll();
        }
        catch (...) {
            // It is hoped that commonly thrown exception, particularly
            // exceptions that can be caused  by external influences
            // should be caught close to where they are thrown. If
            // an exception makes it here then it should be debugged.
            log(ERROR, "Exception caught in main()");
        }
    }
    // exit flag has been set so we close down the databases, and indicate
    // to the metaserver (if we are using one) that this server is going down.
    // It is assumed that any preparation for the shutdown that is required
    // by the game has been done before exit flag was set.
    log(NOTICE, "Performing clean shutdown...");

    } // close scope of CommServer, which cause the destruction of the
      // server and world objects, and the entire world contents

    Persistence::instance()->shutdown();

    EntityBuilder::instance()->flushFactories();
    EntityBuilder::del();
    MindFactory::del();

    Inheritance::clear();

    // Shutdown the python interpretter. This frees lots of memory, and if
    // the malloc heap is in any way corrupt, a segfault is likely to
    // occur at this point. Previous occassions where pointers have been
    // deleted twice elsewhere in the code, have resulted in a segfault
    // at this point. AlRiddoch 10th November 2001
    shutdown_python_api();

    delete global_conf;

    log(INFO, "Clean shutdown complete.");
    return 0;
}
Ejemplo n.º 19
0
int main(int argc, char *argv[])
{
	pid_t pid;
	struct sigaction sa;

	if (init_preferences(argc, argv) == FALSE)
		g_error("Config file parsing failed");

	/* Open the log file before forking, so that if there is an error, the
	 * user will get some idea what is going on */
	open_log(prefs.log_file);

	g_log_set_default_handler(scmpc_log, NULL);

	/* Check if scmpc is already running */
	if ((pid = scmpc_is_running()) > 0) {
		clear_preferences();
		g_error("Daemon is already running with PID: %ld", (long)pid);
	}

	/* Daemonise if wanted */
	if (prefs.fork)
		daemonise();

	/* Signal handler */
	open_signal_pipe();
	sa.sa_handler = sighandler;
	sigfillset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGQUIT, &sa, NULL);

	if (as_connection_init() == FALSE) {
		scmpc_cleanup();
		exit(EXIT_FAILURE);
	}
	as_authenticate();

	queue_init();
	queue_load();

	// submit the loaded queue
	as_check_submit();

	mpd.song_pos = g_timer_new();
	mpd.idle_source = 0;
	if (!mpd_connect()) {
		mpd_disconnect();
		mpd_schedule_reconnect();
	}

	// set up main loop events
	loop = g_main_loop_new(NULL, FALSE);

	// save queue
	if (prefs.cache_interval > 0) {
		cache_save_source = g_timeout_add_seconds(prefs.cache_interval * 60,
				queue_save, NULL);
	}

	g_main_loop_run(loop);

	scmpc_cleanup();
}
Ejemplo n.º 20
0
int main(int argc, char ** argv)
{
    if (security_init() != 0) {
        log(CRITICAL, "Security initialisation Error. Exiting.");
        return EXIT_SECURITY_ERROR;
    }

    if (security_check() != SECURITY_OKAY) {
        log(CRITICAL, "Security check error. Exiting.");
        return EXIT_SECURITY_ERROR;
    }

    interactive_signals();

    int config_status = loadConfig(argc, argv, USAGE_SERVER);
    if (config_status < 0) {
        if (config_status == CONFIG_VERSION) {
            std::cout << argv[0] << " (cyphesis) " << consts::version
                      << " (Cyphesis build " << consts::buildId << ")"
                      << std::endl << std::flush;

            return 0;
        } else if (config_status == CONFIG_HELP) {
            showUsage(argv[0], USAGE_SERVER);
            return 0;
        } else if (config_status != CONFIG_ERROR) {
            log(ERROR, "Unknown error reading configuration.");
        }
        // Fatal error loading config file.
        return EXIT_CONFIG_ERROR;
    }

    if (daemon_flag) {
        int pid = daemonise();
        if (pid == -1) {
            return EXIT_FORK_ERROR;
        } else if (pid > 0) {
            return EXIT_SUCCESS;
        }
    }

    readConfigItem(instance, "usedatabase", database_flag);

    // If we are a daemon logging to syslog, we need to set it up.
    initLogger();

    // Initialise the persistance subsystem. If we have been built with
    // database support, this will open the various databases used to
    // store server data.
    if (database_flag) {
        Persistence * p = Persistence::instance();
        int dbstatus = p->init();
        if (dbstatus < 0) {
            database_flag = false;
            log(ERROR, "Error opening database. Database disabled.");
            if (dbstatus == DATABASE_TABERR) {
                log(INFO, "Database connection established, "
                          "but unable to create required tables.");
                log(INFO, "Please ensure that any obsolete database "
                          "tables have been removed.");
            } else {
                log(INFO, "Unable to connect to the RDBMS.");
                log(INFO, "Please ensure that the RDBMS is running, "
                          "the cyphesis database exists and is accessible "
                          "to the user running cyphesis.");
            }
            log(INFO, String::compose("To disable this message please run:\n\n"
                                      "    cyconfig --%1:usedatabase=false\n\n"
                                      "to permanently disable database usage.",
                                      instance));
        }
    }

    // If the restricted flag is set in the config file, then we
    // don't allow connecting users to create accounts. Accounts must
    // be created manually by the server administrator.
    if (restricted_flag) {
        log(INFO, "Setting restricted mode.");
    }

    readConfigItem(instance, "inittime", timeoffset);

    std::string server_name;
    if (readConfigItem(instance, "servername", server_name) != 0) {
        if (instance == CYPHESIS) {
            server_name = get_hostname();
        } else {
            server_name = instance;
        }
    }

    int nice = 1;
    readConfigItem(instance, "nice", nice);
    
    // Start up the python subsystem.
    init_python_api();

    { // scope for CommServer

    // Create commserver instance that will handle connections from clients.
    // The commserver will create the other server related objects, and the
    // world object pair (World + WorldRouter), and initialise the admin
    // account. The primary ruleset name is passed in so it
    // can be stored and queried by clients.
    Inheritance::instance();

    WorldRouter world;

    Ruleset::init();

    TeleportAuthenticator::init();

    StorageManager store(world);

    // This ID is currently generated every time, but should perhaps be
    // persistent in future.
    std::string server_id, lobby_id;
    long int_id, lobby_int_id;

    if (((int_id = newId(server_id)) < 0) ||
        ((lobby_int_id = newId(lobby_id)) < 0)) {
        log(CRITICAL, "Unable to get server IDs from Database");
        return EXIT_DATABASE_ERROR;
    }

    ServerRouting server(world, ruleset, server_name,
                         server_id, int_id,
                         lobby_id, lobby_int_id);

    CommServer commServer(server);

    if (commServer.setup() != 0) {
        log(CRITICAL, "Internal error setting up server infrastructure");
        return EXIT_SOCKET_ERROR;
    }

    // This is where we should restore the database, before
    // the listen sockets are open. Unlike earlier code, we are
    // attempting to construct the internal state from the database,
    // not creating a new world using the contents of the database as a
    // template

    if (database_flag) {
        // log(INFO, _("Restoring world from database..."));

        store.restoreWorld();
        // FIXME Do the following steps.
        // Read the world entity if any from the database, or set it up.
        // If it was there, make sure it did not get any of the wrong
        // position or orientation data.
        store.initWorld();

        // log(INFO, _("Restored world."));

        CommPSQLSocket * dbsocket = new CommPSQLSocket(commServer,
                                        Persistence::instance()->m_connection);
        commServer.addSocket(dbsocket);
        commServer.addIdle(dbsocket);

        IdleConnector * storage_idle = new IdleConnector(commServer);
        storage_idle->idling.connect(sigc::mem_fun(&store, &StorageManager::tick));
        commServer.addIdle(storage_idle);
    } else {
        std::string adminId;
        long intId = newId(adminId);
        assert(intId >= 0);

        Admin * admin = new Admin(0, "admin", "BAD_HASH", adminId, intId);
        server.addAccount(admin);
    }

    // Add the test object, and call it regularly so it can do what it does.
    // UpdateTester * update_tester = new UpdateTester(commServer);
    // commServer.addIdle(update_tester);

    CommTCPListener * listener = new CommTCPListener(commServer,
          *new CommClientFactory<Connection>());
    if (client_port_num < 0) {
        client_port_num = dynamic_port_start;
        for (; client_port_num <= dynamic_port_end; client_port_num++) {
            if (listener->setup(client_port_num) == 0) {
                break;
            }
        }
        if (client_port_num > dynamic_port_end) {
            log(ERROR, String::compose("Could not find free client listen "
                                       "socket in range %1-%2. Init failed.",
                                       dynamic_port_start, dynamic_port_end));
            log(INFO, String::compose("To allocate 8 more ports please run:"
                                      "\n\n    cyconfig "
                                      "--cyphesis:dynamic_port_end=%1\n\n",
                                      dynamic_port_end + 8));
            return EXIT_PORT_ERROR;
        }
        log(INFO, String::compose("Auto configuring new instance \"%1\" "
                                  "to use port %2.",
                                  instance, client_port_num));
        global_conf->setItem(instance, "tcpport", client_port_num,
                             varconf::USER);
        global_conf->setItem(CYPHESIS, "dynamic_port_start",
                             client_port_num + 1, varconf::USER);
    } else {
        if (listener->setup(client_port_num) != 0) {
            log(ERROR, String::compose("Could not create client listen socket "
                                       "on port %1. Init failed.",
                                       client_port_num));
            return EXIT_SOCKET_ERROR;
        }
    }
    commServer.addSocket(listener);

#ifdef HAVE_SYS_UN_H
    CommUnixListener * localListener = new CommUnixListener(commServer,
          *new CommClientFactory<TrustedConnection>());
    if (localListener->setup(client_socket_name) != 0) {
        log(ERROR, String::compose("Could not create local listen socket "
                                   "with address \"%1\"",
                                   localListener->getPath()));
        delete localListener;
    } else {
        commServer.addSocket(localListener);
    }

    CommUnixListener * pythonListener = new CommUnixListener(commServer,
          *new CommPythonClientFactory());
    if (pythonListener->setup(python_socket_name) != 0) {
        log(ERROR, String::compose("Could not create python listen socket "
                                   "with address %1.",
                                   pythonListener->getPath()));
        delete pythonListener;
    } else {
        commServer.addSocket(pythonListener);
    }
#endif

    CommTCPListener * httpListener = new CommTCPListener(commServer,
          *new CommHttpClientFactory());
    if (httpListener->setup(http_port_num) != 0) {
        log(ERROR, String::compose("Could not create http listen socket on "
                                   "port %1.", http_port_num));
        delete httpListener;
    } else {
        commServer.addSocket(httpListener);
    }

    if (useMetaserver) {
        CommMetaClient * cmc = new CommMetaClient(commServer);
        if (cmc->setup(mserver) == 0) {
            commServer.addIdle(cmc);
        } else {
            log(ERROR, "Error creating metaserver comm channel.");
            delete cmc;
        }
    }

#if defined(HAVE_LIBHOWL) || defined(HAVE_AVAHI)

    CommMDNSPublisher * cmdns = new CommMDNSPublisher(commServer);
    if (cmdns->setup() == 0) {
        commServer.addSocket(cmdns);
        commServer.addIdle(cmdns);
    } else {
        log(ERROR, "Unable to register service with MDNS daemon.");
        delete cmdns;
    }

#endif // defined(HAVE_LIBHOWL) || defined(HAVE_AVAHI)

    // Configuration is now complete, and verified as somewhat sane, so
    // we save the updated user config.

    updateUserConfiguration();

    log(INFO, "Running");
    logEvent(START, "- - - Standalone server startup");

    // Inform things that want to know that we are running.
    running();

    // Reduce our system priority to make it easier to debug a runaway
    // server.
    if (nice != 0) {
        reduce_priority(nice);
    }

    // Loop until the exit flag is set. The exit flag can be set anywhere in
    // the code easily.
    while (!exit_flag) {
        try {
            commServer.poll();
        }
        catch (...) {
            // It is hoped that commonly thrown exception, particularly
            // exceptions that can be caused  by external influences
            // should be caught close to where they are thrown. If
            // an exception makes it here then it should be debugged.
            log(ERROR, "Exception caught in main()");
        }
    }
    // exit flag has been set so we close down the databases, and indicate
    // to the metaserver (if we are using one) that this server is going down.
    // It is assumed that any preparation for the shutdown that is required
    // by the game has been done before exit flag was set.
    log(NOTICE, "Performing clean shutdown...");

    } // close scope of CommServer, WorldRouter, and ServerRouting, which
      // cause the destruction of the server and world objects, and the entire
      // world contents

    Persistence::instance()->shutdown();

    EntityBuilder::instance()->flushFactories();
    EntityBuilder::del();
    ArithmeticBuilder::del();
    MindFactory::del();
    TeleportAuthenticator::del();

    Inheritance::clear();

    // Shutdown the python interpretter. This frees lots of memory, and if
    // the malloc heap is in any way corrupt, a segfault is likely to
    // occur at this point. Previous occassions where pointers have been
    // deleted twice elsewhere in the code, have resulted in a segfault
    // at this point. AlRiddoch 10th November 2001
    shutdown_python_api();

    delete global_conf;

    log(INFO, "Clean shutdown complete.");
    logEvent(STOP, "- - - Standalone server shutdown");
    return 0;
}
Ejemplo n.º 21
0
Archivo: wand.c Proyecto: stolf/WAND
int main(int argc,char **argv)
{
	response_t *resp;

	/* The real config options */
	int do_daemonise=1;
	char *pidfile = "wand";
	char *server = 0;
	char *proto = 0;
	int udpport = 44444;
	
	/* Signal handling */
	struct sigaction usr1;
	
	/* Config options from the config file */
	config_t main_config[] = {
		{"server", TYPE_STR|TYPE_NULL, &server},
		{"controlfile", TYPE_STR|TYPE_NULL, &control_file_path},
		{"daemonise", TYPE_BOOL|TYPE_NULL, &do_daemonise},
		{"udpport", TYPE_INT|TYPE_NULL, &udpport},
		{"protocol", TYPE_STR|TYPE_NULL, &proto},
		{ "debug_default", TYPE_INT|TYPE_NULL, &default_log_level},
                { "debug_MOD_INIT", TYPE_INT|TYPE_NULL, &modtolevel[MOD_INIT]},
                { "debug_MOD_IPC", TYPE_INT|TYPE_NULL, &modtolevel[MOD_IPC]},
		{NULL, 0, NULL}
	};

	// Set defaults
	conffile = strdup("/usr/local/etc/wand.conf");
	control_file_path = strdup("/var/run/Etud.ctrl");

	parse_commandline(argc,argv);
	
	/* Set up the signal handler - bind SIGUSR1 to send an update instantly */
	usr1.sa_sigaction = send_update;
	usr1.sa_flags = SA_SIGINFO;
	sigaction(SIGUSR1, &usr1, 0);
	
	/* Check the default log level is sane. */
	if(default_log_level < 0 || default_log_level > 15) {
		default_log_level = 15;
		logger(MOD_INIT, 1, "Default logging level must be a number"
				" between 0 and 15. Giving up.\n");
		return 1;
	}
	
	/* Read the config file */
	if(parse_config(main_config, conffile))
	{
		logger( MOD_INIT, 3, "Error parsing config file: %s\n", conffile);
		return 1;
	}
	
	/* Override config file with command line options if set */
	if (!host && server) 
		host = gethostbyname(server);
	if (ccontrol_file_path != NULL)
		control_file_path = strdup(ccontrol_file_path);
	if (cudpport!=-1) 
		udpport = cudpport;
	if (cpidfile != NULL) 
		pidfile = strdup(cpidfile);
	if (clevel != -1)
		default_log_level=clevel;
	
	/* Check that required parameters are there */
	if(!host)
	{
		logger( MOD_INIT, 3, "Cannot resolve hostname\n");
		return 1;
	}

	sock = socket(PF_INET, SOCK_DGRAM, 0);
	
	if (sock<0) {
		perror("socket");
		return 1;
	};

	/* Get the MAC address from Etud */
	resp = askEtud("GETMAC", control_file_path);
	
	if( resp->status == OKAY) {
		strncpy(macaddr, resp->data[0]+7, 17);
		macaddr[17]='\0';	
	}

	else {
		logger(MOD_IPC, 1, "Could not retrieve MAC address from Etud - Exiting\n");
		return 1;
	}
	
	delete_response( resp );
	free( resp );
	
	resp = askEtud("GETPORT", control_file_path);
	
	if( resp->status == OKAY) {
		our_etud_port = atoi(resp->data[0]+8);
	}

	else {
		logger(MOD_IPC, 1, "Could not retrieve port from Etud - Exiting\n");
		return 1;
	}
	
	delete_response( resp );

	free( resp );

	/* check that the port we got from Etud is sane */

	srand(time(NULL));
	
	address.sin_family = AF_INET;
	address.sin_port = htons(0);
	address.sin_addr.s_addr = htonl(INADDR_ANY);

	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(udpport);
	memcpy(&serveraddr.sin_addr.s_addr,
			host->h_addr,
			sizeof(serveraddr.sin_addr.s_addr));
	if (bind(sock,(struct sockaddr *)&address,sizeof(address))<0) {
		perror("bind");
		return 1;
	}
	
	daemonise(argv[0]);
	put_pid(pidfile);

	return mainloop();
}
Ejemplo n.º 22
0
int main(int argc, char **argv)
{
	char *name = NULL;
	int i = 1, ret = 0, daemon = 0;

	if(argc > 1 && !strcmp(argv[1], "-d")){
		i++;
		daemon = 1;
	}

	for(; i < argc; i++)
		if(!name)
			name = argv[i];
		else if(!host)
			host = argv[i];
		else if(!port)
			port = argv[i];
		else{
			fprintf(stderr, "Unknown option: ``%s''\n", argv[i]);
			goto usage;
		}

	if(!host || !name)
		goto usage;

	if(!port)
		port = DEFAULT_PORT;

	if(setjmp(allocerr)){
		perror("malloc()");
		return 1;
	}

	if((ret = init_files()))
		return ret;

	if(daemon && daemonise()){
		term_files();
		return 1;
	}

	comm_init(&commt);

	if(comm_connect(&commt, host, port, name)){
		outputf(file_err, "%s: couldn't connect: %s\n", *argv, comm_lasterr(&commt));
		term_files();
		return 1;
	}

	ret = lewp();

	comm_close(&commt);
	term_files();

	return ret;
usage:
	printf("Usage: %s [-d] name host [port]\n"
	       "  -d: daemonise\n"
	       , *argv);
	return 1;
}