slattach: new applet.
This commit is contained in:
		@@ -296,6 +296,7 @@ USE_FEATURE_SH_IS_HUSH(APPLET_NOUSAGE(sh, hush, _BB_DIR_BIN, _BB_SUID_NEVER))
 | 
			
		||||
USE_FEATURE_SH_IS_LASH(APPLET_NOUSAGE(sh, lash, _BB_DIR_BIN, _BB_SUID_NEVER))
 | 
			
		||||
USE_FEATURE_SH_IS_MSH(APPLET_NOUSAGE(sh, msh, _BB_DIR_BIN, _BB_SUID_NEVER))
 | 
			
		||||
USE_SHA1SUM(APPLET_ODDNAME(sha1sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sha1sum))
 | 
			
		||||
USE_SLATTACH(APPLET(slattach, _BB_DIR_SBIN, _BB_SUID_NEVER))
 | 
			
		||||
USE_SLEEP(APPLET_NOFORK(sleep, sleep, _BB_DIR_BIN, _BB_SUID_NEVER, sleep))
 | 
			
		||||
USE_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, _BB_DIR_USR_BIN, _BB_SUID_NEVER, softlimit))
 | 
			
		||||
USE_SORT(APPLET_NOEXEC(sort, sort, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sort))
 | 
			
		||||
 
 | 
			
		||||
@@ -2991,6 +2991,20 @@ USE_FEATURE_RUN_PARTS_FANCY("\n	-l	Prints names of all matching files even when
 | 
			
		||||
       "	-s	Don't output anything, status code shows success\n" \
 | 
			
		||||
       "	-w	Warn about improperly formatted SHA1 checksum lines")
 | 
			
		||||
 | 
			
		||||
#define slattach_trivial_usage \
 | 
			
		||||
       "[-cehmLF] [-s speed] [-p protocol] DEVICEs"
 | 
			
		||||
#define slattach_full_usage \
 | 
			
		||||
       "Attach network interface(s) to serial line(s)\n" \
 | 
			
		||||
     "\nOptions:" \
 | 
			
		||||
     "\n	-p	Set protocol (slip, cslip, slip6, clisp6 or adaptive)" \
 | 
			
		||||
     "\n	-s	Set line speed" \
 | 
			
		||||
     "\n	-e	Exit after initializing device" \
 | 
			
		||||
     "\n	-h	Exit when the carrier is lost" \
 | 
			
		||||
     "\n	-c	Execute a command when the line is hung up" \
 | 
			
		||||
     "\n	-m	Do NOT initialize the line in raw 8 bits mode" \
 | 
			
		||||
     "\n	-L	Enable 3-wire operation" \
 | 
			
		||||
     "\n	-F	Disable RTS/CTS flow control" \
 | 
			
		||||
 
 | 
			
		||||
#define sleep_trivial_usage \
 | 
			
		||||
	USE_FEATURE_FANCY_SLEEP("[") "N" USE_FEATURE_FANCY_SLEEP("]...")
 | 
			
		||||
#define sleep_full_usage \
 | 
			
		||||
 
 | 
			
		||||
@@ -548,6 +548,12 @@ config ROUTE
 | 
			
		||||
	help
 | 
			
		||||
	  Route displays or manipulates the kernel's IP routing tables.
 | 
			
		||||
 | 
			
		||||
config SLATTACH
 | 
			
		||||
	bool "slattach"
 | 
			
		||||
	default n
 | 
			
		||||
	help
 | 
			
		||||
	  slattach is a small utility to attach network interfaces to serial lines.
 | 
			
		||||
 | 
			
		||||
config TELNET
 | 
			
		||||
	bool "telnet"
 | 
			
		||||
	default n
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ lib-$(CONFIG_PING)         += ping.o
 | 
			
		||||
lib-$(CONFIG_PING6)        += ping.o
 | 
			
		||||
lib-$(CONFIG_PSCAN)        += pscan.o
 | 
			
		||||
lib-$(CONFIG_ROUTE)        += route.o
 | 
			
		||||
lib-$(CONFIG_SLATTACH)     += slattach.o
 | 
			
		||||
lib-$(CONFIG_TELNET)       += telnet.o
 | 
			
		||||
lib-$(CONFIG_TELNETD)      += telnetd.o
 | 
			
		||||
lib-$(CONFIG_TFTP)         += tftp.o
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										240
									
								
								networking/slattach.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								networking/slattach.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,240 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Stripped down version of net-tools for busybox.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Ignacio Garcia Perez (iggarpe at gmail dot com)
 | 
			
		||||
 *
 | 
			
		||||
 * License: GPLv2 or later, see LICENSE file in this tarball.
 | 
			
		||||
 *
 | 
			
		||||
 * There are some differences from the standard net-tools slattach:
 | 
			
		||||
 *
 | 
			
		||||
 * - The -l option is not supported.
 | 
			
		||||
 *
 | 
			
		||||
 * - The -F options allows disabling of RTS/CTS flow control.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libbb.h"
 | 
			
		||||
 | 
			
		||||
/* Line discipline code table */
 | 
			
		||||
static const char *const proto_names[] = {
 | 
			
		||||
	"slip",		/* 0 */
 | 
			
		||||
	"cslip",	/* 1 */
 | 
			
		||||
	"slip6",	/* 2 */
 | 
			
		||||
	"cslip6",	/* 3 */
 | 
			
		||||
	"adaptive",	/* 8 */
 | 
			
		||||
	NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct globals {
 | 
			
		||||
	int handle;
 | 
			
		||||
	int saved_disc;
 | 
			
		||||
	struct termios saved_state;
 | 
			
		||||
};
 | 
			
		||||
#define G (*(struct globals*)&bb_common_bufsiz1)
 | 
			
		||||
#define handle       (G.handle      )
 | 
			
		||||
#define saved_disc   (G.saved_disc  )
 | 
			
		||||
#define saved_state  (G.saved_state )
 | 
			
		||||
#define INIT_G() do {} while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Save tty state and line discipline
 | 
			
		||||
 *
 | 
			
		||||
 * It is fine here to bail out on errors, since we haven modified anything yet
 | 
			
		||||
 */
 | 
			
		||||
static void save_state(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Save line status */
 | 
			
		||||
	if (tcgetattr(handle, &saved_state) < 0)
 | 
			
		||||
		bb_perror_msg_and_die("get state");
 | 
			
		||||
 | 
			
		||||
	/* Save line discipline */
 | 
			
		||||
	if (ioctl(handle, TIOCGETD, &saved_disc) < 0)
 | 
			
		||||
		bb_perror_msg_and_die("get discipline");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Restore state and line discipline for ALL managed ttys
 | 
			
		||||
 *
 | 
			
		||||
 * Restoring ALL managed ttys is the only way to have a single
 | 
			
		||||
 * hangup delay.
 | 
			
		||||
 *
 | 
			
		||||
 * Go on after errors: we want to restore as many controlled ttys
 | 
			
		||||
 * as possible.
 | 
			
		||||
 */
 | 
			
		||||
static void restore_state_and_exit(int exitcode) ATTRIBUTE_NORETURN;
 | 
			
		||||
static void restore_state_and_exit(int exitcode)
 | 
			
		||||
{
 | 
			
		||||
	struct termios state;
 | 
			
		||||
 | 
			
		||||
	/* Restore line discipline */
 | 
			
		||||
	if (ioctl(handle, TIOCSETD, &saved_disc) < 0) {
 | 
			
		||||
		bb_perror_msg("set discipline");
 | 
			
		||||
		exitcode = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Hangup */
 | 
			
		||||
	memcpy(&state, &saved_state, sizeof(state));
 | 
			
		||||
	cfsetispeed(&state, B0);
 | 
			
		||||
	cfsetospeed(&state, B0);
 | 
			
		||||
	if (tcsetattr(handle, TCSANOW, &state) < 0) {
 | 
			
		||||
		bb_perror_msg("set state");
 | 
			
		||||
		exitcode = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sleep(1);
 | 
			
		||||
 | 
			
		||||
	/* Restore line status */
 | 
			
		||||
	if (tcsetattr(handle, TCSANOW, &saved_state) < 0) {
 | 
			
		||||
		bb_perror_msg_and_die("set state");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ENABLE_FEATURE_CLEAN_UP)
 | 
			
		||||
		close(handle);
 | 
			
		||||
 | 
			
		||||
	exit(exitcode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set tty state, line discipline and encapsulation
 | 
			
		||||
 */
 | 
			
		||||
static void set_state(struct termios *state, int encap)
 | 
			
		||||
{
 | 
			
		||||
	int disc;
 | 
			
		||||
 | 
			
		||||
	/* Set line status */
 | 
			
		||||
	if (tcsetattr(handle, TCSANOW, state) < 0) {
 | 
			
		||||
		bb_perror_msg("set state");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set line discliple (N_SLIP always) */
 | 
			
		||||
	disc = N_SLIP;
 | 
			
		||||
	if (ioctl(handle, TIOCSETD, &disc) < 0) {
 | 
			
		||||
		bb_perror_msg("set discipline");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set encapsulation (SLIP, CSLIP, etc) */
 | 
			
		||||
	if (ioctl(handle, SIOCSIFENCAP, &encap) < 0) {
 | 
			
		||||
		bb_perror_msg("set encapsulation");
 | 
			
		||||
 bad:
 | 
			
		||||
		restore_state_and_exit(1);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sig_handler(int signo)
 | 
			
		||||
{
 | 
			
		||||
	restore_state_and_exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int slattach_main(int argc, char **argv);
 | 
			
		||||
int slattach_main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	int i, encap, opt;
 | 
			
		||||
	struct termios state;
 | 
			
		||||
	const char *proto = "cslip";
 | 
			
		||||
	const char *extcmd;				/* Command to execute after hangup */
 | 
			
		||||
	const char *baud_str;
 | 
			
		||||
	int baud_code = -1;				/* Line baud rate (system code) */
 | 
			
		||||
 | 
			
		||||
	enum {
 | 
			
		||||
		OPT_p_proto  = 1 << 0,
 | 
			
		||||
		OPT_s_baud   = 1 << 1,
 | 
			
		||||
		OPT_c_extcmd = 1 << 2,
 | 
			
		||||
		OPT_e_quit   = 1 << 3,
 | 
			
		||||
		OPT_h_watch  = 1 << 4,
 | 
			
		||||
		OPT_m_nonraw = 1 << 5,
 | 
			
		||||
		OPT_L_local  = 1 << 6,
 | 
			
		||||
		OPT_F_noflow = 1 << 7,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	INIT_G();
 | 
			
		||||
 | 
			
		||||
	/* Parse command line options */
 | 
			
		||||
	opt = getopt32(argc, argv, "p:s:c:ehmLF", &proto, &baud_str, &extcmd);
 | 
			
		||||
	/*argc -= optind;*/
 | 
			
		||||
	argv += optind;
 | 
			
		||||
 | 
			
		||||
	if (!*argv)
 | 
			
		||||
		bb_show_usage();
 | 
			
		||||
 | 
			
		||||
	encap = index_in_str_array(proto_names, proto);
 | 
			
		||||
 | 
			
		||||
	if (encap < 0)
 | 
			
		||||
		bb_error_msg_and_die("invalid protocol %s", proto);
 | 
			
		||||
	if (encap > 3)
 | 
			
		||||
		encap = 8;
 | 
			
		||||
 | 
			
		||||
	/* We want to know if the baud rate is valid before we start touching the ttys */
 | 
			
		||||
	if (opt & OPT_s_baud) {
 | 
			
		||||
		baud_code = tty_value_to_baud(xatoi(baud_str));
 | 
			
		||||
		if (baud_code < 0)
 | 
			
		||||
			bb_error_msg_and_die("invalid baud rate");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Trap signals in order to restore tty states upon exit */
 | 
			
		||||
	if (!(opt & OPT_e_quit)) {
 | 
			
		||||
		signal(SIGHUP, sig_handler);
 | 
			
		||||
		signal(SIGINT, sig_handler);
 | 
			
		||||
		signal(SIGQUIT, sig_handler);
 | 
			
		||||
		signal(SIGTERM, sig_handler);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Open tty */ 
 | 
			
		||||
	handle = open(*argv, O_RDWR | O_NDELAY);
 | 
			
		||||
	if (handle < 0) {
 | 
			
		||||
		char *buf = xasprintf("/dev/%s", *argv);
 | 
			
		||||
		handle = xopen(buf, O_RDWR | O_NDELAY);
 | 
			
		||||
		/* maybe if (ENABLE_FEATURE_CLEAN_UP) ?? */
 | 
			
		||||
		free(buf);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Save current tty state */
 | 
			
		||||
	save_state();
 | 
			
		||||
 | 
			
		||||
	/* Confgure tty */
 | 
			
		||||
	memcpy(&state, &saved_state, sizeof(state));
 | 
			
		||||
	if (!(opt & OPT_m_nonraw)) { /* raw not suppressed */
 | 
			
		||||
		memset(&state.c_cc, 0, sizeof(state.c_cc));
 | 
			
		||||
		state.c_cc[VMIN] = 1;
 | 
			
		||||
		state.c_iflag = IGNBRK | IGNPAR;
 | 
			
		||||
		state.c_oflag = 0;
 | 
			
		||||
		state.c_lflag = 0;
 | 
			
		||||
		state.c_cflag = CS8 | HUPCL | CREAD
 | 
			
		||||
		              | ((opt & OPT_L_local) ? CLOCAL : 0)
 | 
			
		||||
		              | ((opt & OPT_F_noflow) ? 0 : CRTSCTS);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (opt & OPT_s_baud) {
 | 
			
		||||
		cfsetispeed(&state, baud_code);
 | 
			
		||||
		cfsetospeed(&state, baud_code);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	set_state(&state, encap);
 | 
			
		||||
 | 
			
		||||
	/* Exit now if option -e was passed */
 | 
			
		||||
	if (opt & OPT_e_quit)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* If we're not requested to watch, just keep descriptor open
 | 
			
		||||
	 * till we are killed */
 | 
			
		||||
	if (!(opt & OPT_h_watch))
 | 
			
		||||
		while (1)
 | 
			
		||||
			sleep(24*60*60);
 | 
			
		||||
 | 
			
		||||
	/* Watch line for hangup */
 | 
			
		||||
	while (1) {
 | 
			
		||||
		if (ioctl(handle, TIOCMGET, &i) < 0 || !(i & TIOCM_CAR))
 | 
			
		||||
			goto no_carrier;
 | 
			
		||||
		sleep(15);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 no_carrier:
 | 
			
		||||
 | 
			
		||||
	/* Execute command on hangup */
 | 
			
		||||
	if (opt & OPT_c_extcmd)
 | 
			
		||||
		system(extcmd);
 | 
			
		||||
 | 
			
		||||
	/* Restore states and exit */
 | 
			
		||||
	restore_state_and_exit(0);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user