From 4e2aac5e36dc411f42540c3c77a3440ce56062f4 Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Tue, 18 Apr 2000 12:00:00 -0700 Subject: [PATCH 1/1] Initial import of sersniff 0.0.3 --- HISTORY | 18 +++ LICENSE | 280 +++++++++++++++++++++++++++++++++++++++ Makefile | 15 +++ README | 124 ++++++++++++++++++ TODO | 11 ++ disp_basic.c | 95 ++++++++++++++ disp_basic.h | 41 ++++++ disp_ncurses.c | 96 ++++++++++++++ disp_ncurses.h | 41 ++++++ sersniff.c | 345 +++++++++++++++++++++++++++++++++++++++++++++++++ tcp.c | 95 ++++++++++++++ tcp.h | 14 ++ 12 files changed, 1175 insertions(+) create mode 100644 HISTORY create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README create mode 100644 TODO create mode 100644 disp_basic.c create mode 100644 disp_basic.h create mode 100644 disp_ncurses.c create mode 100644 disp_ncurses.h create mode 100644 sersniff.c create mode 100644 tcp.c create mode 100644 tcp.h diff --git a/HISTORY b/HISTORY new file mode 100644 index 0000000..7c2e15c --- /dev/null +++ b/HISTORY @@ -0,0 +1,18 @@ +0.0.1 - 10th September 1999 + +First public release. + +0.0.2 - 4th December 1999 + +* Extra error checking added (Cornelius Cook) +* Command line options added (Cornelius Cook) +* Added TCP module. +* Added silent option. +* More documentation about filtering. + +0.0.3 - 18th April 2000 + +* Look change and select code added (Cornelius Cook) +* Some socket tweaks (Cornelius Cook) +* Started breaking out display code in preparation for ncurses version. +* Added check for closed sockets. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b2852a9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,280 @@ +GNU GENERAL PUBLIC LICENSE + + Version 2, June 1991 +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + + The licenses for most software are designed to take away your freedom + to share and change it. By contrast, the GNU General Public License is + intended to guarantee your freedom to share and change free + software--to make sure the software is free for all its users. This + General Public License applies to most of the Free Software + Foundation's software and to any other program whose authors commit to + using it. (Some other Free Software Foundation software is covered by + the GNU Library General Public License instead.) You can apply it to + your programs, too. + + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get it + if you want it, that you can change the software or use pieces of it + in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the rights. + These restrictions translate to certain responsibilities for you if + you distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether + gratis or for a fee, you must give the recipients all the rights that + you have. You must make sure that they, too, receive or can get the + source code. And you must show them these terms so they know their + rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, + we want its recipients to know that what they have is not the + original, so that any problems introduced by others will not reflect + on the original authors' reputations. + + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that redistributors of a free + program will individually obtain patent licenses, in effect making the + program proprietary. To prevent this, we have made it clear that any + patent must be licensed for everyone's free use or not licensed at + all. + + The precise terms and conditions for copying, distribution and + modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", below, + refers to any such program or work, and a "work based on the Program" + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation in + the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running the Program is not restricted, and the output from the Program + is covered only if its contents constitute a work based on the Program + (independent of having been made by running the Program). Whether that + is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's source + code as you receive it, in any medium, provided that you conspicuously + and appropriately publish on each copy an appropriate copyright notice + and disclaimer of warranty; keep intact all the notices that refer to + this License and to the absence of any warranty; and give any other + recipients of the Program a copy of this License along with the + Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a + fee. + + 2. You may modify your copy or copies of the Program or any portion of + it, thus forming a work based on the Program, and copy and distribute + such modifications or work under the terms of Section 1 above, + provided that you also meet all of these conditions: + + * a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + * b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + * c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the + Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Program, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote + it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + * a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software + interchange; or, + * b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + * c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source + code means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the executable. However, as a + special exception, the source code distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of the + operating system on which the executable runs, unless that component + itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt otherwise + to copy, modify, sublicense or distribute the Program is void, and + will automatically terminate your rights under this License. However, + parties who have received copies, or rights, from you under this + License will not have their licenses terminated so long as such + parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties to + this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Program at all. For example, if a patent + license would not permit royalty-free redistribution of the Program by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License + may add an explicit geographical distribution limitation excluding + those countries, so that distribution is permitted only in or among + countries not thus excluded. In such case, this License incorporates + the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and + "any later version", you have the option of following the terms and + conditions either of that version or of any later version published by + the Free Software Foundation. If the Program does not specify a + version number of this License, you may choose any version ever + published by the Free Software Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted by the + Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. + EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR + OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE + PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME + THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY + AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU + FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE + PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING + RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A + FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF + SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7cbc07e --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +# Makefile for sersniff +# Copyright 1999 Jonathan McDowell for Project Purple + +CC = gcc +CFLAGS += -g -Wall +LINK = gcc +LINKFLAGS = -g -o + +all : sersniff + +sersniff: sersniff.o tcp.o disp_basic.o + $(LINK) $(LINKFLAGS) sersniff sersniff.o tcp.o disp_basic.o + +clean : + rm -f *~ core *.o a.out sersniff diff --git a/README b/README new file mode 100644 index 0000000..a9821be --- /dev/null +++ b/README @@ -0,0 +1,124 @@ +sersniff 0.0.3 - A program to tunnel between 2 serial ports and show +what's happening. +Copyright 1999 Jonathan McDowell for Project Purple. +http://www.earth.li/projectpurple/progs/sersniff.html + + +Introduction: + +This program was written to aid me with the decoding of the protocol +used by the Nokia 9000i Communicator to talk to the NServer software +Nokia provides, which only runs under Windows. Having hastily thrown +together the code to do what I needed it occured to me that others may +have a use for something similiar and that having a skeleton available +may help. + +(Aside: Of course, in the usual tradition of Open Source, someone got +there before. Checkout nserver from +http://users.globalnet.co.uk/~syrinx/ if your interested in the Nokia +stuff.) + +I feel that the concept could be taken a lot further, with various +filters and so on being constructed (given a framework in which to +construct them) similiar to that available with ethernet sniffers. This +could aid with the disassembly of unknown protocols over serial lines or +even for debugging serial connections. Maybe I'll write this code +someday, maybe not. Maybe someone else will and will send me a patch. :) + + +Command line options: + +sersniff [-h] [-i DEVICE | -l PORT] [-o DEVICE | -c HOST:PORT] [-b BAUD] [-s] + +-h + Displays some command line option help. + +-i IN_DEV + Set the device to use for Port1, if you're using serial ports. + Default of /dev/ttyS0 + +-l PORT + Set the port to listen on, if you want Port1 to be a TCP socket. + +-o OUT_DEV + Set the device to use for Port2, if you're using serial ports. + Default of /dev/ttyS1 + +-c HOST:PORT + Specify the host and port to connect to if Port2 is to be a TCP + socket. + +-b BAUD + Specify baud rate for serial connections. Defaults to 19200. + +-s + Make sersniff not copy data between the two ports - useful if a + Y cable is being used for serial port sniffing for example. + + +TCP/serial things: + +This program was originally written to cope with serial port data. I +have added simple support for a TCP connection both to aid with +development (it's a /lot/ easier for me to generate TCP streams than +serial streams) and also because I think a lot of the things that are +useful for monitoring a serial port data stream can also be applied to +TCP. Taking this further leads to thinking about UDP/raw ethernet - I'll +think about it once I get some filtering stuff in. + +The TCP stuff does a simple listen on a port and then connects to the +host/port specified. I see no reason why it couldn't be used to allow +telneting to a serial port or connecting from a serial port to a TCP +port, but I haven't tested this. + + +Filtering: + +This is a definite to do. For example, let's assume a regex based +scheme. We could implement the current filter as something like: + +/\x0A/ +/\x0D/ +/\x1B/ +/./ . + +(Yeah, ok, I need to think about syntax. This doesn't cover the < 32 or +> 127 range) + +But then say we learn a bit about our protocol? Let's assume VT100 for a +moment, then we might want: + +/\x0A/ +/\x0D/ +/\x1B/ +/\x1B[2J/ +/\x1B[0m/ +/\0x7/ +/./ . + +Now that's more useful, isn't it? And if it came with filters for common +serial protocols, that might be useful too? Say a VT100 one, a PPP one, +a UUCP one, well, you get the idea hopefully. + +Anyway, this is a major to do. Just needs me to get a round tuit and +think about syntax. + + +Development system: + +sersniff was originally written under Linux on a 486dx2-66. It is +currently being worked on under FreeBSD on a Cyrix P233+. + + +Contacting the author: + +I can be reached as noodles@earth.li or on Fidonet as Jonathan McDowell +@ 2:443/21 + +All constructive criticism about sersniff is welcome. + + +License: + +sersniff is distributed under the GNU Public License, a copy of which +should have been provided with this archive as LICENSE. diff --git a/TODO b/TODO new file mode 100644 index 0000000..51f3902 --- /dev/null +++ b/TODO @@ -0,0 +1,11 @@ +* Make configurable (serial port, speed, flow control etc) + Partly done by Cornelius Cook. + +* Add option to dump to file and display status on screen. + +* Nicer way to terminate program than Ctrl-C/KILLing it. + +* Lock serial ports. + +* Add filtering rules capability. + Perhaps look at some regex libraries? diff --git a/disp_basic.c b/disp_basic.c new file mode 100644 index 0000000..39f4e36 --- /dev/null +++ b/disp_basic.c @@ -0,0 +1,95 @@ +/* + disp_basic.c - Routines to do basic output with no fanciness. + Copyright 2000 Project Purple. Written by Jonathan McDowell + + 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. + http://www.gnu.org/copyleft/gpl.html + + 17/02/2000 - Started writing. +*/ + +#include + +#include "disp_basic.h" + +/* Which port did we display last? */ +static int last=-1; +/* Count of chars so far this line */ +static int wrap=WRAPINIT; + + +/* Initialise the display, ie do nothing */ +int disp_init() +{ + return 0; +} + +/* Close the display, ie do nothing */ +int disp_close() +{ + return 0; +} + +/* Output a status string about what's happening */ +void disp_outputstatus(char *string) +{ + printf("\n%s\n\t", string); + last=-1; + wrap=WRAPINIT; +} + +/* Output a string from the port. */ +void disp_outputstr(int port, char *string, + long usec_threshold, long usec_waited) +{ + if (usec_waited>usec_threshold) { + /* report how long we waited between the last port */ + if (wrap!=WRAPINIT) printf("\n"); + printf("\t\n", + usec_waited / USEC, + usec_waited % USEC); + wrap=WRAPINIT; + } + + if (last!=port) { + /* If we didn't just send a CR, we need to now */ + if (wrap!=WRAPINIT) printf("\n"); + printf("\nPort%d:\t", port); + last=port; + wrap=WRAPINIT; + } else if (wrap==WRAPINIT) { + /* We should indent since we're continuing the same port + as last time */ + printf("\t"); + } + + /* If we'd go over the line end, wrap */ + if (strlen(string)+wrap > SCREEN_WIDTH) { + wrap=WRAPINIT; + printf("\n\t"); + } + + wrap+=strlen(string); + printf("%s", string); + + if (wrap % SCREEN_WIDTH == 0) { + /* we hit the edge of the screen */ + wrap=WRAPINIT; + printf("\n"); + } + + /* flush all the time */ + fflush(NULL); +} diff --git a/disp_basic.h b/disp_basic.h new file mode 100644 index 0000000..cd6062b --- /dev/null +++ b/disp_basic.h @@ -0,0 +1,41 @@ +/* + disp_basic.h - Routines to do basic output with no fanciness. + Copyright 2000 Project Purple. Written by Jonathan McDowell + + 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. + http://www.gnu.org/copyleft/gpl.html + + 17/02/2000 - Started writing. +*/ + +/* where to start wrap counts (needs to include "PortX:\t") */ +#define WRAPINIT 9 +/* Screen width */ +#define SCREEN_WIDTH 80 +#define USEC 1000000 + +/* Initialise the display, ie do nothing */ +int disp_init(); + +/* Close the display, ie do nothing */ +int disp_close(); + +/* Output a status string about what's happening */ +void disp_outputstatus(char *string); + +/* Output a string from the port. */ +void disp_outputstr(int port, char *string, + long usec_threshold, long usec_waited); + diff --git a/disp_ncurses.c b/disp_ncurses.c new file mode 100644 index 0000000..c390ed7 --- /dev/null +++ b/disp_ncurses.c @@ -0,0 +1,96 @@ +/* + disp_ncurses.c - Routines to do pretty ncurses output. + Copyright 2000 Project Purple. Written by Jonathan McDowell + + 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. + http://www.gnu.org/copyleft/gpl.html + + 17/02/2000 - Started writing. +*/ + +#include +#include + +#include "disp_ncurses.h" + +/* Which port did we display last? */ +static int last=-1; +/* Count of chars so far this line */ +static int wrap=WRAPINIT; + + +/* Initialise the display */ +int disp_init() +{ + return 0; +} + +/* Close the display */ +int disp_close() +{ + return 0; +} + +/* Output a status string about what's happening */ +void disp_outputstatus(char *string) +{ + printf("\n%s\n\t", string); + last=-1; + wrap=WRAPINIT; +} + +/* Output a string from the port. */ +void disp_outputstr(int port, char *string, + long usec_threshold, long usec_waited) +{ + if (usec_waited>usec_threshold) { + /* report how long we waited between the last port */ + if (wrap!=WRAPINIT) printf("\n"); + printf("\t\n", + usec_waited / USEC, + usec_waited % USEC); + wrap=WRAPINIT; + } + + if (last!=port) { + /* If we didn't just send a CR, we need to now */ + if (wrap!=WRAPINIT) printf("\n"); + printf("\nPort%d:\t", port); + last=port; + wrap=WRAPINIT; + } else if (wrap==WRAPINIT) { + /* We should indent since we're continuing the same port + as last time */ + printf("\t"); + } + + /* If we'd go over the line end, wrap */ + if (strlen(string)+wrap > SCREEN_WIDTH) { + wrap=WRAPINIT; + printf("\n\t"); + } + + wrap+=strlen(string); + printf("%s", string); + + if (wrap % SCREEN_WIDTH == 0) { + /* we hit the edge of the screen */ + wrap=WRAPINIT; + printf("\n"); + } + + /* flush all the time */ + fflush(NULL); +} diff --git a/disp_ncurses.h b/disp_ncurses.h new file mode 100644 index 0000000..6580fb1 --- /dev/null +++ b/disp_ncurses.h @@ -0,0 +1,41 @@ +/* + disp_ncurses.h - Routines to do pretty ncurses output. + Copyright 2000 Project Purple. Written by Jonathan McDowell + + 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. + http://www.gnu.org/copyleft/gpl.html + + 17/02/2000 - Started writing. +*/ + +/* where to start wrap counts (needs to include "PortX:\t") */ +#define WRAPINIT 9 +/* Screen width */ +#define SCREEN_WIDTH 80 +#define USEC 1000000 + +/* Initialise the display, ie do nothing */ +int disp_init(); + +/* Close the display, ie do nothing */ +int disp_close(); + +/* Output a status string about what's happening */ +void disp_outputstatus(char *string); + +/* Output a string from the port. */ +void disp_outputstr(int port, char *string, + long usec_threshold, long usec_waited); + diff --git a/sersniff.c b/sersniff.c new file mode 100644 index 0000000..dd28d34 --- /dev/null +++ b/sersniff.c @@ -0,0 +1,345 @@ +/* + sersniff.c - A program to tunnel between 2 serial ports and + sniff the data that passes between them. Designed to aid + working out the protocol between a Nokia 9000i and NServer. + Written by Jonathan McDowell for Project Purple, 1999 + Extra stuff by Cornelius Cook (cook@cpoint.net), 1999 + + 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. + http://www.gnu.org/copyleft/gpl.html + + 07/09/1999 - Started writing. + 21Nov1999 - Cook: added command line support and extra error checking + 27Nov1999 - Cook: added select, timer & changed output look +*/ + +#define VERSION "0.0.3" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "disp_basic.h" +#include "tcp.h" + +char * speed_str[] = { "300", "1200", "2400", "4800", "9600", "19200", "38400", + "57600", "115200", "230400", NULL }; +speed_t speed_num[] = { B300, B1200, B2400, B4800, B9600, B19200, B38400, + B57600, B115200, B230400, B0 }; + +int openport(const char *device, speed_t baud) +{ + int filedes; + struct termios serparams; + + if ((filedes=open(device, O_RDWR | O_NONBLOCK))==-1) { + /* Can't open device */ + fprintf(stderr,"%s: ",device); + perror(device); + exit(1); + } + + bzero(&serparams, sizeof(serparams)); + + serparams.c_cflag=baud | CLOCAL | CS8 | CREAD; + + if (tcflush(filedes, TCIFLUSH)) { + fprintf(stderr,"%s: ",device); + perror("tcflush"); + exit(1); + } + if (tcsetattr(filedes, TCSANOW, &serparams)) { + fprintf(stderr,"%s: ",device); + perror("tcsetattr"); + exit(1); + } + + return filedes; +} + +int closeport(int filedes) +{ + /* Should remove any locks at this point */ + return close(filedes); +} + +/* + this returns the string for the character passed to it + It could be expanded in the future to maybe to string recognitions? +*/ +char *chardecide(unsigned char c, int alpha) { + static char result[256]; + + /* everyone should take up 5 characters */ + if (alpha) { + if ((c < 32) | (c > 126)) { + switch (c) { + case 10: + sprintf(result,""); + break; + case 13: + sprintf(result,""); + break; + case 27: + sprintf(result,""); + break; + default: + snprintf(result,256,"<%02hX>",c); + break; + } + } else { + snprintf(result,256,"%c",c); + } + } else { + snprintf(result,256,"0x%02hX ",c); + } + return result; +} + +void outputchar(unsigned char c, int port, int alpha, + long usec_threshold, long usec_waited) +{ + char *todisplay; + + todisplay=chardecide(c,alpha); + disp_outputstr(port, todisplay, usec_threshold, usec_waited); +} + +void mainloop(int port1, int port2, int silent, int alpha, long usec_threshold) +{ + unsigned char c1, c2; + int last; + int rc; + fd_set rfds; + fd_set efds; + int biggestfd=0; + int fdret; + struct timeval before; + struct timeval after; + long timediff; + int quit=0; + + /* need the largest fd for the select call */ + biggestfd=port1 > port2 ? port1 : port2; + biggestfd++; + last=0; + + while (!quit) { + /* reset the select set */ + FD_ZERO(&rfds); + FD_ZERO(&efds); + FD_SET(port1,&rfds); + FD_SET(port1,&efds); + FD_SET(port2,&rfds); + FD_SET(port2,&efds); + + if (gettimeofday(&before,NULL)) { + perror("gettimeofday"); + exit(1); + } + if ((fdret=select(biggestfd, &rfds, NULL, &efds, NULL))<0) { + perror("select"); + exit(1); + } + if (gettimeofday(&after,NULL)) { + perror("gettimeofday"); + exit(1); + } + + /* get seconds difference */ + timediff=after.tv_sec-before.tv_sec; + /* convert to micro seconds */ + timediff*=USEC; + /* add difference in usecs */ + timediff+=after.tv_usec-before.tv_usec; + + if (FD_ISSET(port1, &rfds)) { + for (rc=read(port1, &c1, 1); + rc>0; rc=read(port1, &c1, 1) ) { + outputchar(c1,1,alpha,usec_threshold,timediff); + timediff=0; + if (!silent) write(port2,&c1,1); + } + if (rc==0) { + /* EOF? */ + quit=1; + } + if (rc<0 && errno!=EAGAIN) { + perror("read(port1)"); + exit(1); + } + } + + if (FD_ISSET(port2, &rfds)) { + for (rc=read(port2, &c2, 1); + rc>0; rc=read(port2, &c2, 1) ) { + outputchar(c2,2,alpha,usec_threshold,timediff); + timediff=0; + if (!silent) write(port1,&c2,1); + } + if (rc==0) { + /* EOF? */ + quit=1; + } + if (rc<0 && errno!=EAGAIN) { + perror("read(port2)"); + exit(1); + } + } + + /* check for exceptions (sockets closed, broken, etc) */ + if (FD_ISSET(port1, &efds)) { + /* I can't remember right now what to actually + check for on a fd exception, so we'll just quit */ + fprintf(stderr,"\nException on port1\n"); + quit=1; + } + if (FD_ISSET(port2, &efds)) { + /* I can't remember right now what to actually + check for on a fd exception, so we'll just quit */ + fprintf(stderr,"\nException on port2\n"); + quit=1; + } + } + + closeport(port2); + closeport(port1); +} + +void usage() +{ + fprintf(stderr,"sersniff v%s + +Usage: +sersniff [-h] [-i DEV | -l PORT] [-o DEV | -c HOST:PORT] [-b BAUD] [-w USEC] +-h This help +-x Show hex characters instead of alpha +-i DEVICE Port 1 device (defaults to /dev/ttyS0) +-l PORT Port 1 port for TCP +-o DEVICE Port 2 device (defaults to /dev/ttyS1) +-c HOST:PORT Port 2 host & port to connect to +-b BAUD Baud rate (Defaults to 19200) +-w USECS How many microsecs to wait before reporting a delay + (default is %d) +-s Silent - don't pass data from port1 <=> port2, + just display what we see from them. +",VERSION,USEC); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int optret, speed; + int port1, port2; + char *dev1=NULL; + char *dev2=NULL; + int listenport=0; + int connectport; + char *connecthost=NULL, *tmpchr=NULL; + int show_alpha=1; + speed_t baud=B0; + int silent=0; + long usec_threshold=USEC; + + while ((optret=getopt(argc,argv,"hxsi:l:o:c:b:w:"))!=EOF) { + switch (optret) { + case '?': case 'h': case ':': + usage(); + case 's': + silent=1; + break; + case 'w': + usec_threshold=atoi(optarg); + break; + case 'i': + dev1=strdup(optarg); + break; + case 'o': + dev2=strdup(optarg); + break; + case 'l': + listenport=atoi(optarg); + break; + case 'c': + if ((tmpchr=strchr(optarg, ':'))==NULL) { + printf("Must specify -c option with host:port\n"); + exit(1); + } + *tmpchr='\0'; + connectport=atoi(++tmpchr); + connecthost=strdup(optarg); + break; + case 'x': + show_alpha=0; + break; + case 'b': + for (speed=0; + speed_str[speed]; + speed++) { + if (strstr(optarg,speed_str[speed])==optarg) { + baud=speed_num[speed]; + break; + } + } + if (baud==B0) { + fprintf(stderr,"Unsupported Baud: '%s'\n", + optarg); + exit(1); + } + break; + } + } + + /* Default settings */ + if (!dev1 && !listenport) dev1=strdup("/dev/ttyS0"); + if (!dev2 && !connecthost) dev2=strdup("/dev/ttyS1"); + if (baud==B0) baud=B19200; + + disp_init(); + if (dev1) { + port1=openport(dev1, baud); + } else { + disp_outputstatus("Waiting for connection to TCP port."); + port1=listensock(listenport); + } + + if (dev2) { + port2=openport(dev2, baud); + } else { + disp_outputstatus("Connecting to TCP port."); + port2=opensock(connecthost, connectport); + } + + if (port1 < 0 || port2 < 0) { + fprintf(stderr,"Argh. An open failed!\n"); + exit(1); + } + + mainloop(port1, port2, silent, show_alpha, usec_threshold); + + /* Clean up */ + if (dev1) free(dev1); + if (dev2) free(dev2); + if (connecthost) free(connecthost); + disp_close(); + + return 0; +} diff --git a/tcp.c b/tcp.c new file mode 100644 index 0000000..b8f2b67 --- /dev/null +++ b/tcp.c @@ -0,0 +1,95 @@ +/* + tcp.c - Routines to give us handles to tcp ports. + Copyright 1999 Project Purple. Written by Jonathan McDowell + + 27/11/1999 - Started writing. +*/ + +#include +#include +#include +#include +#include +#include +#include + +int opensock(char *host, int port) +{ + int sock; + struct sockaddr_in saddr; + struct hostent *hoste; + + if ((hoste=gethostbyname(host))==NULL) { + perror("gethostbyname()"); + return -1; + } + + if ((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) { + perror("socket()"); + return -1; + } + + saddr.sin_addr = *(struct in_addr *) hoste->h_addr; + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + + if ((connect(sock, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in)))==-1) { + perror("connect()"); + return -1; + } + + if (fcntl(sock, F_SETFL, O_NONBLOCK)==-1) { + perror("fcntl()"); + return -1; + } + + return sock; +} + +int listensock(int port) +{ + int sock, newsock; + struct sockaddr_in saddr; + int saddrlen; + int on; + + if ((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) { + perror("socket()"); + return -1; + } + + on=1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) { + perror("setsockopt(SO_REUSEADDR)"); + return -1; + } + + saddr.sin_addr.s_addr = INADDR_ANY; + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + saddrlen = sizeof(saddr); + + if (bind(sock, (struct sockaddr *) &saddr, saddrlen)==-1) { + perror("bind()"); + return -1; + } + + if (listen(sock, 0)==-1) { + perror("listen()"); + return -1; + } + + if ((newsock=accept(sock, (struct sockaddr *) &saddr, &saddrlen))==-1) { + perror("accept()"); + return -1; + } + + if (fcntl(newsock, F_SETFL, O_NONBLOCK)==-1) { + perror("fcntl()"); + return -1; + } + + close(sock); + + return newsock; +} diff --git a/tcp.h b/tcp.h new file mode 100644 index 0000000..378079e --- /dev/null +++ b/tcp.h @@ -0,0 +1,14 @@ +/* + tcp.h - Routines to give us handles to tcp ports. + Copyright 1999 Project Purple. Written by Jonathan McDowell + + 27/11/1999 - Started writing. +*/ + +#ifndef __TCP_H_ +#define __TCP_H_ + +int opensock(char *host, int port); +int listensock(int port); + +#endif __TCP_H_ -- 2.39.2