Exemplo n.º 1
0
void
listeners_reload(struct Listener_head *existing_listeners,
        struct Listener_head *new_listeners,
        const struct Table_head *tables, struct ev_loop *loop) {
    struct Listener *iter_existing = SLIST_FIRST(existing_listeners);
    struct Listener *iter_new = SLIST_FIRST(new_listeners);

    while (iter_existing != NULL || iter_new != NULL) {
        int compare_result;
        char address[ADDRESS_BUFFER_SIZE];

        if (iter_existing == NULL)
            compare_result = 1;
        else if (iter_new == NULL)
            compare_result = -1;
        else
            compare_result = address_compare(iter_existing->address, iter_new->address);

        if (compare_result > 0) {
            struct Listener *new_listener = iter_new;
            iter_new = SLIST_NEXT(iter_new, entries);

            notice("Listener %s added.",
                    display_address(new_listener->address,
                            address, sizeof(address)));

            SLIST_REMOVE(new_listeners, new_listener, Listener, entries);
            add_listener(existing_listeners, new_listener);
            init_listener(new_listener, tables, loop);

            /* -1 for removing from new_listeners */
            listener_ref_put(new_listener);
        } else if (compare_result == 0) {
            notice ("Listener %s updated.",
                    display_address(iter_existing->address,
                            address, sizeof(address)));

            listener_update(iter_existing, iter_new, tables);

            iter_existing = SLIST_NEXT(iter_existing, entries);
            iter_new = SLIST_NEXT(iter_new, entries);
        } else {
            struct Listener *removed_listener = iter_existing;
            iter_existing = SLIST_NEXT(iter_existing, entries);

            notice("Listener %s removed.",
                    display_address(removed_listener->address,
                            address, sizeof(address)));

            SLIST_REMOVE(existing_listeners, removed_listener, Listener, entries);
            close_listener(loop, removed_listener);

            /* -1 for removing from existing_listeners */
            listener_ref_put(removed_listener);
        }
    }
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
/*
 * close_listeners - close and free all listeners that are not being used
 */
void
close_listeners()
{
    struct Listener *listener;
    struct Listener *listener_next = 0;
    /*
     * close all 'extra' listening ports we have
     */
    for (listener = ListenerPollList; listener; listener = listener_next) {
        listener_next = listener->next;
        close_listener(listener);
    }
}
Exemplo n.º 4
0
/*
 * close_listeners - close and free all listeners that are not being used
 */
void close_listeners()
{
  struct Listener* listener;
  struct Listener* listener_next = 0;
  /*
   * close all 'extra' listening ports we have
   */
  for (listener = ListenerPollList; listener; listener = listener_next) {
    listener_next = listener->next;
    if (0 == listener->active && 0 == listener->ref_count)
      close_listener(listener);
  }
}
Exemplo n.º 5
0
bool CHttpServer::init()
{
    RAWTRACE("Open listening socket...");
    
    close_listener();
    m_listener = socket(AF_INET, SOCK_STREAM, 0);
    if (m_listener == INVALID_SOCKET) {
        RAWLOG_ERROR1("Can not create listener: %d", RHO_NET_ERROR_CODE);
        return false;
    }
    
    int enable = 1;
    if (setsockopt(m_listener, SOL_SOCKET, SO_REUSEADDR, (const char *)&enable, sizeof(enable)) == SOCKET_ERROR) {
        RAWLOG_ERROR1("Can not set socket option (SO_REUSEADDR): %d", RHO_NET_ERROR_CODE);
        close_listener();
        return false;
    }
    
    struct sockaddr_in sa;
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons((uint16_t)m_port);
    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    if (bind(m_listener, (const sockaddr *)&sa, sizeof(sa)) == SOCKET_ERROR) {
        RAWLOG_ERROR2("Can not bind to port %d: %d", m_port, RHO_NET_ERROR_CODE);
        close_listener();
        return false;
    }
    
    if (listen(m_listener, 128) == SOCKET_ERROR) {
        RAWLOG_ERROR1("Can not listen on socket: %d", RHO_NET_ERROR_CODE);
        close_listener();
        return false;
    }
    
    RAWLOG_INFO1("Listen for connections on port %d", m_port);
    return true;
}
Exemplo n.º 6
0
void terminate(int signal)
{
	// Block SIGINT
	sigset_t set;
	sigemptyset(&set);
	sigaddset (&set, SIGINT);
	sigprocmask(SIG_BLOCK, &set, NULL);
	
#ifdef DEBUG
	fprintf(printf_file, "Terminating...\n");
	fflush(printf_file);
#endif
	
	close_listener();
	exit(0);
}
Exemplo n.º 7
0
/*
 * add_listener- create a new listener
 * port - the port number to listen on
 * vhost_ip - if non-null must contain a valid IP address string in
 * the format "255.255.255.255"
 */
void
add_listener(int port, const char *vhost_ip, int family, int ssl)
{
	struct Listener *listener;
	struct rb_sockaddr_storage vaddr;

	/*
	 * if no port in conf line, don't bother
	 */
	if(port == 0)
		return;
	memset(&vaddr, 0, sizeof(vaddr));
	vaddr.ss_family = family;

	if(vhost_ip != NULL)
	{
		if(family == AF_INET)
		{
			if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in *)&vaddr)->sin_addr) <= 0)
				return;
		} 
#ifdef RB_IPV6
		else
		{
			if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in6 *)&vaddr)->sin6_addr) <= 0)
				return;
		
		}
#endif
	} else
	{
		switch(family)
		{
			case AF_INET:
				((struct sockaddr_in *)&vaddr)->sin_addr.s_addr = INADDR_ANY;
				break;
#ifdef RB_IPV6
			case AF_INET6:
				memcpy(&((struct sockaddr_in6 *)&vaddr)->sin6_addr, &in6addr_any, sizeof(struct in6_addr));
				break;
			default:
				return;
#endif
		} 
	}
	switch(family)
	{
		case AF_INET:
			SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in));
			((struct sockaddr_in *)&vaddr)->sin_port = htons(port);
			break;
#ifdef RB_IPV6
		case AF_INET6:
			SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in6));
			((struct sockaddr_in6 *)&vaddr)->sin6_port = htons(port);
			break;
#endif
		default:
			break;
	}
	if((listener = find_listener(&vaddr)))
	{
		if(listener->F != NULL)
			return;
	}
	else
	{
		listener = make_listener(&vaddr);
		listener->next = ListenerPollList;
		ListenerPollList = listener;
	}

	listener->F = NULL;
	listener->ssl = ssl;

	if(inetport(listener))
		listener->active = 1;
	else
		close_listener(listener);
}
Exemplo n.º 8
0
bool CHttpServer::init()
{
	if (verbose) RAWTRACE("Open listening socket...");

    close_listener();
    
    //m_listener = socket(AF_INET, SOCK_STREAM, 0);
    m_listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    if (m_listener == INVALID_SOCKET) {
        if (verbose) RAWLOG_ERROR1("Can not create listener: %d", RHO_NET_ERROR_CODE);
        return false;
    }

    int enable = 1;
    if (setsockopt(m_listener, SOL_SOCKET, SO_REUSEADDR, (const char *)&enable, sizeof(enable)) == SOCKET_ERROR) {
        if (verbose) RAWLOG_ERROR1("Can not set socket option (SO_REUSEADDR): %d", RHO_NET_ERROR_CODE);
        close_listener();
        return false;
    }
    
    struct sockaddr_in sa;
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons((uint16_t)m_port);
    
    if (m_enable_external_access) {
        sa.sin_addr.s_addr = htonl(INADDR_ANY);
    }
    else {
        sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    }
    
    
    if (bind(m_listener, (const sockaddr *)&sa, sizeof(sa)) == SOCKET_ERROR) {
        if (verbose) RAWLOG_ERROR2("Can not bind to port %d: %d", m_port, RHO_NET_ERROR_CODE);
        close_listener();
        return false;
    }
    
    if (listen(m_listener, 128) == SOCKET_ERROR) {
        if (verbose) RAWLOG_ERROR1("Can not listen on socket: %d", RHO_NET_ERROR_CODE);
        close_listener();
        return false;
    }
    
    // detect local IP adress
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    //sin.sin_len = sizeof(sin);
    sin.sin_family = AF_INET; // or AF_INET6 (address family)
    socklen_t len = sizeof(sin);
    if (getsockname(m_listener, (struct sockaddr *)&sin, &len) < 0) {
        // Handle error here
        if (verbose) RAWLOG_ERROR("Can not detect local IP adress");
    }
    else {
        m_IP_adress = inet_ntoa(sin.sin_addr);
    }
    
    if (verbose) RAWLOG_INFO1("Listen for connections on port %d", m_port);
    return true;
}
Exemplo n.º 9
0
/** Main loop for redundant processes */
void redundancy_main(uint64_t process_type, uint64_t process_type_version, int port, uint64_t input_process_type, void (*process_input)(char *, int), void (*vote_and_process)(), void (*flush_inputs)(), int flags, int argc, char ** argv)
{
	// Get pid
	pid = getpid();
	
	// Open debug file
#ifdef DEBUG_FILE
	char fn[64];
	sprintf(fn, "redundancy_%llu.log", pid);
	debug_file = fopen(fn, "a");
	printf_file = (debug_file != NULL) ? debug_file : stdin;
#else
	printf_file = stdin;
#endif
	
	// Store process type
	ptype = process_type;
	ptype_version = process_type_version;
	
	// Get start time
	struct timeval tv;
	gettimeofday(&tv, NULL);
	timestamp = (tv.tv_sec * 100 + (tv.tv_usec / 10000)) & 0x00000000ffffffffLLU;	// In 100ths of seconds
	
	// Set up signal handling
	signal(SIGABRT, terminate);
	signal(SIGTERM, terminate);
	signal(SIGINT, terminate);
	
	// There are no last inputs processed
	memset(&last_inputs_processes, 0, sizeof last_inputs_processes);
	
	// Check number of args
	if (argc != 2)
	{
		fprintf(printf_file, "Usage: %s <host_num>\n", argv[0]);
		fflush(printf_file);
		exit(1);
	}
	
	// Get host number
	sscanf (argv[1], "%llu", &host_num);
	
	// Register address
	pthread_mutex_lock(&sisis_addr_mutex);
	if (sisis_register(sisis_addr, process_type, process_type_version, host_num, pid, timestamp) != 0)
	{
		fprintf(printf_file, "Failed to register SIS-IS address.\n");
		fflush(printf_file);
		exit(1);
	}
	pthread_mutex_unlock(&sisis_addr_mutex);
	gettimeofday(&timestamp_sisis_registered, NULL);
	
	// Status
	fprintf(printf_file, "Opening socket at %s on port %i.\n", sisis_addr, port);
	fflush(printf_file);
	
	// Set up socket address info
	struct addrinfo hints, *addr;
	memset(&hints, 0, sizeof hints);
	hints.ai_family = AF_INET6;	// IPv6
	hints.ai_socktype = SOCK_DGRAM;
	char port_str[8];
	sprintf(port_str, "%u", port);
	getaddrinfo(sisis_addr, port_str, &hints, &addr);
	
	// Create socket
	if ((sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) == -1)
	{
		fprintf(printf_file, "Failed to open socket.\n");
		fflush(printf_file);
		exit(1);
	}
	
	// Bind to port
	if (bind(sockfd, addr->ai_addr, addr->ai_addrlen) == -1)
	{
		fprintf(printf_file, "Failed to bind socket to port.\n");
		fflush(printf_file);
		close_listener();
		exit(2);
	}
	
	// Are we checking redundancy?
	if (!(flags & REDUNDANCY_MAIN_FLAG_SKIP_REDUNDANCY))
	{
		// Open socket to stop redundancy
		sprintf(port_str, "%u", STOP_REDUNDANCY_PORT);
		stop_redundancy_socket = make_socket(port_str);
	}
	
	// Short sleep while address propagates
	usleep(50000);	// 50ms
	
	// Status message
	inet_ntop(AF_INET6, &((struct sockaddr_in6 *)(addr->ai_addr))->sin6_addr, sisis_addr, INET6_ADDRSTRLEN);
	fprintf(printf_file, "Socket opened at %s on port %u.\n", sisis_addr, ntohs(((struct sockaddr_in *)(addr->ai_addr))->sin_port));
	fflush(printf_file);
	
	// Info to subscribe to RIB changes
	struct subscribe_to_rib_changes_info info;
	
	// Are we checking redundancy?
	if (!(flags & REDUNDANCY_MAIN_FLAG_SKIP_REDUNDANCY))
	{
		// Set up signal handling for alarm
		signal(SIGALRM, recheck_redundance_alarm_handler);
		
		// Check redundancy
		check_redundancy();
		
		// Subscribe to RIB changes
		memset(&info, 0, sizeof info);
		info.rib_add_ipv6_route = rib_monitor_add_ipv6_route;
		info.rib_remove_ipv6_route = rib_monitor_remove_ipv6_route;
		subscribe_to_rib_changes(&info);
	}
	
	// Set of sockets for select call when waiting for other inputs
	fd_set socks;
	
	// Timeout information for select call
	struct timeval select_timeout;
	struct timeval start_time, cur_time, tmp1, tmp2;
	
	// Number of input processes
	int num_input_processes;
	int num_input = 0;
	
	// Wait for message
	struct sockaddr_in6 remote_addr;
	int buflen;
	char buf[RECV_BUFFER_SIZE];
	socklen_t addr_size = sizeof remote_addr;
	while (1)
	{
		// Set of sockets for main select call
		int main_socks_max_fd;
		fd_set main_socks;
		FD_ZERO(&main_socks);
		FD_SET(sockfd, &main_socks);
		
		// Are we checking redundancy?
		if (!(flags & REDUNDANCY_MAIN_FLAG_SKIP_REDUNDANCY))
		{
			FD_SET(stop_redundancy_socket, &main_socks);
			main_socks_max_fd = MAX(stop_redundancy_socket, sockfd)+1;
		}
		else
			main_socks_max_fd = sockfd+1;
		
		// Wait for message on either socket
		if (select(main_socks_max_fd, &main_socks, NULL, NULL, NULL) > 0)
		{
			// Stop redundancy socket
			if (FD_ISSET(stop_redundancy_socket, &main_socks))
			{
				if ((buflen = recvfrom(stop_redundancy_socket, buf, RECV_BUFFER_SIZE, 0, NULL, NULL)) != -1)
				{
					// Very primative security
					if (buflen == strlen(PASSWORD) && memcmp(buf, PASSWORD, buflen) == 0)
					{
#ifdef DEBUG
						fprintf(printf_file, "Stopping Redundancy.\n");
						fflush(printf_file);
#endif
						
						// Unsubscribe to RIB changes
						subscribe_to_rib_changes(&info);
						redundancy_flag = 0;
					}
				}
			}
			// Input socket
			else if (FD_ISSET(sockfd, &main_socks))
			{
				do
				{
					// Read from socket
					if ((buflen = recvfrom(sockfd, buf, RECV_BUFFER_SIZE, 0, (struct sockaddr *)&remote_addr, &addr_size)) != -1)
					{
#ifdef DEBUG
						gettimeofday(&cur_time, NULL);
						char addr[INET6_ADDRSTRLEN];
						if (inet_ntop(AF_INET6, &(remote_addr.sin6_addr), addr, INET6_ADDRSTRLEN) != NULL)
							fprintf(printf_file, "[%llu.%06llu] Input from %*s.\n", (uint64_t)cur_time.tv_sec, (uint64_t)cur_time.tv_usec, INET6_ADDRSTRLEN, addr);
						fflush(printf_file);
#endif
						// Setup input
						if (num_input == 0)
						{
							// Set socket select timeout
							select_timeout.tv_sec = GATHER_RESULTS_TIMEOUT_USEC / 1000000;
							select_timeout.tv_usec = GATHER_RESULTS_TIMEOUT_USEC % 1000000;
							
							// Get start time
							gettimeofday(&start_time, NULL);
						}
						else
						{
							// Determine new socket select timeout
							gettimeofday(&cur_time, NULL);
							timersub(&cur_time, &start_time, &tmp1);
							timersub(&select_timeout, &tmp1, &tmp2);
							select_timeout.tv_sec = tmp2.tv_sec;
							select_timeout.tv_usec = tmp2.tv_usec;
						}
						
						// Record input
						num_input++;
						
						// Process the input
						process_input(buf, buflen);
						
						// Check how many input processes there are
						if (!(flags & REDUNDANCY_MAIN_FLAG_SINGLE_INPUT))
						{
							num_input_processes = get_process_type_count(input_process_type);
			#ifdef DEBUG
							fprintf(printf_file, "# inputs: %d\n", num_input);
							fprintf(printf_file, "# input processes: %d\n", num_input_processes);
							fprintf(printf_file, "Waiting %ld.%06ld seconds for more results.\n", (long)(select_timeout.tv_sec), (long)(select_timeout.tv_usec));
							fflush(printf_file);
			#endif
						}
					}
					
					// Set of sockets for select call when waiting for other inputs
					FD_ZERO(&socks);
					FD_SET(sockfd, &socks);
				} while(!(flags & REDUNDANCY_MAIN_FLAG_SINGLE_INPUT) && num_input < num_input_processes && select(sockfd+1, &socks, NULL, NULL, &select_timeout) > 0);
				
				// Check that at least 1/2 of the processes sent inputs
				if (!(flags & REDUNDANCY_MAIN_FLAG_SINGLE_INPUT) && num_input <= num_input_processes/2)
				{
					// Check how late these are for the last set of inputs
					gettimeofday(&cur_time, NULL);
					timersub(&cur_time, &last_inputs_processes, &tmp1);
					//if ((tmp1.tv_sec * 1000000 + tmp1.tv_usec) < GATHER_RESULTS_TIMEOUT_USEC * 1.25)
					fprintf(printf_file, "Late by %llu.%06llu seconds.\n", (uint64_t)tmp1.tv_sec, (uint64_t)tmp1.tv_usec);
					fflush(printf_file);
					
					// Flush inputs
					flush_inputs();
		#ifdef DEBUG
					fprintf(printf_file, "Not enough inputs for a vote.\n");
					fflush(printf_file);
		#endif
				}
				else
				{
		#ifdef DEBUG
					fprintf(printf_file, "Voting...\n");
					fflush(printf_file);
		#endif
					// Record time
					gettimeofday(&last_inputs_processes, NULL);
					
					// Vote and process results
					vote_and_process();
				}
				
				// Reset
				num_input = 0;
			}
		}
	}
	
	// Close socket
	close_listener();
}
Exemplo n.º 10
0
void
remove_listener(struct Listener_head *listeners, struct Listener *listener) {
    SLIST_REMOVE(listeners, listener, Listener, entries);
    close_listener(EV_DEFAULT, listener);
    free_listener(listener);
}
Exemplo n.º 11
0
static int 
inetport(struct Listener* listener)
{
  struct irc_sockaddr lsin;
  int                fd;
  int                opt = 1;

  /*
   * At first, open a new socket
   */
  fd = comm_open(DEF_FAM, SOCK_STREAM, 0, "Listener socket");

#ifdef IPV6
  if (!IN6_ARE_ADDR_EQUAL((struct in6_addr *)&listener->addr, &in6addr_any))
  {
#else
  if (INADDR_ANY != listener->addr.sins.sin.s_addr)
  {
#endif
    inetntop(DEF_FAM, &IN_ADDR(listener->addr), listener->vhost, HOSTLEN);
    listener->name = listener->vhost;
  }

  if (fd == -1)
  {
    report_error(L_ALL, "opening listener socket %s:%s",
                 get_listener_name(listener), errno);
    return 0;
  }
  else if ((HARD_FDLIMIT - 10) < fd)
  {
    report_error(L_ALL, "no more connections left for listener %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }
  /*
   * XXX - we don't want to do all this crap for a listener
   * set_sock_opts(listener);
   */
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(opt)))
  {
    report_error(L_ALL, "setting SO_REUSEADDR for listener %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  /*
   * Bind a port to listen for new connections if port is non-null,
   * else assume it is already open and try get something from it.
   */
  memset(&lsin, 0, sizeof(struct irc_sockaddr));
  S_FAM(lsin) = DEF_FAM;
  copy_s_addr(S_ADDR(lsin), IN_ADDR(listener->addr));
  S_PORT(lsin) = htons(listener->port);


  if (bind(fd, (struct sockaddr*) &SOCKADDR(lsin),
      sizeof(struct irc_sockaddr)))
  {
    report_error(L_ALL, "binding listener socket %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  if (listen(fd, HYBRID_SOMAXCONN)) {
    report_error(L_ALL, "listen failed for %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  /*
   * XXX - this should always work, performance will suck if it doesn't
   */
  if (!set_non_blocking(fd))
    report_error(L_ALL, NONB_ERROR_MSG, get_listener_name(listener), errno);

  listener->fd = fd;

  /* Listen completion events are READ events .. */

  accept_connection(fd, listener);
  return 1;
}

static struct Listener* 
find_listener(int port, struct irc_inaddr *addr)
{
  struct Listener* listener = NULL;
  struct Listener* last_closed = NULL;

  for (listener = ListenerPollList; listener; listener = listener->next)
  {

    if ( (port == listener->port) &&
         (!memcmp(&PIN_ADDR(addr),
                 &IN_ADDR(listener->addr),
                 sizeof(struct irc_inaddr))))
    {
      /* Try to return an open listener, otherwise reuse a closed one */
      if (listener->fd == -1)
        last_closed = listener;
      else
        return listener;
    }
  }
  return last_closed;
}


/*
 * add_listener- create a new listener
 * port - the port number to listen on
 * vhost_ip - if non-null must contain a valid IP address string in
 * the format "255.255.255.255"
 */
void 
add_listener(int port, const char* vhost_ip)
{
  struct Listener* listener;
  struct irc_inaddr   vaddr;

  /*
   * if no port in conf line, don't bother
   */
  if (port == 0)
    return;

#ifdef IPV6
  copy_s_addr(IN_ADDR(vaddr), &in6addr_any);
#else
  copy_s_addr(IN_ADDR(vaddr), INADDR_ANY);
#endif

  if (vhost_ip)
  {
    if(inetpton(DEF_FAM, vhost_ip, &IN_ADDR(vaddr)) <= 0)
      return;
  }

  if ((listener = find_listener(port, &vaddr)))
  {
    if (listener->fd > -1)
      return;
  }
  else
  {
    listener = make_listener(port, &vaddr);
    listener->next = ListenerPollList;
    ListenerPollList = listener;
  }

  listener->fd = -1;

  if (inetport(listener))
    listener->active = 1;
  else
    close_listener(listener);
}

/*
 * close_listener - close a single listener
 */
void close_listener(struct Listener* listener)
{
  assert(listener != NULL);
  if(listener == NULL)
    return;
  if (listener->fd >= 0)
  {
    fd_close(listener->fd);
    listener->fd = -1;
  }

  listener->active = 0;

  if (listener->ref_count)
    return;

  free_listener(listener);
}
Exemplo n.º 12
0
int main(int argc, char *argv[])
{
    if (argc < 1) {
        dprintf(STDERR_FILENO, "wrun called without argument\n");
        terminate_nocore();
    }
    shift(&argc, &argv);
    if (argc > 1 && !strcmp(argv[0], "--tool_name")) {
        shift(&argc, &argv);
        tool_name = shift(&argc, &argv);
    }

    fill_std_fd_info_identity(STDIN_FILENO);
    fill_std_fd_info_identity(STDOUT_FILENO);
    fill_std_fd_info_identity(STDERR_FILENO);

    bool force_redirects = false;
    bool silent_breakaway = false;

    int port;
    bool terminate = !get_outbash_infos(&port, &force_redirects);

    struct string outbash_command = string_create("");

    if (argc && !strcmp(argv[0], ":")) {
        shift(&argc, &argv);
        string_append(&outbash_command, "cd:~\n");
    } else {
        char* cwd = agetcwd();
        if (is_absolute_drive_fs_path(cwd)) {
            char* cwd_win32 = convert_drive_fs_path_to_win32(cwd);
            string_append(&outbash_command, "cd:");
            string_append(&outbash_command, cwd_win32);
            string_append(&outbash_command, "\n");
            free(cwd_win32);
        }
        free(cwd);
    }

    while (argc && !strncmp(argv[0], "--", 2)) {

        if (!strcmp(argv[0], "--")) {
            shift(&argc, &argv);
            break;
        }

        if (!strcmp(argv[0], "--env")) {
            shift(&argc, &argv);
            while (argc && strncmp(argv[0], "--", 2) != 0
                        && *argv[0] != '\0' && strchr(argv[0] + 1, '=')) {
                string_append(&outbash_command, "env:");
                string_append(&outbash_command, argv[0]);
                string_append(&outbash_command, "\n");
                shift(&argc, &argv);
            }
        } else if (!strcmp(argv[0], "--force-redirects")) {
            force_redirects = true;
            shift(&argc, &argv);
        } else if (!strcmp(argv[0], "--silent-breakaway")) {
            silent_breakaway = true;
            shift(&argc, &argv);
        } else if (!strcmp(argv[0], "--help")) {
            print_help();
            exit(1);
        } else {
            dprintf(STDERR_FILENO, "%s: unknown command line option: %s\n", tool_name, argv[0]);
            dprintf(STDERR_FILENO, "type %s --help for more information.\n", tool_name);
            terminate_nocore();
        }
    }
    if (terminate)
        terminate_nocore();
    check_argc(argc);

    decide_will_redirect(STDIN_FILENO,  force_redirects);
    decide_will_redirect(STDOUT_FILENO, force_redirects);
    decide_will_redirect(STDERR_FILENO, force_redirects);

    int sock_ctrl = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock_ctrl < 0) {
        dprintf(STDERR_FILENO, "%s: socket() failed: %s\n", tool_name, my_strerror(errno));
        terminate_nocore();
    }

#define STDIN_NEEDS_SOCKET_REDIRECT     1
#define STDOUT_NEEDS_SOCKET_REDIRECT    2
#define STDERR_NEEDS_SOCKET_REDIRECT    4
#define STDERR_SOCKREDIR_TO_STDOUT      8
    int redirects =   (needs_socket_redirect(STDIN_FILENO)  ? STDIN_NEEDS_SOCKET_REDIRECT  : 0)
                    | (needs_socket_redirect(STDOUT_FILENO) ? STDOUT_NEEDS_SOCKET_REDIRECT : 0);
    if (needs_socket_redirect(STDERR_FILENO)) {
        if ((redirects & STDOUT_NEEDS_SOCKET_REDIRECT) && are_stdfd_to_same_thing(STDOUT_FILENO, STDERR_FILENO))
            redirects |= STDERR_SOCKREDIR_TO_STDOUT;
        else
            redirects |= STDERR_NEEDS_SOCKET_REDIRECT;
    }

    struct listening_socket lsock_in = NO_LISTENING_SOCKET;
    struct listening_socket lsock_out = NO_LISTENING_SOCKET;
    struct listening_socket lsock_err = NO_LISTENING_SOCKET;
    if (redirects & STDIN_NEEDS_SOCKET_REDIRECT) lsock_in = socket_listen_one_loopback();
    if (redirects & STDOUT_NEEDS_SOCKET_REDIRECT) lsock_out = socket_listen_one_loopback();
    if (redirects & STDERR_NEEDS_SOCKET_REDIRECT) lsock_err = socket_listen_one_loopback();
    ask_redirect(&outbash_command, "stdin:", STDIN_FILENO, lsock_in.port);
    ask_redirect(&outbash_command, "stdout:", STDOUT_FILENO, lsock_out.port);
    ask_redirect(&outbash_command, "stderr:", STDERR_FILENO,
                 (redirects & STDERR_NEEDS_SOCKET_REDIRECT) ? lsock_err.port : lsock_out.port);

    if (silent_breakaway)
        string_append(&outbash_command, "silent_breakaway:1\n");

    char* win32_module;
    if (is_absolute_drive_fs_path(argv[0])) {
        win32_module = convert_drive_fs_path_to_win32(argv[0]);
        string_append(&outbash_command, "module:");
        string_append(&outbash_command, win32_module);
        string_append(&outbash_command, "\n");
    } else {
        win32_module = convert_slash_to_backslash(argv[0]);
    }

    const bool module_need_quotes = (NULL != strpbrk(win32_module, " \t"));
    string_append(&outbash_command, "run:");
    if (module_need_quotes)
        string_append(&outbash_command, "\"");
    string_append(&outbash_command, win32_module);
    if (module_need_quotes)
        string_append(&outbash_command, "\"");

    free(win32_module);

    for (int i = 1; i < argc; i++) {
        string_append(&outbash_command, " ");
        string_append(&outbash_command, argv[i]);
    }
    string_append(&outbash_command, "\n\n");
    //dprintf(STDOUT_FILENO, "%s", outbash_command.str);
    //return EXIT_FAILURE;

    signal(SIGPIPE, SIG_IGN);

    sigset_t signal_set, orig_mask;

    //////////////////////////// unblock SIGUSR1
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGUSR1);
    pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);

    //////////////////////////// block SIGTSTP
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGTSTP);
    pthread_sigmask(SIG_BLOCK, &signal_set, &orig_mask);

    //////////////////////////// install custom SIGTSTP handler if signal was not ignored
    struct sigaction sa;
    sigaction(SIGTSTP, NULL, &sa);
    const bool ignore_sigtstp = (sa.sa_handler == SIG_IGN);
    if (!ignore_sigtstp) {
        sa.sa_handler = tstop_handler;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
        sigaction(SIGTSTP, &sa, NULL);
    }

    //////////////////////////// install custom SIGUSR1 handler to wake-up blocked IO forwarding threads
    // NOTE: the handler itself do nothing, but any blocked syscall will return with EINTR error
    sa.sa_handler = noop_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGUSR1, &sa, NULL);

    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    serv_addr.sin_port = htons(port);
    if (connect(sock_ctrl, (const struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
        // NOTE: I'm not sure that WSL does what Linux does concerning
        // http://www.madore.org/~david/computers/connect-intr.html
        // for now we do not expect to recover after an interruption here.
        dprintf(STDERR_FILENO, "%s: connect() failed: %s\n", tool_name, my_strerror(errno));
        terminate_nocore();
    }

    if (send_all(sock_ctrl, outbash_command.str, outbash_command.length, 0) < 0) {
        dprintf(STDERR_FILENO, "%s: send_all() failed: %s\n", tool_name, my_strerror(errno));
        terminate_nocore();
    }
    string_destroy(&outbash_command);

    static struct forward_state fs[3];
    fs_init_accept_as_needed(&fs[STDIN_FILENO],  &lsock_in,  redirects & STDIN_NEEDS_SOCKET_REDIRECT,  STDIN_FILENO,  "stdin");
    fs_init_accept_as_needed(&fs[STDOUT_FILENO], &lsock_out, redirects & STDOUT_NEEDS_SOCKET_REDIRECT, STDOUT_FILENO, "stdout");
    fs_init_accept_as_needed(&fs[STDERR_FILENO], &lsock_err, redirects & STDERR_NEEDS_SOCKET_REDIRECT, STDERR_FILENO, "stderr");

    char *line = ctrl_readln(sock_ctrl, NULL);
    if (!line || strcmp(line, "connected")) {
        dprintf(STDERR_FILENO, "%s: did not receive connection validation from outbash.exe\n", tool_name);
        terminate_nocore();
    }

    close_listener(&lsock_in);
    close_listener(&lsock_out);
    close_listener(&lsock_err);

    enum state_e state = RUNNING;
    int program_return_code = 255;

    pthread_t   forward_threads[3];
    bool        active_threads[3] = {0};

    for (int i = 0; i < 3; i++) {
        if ((!fs[i].dead_in) || (!fs[i].dead_out)) {
            int err = pthread_create(&forward_threads[i], NULL, forward_one_stream, &fs[i]);
            if (err != 0) {
                dprintf(STDERR_FILENO, "%s: pthread_create() failed: %s\n", tool_name, my_strerror(err));
                terminate_nocore();
            }
            active_threads[i] = true;
        }
    }

    int nfds = sock_ctrl + 1;

    while (state != TERMINATED) {
        fd_set rfds;
        FD_ZERO(&rfds);
        if (sock_ctrl < 0 || sock_ctrl >= FD_SETSIZE) {
            dprintf(STDERR_FILENO, "%s: sock_ctrl=%d out of range\n", tool_name, sock_ctrl);
            abort();
        }
        FD_SET(sock_ctrl, &rfds);

        int pselect_res = pselect(nfds, &rfds, NULL, NULL, NULL, &orig_mask); // tstop_handler can run here
        int pselect_errno = errno;

        if (tstop_req && state == RUNNING) {
            int r = send_all(sock_ctrl, "suspend\n", strlen("suspend\n"), 0);
            if (r < 0 && err_is_connection_broken(errno)) {
                // We will never be able to ask outbash to suspend the
                // Windows process, the expected reason is that it actually
                // has already terminated and we don't know yet about that,
                // so stop the suspend forwarding mechanism and suspend
                // ourselves immediately.
                shutdown(sock_ctrl, SHUT_WR); // also we can't send anything anymore // XXX to comment for WSL bug workaround? proba low here...
                signal(SIGTSTP, SIG_DFL);
                state = DYING;
                raise(SIGTSTP);
                pthread_sigmask(SIG_SETMASK, &orig_mask, NULL);
            } else if (r < 0) { // other errors
                dprintf(STDERR_FILENO, "%s: send_all(\"suspend\\n\") failed: %s\n", tool_name, my_strerror(errno));
                abort();
            } else { // OK
                // It's up to outbash now, just wait for its "suspend_ok"
                // answer after it has suspended the Windows process.
                state = SUSPEND_PENDING;
            }
        }

        if (pselect_res < 0 && pselect_errno == EINTR) {
            // "On error, -1 is returned, and errno is set appropriately;
            //  the sets and timeout become undefined, so do not rely on
            //  their contents after an error."
            continue;
        }

        if (pselect_res < 0) {
            dprintf(STDERR_FILENO, "%s: pselect() failed: %s\n", tool_name, my_strerror(pselect_errno));
            abort();
        }

        if (FD_ISSET(sock_ctrl, &rfds)) {
            while (1) {
                int nonblock_marker;
                line = ctrl_readln(sock_ctrl, &nonblock_marker);
                if (!line && nonblock_marker) break;
                if (line && !strcmp(line, "suspend_ok")) {
                    if (state == SUSPEND_PENDING) {
                        signal(SIGTSTP, SIG_DFL);
                        raise(SIGTSTP);
                        sigset_t previous_mask;
                        pthread_sigmask(SIG_SETMASK, &orig_mask, &previous_mask);
                            // >>> Process will Stop here, until SIGCONT <<<
                        pthread_sigmask(SIG_SETMASK, &previous_mask, NULL);
                        tstop_req = 0;
                        int r = send_all(sock_ctrl, "resume\n", strlen("resume\n"), 0);
                        if (r < 0 && err_is_connection_broken(errno)) {
                            // killed when suspended (if this is possible?)
                            // or maybe just before an attempt?
                            shutdown(sock_ctrl, SHUT_WR); // XXX to comment for WSL bug workaround? proba low here...
                            state = DYING;
                            pthread_sigmask(SIG_SETMASK, &orig_mask, NULL);
                        } else if (r < 0) {
                            dprintf(STDERR_FILENO, "%s: send_all(\"resume\\n\") failed: %s\n", tool_name, my_strerror(errno));
                            abort();
                        } else {
                            state = RUNNING;
                            sa.sa_handler = tstop_handler;
                            sigemptyset(&sa.sa_mask);
                            sa.sa_flags = 0;
                            sigaction(SIGTSTP, &sa, NULL);
                        }
                    } else {
                        dprintf(STDERR_FILENO, "%s: spurious \"suspend_ok\" received\n", tool_name);
                    }
                } else { // not "suspend_ok" => for now only other cases are exit conditions
                    program_return_code = get_return_code(line);
                    shutdown(sock_ctrl, SHUT_RDWR);
                    signal(SIGTSTP, ignore_sigtstp ? SIG_IGN : SIG_DFL);
                    if ((tstop_req && state == RUNNING) || state == SUSPEND_PENDING) {
                        // We expect to stop soon, but not without flushing the OS TCP
                        // buffers and our owns, and other WSL processes in a pipe might
                        // already be suspended, so we better honor suspend requests ASAP.
                        raise(SIGTSTP);
                    }
                    pthread_sigmask(SIG_SETMASK, &orig_mask, NULL);
                    tstop_req = 0;
                    state = TERMINATED;
                    break;
                }
            }
        }
    }

    // XXX: this is not ideal if the Win32 side managed to maintain the
    // redirection socket beyond the lifetime of the launched process,
    // however things seem to already be not reliable for Windows reasons
    // in this case
    if (active_threads[0]) {
        __sync_fetch_and_add(&fs[0].ask_terminate, 1);
        useconds_t usec_sleep = 1000;
        while (!__sync_fetch_and_add(&fs[0].finished, 0)) {
            pthread_kill(forward_threads[0], SIGUSR1);
            usleep(usec_sleep);
            usec_sleep *= 2;
            if (usec_sleep > 60000000)
                usec_sleep = 60000000;
        }
    }

    for (int i = 0; i < 3; i++)
        if (active_threads[i])
            pthread_join(forward_threads[i], NULL);

    return program_return_code;
}
Exemplo n.º 13
0
void
remove_listener(struct Listener_head *listeners, struct Listener *listener, struct ev_loop *loop) {
    SLIST_REMOVE(listeners, listener, Listener, entries);
    close_listener(loop, listener);
    listener_ref_put(listener);
}
Exemplo n.º 14
0
Arquivo: killer.c Projeto: ecks/sis-is
void terminate(int signal)
{
	printf("Terminating...\n");
	close_listener();
	exit(0);
}