long redrobd_voltage_monitor_thread::setup(void)
{
  try {
    redrobd_log_writeln(get_name() + " : setup started");

    init_members();

    // Start timer controlling when to log voltages
    if (m_voltage_log_timer.reset() != TIMER_SUCCESS) {
      THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_TIME_ERROR,
		"Error resetting voltage log timer for thread %s",
		get_name().c_str());      
    }
            
    redrobd_log_writeln(get_name() + " : setup done");

    return THREAD_SUCCESS;    
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_voltage_monitor_thread::setup->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
long redrobd_rc_net_server_thread::execute(void *arg)
{
  // Make GCC happy (-Wextra)
  if (arg) {
    return THREAD_INTERNAL_ERROR;
  }

  try {
    redrobd_log_writeln(get_name() + " : execute started");

    handle_clients();
        
    redrobd_log_writeln(get_name() + " : execute done");

    return THREAD_SUCCESS;
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_rc_net_server_thread::execute->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
Beispiel #3
0
static void client_srv_passive(char *arg)
{
	int h1, h2, h3, h4, p1, p2;
	u_int32_t addr, ladr;
	u_int16_t port;
	int       incr;

	if (arg == NULL)		/* Basic sanity check	*/
		return;

	/*
	** Read the port. According to RFC 1123, 4.1.2.6,
	** we have to scan the string for the first digit.
	*/
	while (*arg < '0' || *arg > '9')
		arg++;
	if (sscanf(arg, "%d,%d,%d,%d,%d,%d",
			&h1, &h2, &h3, &h4, &p1, &p2) != 6) {
		syslog_error("bad PASV 277 response from server for %s",
						ctx.cli_ctrl->peer);
		client_respond(425, NULL, "Can't open data connection");
		client_data_reset(MOD_RESET);
		ctx.expect = EXP_IDLE;
		return;
	}
	addr = (u_int32_t) ((h1 << 24) + (h2 << 16) + (h3 << 8) + h4);
	port = (u_int16_t) ((p1 <<  8) +  p2);
	syslog_write(T_DBG, "got SRV-PASV %s:%d for %s:%d",
	                    socket_addr2str(addr), port,
	                    ctx.cli_ctrl->peer, ctx.cli_ctrl->port);

	/*
	** should we bind a rand(port-range) or increment?
	*/
	incr = !config_bool(NULL,"SockBindRand", 0);

	/*
	** Open a connection to the server at the given port
	*/
	ladr = socket_sck2addr(ctx.srv_ctrl->sock, LOC_END, NULL);
	if (socket_d_connect(addr, port, ladr, ctx.srv_lrng,
			ctx.srv_urng, &(ctx.srv_data),
			"Srv-Data", incr) == 0)
	{
		syslog_error("can't connect Srv-Data for %s",
						ctx.cli_ctrl->peer);
		client_respond(425, NULL, "Can't open data connection");
		client_data_reset(MOD_RESET);
		ctx.expect = EXP_IDLE;
		return;
	}

	/*
	** Finally send the original command from the client
	*/
	client_xfer_fireup();
}
long redrobd_voltage_monitor_thread::cyclic_execute(void)
{
  try {
    uint16_t adc_value;
    float v_mon;
    float v_in;

    // Get voltage from analog input
    m_mcp3008_io_ptr->read_single(m_mcp3008_io_chn, adc_value);
    v_mon = m_mcp3008_io_ptr->to_voltage(adc_value);

    // Scale back to input voltage
    v_in = v_mon / m_voltage_sf;

    // Lockdown read operation
    pthread_mutex_lock(&m_voltage_mutex);
    
    m_voltage.v_mon = v_mon;
    m_voltage.v_in  = v_in;
    
    // Lockup read operation
    pthread_mutex_unlock(&m_voltage_mutex);

    // Check if time to log voltages
    if ( m_voltage_log_timer.get_elapsed_time() >
	 LOG_VOLTAGES_INTERVAL ) {

      // Log voltages
      ostringstream oss_msg;
      oss_msg.precision(3);
      oss_msg << fixed;
      oss_msg << get_name() << " : Vmon=" << v_mon << ", Vin=" << v_in;
      
      redrobd_log_writeln(oss_msg.str());
      oss_msg.str("");

      // Reset timer
      if (m_voltage_log_timer.reset() != TIMER_SUCCESS) {
	THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_TIME_ERROR,
		  "Error resetting voltage log timer for thread %s",
		  get_name().c_str());      
      }
    }

    return THREAD_SUCCESS;
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_voltage_monitor_thread::cyclic_execute->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
long redrobd_rc_net_server_thread::setup(void)
{
  try {
    redrobd_log_writeln(get_name() + " : setup started");

    // Create server socket
    if (create_tcp_socket(&m_server_sd) != SOCKET_SUPPORT_SUCCESS) {
      THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED,
		"Create server socket failed in thread %s",
		get_name().c_str());
    }

    // Create socket address
    socket_address server_sa;
    if (to_net_address(m_server_ip_address.c_str(),
		       &server_sa.net_addr) != SOCKET_SUPPORT_SUCCESS) {
      THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED,
		"Create server socket address failed in thread %s",
		get_name().c_str());
    }
    server_sa.port = m_server_port;

    // Bind socket to local address and port
    if (bind_socket(m_server_sd,
		    server_sa) != SOCKET_SUPPORT_SUCCESS) {
      THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED,
		"Bind server socket failed in thread %s",
		get_name().c_str());
    }

    // Mark socket as accepting connections
    if (listen_socket(m_server_sd, 0) != SOCKET_SUPPORT_SUCCESS) {
      THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED,
		"Listen server socket failed in thread %s",
		get_name().c_str());
    }
            
    redrobd_log_writeln(get_name() + " : setup done");

    return THREAD_SUCCESS;    
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_rc_net_server_thread::setup->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
Beispiel #6
0
long redrobd_alive_thread::cyclic_execute(void)
{
  try {
    redrobd_led_alive(m_led_alive_activate); // Toggle status LED on/off
    m_led_alive_activate = !m_led_alive_activate;
        
    return THREAD_SUCCESS;
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_alive_thread::cyclic_execute->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
long redrobd_voltage_monitor_thread::cleanup(void)
{
  try {
    redrobd_log_writeln(get_name() + " : cleanup started");
    
    redrobd_log_writeln(get_name() + " : cleanup done");

    return THREAD_SUCCESS;
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_voltage_monitor_thread::cleanup->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
long redrobd_rc_net_server_thread::cleanup(void)
{
  try {
    redrobd_log_writeln(get_name() + " : cleanup started");

    ///////////////////////////////////////////////
    // If no controlled shutdown was requested,
    // proceed with cleanup
    ///////////////////////////////////////////////
    if (!m_shutdown_requested) {

      // Shutdown server socket
      if (shutdown_socket(m_server_sd,
			  true,
			  true) != SOCKET_SUPPORT_SUCCESS) {
	THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED,
		  "Shutdown server socket failed in thread %s",
		  get_name().c_str());
      }
      
      // Close server socket
      if (close_socket(m_server_sd) != SOCKET_SUPPORT_SUCCESS) {
	THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED,
		  "Close server socket failed in thread %s",
		  get_name().c_str());
      }
      m_server_closed = true;
    }

    redrobd_log_writeln(get_name() + " : cleanup done");
    
    return THREAD_SUCCESS;
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_rc_net_server_thread::cleanup->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
Beispiel #9
0
long send_signal_self(int sig)
{
  // Send signal to calling process
  if (kill(getpid(), sig) == -1) {
    syslog_error("kill failed for signal(%d), code=%d (%s)",
		 sig, errno, strerror(errno));
    return DAEMON_FAILURE;
  }

  return DAEMON_SUCCESS;
}
Beispiel #10
0
long redrobd_alive_thread::cleanup(void)
{
  try {
    redrobd_log_writeln(get_name() + " : cleanup started");

    redrobd_led_alive(false); // Turn status LED off

    redrobd_log_writeln(get_name() + " : cleanup done");
    
    return THREAD_SUCCESS;
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_alive_thread::cleanup->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
Beispiel #11
0
long define_signal_handler(int sig, void (*handler)(int))
{
  struct sigaction sa;

  sigemptyset(&sa.sa_mask);
  sa.sa_flags   = SA_RESTART;
  sa.sa_handler = handler;

  if (sigaction(sig, &sa, NULL) == -1) {
    syslog_error("sigaction failed for signal(%d), code=%d (%s)",
		 sig, errno, strerror(errno));
    return DAEMON_FAILURE;
  }

  return DAEMON_SUCCESS;
}
Beispiel #12
0
static long acquire_lock_file(const char *lock_file,
			      int *fd_lock_file)
{
  long rc = DAEMON_FAILURE;
  int fd;

  *fd_lock_file = DAEMON_BAD_FD_LOCK_FILE; // No file descriptor yet
  
  fd = open(lock_file, O_RDWR | O_CLOEXEC | O_CREAT, S_IRUSR | S_IWUSR);
  if (fd != -1) {
  
    struct flock fl;
    fl.l_type   = F_WRLCK;  // Place a write lock
    fl.l_whence = SEEK_SET; // on the entire file
    fl.l_start  = 0;
    fl.l_len    = 0;
    fl.l_pid    = getpid();
 
    if (fcntl(fd, F_SETLK, &fl) != -1) {
      // We have locked file, truncate to zero bytes
      if (ftruncate(fd, 0) != -1) {
	// Write PID to file
	char pid_text[20];
	snprintf(pid_text, sizeof(pid_text), "%ld\n", (long)getpid());
	if (write(fd, pid_text, strlen(pid_text)) == (int)strlen(pid_text)) {
	  rc = DAEMON_SUCCESS; // We created the PID lock file,
	                       // truncated, and write the PID to it.
	  *fd_lock_file = fd;  // Return descriptor to caller
	}
      }
    }    
  }

  if ( (rc != DAEMON_SUCCESS) && (fd != -1) ) {
    close(fd);
    syslog_error("Unable to acquire lock file '%s', code=%d (%s)",
		 lock_file, errno, strerror(errno));
  }

  return rc;
}
Beispiel #13
0
void client_srv_open(void)
{
	struct sockaddr_in saddr;
	u_int16_t          lprt, lowrng, res;
	int                sock, incr, retry;

	/*
	** should we bind a rand(port-range) or increment?
	*/
	incr = !config_bool(NULL,"SockBindRand", 0);

	/*
	** mark socket invalid
	*/
	sock = -1;

	/*
	** Forward connection to destination
	*/
	retry = MAX_RETRIES;
	lprt  = ctx.srv_lrng;
	while(0 <= retry--) {
		/*
		** First of all, get a socket
		*/
		if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
			syslog_error("Srv-Ctrl: can't create socket for %s",
			             ctx.cli_ctrl->peer);
			exit(EXIT_FAILURE);
		}
		socket_opts(sock, SK_CONTROL);

		/*
		** check if we have to take care to a port range
		*/
		if( !(INPORT_ANY == ctx.srv_lrng &&
                      INPORT_ANY == ctx.srv_urng))
		{
			u_int32_t ladr = INADDR_ANY;

			/*
			** bind the socket, taking care of a given port range
			*/
			if(incr) {
				lowrng = lprt;
#if defined(COMPILE_DEBUG)
				debug(2, "Srv-Ctrl: "
				         "about to bind to %s:range(%d-%d)",
				         socket_addr2str(ladr),
				         lowrng, ctx.srv_urng);
#endif
				res = socket_d_bind(sock, ladr,
				       lowrng, ctx.srv_urng, incr);
			} else {
				lowrng = ctx.srv_lrng;
#if defined(COMPILE_DEBUG)
				debug(2, "Srv-Ctrl: "
				         "about to bind to %s:range(%d-%d)",
				         socket_addr2str(ladr),
				         lowrng, ctx.srv_urng);
#endif
				res = socket_d_bind(sock, ladr,
				           lowrng, ctx.srv_urng, incr);
			}

			if (INPORT_ANY == res) {
				/* nothing found? */
				close(sock);
				syslog_error("Srv-Ctrl: can't bind to"
				             " %s:%d for %s",
					     socket_addr2str(ladr),
					     (int)lprt, ctx.cli_ctrl->peer);
				exit(EXIT_FAILURE);
			} else {
				lprt = res;
			}
		} else lprt = INPORT_ANY;

		/*
		** Okay, now try the actual connect to the server
		*/
		memset(&saddr, 0, sizeof(saddr));
		saddr.sin_addr.s_addr = htonl(ctx.srv_addr);
		saddr.sin_family      = AF_INET;
		saddr.sin_port        = htons(ctx.srv_port);

		if (connect(sock, (struct sockaddr *)&saddr,
		            sizeof(saddr)) < 0)
		{
#if defined(COMPILE_DEBUG)
				debug(2, "Srv-Ctrl: connect failed with '%s'",
				      strerror(errno));
#endif
			close(sock);
			sock = -1;
			/* check if is makes sense to retry?
			** perhaps we only need an other
			** local port (EADDRNOTAVAIL) for
			** this destination?
			*/
			if( !(EINTR == errno ||
			      EAGAIN == errno ||
			      EADDRINUSE == errno ||
			      EADDRNOTAVAIL == errno))
			{
				/*
				** an other (real) error ocurred
				*/
				syslog_error("Srv-Ctrl: "
				             "can't connect %s:%d for %s",
				             socket_addr2str(ctx.srv_addr),
				             (int) ctx.srv_port,
				             ctx.cli_ctrl->peer);
				exit(EXIT_FAILURE);
			}
			if(incr && INPORT_ANY != lprt) {
				/* increment lower range if we use
				** increment mode and have a range
				*/
				if(lprt < ctx.srv_urng) {
					lprt++;
				} else {
				/*
				** no more ports in range we can try
				*/
				syslog_error("Srv-Ctrl: "
				             "can't connect %s:%d for %s",
				             socket_addr2str(ctx.srv_addr),
				             (int) ctx.srv_port,
				             ctx.cli_ctrl->peer);
				exit(EXIT_FAILURE);
				}
			}
		} else break;
	}

	/*
	** check if we have a valid, connected socket
	*/
	if(-1 == sock) {
		syslog_error("Srv-Ctrl: can't connect %s:%d for %s",
		             socket_addr2str(ctx.srv_addr),
		             (int) ctx.srv_port,
		             ctx.cli_ctrl->peer);
		exit(EXIT_FAILURE);
	}

	if ((ctx.srv_ctrl = socket_init(sock)) == NULL)
		misc_die(FL, "cmds_user: ?srv_ctrl?");
	ctx.srv_ctrl->ctyp = "Srv-Ctrl";

#if defined(COMPILE_DEBUG)
		debug(2, "Srv-Ctrl is %s:%d",
			ctx.srv_ctrl->peer, (int) ctx.srv_port);
#endif

	ctx.expect = EXP_CONN;		/* Expect Welcome	*/
}
Beispiel #14
0
long redrobd_ctrl_thread::cleanup(void)
{
  try {
    redrobd_log_writeln(get_name() + " : cleanup started");

    ////////////////////////////////////////
    //  FINALIZE battery monitor
    ////////////////////////////////////////
    redrobd_log_writeln("About to finalize battery monitor thread");

    // Take back ownership from auto_ptr
    redrobd_voltage_monitor_thread *thread_ptr2 =
      m_bat_mon_thread_auto.release();
    
    try {
      // Finalize the cyclic battery monitor thread object
      redrobd_thread_finalize((thread *)thread_ptr2,
			      BAT_MON_THREAD_STOP_TIMEOUT);
    }
    catch (...) {
      m_bat_mon_thread_auto =
	auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2);
      throw;
    }
    
    // Give back ownership to auto_ptr
    m_bat_mon_thread_auto =
      auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2);

    // Delete the cyclic battery monitor thread object
    m_bat_mon_thread_auto.reset();

    ////////////////////////////////////////
    //  FINALIZE motor control
    ////////////////////////////////////////

    // Finalize and delete the motor control object
    if (m_cont_steering) {
      m_mc_cont_steer_auto->finalize();
      m_mc_cont_steer_auto.reset();
    }
    else {
      m_mc_non_cont_steer_auto->finalize();
      m_mc_non_cont_steer_auto.reset();
    }

    ////////////////////////////////////////
    //  FINALIZE camera control
    ////////////////////////////////////////

    // Finalize and delete the camera control object
    m_cc_auto->finalize();
    m_cc_auto.reset();

    ////////////////////////////////////////
    //  FINALIZE remote control
    ////////////////////////////////////////

    // Finalize and delete the remote control objects
    m_rc_net_auto->finalize();
    m_rc_net_auto.reset();

    m_rc_rf_auto->finalize();   
    m_rc_rf_auto.reset();

    
    ////////////////////////////////////////
    //  FINALIZE HW configuration
    ////////////////////////////////////////    

    // Finalize and delete the hardware configuration object
    m_hw_cfg_auto->finalize();
    m_hw_cfg_auto.reset();

    ////////////////////////////////////////
    //  FINALIZE A/D Converter
    ////////////////////////////////////////

    // Finalize and delete A/D Converter
    m_mcp3008_io_ptr->finalize();
    delete m_mcp3008_io_ptr;
    m_mcp3008_io_ptr = NULL;

    /////////////////////////////////
    //  FINALIZE ALIVE THREAD
    /////////////////////////////////
    redrobd_log_writeln("About to finalize alive thread");

    // Take back ownership from auto_ptr
    redrobd_alive_thread *thread_ptr1 = m_alive_thread_auto.release();
    
    try {
      // Finalize the cyclic alive thread object
      redrobd_thread_finalize((thread *)thread_ptr1,
			      ALIVE_THREAD_STOP_TIMEOUT);
    }
    catch (...) {
      m_alive_thread_auto = auto_ptr<redrobd_alive_thread>(thread_ptr1);
      throw;
    }

    // Give back ownership to auto_ptr
    m_alive_thread_auto = auto_ptr<redrobd_alive_thread>(thread_ptr1);
    
    // Delete the cyclic alive thread object
    m_alive_thread_auto.reset();
    
    redrobd_log_writeln(get_name() + " : cleanup done");

    return THREAD_SUCCESS;
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_ctrl_thread::cleanup->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
Beispiel #15
0
long redrobd_ctrl_thread::cyclic_execute(void)
{
  try {
    // Check if shutdown was selected (DIP-switch)
    if ( (!m_shutdown_select) && (m_hw_cfg_auto->select_shutdown()) ) {
      redrobd_log_writeln(get_name() + " : Shutdown selected");
      // Send signal to main process
      if (send_signal_self(SIG_TERMINATE_DAEMON) != DAEMON_SUCCESS) {
	THROW_EXP(REDROBD_LINUX_ERROR, REDROBD_SIGNAL_OPERATION_FAILED,
		  "Error sending shutdown signal for thread %s",
		  get_name().c_str());   
      }
      m_shutdown_select = true; // Only signal once
    }

    // Check battery voltage
    if ( !battery_voltage_ok() ) {
      redrobd_led_bat_low(true);   // Turn status LED on
    }
    else {
      redrobd_led_bat_low(false);  // Turn status LED off
    }

    // Check system stats
    check_system_stats();

    // Check state and status of created threads
    check_thread_run_status();

    // Check remote control steering
    uint16_t steering = get_remote_steering();

    // Do motor control
    switch (steering) {
    case REDROBD_RC_STEER_NONE:
      motor_control(REDROBD_MC_NONE);
      break;
    case REDROBD_RC_STEER_FORWARD:
      if (m_verbose) {
	redrobd_log_writeln(get_name() + " : steer forward");
      }
      motor_control(REDROBD_MC_FORWARD);
      break;
    case REDROBD_RC_STEER_REVERSE:
      if (m_verbose) {
	redrobd_log_writeln(get_name() + " : steer reverse");
      }
      motor_control(REDROBD_MC_REVERSE);
      break; 
    case REDROBD_RC_STEER_RIGHT:      
      if (m_verbose) {
	redrobd_log_writeln(get_name() + " : steer right");
      }
      motor_control(REDROBD_MC_RIGHT);
      break;
    case REDROBD_RC_STEER_LEFT:
      if (m_verbose) {
	redrobd_log_writeln(get_name() + " : steer left");
      }
      motor_control(REDROBD_MC_LEFT);
      break;
    default:
      // All other steerings are ignored for now
       ostringstream oss_msg;
       oss_msg << get_name()
	       << " : Got undefined steering = 0x"
	       << hex << setw(4) << setfill('0') << (unsigned)steering;
       redrobd_log_writeln(oss_msg.str());
       oss_msg.str("");

       motor_control(REDROBD_MC_STOP); 
    }

    // Check remote control camera code
    uint16_t camera_code = m_rc_net_auto->get_camera_code();

    // Do camera control
    switch (camera_code) {
    case REDROBD_RC_CAMERA_NONE:
      camera_control(REDROBD_CC_NONE);
      break;
    case REDROBD_RC_CAMERA_STOP_STREAM:
      camera_control(REDROBD_CC_STOP_STREAM);
      break;
    case REDROBD_RC_CAMERA_START_STREAM:
      camera_control(REDROBD_CC_START_STREAM);
      break; 
    default:
      // All other camera codes are ignored for now
       ostringstream oss_msg;
       oss_msg << get_name()
	       << " : Got undefined camera code = 0x"
	       << hex << setw(4) << setfill('0') << (unsigned)steering;
       redrobd_log_writeln(oss_msg.str());
       oss_msg.str("");
    }

    return THREAD_SUCCESS;
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_ctrl_thread::cyclic_execute->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
Beispiel #16
0
static void client_xfer_fireup(void)
{
	u_int32_t ladr = INADDR_ANY;
	int       incr;

	/*
	** should we bind a rand(port-range) or increment?
	*/
	incr = !config_bool(NULL,"SockBindRand", 0);

	/*
	** If appropriate, connect to the client's data port
	*/
	if (ctx.cli_mode == MOD_ACT_FTP) {
		/*
		** TransProxy mode: check if we can use our real
		** ip instead of the server's one as our local ip,
		** we pre-bind the socket/ports to before connect.
		*/
		if(config_bool(NULL, "AllowTransProxy", 0)) {
			ladr = config_addr(NULL, "Listen",
					(u_int32_t)INADDR_ANY);
		}
		if(INADDR_ANY == ladr) {
			ladr = socket_sck2addr(ctx.cli_ctrl->sock,
						LOC_END, NULL);
		}
		if (socket_d_connect(ctx.cli_addr, ctx.cli_port,
				ladr, ctx.act_lrng, ctx.act_urng,
				&(ctx.cli_data), "Cli-Data", incr) == 0)
		{
			syslog_error("can't connect Cli-Data for %s",
						ctx.cli_ctrl->peer);
			client_respond(425, NULL,
					"Can't open data connection");
			client_data_reset(MOD_RESET);
			ctx.expect = EXP_IDLE;
			return;
		}
	}

	/*
	** Send the original command from the client
	*/
	if (ctx.xfer_arg[0] != '\0') {
		socket_printf(ctx.srv_ctrl, "%s %s\r\n",
				ctx.xfer_cmd, ctx.xfer_arg);
		syslog_write(T_INF, "'%s %s' sent for %s",
			ctx.xfer_cmd, ctx.xfer_arg, ctx.cli_ctrl->peer);
	} else {
		socket_printf(ctx.srv_ctrl, "%s\r\n", ctx.xfer_cmd);
		syslog_write(T_INF, "'%s' sent for %s",
			ctx.xfer_cmd, ctx.cli_ctrl->peer);
	}

	/*
	** Prepare the handling and statistics buffers
	*/
	memset(ctx.xfer_rep, 0, sizeof(ctx.xfer_rep));
	ctx.xfer_beg = time(NULL);

	ctx.expect = EXP_XFER;		/* Expect 226 complete	*/
}
Beispiel #17
0
long redrobd_ctrl_thread::setup(void)
{
  try {
    redrobd_log_writeln(get_name() + " : setup started");

    init_members();

    /////////////////////////////////
    //  INITIALIZE ALIVE THREAD
    /////////////////////////////////

    // Create the cyclic alive thread object with garbage collector
    redrobd_alive_thread *thread_ptr1 =
      new redrobd_alive_thread(ALIVE_THREAD_NAME,
			       ALIVE_THREAD_FREQUENCY);    
    m_alive_thread_auto =
      auto_ptr<redrobd_alive_thread>(thread_ptr1);
    
    redrobd_log_writeln("About to initialize alive thread");

    // Take back ownership from auto_ptr
    thread_ptr1 = m_alive_thread_auto.release();
    
    try {
       // Initialize cyclic alive thread object
      redrobd_thread_initialize((thread *)thread_ptr1,
				ALIVE_THREAD_START_TIMEOUT,
				ALIVE_THREAD_EXECUTE_TIMEOUT);
    }
    catch (...) {
      m_alive_thread_auto = auto_ptr<redrobd_alive_thread>(thread_ptr1);
      throw;
    }

    // Give back ownership to auto_ptr
    m_alive_thread_auto = auto_ptr<redrobd_alive_thread>(thread_ptr1);

    /////////////////////////////////
    //  INITIALIZE A/D Converter
    /////////////////////////////////

    // Create the A/D Converter object
    m_mcp3008_io_ptr = new mcp3008_io(MCP3008_SPI_DEV,
				      MCP3008_REF_VOLTAGE);
    
    // Initialize A/D Converter
    m_mcp3008_io_ptr->initialize(MCP3008_SPI_SPEED);
    
    /////////////////////////////////
    //  INITIALIZE HW configuration
    /////////////////////////////////

    // Create the hardware configuration object object with garbage collector
    redrobd_hw_cfg *redrobd_hw_cfg_ptr =
      new redrobd_hw_cfg(m_mcp3008_io_ptr,
			 (MCP3008_IO_CHANNEL)MCP3008_CHN_SHUTDOWN,
			 (MCP3008_IO_CHANNEL)MCP3008_CHN_CONT_STEER);

    m_hw_cfg_auto = auto_ptr<redrobd_hw_cfg>(redrobd_hw_cfg_ptr);

    // Initialize hardware configuration
    m_hw_cfg_auto->initialize();

    /////////////////////////////////
    //  INITIALIZE remote control
    /////////////////////////////////

    // Create the remote control object with garbage collector (RF, Radio)
    redrobd_rc_rf *rc_rf_ptr =
      new redrobd_rc_rf(PIN_RF_IN_3,  // Forward
			PIN_RF_IN_2,  // Reverse
			PIN_RF_IN_0,  // Right
			PIN_RF_IN_1); // Left

    m_rc_rf_auto = auto_ptr<redrobd_rc_rf>(rc_rf_ptr);

    // Initialize remote control (RF, Radio)
    m_rc_rf_auto->initialize();

    // Create the remote control object with garbage collector (NET, Sockets)
    redrobd_rc_net *rc_net_ptr =
      new redrobd_rc_net(RC_NET_SERVER_IP,    // Server local IP address
			 RC_NET_SERVER_PORT); // Server local port

    m_rc_net_auto = auto_ptr<redrobd_rc_net>(rc_net_ptr);

    // Initialize remote control (NET, Sockets)
    m_rc_net_auto->initialize();
    m_rc_net_auto->set_voltage(0.0);

    /////////////////////////////////
    //  INITIALIZE camera control
    /////////////////////////////////

    // Create the camera control object with garbage collector
    redrobd_camera_ctrl *cc_ptr = new redrobd_camera_ctrl();
    m_cc_auto = auto_ptr<redrobd_camera_ctrl>(cc_ptr);

    // Initialize camera control
    m_cc_auto->initialize();
    
    /////////////////////////////////
    //  INITIALIZE motor control
    /////////////////////////////////

    // Check if continuous steering was selected (DIP-switch)
    m_cont_steering = m_hw_cfg_auto->select_continuous_steering();
    if (m_cont_steering) {
      redrobd_log_writeln(get_name() + " : Continuous steering selected");      
    }
    else {
      redrobd_log_writeln(get_name() + " : Non-continuous steering selected");
    }

    // Create the motor control object with garbage collector
    if (m_cont_steering) {
      redrobd_mc_cont_steer *mc_ptr =
	new redrobd_mc_cont_steer(PIN_L293D_1A,  // Right motor
				  PIN_L293D_2A,
				  PIN_L293D_3A,  // Left motor
				  PIN_L293D_4A);
      
      m_mc_cont_steer_auto = auto_ptr<redrobd_mc_cont_steer>(mc_ptr);
    }
    else {
      redrobd_mc_non_cont_steer *mc_ptr =
	new redrobd_mc_non_cont_steer(PIN_L293D_1A,  // Right motor
				      PIN_L293D_2A,
				      PIN_L293D_3A,  // Left motor
				      PIN_L293D_4A);
      
      m_mc_non_cont_steer_auto = auto_ptr<redrobd_mc_non_cont_steer>(mc_ptr);
    }

    // Initialize motor control
    if (m_cont_steering) {
      m_mc_cont_steer_auto->initialize();
    }
    else {
      m_mc_non_cont_steer_auto->initialize();
    }

    /////////////////////////////////
    //  INITIALIZE battery monitor
    /////////////////////////////////

    // Create the cyclic battery monitor thread object with garbage collector
    redrobd_voltage_monitor_thread *thread_ptr2 =
      new redrobd_voltage_monitor_thread(BAT_MON_THREAD_NAME,
					 BAT_MON_THREAD_FREQUENCY,
					 m_mcp3008_io_ptr,
					 (MCP3008_IO_CHANNEL)MCP3008_CHN_VBAT,
					 MCP3008_CHN_VBAT_SF);    
    m_bat_mon_thread_auto =
      auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2);

    redrobd_log_writeln("About to initialize battery monitor thread");

    // Take back ownership from auto_ptr
    thread_ptr2 = m_bat_mon_thread_auto.release();
    
    try {
      // Initialize cyclic battery monitor thread object
      redrobd_thread_initialize((thread *)thread_ptr2,
				BAT_MON_THREAD_START_TIMEOUT,
				BAT_MON_THREAD_EXECUTE_TIMEOUT);
    }
    catch (...) {
      m_bat_mon_thread_auto =
	auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2);
      throw;
    }
    
    // Give back ownership to auto_ptr
    m_bat_mon_thread_auto =
      auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2);

    // Start timer controlling when to check battery
    if (m_battery_check_timer.reset() != TIMER_SUCCESS) {
      THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_TIME_ERROR,
		"Error resetting battery check timer for thread %s",
		get_name().c_str());      
    }

    // Start timer controlling when to check system stats
    if (m_sys_stat_check_timer.reset() != TIMER_SUCCESS) {
      THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_TIME_ERROR,
		"Error resetting system stats check timer for thread %s",
		get_name().c_str());      
    }

    redrobd_log_writeln(get_name() + " : setup done");

    return THREAD_SUCCESS;    
  }
  catch (excep &exp) {
    syslog_error(redrobd_error_syslog_string(exp).c_str());
    return THREAD_INTERNAL_ERROR;
  }
  catch (...) {
    syslog_error("redrobd_ctrl_thread::setup->Unexpected exception");
    return THREAD_INTERNAL_ERROR;
  }
}
Beispiel #18
0
static void client_srv_ctrl_read(char *str)
{
	int code, c1, c2, c3;
	char *arg;

	if (str == NULL)		/* Basic sanity check	*/
		return;

	syslog_write(T_DBG, "from Server-PI (%d): '%.512s'",
	             ctx.srv_ctrl->sock, str);
#if defined(COMPILE_DEBUG)
	debug(1, "from Server-PI (%d): '%.512s'",
					ctx.srv_ctrl->sock, str);
#endif

	/*
	** Intermediate responses can usually be forwarded
	*/
	if (*str < '2' || *str > '5' || str[3] != ' ') {
		/*
		** If this is the destination host's
		** welcome message let's discard it.
		*/
		if (ctx.expect == EXP_CONN)
			return;
		if (ctx.expect == EXP_USER && UAUTH_NONE != ctx.auth_mode)
			return;

#if defined(COMPILE_DEBUG)
		debug(2, "'%.4s'... forwarded to %s %d=%s", str,
			ctx.cli_ctrl->ctyp, ctx.cli_ctrl->sock,
			ctx.cli_ctrl->peer);
#endif
		socket_printf(ctx.cli_ctrl, "%s\r\n", str);
		return;
	}

	/*
	** Consider only valid final response codes
	*/
	if ((code = atoi(str)) < 200 || code > 599) {
		syslog_error("bad response %d from server for %s",
					code, ctx.srv_ctrl->peer);
		return;
	}
	c1 =  code / 100;
	c2 = (code % 100) / 10;
	c3 =  code % 10;
	for (arg = str + 3; *arg == ' '; arg++)
		;

	/*
	** We have a response code, go see what we expected
	*/
	switch (ctx.expect) {
		case EXP_CONN:
			/*
			** Waiting for a 220 Welcome
			*/
			if (c1 == 2) {
				socket_printf(ctx.srv_ctrl,
				              "USER %s\r\n",
				              ctx.username);
				ctx.expect = EXP_USER;
			} else {
				if(UAUTH_NONE != ctx.auth_mode) {
					client_respond(530, NULL,
					               "Login incorrect");
				} else {
					socket_printf(ctx.cli_ctrl,
					              "%s\r\n", str);
				}
				ctx.expect = EXP_IDLE;
				ctx.cli_ctrl->kill = 1;
			}
			break;

		case EXP_USER:
			/*
			** Only the following codes are useful:
			**	230=logged in,
			**	331=need password,
			**	332=need password+account
			*/
			if(UAUTH_NONE != ctx.auth_mode) {
				/*
				** logged in, NO password needed
				*/
				if(c1 == 2 && c2 == 3) {
					client_respond(230, NULL,
					               "User logged in, proceed.");
					ctx.expect = EXP_IDLE;
					break;
				} else
				/*
				** OK, password (+account) needed
				*/
				if(c1 == 3 && c2 == 3) {
					if(ctx.userpass) {
						socket_printf(ctx.srv_ctrl,
						              "PASS %s\r\n",
						              ctx.userpass);
						misc_free(FL, ctx.userpass);
						ctx.userpass = NULL;
					} else {
						socket_printf(ctx.srv_ctrl,
						              "PASS \r\n");
					}
					ctx.expect = EXP_PTHR;
					break;
				}
			}
			/*
			** pass server response through to client
			*/
			socket_printf(ctx.cli_ctrl, "%s\r\n", str);
			if (c1 != 2 && c1 != 3) {
				ctx.cli_ctrl->kill = 1;
			}
			ctx.expect = EXP_IDLE;
			break;

		case EXP_ABOR:
			if (c1 == 2) {
				client_data_reset(MOD_RESET);
				ctx.expect = EXP_IDLE;
			}
			break;

		case EXP_PASV:
			if (code == 227 && *arg != '\0') {
				client_srv_passive(arg);
			} else {
				socket_printf(ctx.cli_ctrl,
						"%s\r\n", str);
				client_data_reset(MOD_RESET);
				ctx.expect = EXP_IDLE;
			}
			break;

		case EXP_PORT:
			if (code == 200) {
				client_xfer_fireup();
			} else {
				socket_printf(ctx.cli_ctrl,
						"%s\r\n", str);
				client_data_reset(MOD_RESET);
				ctx.expect = EXP_IDLE;
			}
			break;

		case EXP_XFER:
			/*
			** Distinguish between success and failure
			*/
			if (c1 == 2) {
				misc_strncpy(ctx.xfer_rep, str,
					sizeof(ctx.xfer_rep));
			} else {
				socket_printf(ctx.cli_ctrl,
						"%s\r\n", str);
				if(config_bool(NULL,"FailResetsPasv", 0)) {
					client_data_reset(MOD_RESET);
				} else {
					client_data_reset(ctx.cli_mode);
				}
			}
			ctx.expect = EXP_IDLE;
			break;

		case EXP_PTHR:
			socket_printf(ctx.cli_ctrl, "%s\r\n", str);
			ctx.expect = EXP_IDLE;
			break;

		case EXP_IDLE:
			socket_printf(ctx.cli_ctrl, "%s\r\n", str);
			if (code == 421) {
				syslog_write(T_WRN,
					"server closed connection "
					"for %s", ctx.cli_ctrl->peer);
				ctx.cli_ctrl->kill = 1;
			} else {
				syslog_write(T_WRN,
					"bogus '%.512s' from "
					"Server-PI for %s",
					ctx.cli_ctrl->peer, str);
			}
			break;
	}
}
Beispiel #19
0
static int client_setup_file(CONTEXT *ctx, char *who)
{
	char      *p;
	u_int16_t  l, u;

	/*
	** little bit sanity check
	*/
	if( !(ctx && who && *who)) {
		return -1;
	}

	/*
	** Inform the auditor that we are using the config file
	*/
	syslog_write(U_INF, "reading data for '%s' from cfg-file", who);

	/*
	** Evaluate DestinationAddress, except we have magic_addr
	*/
	if (INADDR_ANY != ctx->magic_addr) {
		ctx->srv_addr = ctx->magic_addr;
	} else {
		ctx->srv_addr = config_addr(who, "DestinationAddress",
		                                 INADDR_ANY);
#if defined(COMPILE_DEBUG)
		debug(2, "file DestAddr for %s: '%s'",
		      ctx->cli_ctrl->peer, socket_addr2str(ctx->srv_addr));
#endif
	}

	/*
	** Evaluate DestinationPort, except we have magic_port
	*/
	if (INPORT_ANY != ctx->magic_port) {
		ctx->srv_port = ctx->magic_port;
	} else {
		ctx->srv_port = config_port(who, "DestinationPort",
		                                 IPPORT_FTP);
#if defined(COMPILE_DEBUG)
		debug(2, "file DestPort for %s: %d",
		      ctx->cli_ctrl->peer, (int) ctx->srv_port);
#endif
	}

	/*
	** Evaluate the destination transfer mode
	*/
	p = config_str(who, "DestinationTransferMode", "client");
	if(0 == strcasecmp(p, "active")) {
		ctx->srv_mode = MOD_ACT_FTP;
	} else
	if(0 == strcasecmp(p, "passive")) {
		ctx->srv_mode = MOD_PAS_FTP;
	} else
	if(0 == strcasecmp(p, "client")) {
		ctx->srv_mode = MOD_CLI_FTP;
	} else {
		syslog_error("can't eval DestMode for %s",
		             ctx->cli_ctrl->peer);
		return -1;
	}
#if defined(COMPILE_DEBUG)
	debug(2, "file DestMode for %s: %s", ctx->cli_ctrl->peer, p);
#endif

	/*
	** Evaluate min/max destination port range
	*/
	l = config_port(who, "DestinationMinPort", INPORT_ANY);
	u = config_port(who, "DestinationMaxPort", INPORT_ANY);
	if (l > 0 && u > 0 && u >= l) {
		ctx->srv_lrng = l;
		ctx->srv_urng = u;
	} else {
		ctx->srv_lrng = INPORT_ANY;
		ctx->srv_urng = INPORT_ANY;
	}
#if defined(COMPILE_DEBUG)
	debug(2, "file DestRange for %s: %u-%u", ctx->cli_ctrl->peer,
	         ctx->srv_lrng, ctx->srv_urng);
#endif

	/*
	** Evaluate min/max active port range
	*/
	l = config_port(who, "ActiveMinDataPort", INPORT_ANY);
	u = config_port(who, "ActiveMaxDataPort", INPORT_ANY);
	if (l > 0 && u > 0 && u >= l) {
		ctx->act_lrng = l;
		ctx->act_urng = u;
	} else {
		/* do not try to bind a port < 1024 if running as UID != 0 */
		if(0 == getuid()) {
			ctx->act_lrng = (IPPORT_FTP - 1);
			ctx->act_urng = (IPPORT_FTP - 1);
		} else {
			ctx->act_lrng = INPORT_ANY;
			ctx->act_urng = INPORT_ANY;
		}
	}
#if defined(COMPILE_DEBUG)
	debug(2, "file ActiveRange for %s: %u-%u", ctx->cli_ctrl->peer,
	         ctx->act_lrng, ctx->act_urng);
#endif

	/*
	** Evaluate min/max passive port range
	*/
	l = config_port(who, "PassiveMinDataPort", INPORT_ANY);
	u = config_port(who, "PassiveMaxDataPort", INPORT_ANY);
	if (l > 0 && u > 0 && u >= l) {
		ctx->pas_lrng = l;
		ctx->pas_urng = u;
	} else {
		ctx->pas_lrng = INPORT_ANY;
		ctx->pas_urng = INPORT_ANY;
	}
#if defined(COMPILE_DEBUG)
	debug(2, "file PassiveRange for %s: %u-%u", ctx->cli_ctrl->peer,
	         ctx->pas_lrng, ctx->pas_urng);
#endif

	/*
	** Setup other configuration options
	*/
	ctx->same_adr = config_bool(who, "SameAddress", 1);
	ctx->timeout  = config_int (who, "TimeOut",   900);
#if defined(COMPILE_DEBUG)
	debug(2, "file SameAddress for %s: %s", ctx->cli_ctrl->peer,
	                                        ctx->same_adr ? "yes" : "no");
	debug(2, "file TimeOut for %s: %d", ctx->cli_ctrl->peer, ctx->timeout);
#endif

	/*
	** Adjust the allow/deny flags for the commands
	*/
	p = config_str(who, "ValidCommands", NULL);
	cmds_set_allow(p);

	return 0;
}
Beispiel #20
0
int client_setup(char *pwd)
{
	char      *type;
	char      *who;

	/*
	** Setup defaults for the client's DTP process
	*/
	ctx.cli_mode = MOD_ACT_FTP;
	ctx.cli_addr = ctx.cli_ctrl->addr;
	ctx.cli_port = ctx.cli_ctrl->port;
	ctx.srv_addr = INADDR_ANY;
	ctx.srv_port = INPORT_ANY;

	/*
	** select the proper name for user specific setup...
	*/
	if(NULL != ctx.userauth) {
		who = ctx.userauth;
	} else {
		who = ctx.username;
	}

	/*
	** don't allow empty or invalid names...
	*/
	if(NULL != who && '\0' != who[0]) {
		char *ptr;
#if defined(HAVE_REGEX)
		char *rule;
		void *preg = NULL;

		rule = config_str(NULL, "UserNameRule",
		       "^[[:alnum:]]+([%20@/\\._-][[:alnum:]]+)*$");
		       
		syslog_write(T_DBG, "compiling UserNameRule: '%.1024s'", rule);
		if(NULL == (ptr = cmds_reg_comp(&preg, rule))) {
		    return -1;
		}
		syslog_write(T_DBG, "DeHTMLized UserNameRule: '%.1024s'", ptr);

		ptr = cmds_reg_exec(preg, who);
		if(NULL != ptr) {
			syslog_write(U_WRN, "invalid user name '%.128s'%s: %s",
			             who, (strlen(who)>128 ? "..." : ""), ptr);
			cmds_reg_comp(&preg, NULL); /* free regex ptr */
			return -1;
		} else {
			cmds_reg_comp(&preg, NULL); /* free regex ptr */
		}
#else
		/*
		** Simplified "emulation" of the above regex:
		*/
		if( !(isalnum(who[0]) && isalnum(who[strlen(who)-1]))) {
		    syslog_write(U_ERR, "invalid user name '%.128s'%s",
		                 who, (strlen(who)>128 ? "..." : ""));
		    return 1;
		}
		for(ptr=who+1; *ptr; ptr++) {
		    if( !(isalnum(*ptr) ||
		           ' ' == *ptr  || '@' == *ptr || '/' == *ptr ||
		           '.' == *ptr  || '_' == *ptr || '-' == *ptr))
		    {
			syslog_write(U_ERR, "invalid user name '%.128s'%s",
			             who, (strlen(who)>128 ? "..." : ""));
			return -1;
		    }
		}
#endif
	} else {
		/* HUH ?! */
		syslog_write(U_ERR, "empty user name");
		return -1;
	}

	/*
	** user specific setup from config file
	** with fallback to default values
	*/
	if(0 != client_setup_file(&ctx, who)) {
		return -1;
	}

	/*
	** check if we have to authenticate the user
	**
	** authenticate user and setup user specific
	** from ldap server if configured
	*/
	type = config_str(NULL, "UserAuthType", NULL);
	if(NULL != type) {

		if(0 == strcasecmp(type, "ldap")) {
			/*
			** ldap server is mandatory
			*/
			if(NULL == config_str(NULL, "LDAPServer", NULL)) {
				misc_die(FL, "client_setup: ?LDAPServer?");
			}

			/*
			** ldap auth + setup
			*/
			if(0 != ldap_setup_user(&ctx, who, pwd ? pwd : ""))
				return -1;
		} else {
			misc_die(FL, "client_setup: unknown ?UserAuthType?");
		}

	} else {
		/*
		** try ldap setup only
		*/
		ldap_setup_user(&ctx, who, NULL);
	}

	/*
	** Evaluate mandatory settings or refuse to run.
	*/
	errno = 0;
	if(INADDR_ANY == ctx.srv_addr || INADDR_BROADCAST == ctx.srv_addr) {
		syslog_error("can't eval DestAddr for %s", ctx.cli_ctrl->peer);
		return -1;
	}
	if(INPORT_ANY == ctx.srv_port) {
		syslog_error("can't eval DestPort for %s", ctx.cli_ctrl->peer);
		return -1;
	}

	return 0; /* all right */
}
Beispiel #21
0
static int client_setup_file(CONTEXT *ctx, char *who)
{
	char      *p;

	u_int16_t  l, u;

	/*
	** little bit sanity check
	*/
	if( !(ctx && who && *who)) {
		return -1;
	}

	/*
	** Inform the auditor that we are using the config file
	*/
	syslog_write(U_INF, "[ %s ] reading data for '%s' from cfg-file", ctx->cli_ctrl->peer, who);

	/*
	** Evaluate DestinationAddress, except we have magic_addr
	*/
	if (INADDR_ANY != ctx->magic_addr) {
		ctx->srv_addr = ctx->magic_addr;
	} else {
		ctx->srv_addr = config_addr(who, "DestinationAddress",
		                                 INADDR_ANY);
#if defined(COMPILE_DEBUG)
		debug(2, "[ %s ] file DestAddr for %s: '%s'", ctx->cli_ctrl->peer,
		      ctx->cli_ctrl->peer, socket_addr2str(ctx->srv_addr));
#endif
	}

	/*
	** Evaluate DestinationPort, except we have magic_port
	*/
	if (INPORT_ANY != ctx->magic_port) {
		ctx->srv_port = ctx->magic_port;
	} else {
		ctx->srv_port = config_port(who, "DestinationPort",
		                                 IPPORT_FTP);
#if defined(COMPILE_DEBUG)
		debug(2, "[ %s ] file DestPort for %s: %d", ctx->cli_ctrl->peer,
		      ctx->cli_ctrl->peer, (int) ctx->srv_port);
#endif
	}

	/*
	** Evaluate the destination transfer mode
	*/
	p = config_str(who, "DestinationTransferMode", "client");
	if(0 == strcasecmp(p, "active")) {
		ctx->srv_mode = MOD_ACT_FTP;
	} else
	if(0 == strcasecmp(p, "passive")) {
		ctx->srv_mode = MOD_PAS_FTP;
	} else
	if(0 == strcasecmp(p, "client")) {
		ctx->srv_mode = MOD_CLI_FTP;
	} else {
		syslog_error("can't eval DestMode for %s",
		             ctx->cli_ctrl->peer);
		return -1;
	}
#if defined(COMPILE_DEBUG)
	debug(2, "file DestMode for %s: %s", ctx->cli_ctrl->peer, p);
#endif

	/*
	** Evaluate min/max destination port range
	*/
	l = config_port(who, "DestinationMinPort", INPORT_ANY);
	u = config_port(who, "DestinationMaxPort", INPORT_ANY);
	if (l > 0 && u > 0 && u >= l) {
		ctx->srv_lrng = l;
		ctx->srv_urng = u;
	} else {
		ctx->srv_lrng = INPORT_ANY;
		ctx->srv_urng = INPORT_ANY;
	}
#if defined(COMPILE_DEBUG)
	debug(2, "file DestRange for %s: %u-%u", ctx->cli_ctrl->peer,
	         ctx->srv_lrng, ctx->srv_urng);
#endif

	/*
	** Evaluate min/max active port range
	*/
	l = config_port(who, "ActiveMinDataPort", INPORT_ANY);
	u = config_port(who, "ActiveMaxDataPort", INPORT_ANY);
	if (l > 0 && u > 0 && u >= l) {
		ctx->act_lrng = l;
		ctx->act_urng = u;
	} else {
		/* do not try to bind a port < 1024 if running as UID != 0 */
		if(0 == getuid()) {
			ctx->act_lrng = (IPPORT_FTP - 1);
			ctx->act_urng = (IPPORT_FTP - 1);
		} else {
			ctx->act_lrng = INPORT_ANY;
			ctx->act_urng = INPORT_ANY;
		}
	}
#if defined(COMPILE_DEBUG)
	debug(2, "file ActiveRange for %s: %u-%u", ctx->cli_ctrl->peer,
	         ctx->act_lrng, ctx->act_urng);
#endif

	/*
	** Evaluate min/max passive port range
	*/
	l = config_port(who, "PassiveMinDataPort", INPORT_ANY);
	u = config_port(who, "PassiveMaxDataPort", INPORT_ANY);
	if (l > 0 && u > 0 && u >= l) {
		ctx->pas_lrng = l;
		ctx->pas_urng = u;
	} else {
		ctx->pas_lrng = INPORT_ANY;
		ctx->pas_urng = INPORT_ANY;
	}
#if defined(COMPILE_DEBUG)
	debug(2, "file PassiveRange for %s: %u-%u", ctx->cli_ctrl->peer,
	         ctx->pas_lrng, ctx->pas_urng);
#endif

	/*
	** Setup other configuration options
	*/
	ctx->same_adr = config_bool(who, "SameAddress", 1);
	ctx->timeout  = config_int (who, "TimeOut",   900);
#if defined(COMPILE_DEBUG)
	debug(2, "file SameAddress for %s: %s", ctx->cli_ctrl->peer,
	                                        ctx->same_adr ? "yes" : "no");
	debug(2, "file TimeOut for %s: %d", ctx->cli_ctrl->peer, ctx->timeout);
#endif

/*** Adjust the allow/deny flags for the commands ** Fred patch */
	
	char dest[17];
	char ipdest[17];
	char ipsrc[17];
	strcpy (ipsrc,ctx->cli_ctrl->peer);
	strcpy (ipdest, socket_addr2str(ctx->srv_addr));
	syslog_write(U_INF, "\n");	
	syslog_write(U_INF, "[ %s ] Fred Patch rules dest: %s src: %s", ipsrc, ipdest, ipsrc);	

	char groupname[]="group";
	char commandename[]="ValidCommands";
	char *group;
	FILE *fp;
	group = "group1";
	int ix;
	int ix2;
	u_int32_t dnsaddr;
	for(ix=1; group != NULL; ix++) {
		sprintf (&groupname[5],"%d",ix);
		group = config_str(who, groupname, NULL);
		}
	
	syslog_write(U_INF, "[ %s ] Number of groups: %d", ipsrc, ix-2);
		
	for (ix2=1; ix2 <= ix-2; ix2++) {
		sprintf (&groupname[5],"%d",ix2);
		group = config_str(who, groupname, NULL);
		syslog_write(U_INF, "[ %s ] Reading: %s",ipsrc, group );
		if ((fp = fopen(group, "r")) == NULL)
			{
			syslog_write(U_INF, "File not found");
			return 0;
			}
		else
			{	
			fseek(fp, 0, SEEK_SET);
			while (fgets(dest, 17 , fp) != NULL)
				{	
				// Pour une IP
				// Correction Bug Ligne sans \n 
					dest[16] = '\n';
					char *c = strchr (dest, '\n');
					*c = 0;
					/*  Dns resolution */
					if (ipdest != dest) {
						dnsaddr = socket_str2addr(dest, INADDR_ANY);
						if (dnsaddr != 0) 
							strcpy (dest, socket_addr2str(dnsaddr));
						}
					if (strcmp(dest,ipdest) == 0 || strcmp(dest,ipsrc) == 0)
					{
						sprintf (&commandename[13],"%d",ix);
						p = config_str(who,commandename, NULL);
						cmds_set_allow(p);
						syslog_write(U_INF, "[ %s ] Apply rules for: %s dst: %s",ipsrc, ipsrc, ipdest);
						syslog_write(U_INF, "[ %s ] Server match %s ",ipsrc, group );
						syslog_write(U_INF, "\n");
						fclose(fp);
						return 0;
					}
			// Network
				if (strchr(dest, 'x') != NULL)
					{ 
						char *c = strchr(dest, 'x');
						*c = 0;
						int longueur;
						longueur = strlen(dest);
						if (strncmp(dest,ipdest,longueur) == 0 || strncmp(dest,ipsrc,longueur) == 0)
						{
							sprintf (&commandename[13],"%d",ix);
							p = config_str(who,commandename, NULL);
							cmds_set_allow(p);
							syslog_write(U_INF, "[ %s ] Apply rules for Network: %s src: %s",ipsrc, ipdest, ipsrc);
							syslog_write(U_INF, "[ %s ] Server match %s ",ipsrc, group );
							syslog_write(U_INF, "\n");
							fclose(fp);
							return 0;
						}
					}
				}

			fclose(fp);
			}	
		}
	syslog_write(U_INF, "[ %s ] Oh, Oh, no rule found -> defaultrules", ipsrc) ;
	p = config_str(who, "defaultrules", NULL);
	cmds_set_allow(p); 
	return 0;
}
Beispiel #22
0
long become_daemon(const char *run_as_user,
		   const char *work_dir,
		   const char *lock_file,
		   int *fd_lock_file)
{
  pid_t pid;
  int fd;

  *fd_lock_file = DAEMON_BAD_FD_LOCK_FILE;

  // Switch to specified user
  if (run_as_user) {
    struct passwd *pw_info = getpwnam(run_as_user);
    if (pw_info) {
      if (setuid(pw_info->pw_uid) == -1) {
	syslog_error("setuid failed for %s, code=%d (%s)",
		     run_as_user, errno, strerror(errno));
	return DAEMON_FAILURE;
      }
    }
    else {
      syslog_error("getpwnam failed for %s", run_as_user);
      return DAEMON_FAILURE;
    }
  }

  // Step 1 : Create a child process
  pid = fork();
  switch (pid) {
  case -1 :
    syslog_error("fork(1) failed, code=%d (%s)", errno, strerror(errno));
    return DAEMON_FAILURE;
  case 0 :
    break;               // Child falls through
  default :
    exit(EXIT_SUCCESS);  // Parent terminates OK
  }

  // Step 2 : Become leader of new session
  if (setsid() == -1) {
    syslog_error("setsid failed, code=%d (%s)", errno, strerror(errno));
    return DAEMON_FAILURE;
  }

  // Step 3 : Ensure no controlling terminal
  pid = fork();
  switch (pid) {
  case -1 :
    syslog_error("fork(2) failed, code=%d (%s)", errno, strerror(errno));
    return DAEMON_FAILURE;
  case 0 :
    break;               // Grand-child falls through
  default :
    exit(EXIT_SUCCESS);  // Child terminates OK
  }

  // This process (grand-child) will be the actual daemon

  // Step 4 : Clear file mode creation mask
  umask(0);

  // Step 5 : Change current working directory
  if (chdir(work_dir) == -1) {
    syslog_error("chdir to '%s' failed, code=%d (%s)",
		 work_dir, errno, strerror(errno));
    return DAEMON_FAILURE;
  }

  // Step 6: Close standard file descriptors
  close(STDIN_FILENO);
  close(STDOUT_FILENO);
  close(STDERR_FILENO);

  // Step 7 : Redirect standard file descriptors to /dev/null
  fd = open("/dev/null", O_RDWR);
  if (fd != STDIN_FILENO) {
    syslog_error("Redirect STDIN failed, code=%d (%s)",
		 errno, strerror(errno));
    return DAEMON_FAILURE;
  }
  if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO) {
    syslog_error("Redirect STDOUT failed, code=%d (%s)",
		 errno, strerror(errno));
    return DAEMON_FAILURE;
  }
  if (dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) {
    syslog_error("Redirect STDERR failed, code=%d (%s)",
		 errno, strerror(errno));
    return DAEMON_FAILURE;
  }

  // Create lock file to prevent more than one instance
  // of the daemon is being executed
  if (lock_file) {
    if (acquire_lock_file(lock_file,
			  fd_lock_file) != DAEMON_SUCCESS) {
      return DAEMON_FAILURE;
    }
  }

  return DAEMON_SUCCESS;
}