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

📄 dataxfer.c

📁 This project provides a proxy that allows telnet/tcp connections to be made to serial ports on a mac
💻 C
📖 第 1 页 / 共 4 页
字号:
	    /* EINTR means we were interrupted, just retry by returning. */	    return;	}	if (errno == EAGAIN) {	    /* This was due to O_NONBLOCK, we need to shut off the reader	       and start the writer monitor. */	    sel_set_fd_read_handler(ser2net_sel, port->tcpfd,				    SEL_FD_HANDLER_DISABLED);	    sel_set_fd_write_handler(ser2net_sel, port->devfd,				     SEL_FD_HANDLER_ENABLED);	    port->tcp_to_dev_state = PORT_WAITING_OUTPUT_CLEAR;	} else {	    /* Some other bad error. */	    syslog(LOG_ERR, "The dev write for port %s had error: %m",		   port->portname);	    shutdown_port(port, "dev write error");	}    } else {	port->dev_bytes_sent += write_count;	port->tcp_to_dev_buf_count -= write_count;	if (port->tcp_to_dev_buf_count != 0) {	    /* We didn't write all the data, shut off the reader and               start the write monitor. */	    port->tcp_to_dev_buf_start += write_count;	    sel_set_fd_read_handler(ser2net_sel, port->tcpfd,				    SEL_FD_HANDLER_DISABLED);	    sel_set_fd_write_handler(ser2net_sel, port->devfd,				     SEL_FD_HANDLER_ENABLED);	    port->tcp_to_dev_state = PORT_WAITING_OUTPUT_CLEAR;	}    }    reset_timer(port);}/* The TCP port has room to write some data.  This is only activated   if a write fails to complete, it is deactivated as soon as writing   is available again. */static voidhandle_tcp_fd_write(int fd, void *data){    port_info_t *port = (port_info_t *) data;    telnet_data_t *td = &port->tn_data;    int write_count;    if (td->out_telnet_cmd_size > 0) {	write_count = write(port->tcpfd,			    &(td->out_telnet_cmd[0]),			    td->out_telnet_cmd_size);	if (write_count == -1) {	    if (errno == EINTR) {		/* EINTR means we were interrupted, just retry by returning. */		return;	    }	    if (errno == EAGAIN) {		/* This again was due to O_NONBLOCK, just ignore it. */	    } else if (errno == EPIPE) {		shutdown_port(port, "EPIPE");	    } else {		/* Some other bad error. */		syslog(LOG_ERR, "The tcp write for port %s had error: %m",		       port->portname);		shutdown_port(port, "tcp write error");	    }	} else {	    int i, j;	    /* Copy the remaining data. */	    for (j=0, i=write_count; i<td->out_telnet_cmd_size; i++, j++)		td->out_telnet_cmd[j] = td->out_telnet_cmd[i];	    td->out_telnet_cmd_size -= write_count;	    if (td->out_telnet_cmd_size != 0)		/* If we have more telnet command data to send, don't		   send any real data. */		return;	}    }    write_count = write(port->tcpfd,			&(port->dev_to_tcp_buf[port->dev_to_tcp_buf_start]),			port->dev_to_tcp_buf_count);    if (write_count == -1) {	if (errno == EINTR) {	    /* EINTR means we were interrupted, just retry by returning. */	    return;	}	if (errno == EAGAIN) {	    /* This again was due to O_NONBLOCK, just ignore it. */	} else if (errno == EPIPE) {	    shutdown_port(port, "EPIPE");	} else {	    /* Some other bad error. */	    syslog(LOG_ERR, "The tcp write for port %s had error: %m",		   port->portname);	    shutdown_port(port, "tcp write error");	}    } else {	port->tcp_bytes_sent += write_count;	port->dev_to_tcp_buf_count -= write_count;	if (port->dev_to_tcp_buf_count != 0) {	    /* We didn't write all the data, continue writing. */	    port->dev_to_tcp_buf_start += write_count;	} else {	    /* We are done writing, turn the reader back on. */	    sel_set_fd_read_handler(ser2net_sel, port->devfd,				    SEL_FD_HANDLER_ENABLED);	    sel_set_fd_write_handler(ser2net_sel, port->tcpfd,				     SEL_FD_HANDLER_DISABLED);	    port->dev_to_tcp_state = PORT_WAITING_INPUT;	}    }    reset_timer(port);}/* Handle an exception from the TCP port. */static voidhandle_tcp_fd_except(int fd, void *data){    port_info_t *port = (port_info_t *) data;    syslog(LOG_ERR, "Select exception on port %s", port->portname);    shutdown_port(port, "tcp fd exception");}static voidtelnet_cmd_handler(void *cb_data, unsigned char cmd){    port_info_t *port = cb_data;    if (cmd == TN_BREAK)	tcsendbreak(port->devfd, 0);}/* Called when the telnet code has output ready. */static voidtelnet_output_ready(void *cb_data){    port_info_t *port = cb_data;    sel_set_fd_read_handler(ser2net_sel, port->devfd,			    SEL_FD_HANDLER_DISABLED);    sel_set_fd_write_handler(ser2net_sel, port->tcpfd,			     SEL_FD_HANDLER_ENABLED);}/* Checks to see if some other port has the same device in use. */static intis_device_already_inuse(port_info_t *check_port){    port_info_t *port = ports;    while (port != NULL) {	if (port != check_port) {	    if ((strcmp(port->devname, check_port->devname) == 0) 		&& (port->tcp_to_dev_state != PORT_UNCONNECTED))	    {		return 1;	    }	}    	port = port->next;    }    return 0;}static voidadd_port_tcp_char(port_info_t *port, char c){    int pos = port->dev_to_tcp_buf_start + port->dev_to_tcp_buf_count;    if (pos >= PORT_BUFSIZE)	return;    port->dev_to_tcp_buf[pos] = c;    port->dev_to_tcp_buf_count++;}static intfrom_hex_digit(char c){    if ((c >= '0') && (c <= '9'))	return c - '0';    if ((c >= 'A') && (c <= 'F'))	return c = 'A' + 10;    if ((c >= 'a') && (c <= 'f'))	return c = 'a' + 10;    return 0;}static voiddisplay_banner(port_info_t *port){    char val;    char *s;    char *t;    if (!port->banner)	return;    s = port->banner;    while (*s) {	if (*s == '\\') {	    s++;	    if (!*s)		return;	    switch (*s) {	    /* Standard "C" characters. */	    case 'a': add_port_tcp_char(port, 7); break;	    case 'b': add_port_tcp_char(port, 8); break;	    case 'f': add_port_tcp_char(port, 12); break;	    case 'n': add_port_tcp_char(port, 10); break;	    case 'r': add_port_tcp_char(port, 13); break;	    case 't': add_port_tcp_char(port, 9); break;	    case 'v': add_port_tcp_char(port, 11); break;	    case '\\': add_port_tcp_char(port, '\\'); break;	    case '?': add_port_tcp_char(port, '?'); break;	    case '\'': add_port_tcp_char(port, '\''); break;	    case '"': add_port_tcp_char(port, '"'); break;	    case 'd':		/* ser2net device name. */		for (t=port->devname; *t; t++)		    add_port_tcp_char(port, *t);		break;	    case 'p':		/* ser2net TCP port. */		for (t=port->portname; *t; t++)		    add_port_tcp_char(port, *t);		break;	    case '0': case '1': case '2': case '3': case '4': case '5':	    case '6': case '7':		/* Octal digit */		val = (*s) - '0';		s++;		if (!*s) {		    add_port_tcp_char(port, val);		    return;		}		if (!isdigit(*s)) {		    continue;		}		val = (val * 8) + (*s) - '0';		s++;		if (!*s) {		    add_port_tcp_char(port, val);		    return;		}		if (!isdigit(*s)) {		    continue;		}		val = (val * 8) + (*s) - '0';		break;	    case 'x':		/* Hex digit */		s++;		if (!*s)		    return;		if (!isxdigit(*s))		    continue;		val = from_hex_digit(*s);		s++;		if (!*s) {		    add_port_tcp_char(port, val);		    return;		}		if (!isdigit(*s))		    continue;		val = (val * 16) + from_hex_digit(*s);		break;	    default:		add_port_tcp_char(port, *s);	    }	} else	    add_port_tcp_char(port, *s);	s++;    }}/* A connection request has come in on a port. */static voidhandle_accept_port_read(int fd, void *data){    port_info_t *port = (port_info_t *) data;    socklen_t len;    char *err = NULL;    int options;    struct timeval then;    if (port->tcp_to_dev_state != PORT_UNCONNECTED) {	err = "Port already in use\n\r";    } else if (is_device_already_inuse(port)) {	err = "Port's device already in use\n\r";    }    if (err != NULL) {	struct sockaddr_in dummy_sockaddr;	socklen_t len = sizeof(dummy_sockaddr);	int new_fd = accept(fd, (struct sockaddr *) &dummy_sockaddr, &len);	if (new_fd != -1) {	    write(new_fd, err, strlen(err));	    close(new_fd);	}	return;    }    len = sizeof(port->remote);    port->tcpfd = accept(fd, (struct sockaddr *) &(port->remote), &len);    if (port->tcpfd == -1) {	syslog(LOG_ERR, "Could not accept on port %s: %m", port->portname);	return;    }    if (fcntl(port->tcpfd, F_SETFL, O_NONBLOCK) == -1) {	close(port->tcpfd);	syslog(LOG_ERR, "Could not fcntl the tcp port %s: %m", port->portname);	return;    }#ifdef HAVE_TCPD_H    {	struct request_info req;		request_init(&req, RQ_DAEMON, progname, RQ_FILE, port->tcpfd, NULL);	fromhost(&req);	if (!hosts_access(&req)) {	    char *err = "Access denied\n\r";	    write(port->tcpfd, err, strlen(err));	    close(port->tcpfd);	    return;	}    }#endif /* HAVE_TCPD_H */#ifdef USE_UUCP_LOCKING    {	int rv;	rv = uucp_mk_lock(port->devname);	if (rv > 0 ) {	    char *err;	    err = "Port already in use by another process\n\r";	    write(port->tcpfd, err, strlen(err));	    close(port->tcpfd);	    return;	} else if (rv < 0) {	    char *err;	    err = "Error creating port lock file\n\r";	    write(port->tcpfd, err, strlen(err));	    close(port->tcpfd);	    return;	}    }#endif /* USE_UUCP_LOCKING */    /* Oct 05 2001 druzus: NOCTTY - don't make        device control tty for our process */    options = O_NONBLOCK | O_NOCTTY;    if (port->enabled == PORT_RAWLP) {	options |= O_WRONLY;    } else {	options |= O_RDWR;    }    port->devfd = open(port->devname, options);    if (port->devfd == -1) {	close(port->tcpfd);	syslog(LOG_ERR, "Could not open device %s for port %s: %m",	       port->devname,	       port->portname);	return;    }    if (port->enabled != PORT_RAWLP &&              tcsetattr(port->devfd, TCSANOW, &(port->termctl)) == -1) {	close(port->tcpfd);	close(port->devfd);	syslog(LOG_ERR, "Could not set up device %s for port %s: %m",	       port->devname,	       port->portname);	return;    }    /* Turn of BREAK. */    if (ioctl(port->devfd, TIOCCBRK) == -1) {	close(port->tcpfd);	close(port->devfd);	syslog(LOG_ERR, "Could not turn off break for device %s port %s: %m",	       port->devname,	       port->portname);	return;    }    port->is_2217 = 0;    port->break_set = 0;    sel_set_fd_handlers(ser2net_sel,			port->devfd,			port,			port->enabled == PORT_RAWLP			? NULL			: handle_dev_fd_read,			handle_dev_fd_write,			handle_dev_fd_except);    sel_set_fd_read_handler(ser2net_sel,			    port->devfd,			    ((port->enabled == PORT_RAWLP)			     ? SEL_FD_HANDLER_DISABLED			     : SEL_FD_HANDLER_ENABLED));    sel_set_fd_except_handler(ser2net_sel, port->devfd,			      SEL_FD_HANDLER_ENABLED);    port->dev_to_tcp_state = PORT_WAITING_INPUT;    sel_set_fd_handlers(ser2net_sel,			port->tcpfd,			port,			handle_tcp_fd_read,			handle_tcp_fd_write,			handle_tcp_fd_except);    sel_set_fd_read_handler(ser2net_sel, port->tcpfd,			    SEL_FD_HANDLER_ENABLED);    sel_set_fd_except_handler(ser2net_sel, port->tcpfd,			      SEL_FD_HANDLER_ENABLED);    port->tcp_to_dev_state = PORT_WAITING_INPUT;    if (port->enabled == PORT_TELNET) {	telnet_init(&port->tn_data, port, telnet_output_ready,		    telnet_cmd_handler,		    telnet_cmds,		    telnet_init_seq, sizeof(telnet_init_seq));    } else {	sel_set_fd_read_handler(ser2net_sel, port->devfd,				SEL_FD_HANDLER_ENABLED);    }    display_banner(port);    gettimeofday(&then, NULL);    then.tv_sec += 1;    sel_start_timer(port->timer, &then);    reset_timer(port);}/* Start monitoring for connections on a specific port. */static char *startup_port(port_info_t *port){    int optval = 1;        port->acceptfd = socket(PF_INET, SOCK_STREAM, 0);    if (port->acceptfd == -1) {	return "Unable to create TCP socket";    }    if (fcntl(port->acceptfd, F_SETFL, O_NONBLOCK) == -1) {	close(port->acceptfd);	return "Could not fcntl the accept port";    }    if (setsockopt(port->acceptfd,		   SOL_SOCKET,		   SO_REUSEADDR,		   (void *)&optval,		   sizeof(optval)) == -1) {	close(port->acceptfd);	return "Unable to set reuseaddress on socket";    }    if (bind(port->acceptfd,	     (struct sockaddr *) &port->tcpport,	     sizeof(port->tcpport)) == -1) {	close(port->acceptfd);	return "Unable to bind TCP port";    }    if (listen(port->acceptfd, 1) != 0) {	close(port->acceptfd);	return "Unable to listen to TCP port";    }    sel_set_fd_handlers(ser2net_sel,			port->acceptfd,			port,			handle_accept_port_read,			NULL,			NULL);    sel_set_fd_read_handler(ser2net_sel, port->acceptfd,			    SEL_FD_HANDLER_ENABLED);    return NULL;}char *change_port_state(port_info_t *port, int state){    char *rv = NULL;    if (port->enabled == state) {	return rv;    }    if (state == PORT_DISABLED) {	if (port->acceptfd != -1) {	    sel_set_fd_read_handler(ser2net_sel,				    port->acceptfd,				    SEL_FD_HANDLER_DISABLED);	    sel_clear_fd_handlers(ser2net_sel, port->acceptfd);	    close(port->acceptfd);	    port->acceptfd = -1;	}    } else if (port->enabled == PORT_DISABLED) {	rv = startup_port(port);    }    port->enabled = state;    return rv;}static voidfree_port(port_info_t *port){    sel_free_timer(port->timer);    change_port_state(port, PORT_DISABLED);    if (port->portname != NULL) {	free(port->portname);    }    if (port->devname != NULL) {	free(port->devname);    }    if (port->new_config != NULL) {	free_port(port->new_config);    }    free(port);}static voidshutdown_port(port_info_t *port, char *reason){    sel_stop_timer(port->timer);    sel_clear_fd_handlers(ser2net_sel, port->devfd);    sel_clear_fd_handlers(ser2net_sel, port->tcpfd);    close(port->tcpfd);    /* To avoid blocking on close if we have written bytes and are in       flow-control, we flush the output queue. */    tcflush(port->devfd, TCOFLUSH);    close(port->devfd);#ifdef USE_UUCP_LOCKING    uucp_rm_lock(port->devname);#endif /* USE_UUCP_LOCKING */    port->tcp_to_dev_state = PORT_UNCONNECTED;    port->tcp_to_dev_buf_start = 0;    port->tcp_to_dev_buf_count = 0;    port->tcp_bytes_received = 0;    port->tcp_bytes_sent = 0;    port->dev_to_tcp_state = PORT_UNCONNECTED;    port->dev_to_tcp_buf_start = 0;    port->dev_to_tcp_buf_count = 0;    port->dev_bytes_received = 0;    port->dev_bytes_sent = 0;    /* If the port has been disabled, then delete it.  Check this before       the new config so the port will be deleted properly and not       reconfigured on a reconfig. */    if (port->config_num == -1) {

⌨️ 快捷键说明

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