⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 controller.c

📁 This project provides a proxy that allows telnet/tcp connections to be made to serial ports on a mac
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  ser2net - A program for allowing telnet connection to serial ports *  Copyright (C) 2001  Corey Minyard <minyard@acm.org> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <sys/types.h>#include <sys/time.h>#include <sys/socket.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <netinet/in.h>#include <errno.h>#include <syslog.h>#include "controller.h"#include "selector.h"#include "dataxfer.h"#include "utils.h"#include "telnet.h"extern selector_t *ser2net_sel;/** BASED ON sshd.c FROM openssh.com */#ifdef HAVE_TCPD_H#include <tcpd.h>int allow_severity = LOG_INFO;int deny_severity = LOG_WARNING;static char *progname = "ser2net-control";#endif /* HAVE_TCPD_H *//* This file holds the code that runs the control port. */static int acceptfd;	/* The file descriptor for the accept port. */static int max_controller_ports = 4;	/* How many control connections					   do we allow at a time. */static int num_controller_ports = 0;	/* How many control connections					   are currently active. */#define INBUF_SIZE 255	/* The size of the maximum input command. */char *prompt = "-> ";/* This data structure is kept for each control connection. */typedef struct controller_info {    int            tcpfd;		/* When connected, the file                                           descriptor for the TCP                                           port used for I/O. */    struct sockaddr_in remote;		/* The socket address of who					   is connected to this port. */    unsigned char inbuf[INBUF_SIZE+1];	/* Buffer to receive command on. */    int  inbuf_count;			/* The number of bytes currently					   in the inbuf. */    char *outbuf;			/* The output buffer, NULL if					   no output. */    int  outbufsize;			/* Total size of the memory					   allocated in outbuf. */    int  outbuf_pos;			/* The current position in the					   output buffer. */    int  outbuf_count;			/* The number of bytes					   (starting at outbuf_pos)					   left to transmit. */    void *monitor_port_id;		/* When port monitoring, this is					   the id given when the monitoring					   is started.  It is used to stop					   monitoring. */    struct controller_info *next;	/* Used to keep these items in					   a linked list. */    /* Data used by the telnet processing. */    telnet_data_t tn_data;} controller_info_t;/* List of current control connections. */controller_info_t *controllers = NULL;/* Used to initialize the telnet session. */static char telnet_init_seq[] = {    TN_IAC, TN_WILL, TN_OPT_SUPPRESS_GO_AHEAD,    TN_IAC, TN_WILL, TN_OPT_ECHO,    TN_IAC, TN_DONT, TN_OPT_ECHO,};static struct telnet_cmd telnet_cmds[] = {    /*                        I will,  I do,  sent will, sent do */    { TN_OPT_SUPPRESS_GO_AHEAD,	   0,     1,          1,       0, },    { TN_OPT_ECHO,		   0,     1,          1,       1, },    { TN_OPT_BINARY_TRANSMISSION,  1,     1,          0,       1, },    { 255 }};/* Shut down a control connection and remove it from the list of   controllers. */static voidshutdown_controller(controller_info_t *cntlr){    controller_info_t *prev;    controller_info_t *curr;    if (cntlr->monitor_port_id != NULL) {	data_monitor_stop(cntlr, cntlr->monitor_port_id);	cntlr->monitor_port_id = NULL;    }    sel_clear_fd_handlers(ser2net_sel, cntlr->tcpfd);    close(cntlr->tcpfd);    if (cntlr->outbuf != NULL) {	free(cntlr->outbuf);    }    cntlr->outbuf = NULL;    /* Remove it from the linked list. */    prev = NULL;    curr = controllers;    while (curr != NULL) {	if (cntlr == curr) {	    if (prev == NULL) {		controllers = controllers->next;	    } else {		prev->next = curr->next;	    }	    num_controller_ports--;	    break;	}	prev = curr;	curr = curr->next;    }    free(cntlr);}/* Send some output to the control connection.  This allocates and   free a buffer in blocks of 1024 and increases the size of the   buffer as necessary. */voidcontroller_output(struct controller_info *cntlr,		  char                   *data,		  int                    count){    if (cntlr->outbuf != NULL) {	/* Already outputting data, just add more onto it. */	int  new_size = cntlr->outbuf_count + count;	if (new_size <= cntlr->outbufsize) {	    /* It will fit into the current buffer, just move things	       around and append it. */	    int i;	    if (cntlr->outbuf_pos > 0) {		for (i=0; i<cntlr->outbuf_count; i++) {		    cntlr->outbuf[i] = cntlr->outbuf[cntlr->outbuf_pos + i];		}	    }	    memcpy(&(cntlr->outbuf[cntlr->outbuf_count]), data, count);	} else {	    /* We need to allocate a larger buffer. */	    char *newbuf;	    /* Allocate the next even multiple of 1024 bytes. */	    new_size = ((new_size / 1024) * 1024) + 1024;	    newbuf = malloc(new_size);	    if (newbuf == NULL) {		/* Out of memory, just ignore thre request */		return;	    }	    cntlr->outbufsize = new_size;	    /* Copy all the data into a new buffer. */	    memcpy(newbuf,		   &(cntlr->outbuf[cntlr->outbuf_pos]),		   cntlr->outbuf_count);	    memcpy(newbuf+cntlr->outbuf_count, data, count);	    free(cntlr->outbuf);	    cntlr->outbuf = newbuf;	}	cntlr->outbuf_pos = 0;	cntlr->outbuf_count += count;    } else {	/* We are starting a new buffer, just get it. */	char *newbuf;	int  new_size = ((count / 1024) * 1024) + 1024;	newbuf = malloc(new_size);	if (newbuf == NULL) {	    /* Out of memory, just ignore thre request */	    return;	}		cntlr->outbufsize = new_size;	memcpy(newbuf, data, count);	cntlr->outbuf = newbuf;	cntlr->outbuf_pos = 0;	cntlr->outbuf_count = count;	sel_set_fd_read_handler(ser2net_sel, cntlr->tcpfd,				SEL_FD_HANDLER_DISABLED);	sel_set_fd_write_handler(ser2net_sel, cntlr->tcpfd,				 SEL_FD_HANDLER_ENABLED);    }}/* Write some data directly to the controllers output port. */voidcontroller_write(struct controller_info *cntlr, char *data, int count){    write(cntlr->tcpfd, data, count);}static voidtelnet_output_ready(void *cb_data){    struct controller_info *cntlr = cb_data;    sel_set_fd_read_handler(ser2net_sel, cntlr->tcpfd,			    SEL_FD_HANDLER_DISABLED);    sel_set_fd_write_handler(ser2net_sel, cntlr->tcpfd,			     SEL_FD_HANDLER_ENABLED);}/* Called when a telnet command is received. */voidtelnet_cmd_handler(void *cb_data, unsigned char cmd){    /* These are ignored for now. */}static char *help_str ="exit - leave the program.\n\r""help - display this help.\n\r""version - display the version of this program.\n\r""monitor <type> <tcp port> - display all the input for a given port on\n\r""       the calling control port.  Only one direction may be monitored\n\r""       at a time.  The type field may be 'tcp' or 'term' and specifies\n\r""       whether to monitor data from the TCP port or from the serial port\n\r""       Note that data monitoring is best effort, if the controller port\n\r""       cannot keep up the data will be silently dropped.  A controller\n\r""       may only monitor one thing and a port may only be monitored by\n\r""       one controller.\n\r""monitor stop - stop the current monitor.\n\r""disconnect <tcp port> - disconnect the tcp connection on the port.\n\r""showport [<tcp port>] - Show information about a port. If no port is\n\r""       given, all ports are displayed.\n\r""showshortport [<tcp port>] - Show information about a port in a one-line\n\r""       format. If no port is given, all ports are displayed.\n\r""setporttimeout <tcp port> <timeout> - Set the amount of time in seconds\n\r""       before the port connection will be shut down if no activity\n\r""       has been seen on the port.\n\r""setportconfig <tcp port> <config> - Set the port configuration as in\n\r""       the device configuration in the ser2net.conf file.  Valid options\n\r""       are: 300, 1200, 2400, 4800, 9600, 19200, 38400, 115200, EVEN, ODD\n\r""       NONE, 1STOPBIT, 2STOPBITS, 7DATABITS, 8DATABITS, LOCAL (ignore\n\r""       modem control), [-]RTSCTS, [-]XONXOFF.\n\r""       Note that these will not change until the port is disconnected\n\r""       and connected again.\n\r""setportcontrol <tcp port> <controls>\n\r""       Dynamically modify the characteristics of the port.  These are\n\r""       immedaite and won't live between connections.  Valid controls are\n\r""       DTRHI, DTRLO, RTSHI, and RTSLO.\n\r""setportenable <tcp port> <enable state> - Sets the port operation state.\n\r""       Valid states are:\n\r""         off - The TCP port is shut down\n\r""         raw - The TCP port is up and all I/O is transferred\n\r""         rawlp - The TCP port is up and the input is transferred to dev\n\r""         telnet - The TCP port is up and the telnet negotiation protocol\n\r""                  runs on the port.\n\r";/* Process a line of input.  This scans for commands, reads any   parameters, then calls the actual code to handle the command. */voidprocess_input_line(controller_info_t *cntlr){    char *strtok_data;    char *tok;    char *str;    tok = strtok_r(cntlr->inbuf, " \t", &strtok_data);    if (tok == NULL) {	/* Empty line, just ignore it. */    } else if (strcmp(tok, "exit") == 0) {	shutdown_controller(cntlr);	return; /* We don't want a prompt any more. */    } else if (strcmp(tok, "quit") == 0) {	shutdown_controller(cntlr);	return; /* We don't want a prompt any more. */    } else if (strcmp(tok, "help") == 0) {	controller_output(cntlr, help_str, strlen(help_str));    } else if (strcmp(tok, "version") == 0) {	str = "ser2net version ";	controller_output(cntlr, str, strlen(str));	str = VERSION;	controller_output(cntlr, str, strlen(str));	controller_output(cntlr, "\n\r", 2);    } else if (strcmp(tok, "showport") == 0) {	tok = strtok_r(NULL, " \t", &strtok_data);	showports(cntlr, tok);    } else if (strcmp(tok, "showshortport") == 0) {	tok = strtok_r(NULL, " \t", &strtok_data);	showshortports(cntlr, tok);    } else if (strcmp(tok, "monitor") == 0) {	tok = strtok_r(NULL, " \t", &strtok_data);	if (tok == NULL) {	    char *err = "No monitor type given\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}	if (strcmp(tok, "stop") == 0) {	    if (cntlr->monitor_port_id != NULL) {		data_monitor_stop(cntlr, cntlr->monitor_port_id);		cntlr->monitor_port_id = NULL;	    }	} else {	    if (cntlr->monitor_port_id != NULL) {		char *err = "Already monitoring a port\n\r";		controller_output(cntlr, err, strlen(err));		goto out;	    }			    str = strtok_r(NULL, " \t", &strtok_data);	    if (str == NULL) {		char *err = "No tcp port given\n\r";		controller_output(cntlr, err, strlen(err));		goto out;	    }	    cntlr->monitor_port_id = data_monitor_start(cntlr, tok, str);	}    } else if (strcmp(tok, "disconnect") == 0) {	tok = strtok_r(NULL, " \t", &strtok_data);	if (tok == NULL) {	    char *err = "No port given\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}	disconnect_port(cntlr, tok);    } else if (strcmp(tok, "setporttimeout") == 0) {	tok = strtok_r(NULL, " \t", &strtok_data);	if (tok == NULL) {	    char *err = "No port given\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}	str = strtok_r(NULL, " \t", &strtok_data);	if (str == NULL) {	    char *err = "No timeout given\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}	setporttimeout(cntlr, tok, str);    } else if (strcmp(tok, "setportenable") == 0) {	tok = strtok_r(NULL, " \t", &strtok_data);	if (tok == NULL) {	    char *err = "No port given\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}	str = strtok_r(NULL, " \t", &strtok_data);	if (str == NULL) {	    char *err = "No timeout given\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -