add in the passthrough sniffer, and start factoring out common code.
This commit is contained in:
parent
502f5eb378
commit
7f1f017295
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,8 +2,9 @@
|
|||
# Lines that start with '#' are comments.
|
||||
|
||||
# Build temp files
|
||||
*.o
|
||||
|
||||
# Executables
|
||||
serialstats
|
||||
sobredird
|
||||
|
||||
passthru
|
||||
|
|
33
Makefile
33
Makefile
|
@ -1,33 +1,13 @@
|
|||
# Makefile
|
||||
#
|
||||
#--------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2006 AbsoluteValue Systems, Inc. All Rights Reserved.
|
||||
#
|
||||
# The contents of this file are subject to the licensing terms
|
||||
# between AbsoluteValue Systems, Inc., and licensees of
|
||||
# AbsoluteValue Systems linux-wlan(tm). You may not use this file
|
||||
# except in compliance with the said License. When in doubt, do not
|
||||
# distribute the contents of this file without permission from
|
||||
# AbsoluteValue Sytems, Inc.
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# Any inquiries regarding this software may be directed to:
|
||||
#
|
||||
# AbsoluteValue Systems, Inc.
|
||||
# info@linux-wlan.com
|
||||
# http://www.linux-wlan.com
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
CPPFLAGS= -Wall
|
||||
|
||||
all: sobredird serialstats
|
||||
all: sobredird serialstats passthru
|
||||
|
||||
sobredird: redirector.o
|
||||
sobredird: redirector.o common.o
|
||||
$(CC) -o $@ $^
|
||||
|
||||
passthru: passthru.o common.o
|
||||
$(CC) -o $@ $^
|
||||
|
||||
serialstats: serialstats.o
|
||||
|
@ -40,8 +20,9 @@ install:
|
|||
mkdir -p $(PREFIX)/bin
|
||||
cp -f sobredird $(PREFIX)/bin
|
||||
cp -f serialstats $(PREFIX)/bin
|
||||
cp -f passthru $(PREFIX)/bin
|
||||
|
||||
distclean: clean
|
||||
|
||||
clean:
|
||||
rm -f core core.* *.o .*.o *.s *.a .depend tmp_make *~ sobredird serialstats
|
||||
rm -f core core.* *.o .*.o *.s *.a .depend tmp_make *~ sobredird serialstats passthru
|
||||
|
|
166
common.c
Normal file
166
common.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
Copyright (C) 2006 AbsoluteValue Systems, Inc. All Rights Reserved.
|
||||
|
||||
Originally written and maintained by: Solomon Peachy <pizza@shaftnet.org>
|
||||
Local redirection & Debugging code by: Mark Mathews <mark@linux-wlan.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
int setserial(struct termios *cfg, int ser_fd, int baud,
|
||||
int databits, char parity, int stopbits,
|
||||
int hw_flow, int sw_flow, int modemlines)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
rval = tcgetattr(ser_fd, cfg);
|
||||
if (rval) goto done;
|
||||
|
||||
cfmakeraw(cfg);
|
||||
|
||||
cfg->c_cc[VMIN] = 1; /* 1 byte minimum */
|
||||
cfg->c_cc[VTIME] = 0; /* No timeout */
|
||||
|
||||
switch(baud) {
|
||||
SERIAL_BAUD_CASE(50);
|
||||
SERIAL_BAUD_CASE(75);
|
||||
SERIAL_BAUD_CASE(110);
|
||||
SERIAL_BAUD_CASE(134);
|
||||
SERIAL_BAUD_CASE(150);
|
||||
SERIAL_BAUD_CASE(200);
|
||||
SERIAL_BAUD_CASE(300);
|
||||
SERIAL_BAUD_CASE(600);
|
||||
SERIAL_BAUD_CASE(1200);
|
||||
SERIAL_BAUD_CASE(1800);
|
||||
SERIAL_BAUD_CASE(2400);
|
||||
SERIAL_BAUD_CASE(4800);
|
||||
SERIAL_BAUD_CASE(9600);
|
||||
SERIAL_BAUD_CASE(19200);
|
||||
SERIAL_BAUD_CASE(38400);
|
||||
SERIAL_BAUD_CASE(57600);
|
||||
SERIAL_BAUD_CASE(115200);
|
||||
SERIAL_BAUD_CASE(230400);
|
||||
default:
|
||||
fprintf(stderr, "Invalid serial baud rate specified (%d)\n",
|
||||
baud);
|
||||
rval = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
parity &= ~0x20; /* make things case insensitive */
|
||||
switch (parity) {
|
||||
case 'N':
|
||||
cfg->c_cflag &= ~PARENB;
|
||||
break;
|
||||
case 'E':
|
||||
cfg->c_cflag |= PARENB;
|
||||
cfg->c_cflag &= ~PARODD;
|
||||
break;
|
||||
case 'O':
|
||||
cfg->c_cflag |= PARENB;
|
||||
cfg->c_cflag |= PARODD;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid serial parity specified (%c), should be E/O/N\n",
|
||||
parity);
|
||||
rval = 2;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cfg->c_cflag &= ~CSIZE;
|
||||
switch(databits) {
|
||||
SERIAL_DATA_CASE(5);
|
||||
SERIAL_DATA_CASE(6);
|
||||
SERIAL_DATA_CASE(7);
|
||||
SERIAL_DATA_CASE(8);
|
||||
default:
|
||||
fprintf(stderr, "Invalid number of data bits specified (%d), should be between 5 and 8.\n",
|
||||
databits);
|
||||
rval = 3;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (stopbits) {
|
||||
case 1:
|
||||
cfg->c_cflag &= ~CSTOPB;
|
||||
break;
|
||||
case 2:
|
||||
cfg->c_cflag |= CSTOPB;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid number of stop bits specified (%d), should be 1 or 2.\n",
|
||||
stopbits);
|
||||
rval = 4;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cfg->c_iflag &= ~CRTSCTS;
|
||||
cfg->c_iflag &= ~(IXON|IXOFF|IXANY);
|
||||
|
||||
if (hw_flow) {
|
||||
cfg->c_iflag |= CRTSCTS;
|
||||
}
|
||||
if (sw_flow) {
|
||||
cfg->c_iflag |= (IXON|IXOFF|IXANY);
|
||||
cfg->c_cc[VSTART] = 17;
|
||||
cfg->c_cc[VSTOP] = 19;
|
||||
}
|
||||
|
||||
if (modemlines) {
|
||||
cfg->c_cflag |= HUPCL;
|
||||
cfg->c_cflag &= ~CLOCAL;
|
||||
} else {
|
||||
cfg->c_cflag |= CLOCAL;
|
||||
cfg->c_cflag &= ~HUPCL;
|
||||
}
|
||||
|
||||
cfg->c_cflag |= CREAD;
|
||||
|
||||
cfg->c_iflag |= PARMRK;
|
||||
cfg->c_iflag &= ~(IGNPAR | BRKINT | IGNBRK);
|
||||
|
||||
rval = tcsetattr(ser_fd, TCSANOW, cfg);
|
||||
if (rval) goto done;
|
||||
|
||||
done:
|
||||
if (rval) fprintf(stderr, "ERROR.. %d\n", rval);
|
||||
|
||||
{
|
||||
struct termios cfg2;
|
||||
tcgetattr(ser_fd, &cfg2);
|
||||
if (cfg->c_iflag != cfg2.c_iflag) {
|
||||
fprintf(stderr, "ERROR! c_iflag %x vs %x\n",
|
||||
cfg->c_iflag, cfg2.c_iflag);
|
||||
}
|
||||
if (cfg->c_oflag != cfg2.c_oflag) {
|
||||
fprintf(stderr, "ERROR! c_oflag %x vs %x\n",
|
||||
cfg->c_oflag, cfg2.c_oflag);
|
||||
}
|
||||
if (cfg->c_cflag != cfg2.c_cflag) {
|
||||
fprintf(stderr, "ERROR! c_cflag %x vs %x\n",
|
||||
cfg->c_cflag, cfg2.c_cflag);
|
||||
}
|
||||
if (cfg->c_lflag != cfg2.c_lflag) {
|
||||
fprintf(stderr, "ERROR! c_lflag %x vs %x\n",
|
||||
cfg->c_lflag, cfg2.c_lflag);
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
43
common.h
Normal file
43
common.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright (C) 2006 AbsoluteValue Systems, Inc. All Rights Reserved.
|
||||
|
||||
Originally written and maintained by: Solomon Peachy <pizza@shaftnet.org>
|
||||
Local redirection & Debugging code by: Mark Mathews <mark@linux-wlan.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#define min_t(type,x,y) \
|
||||
({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
|
||||
#define max_t(type,x,y) \
|
||||
({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
|
||||
|
||||
#define SERIAL_BAUD_CASE(__b__) case __b__: cfsetispeed(cfg, B ## __b__) ; \
|
||||
cfsetospeed(cfg, B ## __b__) ; \
|
||||
break
|
||||
|
||||
#define SERIAL_DATA_CASE(__b__) case __b__: cfg->c_cflag |= CS ## __b__ ; \
|
||||
break
|
||||
|
||||
int setserial(struct termios *cfg, int ser_fd, int baud,
|
||||
int databits, char parity, int stopbits,
|
||||
int hw_flow, int sw_flow, int modemlines);
|
335
passthru.c
Normal file
335
passthru.c
Normal file
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
Copyright (C) 2006 AbsoluteValue Systems, Inc. All Rights Reserved.
|
||||
|
||||
Originally written and maintained by: Solomon Peachy <pizza@shaftnet.org>
|
||||
Local redirection & Debugging code by: Mark Mathews <mark@linux-wlan.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include "common.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
struct sob_config {
|
||||
uint32_t baud;
|
||||
uint32_t stopbits;
|
||||
uint32_t databits;
|
||||
uint8_t parity;
|
||||
uint8_t flow;
|
||||
};
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
static void dump_config(char *prefix, struct sob_config *cfg)
|
||||
{
|
||||
syslog(LOG_INFO, "%s Serial %d-%d%c%d Flow %c",
|
||||
prefix,
|
||||
cfg->baud, cfg->databits, cfg->parity, cfg->stopbits,
|
||||
cfg->flow);
|
||||
}
|
||||
|
||||
|
||||
void printhelp() {
|
||||
fprintf(stderr, " Serial to Serial forwarder and sniffer\n\n");
|
||||
fprintf(stderr, "\t-d <serialdev> -s <commsparams>\n");
|
||||
fprintf(stderr, "\t-D <serialdev> -S <commsparams>\n");
|
||||
|
||||
fprintf(stderr, "commsparams: <baud>-<databits><parity><stopbits>\n");
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static int run = 1;
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
struct sob_config sob_cfg1;
|
||||
struct sob_config sob_cfg2;
|
||||
|
||||
/* Basic communications parameters */
|
||||
|
||||
int modem_lines = 0;
|
||||
|
||||
int hw_flow = 0;
|
||||
int sw_flow = 0;
|
||||
|
||||
char *ser_dev1 = NULL;
|
||||
char *ser_dev2 = NULL;
|
||||
|
||||
int ser_fd1;
|
||||
int ser_fd2;
|
||||
|
||||
char *comm_params1 = NULL;
|
||||
char *comm_params2 = NULL;
|
||||
|
||||
struct termios ser_cfg1;
|
||||
struct termios ser_cfg2;
|
||||
|
||||
int daemonize = 0;
|
||||
|
||||
int i;
|
||||
|
||||
/* Parse command line */
|
||||
while(1) {
|
||||
int c;
|
||||
c = getopt(argc, argv, "hd:s:D:S:");
|
||||
if (c == -1) break;
|
||||
switch (c) {
|
||||
case 'h':
|
||||
printhelp();
|
||||
exit(0);
|
||||
case 'd':
|
||||
ser_dev1 = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
ser_dev2 = optarg;
|
||||
break;
|
||||
case 's':
|
||||
comm_params1 = optarg;
|
||||
break;
|
||||
case 'S':
|
||||
comm_params2 = optarg;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "getopt returned bogus option '%c'\n", c);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ser_dev1 || !ser_dev2 || !comm_params1 || !comm_params2) {
|
||||
fprintf(stderr, "ERROR: missing command-line arguments.\n\n");
|
||||
printhelp();
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Parse serial parameters #1 */
|
||||
i = sscanf(comm_params1, "%d-%d%c%d", &sob_cfg1.baud, &sob_cfg1.databits,
|
||||
&sob_cfg1.parity, &sob_cfg1.stopbits);
|
||||
if (i < 4) {
|
||||
fprintf(stderr, "Invalid commparameters (%s)\n", comm_params1);
|
||||
printhelp();
|
||||
return 6;
|
||||
}
|
||||
sob_cfg1.parity &= ~0x20; /* Case insensitive */
|
||||
|
||||
/* Parse serial parameters #2 */
|
||||
i = sscanf(comm_params2, "%d-%d%c%d", &sob_cfg2.baud, &sob_cfg2.databits,
|
||||
&sob_cfg2.parity, &sob_cfg2.stopbits);
|
||||
if (i < 4) {
|
||||
fprintf(stderr, "Invalid commparameters (%s)\n", comm_params2);
|
||||
printhelp();
|
||||
return 6;
|
||||
}
|
||||
sob_cfg2.parity &= ~0x20; /* Case insensitive */
|
||||
|
||||
/* Open serial port #1 */
|
||||
ser_fd1 = open(ser_dev1, O_RDWR|O_NONBLOCK|O_NOCTTY|O_ASYNC);
|
||||
if (ser_fd1 < 0) {
|
||||
perror("Could not open serial device #1");
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (!isatty(ser_fd1)) {
|
||||
perror("Not a TTY\n");
|
||||
return 999;
|
||||
}
|
||||
|
||||
/* Set serial Parameters #1*/
|
||||
i = setserial(&ser_cfg1, ser_fd1, sob_cfg1.baud, sob_cfg1.databits,
|
||||
sob_cfg1.parity, sob_cfg1.stopbits,
|
||||
hw_flow, sw_flow, modem_lines);
|
||||
if (i > 0) {
|
||||
printhelp();
|
||||
return 7;
|
||||
}
|
||||
|
||||
if (i < 0) {
|
||||
perror("Could not initialize serial device");
|
||||
return 8;
|
||||
}
|
||||
|
||||
/* Turn off Break #1*/
|
||||
i = ioctl(ser_fd1, TIOCCBRK);
|
||||
if (i < 0) {
|
||||
perror("Could not turn off BREAK");
|
||||
return 18;
|
||||
}
|
||||
|
||||
/* Open serial port #2 */
|
||||
ser_fd2 = open(ser_dev2, O_RDWR|O_NONBLOCK|O_NOCTTY|O_ASYNC);
|
||||
if (ser_fd2 < 0) {
|
||||
perror("Could not open serial device #2");
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (!isatty(ser_fd2)) {
|
||||
perror("Not a TTY\n");
|
||||
return 999;
|
||||
}
|
||||
|
||||
/* Set serial Parameters #2*/
|
||||
i = setserial(&ser_cfg2, ser_fd2, sob_cfg2.baud, sob_cfg2.databits,
|
||||
sob_cfg2.parity, sob_cfg2.stopbits,
|
||||
hw_flow, sw_flow, modem_lines);
|
||||
if (i > 0) {
|
||||
printhelp();
|
||||
return 7;
|
||||
}
|
||||
|
||||
if (i < 0) {
|
||||
perror("Could not initialize serial device");
|
||||
return 8;
|
||||
}
|
||||
|
||||
/* Turn off Break #2*/
|
||||
i = ioctl(ser_fd2, TIOCCBRK);
|
||||
if (i < 0) {
|
||||
perror("Could not turn off BREAK");
|
||||
return 18;
|
||||
}
|
||||
|
||||
/* Ignore sigpipes */
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (daemonize) daemon(0, 0);
|
||||
|
||||
/* And at this point, start! */
|
||||
openlog("sob", LOG_PID, LOG_DAEMON);
|
||||
|
||||
struct pollfd pfds[2];
|
||||
|
||||
/* Set up the poll */
|
||||
pfds[0].fd = ser_fd1;
|
||||
pfds[0].revents = 0;
|
||||
pfds[0].events = POLLIN|POLLPRI;
|
||||
pfds[1].fd = ser_fd2;
|
||||
pfds[1].revents = 0;
|
||||
pfds[1].events = POLLIN|POLLPRI;
|
||||
|
||||
syslog(LOG_INFO, "serialsnif bound and active");
|
||||
dump_config("Local config#1: ", &sob_cfg1);
|
||||
dump_config("Local config#2: ", &sob_cfg2);
|
||||
|
||||
#define TV_FLATTEN(__tv__) ((__tv__.tv_sec * 1000000) + __tv__.tv_usec)
|
||||
|
||||
/* Now we can run */
|
||||
while (run) {
|
||||
|
||||
pfds[0].revents = 0;
|
||||
pfds[1].revents = 0;
|
||||
|
||||
i = poll(pfds, 2, 1000);
|
||||
|
||||
/* If the poll timed out, just do it again */
|
||||
if (i == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle serial port reset */
|
||||
if (pfds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) {
|
||||
syslog(LOG_ERR, "Serial port #1 reset, purging buffers (%d)\n", pfds[0].revents);
|
||||
|
||||
tcflush(ser_fd1, TCIOFLUSH);
|
||||
|
||||
close(ser_fd1);
|
||||
ser_fd1 = open(ser_dev1,O_RDWR|O_NONBLOCK|O_NOCTTY|O_ASYNC);
|
||||
|
||||
if (ser_fd1 < 0) {
|
||||
syslog(LOG_CRIT, "Could not open serial device, terminating: %m");
|
||||
return 5;
|
||||
}
|
||||
|
||||
i = tcsetattr(ser_fd1, TCSANOW, &ser_cfg1);
|
||||
if (i < 0) {
|
||||
syslog(LOG_CRIT, "Could not initialize serial device: %m");
|
||||
}
|
||||
pfds[1].fd = ser_fd1;
|
||||
continue;
|
||||
}
|
||||
if (pfds[1].revents & (POLLERR|POLLHUP|POLLNVAL)) {
|
||||
syslog(LOG_ERR, "Serial port #2 reset, purging buffers (%d)\n", pfds[1].revents);
|
||||
|
||||
tcflush(ser_fd2, TCIOFLUSH);
|
||||
|
||||
close(ser_fd2);
|
||||
ser_fd2 = open(ser_dev1,O_RDWR|O_NONBLOCK|O_NOCTTY|O_ASYNC);
|
||||
|
||||
if (ser_fd2 < 0) {
|
||||
syslog(LOG_CRIT, "Could not open serial device, terminating: %m");
|
||||
return 5;
|
||||
}
|
||||
|
||||
i = tcsetattr(ser_fd2, TCSANOW, &ser_cfg2);
|
||||
if (i < 0) {
|
||||
syslog(LOG_CRIT, "Could not initialize serial device: %m");
|
||||
}
|
||||
pfds[1].fd = ser_fd2;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle the serial port IN */
|
||||
if (pfds[0].revents & (POLLIN|POLLPRI)) {
|
||||
uint8_t c;
|
||||
|
||||
while ((i = read(ser_fd1, &c, sizeof(c))) > 0) {
|
||||
char buf[20];
|
||||
write(ser_fd2, &c, sizeof(c));
|
||||
// write(fileno(stdout), "1> ", 3);
|
||||
sprintf(buf, "1> 0x%02x \n", c);
|
||||
write(fileno(stdout), buf, strlen(buf));
|
||||
// write(fileno(stdout), &c, sizeof(c));
|
||||
// write(fileno(stdout), "\n", 1);
|
||||
}
|
||||
}
|
||||
if (pfds[1].revents & (POLLIN|POLLPRI)) {
|
||||
uint8_t c;
|
||||
|
||||
while ((i = read(ser_fd2, &c, sizeof(c))) > 0) {
|
||||
write(ser_fd1, &c, sizeof(c));
|
||||
// write(fileno(stdout), "2> ", 3);
|
||||
write(fileno(stdout), &c, sizeof(c));
|
||||
// write(fileno(stdout), "\n", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
syslog(LOG_INFO, "sobredird shutting down");
|
||||
|
||||
tcflush(ser_fd1, TCIOFLUSH);
|
||||
tcflush(ser_fd2, TCIOFLUSH);
|
||||
close(ser_fd1);
|
||||
close(ser_fd2);
|
||||
|
||||
closelog();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
228
redirector.c
228
redirector.c
|
@ -1,32 +1,24 @@
|
|||
/*
|
||||
*--------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2006 AbsoluteValue Systems, Inc. All Rights Reserved.
|
||||
*
|
||||
* The contents of this file are subject to the licensing terms
|
||||
* between AbsoluteValue Systems, Inc., and licensees of
|
||||
* AbsoluteValue Systems linux-wlan(tm). You may not use this file
|
||||
* except in compliance with the said License. When in doubt, do not
|
||||
* distribute the contents of this file without permission from
|
||||
* AbsoluteValue Sytems, Inc.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* Any inquiries regarding this software may be directed to:
|
||||
*
|
||||
* AbsoluteValue Systems, Inc.
|
||||
* info@linux-wlan.com
|
||||
* http://www.linux-wlan.com
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
Copyright (C) 2006 AbsoluteValue Systems, Inc. All Rights Reserved.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
Originally written and maintained by: Solomon Peachy <pizza@shaftnet.org>
|
||||
Local redirection & Debugging code by: Mark Mathews <mark@linux-wlan.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -43,13 +35,13 @@
|
|||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
|
||||
/* Basic over-the-wire serial packet */
|
||||
|
||||
struct s_msg {
|
||||
|
@ -82,21 +74,9 @@ struct sob_config {
|
|||
#define SERIAL_ESC_CHAR2 0x00
|
||||
#define SERIAL_ESC_BREAK 0x00
|
||||
|
||||
#define min_t(type,x,y) \
|
||||
({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
|
||||
#define max_t(type,x,y) \
|
||||
({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
|
||||
|
||||
#define MAX_PACKET_LEN 1470
|
||||
#define BUF_LEN 4096
|
||||
|
||||
#define SERIAL_BAUD_CASE(__b__) case __b__: cfsetispeed(cfg, B ## __b__) ; \
|
||||
cfsetospeed(cfg, B ## __b__) ; \
|
||||
break
|
||||
|
||||
#define SERIAL_DATA_CASE(__b__) case __b__: cfg->c_cflag |= CS ## __b__ ; \
|
||||
break
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
static void dump_config(char *prefix, struct sob_config *cfg)
|
||||
|
@ -157,148 +137,6 @@ static void send_config(int far_sock, struct sob_config *far_cfg,
|
|||
}
|
||||
}
|
||||
|
||||
int setserial(struct termios *cfg, int ser_fd, int baud,
|
||||
int databits, char parity, int stopbits,
|
||||
int hw_flow, int sw_flow, int modemlines)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
rval = tcgetattr(ser_fd, cfg);
|
||||
if (rval) goto done;
|
||||
|
||||
cfmakeraw(cfg);
|
||||
|
||||
cfg->c_cc[VMIN] = 1; /* 1 byte minimum */
|
||||
cfg->c_cc[VTIME] = 0; /* No timeout */
|
||||
|
||||
switch(baud) {
|
||||
SERIAL_BAUD_CASE(50);
|
||||
SERIAL_BAUD_CASE(75);
|
||||
SERIAL_BAUD_CASE(110);
|
||||
SERIAL_BAUD_CASE(134);
|
||||
SERIAL_BAUD_CASE(150);
|
||||
SERIAL_BAUD_CASE(200);
|
||||
SERIAL_BAUD_CASE(300);
|
||||
SERIAL_BAUD_CASE(600);
|
||||
SERIAL_BAUD_CASE(1200);
|
||||
SERIAL_BAUD_CASE(1800);
|
||||
SERIAL_BAUD_CASE(2400);
|
||||
SERIAL_BAUD_CASE(4800);
|
||||
SERIAL_BAUD_CASE(9600);
|
||||
SERIAL_BAUD_CASE(19200);
|
||||
SERIAL_BAUD_CASE(38400);
|
||||
SERIAL_BAUD_CASE(57600);
|
||||
SERIAL_BAUD_CASE(115200);
|
||||
// SERIAL_BAUD_CASE(230400);
|
||||
default:
|
||||
fprintf(stderr, "Invalid serial baud rate specified (%d)\n",
|
||||
baud);
|
||||
rval = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
parity &= ~0x20; /* make things case insensitive */
|
||||
switch (parity) {
|
||||
case 'N':
|
||||
cfg->c_cflag &= ~PARENB;
|
||||
break;
|
||||
case 'E':
|
||||
cfg->c_cflag |= PARENB;
|
||||
cfg->c_cflag &= ~PARODD;
|
||||
break;
|
||||
case 'O':
|
||||
cfg->c_cflag |= PARENB;
|
||||
cfg->c_cflag |= PARODD;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid serial parity specified (%c), should be E/O/N\n",
|
||||
parity);
|
||||
rval = 2;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cfg->c_cflag &= ~CSIZE;
|
||||
switch(databits) {
|
||||
SERIAL_DATA_CASE(5);
|
||||
SERIAL_DATA_CASE(6);
|
||||
SERIAL_DATA_CASE(7);
|
||||
SERIAL_DATA_CASE(8);
|
||||
default:
|
||||
fprintf(stderr, "Invalid number of data bits specified (%d), should be between 5 and 8.\n",
|
||||
databits);
|
||||
rval = 3;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (stopbits) {
|
||||
case 1:
|
||||
cfg->c_cflag &= ~CSTOPB;
|
||||
break;
|
||||
case 2:
|
||||
cfg->c_cflag |= CSTOPB;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid number of stop bits specified (%d), should be 1 or 2.\n",
|
||||
stopbits);
|
||||
rval = 4;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cfg->c_iflag &= ~CRTSCTS;
|
||||
cfg->c_iflag &= ~(IXON|IXOFF|IXANY);
|
||||
|
||||
if (hw_flow) {
|
||||
cfg->c_iflag |= CRTSCTS;
|
||||
}
|
||||
if (sw_flow) {
|
||||
cfg->c_iflag |= (IXON|IXOFF|IXANY);
|
||||
cfg->c_cc[VSTART] = 17;
|
||||
cfg->c_cc[VSTOP] = 19;
|
||||
}
|
||||
|
||||
if (modemlines) {
|
||||
cfg->c_cflag |= HUPCL;
|
||||
cfg->c_cflag &= ~CLOCAL;
|
||||
} else {
|
||||
cfg->c_cflag |= CLOCAL;
|
||||
cfg->c_cflag &= ~HUPCL;
|
||||
}
|
||||
|
||||
cfg->c_cflag |= CREAD;
|
||||
|
||||
cfg->c_iflag |= PARMRK;
|
||||
cfg->c_iflag &= ~(IGNPAR | BRKINT | IGNBRK);
|
||||
|
||||
rval = tcsetattr(ser_fd, TCSANOW, cfg);
|
||||
if (rval) goto done;
|
||||
|
||||
done:
|
||||
if (rval) fprintf(stderr, "ERROR.. %d\n", rval);
|
||||
|
||||
{
|
||||
struct termios cfg2;
|
||||
tcgetattr(ser_fd, &cfg2);
|
||||
if (cfg->c_iflag != cfg2.c_iflag) {
|
||||
fprintf(stderr, "ERROR! c_iflag %x vs %x\n",
|
||||
cfg->c_iflag, cfg2.c_iflag);
|
||||
}
|
||||
if (cfg->c_oflag != cfg2.c_oflag) {
|
||||
fprintf(stderr, "ERROR! c_oflag %x vs %x\n",
|
||||
cfg->c_oflag, cfg2.c_oflag);
|
||||
}
|
||||
if (cfg->c_cflag != cfg2.c_cflag) {
|
||||
fprintf(stderr, "ERROR! c_cflag %x vs %x\n",
|
||||
cfg->c_cflag, cfg2.c_cflag);
|
||||
}
|
||||
if (cfg->c_lflag != cfg2.c_lflag) {
|
||||
fprintf(stderr, "ERROR! c_lflag %x vs %x\n",
|
||||
cfg->c_lflag, cfg2.c_lflag);
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
void printhelp() {
|
||||
fprintf(stderr, " Serial Over Broadband Redirector\n (c) AbsoluteValue Systems 2006\n\n");
|
||||
fprintf(stderr, "\t-d <serialdev> -s <commsparams> -i <farhost> -p <farport>\n");
|
||||
|
@ -607,7 +445,7 @@ int main (int argc, char **argv)
|
|||
pfds[1].revents = 0;
|
||||
pfds[1].events = POLLIN|POLLPRI;
|
||||
|
||||
syslog(LOG_INFO, "sobredird WIP3 bound and active");
|
||||
syslog(LOG_INFO, "sobredird bound and active");
|
||||
dump_config("Local config: ", &sob_cfg);
|
||||
|
||||
send_config(far_sock, &sob_cfg, &far_addr);
|
||||
|
@ -649,30 +487,6 @@ int main (int argc, char **argv)
|
|||
|
||||
i = poll(pfds, 2, min_t(int64_t, delta1, delta2) / 1000);
|
||||
|
||||
#if 0
|
||||
{
|
||||
fd_set rfds;
|
||||
fd_set wfds;
|
||||
int v = 0, j = 0;
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
for (j = 0; j < 2 ; j++) {
|
||||
FD_SET(pfds[j].fd, &rfds);
|
||||
FD_SET(pfds[j].fd, &wfds);
|
||||
if (pfds[j].fd > v)
|
||||
v = pfds[j].fd;
|
||||
}
|
||||
v = select(v+1, &rfds, &wfds, NULL, NULL);
|
||||
for (j = 0; j < 2 ; j++) {
|
||||
if (FD_ISSET(pfds[j].fd, &rfds))
|
||||
fprintf(stderr, "rfd %d %d set\n", j, pfds[i].fd);
|
||||
if (FD_ISSET(pfds[j].fd, &wfds))
|
||||
fprintf(stderr, "wfd %d %d set\n", j, pfds[i].fd);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
{
|
||||
// XXX this lets us get serial line twiddles:
|
||||
|
|
|
@ -1,3 +1,24 @@
|
|||
/*
|
||||
Copyright (C) 2006 AbsoluteValue Systems, Inc. All Rights Reserved.
|
||||
|
||||
Originally written and maintained by: Solomon Peachy <pizza@shaftnet.org>
|
||||
Local redirection & Debugging code by: Mark Mathews <mark@linux-wlan.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
|
Loading…
Reference in a new issue