tcpser/0040755000076400010400000000000010747540171013244 5ustar brainAdministratorstcpser/.cdtproject0100644000076400010400000000277310562020167015405 0ustar brainAdministrators make -f Makefile.win32 all false false tcpser/.cproject0100644000076400010400000000365710742356416015070 0ustar brainAdministrators make -f Makefile.win32 all false false tcpser/.project0100644000076400010400000000674310562022335014712 0ustar brainAdministrators tcpser org.eclipse.cdt.make.core.makeBuilder org.eclipse.cdt.core.errorOutputParser org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser; org.eclipse.cdt.make.core.fullBuildTarget clean all org.eclipse.cdt.make.core.incrementalBuildTarget all org.eclipse.cdt.make.core.buildLocation org.eclipse.cdt.make.core.enableAutoBuild false org.eclipse.cdt.make.core.enableFullBuild true org.eclipse.cdt.make.core.enabledIncrementalBuild true org.eclipse.cdt.make.core.enableCleanBuild true org.eclipse.cdt.make.core.cleanBuildTarget clean org.eclipse.cdt.make.core.useDefaultBuildCmd false org.eclipse.cdt.make.core.buildArguments -f Makefile.win32 org.eclipse.cdt.make.core.buildCommand make org.eclipse.cdt.make.core.autoBuildTarget all org.eclipse.cdt.make.core.stopOnError false org.eclipse.cdt.make.core.ScannerConfigBuilder org.eclipse.cdt.make.core.ScannerConfigDiscoveryEnabled true org.eclipse.cdt.make.core.makeBuilderParserId org.eclipse.cdt.make.core.GCCScannerInfoConsoleParser org.eclipse.cdt.make.core.esiProviderCommandEnabled true org.eclipse.cdt.make.core.siProblemGenerationEnabled true org.eclipse.cdt.make.core.useDefaultESIProviderCmd true org.eclipse.cdt.make.core.makeBuilderParserEnabled true org.eclipse.cdt.make.core.esiProviderParserId org.eclipse.cdt.make.core.GCCSpecsConsoleParser org.eclipse.cdt.core.cnature org.eclipse.cdt.make.core.makeNature org.eclipse.cdt.make.core.ScannerConfigNature tcpser/.settings/0040755000076400010400000000000010574105513015155 5ustar brainAdministratorstcpser/.settings/.svn/0040755000076400010400000000000010574105513016041 5ustar brainAdministratorstcpser/.settings/.svn/all-wcprops0100444000076400010400000000032410562022502020212 0ustar brainAdministratorsK 25 svn:wc:ra_dav:version-url V 38 /svn/tcpser/!svn/ver/4/trunk/.settings END org.eclipse.cdt.core.prefs K 25 svn:wc:ra_dav:version-url V 65 /svn/tcpser/!svn/ver/4/trunk/.settings/org.eclipse.cdt.core.prefs END tcpser/.settings/.svn/entries0100444000076400010400000000055210562022502017423 0ustar brainAdministrators8 dir 5 http://www.jimbrain.com/svn/tcpser/trunk/.settings http://www.jimbrain.com/svn/tcpser 2007-02-06T06:43:32.577387Z 4 brain svn:special svn:externals svn:needs-lock 8602611e-c928-0410-ae49-afcc62ab246b org.eclipse.cdt.core.prefs file 2007-02-06T06:50:41.680046Z 3f613fdb51fe217b12933b9b3b900bc7 2007-02-06T06:43:32.577387Z 4 brain tcpser/.settings/.svn/format0100444000076400010400000000000210562022502017230 0ustar brainAdministrators8 tcpser/.settings/.svn/prop-base/0040755000076400010400000000000010574105513017731 5ustar brainAdministratorstcpser/.settings/.svn/props/0040755000076400010400000000000010574105513017204 5ustar brainAdministratorstcpser/.settings/.svn/text-base/0040755000076400010400000000000010574105513017735 5ustar brainAdministratorstcpser/.settings/.svn/text-base/org.eclipse.cdt.core.prefs.svn-base0100444000076400010400000000015210562022502026407 0ustar brainAdministrators#Sun Feb 04 01:47:17 CST 2007 eclipse.preferences.version=1 indexerId=org.eclipse.cdt.core.fastIndexer tcpser/.settings/.svn/tmp/0040755000076400010400000000000010574105513016641 5ustar brainAdministratorstcpser/.settings/.svn/tmp/prop-base/0040755000076400010400000000000010574105513020531 5ustar brainAdministratorstcpser/.settings/.svn/tmp/props/0040755000076400010400000000000010574105513020004 5ustar brainAdministratorstcpser/.settings/.svn/tmp/text-base/0040755000076400010400000000000010574105513020535 5ustar brainAdministratorstcpser/.settings/org.eclipse.cdt.core.prefs0100644000076400010400000000023610742356416022135 0ustar brainAdministrators#Sun Jan 13 03:42:38 CST 2008 eclipse.preferences.version=1 indexer/indexerId=org.eclipse.cdt.core.fastIndexer indexerId=org.eclipse.cdt.core.fastIndexer tcpser/.svn/0040755000076400010400000000000010747537570014141 5ustar brainAdministratorstcpser/.svn/all-wcprops0100444000076400010400000000130710562025525016306 0ustar brainAdministratorsK 25 svn:wc:ra_dav:version-url V 28 /svn/tcpser/!svn/ver/4/trunk END .cdtproject K 25 svn:wc:ra_dav:version-url V 40 /svn/tcpser/!svn/ver/4/trunk/.cdtproject END .project K 25 svn:wc:ra_dav:version-url V 37 /svn/tcpser/!svn/ver/6/trunk/.project END Makefile.solaris K 25 svn:wc:ra_dav:version-url V 46 /svn/tcpser/!svn/ver/24/trunk/Makefile.solaris END CHANGES K 25 svn:wc:ra_dav:version-url V 37 /svn/tcpser/!svn/ver/24/trunk/CHANGES END Makefile K 25 svn:wc:ra_dav:version-url V 38 /svn/tcpser/!svn/ver/24/trunk/Makefile END README K 25 svn:wc:ra_dav:version-url V 36 /svn/tcpser/!svn/ver/24/trunk/README END Makefile.win32 K 25 svn:wc:ra_dav:version-url V 44 /svn/tcpser/!svn/ver/24/trunk/Makefile.win32 END tcpser/.svn/entries0100444000076400010400000000210410747537570015525 0ustar brainAdministrators8 dir 5 http://www.jimbrain.com/svn/tcpser/trunk http://www.jimbrain.com/svn/tcpser 2007-02-06T06:43:32.577387Z 4 brain svn:special svn:externals svn:needs-lock 8602611e-c928-0410-ae49-afcc62ab246b .cdtproject file 2007-02-06T06:50:41.770176Z 091a4507f45b56fb0126d5d2c49ec9ac 2007-02-06T06:43:32.577387Z 4 brain .project file 6 2007-02-06T06:49:01.495988Z dc563887f0068cbc319519aa5b312691 2007-02-06T07:04:10.627566Z 6 brain src dir Makefile.solaris file 24 2006-06-15T08:40:42.000000Z a3c8e2e5702eb2062874a4adb6d21c96 2007-02-06T07:26:33.108543Z 24 brain CHANGES file 25 2008-01-29T05:53:50.866548Z 49dc9550b8aa72765108b6f1a61408e8 2007-02-06T07:26:33.108543Z 24 brain Makefile file 24 2006-06-15T08:41:04.000000Z 640e4f08da77487652f701e0ba4384ad 2007-02-06T07:26:33.108543Z 24 brain README file 25 2008-01-29T05:53:59.508976Z 384433c2157e77175f88ac27576adab8 2007-02-06T07:26:33.108543Z 24 brain .settings dir Makefile.win32 file 24 2006-06-14T05:06:06.000000Z 6c03531002942eeb55bd3d9b5cf67312 2007-02-06T07:26:33.108543Z 24 brain tcpser/.svn/format0100444000076400010400000000000210562022500015310 0ustar brainAdministrators8 tcpser/.svn/prop-base/0040755000076400010400000000000010574105513016013 5ustar brainAdministratorstcpser/.svn/props/0040755000076400010400000000000010574105513015266 5ustar brainAdministratorstcpser/.svn/text-base/0040755000076400010400000000000010574105513016017 5ustar brainAdministratorstcpser/.svn/text-base/.cdtproject.svn-base0100444000076400010400000000277310562022500021671 0ustar brainAdministrators make -f Makefile.win32 all false false tcpser/.svn/text-base/.project.svn-base0100444000076400010400000000674310562022335021205 0ustar brainAdministrators tcpser org.eclipse.cdt.make.core.makeBuilder org.eclipse.cdt.core.errorOutputParser org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser; org.eclipse.cdt.make.core.fullBuildTarget clean all org.eclipse.cdt.make.core.incrementalBuildTarget all org.eclipse.cdt.make.core.buildLocation org.eclipse.cdt.make.core.enableAutoBuild false org.eclipse.cdt.make.core.enableFullBuild true org.eclipse.cdt.make.core.enabledIncrementalBuild true org.eclipse.cdt.make.core.enableCleanBuild true org.eclipse.cdt.make.core.cleanBuildTarget clean org.eclipse.cdt.make.core.useDefaultBuildCmd false org.eclipse.cdt.make.core.buildArguments -f Makefile.win32 org.eclipse.cdt.make.core.buildCommand make org.eclipse.cdt.make.core.autoBuildTarget all org.eclipse.cdt.make.core.stopOnError false org.eclipse.cdt.make.core.ScannerConfigBuilder org.eclipse.cdt.make.core.ScannerConfigDiscoveryEnabled true org.eclipse.cdt.make.core.makeBuilderParserId org.eclipse.cdt.make.core.GCCScannerInfoConsoleParser org.eclipse.cdt.make.core.esiProviderCommandEnabled true org.eclipse.cdt.make.core.siProblemGenerationEnabled true org.eclipse.cdt.make.core.useDefaultESIProviderCmd true org.eclipse.cdt.make.core.makeBuilderParserEnabled true org.eclipse.cdt.make.core.esiProviderParserId org.eclipse.cdt.make.core.GCCSpecsConsoleParser org.eclipse.cdt.core.cnature org.eclipse.cdt.make.core.makeNature org.eclipse.cdt.make.core.ScannerConfigNature tcpser/.svn/text-base/CHANGES.svn-base0100444000076400010400000000273610445277232020537 0ustar brainAdministrators1.0 Initial release 1.0rc2 Cleaned up code 10.rc3 changed char fields to unsigned char Changed many functions to return status Added macros for __FUNCTION__ keyword, for compiler sanity Added include headers needed for other UNIX platforms 1.0rc4 Changed cfg->connection to cfg->conn_type Added support for send file text to connections on actions If data received while off-hook and no conn, go on-hook. Clean up parseRegister action in getcmd.c Add support for ':' and '-' extended commands Cleaned up functions to only exit at one point 1.0rc5 Moved includes to be in correct order Fixed Q0 and Q1 (they were reversed) 1.0rc6 Add support for direct connection 1.0rc7 Fixed mislocated tcsetattr in serial.com:ser_init_conn 1.0rc8 Fixed bug in ip_thread (calling a null number would turn on ip_thread, but no connection, generating a dump Fixed bugs in dce_set_flow_control Fixed behavior of parms parsing for &Z (complex) and S (simple) Defaulted code to not assume /dev/ttyS0 as serport 1.0rc9 Fixed bug that would stop first session if second call came in Fixed outbound call not bringing DCD high. 1.0rc10 Added some more debugging information Changed logging to go to stdout from stderr Fixed Phone book matching function to use logger 1.0rc11 Added ip232 support with custom protocol for use with matching modified version of WinVICE 1.19 Added full support for Telnet Binary Transmission (RFC 856) tcpser/.svn/text-base/Makefile.solaris.svn-base0100444000076400010400000000157610444216412022650 0ustar brainAdministratorsSRC=src SRCS = $(SRC)/bridge.c $(SRC)/debug.c $(SRC)/getcmd.c $(SRC)/ip.c $(SRC)/init.c $(SRC)/modem_core.c $(SRC)/nvt.c $(SRC)/serial.c $(SRC)/ip232.c $(SRC)/util.c $(SRC)/phone_book.c $(SRC)/shared.c $(SRC)/tcpser.c $(SRC)/line.c $(SRC)/dce.c OBJS = $(SRC)/bridge.o $(SRC)/debug.o $(SRC)/getcmd.o $(SRC)/ip.o $(SRC)/init.o $(SRC)/modem_core.o $(SRC)/nvt.o $(SRC)/serial.o $(SRC)/ip232.o $(SRC)/util.o $(SRC)/phone_book.o $(SRC)/shared.o $(SRC)/tcpser.o $(SRC)/dce.o $(SRC)/line.o CC = gcc DEF = CFLAGS = -O $(DEF) -Wall LDFLAGS = -lpthread -lsocket -lnsl -lresolv DEPEND = makedepend $(DEF) $(CFLAGS) all: tcpser #.o.c: # $(CC) $(CFLAGS) -c $*.c $(SRCS): $(CC) $(CFLAGS) -c $*.c tcpser: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) depend: $(SRCS) $(DEPEND) $(SRCS) clean: -rm tcpser *.bak $(SRC)/*~ $(SRC)/*.o $(SRC)/*.bak core # DO NOT DELETE THIS LINE -- make depend depends on it. tcpser/.svn/text-base/Makefile.svn-base0100444000076400010400000000160410444216440021166 0ustar brainAdministratorsSRC=src SRCS = $(SRC)/bridge.c $(SRC)/debug.c $(SRC)/getcmd.c $(SRC)/ip.c $(SRC)/init.c $(SRC)/modem_core.c $(SRC)/nvt.c $(SRC)/serial.c $(SRC)/ip232.c $(SRC)/util.c $(SRC)/phone_book.c $(SRC)/shared.c $(SRC)/tcpser.c $(SRC)/line.c $(SRC)/dce.c OBJS = $(SRC)/bridge.o $(SRC)/debug.o $(SRC)/getcmd.o $(SRC)/ip.o $(SRC)/init.o $(SRC)/modem_core.o $(SRC)/nvt.o $(SRC)/serial.o $(SRC)/ip232.o $(SRC)/util.o $(SRC)/phone_book.o $(SRC)/shared.o $(SRC)/tcpser.o $(SRC)/dce.o $(SRC)/line.o CC = gcc DEF = CFLAGS = -O $(DEF) -Wall LDFLAGS = -lpthread DEPEND = makedepend $(DEF) $(CFLAGS) all: tcpser #.o.c: # $(CC) $(CFLAGS) -c $*.c $(SRCS): $(CC) $(CFLAGS) -c $*.c tcpser: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) depend: $(SRCS) $(DEPEND) $(SRCS) clean: -rm tcpser *.bak $(SRC)/*~ $(SRC)/*.o $(SRC)/*.bak core # DO NOT DELETE THIS LINE -- make depend depends on it. tcpser/.svn/text-base/Makefile.win32.svn-base0100444000076400010400000000160710443714476022145 0ustar brainAdministratorsSRC=src SRCS = $(SRC)/bridge.c $(SRC)/debug.c $(SRC)/getcmd.c $(SRC)/ip.c $(SRC)/init.c $(SRC)/modem_core.c $(SRC)/nvt.c $(SRC)/serial.c $(SRC)/ip232.c $(SRC)/util.c $(SRC)/phone_book.c $(SRC)/shared.c $(SRC)/tcpser.c $(SRC)/line.c $(SRC)/dce.c OBJS = $(SRC)/bridge.o $(SRC)/debug.o $(SRC)/getcmd.o $(SRC)/ip.o $(SRC)/init.o $(SRC)/modem_core.o $(SRC)/nvt.o $(SRC)/serial.o $(SRC)/ip232.o $(SRC)/util.o $(SRC)/phone_book.o $(SRC)/shared.o $(SRC)/tcpser.o $(SRC)/dce.o $(SRC)/line.o CC = gcc DEF = CFLAGS = -O $(DEF) -Wall -DWIN32 LDFLAGS = DEPEND = makedepend $(DEF) $(CFLAGS) all: tcpser #.o.c: # $(CC) $(CFLAGS) -c $*.c $(SRCS): $(CC) $(CFLAGS) -c $*.c tcpser: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) depend: $(SRCS) $(DEPEND) $(SRCS) clean: -rm tcpser.exe *.bak $(SRC)/*~ $(SRC)/*.o $(SRC)/*.bak core # DO NOT DELETE THIS LINE -- make depend depends on it. tcpser/.svn/text-base/README.svn-base0100444000076400010400000001565610445277620020432 0ustar brainAdministrators README Application: TCPSER turns a PC serial port into an emulated Hayes compatible modem that uses TCP/IP for incoming and outgoing connections. It can be used to allow older applications and systems designed for modem use to operate on the Internet. TCPSER supports all standard Hayes commands, and understands extended and vendor proprietary commands (though it does not implement many of them). TCPSER can be used for both inbound and outbound connections. License: TCPSER is distributed under the GPL 2.0 or later Executable/Building: UNIX/Linux/BSD: Simply untar the archive into a directory, and use the appropriate make command generate the exectutable. If unsure, try the default make command first. Default/Linux: make Solaris: make -f Makefile.solaris *BSD: gmake Windows 95/OSR2/98/SE/ME/NT/2000/XP/2003: The application archive contains a pregenerated Windows 32 bit executable (tcpser.exe). No compilation should be required, though the GNU toolchain and the CYGWIN POSIX libraries can be used to regenerate the executable if desired: Win32: make -f Makefile.win32 Note that at least the cygwin1.dll library is required to operate tcpser under Windows. I recommend downloading a recent version from www.cygwin.com This version of tcpser supports setting up an ip232 port instead of using a real serial port. This is for use with the version of WinVICE 1.19 that has the ACIA fix and ip232 support, allowing WinVICE to use tcpser as if it was connected via a serial cable. Operation: tcpser -d -s -l -t ... -or- tcpser -v -s -l -t ... samples: tcpser -d /dev/ttyS0 -s 38400 -l 7 -tsSiI -i "s0=1" -p 6400 Will start tcpser on ttyS0 at 38400 bps, level 7 logging, tracing of inbound serial, outbound serial, inbound IP, outbound IP, init modem to answer after 1 ring, and listen for incoming connections on port 6400 tcpser -v 25232 -s 38400 -l 4 -p 23 Will set up an ip232 port at 25232, report 38400 bps connections, level 4 logging, and listen for incoming connections on port 23. tcpser -h will provide additional information tcpser can be configured to send the contents of a file upon: connect ; -c -C answer ; -a -A no-answer ; -I busy ; -B inactivity-timeout ; -T For connect and answer, there are separate options for sending a file to the local serial connection (-c, -a) and the remote IP connection (-C, -A). If tcpser connects to a telnet service, tcpser will negotiate the connection using the telnet protocol. If telnet is detected, then tcpser will support RFC 856 (Telnet Binary Transmission), so that 8-bit file transfers will work correctly. tcpser can be configured to support multiple serial/ip232 ports on one TCP/IP port. Simply repeat the -s and -d/-v parameters on the command line for each serial/ip232 port to be configured. Options s,S,a,A,c,C,I, and T will "propagate" to subsequent connections, unless they are redefined. Defaults for s and S are 38400. This configuration enables the operation of a multi-line BBS on one TCP/IP port. Frequently used addresses can be configured in the "phonebook", like so: tcpser .... -nhome=jbrain.com:6400 This is also useful for systems that do not accept non-numeric phone numbers: tcpser .... -n5551212=bestbbs.net One can even "hide" a regular IP address or DNS entry by aliasing it to something else: tcpser .... -njbrain.com=bestbbs.com At this point, phonebook support is very alpha, so use with care. Emulation: All of the standard Hayes commands should behave as expected. Some of of the proprietary commands are not implemented, but should not cause errors. Examples: ats0=1 ; set number of rings to answer ata ; answer the line ath0 ; hang up ats12? ; query S register 12 ate0 ; turn off echo at&k3 ; set flow control to RTS/CTS atdtjbrain.com:6400 ; "dial" jbrain.com, port 6400 (defaults to port 23) atdl ; "dial" last number a/ ; repeat last command Commands can be chained, as on a regular modem: ats0=1z&c1&k3%f0s3=13dtjbrain.com tcpser supports the Hayes break sequence semantics, so +++ should operate correctly, even if the sequence of characters is used in normal data transmissions.i Cable: tcpser can be used with a regular null modem cable, but it utilizes the DTR line on the PC serial port to reflect the state of the DCD line as seen by the target system. On a normal null-modem cable, DTR is mapped to DCD/DSR, which implies DSR will also reflect the state of DCD on the target machine. However, some systems (notably those utilizing the 6551 ACIA communication IC) will not transmit unless DSR is held high. In this case, a quick qorkaround is to force DCD to be held high by adding -i"&c0" to the tcpser parameter list. However, this also prevents normal operation of the DCD line, which is needed by some BBS systems. A more permanent solution is to construct a modified null-modem cable or modify an existing cable to the following specifications: PC Target CTS-----RTS RTS-----CTS SND-----RCV RCV-----SND DTR-----DCD DCD-+-+-DTR | | DSR-+ +-DSR GND-----GND This differs from a regular null-modem cable in that the target machine has DSR looped to DTR, not to DCD. Note that this cable is directional. Normally, the target machine will configure DSR to float to a high state if unconnected. As well, PCs do not require a valid DSR line for operation. Thus, a simpler cable can be constructed that is bi-directional: CTS-----RTS RTS-----CTS SND-----RCV RCV-----SND DTR-----DCD DCD-----DTR GND-----GND Unless there are issues, we recommend this simplified version, as it can be installed in either direction. As an even simpler solution, many have simply taken a normal rs232 DE-9F to DE-9M cable and removed pin 6 from the male end (DSR). This is fine, but the cable must be installed between the null modem adapter and the target machine: PC ----- null-modem adapter ----- cable with pin 6 removed ------ target machine Any other configuration will not work correctly. Platform notes: Win32 users should use /dev/ttyS0-3 for COM1-4. At present, using "com1:" does not operate correctly. This has been tested on the following platforms: Linux 2.4.20-8 Windows XP Windows XP SP1 Slackware 10.0 Help: tcpser has a small but active user community. Help can be found by asking a question in comp.sys.cbm, on the NEWNet #c64friends IRC channel, or by emailing the author. ----------------------------------- Jim Brain brain@jbrain.com www.jbrain.com The ip232 support was added by Anthony Tolle. For questions regarding that, e-mail atolle@gcns.com tcpser/.svn/tmp/0040755000076400010400000000000010747537570014741 5ustar brainAdministratorstcpser/.svn/tmp/prop-base/0040755000076400010400000000000010574105512016612 5ustar brainAdministratorstcpser/.svn/tmp/props/0040755000076400010400000000000010574105512016065 5ustar brainAdministratorstcpser/.svn/tmp/text-base/0040755000076400010400000000000010574105512016616 5ustar brainAdministratorstcpser/bridge0100644000076400010400000000013110314630070014377 0ustar brainAdministratorstcpser-1.0rc10/tcpser -d /dev/ttyS1 -s 1200 -i"e0" -tsS -n"5551212=ltshosting.net:5190" tcpser/CHANGES0100644000076400010400000000310610747533047014240 0ustar brainAdministrators1.0 Initial release 1.0rc2 Cleaned up code 10.rc3 changed char fields to unsigned char Changed many functions to return status Added macros for __FUNCTION__ keyword, for compiler sanity Added include headers needed for other UNIX platforms 1.0rc4 Changed cfg->connection to cfg->conn_type Added support for send file text to connections on actions If data received while off-hook and no conn, go on-hook. Clean up parseRegister action in getcmd.c Add support for ':' and '-' extended commands Cleaned up functions to only exit at one point 1.0rc5 Moved includes to be in correct order Fixed Q0 and Q1 (they were reversed) 1.0rc6 Add support for direct connection 1.0rc7 Fixed mislocated tcsetattr in serial.com:ser_init_conn 1.0rc8 Fixed bug in ip_thread (calling a null number would turn on ip_thread, but no connection, generating a dump Fixed bugs in dce_set_flow_control Fixed behavior of parms parsing for &Z (complex) and S (simple) Defaulted code to not assume /dev/ttyS0 as serport 1.0rc9 Fixed bug that would stop first session if second call came in Fixed outbound call not bringing DCD high. 1.0rc10 Added some more debugging information Changed logging to go to stdout from stderr Fixed Phone book matching function to use logger 1.0rc11 Added ip232 support with custom protocol for use with matching modified version of WinVICE 1.19 Added full support for Telnet Binary Transmission (RFC 856) 1.0rc12 Added code to hook SIG_IO to SIG_IGN. Newer versions of Linux are terminating when IO arrives. tcpser/Makefile0100644000076400010400000000160410444216440014673 0ustar brainAdministratorsSRC=src SRCS = $(SRC)/bridge.c $(SRC)/debug.c $(SRC)/getcmd.c $(SRC)/ip.c $(SRC)/init.c $(SRC)/modem_core.c $(SRC)/nvt.c $(SRC)/serial.c $(SRC)/ip232.c $(SRC)/util.c $(SRC)/phone_book.c $(SRC)/shared.c $(SRC)/tcpser.c $(SRC)/line.c $(SRC)/dce.c OBJS = $(SRC)/bridge.o $(SRC)/debug.o $(SRC)/getcmd.o $(SRC)/ip.o $(SRC)/init.o $(SRC)/modem_core.o $(SRC)/nvt.o $(SRC)/serial.o $(SRC)/ip232.o $(SRC)/util.o $(SRC)/phone_book.o $(SRC)/shared.o $(SRC)/tcpser.o $(SRC)/dce.o $(SRC)/line.o CC = gcc DEF = CFLAGS = -O $(DEF) -Wall LDFLAGS = -lpthread DEPEND = makedepend $(DEF) $(CFLAGS) all: tcpser #.o.c: # $(CC) $(CFLAGS) -c $*.c $(SRCS): $(CC) $(CFLAGS) -c $*.c tcpser: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) depend: $(SRCS) $(DEPEND) $(SRCS) clean: -rm tcpser *.bak $(SRC)/*~ $(SRC)/*.o $(SRC)/*.bak core # DO NOT DELETE THIS LINE -- make depend depends on it. tcpser/Makefile.solaris0100644000076400010400000000157610444216412016355 0ustar brainAdministratorsSRC=src SRCS = $(SRC)/bridge.c $(SRC)/debug.c $(SRC)/getcmd.c $(SRC)/ip.c $(SRC)/init.c $(SRC)/modem_core.c $(SRC)/nvt.c $(SRC)/serial.c $(SRC)/ip232.c $(SRC)/util.c $(SRC)/phone_book.c $(SRC)/shared.c $(SRC)/tcpser.c $(SRC)/line.c $(SRC)/dce.c OBJS = $(SRC)/bridge.o $(SRC)/debug.o $(SRC)/getcmd.o $(SRC)/ip.o $(SRC)/init.o $(SRC)/modem_core.o $(SRC)/nvt.o $(SRC)/serial.o $(SRC)/ip232.o $(SRC)/util.o $(SRC)/phone_book.o $(SRC)/shared.o $(SRC)/tcpser.o $(SRC)/dce.o $(SRC)/line.o CC = gcc DEF = CFLAGS = -O $(DEF) -Wall LDFLAGS = -lpthread -lsocket -lnsl -lresolv DEPEND = makedepend $(DEF) $(CFLAGS) all: tcpser #.o.c: # $(CC) $(CFLAGS) -c $*.c $(SRCS): $(CC) $(CFLAGS) -c $*.c tcpser: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) depend: $(SRCS) $(DEPEND) $(SRCS) clean: -rm tcpser *.bak $(SRC)/*~ $(SRC)/*.o $(SRC)/*.bak core # DO NOT DELETE THIS LINE -- make depend depends on it. tcpser/Makefile.win320100644000076400010400000000160710443714476015652 0ustar brainAdministratorsSRC=src SRCS = $(SRC)/bridge.c $(SRC)/debug.c $(SRC)/getcmd.c $(SRC)/ip.c $(SRC)/init.c $(SRC)/modem_core.c $(SRC)/nvt.c $(SRC)/serial.c $(SRC)/ip232.c $(SRC)/util.c $(SRC)/phone_book.c $(SRC)/shared.c $(SRC)/tcpser.c $(SRC)/line.c $(SRC)/dce.c OBJS = $(SRC)/bridge.o $(SRC)/debug.o $(SRC)/getcmd.o $(SRC)/ip.o $(SRC)/init.o $(SRC)/modem_core.o $(SRC)/nvt.o $(SRC)/serial.o $(SRC)/ip232.o $(SRC)/util.o $(SRC)/phone_book.o $(SRC)/shared.o $(SRC)/tcpser.o $(SRC)/dce.o $(SRC)/line.o CC = gcc DEF = CFLAGS = -O $(DEF) -Wall -DWIN32 LDFLAGS = DEPEND = makedepend $(DEF) $(CFLAGS) all: tcpser #.o.c: # $(CC) $(CFLAGS) -c $*.c $(SRCS): $(CC) $(CFLAGS) -c $*.c tcpser: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) depend: $(SRCS) $(DEPEND) $(SRCS) clean: -rm tcpser.exe *.bak $(SRC)/*~ $(SRC)/*.o $(SRC)/*.bak core # DO NOT DELETE THIS LINE -- make depend depends on it. tcpser/README0100644000076400010400000001664010747532642014134 0ustar brainAdministrators README Application: TCPSER turns a PC serial port into an emulated Hayes compatible modem that uses TCP/IP for incoming and outgoing connections. It can be used to allow older applications and systems designed for modem use to operate on the Internet. TCPSER supports all standard Hayes commands, and understands extended and vendor proprietary commands (though it does not implement many of them). TCPSER can be used for both inbound and outbound connections. License: TCPSER is distributed under the GPL 2.0 or later Executable/Building: UNIX/Linux/BSD: Simply untar the archive into a directory, and use the appropriate make command generate the exectutable. If unsure, try the default make command first. Default/Linux: make Solaris: make -f Makefile.solaris *BSD: gmake Windows 95/OSR2/98/SE/ME/NT/2000/XP/2003: The application archive contains a pregenerated Windows 32 bit executable (tcpser.exe). No compilation should be required, though the GNU toolchain and the CYGWIN POSIX libraries can be used to regenerate the executable if desired: Win32: make -f Makefile.win32 Note that at least the cygwin1.dll library is required to operate tcpser under Windows. I recommend downloading a recent version from www.cygwin.com This version of tcpser supports setting up an ip232 port instead of using a real serial port. This is for use with the version of WinVICE 1.19 that has the ACIA fix and ip232 support, allowing WinVICE to use tcpser as if it was connected via a serial cable. Operation: tcpser -d -s -l -t ... -or- tcpser -v -s -l -t ... samples: tcpser -d /dev/ttyS0 -s 38400 -l 7 -tsSiI -i "s0=1" -p 6400 Will start tcpser on ttyS0 at 38400 bps, level 7 logging, tracing of inbound serial, outbound serial, inbound IP, outbound IP, init modem to answer after 1 ring, and listen for incoming connections on port 6400 tcpser -v 25232 -s 38400 -l 4 -p 23 Will set up an ip232 port at 25232, report 38400 bps connections, level 4 logging, and listen for incoming connections on port 23. tcpser -h will provide additional information tcpser can be configured to send the contents of a file upon: connect ; -c -C answer ; -a -A no-answer ; -I busy ; -B inactivity-timeout ; -T For connect and answer, there are separate options for sending a file to the local serial connection (-c, -a) and the remote IP connection (-C, -A). If tcpser connects to a telnet service, tcpser will negotiate the connection using the telnet protocol. If telnet is detected, then tcpser will support RFC 856 (Telnet Binary Transmission), so that 8-bit file transfers will work correctly. tcpser can be configured to support multiple serial/ip232 ports on one TCP/IP port. Simply repeat the -s and -d/-v parameters on the command line for each serial/ip232 port to be configured. Options s,S,a,A,c,C,I, and T will "propagate" to subsequent connections, unless they are redefined. Defaults for s and S are 38400. This configuration enables the operation of a multi-line BBS on one TCP/IP port. Frequently used addresses can be configured in the "phonebook", like so: tcpser .... -nhome=jbrain.com:6400 This is also useful for systems that do not accept non-numeric phone numbers: tcpser .... -n5551212=bestbbs.net One can even "hide" a regular IP address or DNS entry by aliasing it to something else: tcpser .... -njbrain.com=bestbbs.com At this point, phonebook support is very alpha, so use with care. Emulation: All of the standard Hayes commands should behave as expected. Some of of the proprietary commands are not implemented, but should not cause errors. Examples: ats0=1 ; set number of rings to answer ata ; answer the line ath0 ; hang up ats12? ; query S register 12 ate0 ; turn off echo at&k3 ; set flow control to RTS/CTS atdtjbrain.com:6400 ; "dial" jbrain.com, port 6400 (defaults to port 23) atdl ; "dial" last number a/ ; repeat last command Commands can be chained, as on a regular modem: ats0=1z&c1&k3%f0s3=13dtjbrain.com tcpser supports the Hayes break sequence semantics, so +++ should operate correctly, even if the sequence of characters is used in normal data transmissions.i Cable: tcpser can be used with a regular null modem cable, but it utilizes the DTR line on the PC serial port to reflect the state of the DCD line as seen by the target system. On a normal null-modem cable, DTR is mapped to DCD/DSR, which implies DSR will also reflect the state of DCD on the target machine. However, some systems (notably those utilizing the 6551 ACIA communication IC) will not transmit unless DSR is held high. In this case, a quick qorkaround is to force DCD to be held high by adding -i"&c0" to the tcpser parameter list. However, this also prevents normal operation of the DCD line, which is needed by some BBS systems. A more permanent solution is to construct a modified null-modem cable or modify an existing cable to the following specifications: PC Target CTS-----RTS RTS-----CTS SND-----RCV RCV-----SND DTR-----DCD DCD-+-+-DTR | | DSR-+ +-DSR GND-----GND This differs from a regular null-modem cable in that the target machine has DSR looped to DTR, not to DCD. Note that this cable is directional. Normally, the target machine will configure DSR to float to a high state if unconnected. As well, PCs do not require a valid DSR line for operation. Thus, a simpler cable can be constructed that is bi-directional: CTS-----RTS RTS-----CTS SND-----RCV RCV-----SND DTR-----DCD DCD-----DTR GND-----GND Unless there are issues, we recommend this simplified version, as it can be installed in either direction. As an even simpler solution, many have simply taken a normal rs232 DE-9F to DE-9M cable and removed pin 6 from the male end (DSR). This is fine, but the cable must be installed between the null modem adapter and the target machine: PC ----- null-modem adapter ----- cable with pin 6 removed ------ target machine Any other configuration will not work correctly. Platform notes: Win32 users should use /dev/ttyS0-3 for COM1-4. At present, using "com1:" does not operate correctly. Raymond Day sends the following Ubuntu 7.10 autorun scripts: In: /etc/init.d/ Make a file named something like tcpser with this code in it: #!/bin/sh # Start tcpser at 1200 boud on both RS232 ports for Q-Link Reloaded. case "$1" in 'start') tcpser -d /dev/ttyS0 -s 1200 -i"e0&k0&c0" -n"5551212"=66.135.39.36:5190& tcpser -d /dev/ttyS1 -p 6401 -s 1200 -i"e0&k0&c0" -n"5551212"=66.135.39.36:5190& ;; 'stop') ;; *) echo "Usage: $0 { start | stop }" ;; esac exit 0 This has been tested on the following platforms: Linux 2.4.20-8 Windows XP Windows XP SP1 Slackware 10.0 Help: tcpser has a small but active user community. Help can be found by asking a question in comp.sys.cbm, on the NEWNet #c64friends IRC channel, or by emailing the author. ----------------------------------- Jim Brain brain@jbrain.com www.jbrain.com The ip232 support was added by Anthony Tolle. For questions regarding that, e-mail atolle@gcns.com tcpser/src/0040755000076400010400000000000010747540205014031 5ustar brainAdministratorstcpser/src/.svn/0040755000076400010400000000000010747537547014734 5ustar brainAdministratorstcpser/src/.svn/all-wcprops0100444000076400010400000000564010562025525017101 0ustar brainAdministratorsK 25 svn:wc:ra_dav:version-url V 32 /svn/tcpser/!svn/ver/4/trunk/src END tcpser.c K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/20/trunk/src/tcpser.c END bridge.h K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/10/trunk/src/bridge.h END init.c K 25 svn:wc:ra_dav:version-url V 40 /svn/tcpser/!svn/ver/24/trunk/src/init.c END getcmd.c K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/22/trunk/src/getcmd.c END tcpser.h K 25 svn:wc:ra_dav:version-url V 41 /svn/tcpser/!svn/ver/6/trunk/src/tcpser.h END ip.c K 25 svn:wc:ra_dav:version-url V 38 /svn/tcpser/!svn/ver/12/trunk/src/ip.c END init.h K 25 svn:wc:ra_dav:version-url V 40 /svn/tcpser/!svn/ver/10/trunk/src/init.h END getcmd.h K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/10/trunk/src/getcmd.h END modem_core.c K 25 svn:wc:ra_dav:version-url V 46 /svn/tcpser/!svn/ver/20/trunk/src/modem_core.c END util.c K 25 svn:wc:ra_dav:version-url V 40 /svn/tcpser/!svn/ver/10/trunk/src/util.c END ip.h K 25 svn:wc:ra_dav:version-url V 38 /svn/tcpser/!svn/ver/10/trunk/src/ip.h END modem_core.h K 25 svn:wc:ra_dav:version-url V 46 /svn/tcpser/!svn/ver/24/trunk/src/modem_core.h END serial.c K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/22/trunk/src/serial.c END util.h K 25 svn:wc:ra_dav:version-url V 40 /svn/tcpser/!svn/ver/10/trunk/src/util.h END phone_book.c K 25 svn:wc:ra_dav:version-url V 46 /svn/tcpser/!svn/ver/22/trunk/src/phone_book.c END tcpmdm.c K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/10/trunk/src/tcpmdm.c END serial.h K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/10/trunk/src/serial.h END debug.c K 25 svn:wc:ra_dav:version-url V 41 /svn/tcpser/!svn/ver/22/trunk/src/debug.c END phone_book.h K 25 svn:wc:ra_dav:version-url V 46 /svn/tcpser/!svn/ver/10/trunk/src/phone_book.h END tcpmdm.h K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/10/trunk/src/tcpmdm.h END dce.c K 25 svn:wc:ra_dav:version-url V 39 /svn/tcpser/!svn/ver/24/trunk/src/dce.c END debug.h K 25 svn:wc:ra_dav:version-url V 41 /svn/tcpser/!svn/ver/10/trunk/src/debug.h END ip232.c K 25 svn:wc:ra_dav:version-url V 41 /svn/tcpser/!svn/ver/24/trunk/src/ip232.c END dce.h K 25 svn:wc:ra_dav:version-url V 39 /svn/tcpser/!svn/ver/10/trunk/src/dce.h END ip232.h K 25 svn:wc:ra_dav:version-url V 41 /svn/tcpser/!svn/ver/24/trunk/src/ip232.h END shared.c K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/14/trunk/src/shared.c END nvt.c K 25 svn:wc:ra_dav:version-url V 39 /svn/tcpser/!svn/ver/24/trunk/src/nvt.c END shared.h K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/10/trunk/src/shared.h END nvt.h K 25 svn:wc:ra_dav:version-url V 39 /svn/tcpser/!svn/ver/24/trunk/src/nvt.h END line.c K 25 svn:wc:ra_dav:version-url V 40 /svn/tcpser/!svn/ver/24/trunk/src/line.c END line.h K 25 svn:wc:ra_dav:version-url V 40 /svn/tcpser/!svn/ver/10/trunk/src/line.h END bridge.c K 25 svn:wc:ra_dav:version-url V 42 /svn/tcpser/!svn/ver/24/trunk/src/bridge.c END tcpser/src/.svn/entries0100444000076400010400000001017310747537546016324 0ustar brainAdministrators8 dir 5 http://www.jimbrain.com/svn/tcpser/trunk/src http://www.jimbrain.com/svn/tcpser 2007-02-06T06:43:32.577387Z 4 brain svn:special svn:externals svn:needs-lock 8602611e-c928-0410-ae49-afcc62ab246b tcpser.c file 25 2008-01-29T05:53:42.394366Z b1b1bf67a0899eec8caebcf42ac195c1 2007-02-06T07:18:50.343343Z 20 brain bridge.h file 10 2004-06-25T05:34:58.000000Z 709b6569a8f4ebe84e47679ea7217249 2007-02-06T07:09:21.911371Z 10 brain getcmd.c file 22 2005-08-14T07:18:04.000000Z a9688f12dd0165fc83016c423aeedfdc 2007-02-06T07:20:51.581213Z 22 brain init.c file 24 2006-06-18T15:01:24.000000Z c77848808846789b08cc43f336fe1973 2007-02-06T07:26:33.108543Z 24 brain tcpser.h file 6 2004-05-03T19:55:54.000000Z d41d8cd98f00b204e9800998ecf8427e 2007-02-06T07:04:10.627566Z 6 brain getcmd.h file 10 2004-06-25T05:34:58.000000Z 62db7febb7a9fc7bb7736421d8370a32 2007-02-06T07:09:21.911371Z 10 brain init.h file 10 2004-06-25T05:34:58.000000Z 915673b09bff87fcd6fbc6d12f6ba64c 2007-02-06T07:09:21.911371Z 10 brain ip.c file 12 2004-07-27T02:39:59.000000Z eba32cd8708f6baf7f8ea844b8f2adef 2007-02-06T07:11:31.776866Z 12 brain modem_core.c file 20 2005-03-06T22:10:16.000000Z 0aff0f81727b4b178260c1ca9a741e15 2007-02-06T07:18:50.343343Z 20 brain util.c file 10 2004-06-25T05:34:58.000000Z 234a4462405cfc000a9c77713c7cdd78 2007-02-06T07:09:21.911371Z 10 brain ip.h file 10 2004-06-25T05:34:58.000000Z 26cc6e8c5810d22897baf0d0540e2df6 2007-02-06T07:09:21.911371Z 10 brain modem_core.h file 24 2006-06-13T23:53:34.000000Z 249c89e974797fc1814469d566821b31 2007-02-06T07:26:33.108543Z 24 brain serial.c file 22 2005-09-20T05:14:26.000000Z 9f6a1acbf3996e3e1695c433b6f99784 2007-02-06T07:20:51.581213Z 22 brain util.h file 10 2004-06-25T05:34:58.000000Z eaae47082bac117a94a19d67909b9474 2007-02-06T07:09:21.911371Z 10 brain phone_book.c file 22 2005-09-20T05:29:58.000000Z 45efc345d55a6336dfae25e5a040667e 2007-02-06T07:20:51.581213Z 22 brain tcpmdm.c file 10 2004-06-25T05:34:58.000000Z 29d58f5f46b83889932b82c37cf3c3c7 2007-02-06T07:09:21.911371Z 10 brain serial.h file 10 2004-06-25T05:34:58.000000Z 3316a6fe2b24b446596074f0f447ce2a 2007-02-06T07:09:21.911371Z 10 brain debug.c file 22 2005-08-17T07:19:24.000000Z 01bd6a218ab392ad65ee67f711d62c18 2007-02-06T07:20:51.581213Z 22 brain phone_book.h file 10 2004-06-25T05:34:58.000000Z 117e5ec742424894912c60cb747edd88 2007-02-06T07:09:21.911371Z 10 brain tcpmdm.h file 10 2004-06-25T05:34:58.000000Z 68b329da9893e34099c7d8ad5cb9c940 2007-02-06T07:09:21.911371Z 10 brain dce.c file 24 2006-06-14T05:09:42.000000Z ccaf9121be0220469f57fcf1fa729e7b 2007-02-06T07:26:33.108543Z 24 brain debug.h file 10 2004-06-25T05:34:58.000000Z 516a843f31a3ea8e3fc6fde852d30151 2007-02-06T07:09:21.911371Z 10 brain ip232.c file 24 2006-06-15T08:27:38.000000Z 70fb3d4f9d09cd18fd3df6bbd3696676 2007-02-06T07:26:33.108543Z 24 brain modem_data.h file 6 deleted dce.h file 10 2004-06-25T05:34:58.000000Z cc01f11badd5c031ba9056ddde621b82 2007-02-06T07:09:21.911371Z 10 brain ip232.h file 24 2006-06-14T05:10:30.000000Z 40bfa6c501500c3098098b3088f3fefe 2007-02-06T07:26:33.108543Z 24 brain shared.c file 14 2004-08-01T07:38:46.000000Z 358b801da059b4225907c3d748952044 2007-02-06T07:13:17.349634Z 14 brain nvt.c file 24 2006-04-03T07:06:00.000000Z fb21d2dbf16d463ee1b9ae857feeb25b 2007-02-06T07:26:33.108543Z 24 brain connect file 12 deleted shared.h file 10 2004-06-25T05:34:58.000000Z 03ed49293987680880e2069598748679 2007-02-06T07:09:21.911371Z 10 brain nvt.h file 24 2006-04-01T23:31:56.000000Z 49905189a6be9329c9f3acae9fe72577 2007-02-06T07:26:33.108543Z 24 brain main.c file 6 deleted line.c file 24 2006-04-18T21:27:04.000000Z 879eb12cbb71ead8967d7590b56eaa82 2007-02-06T07:26:33.108543Z 24 brain main.h file 6 deleted bridge.c file 24 2006-06-18T15:00:20.000000Z 72614ab784e6e9f688e9d3b1afdfca1e 2007-02-06T07:26:33.108543Z 24 brain line.h file 10 2004-06-25T05:34:58.000000Z 50d226b6d7d3c3cb3fd576be85d3f1f0 2007-02-06T07:09:21.911371Z 10 brain tcpser/src/.svn/format0100444000076400010400000000000210562022500016077 0ustar brainAdministrators8 tcpser/src/.svn/prop-base/0040755000076400010400000000000010574105512016601 5ustar brainAdministratorstcpser/src/.svn/props/0040755000076400010400000000000010574105512016054 5ustar brainAdministratorstcpser/src/.svn/text-base/0040755000076400010400000000000010574105512016605 5ustar brainAdministratorstcpser/src/.svn/text-base/bridge.c.svn-base0100444000076400010400000003066310445265204021727 0ustar brainAdministrators#include #include // for recv... #include // for read... #include // for exit... #include #include #include #include "util.h" #include "debug.h" #include "nvt.h" #include "modem_core.h" #include "ip.h" //#include "serial.h" #include "getcmd.h" #include "bridge.h" const unsigned char MDM_NO_ANSWER[] = "NO ANSWER\n"; //const unsigned char CONNECT_NOTICE[] = "\r\nCONNECTING...\r\n"; //const unsigned char TELNET_NOTICE[] = "TELNET MODE ENABLED\r\n"; int accept_connection(modem_config* cfg) { LOG_ENTER(); cfg->line_data.fd=ip_accept(cfg->line_data.sfd); if(cfg->line_data.fd > -1) { cfg->line_data.valid_conn=TRUE; if(cfg->data.direct_conn == TRUE) { cfg->conn_type=MDM_CONN_INCOMING; mdm_off_hook(cfg); cfg->cmd_mode=TRUE; } else { //line_write(cfg,(unsigned char*)CONNECT_NOTICE,strlen(CONNECT_NOTICE)); cfg->rings=0; mdm_send_ring(cfg); } // tell parent I got it. LOG(LOG_DEBUG,"Informing parent task that I am busy"); writePipe(cfg->data.mp[0][1],MSG_ACCEPTED); } LOG_EXIT(); return 0; } int parse_ip_data(modem_config *cfg, unsigned char* data, int len) { // I'm going to cheat and assume it comes in chunks. int i=0; unsigned char ch; unsigned char text[1025]; int text_len=0; if(cfg->line_data.first_char==TRUE) { cfg->line_data.first_char=FALSE; if((data[0] == 0xff) || (data[0] == 0x1a)) { //line_write(cfg,(unsigned char*)TELNET_NOTICE,strlen(TELNET_NOTICE)); LOG(LOG_INFO,"Detected telnet"); cfg->line_data.is_telnet=TRUE; } } if(cfg->line_data.is_telnet == TRUE) { while(iline_data.fd, &cfg->line_data.nvt_data,ch,data[i+2]); i+=3; break; case NVT_SB: // sub negotiation // again, overflow... i+=parse_nvt_subcommand(cfg->line_data.fd, &cfg->line_data.nvt_data,data + i,len - i); break; case NVT_IAC: if (cfg->line_data.nvt_data.binary_recv) text[text_len++] = NVT_IAC; // fall through to skip this sequence default: // ignore... i+=2; } } else { text[text_len++]=data[i++]; } if(text_len == 1024) { text[text_len] = 0; // write to serial... mdm_write(cfg,text,text_len); text_len=0; } } if(text_len) { text[text_len] = 0; // write to serial... mdm_write(cfg,text,text_len); } } else { mdm_write(cfg,data,len); } return 0; } void *ip_thread(void *arg) { modem_config* cfg=(modem_config *)arg; int action_pending=FALSE; fd_set readfs; int max_fd; int res=0; unsigned char buf[256]; int rc; LOG_ENTER(); while(TRUE) { FD_ZERO(&readfs); FD_SET(cfg->data.cp[1][0], &readfs); max_fd=cfg->data.cp[1][0]; if(action_pending == FALSE && cfg->conn_type != MDM_CONN_NONE && cfg->cmd_mode == FALSE && cfg->line_data.fd > -1 && cfg->line_data.valid_conn ==TRUE ) { FD_SET(cfg->line_data.fd, &readfs); max_fd=MAX(max_fd,cfg->line_data.fd); } max_fd++; rc=select(max_fd, &readfs, NULL, NULL, NULL); if(rc == -1) { ELOG(LOG_WARN,"Select returned error"); // handle error } else { // we got data if (cfg->line_data.valid_conn==TRUE && FD_ISSET(cfg->line_data.fd,&readfs)) { // socket LOG(LOG_DEBUG,"Data available on socket"); res = recv(cfg->line_data.fd,buf,sizeof(buf),0); if(0 >= res) { LOG(LOG_INFO,"No socket data read, assume closed peer"); writePipe(cfg->data.cp[0][1],MSG_DISCONNECT); action_pending=TRUE; } else { LOG(LOG_DEBUG,"Read %d bytes from socket",res); buf[res]=0; log_trace(TRACE_IP_IN,buf,res); parse_ip_data(cfg,buf,res); } } if (FD_ISSET(cfg->data.cp[1][0],&readfs)) { // pipe res = read(cfg->data.cp[1][0],buf,sizeof(buf) - 1); LOG(LOG_DEBUG,"IP thread notified"); action_pending=FALSE; } } } LOG_EXIT(); } void *ctrl_thread(void *arg) { modem_config* cfg=(modem_config *)arg; int status; int new_status; LOG_ENTER(); status=dce_get_control_lines(cfg); while(status > -1) { new_status = dce_check_control_lines(cfg); if(new_status > -1 && status != new_status) { // something changed if((status & MDM_CL_DTR_HIGH) != (new_status & MDM_CL_DTR_HIGH)) { if((new_status & MDM_CL_DTR_HIGH) == 0) { LOG(LOG_INFO,"DTR has gone low"); writePipe(cfg->data.wp[0][1],MSG_DTR_DOWN); } else { LOG(LOG_INFO,"DTR has gone high"); writePipe(cfg->data.wp[0][1],MSG_DTR_UP); } } } status = new_status; } LOG_EXIT(); // need to quit application, as status cannot be obtained. exit(-1); } int spawn_ctrl_thread(modem_config *cfg) { int rc; pthread_t thread_id; rc=pthread_create(&thread_id,NULL,ctrl_thread,(void *)cfg); LOG(LOG_ALL,"CTRL thread ID=%d",(int)thread_id); if(rc < 0) { ELOG(LOG_FATAL,"CTRL thread could not be started"); exit(-1); } return 0; } int spawn_ip_thread(modem_config *cfg) { int rc; pthread_t thread_id; rc=pthread_create(&thread_id,NULL,ip_thread,(void *)cfg); LOG(LOG_ALL,"IP thread ID=%d",(int)thread_id); if(rc < 0) { ELOG(LOG_FATAL,"IP thread could not be started"); exit(-1); } return 0; } void *run_bridge(void * arg) { modem_config *cfg=(modem_config *)arg; struct timeval timer; struct timeval* ptimer; int max_fd=0; fd_set readfs; int res=0; unsigned char buf[256]; int rc=0; int last_conn_type; int last_cmd_mode=cfg->cmd_mode; LOG_ENTER(); if( -1 == pipe(cfg->data.wp[0])) { ELOG(LOG_FATAL,"Control line watch task incoming IPC pipe could not be created"); exit(-1); } if( -1 == pipe(cfg->data.cp[0])) { ELOG(LOG_FATAL,"IP thread incoming IPC pipe could not be created"); exit(-1); } if( -1 == pipe(cfg->data.cp[1])) { ELOG(LOG_FATAL,"IP thread outgoing IPC pipe could not be created"); exit(-1); } spawn_ctrl_thread(cfg); spawn_ip_thread(cfg); mdm_set_control_lines(cfg); strncpy(cfg->cur_line,cfg->config0,sizeof(cfg->cur_line)); last_conn_type=cfg->conn_type; last_cmd_mode=cfg->cmd_mode; cfg->allow_transmit=FALSE; // call some functions behind the scenes mdm_disconnect(cfg); mdm_parse_cmd(cfg); // if direct connection, and num length > 0, dial number. if (cfg->data.direct_conn == TRUE) { if(strlen(cfg->data.direct_conn_num) > 0 && cfg->data.direct_conn_num[0] != ':') { // we have a direct number to connect to. strncpy(cfg->dialno,cfg->data.direct_conn_num,sizeof(cfg->dialno)); if(0 != line_connect(cfg)) { LOG(LOG_FATAL,"Cannot connect to Direct line address!"); // probably should exit... exit(-1); } else { cfg->conn_type=MDM_CONN_OUTGOING; } } } cfg->allow_transmit=TRUE; for(;;) { if(last_conn_type!= cfg->conn_type) { LOG(LOG_ALL,"Connection status change, handling"); //writePipe(cfg->data.mp[0][1],MSG_NOTIFY); writePipe(cfg->data.cp[1][1],MSG_NOTIFY); if(cfg->conn_type == MDM_CONN_OUTGOING) { if(strlen(cfg->data.local_connect) > 0) { writeFile(cfg->data.local_connect,cfg->line_data.fd); } if(strlen(cfg->data.remote_connect) > 0) { writeFile(cfg->data.remote_connect,cfg->line_data.fd); } } else if(cfg->conn_type == MDM_CONN_INCOMING) { if(strlen(cfg->data.local_answer) > 0) { writeFile(cfg->data.local_answer,cfg->line_data.fd); } if(strlen(cfg->data.remote_answer) > 0) { writeFile(cfg->data.remote_answer,cfg->line_data.fd); } } last_conn_type=cfg->conn_type; } if(last_cmd_mode != cfg->cmd_mode) { writePipe(cfg->data.cp[1][1],MSG_NOTIFY); last_cmd_mode=cfg->cmd_mode; } LOG(LOG_ALL,"Waiting for modem/control line/timer/socket activity"); LOG(LOG_ALL,"Command Mode=%d, Connection status=%d",cfg->cmd_mode,cfg->conn_type); max_fd=MAX(cfg->data.mp[1][0],cfg->dce_data.fd); max_fd=MAX(max_fd,cfg->data.wp[0][0]); max_fd=MAX(max_fd,cfg->data.cp[0][0]); FD_ZERO(&readfs); FD_SET(cfg->data.mp[1][0], &readfs); FD_SET(cfg->dce_data.fd, &readfs); FD_SET(cfg->data.wp[0][0], &readfs); FD_SET(cfg->data.cp[0][0], &readfs); ptimer=NULL; if(cfg->cmd_mode == FALSE) { if(cfg->pre_break_delay == FALSE || cfg->break_len == 3) { LOG(LOG_ALL,"Setting timer for break delay"); timer.tv_sec=0; timer.tv_usec=cfg->s[12] * 20000; ptimer=&timer; } else if(cfg->pre_break_delay == TRUE && cfg->break_len > 0) { LOG(LOG_ALL,"Setting timer for inter-break character delay"); timer.tv_sec=1; // 1 second timer.tv_usec=0; ptimer=&timer; } else if (cfg->s[30] != 0) { LOG(LOG_ALL,"Setting timer for inactivity delay"); timer.tv_sec=cfg->s[30] * 10; timer.tv_usec=0; ptimer=&timer; } } else if(cfg->cmd_mode == TRUE && cfg->conn_type== MDM_CONN_NONE && cfg->line_data.valid_conn ==TRUE) { LOG(LOG_ALL,"Setting timer for rings"); timer.tv_sec=4; timer.tv_usec=0; ptimer=&timer; } max_fd++; rc=select(max_fd, &readfs, NULL, NULL, ptimer); if(rc == -1) { ELOG(LOG_WARN,"Select returned error"); // handle error } else if(rc == 0) { // timer popped. if(cfg->cmd_mode == TRUE && cfg->conn_type == MDM_CONN_NONE && cfg->line_data.valid_conn == TRUE) { if(cfg->s[0] == 0 && cfg->rings==10) { // not going to answer, send some data back to IP and disconnect. if(strlen(cfg->data.no_answer) == 0) { line_write(cfg,(unsigned char*)MDM_NO_ANSWER,strlen(MDM_NO_ANSWER)); } else { writeFile(cfg->data.no_answer,cfg->line_data.fd); } mdm_disconnect(cfg); } else mdm_send_ring(cfg); } else mdm_handle_timeout(cfg); } if (FD_ISSET(cfg->dce_data.fd,&readfs)) { // serial port LOG(LOG_DEBUG,"Data available on serial port"); res = dce_read(cfg,buf,sizeof(buf)); LOG(LOG_DEBUG,"Read %d bytes from serial port",res); if(res > 0) { if(cfg->conn_type == MDM_CONN_NONE && cfg->off_hook == TRUE) { // this handles the case where atdt goes off hook, but no // connection mdm_disconnect(cfg); mdm_send_response(MDM_RESP_OK,cfg); } else { mdm_parse_data(cfg,buf,res); } } } if (FD_ISSET(cfg->data.wp[0][0],&readfs)) { // control pipe res = read(cfg->data.wp[0][0],buf,sizeof(buf) -1); buf[res]=0; LOG(LOG_DEBUG,"Received %c from Control line watch task",buf[0]); switch (buf[0]) { case MSG_DTR_DOWN: // DTR drop, close any active connection and put // in cmd_mode mdm_disconnect(cfg); break; case MSG_DTR_UP: break; } } if (FD_ISSET(cfg->data.cp[0][0],&readfs)) { // ip thread pipe res = read(cfg->data.cp[0][0],buf,sizeof(buf)); LOG(LOG_DEBUG,"Received %c from ip thread",buf[0]); switch (buf[0]) { case MSG_DISCONNECT: if(cfg->data.direct_conn == TRUE) { // what should we do here... LOG(LOG_ERROR,"Direct Connection Link broken, disconnecting and awaiting new direct connection"); cfg->data.direct_conn=FALSE; mdm_disconnect(cfg); cfg->data.direct_conn=TRUE; } else { mdm_disconnect(cfg); } break; } } if (FD_ISSET(cfg->data.mp[1][0],&readfs)) { // parent pipe LOG(LOG_DEBUG,"Data available on incoming IPC pipe"); res = read(cfg->data.mp[1][0],buf,sizeof(buf)); switch (buf[0]) { case MSG_ACCEPT: // accept connection. accept_connection(cfg); break; } } } LOG_EXIT(); } tcpser/src/.svn/text-base/bridge.h.svn-base0100444000076400010400000000102210066734602021721 0ustar brainAdministrators#define MSG_NOT_ACTIVE 'a' #define MSG_ACTIVE 'A' #define MSG_NOT_LISTENING 'l' #define MSG_LISTENING 'L' #define MSG_ACCEPT '+' #define MSG_ACCEPTED '+' #define MSG_DTR_DOWN 'd' #define MSG_DTR_UP 'D' #define MSG_RTS_DOWN 'r' #define MSG_RTS_UP 'R' #define MSG_CD_DOWN 'c' #define MSG_CD_UP 'c' #define MSG_RNG_DOWN 'n' #define MSG_RNG_UP 'N' #define MSG_DISCONNECT 'D' #define MSG_NOTIFY 'N' int accept_connection(modem_config*); int parse_ip_data(modem_config *cfg, unsigned char* data, int len); void *run_bridge(void *arg); tcpser/src/.svn/text-base/dce.c.svn-base0100444000076400010400000000541510443715026021223 0ustar brainAdministrators#include #include #include #include "debug.h" #include "serial.h" #include "modem_core.h" #include "ip232.h" // needs modem_core.h #include "dce.h" int dce_init_config(modem_config *cfg) { return 0; } int dce_init_conn(modem_config* cfg) { int rc; LOG_ENTER(); if (cfg->dce_data.is_ip232) { rc=ip232_init_conn(cfg); } else { rc=ser_init_conn(cfg->dce_data.tty,cfg->dte_speed); cfg->dce_data.fd=rc; } LOG_EXIT(); return rc; } int dce_set_flow_control(modem_config *cfg,int opts) { int status=0; int rc=0; LOG_ENTER(); if(opts == 0) { LOG(LOG_ALL,"Setting NONE flow control"); } else { if((opts & MDM_FC_RTS) != 0) { LOG(LOG_ALL,"Setting RTSCTS flow control"); status |= CRTSCTS; } if((opts && MDM_FC_XON) != 0) { status |= (IXON | IXOFF); LOG(LOG_ALL,"Setting XON/XOFF flow control"); } } if (cfg->dce_data.is_ip232) { rc=ip232_set_flow_control(cfg,status); } else { rc=ser_set_flow_control(cfg->dce_data.fd,status); } LOG_EXIT() return rc; } int dce_set_control_lines(modem_config *cfg,int state) { int status=0; int rc; LOG_ENTER(); if((state & MDM_CL_CTS_HIGH) != 0) { LOG(LOG_ALL,"Setting CTS pin high"); status |= TIOCM_RTS; } else { LOG(LOG_ALL,"Setting CTS pin low"); //status &= ~TIOCM_RTS; } if((state & MDM_CL_DCD_HIGH) != 0) { LOG(LOG_ALL,"Setting DCD pin high"); status |= TIOCM_DTR; } else { LOG(LOG_ALL,"Setting DCD pin low"); //status &= ~TIOCM_DTR; } if (cfg->dce_data.is_ip232) { rc = ip232_set_control_lines(cfg,status); } else { rc = ser_set_control_lines(cfg->dce_data.fd,status); } LOG_EXIT(); return rc; } int dce_get_control_lines(modem_config *cfg) { int status; int rc_status; if (cfg->dce_data.is_ip232) { status = ip232_get_control_lines(cfg); } else { status = ser_get_control_lines(cfg->dce_data.fd); } if(status > -1) { rc_status=((status & TIOCM_DSR) != 0?MDM_CL_DTR_HIGH:0); } else { rc_status=status; } return rc_status; } int dce_check_control_lines(modem_config *cfg) { int status=0; int new_status=0; LOG_ENTER(); status = dce_get_control_lines(cfg); new_status = status; while(new_status > -1 && status == new_status) { usleep(100000); new_status = dce_get_control_lines(cfg); } LOG_EXIT(); return new_status; } int dce_write(modem_config *cfg,unsigned char data[], int len) { if (cfg->dce_data.is_ip232) { return ip232_write(cfg,data,len); } return ser_write(cfg->dce_data.fd,data,len); } int dce_read(modem_config *cfg, unsigned char data[], int len) { if (cfg->dce_data.is_ip232) { return ip232_read(cfg,data,len); } return ser_read(cfg->dce_data.fd,data,len); } tcpser/src/.svn/text-base/dce.h.svn-base0100444000076400010400000000103110066734602021220 0ustar brainAdministrators#ifndef DCE_H #define DCE_H 1 int dce_init(void); int dce_init_config(modem_config *cfg); int dce_init_conn(modem_config* cfg); int dce_set_flow_control(modem_config *cfg,int opts); int dce_set_control_lines(modem_config *cfg,int state); int dce_get_control_lines(modem_config *cfg); int dce_check_control_lines(modem_config *cfg); int dce_read(modem_config *cfg,unsigned char* data,int len); int dce_write(modem_config *cfg,unsigned char* data,int len); //int dce_check_for_break(modem_config *cfg, char ch, int chars_left); #endif tcpser/src/.svn/text-base/debug.c.svn-base0100444000076400010400000000541510300562374021554 0ustar brainAdministrators#include // for exit... #include #include #include #define DEBUG_VARS 1 // need this so we don't get extern defs #include "debug.h" int log_level=0; FILE* log_file; int trace_flags=0; unsigned char* trace_type[9]; // cheesy, but I can't think of another o(1) way unsigned char* log_desc[LOG_TRACE+1]; pthread_mutex_t log_mutex; int log_init() { log_file=stdout; log_level=0; trace_flags=0; trace_type[TRACE_MODEM_IN]="RS<-"; trace_type[TRACE_MODEM_OUT]="RS->"; trace_type[TRACE_IP_IN]="IP<-"; trace_type[TRACE_IP_OUT]="IP->"; log_desc[LOG_FATAL]="FATAL"; log_desc[LOG_ERROR]="ERROR"; log_desc[LOG_WARN]="WARN"; log_desc[LOG_INFO]="INFO"; log_desc[LOG_DEBUG]="DEBUG"; log_desc[LOG_ENTER_EXIT]="ENTER_EXIT"; log_desc[LOG_ALL]="DEBUG_X"; log_desc[LOG_TRACE]=""; if( -1 == pthread_mutex_init(&log_mutex,NULL)) { perror("Could not create Log Mutex"); exit(-1); } return 0; } void log_set_file(FILE* a) { log_file=a; } void log_set_level(int a) { log_level=a; } void log_set_trace_flags(int a) { trace_flags=a; } int log_get_trace_flags() { return trace_flags; } void log_trace(int type, unsigned char* line, int len) { int i=0; int ch; unsigned char data[64]="\0"; unsigned char *dptr=NULL; unsigned char text[17]; if(len==0) return; if((type & trace_flags) != 0) { text[16]=0; for(i=0;i 31 && ch < 127) { text[i % 16] = ch; } else { text[i % 16] = '.'; } if((i %16) == 15) { log_start(LOG_TRACE); fprintf(log_file,"%s|%s|%s|",trace_type[type],data,text); log_end(); } else { sprintf(dptr + 7 + ((i % 16) * 3)," "); } } i=i%16; if(i > 0) { for(;i<16;i++) { sprintf(dptr + 5 + ((i % 16) * 3)," "); if((i % 16) != 15) { sprintf(dptr + 7 + ((i % 16) * 3)," "); } text[i % 16] = ' '; } log_start(LOG_TRACE); fprintf(log_file,"%s|%s|%s|",trace_type[type],data,text); } log_end(); } } void log_start(int level) { unsigned char t[23]; time_t now; if(-1 == pthread_mutex_lock(&log_mutex)) { perror("Could not lock the log mutex"); } else { // we have the lock. now=time(NULL); strftime(t,22,"%Y-%m-%d %H:%M:%S",localtime(&now)); fprintf(log_file,"%s:%5.5d:%s:",t,(int)pthread_self(),log_desc[level]); //free(t); } } void log_end() { fprintf(log_file,"\n"); fflush(log_file); if(-1 == pthread_mutex_unlock(&log_mutex)) { perror("Could not lock the log mutex"); } } tcpser/src/.svn/text-base/debug.h.svn-base0100444000076400010400000000330710066734602021563 0ustar brainAdministrators#ifndef DEBUG_H #define DEBUG_H 1 #define LOG_TRACE 10 #define LOG_ALL 7 #define LOG_ENTER_EXIT 6 #define LOG_DEBUG 5 #define LOG_INFO 4 #define LOG_WARN 3 #define LOG_ERROR 2 #define LOG_FATAL 1 #define LOG_NONE 0 #define TRACE_MODEM_IN 1 #define TRACE_MODEM_OUT 2 #define TRACE_IP_IN 4 #define TRACE_IP_OUT 8 #include // needed for strerror #include // needed for strerror #include // needed for errno #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 # define __func__ __FUNCTION__ # else # define __func__ "" # endif #endif #define LOG(a,args...) do { \ if(a <= log_level) { \ log_start(a); \ fprintf(log_file,args); \ log_end(); \ } \ } while(0) #define ELOG(a,args...) do { \ if(a <= log_level) { \ log_start(a); \ fprintf(log_file,args); \ fprintf(log_file," (%s)\n",strerror(errno)); \ log_end(); \ } \ } while(0) #define LOG_ENTER() LOG(LOG_ENTER_EXIT,"Entering %s function",__func__); #define LOG_EXIT() LOG(LOG_ENTER_EXIT,"Exitting %s function",__func__); int log_init(void); void log_set_file(FILE* a); void log_set_level(int a); int log_get_trace_flags(); void log_set_trace_flags(int a); void log_trace(int type, unsigned char* line, int len); void log_start(int level); void log_end(); #endif #ifndef DEBUG_VARS #define DEBUG_VARS 1 #include extern int log_level; extern FILE* log_file; #endif tcpser/src/.svn/text-base/getcmd.c.svn-base0100444000076400010400000001504610277570054021741 0ustar brainAdministrators#include #include #include #include "getcmd.h" int getData(unsigned char line[], int* index, int len, int* data_start, int* data_end, int complex_parse ) { int alpha=FALSE; int done=FALSE; *data_start=*index; while(*index < len && done != TRUE) { // I'm going to assume either // a number // a string with a space switch(line[*index]) { case ' ': if(!complex_parse && *index != *data_start) { // leave space, next call will skip it. done=TRUE; } else if(*index != *data_start) { // we are complex, add the space and continue. (*index)++; } else { // we have not started, eat space and continue. (*index)++; *data_start=*index; } break; case 0: done=TRUE; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': // isnum (*index)++; break; default: if(!complex_parse && *index != *data_start && 0==alpha ) { // we were a number, but we've hit an alpha 'S0=137S...' done=TRUE; } else { (*index)++; alpha=TRUE; } break; } } *data_end=(*index); return 0; } int getNumber(unsigned char line[], int* index, int len ) { int num=0; int found=FALSE; while(*index *num) *num=0; return toupper(cmd) | flags; } int parseRegister(unsigned char line[], int flags, int* index, int* num, int len, int* data_start, int* data_end, int complex_parse ) { // need to handle S?, which queries that S register. int cmd=0; cmd = getCommand(line,flags,index,num,len); if(0 > num) return AT_CMD_ERR; skip(line,index,len,' '); if(len == *index) return AT_CMD_ERR; switch (line[(*index)++]) { case '=': // set a register skip(line, index, len, ' '); if(0 > getData(line, index, len, data_start, data_end, complex_parse)) return AT_CMD_ERR; break; case '?': // query a register flags |= AT_CMD_FLAG_QUERY; if(*num < 0) *num=0; break; default: return AT_CMD_ERR; } return toupper(cmd) | flags; } int getcmd(unsigned char line[], int* index, int* num, int* data_start, int* data_end ) { int len=0; int cmd=AT_CMD_END; *num=0; *data_start=0; *data_end=0; if(line == NULL) return AT_CMD_NONE; len=strlen(line); while(*index < len) { cmd=toupper(line[*index]); switch (cmd) { case ' ': break; case 0: return AT_CMD_END; case '%': (*index)++; while(*index #include // for exit,atoi #include #include "debug.h" #include "phone_book.h" #include "init.h" void print_help(unsigned char* name) { fprintf(stderr, "Usage: %s \n",name); fprintf(stderr, " -p port to listen on (defaults to 6400)\n"); fprintf(stderr, " -t trace flags: (can be combined)\n"); fprintf(stderr, " 's' = modem input\n"); fprintf(stderr, " 'S' = modem output\n"); fprintf(stderr, " 'i' = IP input\n"); fprintf(stderr, " 'I' = IP input\n"); fprintf(stderr, " -l 0 (NONE), 1 (FATAL) - 7 (DEBUG_X) (defaults to 0)\n"); fprintf(stderr, " -L log file (defaults to stderr)\n"); fprintf(stderr, "\n"); fprintf(stderr, " The following can be repeated for each modem desired\n"); fprintf(stderr, " (-s, -S, and -i will apply to any subsequent device if not set again)\n"); fprintf(stderr, "\n"); fprintf(stderr, " -d serial device (e.g. /dev/ttyS0). Cannot be used with -v\n"); fprintf(stderr, " -v tcp port for VICE RS232 (e.g. 25232). Cannot be used with -d\n"); fprintf(stderr, " -s serial port speed (defaults to 38400)\n"); fprintf(stderr, " -S speed modem will report (defaults to -s value)\n"); fprintf(stderr, " -I invert DCD pin\n"); fprintf(stderr, " -n add phone entry (number=replacement)\n"); fprintf(stderr, " -a filename to send to local side upon answer\n"); fprintf(stderr, " -A filename to send to remote side upon answer\n"); fprintf(stderr, " -c filename to send to local side upon connect\n"); fprintf(stderr, " -C filename to send to remote side upon connect\n"); fprintf(stderr, " -N filename to send when no answer\n"); fprintf(stderr, " -B filename to send when modem(s) busy\n"); fprintf(stderr, " -T filename to send upon inactivity timeout\n"); fprintf(stderr, " -i modem init string (defaults to '', leave off 'at' prefix when specifying)\n"); fprintf(stderr, " -D direct connection (follow with hostname:port for caller, : for receiver)\n"); exit(1); } int init(int argc, char** argv, modem_config cfg[], int max_modem, int* port, unsigned char* all_busy, int all_busy_len ) { int i=0; int j=0; int opt=0; int trace_flags=0; unsigned char* tok; int dce_set=FALSE; int tty_set=FALSE; LOG_ENTER(); *port=6400; mdm_init_config(&cfg[0]); cfg[0].dte_speed=38400; cfg[0].dce_speed=38400; while(opt>-1 && i < max_modem) { opt=getopt(argc,argv,"p:s:S:d:v:hw:i:Il:L:t:n:a:A:c:C:N:B:T:D:"); switch(opt) { case 't': trace_flags=log_get_trace_flags(); for(j=0;j #include #include #include #include #include // for read... #include // for atoi... #include "debug.h" #include "ip.h" const int BACK_LOG = 5; int ip_init_server_conn(int port) { int sSocket = 0, on = 0, rc = 0; struct sockaddr_in serverName = { 0 }; LOG_ENTER(); LOG(LOG_DEBUG,"Creating server socket"); sSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (-1 == sSocket) { ELOG(LOG_FATAL,"Server socket could not be created"); } else { /* * turn off bind address checking, and allow * port numbers to be reused - otherwise * the TIME_WAIT phenomenon will prevent * binding to these addreG. */ on = 1; rc = setsockopt(sSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on) ); if (-1 == rc) { ELOG(LOG_ERROR,"bind address checking could not be turned off"); } serverName.sin_addr.s_addr=htonl(INADDR_ANY); serverName.sin_family = AF_INET; /* network-order */ serverName.sin_port = htons(port); LOG(LOG_DEBUG,"Binding server socket to port %d",port); rc = bind(sSocket, (struct sockaddr *) &serverName, sizeof(serverName) ); if (-1 == rc) { ELOG(LOG_FATAL,"Server socket could not be bound to port"); sSocket = -1; } else { LOG(LOG_INFO,"Server socket bound to port"); rc = listen(sSocket, BACK_LOG); LOG(LOG_INFO,"Server socket listening for connections"); if (-1 == rc) { ELOG(LOG_FATAL,"Server socket could not listen on port"); sSocket = -1; } } } LOG_EXIT(); return sSocket; } int ip_connect(unsigned char addy[]) { struct sockaddr_in pin; struct in_addr cin_addr; struct hostent *hp; int sd=0; int port=23; unsigned char* address; unsigned char* tmp; LOG_ENTER(); address=(unsigned char*)strtok(addy,":"); tmp=(unsigned char*)strtok((unsigned char*)0,":"); if(tmp != NULL && strlen(tmp) > 0) { port=atoi(tmp); } LOG(LOG_DEBUG,"Calling %s",addy); memset(&pin, 0, sizeof(pin)); /* go find out about the desired host machine */ if ((hp = gethostbyname(address)) == 0) { // well, not a DNS entry... Treat as IP... if(1 != inet_aton(address,&cin_addr)) { ELOG(LOG_ERROR,"Host %s was invalid",addy); return -1; } } else { cin_addr=*((struct in_addr *)(hp->h_addr)); } pin.sin_family = AF_INET; pin.sin_addr.s_addr = cin_addr.s_addr; pin.sin_port = htons(port); /* grab an Internet domain socket */ if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { ELOG(LOG_ERROR,"could not create client socket"); return -1; } /* connect to PORT on HOST */ if (connect(sd,(struct sockaddr *) &pin, sizeof(pin)) == -1) { ELOG(LOG_ERROR,"could not connect to address"); return -1; } LOG(LOG_INFO, "Connection to %s established",addy); LOG_EXIT(); return sd; } int ip_accept(int sSocket) { struct sockaddr_in clientName = { 0 }; int clientLength = sizeof(clientName); int cSocket=-1; LOG_ENTER(); (void) memset(&clientName, 0, sizeof(clientName)); cSocket = accept(sSocket, (struct sockaddr *) &clientName, &clientLength ); if (-1 == cSocket) { ELOG(LOG_ERROR,"Could not accept incoming connection"); return -1; } if (-1 == getpeername(cSocket, (struct sockaddr *) &clientName, &clientLength )) { ELOG(LOG_WARN,"Could not obtain peer name"); } else { LOG(LOG_INFO,"Connection accepted from %s", inet_ntoa(clientName.sin_addr) ); } LOG_EXIT(); return cSocket; } int ip_disconnect(int fd) { if(fd > -1) close(fd); return 0; } int ip_write(int fd,unsigned char* data,int len) { log_trace(TRACE_IP_OUT,data,len); return write(fd,data,len); } int ip_read(int fd, unsigned char* data, int len) { int res; res = recv(fd,data,len,0); log_trace(TRACE_IP_IN,data,res); return res; } tcpser/src/.svn/text-base/ip.h.svn-base0100444000076400010400000000052010066734602021077 0ustar brainAdministrators#ifndef IP_H #define IP_H #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif int ip_init(void); int ip_init_server_conn(int port); int ip_connect(unsigned char addy[]); int ip_accept(int sSocket); int ip_disconnect(int fd); int ip_write(int fd,unsigned char* data,int len); int ip_read(int fd, unsigned char* data, int len); #endif tcpser/src/.svn/text-base/ip232.c.svn-base0100444000076400010400000001457210444214772021336 0ustar brainAdministrators#include // for recv... #include // for exit... #include #include #include #include #include #include #include #include "util.h" #include "debug.h" #include "modem_core.h" #include "ip.h" #include "ip232.h" void *ip232_thread(void *arg) { modem_config* cfg=(modem_config *)arg; int accept_pending=FALSE; int rc; int res=0; unsigned char buf[256]; fd_set readfs; int max_fd=0; int cSocket; LOG_ENTER(); for(;;) { FD_ZERO(&readfs); FD_SET(cfg->dce_data.dp[1][0], &readfs); max_fd=cfg->dce_data.dp[1][0]; if (accept_pending == FALSE) { FD_SET(cfg->dce_data.sSocket, &readfs); max_fd=MAX(max_fd,cfg->dce_data.sSocket); } LOG(LOG_ALL,"Waiting for incoming ip232 connections"); rc = select(max_fd+1, &readfs, NULL, NULL, NULL); if (rc < 0) { // handle error } else { if (FD_ISSET(cfg->dce_data.dp[1][0],&readfs)) { // pipe res = read(cfg->dce_data.dp[1][0],buf,sizeof(buf) - 1); LOG(LOG_DEBUG,"ip232 thread notified"); accept_pending=FALSE; } if (FD_ISSET(cfg->dce_data.sSocket,&readfs)) { // ip connection if(cfg->dce_data.ip232_is_connected) { LOG(LOG_DEBUG,"Already have ip232 connection, rejecting new"); // already have a connection... accept and close cSocket=ip_accept(cfg->dce_data.sSocket); if(cSocket > -1) { close(cSocket); } } else { LOG(LOG_DEBUG,"Incoming ip232 connection"); writePipe(cfg->dce_data.dp[0][1],MSG_ACCEPT); accept_pending=TRUE; } } } } LOG_EXIT(); } int spawn_ip232_thread(modem_config *cfg) { int rc; pthread_t thread_id; rc=pthread_create(&thread_id,NULL,ip232_thread,(void *)cfg); LOG(LOG_ALL,"ip232 thread ID=%d",(int)thread_id); if(rc < 0) { ELOG(LOG_FATAL,"ip232 thread could not be started"); exit(-1); } return 0; } int ip232_init_conn(modem_config *cfg) { int rc = -1; int port; LOG_ENTER(); LOG(LOG_INFO,"Opening ip232 device"); port = atoi(cfg->dce_data.tty); rc = ip_init_server_conn(port); if (rc < 0) { ELOG(LOG_FATAL,"Could not initialize ip232 server socket"); exit(-1); } if( -1 == pipe(cfg->dce_data.dp[0])) { ELOG(LOG_FATAL,"ip232 thread incoming IPC pipe could not be created"); exit(-1); } if( -1 == pipe(cfg->dce_data.dp[1])) { ELOG(LOG_FATAL,"ip232 thread outgoing IPC pipe could not be created"); exit(-1); } cfg->dce_data.sSocket = rc; cfg->dce_data.ip232_is_connected = FALSE; cfg->dce_data.fd = cfg->dce_data.dp[0][0]; spawn_ip232_thread(cfg); LOG(LOG_INFO,"ip232 device configured"); LOG_EXIT(); return rc; } int ip232_set_flow_control(modem_config *cfg, int status) { return 0; } int ip232_get_control_lines(modem_config *cfg) { int status=0; if (cfg->dce_data.ip232_is_connected && cfg->dce_data.ip232_dtr) { status |= TIOCM_DSR; } return status; } int ip232_set_control_lines(modem_config *cfg, int state) { int dcd; unsigned char cmd[2]; if (cfg->dce_data.ip232_is_connected) { dcd = (state & TIOCM_DTR) ? TRUE : FALSE; if (dcd != cfg->dce_data.ip232_dcd) { cfg->dce_data.ip232_dcd = dcd; cmd[0] = 255; cmd[1] = dcd ? 1 : 0; ip_write(cfg->dce_data.fd,cmd,sizeof(cmd)); } } return 0; } int ip232_write(modem_config *cfg, unsigned char* data,int len) { int retval; int i=0; int double_iac = FALSE; unsigned char text[1024]; int text_len=0; log_trace(TRACE_MODEM_OUT,data,len); retval = len; if (cfg->dce_data.ip232_is_connected) { while(idce_data.fd,text,text_len); text_len = 0; } } if(text_len) { retval = ip_write(cfg->dce_data.fd,text,text_len); } } return retval; } int ip232_read(modem_config *cfg, unsigned char* data, int len) { int res; int rc; unsigned char buf[256]; int i=0; unsigned char ch; int text_len=0; LOG_ENTER(); if (len > sizeof(buf)) { LOG(LOG_FATAL, "ip232_read: len > sizeof(buf)"); exit(-1); } if (cfg->dce_data.ip232_is_connected) { res = recv(cfg->dce_data.fd,buf,len,0); if (0 >= res) { LOG(LOG_INFO,"No ip232 socket data read, assume closed peer"); ip_disconnect(cfg->dce_data.fd); cfg->dce_data.fd = cfg->dce_data.dp[0][0]; cfg->dce_data.ip232_is_connected = FALSE; } else { LOG(LOG_DEBUG,"Read %d bytes from ip232 socket",res); log_trace(TRACE_MODEM_IN,buf,res); while(idce_data.ip232_iac) { cfg->dce_data.ip232_iac = FALSE; switch (ch) { case 0: cfg->dce_data.ip232_dtr = FALSE; break; case 1: cfg->dce_data.ip232_dtr = TRUE; break; case 255: data[text_len++] = 255; break; } } else { if (255 == ch) { cfg->dce_data.ip232_iac = TRUE; } else { data[text_len++] = ch; } } i++; } } } else { // not connected res = read(cfg->dce_data.dp[0][0],buf,sizeof(buf)); switch (buf[0]) { case MSG_ACCEPT: // accept connection. LOG(LOG_INFO,"Accepting ip232 connection..."); rc=ip_accept(cfg->dce_data.sSocket); if(res > -1) { cfg->dce_data.fd = rc; cfg->dce_data.ip232_is_connected = TRUE; cfg->dce_data.ip232_dtr = FALSE; cfg->dce_data.ip232_dcd = FALSE; writePipe(cfg->dce_data.dp[1][1],MSG_ACCEPTED); } break; } } LOG_EXIT(); return text_len; } tcpser/src/.svn/text-base/ip232.h.svn-base0100444000076400010400000000074110443715106021330 0ustar brainAdministrators#ifndef IP232_H #define IP232_H 1 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define MSG_ACCEPT '+' #define MSG_ACCEPTED '+' int ip232_init_conn(modem_config *); int ip232_set_flow_control(modem_config *, int status); int ip232_get_control_lines(modem_config *); int ip232_set_control_lines(modem_config *, int state); int ip232_write(modem_config *, unsigned char* data,int len); int ip232_read(modem_config *, unsigned char* data, int len); #endif tcpser/src/.svn/text-base/line.c.svn-base0100444000076400010400000000413210421254650021407 0ustar brainAdministrators#include "debug.h" #include "modem_core.h" #include "phone_book.h" #include "ip.h" #include "bridge.h" #include "line.h" int line_init_config(modem_config *cfg) { cfg->line_data.fd=-1; cfg->line_data.is_telnet=FALSE; cfg->line_data.first_char=TRUE; cfg->line_data.valid_conn=FALSE; nvt_init_config(&cfg->line_data.nvt_data); return 0; } int line_write(modem_config *cfg,unsigned char* data,int len) { int retval; int i=0; int double_iac = FALSE; unsigned char text[1024]; int text_len=0; if(cfg->line_data.is_telnet && cfg->line_data.nvt_data.binary_xmit) { retval = 0; while(iline_data.fd,text,text_len); text_len = 0; } } if(text_len) { retval = ip_write(cfg->line_data.fd,text,text_len); } return retval; } return ip_write(cfg->line_data.fd,data,len); } int line_listen(modem_config *cfg) { return 0; } int line_off_hook(modem_config *cfg) { return 0; } int line_connect(modem_config *cfg) { unsigned char* addy=cfg->dialno; LOG(LOG_INFO,"Connecting"); addy = pb_search(addy); cfg->line_data.fd=ip_connect(addy); if(cfg->line_data.fd > -1) { LOG(LOG_ALL,"Connected to %s",addy); cfg->line_data.valid_conn = TRUE; return 0; } else { LOG(LOG_ALL,"Could not connect to %s",addy); cfg->line_data.valid_conn = FALSE; return -1; } } int line_disconnect(modem_config *cfg) { LOG(LOG_INFO,"Disconnecting"); if(cfg->data.direct_conn == TRUE) { LOG(LOG_INFO,"Direct connection active, maintaining link"); return -1; } else { cfg->line_data.is_telnet=FALSE; cfg->line_data.first_char=TRUE; if(cfg->line_data.valid_conn == TRUE) { ip_disconnect(cfg->line_data.fd); cfg->line_data.valid_conn=FALSE; } } return 0; } tcpser/src/.svn/text-base/line.h.svn-base0100444000076400010400000000064410066734602021425 0ustar brainAdministrators#ifndef LINE_H #define LINE_H 1 int line_init(void); int line_init_conn(modem_config *cfg); int line_init_config(modem_config *cfg); int line_read(modem_config *cfg,unsigned char* data,int len); int line_write(modem_config *cfg,unsigned char* data,int len); int line_listen(modem_config *cfg); int line_off_hook(modem_config *cfg); int line_connect(modem_config *cfg); int line_disconnect(modem_config *cfg); #endif tcpser/src/.svn/text-base/modem_core.c.svn-base0100444000076400010400000003765310212677710022613 0ustar brainAdministrators#include #include // for atoi #include "getcmd.h" #include "debug.h" #include "modem_core.h" unsigned char* mdm_responses[37]; int mdm_init() { mdm_responses[MDM_RESP_OK]="OK"; mdm_responses[MDM_RESP_RING]="RING"; mdm_responses[MDM_RESP_ERROR]="ERROR"; mdm_responses[MDM_RESP_CONNECT]="CONNECT"; mdm_responses[MDM_RESP_NO_CARRIER]="NO CARRIER"; mdm_responses[MDM_RESP_CONNECT_1200] = "CONNECT 1200"; mdm_responses[MDM_RESP_NO_DIALTONE] = "NO DIALTONE"; mdm_responses[MDM_RESP_BUSY] = "BUSY"; mdm_responses[MDM_RESP_NO_ANSWER] = "NO ANSWER"; mdm_responses[MDM_RESP_CONNECT_0600] = "CONNECT 0600"; mdm_responses[MDM_RESP_CONNECT_2400] = "CONNECT 2400"; mdm_responses[MDM_RESP_CONNECT_4800] = "CONNECT 4800"; mdm_responses[MDM_RESP_CONNECT_9600] = "CONNECT 9600"; mdm_responses[MDM_RESP_CONNECT_7200] = "CONNECT 7200"; mdm_responses[MDM_RESP_CONNECT_12000] = "CONNECT 12000"; mdm_responses[MDM_RESP_CONNECT_14400] = "CONNECT 14400"; mdm_responses[MDM_RESP_CONNECT_19200] = "CONNECT 19200"; mdm_responses[MDM_RESP_CONNECT_38400] = "CONNECT 38400"; mdm_responses[MDM_RESP_CONNECT_57600] = "CONNECT 57600"; mdm_responses[MDM_RESP_CONNECT_115200] = "CONNECT 115200"; mdm_responses[MDM_RESP_CONNECT_234000]="CONNECT 230400"; return 0; } int get_connect_response(int speed, int level) { if(level == 0) { return MDM_RESP_CONNECT; } switch (speed) { case 115200: return MDM_RESP_CONNECT_115200; case 57600: return MDM_RESP_CONNECT_57600; case 38400: return MDM_RESP_CONNECT_38400; case 19200: return MDM_RESP_CONNECT_19200; case 9600: return MDM_RESP_CONNECT_9600; case 4800: return MDM_RESP_CONNECT_4800; case 2400: return MDM_RESP_CONNECT_2400; case 1200: return MDM_RESP_CONNECT_1200; case 600: return MDM_RESP_CONNECT_0600; } return MDM_RESP_CONNECT; } void mdm_init_config(modem_config* cfg) { int i=0; cfg->send_responses=TRUE; cfg->connect_response=0; cfg->response_code_level=4; cfg->text_responses=TRUE; cfg->echo=TRUE; cfg->cmd_mode=TRUE; cfg->conn_type=MDM_CONN_NONE; cfg->off_hook=FALSE; cfg->line_ringing=FALSE; cfg->cur_line_idx=0; for(i=0;i<100;i++) { cfg->s[i]=0; } cfg->s[2]=43; cfg->s[3]=13; cfg->s[4]=10; cfg->s[5]=8; cfg->s[6]=2; cfg->s[7]=50; cfg->s[8]=2; cfg->s[9]=6; cfg->s[10]=14; cfg->s[11]=95; cfg->s[12]=50; cfg->crlf[0]=cfg->s[3]; cfg->crlf[1]=cfg->s[4]; cfg->crlf[2]=0; cfg->dial_type=0; cfg->last_dial_type=0; cfg->disconnect_delay=0; cfg->pre_break_delay=FALSE; cfg->break_len=0; cfg->memory_dial=FALSE; cfg->dsr_active=FALSE; cfg->dsr_on=TRUE; cfg->dcd_on=FALSE; cfg->found_a=FALSE; cfg->cmd_started=FALSE; cfg->allow_transmit=TRUE; cfg->invert_dsr=FALSE; cfg->invert_dcd=FALSE; cfg->config0[0]='\0'; cfg->config1[0]='\0'; dce_init_config(cfg); sh_init_config(cfg); line_init_config(cfg); } int get_new_cts_state(modem_config *cfg, int up) { return MDM_CL_CTS_HIGH; } int get_new_dsr_state(modem_config *cfg, int up) { if(cfg->dsr_on == TRUE) return (cfg->invert_dsr == TRUE?MDM_CL_DSR_LOW:MDM_CL_DSR_HIGH); if((up == TRUE && cfg->invert_dsr == FALSE) || (up == FALSE && cfg->invert_dsr==TRUE) ) return MDM_CL_DSR_HIGH; else return MDM_CL_DSR_LOW; } int get_new_dcd_state(modem_config *cfg, int up) { if(cfg->dcd_on == TRUE) return (cfg->invert_dcd == TRUE?MDM_CL_DCD_LOW:MDM_CL_DCD_HIGH); if((up == TRUE && cfg->invert_dcd == FALSE) || (up == FALSE && cfg->invert_dcd==TRUE) ) return MDM_CL_DCD_HIGH; else return MDM_CL_DCD_LOW; } int mdm_set_control_lines(modem_config *cfg) { int state=0; int up=(cfg->conn_type == MDM_CONN_NONE?FALSE:TRUE); state |=get_new_cts_state(cfg,up); state |=get_new_dsr_state(cfg,up); state |=get_new_dcd_state(cfg,up); LOG(LOG_INFO,"Control Lines: DSR:%d DCD:%d CTS:%d", ((state & MDM_CL_DSR_HIGH) != 0?1:0), ((state & MDM_CL_DCD_HIGH) != 0?1:0), ((state & MDM_CL_CTS_HIGH) != 0?1:0) ); dce_set_control_lines(cfg,state); return 0; } void mdm_write_char(modem_config *cfg,unsigned char data) { unsigned char str[2]; str[0]=data; mdm_write(cfg,str,1); } void mdm_write(modem_config *cfg,unsigned char data[], int len) { if(cfg->allow_transmit == TRUE) { dce_write(cfg,data,len); } } void mdm_send_response(int msg,modem_config *cfg) { unsigned char msgID[17]; LOG(LOG_DEBUG,"Sending %s response to modem",mdm_responses[msg]); if(cfg->send_responses==TRUE) { mdm_write(cfg,cfg->crlf,2); if(cfg->text_responses==TRUE) { LOG(LOG_ALL,"Sending text response"); mdm_write(cfg,mdm_responses[msg],strlen(mdm_responses[msg])); } else { LOG(LOG_ALL,"Sending numeric response"); sprintf(msgID,"%d",msg); mdm_write(cfg,msgID,strlen(msgID)); } mdm_write(cfg,cfg->crlf,2); } } int mdm_off_hook(modem_config *cfg) { LOG(LOG_INFO,"taking modem off hook"); cfg->off_hook=TRUE; cfg->cmd_mode=FALSE; line_off_hook(cfg); return 0; } int mdm_answer(modem_config *cfg) { if(cfg->line_ringing == TRUE) { cfg->conn_type=MDM_CONN_INCOMING; mdm_off_hook(cfg); mdm_set_control_lines(cfg); mdm_print_speed(cfg); } else if(cfg->conn_type == MDM_CONN_INCOMING) { // we are connected, just go off hook. mdm_off_hook(cfg); mdm_set_control_lines(cfg); } else { mdm_disconnect(cfg); } return 0; } int mdm_print_speed(modem_config *cfg) { int speed; switch(cfg->connect_response) { case 2: speed=cfg->dte_speed; break; default: speed=cfg->dce_speed; break; } mdm_send_response(get_connect_response(speed,cfg->response_code_level),cfg); return 0; } int mdm_connect(modem_config* cfg) { mdm_off_hook(cfg); if(cfg->conn_type == MDM_CONN_NONE) { if(line_connect(cfg) == 0) { cfg->conn_type=MDM_CONN_OUTGOING; mdm_set_control_lines(cfg); mdm_print_speed(cfg); } else { cfg->conn_type=MDM_CONN_OUTGOING; // so disconnect will print NO CARRIER mdm_disconnect(cfg); } } return 0; } int mdm_listen(modem_config *cfg) { return line_listen(cfg); } int mdm_disconnect(modem_config* cfg) { int type; LOG_ENTER(); LOG(LOG_INFO,"Disconnecting modem"); cfg->cmd_mode=TRUE; cfg->off_hook=FALSE; cfg->break_len=0; cfg->line_ringing = FALSE; cfg->pre_break_delay=FALSE; if(0 == line_disconnect(cfg)) { type=cfg->conn_type; cfg->conn_type=MDM_CONN_NONE; mdm_set_control_lines(cfg); if(type != MDM_CONN_NONE) { mdm_send_response(MDM_RESP_NO_CARRIER,cfg); usleep(cfg->disconnect_delay * 1000); } cfg->rings=0; mdm_listen(cfg); } else { // line still connected. } LOG_EXIT(); return 0; } int mdm_parse_cmd(modem_config* cfg) { int done=FALSE; int index=0; int num=0; int start=0; int end=0; int cmd=AT_CMD_NONE; unsigned char* command=cfg->cur_line; unsigned char tmp[256]; LOG_ENTER(); LOG(LOG_DEBUG,"Evaluating AT%s",command); while(TRUE != done ) { if(cmd != AT_CMD_ERR) { cmd=getcmd(command,&index,&num, &start,&end); LOG(LOG_DEBUG,"Command: %c (%d), Flags: %d, index=%d, num=%d, data=%d-%d", (cmd > -1?cmd & 0xff:' '), cmd, cmd >> 8, index, num, start, end ); } switch(cmd) { case AT_CMD_ERR: mdm_send_response(MDM_RESP_ERROR,cfg); done=TRUE; break; case AT_CMD_END: if(cfg->cmd_mode == TRUE) mdm_send_response(MDM_RESP_OK,cfg); done=TRUE; break; case AT_CMD_NONE: done=TRUE; break; case 'O': case 'A': mdm_answer(cfg); cmd=AT_CMD_END; done=TRUE; break; case 'B': // 212A versus V.22 connection if(num > 1) { cmd=AT_CMD_ERR; } else { //cfg->connect_1200=num; } break; case 'D': if(end>start) { strncpy(cfg->dialno,command+start,end-start); cfg->dialno[end-start]='\0'; cfg->dial_type=(unsigned char)num; cfg->last_dial_type=(unsigned char)num; strncpy(cfg->last_dialno,command+start,end-start); cfg->last_dialno[end-start]='\0'; cfg->memory_dial=FALSE; } else if (num == 'L') { strncpy(cfg->dialno,cfg->last_dialno,strlen(cfg->last_dialno)); cfg->dial_type=cfg->dial_type; cfg->memory_dial=TRUE; mdm_write(cfg,cfg->crlf,2); mdm_write(cfg,cfg->dialno,strlen(cfg->dialno)); } else { cfg->dialno[0]=0; cfg->last_dialno[0]=0; cfg->dial_type=0; cfg->last_dial_type=0; } if(strlen(cfg->dialno) > 0) { mdm_connect(cfg); } else { mdm_off_hook(cfg); } done=TRUE; break; case 'E': // still need to define #2 if(num == 0) cfg->echo=FALSE; else if(num == 1) cfg->echo=TRUE; else { cmd=AT_CMD_ERR; } break; case 'H': if(num == 0) { mdm_disconnect(cfg); } else if(num == 1) { mdm_answer(cfg); } else cmd=AT_CMD_ERR; break; case 'I': // Information. break; case 'L': // Speaker volume if(num < 1 || num > 3) cmd=AT_CMD_ERR; else { //cfg->volume=num; } break; case 'M': // speaker settings if(num > 3) cmd=AT_CMD_ERR; else { //cfg->speaker_setting=num; } break; case 'N': // automode negotiate if(num > 1) cmd=AT_CMD_ERR; else { //cfg->auto_mode=num; } break; case 'P': // defaut to pulse dialing //cfg->default_dial_type=MDM_DT_PULSE; break; case 'Q': // still need to define #2 if(num == 0) cfg->send_responses=TRUE; else if(num == 1) cfg->send_responses=FALSE; else if(num == 2) // this should be yes orig/no answer. cfg->send_responses=TRUE; else { cmd=AT_CMD_ERR; } break; case 'S': strncpy(tmp,command+start,end-start); tmp[end-start]='\0'; cfg->s[num]=atoi(tmp); switch(num) { case 3: cfg->crlf[0]=cfg->s[3]; break; case 4: cfg->crlf[1]=cfg->s[4]; break; } break; case AT_CMD_FLAG_QUERY | 'S': sprintf(tmp,"%s%3.3d",cfg->crlf,cfg->s[num]); mdm_write(cfg,tmp,strlen(tmp)); break; case 'T': // defaut to tone dialing //cfg->default_dial_type=MDM_DT_TONE; break; case 'V': // done if(num == 0) cfg->text_responses=FALSE; else if(num ==1) cfg->text_responses=TRUE; else { cmd=AT_CMD_ERR; } break; case 'W': if(num > -1 && num < 3) cfg->connect_response=num; else cmd=AT_CMD_ERR; break; case 'X': if(num > -1 && num < 5) cfg->response_code_level=num; else cmd=AT_CMD_ERR; break; case 'Y': // long space disconnect. if(num > 1) cmd=AT_CMD_ERR; else { //cfg->long_disconnect=num; } break; case 'Z': // long space disconnect. if(num > 1) cmd=AT_CMD_ERR; else { // set config0 to cur_line and go. } break; case AT_CMD_FLAG_EXT + 'C': switch(num) { case 0: cfg->dcd_on=TRUE; mdm_set_control_lines(cfg); break; case 1: cfg->dcd_on=FALSE; mdm_set_control_lines(cfg); break; default: cmd=AT_CMD_ERR; break; } break; case AT_CMD_FLAG_EXT + 'K': // flow control. switch (num) { case 0: dce_set_flow_control(cfg,0); break; case 3: dce_set_flow_control(cfg,MDM_FC_RTS); break; case 4: dce_set_flow_control(cfg,MDM_FC_XON); break; case 5: dce_set_flow_control(cfg,MDM_FC_XON); // need to add passthrough.. Not sure how. break; case 6: dce_set_flow_control(cfg,MDM_FC_XON | MDM_FC_RTS); break; default: cmd=AT_CMD_ERR; break; } break; default: break; } } cfg->cur_line_idx=0; return cmd; } int mdm_handle_char(modem_config* cfg, unsigned char ch) { if(cfg->echo == TRUE) mdm_write_char(cfg,ch); if(cfg->cmd_started == TRUE) { if(ch == (unsigned char)(cfg->s[5])) { if(cfg->cur_line_idx == 0 && cfg->echo == TRUE) { mdm_write_char(cfg,'T'); } else { cfg->cur_line_idx--; } } else if(ch == (unsigned char)(cfg->s[3])) { // we have a line, process. cfg->cur_line[cfg->cur_line_idx] = 0; strncpy(cfg->last_cmd,cfg->cur_line,sizeof(cfg->last_cmd) - 1); mdm_parse_cmd(cfg); cfg->found_a=FALSE; cfg->cmd_started=FALSE; } else { cfg->cur_line[cfg->cur_line_idx++ % sizeof(cfg->cur_line)]=ch; } } else if(cfg->found_a == TRUE) { if(ch == 't' || ch == 'T') { cfg->cmd_started=TRUE; LOG(LOG_ALL,"'T' parsed in serial stream, switching to command parse mode"); } else if(ch == '/') { LOG(LOG_ALL,"'/' parsed in the serial stream, replaying last command"); cfg->cur_line_idx=strlen(cfg->last_cmd); strncpy(cfg->cur_line,cfg->last_cmd,cfg->cur_line_idx); mdm_parse_cmd(cfg); cfg->cmd_started=FALSE; } else if(ch!='a' && ch!='A') { cfg->found_a=FALSE; } } else if(ch == 'a' || ch == 'A') { LOG(LOG_ALL,"'A' parsed in serial stream"); cfg->found_a=TRUE; } return 0; } int mdm_clear_break(modem_config* cfg) { cfg->break_len=0; cfg->pre_break_delay=FALSE; return 0; } int mdm_parse_data(modem_config* cfg,unsigned char* data, int len) { int i; if(cfg->cmd_mode==TRUE) { for(i=0;ipre_break_delay == TRUE) { for(i=0;is[2]) { LOG(LOG_DEBUG,"Break character received"); cfg->break_len++; if(cfg->break_len > 3) { // more than 3, considered invalid cfg->pre_break_delay=FALSE; cfg->break_len=0; } } else { LOG(LOG_ALL,"Found non-break character, cancelling break"); // chars past +++ mdm_clear_break(cfg); } } } } return 0; } int mdm_handle_timeout(modem_config* cfg) { if(cfg->pre_break_delay == TRUE && cfg->break_len == 3) { // pre and post break. LOG(LOG_INFO,"Break condition detected"); cfg->cmd_mode=TRUE; mdm_send_response(MDM_RESP_OK,cfg); mdm_clear_break(cfg); } else if(cfg->pre_break_delay == FALSE) { // pre break wait over. LOG(LOG_DEBUG,"Initial Break Delay detected"); cfg->pre_break_delay=TRUE; } else if(cfg->pre_break_delay == TRUE && cfg->break_len > 0 ) { LOG(LOG_ALL,"Inter-break-char delay time exceeded"); mdm_clear_break(cfg); } else if(cfg->s[30] != 0) { // timeout... LOG(LOG_INFO,"DTE communication inactivity timeout"); mdm_disconnect(cfg); } return 0; } int mdm_send_ring(modem_config *cfg) { LOG(LOG_DEBUG,"Sending 'RING' to modem"); cfg->line_ringing = TRUE; mdm_send_response(MDM_RESP_RING,cfg); cfg->rings++; LOG(LOG_ALL,"Sent #%d ring",cfg->rings); if(cfg->cmd_mode == FALSE || (cfg->s[0] != 0 &&cfg->rings>=cfg->s[0])) { mdm_answer(cfg); } return 0; } tcpser/src/.svn/text-base/modem_core.h.svn-base0100444000076400010400000000745610443647776022635 0ustar brainAdministrators#ifndef MODEM_CORE_H #define MODEM_CORE_H 1 #define MDM_RESP_OK 0 #define MDM_RESP_CONNECT 1 #define MDM_RESP_RING 2 #define MDM_RESP_NO_CARRIER 3 #define MDM_RESP_ERROR 4 #define MDM_RESP_CONNECT_1200 5 #define MDM_RESP_NO_DIALTONE 6 #define MDM_RESP_BUSY 7 #define MDM_RESP_NO_ANSWER 8 #define MDM_RESP_CONNECT_0600 9 #define MDM_RESP_CONNECT_2400 10 #define MDM_RESP_CONNECT_4800 11 #define MDM_RESP_CONNECT_9600 12 #define MDM_RESP_CONNECT_7200 13 #define MDM_RESP_CONNECT_12000 14 #define MDM_RESP_CONNECT_14400 15 #define MDM_RESP_CONNECT_19200 16 #define MDM_RESP_CONNECT_38400 17 #define MDM_RESP_CONNECT_57600 18 #define MDM_RESP_CONNECT_115200 19 #define MDM_RESP_CONNECT_234000 20 #define MDM_CL_DSR_LOW 0 #define MDM_CL_DSR_HIGH 1 #define MDM_CL_DCD_LOW 0 #define MDM_CL_DCD_HIGH 2 #define MDM_CL_CTS_LOW 0 #define MDM_CL_CTS_HIGH 4 #define MDM_CL_DTR_LOW 0 #define MDM_CL_DTR_HIGH 8 #define MDM_FC_RTS 1 #define MDM_FC_XON 2 #define MDM_CONN_NONE 0 #define MDM_CONN_OUTGOING 1 #define MDM_CONN_INCOMING 2 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #include "nvt.h" #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif typedef struct line_config { int valid_conn; int fd; int sfd; int is_telnet; int first_char; nvt_vars nvt_data; } line_config; typedef struct x_config { int mp[2][2]; int cp[2][2]; int wp[2][2]; unsigned char no_answer[256]; unsigned char local_connect[256]; unsigned char remote_connect[256]; unsigned char local_answer[256]; unsigned char remote_answer[256]; unsigned char inactive[256]; unsigned int direct_conn; unsigned char direct_conn_num[256]; } x_config; typedef struct dce_config { int is_ip232; unsigned char tty[256]; int first_char; int fd; int dp[2][2]; int sSocket; int ip232_is_connected; int ip232_dtr; int ip232_dcd; int ip232_iac; } dce_config; typedef struct modem_config { // master configuration information // need to eventually change these dce_config dce_data; line_config line_data; x_config data; unsigned char config0[1024]; unsigned char config1[1024]; int dce_speed; int dte_speed; int conn_type; int line_ringing; int off_hook; int dsr_active; int dsr_on; int dcd_on; int invert_dsr; int invert_dcd; int allow_transmit; int rings; // command information int pre_break_delay; int found_a; int cmd_started; int cmd_mode; unsigned char last_cmd[1024]; unsigned char cur_line[1024]; int cur_line_idx; // dailing information unsigned char dialno[256]; unsigned char last_dialno[256]; unsigned char dial_type; unsigned char last_dial_type; int memory_dial; // modem config int connect_response; int response_code_level; int send_responses; int text_responses; int echo; int s[100]; int break_len; int disconnect_delay; unsigned char crlf[3]; } modem_config; int mdm_init(void); void mdm_init_config(modem_config* cfg); int get_new_cts_state(modem_config *cfg, int up); int get_new_dsr_state(modem_config *cfg, int up); int get_new_dcd_state(modem_config *cfg, int up); int mdm_set_control_lines(modem_config *cfg); void mdm_write_char(modem_config *cfg,unsigned char data); void mdm_write(modem_config *cfg,unsigned char data[], int len); void mdm_send_response(int msg,modem_config *cfg); int mdm_off_hook(modem_config *cfg); int mdm_answer(modem_config *cfg); int mdm_print_speed(modem_config *cfg); int mdm_connect(modem_config* cfg); int mdm_listen(modem_config *cfg); int mdm_disconnect(modem_config* cfg); int mdm_parse_cmd(modem_config* cfg); int mdm_handle_char(modem_config* cfg, unsigned char ch); int mdm_clear_break(modem_config* cfg); int mdm_parse_data(modem_config* cfg,unsigned char* data, int len); int mdm_handle_timeout(modem_config* cfg); int mdm_send_ring(modem_config *cfg); #include "line.h" #include "shared.h" #include "dce.h" #endif tcpser/src/.svn/text-base/nvt.c.svn-base0100444000076400010400000000722410414144530021271 0ustar brainAdministrators#include #include "debug.h" #include "ip.h" #include "nvt.h" int nvt_init_config(nvt_vars *vars) { int i; vars->binary_xmit = FALSE; vars->binary_recv = FALSE; for (i = 0; i < 256; i++) vars->term[i] = 0; return 0; } unsigned char get_nvt_cmd_response(unsigned char action, unsigned char type) { unsigned char rc=0; if(type == TRUE) { switch (action) { case NVT_DO: rc=NVT_WILL_RESP; break; case NVT_DONT: rc=NVT_WONT_RESP; break; case NVT_WILL: rc=NVT_DO_RESP; break; case NVT_WONT: rc=NVT_DONT_RESP; break; } } else { switch (action) { case NVT_DO: case NVT_DONT: rc=NVT_WONT_RESP; break; case NVT_WILL: case NVT_WONT: rc=NVT_DONT_RESP; break; } } return rc; } int parse_nvt_subcommand(int fd, nvt_vars *vars , unsigned char * data, int len) { // overflow issue, again... int opt=data[2]; unsigned char resp[100]; unsigned char *response = resp + 3; int resp_len = 0; int response_len = 0; unsigned char tty_type[]="VT100"; int rc; int slen=0; for (rc = 2; rc < len - 1; rc++) { if (NVT_IAC == data[rc]) if (NVT_SE == data[rc + 1]) { rc += 2; break; } } if (rc > 5 && (NVT_SB_SEND == data[4])) { switch(opt) { case NVT_OPT_TERMINAL_TYPE: case NVT_OPT_X_DISPLAY_LOCATION: // should not have to have these case NVT_OPT_ENVIRON: // but telnet seems to expect. case NVT_OPT_NEW_ENVIRON: // them. case NVT_OPT_TERMINAL_SPEED: response[response_len++] = NVT_SB_IS; switch(opt) { case NVT_OPT_TERMINAL_TYPE: slen=strlen(tty_type); strncpy(response + response_len,tty_type,slen); response_len += slen; break; } break; } } if (response_len) { resp[resp_len++]=NVT_IAC; resp[resp_len++]=NVT_SB; resp[resp_len++]=opt; resp_len += response_len; resp[resp_len++]=NVT_IAC; resp[resp_len++]=NVT_SE; ip_write(fd,resp,resp_len); } return rc; } int send_nvt_command(int fd, nvt_vars *vars, unsigned char action, unsigned char opt) { unsigned char cmd[3]; cmd[0]= NVT_IAC; cmd[1] = action; cmd[2]= opt; ip_write(fd,cmd,3); vars->term[opt] = action; return 0; } int parse_nvt_command(int fd, nvt_vars *vars, unsigned char action, unsigned char opt) { unsigned char resp[3]; resp[0]= NVT_IAC; resp[2]= opt; switch (opt) { case NVT_OPT_TRANSMIT_BINARY : switch (action) { case NVT_DO : LOG(LOG_INFO,"Enabling telnet binary xmit"); vars->binary_xmit = TRUE; break; case NVT_DONT : LOG(LOG_INFO,"Disabling telnet binary xmit"); vars->binary_xmit = FALSE; break; case NVT_WILL : LOG(LOG_INFO,"Enabling telnet binary recv"); vars->binary_recv = TRUE; break; case NVT_WONT : LOG(LOG_INFO,"Disabling telnet binary recv"); vars->binary_recv = FALSE; break; } // fall through to get response case NVT_OPT_NAWS: case NVT_OPT_TERMINAL_TYPE: case NVT_OPT_SUPPRESS_GO_AHEAD: case NVT_OPT_ECHO: case NVT_OPT_X_DISPLAY_LOCATION: // should not have to have these case NVT_OPT_ENVIRON: // but telnet seems to expect. case NVT_OPT_NEW_ENVIRON: // them. case NVT_OPT_TERMINAL_SPEED: resp[1] = get_nvt_cmd_response(action,TRUE); break; default: resp[1] = get_nvt_cmd_response(action,FALSE); break; } ip_write(fd,resp,3); return 0; } tcpser/src/.svn/text-base/nvt.h.svn-base0100444000076400010400000000243210413606554021302 0ustar brainAdministrators#ifndef NVT_H #define NVT_H 1 #define NVT_SE 240 #define NVT_NOP 241 #define NVT_DM 242 #define NVT_SB 250 #define NVT_WILL 251 #define NVT_WONT 252 #define NVT_DO 253 #define NVT_DONT 254 #define NVT_IAC 255 #define NVT_WILL_RESP 251 #define NVT_WONT_RESP 252 #define NVT_DO_RESP 253 #define NVT_DONT_RESP 254 #define NVT_OPT_TRANSMIT_BINARY 0 #define NVT_OPT_ECHO 1 #define NVT_OPT_SUPPRESS_GO_AHEAD 3 #define NVT_OPT_STATUS 5 #define NVT_OPT_RCTE 7 #define NVT_OPT_TIMING_MARK 6 #define NVT_OPT_NAOCRD 10 #define NVT_OPT_TERMINAL_TYPE 24 #define NVT_OPT_NAWS 31 #define NVT_OPT_TERMINAL_SPEED 32 #define NVT_OPT_LINEMODE 34 #define NVT_OPT_X_DISPLAY_LOCATION 35 #define NVT_OPT_ENVIRON 36 #define NVT_OPT_NEW_ENVIRON 39 #define NVT_SB_IS 0 #define NVT_SB_SEND 1 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif typedef struct nvt_vars { int binary_xmit; int binary_recv; unsigned char term[256]; } nvt_vars; unsigned char get_nvt_cmd_response(unsigned char action, unsigned char type); int parse_nvt_subcommand(int fd, nvt_vars *vars , unsigned char * data, int len); int parse_nvt_command(int fd, nvt_vars *vars, unsigned char action, unsigned char opt); int nvt_init_config(nvt_vars *vars); int send_nvt_command(int fd, nvt_vars *vars, unsigned char action, unsigned char opt); #endif tcpser/src/.svn/text-base/phone_book.c.svn-base0100444000076400010400000000165010313717126022607 0ustar brainAdministrators#include #include #include "phone_book.h" #include "debug.h" #define PBSIZE 100 unsigned char phone_book[PBSIZE][2][128]; int size=0; int pb_init() { return 0; } int pb_add(unsigned char* from,unsigned char* to) { LOG_ENTER(); if(size < PBSIZE && from != NULL && to != NULL && strlen(from) > 0 && strlen(to) > 0 ) { // should really trim spaces. strncpy(phone_book[size][0],from,sizeof(phone_book[size][0])); strncpy(phone_book[size][1],to,sizeof(phone_book[size][1])); size++; LOG_EXIT(); return 0; } LOG_EXIT(); return -1; } unsigned char* pb_search(unsigned char *number) { int i=0; LOG_ENTER(); for(i=0;i #include #include #include #include #include #include "debug.h" #include "serial.h" int ser_get_bps_const(int speed) { int bps_rate=0; LOG_ENTER(); LOG(LOG_DEBUG,"Checking speed: %d",speed); switch (speed) { case 115200: bps_rate=B115200; break; case 57600: bps_rate=B57600; break; case 38400: bps_rate=B38400; break; case 19200: bps_rate=B19200; break; case 9600: bps_rate=B9600; break; case 4800: bps_rate=B4800; break; case 2400: bps_rate=B2400; break; case 1200: bps_rate=B1200; break; case 600: bps_rate=B600; break; case 300: bps_rate=B300; break; case 150: bps_rate=B150; break; case 134: bps_rate=B134; break; case 110: bps_rate=B110; break; case 75: bps_rate=B75; break; case 50: bps_rate=B50; break; case 0: bps_rate=B0; break; default: ELOG(LOG_FATAL,"Unknown baud rate"); bps_rate=-1; } LOG_EXIT(); return bps_rate; } int ser_init_conn(unsigned char* tty, int speed) { int fd = -1; struct termios tio; int bps_rate=0; LOG_ENTER(); bps_rate=ser_get_bps_const(speed); if(bps_rate > -1) { /* open the device to be non-blocking (read will return immediatly) */ LOG(LOG_INFO,"Opening serial device"); fd = open(tty, O_RDWR | O_NOCTTY); if (fd <0) { ELOG(LOG_FATAL,"TTY %s could not be opened",tty); } else { LOG(LOG_INFO,"Opened serial device %s at speed %d as fd %d",tty,speed,fd); /* Make the file descriptor asynchronous (the manual page says only O_APPEND and O_NONBLOCK, will work with F_SETFL...) */ fcntl(fd, F_SETFL, FASYNC); tio.c_cflag = bps_rate | CS8 | CLOCAL | CREAD | CRTSCTS; tio.c_iflag = (IGNBRK); tio.c_oflag = 0; tio.c_lflag = 0; tio.c_cc[VMIN]=1; tio.c_cc[VTIME]=0; tcflush(fd, TCIFLUSH); cfsetispeed(&tio, bps_rate); cfsetospeed(&tio, bps_rate); tcsetattr(fd,TCSANOW,&tio); LOG(LOG_INFO,"serial device configured"); } } LOG_EXIT(); return fd; } int ser_set_flow_control(int fd, int status) { struct termios tio; if(0 != tcgetattr(fd,&tio)) { ELOG(LOG_FATAL,"Could not get serial port attributes"); return -1; } // turn all off. tio.c_cflag &= ~(IXON | IXOFF | CRTSCTS); tio.c_cflag |= status; if(0 != tcsetattr(fd,TCSANOW,&tio)) { ELOG(LOG_FATAL,"Could not set serial port attributes"); return -1; } return 0; } int ser_get_control_lines(int fd) { int status; if(0 > ioctl(fd, TIOCMGET, &status)) { ELOG(LOG_FATAL,"Could not obtain serial port status"); return -1; } return status; } int ser_set_control_lines(int fd, int state) { unsigned int status; if(0 > (status=ser_get_control_lines(fd))) { return status; } status &= ~(TIOCM_RTS | TIOCM_DTR); status |= state; if(0 > ioctl(fd, TIOCMSET, &status)) { #ifndef WIN32 ELOG(LOG_FATAL,"Could not set serial port status"); return -1; #else ELOG(LOG_WARN,"Could not set serial port status, CYGWIN bug?"); #endif } return 0; } int ser_write(int fd, unsigned char* data,int len) { log_trace(TRACE_MODEM_OUT,data,len); return write(fd,data,len); } int ser_read(int fd, unsigned char* data, int len) { int res; res=read(fd,data,len); log_trace(TRACE_MODEM_IN,data,res); return res; } tcpser/src/.svn/text-base/serial.h.svn-base0100444000076400010400000000063410066734602021754 0ustar brainAdministrators#ifndef SERIAL_H #define SERIAL_H 1 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif int ser_get_bps_const(int speed); int ser_init_conn(unsigned char* tty, int speed); int ser_set_flow_control(int fd, int status); int ser_get_control_lines(int fd); int ser_set_control_lines(int fd, int state); int ser_write(int fd, unsigned char* data,int len); int ser_read(int fd, unsigned char* data, int len); #endif tcpser/src/.svn/text-base/shared.c.svn-base0100444000076400010400000000051010103117006021710 0ustar brainAdministrators#include "modem_core.h" int sh_init_config(modem_config *cfg) { cfg->data.local_connect[0]=0; cfg->data.remote_connect[0]=0; cfg->data.local_answer[0]=0; cfg->data.remote_answer[0]=0; cfg->data.no_answer[0]=0; cfg->data.inactive[0]=0; cfg->data.direct_conn=FALSE; cfg->data.direct_conn_num[0]=0; return 0; } tcpser/src/.svn/text-base/shared.h.svn-base0100444000076400010400000000012510066734602021736 0ustar brainAdministrators#ifndef SHARED_H #define SHARED_H 1 int sh_init_config(modem_config *cfg); #endif tcpser/src/.svn/text-base/tcpmdm.c.svn-base0100444000076400010400000000505310066734602021754 0ustar brainAdministrators#include #include #include #include #include #include #include "serial.h" #include "ip.h" #include "debug.h" #include "tcpser.h" int main(int argc, char* argv[]) { struct timeval timer; struct timeval* ptimer; unsigned char tty[255]="/dev/ttyS2"; //unsigned char addy[255]="dilbert:6400"; unsigned char init[255]="at"; unsigned char cr[1]="\x0d"; int speed=38400; int sfd=-1; int csd=-1; //int ssd=-1; int max_fd=0; fd_set readfs; int res=0; unsigned char buf[255]; int rc; log_init(); log_set_trace_flags(TRACE_MODEM_IN | TRACE_MODEM_OUT); log_set_level(7); // open serial port // config serial port if(0 > (sfd = ser_init_conn(tty,speed))) { ELOG(LOG_FATAL,"Could not open serial port"); exit(-1); } // send init string if(strlen(init) > 0) { ser_write(sfd,init,strlen(init)); ser_write(sfd,cr,1); } // if configured, listen on ip address // check for carrier detect line // when line goes high, connect to IP:port // when line goes low, disconnect for(;;) { FD_ZERO(&readfs); max_fd=sfd; FD_SET(sfd, &readfs); if(-1 < csd) { // we are connected. max_fd=MAX(max_fd,csd); FD_SET(csd, &readfs); } max_fd++; timer.tv_sec=0; timer.tv_usec=1000; ptimer=&timer; LOG(LOG_ALL,"csd=%d",csd); rc=select(max_fd, &readfs, NULL, NULL, ptimer); if(-1 == rc) { ELOG(LOG_WARN,"Select returned error"); } else if (0 == rc) { // timer popped. if(-1 == csd && (ser_get_control_lines(sfd) & TIOCM_CD) > 0) { // we need to connect // commented out for now. //csd=ip_connect(addy); } else if(-1 < csd && (ser_get_control_lines(sfd) & TIOCM_CD) == 0) { // we need to disconnect. ip_disconnect(csd); csd=-1; } } else if(rc > 0) { // we got data from someone. if (FD_ISSET(sfd,&readfs)) { // serial port LOG(LOG_DEBUG,"Data available on serial port"); res = ser_read(sfd,buf,sizeof(buf) -1); if(res > 0 && csd > -1) { ip_write(csd,buf,res); } } if (csd > -1 && FD_ISSET(csd,&readfs)) { // ip port LOG(LOG_DEBUG,"Data available on tcp/ip port"); res = ip_read(sfd,buf,sizeof(buf) -1); if(res==0) { // conn closed, disconnect. ip_disconnect(csd); csd=-1; } if(res > 0 && csd > -1) { ser_write(csd,buf,res); } } } } } tcpser/src/.svn/text-base/tcpmdm.h.svn-base0100444000076400010400000000000110066734602021745 0ustar brainAdministrators tcpser/src/.svn/text-base/tcpser.c.svn-base0100444000076400010400000000715710212675046021776 0ustar brainAdministrators#include #include #include #include #include #include #include "init.h" #include "ip.h" #include "modem_core.h" #include "bridge.h" #include "phone_book.h" #include "util.h" #include "debug.h" #include "tcpmdm.h" const unsigned char MDM_BUSY[]="BUSY\n"; int main(int argc, char *argv[]) { modem_config cfg[64]; int modem_count; int port=0; unsigned char all_busy[255]; pthread_t thread_id; int i; int rc; int sSocket = 0; fd_set readfs; int max_fd=0; int accept_pending=FALSE; int res=0; unsigned char buf[255]; int cSocket; log_init(); LOG_ENTER(); log_set_level(LOG_FATAL); mdm_init(); pb_init(); modem_count = init(argc, argv, cfg, 64, &port,all_busy,sizeof(all_busy)); sSocket = ip_init_server_conn(port); for(i=0;idce_data.tty); exit(-1); } cfg[i].line_data.sfd=sSocket; rc=pthread_create(&thread_id,NULL,*run_bridge,(void *)&cfg[i]); if(rc < 0) { ELOG(LOG_FATAL,"IP thread could not be started"); exit(-1); } } for(;;) { FD_ZERO(&readfs); max_fd=0; for(i=0;i -1) { buf[res]=0; LOG(LOG_DEBUG,"modem core #%d sent response '%c'",i,buf[0]); accept_pending=FALSE; } } } if (FD_ISSET(sSocket,&readfs)) { // IP traffic if(!accept_pending) { LOG(LOG_DEBUG,"Incoming connection pending"); // first try for a modem that is listening. for(i=0;i -1) { if(strlen(all_busy) < 1) { ip_write(cSocket,(unsigned char*)MDM_BUSY,strlen(MDM_BUSY)); } else { writeFile(all_busy,cSocket); } close(cSocket); } } } } } LOG_EXIT(); return rc; } tcpser/src/.svn/text-base/tcpser.h.svn-base0100444000076400010400000000000010045521712021751 0ustar brainAdministratorstcpser/src/.svn/text-base/util.c.svn-base0100444000076400010400000000106510066734602021444 0ustar brainAdministrators#include #include #include "util.h" int writePipe(int fd,unsigned char msg) { unsigned char tmp[3]; tmp[0]=msg; tmp[1]='\n'; tmp[2]='\0'; //printf("Writing %c to pipe fd: %d\n",msg,fd); return write(fd,tmp,2); } int writeFile(unsigned char* name, int fd) { FILE* file; unsigned char buf[255]; size_t len; size_t size=1; size_t max=255; if(NULL != (file = fopen(name,"rb"))) { while(0 < (len = fread(buf,size,max,file))) { write(fd, buf, len); } fclose(file); return 0; } return -1; } tcpser/src/.svn/text-base/util.h.svn-base0100444000076400010400000000012610066734602021446 0ustar brainAdministratorsint writePipe(int fd,unsigned char msg); int writeFile(unsigned char* name, int fd); tcpser/src/.svn/tmp/0040755000076400010400000000000010747537547015534 5ustar brainAdministratorstcpser/src/.svn/tmp/prop-base/0040755000076400010400000000000010574105507017405 5ustar brainAdministratorstcpser/src/.svn/tmp/props/0040755000076400010400000000000010574105507016660 5ustar brainAdministratorstcpser/src/.svn/tmp/text-base/0040755000076400010400000000000010574105507017411 5ustar brainAdministratorstcpser/src/bridge.c0100644000076400010400000003066310445265204015434 0ustar brainAdministrators#include #include // for recv... #include // for read... #include // for exit... #include #include #include #include "util.h" #include "debug.h" #include "nvt.h" #include "modem_core.h" #include "ip.h" //#include "serial.h" #include "getcmd.h" #include "bridge.h" const unsigned char MDM_NO_ANSWER[] = "NO ANSWER\n"; //const unsigned char CONNECT_NOTICE[] = "\r\nCONNECTING...\r\n"; //const unsigned char TELNET_NOTICE[] = "TELNET MODE ENABLED\r\n"; int accept_connection(modem_config* cfg) { LOG_ENTER(); cfg->line_data.fd=ip_accept(cfg->line_data.sfd); if(cfg->line_data.fd > -1) { cfg->line_data.valid_conn=TRUE; if(cfg->data.direct_conn == TRUE) { cfg->conn_type=MDM_CONN_INCOMING; mdm_off_hook(cfg); cfg->cmd_mode=TRUE; } else { //line_write(cfg,(unsigned char*)CONNECT_NOTICE,strlen(CONNECT_NOTICE)); cfg->rings=0; mdm_send_ring(cfg); } // tell parent I got it. LOG(LOG_DEBUG,"Informing parent task that I am busy"); writePipe(cfg->data.mp[0][1],MSG_ACCEPTED); } LOG_EXIT(); return 0; } int parse_ip_data(modem_config *cfg, unsigned char* data, int len) { // I'm going to cheat and assume it comes in chunks. int i=0; unsigned char ch; unsigned char text[1025]; int text_len=0; if(cfg->line_data.first_char==TRUE) { cfg->line_data.first_char=FALSE; if((data[0] == 0xff) || (data[0] == 0x1a)) { //line_write(cfg,(unsigned char*)TELNET_NOTICE,strlen(TELNET_NOTICE)); LOG(LOG_INFO,"Detected telnet"); cfg->line_data.is_telnet=TRUE; } } if(cfg->line_data.is_telnet == TRUE) { while(iline_data.fd, &cfg->line_data.nvt_data,ch,data[i+2]); i+=3; break; case NVT_SB: // sub negotiation // again, overflow... i+=parse_nvt_subcommand(cfg->line_data.fd, &cfg->line_data.nvt_data,data + i,len - i); break; case NVT_IAC: if (cfg->line_data.nvt_data.binary_recv) text[text_len++] = NVT_IAC; // fall through to skip this sequence default: // ignore... i+=2; } } else { text[text_len++]=data[i++]; } if(text_len == 1024) { text[text_len] = 0; // write to serial... mdm_write(cfg,text,text_len); text_len=0; } } if(text_len) { text[text_len] = 0; // write to serial... mdm_write(cfg,text,text_len); } } else { mdm_write(cfg,data,len); } return 0; } void *ip_thread(void *arg) { modem_config* cfg=(modem_config *)arg; int action_pending=FALSE; fd_set readfs; int max_fd; int res=0; unsigned char buf[256]; int rc; LOG_ENTER(); while(TRUE) { FD_ZERO(&readfs); FD_SET(cfg->data.cp[1][0], &readfs); max_fd=cfg->data.cp[1][0]; if(action_pending == FALSE && cfg->conn_type != MDM_CONN_NONE && cfg->cmd_mode == FALSE && cfg->line_data.fd > -1 && cfg->line_data.valid_conn ==TRUE ) { FD_SET(cfg->line_data.fd, &readfs); max_fd=MAX(max_fd,cfg->line_data.fd); } max_fd++; rc=select(max_fd, &readfs, NULL, NULL, NULL); if(rc == -1) { ELOG(LOG_WARN,"Select returned error"); // handle error } else { // we got data if (cfg->line_data.valid_conn==TRUE && FD_ISSET(cfg->line_data.fd,&readfs)) { // socket LOG(LOG_DEBUG,"Data available on socket"); res = recv(cfg->line_data.fd,buf,sizeof(buf),0); if(0 >= res) { LOG(LOG_INFO,"No socket data read, assume closed peer"); writePipe(cfg->data.cp[0][1],MSG_DISCONNECT); action_pending=TRUE; } else { LOG(LOG_DEBUG,"Read %d bytes from socket",res); buf[res]=0; log_trace(TRACE_IP_IN,buf,res); parse_ip_data(cfg,buf,res); } } if (FD_ISSET(cfg->data.cp[1][0],&readfs)) { // pipe res = read(cfg->data.cp[1][0],buf,sizeof(buf) - 1); LOG(LOG_DEBUG,"IP thread notified"); action_pending=FALSE; } } } LOG_EXIT(); } void *ctrl_thread(void *arg) { modem_config* cfg=(modem_config *)arg; int status; int new_status; LOG_ENTER(); status=dce_get_control_lines(cfg); while(status > -1) { new_status = dce_check_control_lines(cfg); if(new_status > -1 && status != new_status) { // something changed if((status & MDM_CL_DTR_HIGH) != (new_status & MDM_CL_DTR_HIGH)) { if((new_status & MDM_CL_DTR_HIGH) == 0) { LOG(LOG_INFO,"DTR has gone low"); writePipe(cfg->data.wp[0][1],MSG_DTR_DOWN); } else { LOG(LOG_INFO,"DTR has gone high"); writePipe(cfg->data.wp[0][1],MSG_DTR_UP); } } } status = new_status; } LOG_EXIT(); // need to quit application, as status cannot be obtained. exit(-1); } int spawn_ctrl_thread(modem_config *cfg) { int rc; pthread_t thread_id; rc=pthread_create(&thread_id,NULL,ctrl_thread,(void *)cfg); LOG(LOG_ALL,"CTRL thread ID=%d",(int)thread_id); if(rc < 0) { ELOG(LOG_FATAL,"CTRL thread could not be started"); exit(-1); } return 0; } int spawn_ip_thread(modem_config *cfg) { int rc; pthread_t thread_id; rc=pthread_create(&thread_id,NULL,ip_thread,(void *)cfg); LOG(LOG_ALL,"IP thread ID=%d",(int)thread_id); if(rc < 0) { ELOG(LOG_FATAL,"IP thread could not be started"); exit(-1); } return 0; } void *run_bridge(void * arg) { modem_config *cfg=(modem_config *)arg; struct timeval timer; struct timeval* ptimer; int max_fd=0; fd_set readfs; int res=0; unsigned char buf[256]; int rc=0; int last_conn_type; int last_cmd_mode=cfg->cmd_mode; LOG_ENTER(); if( -1 == pipe(cfg->data.wp[0])) { ELOG(LOG_FATAL,"Control line watch task incoming IPC pipe could not be created"); exit(-1); } if( -1 == pipe(cfg->data.cp[0])) { ELOG(LOG_FATAL,"IP thread incoming IPC pipe could not be created"); exit(-1); } if( -1 == pipe(cfg->data.cp[1])) { ELOG(LOG_FATAL,"IP thread outgoing IPC pipe could not be created"); exit(-1); } spawn_ctrl_thread(cfg); spawn_ip_thread(cfg); mdm_set_control_lines(cfg); strncpy(cfg->cur_line,cfg->config0,sizeof(cfg->cur_line)); last_conn_type=cfg->conn_type; last_cmd_mode=cfg->cmd_mode; cfg->allow_transmit=FALSE; // call some functions behind the scenes mdm_disconnect(cfg); mdm_parse_cmd(cfg); // if direct connection, and num length > 0, dial number. if (cfg->data.direct_conn == TRUE) { if(strlen(cfg->data.direct_conn_num) > 0 && cfg->data.direct_conn_num[0] != ':') { // we have a direct number to connect to. strncpy(cfg->dialno,cfg->data.direct_conn_num,sizeof(cfg->dialno)); if(0 != line_connect(cfg)) { LOG(LOG_FATAL,"Cannot connect to Direct line address!"); // probably should exit... exit(-1); } else { cfg->conn_type=MDM_CONN_OUTGOING; } } } cfg->allow_transmit=TRUE; for(;;) { if(last_conn_type!= cfg->conn_type) { LOG(LOG_ALL,"Connection status change, handling"); //writePipe(cfg->data.mp[0][1],MSG_NOTIFY); writePipe(cfg->data.cp[1][1],MSG_NOTIFY); if(cfg->conn_type == MDM_CONN_OUTGOING) { if(strlen(cfg->data.local_connect) > 0) { writeFile(cfg->data.local_connect,cfg->line_data.fd); } if(strlen(cfg->data.remote_connect) > 0) { writeFile(cfg->data.remote_connect,cfg->line_data.fd); } } else if(cfg->conn_type == MDM_CONN_INCOMING) { if(strlen(cfg->data.local_answer) > 0) { writeFile(cfg->data.local_answer,cfg->line_data.fd); } if(strlen(cfg->data.remote_answer) > 0) { writeFile(cfg->data.remote_answer,cfg->line_data.fd); } } last_conn_type=cfg->conn_type; } if(last_cmd_mode != cfg->cmd_mode) { writePipe(cfg->data.cp[1][1],MSG_NOTIFY); last_cmd_mode=cfg->cmd_mode; } LOG(LOG_ALL,"Waiting for modem/control line/timer/socket activity"); LOG(LOG_ALL,"Command Mode=%d, Connection status=%d",cfg->cmd_mode,cfg->conn_type); max_fd=MAX(cfg->data.mp[1][0],cfg->dce_data.fd); max_fd=MAX(max_fd,cfg->data.wp[0][0]); max_fd=MAX(max_fd,cfg->data.cp[0][0]); FD_ZERO(&readfs); FD_SET(cfg->data.mp[1][0], &readfs); FD_SET(cfg->dce_data.fd, &readfs); FD_SET(cfg->data.wp[0][0], &readfs); FD_SET(cfg->data.cp[0][0], &readfs); ptimer=NULL; if(cfg->cmd_mode == FALSE) { if(cfg->pre_break_delay == FALSE || cfg->break_len == 3) { LOG(LOG_ALL,"Setting timer for break delay"); timer.tv_sec=0; timer.tv_usec=cfg->s[12] * 20000; ptimer=&timer; } else if(cfg->pre_break_delay == TRUE && cfg->break_len > 0) { LOG(LOG_ALL,"Setting timer for inter-break character delay"); timer.tv_sec=1; // 1 second timer.tv_usec=0; ptimer=&timer; } else if (cfg->s[30] != 0) { LOG(LOG_ALL,"Setting timer for inactivity delay"); timer.tv_sec=cfg->s[30] * 10; timer.tv_usec=0; ptimer=&timer; } } else if(cfg->cmd_mode == TRUE && cfg->conn_type== MDM_CONN_NONE && cfg->line_data.valid_conn ==TRUE) { LOG(LOG_ALL,"Setting timer for rings"); timer.tv_sec=4; timer.tv_usec=0; ptimer=&timer; } max_fd++; rc=select(max_fd, &readfs, NULL, NULL, ptimer); if(rc == -1) { ELOG(LOG_WARN,"Select returned error"); // handle error } else if(rc == 0) { // timer popped. if(cfg->cmd_mode == TRUE && cfg->conn_type == MDM_CONN_NONE && cfg->line_data.valid_conn == TRUE) { if(cfg->s[0] == 0 && cfg->rings==10) { // not going to answer, send some data back to IP and disconnect. if(strlen(cfg->data.no_answer) == 0) { line_write(cfg,(unsigned char*)MDM_NO_ANSWER,strlen(MDM_NO_ANSWER)); } else { writeFile(cfg->data.no_answer,cfg->line_data.fd); } mdm_disconnect(cfg); } else mdm_send_ring(cfg); } else mdm_handle_timeout(cfg); } if (FD_ISSET(cfg->dce_data.fd,&readfs)) { // serial port LOG(LOG_DEBUG,"Data available on serial port"); res = dce_read(cfg,buf,sizeof(buf)); LOG(LOG_DEBUG,"Read %d bytes from serial port",res); if(res > 0) { if(cfg->conn_type == MDM_CONN_NONE && cfg->off_hook == TRUE) { // this handles the case where atdt goes off hook, but no // connection mdm_disconnect(cfg); mdm_send_response(MDM_RESP_OK,cfg); } else { mdm_parse_data(cfg,buf,res); } } } if (FD_ISSET(cfg->data.wp[0][0],&readfs)) { // control pipe res = read(cfg->data.wp[0][0],buf,sizeof(buf) -1); buf[res]=0; LOG(LOG_DEBUG,"Received %c from Control line watch task",buf[0]); switch (buf[0]) { case MSG_DTR_DOWN: // DTR drop, close any active connection and put // in cmd_mode mdm_disconnect(cfg); break; case MSG_DTR_UP: break; } } if (FD_ISSET(cfg->data.cp[0][0],&readfs)) { // ip thread pipe res = read(cfg->data.cp[0][0],buf,sizeof(buf)); LOG(LOG_DEBUG,"Received %c from ip thread",buf[0]); switch (buf[0]) { case MSG_DISCONNECT: if(cfg->data.direct_conn == TRUE) { // what should we do here... LOG(LOG_ERROR,"Direct Connection Link broken, disconnecting and awaiting new direct connection"); cfg->data.direct_conn=FALSE; mdm_disconnect(cfg); cfg->data.direct_conn=TRUE; } else { mdm_disconnect(cfg); } break; } } if (FD_ISSET(cfg->data.mp[1][0],&readfs)) { // parent pipe LOG(LOG_DEBUG,"Data available on incoming IPC pipe"); res = read(cfg->data.mp[1][0],buf,sizeof(buf)); switch (buf[0]) { case MSG_ACCEPT: // accept connection. accept_connection(cfg); break; } } } LOG_EXIT(); } tcpser/src/bridge.h0100644000076400010400000000102210066743622015430 0ustar brainAdministrators#define MSG_NOT_ACTIVE 'a' #define MSG_ACTIVE 'A' #define MSG_NOT_LISTENING 'l' #define MSG_LISTENING 'L' #define MSG_ACCEPT '+' #define MSG_ACCEPTED '+' #define MSG_DTR_DOWN 'd' #define MSG_DTR_UP 'D' #define MSG_RTS_DOWN 'r' #define MSG_RTS_UP 'R' #define MSG_CD_DOWN 'c' #define MSG_CD_UP 'c' #define MSG_RNG_DOWN 'n' #define MSG_RNG_UP 'N' #define MSG_DISCONNECT 'D' #define MSG_NOTIFY 'N' int accept_connection(modem_config*); int parse_ip_data(modem_config *cfg, unsigned char* data, int len); void *run_bridge(void *arg); tcpser/src/dce.c0100644000076400010400000000541510443715026014730 0ustar brainAdministrators#include #include #include #include "debug.h" #include "serial.h" #include "modem_core.h" #include "ip232.h" // needs modem_core.h #include "dce.h" int dce_init_config(modem_config *cfg) { return 0; } int dce_init_conn(modem_config* cfg) { int rc; LOG_ENTER(); if (cfg->dce_data.is_ip232) { rc=ip232_init_conn(cfg); } else { rc=ser_init_conn(cfg->dce_data.tty,cfg->dte_speed); cfg->dce_data.fd=rc; } LOG_EXIT(); return rc; } int dce_set_flow_control(modem_config *cfg,int opts) { int status=0; int rc=0; LOG_ENTER(); if(opts == 0) { LOG(LOG_ALL,"Setting NONE flow control"); } else { if((opts & MDM_FC_RTS) != 0) { LOG(LOG_ALL,"Setting RTSCTS flow control"); status |= CRTSCTS; } if((opts && MDM_FC_XON) != 0) { status |= (IXON | IXOFF); LOG(LOG_ALL,"Setting XON/XOFF flow control"); } } if (cfg->dce_data.is_ip232) { rc=ip232_set_flow_control(cfg,status); } else { rc=ser_set_flow_control(cfg->dce_data.fd,status); } LOG_EXIT() return rc; } int dce_set_control_lines(modem_config *cfg,int state) { int status=0; int rc; LOG_ENTER(); if((state & MDM_CL_CTS_HIGH) != 0) { LOG(LOG_ALL,"Setting CTS pin high"); status |= TIOCM_RTS; } else { LOG(LOG_ALL,"Setting CTS pin low"); //status &= ~TIOCM_RTS; } if((state & MDM_CL_DCD_HIGH) != 0) { LOG(LOG_ALL,"Setting DCD pin high"); status |= TIOCM_DTR; } else { LOG(LOG_ALL,"Setting DCD pin low"); //status &= ~TIOCM_DTR; } if (cfg->dce_data.is_ip232) { rc = ip232_set_control_lines(cfg,status); } else { rc = ser_set_control_lines(cfg->dce_data.fd,status); } LOG_EXIT(); return rc; } int dce_get_control_lines(modem_config *cfg) { int status; int rc_status; if (cfg->dce_data.is_ip232) { status = ip232_get_control_lines(cfg); } else { status = ser_get_control_lines(cfg->dce_data.fd); } if(status > -1) { rc_status=((status & TIOCM_DSR) != 0?MDM_CL_DTR_HIGH:0); } else { rc_status=status; } return rc_status; } int dce_check_control_lines(modem_config *cfg) { int status=0; int new_status=0; LOG_ENTER(); status = dce_get_control_lines(cfg); new_status = status; while(new_status > -1 && status == new_status) { usleep(100000); new_status = dce_get_control_lines(cfg); } LOG_EXIT(); return new_status; } int dce_write(modem_config *cfg,unsigned char data[], int len) { if (cfg->dce_data.is_ip232) { return ip232_write(cfg,data,len); } return ser_write(cfg->dce_data.fd,data,len); } int dce_read(modem_config *cfg, unsigned char data[], int len) { if (cfg->dce_data.is_ip232) { return ip232_read(cfg,data,len); } return ser_read(cfg->dce_data.fd,data,len); } tcpser/src/dce.h0100644000076400010400000000103110066743622014727 0ustar brainAdministrators#ifndef DCE_H #define DCE_H 1 int dce_init(void); int dce_init_config(modem_config *cfg); int dce_init_conn(modem_config* cfg); int dce_set_flow_control(modem_config *cfg,int opts); int dce_set_control_lines(modem_config *cfg,int state); int dce_get_control_lines(modem_config *cfg); int dce_check_control_lines(modem_config *cfg); int dce_read(modem_config *cfg,unsigned char* data,int len); int dce_write(modem_config *cfg,unsigned char* data,int len); //int dce_check_for_break(modem_config *cfg, char ch, int chars_left); #endif tcpser/src/debug.c0100644000076400010400000000541510300571414015254 0ustar brainAdministrators#include // for exit... #include #include #include #define DEBUG_VARS 1 // need this so we don't get extern defs #include "debug.h" int log_level=0; FILE* log_file; int trace_flags=0; unsigned char* trace_type[9]; // cheesy, but I can't think of another o(1) way unsigned char* log_desc[LOG_TRACE+1]; pthread_mutex_t log_mutex; int log_init() { log_file=stdout; log_level=0; trace_flags=0; trace_type[TRACE_MODEM_IN]="RS<-"; trace_type[TRACE_MODEM_OUT]="RS->"; trace_type[TRACE_IP_IN]="IP<-"; trace_type[TRACE_IP_OUT]="IP->"; log_desc[LOG_FATAL]="FATAL"; log_desc[LOG_ERROR]="ERROR"; log_desc[LOG_WARN]="WARN"; log_desc[LOG_INFO]="INFO"; log_desc[LOG_DEBUG]="DEBUG"; log_desc[LOG_ENTER_EXIT]="ENTER_EXIT"; log_desc[LOG_ALL]="DEBUG_X"; log_desc[LOG_TRACE]=""; if( -1 == pthread_mutex_init(&log_mutex,NULL)) { perror("Could not create Log Mutex"); exit(-1); } return 0; } void log_set_file(FILE* a) { log_file=a; } void log_set_level(int a) { log_level=a; } void log_set_trace_flags(int a) { trace_flags=a; } int log_get_trace_flags() { return trace_flags; } void log_trace(int type, unsigned char* line, int len) { int i=0; int ch; unsigned char data[64]="\0"; unsigned char *dptr=NULL; unsigned char text[17]; if(len==0) return; if((type & trace_flags) != 0) { text[16]=0; for(i=0;i 31 && ch < 127) { text[i % 16] = ch; } else { text[i % 16] = '.'; } if((i %16) == 15) { log_start(LOG_TRACE); fprintf(log_file,"%s|%s|%s|",trace_type[type],data,text); log_end(); } else { sprintf(dptr + 7 + ((i % 16) * 3)," "); } } i=i%16; if(i > 0) { for(;i<16;i++) { sprintf(dptr + 5 + ((i % 16) * 3)," "); if((i % 16) != 15) { sprintf(dptr + 7 + ((i % 16) * 3)," "); } text[i % 16] = ' '; } log_start(LOG_TRACE); fprintf(log_file,"%s|%s|%s|",trace_type[type],data,text); } log_end(); } } void log_start(int level) { unsigned char t[23]; time_t now; if(-1 == pthread_mutex_lock(&log_mutex)) { perror("Could not lock the log mutex"); } else { // we have the lock. now=time(NULL); strftime(t,22,"%Y-%m-%d %H:%M:%S",localtime(&now)); fprintf(log_file,"%s:%5.5d:%s:",t,(int)pthread_self(),log_desc[level]); //free(t); } } void log_end() { fprintf(log_file,"\n"); fflush(log_file); if(-1 == pthread_mutex_unlock(&log_mutex)) { perror("Could not lock the log mutex"); } } tcpser/src/debug.h0100644000076400010400000000330710444213106015257 0ustar brainAdministrators#ifndef DEBUG_H #define DEBUG_H 1 #define LOG_TRACE 10 #define LOG_ALL 7 #define LOG_ENTER_EXIT 6 #define LOG_DEBUG 5 #define LOG_INFO 4 #define LOG_WARN 3 #define LOG_ERROR 2 #define LOG_FATAL 1 #define LOG_NONE 0 #define TRACE_MODEM_IN 1 #define TRACE_MODEM_OUT 2 #define TRACE_IP_IN 4 #define TRACE_IP_OUT 8 #include // needed for strerror #include // needed for strerror #include // needed for errno #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 # define __func__ __FUNCTION__ # else # define __func__ "" # endif #endif #define LOG(a,args...) do { \ if(a <= log_level) { \ log_start(a); \ fprintf(log_file,args); \ log_end(); \ } \ } while(0) #define ELOG(a,args...) do { \ if(a <= log_level) { \ log_start(a); \ fprintf(log_file,args); \ fprintf(log_file," (%s)\n",strerror(errno)); \ log_end(); \ } \ } while(0) #define LOG_ENTER() LOG(LOG_ENTER_EXIT,"Entering %s function",__func__); #define LOG_EXIT() LOG(LOG_ENTER_EXIT,"Exitting %s function",__func__); int log_init(void); void log_set_file(FILE* a); void log_set_level(int a); int log_get_trace_flags(); void log_set_trace_flags(int a); void log_trace(int type, unsigned char* line, int len); void log_start(int level); void log_end(); #endif #ifndef DEBUG_VARS #define DEBUG_VARS 1 #include extern int log_level; extern FILE* log_file; #endif tcpser/src/getcmd.c0100644000076400010400000001504610277577074015457 0ustar brainAdministrators#include #include #include #include "getcmd.h" int getData(unsigned char line[], int* index, int len, int* data_start, int* data_end, int complex_parse ) { int alpha=FALSE; int done=FALSE; *data_start=*index; while(*index < len && done != TRUE) { // I'm going to assume either // a number // a string with a space switch(line[*index]) { case ' ': if(!complex_parse && *index != *data_start) { // leave space, next call will skip it. done=TRUE; } else if(*index != *data_start) { // we are complex, add the space and continue. (*index)++; } else { // we have not started, eat space and continue. (*index)++; *data_start=*index; } break; case 0: done=TRUE; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': // isnum (*index)++; break; default: if(!complex_parse && *index != *data_start && 0==alpha ) { // we were a number, but we've hit an alpha 'S0=137S...' done=TRUE; } else { (*index)++; alpha=TRUE; } break; } } *data_end=(*index); return 0; } int getNumber(unsigned char line[], int* index, int len ) { int num=0; int found=FALSE; while(*index *num) *num=0; return toupper(cmd) | flags; } int parseRegister(unsigned char line[], int flags, int* index, int* num, int len, int* data_start, int* data_end, int complex_parse ) { // need to handle S?, which queries that S register. int cmd=0; cmd = getCommand(line,flags,index,num,len); if(0 > num) return AT_CMD_ERR; skip(line,index,len,' '); if(len == *index) return AT_CMD_ERR; switch (line[(*index)++]) { case '=': // set a register skip(line, index, len, ' '); if(0 > getData(line, index, len, data_start, data_end, complex_parse)) return AT_CMD_ERR; break; case '?': // query a register flags |= AT_CMD_FLAG_QUERY; if(*num < 0) *num=0; break; default: return AT_CMD_ERR; } return toupper(cmd) | flags; } int getcmd(unsigned char line[], int* index, int* num, int* data_start, int* data_end ) { int len=0; int cmd=AT_CMD_END; *num=0; *data_start=0; *data_end=0; if(line == NULL) return AT_CMD_NONE; len=strlen(line); while(*index < len) { cmd=toupper(line[*index]); switch (cmd) { case ' ': break; case 0: return AT_CMD_END; case '%': (*index)++; while(*index #include // for exit,atoi #include #include "debug.h" #include "phone_book.h" #include "init.h" void print_help(unsigned char* name) { fprintf(stderr, "Usage: %s \n",name); fprintf(stderr, " -p port to listen on (defaults to 6400)\n"); fprintf(stderr, " -t trace flags: (can be combined)\n"); fprintf(stderr, " 's' = modem input\n"); fprintf(stderr, " 'S' = modem output\n"); fprintf(stderr, " 'i' = IP input\n"); fprintf(stderr, " 'I' = IP input\n"); fprintf(stderr, " -l 0 (NONE), 1 (FATAL) - 7 (DEBUG_X) (defaults to 0)\n"); fprintf(stderr, " -L log file (defaults to stderr)\n"); fprintf(stderr, "\n"); fprintf(stderr, " The following can be repeated for each modem desired\n"); fprintf(stderr, " (-s, -S, and -i will apply to any subsequent device if not set again)\n"); fprintf(stderr, "\n"); fprintf(stderr, " -d serial device (e.g. /dev/ttyS0). Cannot be used with -v\n"); fprintf(stderr, " -v tcp port for VICE RS232 (e.g. 25232). Cannot be used with -d\n"); fprintf(stderr, " -s serial port speed (defaults to 38400)\n"); fprintf(stderr, " -S speed modem will report (defaults to -s value)\n"); fprintf(stderr, " -I invert DCD pin\n"); fprintf(stderr, " -n add phone entry (number=replacement)\n"); fprintf(stderr, " -a filename to send to local side upon answer\n"); fprintf(stderr, " -A filename to send to remote side upon answer\n"); fprintf(stderr, " -c filename to send to local side upon connect\n"); fprintf(stderr, " -C filename to send to remote side upon connect\n"); fprintf(stderr, " -N filename to send when no answer\n"); fprintf(stderr, " -B filename to send when modem(s) busy\n"); fprintf(stderr, " -T filename to send upon inactivity timeout\n"); fprintf(stderr, " -i modem init string (defaults to '', leave off 'at' prefix when specifying)\n"); fprintf(stderr, " -D direct connection (follow with hostname:port for caller, : for receiver)\n"); exit(1); } int init(int argc, char** argv, modem_config cfg[], int max_modem, int* port, unsigned char* all_busy, int all_busy_len ) { int i=0; int j=0; int opt=0; int trace_flags=0; unsigned char* tok; int dce_set=FALSE; int tty_set=FALSE; LOG_ENTER(); *port=6400; mdm_init_config(&cfg[0]); cfg[0].dte_speed=38400; cfg[0].dce_speed=38400; while(opt>-1 && i < max_modem) { opt=getopt(argc,argv,"p:s:S:d:v:hw:i:Il:L:t:n:a:A:c:C:N:B:T:D:"); switch(opt) { case 't': trace_flags=log_get_trace_flags(); for(j=0;j #include #include #include #include #include // for read... #include // for atoi... #include "debug.h" #include "ip.h" const int BACK_LOG = 5; int ip_init_server_conn(int port) { int sSocket = 0, on = 0, rc = 0; struct sockaddr_in serverName = { 0 }; LOG_ENTER(); LOG(LOG_DEBUG,"Creating server socket"); sSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (-1 == sSocket) { ELOG(LOG_FATAL,"Server socket could not be created"); } else { /* * turn off bind address checking, and allow * port numbers to be reused - otherwise * the TIME_WAIT phenomenon will prevent * binding to these addreG. */ on = 1; rc = setsockopt(sSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on) ); if (-1 == rc) { ELOG(LOG_ERROR,"bind address checking could not be turned off"); } serverName.sin_addr.s_addr=htonl(INADDR_ANY); serverName.sin_family = AF_INET; /* network-order */ serverName.sin_port = htons(port); LOG(LOG_DEBUG,"Binding server socket to port %d",port); rc = bind(sSocket, (struct sockaddr *) &serverName, sizeof(serverName) ); if (-1 == rc) { ELOG(LOG_FATAL,"Server socket could not be bound to port"); sSocket = -1; } else { LOG(LOG_INFO,"Server socket bound to port"); rc = listen(sSocket, BACK_LOG); LOG(LOG_INFO,"Server socket listening for connections"); if (-1 == rc) { ELOG(LOG_FATAL,"Server socket could not listen on port"); sSocket = -1; } } } LOG_EXIT(); return sSocket; } int ip_connect(unsigned char addy[]) { struct sockaddr_in pin; struct in_addr cin_addr; struct hostent *hp; int sd=0; int port=23; unsigned char* address; unsigned char* tmp; LOG_ENTER(); address=(unsigned char*)strtok(addy,":"); tmp=(unsigned char*)strtok((unsigned char*)0,":"); if(tmp != NULL && strlen(tmp) > 0) { port=atoi(tmp); } LOG(LOG_DEBUG,"Calling %s",addy); memset(&pin, 0, sizeof(pin)); /* go find out about the desired host machine */ if ((hp = gethostbyname(address)) == 0) { // well, not a DNS entry... Treat as IP... if(1 != inet_aton(address,&cin_addr)) { ELOG(LOG_ERROR,"Host %s was invalid",addy); return -1; } } else { cin_addr=*((struct in_addr *)(hp->h_addr)); } pin.sin_family = AF_INET; pin.sin_addr.s_addr = cin_addr.s_addr; pin.sin_port = htons(port); /* grab an Internet domain socket */ if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { ELOG(LOG_ERROR,"could not create client socket"); return -1; } /* connect to PORT on HOST */ if (connect(sd,(struct sockaddr *) &pin, sizeof(pin)) == -1) { ELOG(LOG_ERROR,"could not connect to address"); return -1; } LOG(LOG_INFO, "Connection to %s established",addy); LOG_EXIT(); return sd; } int ip_accept(int sSocket) { struct sockaddr_in clientName = { 0 }; int clientLength = sizeof(clientName); int cSocket=-1; LOG_ENTER(); (void) memset(&clientName, 0, sizeof(clientName)); cSocket = accept(sSocket, (struct sockaddr *) &clientName, &clientLength ); if (-1 == cSocket) { ELOG(LOG_ERROR,"Could not accept incoming connection"); return -1; } if (-1 == getpeername(cSocket, (struct sockaddr *) &clientName, &clientLength )) { ELOG(LOG_WARN,"Could not obtain peer name"); } else { LOG(LOG_INFO,"Connection accepted from %s", inet_ntoa(clientName.sin_addr) ); } LOG_EXIT(); return cSocket; } int ip_disconnect(int fd) { if(fd > -1) close(fd); return 0; } int ip_write(int fd,unsigned char* data,int len) { log_trace(TRACE_IP_OUT,data,len); return write(fd,data,len); } int ip_read(int fd, unsigned char* data, int len) { int res; res = recv(fd,data,len,0); log_trace(TRACE_IP_IN,data,res); return res; } tcpser/src/ip.h0100644000076400010400000000052010066743622014606 0ustar brainAdministrators#ifndef IP_H #define IP_H #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif int ip_init(void); int ip_init_server_conn(int port); int ip_connect(unsigned char addy[]); int ip_accept(int sSocket); int ip_disconnect(int fd); int ip_write(int fd,unsigned char* data,int len); int ip_read(int fd, unsigned char* data, int len); #endif tcpser/src/ip232.c0100644000076400010400000001457210444214772015043 0ustar brainAdministrators#include // for recv... #include // for exit... #include #include #include #include #include #include #include #include "util.h" #include "debug.h" #include "modem_core.h" #include "ip.h" #include "ip232.h" void *ip232_thread(void *arg) { modem_config* cfg=(modem_config *)arg; int accept_pending=FALSE; int rc; int res=0; unsigned char buf[256]; fd_set readfs; int max_fd=0; int cSocket; LOG_ENTER(); for(;;) { FD_ZERO(&readfs); FD_SET(cfg->dce_data.dp[1][0], &readfs); max_fd=cfg->dce_data.dp[1][0]; if (accept_pending == FALSE) { FD_SET(cfg->dce_data.sSocket, &readfs); max_fd=MAX(max_fd,cfg->dce_data.sSocket); } LOG(LOG_ALL,"Waiting for incoming ip232 connections"); rc = select(max_fd+1, &readfs, NULL, NULL, NULL); if (rc < 0) { // handle error } else { if (FD_ISSET(cfg->dce_data.dp[1][0],&readfs)) { // pipe res = read(cfg->dce_data.dp[1][0],buf,sizeof(buf) - 1); LOG(LOG_DEBUG,"ip232 thread notified"); accept_pending=FALSE; } if (FD_ISSET(cfg->dce_data.sSocket,&readfs)) { // ip connection if(cfg->dce_data.ip232_is_connected) { LOG(LOG_DEBUG,"Already have ip232 connection, rejecting new"); // already have a connection... accept and close cSocket=ip_accept(cfg->dce_data.sSocket); if(cSocket > -1) { close(cSocket); } } else { LOG(LOG_DEBUG,"Incoming ip232 connection"); writePipe(cfg->dce_data.dp[0][1],MSG_ACCEPT); accept_pending=TRUE; } } } } LOG_EXIT(); } int spawn_ip232_thread(modem_config *cfg) { int rc; pthread_t thread_id; rc=pthread_create(&thread_id,NULL,ip232_thread,(void *)cfg); LOG(LOG_ALL,"ip232 thread ID=%d",(int)thread_id); if(rc < 0) { ELOG(LOG_FATAL,"ip232 thread could not be started"); exit(-1); } return 0; } int ip232_init_conn(modem_config *cfg) { int rc = -1; int port; LOG_ENTER(); LOG(LOG_INFO,"Opening ip232 device"); port = atoi(cfg->dce_data.tty); rc = ip_init_server_conn(port); if (rc < 0) { ELOG(LOG_FATAL,"Could not initialize ip232 server socket"); exit(-1); } if( -1 == pipe(cfg->dce_data.dp[0])) { ELOG(LOG_FATAL,"ip232 thread incoming IPC pipe could not be created"); exit(-1); } if( -1 == pipe(cfg->dce_data.dp[1])) { ELOG(LOG_FATAL,"ip232 thread outgoing IPC pipe could not be created"); exit(-1); } cfg->dce_data.sSocket = rc; cfg->dce_data.ip232_is_connected = FALSE; cfg->dce_data.fd = cfg->dce_data.dp[0][0]; spawn_ip232_thread(cfg); LOG(LOG_INFO,"ip232 device configured"); LOG_EXIT(); return rc; } int ip232_set_flow_control(modem_config *cfg, int status) { return 0; } int ip232_get_control_lines(modem_config *cfg) { int status=0; if (cfg->dce_data.ip232_is_connected && cfg->dce_data.ip232_dtr) { status |= TIOCM_DSR; } return status; } int ip232_set_control_lines(modem_config *cfg, int state) { int dcd; unsigned char cmd[2]; if (cfg->dce_data.ip232_is_connected) { dcd = (state & TIOCM_DTR) ? TRUE : FALSE; if (dcd != cfg->dce_data.ip232_dcd) { cfg->dce_data.ip232_dcd = dcd; cmd[0] = 255; cmd[1] = dcd ? 1 : 0; ip_write(cfg->dce_data.fd,cmd,sizeof(cmd)); } } return 0; } int ip232_write(modem_config *cfg, unsigned char* data,int len) { int retval; int i=0; int double_iac = FALSE; unsigned char text[1024]; int text_len=0; log_trace(TRACE_MODEM_OUT,data,len); retval = len; if (cfg->dce_data.ip232_is_connected) { while(idce_data.fd,text,text_len); text_len = 0; } } if(text_len) { retval = ip_write(cfg->dce_data.fd,text,text_len); } } return retval; } int ip232_read(modem_config *cfg, unsigned char* data, int len) { int res; int rc; unsigned char buf[256]; int i=0; unsigned char ch; int text_len=0; LOG_ENTER(); if (len > sizeof(buf)) { LOG(LOG_FATAL, "ip232_read: len > sizeof(buf)"); exit(-1); } if (cfg->dce_data.ip232_is_connected) { res = recv(cfg->dce_data.fd,buf,len,0); if (0 >= res) { LOG(LOG_INFO,"No ip232 socket data read, assume closed peer"); ip_disconnect(cfg->dce_data.fd); cfg->dce_data.fd = cfg->dce_data.dp[0][0]; cfg->dce_data.ip232_is_connected = FALSE; } else { LOG(LOG_DEBUG,"Read %d bytes from ip232 socket",res); log_trace(TRACE_MODEM_IN,buf,res); while(idce_data.ip232_iac) { cfg->dce_data.ip232_iac = FALSE; switch (ch) { case 0: cfg->dce_data.ip232_dtr = FALSE; break; case 1: cfg->dce_data.ip232_dtr = TRUE; break; case 255: data[text_len++] = 255; break; } } else { if (255 == ch) { cfg->dce_data.ip232_iac = TRUE; } else { data[text_len++] = ch; } } i++; } } } else { // not connected res = read(cfg->dce_data.dp[0][0],buf,sizeof(buf)); switch (buf[0]) { case MSG_ACCEPT: // accept connection. LOG(LOG_INFO,"Accepting ip232 connection..."); rc=ip_accept(cfg->dce_data.sSocket); if(res > -1) { cfg->dce_data.fd = rc; cfg->dce_data.ip232_is_connected = TRUE; cfg->dce_data.ip232_dtr = FALSE; cfg->dce_data.ip232_dcd = FALSE; writePipe(cfg->dce_data.dp[1][1],MSG_ACCEPTED); } break; } } LOG_EXIT(); return text_len; } tcpser/src/ip232.h0100644000076400010400000000074110443715106015035 0ustar brainAdministrators#ifndef IP232_H #define IP232_H 1 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define MSG_ACCEPT '+' #define MSG_ACCEPTED '+' int ip232_init_conn(modem_config *); int ip232_set_flow_control(modem_config *, int status); int ip232_get_control_lines(modem_config *); int ip232_set_control_lines(modem_config *, int state); int ip232_write(modem_config *, unsigned char* data,int len); int ip232_read(modem_config *, unsigned char* data, int len); #endif tcpser/src/line.c0100644000076400010400000000413210421254650015114 0ustar brainAdministrators#include "debug.h" #include "modem_core.h" #include "phone_book.h" #include "ip.h" #include "bridge.h" #include "line.h" int line_init_config(modem_config *cfg) { cfg->line_data.fd=-1; cfg->line_data.is_telnet=FALSE; cfg->line_data.first_char=TRUE; cfg->line_data.valid_conn=FALSE; nvt_init_config(&cfg->line_data.nvt_data); return 0; } int line_write(modem_config *cfg,unsigned char* data,int len) { int retval; int i=0; int double_iac = FALSE; unsigned char text[1024]; int text_len=0; if(cfg->line_data.is_telnet && cfg->line_data.nvt_data.binary_xmit) { retval = 0; while(iline_data.fd,text,text_len); text_len = 0; } } if(text_len) { retval = ip_write(cfg->line_data.fd,text,text_len); } return retval; } return ip_write(cfg->line_data.fd,data,len); } int line_listen(modem_config *cfg) { return 0; } int line_off_hook(modem_config *cfg) { return 0; } int line_connect(modem_config *cfg) { unsigned char* addy=cfg->dialno; LOG(LOG_INFO,"Connecting"); addy = pb_search(addy); cfg->line_data.fd=ip_connect(addy); if(cfg->line_data.fd > -1) { LOG(LOG_ALL,"Connected to %s",addy); cfg->line_data.valid_conn = TRUE; return 0; } else { LOG(LOG_ALL,"Could not connect to %s",addy); cfg->line_data.valid_conn = FALSE; return -1; } } int line_disconnect(modem_config *cfg) { LOG(LOG_INFO,"Disconnecting"); if(cfg->data.direct_conn == TRUE) { LOG(LOG_INFO,"Direct connection active, maintaining link"); return -1; } else { cfg->line_data.is_telnet=FALSE; cfg->line_data.first_char=TRUE; if(cfg->line_data.valid_conn == TRUE) { ip_disconnect(cfg->line_data.fd); cfg->line_data.valid_conn=FALSE; } } return 0; } tcpser/src/line.h0100644000076400010400000000064410066743622015134 0ustar brainAdministrators#ifndef LINE_H #define LINE_H 1 int line_init(void); int line_init_conn(modem_config *cfg); int line_init_config(modem_config *cfg); int line_read(modem_config *cfg,unsigned char* data,int len); int line_write(modem_config *cfg,unsigned char* data,int len); int line_listen(modem_config *cfg); int line_off_hook(modem_config *cfg); int line_connect(modem_config *cfg); int line_disconnect(modem_config *cfg); #endif tcpser/src/modem_core.c0100644000076400010400000003765310747414267016331 0ustar brainAdministrators#include #include // for atoi #include "getcmd.h" #include "debug.h" #include "modem_core.h" unsigned char* mdm_responses[37]; int mdm_init() { mdm_responses[MDM_RESP_OK]="OK"; mdm_responses[MDM_RESP_RING]="RING"; mdm_responses[MDM_RESP_ERROR]="ERROR"; mdm_responses[MDM_RESP_CONNECT]="CONNECT"; mdm_responses[MDM_RESP_NO_CARRIER]="NO CARRIER"; mdm_responses[MDM_RESP_CONNECT_1200] = "CONNECT 1200"; mdm_responses[MDM_RESP_NO_DIALTONE] = "NO DIALTONE"; mdm_responses[MDM_RESP_BUSY] = "BUSY"; mdm_responses[MDM_RESP_NO_ANSWER] = "NO ANSWER"; mdm_responses[MDM_RESP_CONNECT_0600] = "CONNECT 0600"; mdm_responses[MDM_RESP_CONNECT_2400] = "CONNECT 2400"; mdm_responses[MDM_RESP_CONNECT_4800] = "CONNECT 4800"; mdm_responses[MDM_RESP_CONNECT_9600] = "CONNECT 9600"; mdm_responses[MDM_RESP_CONNECT_7200] = "CONNECT 7200"; mdm_responses[MDM_RESP_CONNECT_12000] = "CONNECT 12000"; mdm_responses[MDM_RESP_CONNECT_14400] = "CONNECT 14400"; mdm_responses[MDM_RESP_CONNECT_19200] = "CONNECT 19200"; mdm_responses[MDM_RESP_CONNECT_38400] = "CONNECT 38400"; mdm_responses[MDM_RESP_CONNECT_57600] = "CONNECT 57600"; mdm_responses[MDM_RESP_CONNECT_115200] = "CONNECT 115200"; mdm_responses[MDM_RESP_CONNECT_234000]="CONNECT 230400"; return 0; } int get_connect_response(int speed, int level) { if(level == 0) { return MDM_RESP_CONNECT; } switch (speed) { case 115200: return MDM_RESP_CONNECT_115200; case 57600: return MDM_RESP_CONNECT_57600; case 38400: return MDM_RESP_CONNECT_38400; case 19200: return MDM_RESP_CONNECT_19200; case 9600: return MDM_RESP_CONNECT_9600; case 4800: return MDM_RESP_CONNECT_4800; case 2400: return MDM_RESP_CONNECT_2400; case 1200: return MDM_RESP_CONNECT_1200; case 600: return MDM_RESP_CONNECT_0600; } return MDM_RESP_CONNECT; } void mdm_init_config(modem_config* cfg) { int i=0; cfg->send_responses=TRUE; cfg->connect_response=0; cfg->response_code_level=4; cfg->text_responses=TRUE; cfg->echo=TRUE; cfg->cmd_mode=TRUE; cfg->conn_type=MDM_CONN_NONE; cfg->off_hook=FALSE; cfg->line_ringing=FALSE; cfg->cur_line_idx=0; for(i=0;i<100;i++) { cfg->s[i]=0; } cfg->s[2]=43; cfg->s[3]=13; cfg->s[4]=10; cfg->s[5]=8; cfg->s[6]=2; cfg->s[7]=50; cfg->s[8]=2; cfg->s[9]=6; cfg->s[10]=14; cfg->s[11]=95; cfg->s[12]=50; cfg->crlf[0]=cfg->s[3]; cfg->crlf[1]=cfg->s[4]; cfg->crlf[2]=0; cfg->dial_type=0; cfg->last_dial_type=0; cfg->disconnect_delay=0; cfg->pre_break_delay=FALSE; cfg->break_len=0; cfg->memory_dial=FALSE; cfg->dsr_active=FALSE; cfg->dsr_on=TRUE; cfg->dcd_on=FALSE; cfg->found_a=FALSE; cfg->cmd_started=FALSE; cfg->allow_transmit=TRUE; cfg->invert_dsr=FALSE; cfg->invert_dcd=FALSE; cfg->config0[0]='\0'; cfg->config1[0]='\0'; dce_init_config(cfg); sh_init_config(cfg); line_init_config(cfg); } int get_new_cts_state(modem_config *cfg, int up) { return MDM_CL_CTS_HIGH; } int get_new_dsr_state(modem_config *cfg, int up) { if(cfg->dsr_on == TRUE) return (cfg->invert_dsr == TRUE?MDM_CL_DSR_LOW:MDM_CL_DSR_HIGH); if((up == TRUE && cfg->invert_dsr == FALSE) || (up == FALSE && cfg->invert_dsr==TRUE) ) return MDM_CL_DSR_HIGH; else return MDM_CL_DSR_LOW; } int get_new_dcd_state(modem_config *cfg, int up) { if(cfg->dcd_on == TRUE) return (cfg->invert_dcd == TRUE?MDM_CL_DCD_LOW:MDM_CL_DCD_HIGH); if((up == TRUE && cfg->invert_dcd == FALSE) || (up == FALSE && cfg->invert_dcd==TRUE) ) return MDM_CL_DCD_HIGH; else return MDM_CL_DCD_LOW; } int mdm_set_control_lines(modem_config *cfg) { int state=0; int up=(cfg->conn_type == MDM_CONN_NONE?FALSE:TRUE); state |=get_new_cts_state(cfg,up); state |=get_new_dsr_state(cfg,up); state |=get_new_dcd_state(cfg,up); LOG(LOG_INFO,"Control Lines: DSR:%d DCD:%d CTS:%d", ((state & MDM_CL_DSR_HIGH) != 0?1:0), ((state & MDM_CL_DCD_HIGH) != 0?1:0), ((state & MDM_CL_CTS_HIGH) != 0?1:0) ); dce_set_control_lines(cfg,state); return 0; } void mdm_write_char(modem_config *cfg,unsigned char data) { unsigned char str[2]; str[0]=data; mdm_write(cfg,str,1); } void mdm_write(modem_config *cfg,unsigned char data[], int len) { if(cfg->allow_transmit == TRUE) { dce_write(cfg,data,len); } } void mdm_send_response(int msg,modem_config *cfg) { unsigned char msgID[17]; LOG(LOG_DEBUG,"Sending %s response to modem",mdm_responses[msg]); if(cfg->send_responses==TRUE) { mdm_write(cfg,cfg->crlf,2); if(cfg->text_responses==TRUE) { LOG(LOG_ALL,"Sending text response"); mdm_write(cfg,mdm_responses[msg],strlen(mdm_responses[msg])); } else { LOG(LOG_ALL,"Sending numeric response"); sprintf(msgID,"%d",msg); mdm_write(cfg,msgID,strlen(msgID)); } mdm_write(cfg,cfg->crlf,2); } } int mdm_off_hook(modem_config *cfg) { LOG(LOG_INFO,"taking modem off hook"); cfg->off_hook=TRUE; cfg->cmd_mode=FALSE; line_off_hook(cfg); return 0; } int mdm_answer(modem_config *cfg) { if(cfg->line_ringing == TRUE) { cfg->conn_type=MDM_CONN_INCOMING; mdm_off_hook(cfg); mdm_set_control_lines(cfg); mdm_print_speed(cfg); } else if(cfg->conn_type == MDM_CONN_INCOMING) { // we are connected, just go off hook. mdm_off_hook(cfg); mdm_set_control_lines(cfg); } else { mdm_disconnect(cfg); } return 0; } int mdm_print_speed(modem_config *cfg) { int speed; switch(cfg->connect_response) { case 2: speed=cfg->dte_speed; break; default: speed=cfg->dce_speed; break; } mdm_send_response(get_connect_response(speed,cfg->response_code_level),cfg); return 0; } int mdm_connect(modem_config* cfg) { mdm_off_hook(cfg); if(cfg->conn_type == MDM_CONN_NONE) { if(line_connect(cfg) == 0) { cfg->conn_type=MDM_CONN_OUTGOING; mdm_set_control_lines(cfg); mdm_print_speed(cfg); } else { cfg->conn_type=MDM_CONN_OUTGOING; // so disconnect will print NO CARRIER mdm_disconnect(cfg); } } return 0; } int mdm_listen(modem_config *cfg) { return line_listen(cfg); } int mdm_disconnect(modem_config* cfg) { int type; LOG_ENTER(); LOG(LOG_INFO,"Disconnecting modem"); cfg->cmd_mode=TRUE; cfg->off_hook=FALSE; cfg->break_len=0; cfg->line_ringing = FALSE; cfg->pre_break_delay=FALSE; if(0 == line_disconnect(cfg)) { type=cfg->conn_type; cfg->conn_type=MDM_CONN_NONE; mdm_set_control_lines(cfg); if(type != MDM_CONN_NONE) { mdm_send_response(MDM_RESP_NO_CARRIER,cfg); usleep(cfg->disconnect_delay * 1000); } cfg->rings=0; mdm_listen(cfg); } else { // line still connected. } LOG_EXIT(); return 0; } int mdm_parse_cmd(modem_config* cfg) { int done=FALSE; int index=0; int num=0; int start=0; int end=0; int cmd=AT_CMD_NONE; unsigned char* command=cfg->cur_line; unsigned char tmp[256]; LOG_ENTER(); LOG(LOG_DEBUG,"Evaluating AT%s",command); while(TRUE != done ) { if(cmd != AT_CMD_ERR) { cmd=getcmd(command,&index,&num, &start,&end); LOG(LOG_DEBUG,"Command: %c (%d), Flags: %d, index=%d, num=%d, data=%d-%d", (cmd > -1?cmd & 0xff:' '), cmd, cmd >> 8, index, num, start, end ); } switch(cmd) { case AT_CMD_ERR: mdm_send_response(MDM_RESP_ERROR,cfg); done=TRUE; break; case AT_CMD_END: if(cfg->cmd_mode == TRUE) mdm_send_response(MDM_RESP_OK,cfg); done=TRUE; break; case AT_CMD_NONE: done=TRUE; break; case 'O': case 'A': mdm_answer(cfg); cmd=AT_CMD_END; done=TRUE; break; case 'B': // 212A versus V.22 connection if(num > 1) { cmd=AT_CMD_ERR; } else { //cfg->connect_1200=num; } break; case 'D': if(end>start) { strncpy(cfg->dialno,command+start,end-start); cfg->dialno[end-start]='\0'; cfg->dial_type=(unsigned char)num; cfg->last_dial_type=(unsigned char)num; strncpy(cfg->last_dialno,command+start,end-start); cfg->last_dialno[end-start]='\0'; cfg->memory_dial=FALSE; } else if (num == 'L') { strncpy(cfg->dialno,cfg->last_dialno,strlen(cfg->last_dialno)); cfg->dial_type=cfg->dial_type; cfg->memory_dial=TRUE; mdm_write(cfg,cfg->crlf,2); mdm_write(cfg,cfg->dialno,strlen(cfg->dialno)); } else { cfg->dialno[0]=0; cfg->last_dialno[0]=0; cfg->dial_type=0; cfg->last_dial_type=0; } if(strlen(cfg->dialno) > 0) { mdm_connect(cfg); } else { mdm_off_hook(cfg); } done=TRUE; break; case 'E': // still need to define #2 if(num == 0) cfg->echo=FALSE; else if(num == 1) cfg->echo=TRUE; else { cmd=AT_CMD_ERR; } break; case 'H': if(num == 0) { mdm_disconnect(cfg); } else if(num == 1) { mdm_answer(cfg); } else cmd=AT_CMD_ERR; break; case 'I': // Information. break; case 'L': // Speaker volume if(num < 1 || num > 3) cmd=AT_CMD_ERR; else { //cfg->volume=num; } break; case 'M': // speaker settings if(num > 3) cmd=AT_CMD_ERR; else { //cfg->speaker_setting=num; } break; case 'N': // automode negotiate if(num > 1) cmd=AT_CMD_ERR; else { //cfg->auto_mode=num; } break; case 'P': // defaut to pulse dialing //cfg->default_dial_type=MDM_DT_PULSE; break; case 'Q': // still need to define #2 if(num == 0) cfg->send_responses=TRUE; else if(num == 1) cfg->send_responses=FALSE; else if(num == 2) // this should be yes orig/no answer. cfg->send_responses=TRUE; else { cmd=AT_CMD_ERR; } break; case 'S': strncpy(tmp,command+start,end-start); tmp[end-start]='\0'; cfg->s[num]=atoi(tmp); switch(num) { case 3: cfg->crlf[0]=cfg->s[3]; break; case 4: cfg->crlf[1]=cfg->s[4]; break; } break; case AT_CMD_FLAG_QUERY | 'S': sprintf(tmp,"%s%3.3d",cfg->crlf,cfg->s[num]); mdm_write(cfg,tmp,strlen(tmp)); break; case 'T': // defaut to tone dialing //cfg->default_dial_type=MDM_DT_TONE; break; case 'V': // done if(num == 0) cfg->text_responses=FALSE; else if(num ==1) cfg->text_responses=TRUE; else { cmd=AT_CMD_ERR; } break; case 'W': if(num > -1 && num < 3) cfg->connect_response=num; else cmd=AT_CMD_ERR; break; case 'X': if(num > -1 && num < 5) cfg->response_code_level=num; else cmd=AT_CMD_ERR; break; case 'Y': // long space disconnect. if(num > 1) cmd=AT_CMD_ERR; else { //cfg->long_disconnect=num; } break; case 'Z': // long space disconnect. if(num > 1) cmd=AT_CMD_ERR; else { // set config0 to cur_line and go. } break; case AT_CMD_FLAG_EXT + 'C': switch(num) { case 0: cfg->dcd_on=TRUE; mdm_set_control_lines(cfg); break; case 1: cfg->dcd_on=FALSE; mdm_set_control_lines(cfg); break; default: cmd=AT_CMD_ERR; break; } break; case AT_CMD_FLAG_EXT + 'K': // flow control. switch (num) { case 0: dce_set_flow_control(cfg,0); break; case 3: dce_set_flow_control(cfg,MDM_FC_RTS); break; case 4: dce_set_flow_control(cfg,MDM_FC_XON); break; case 5: dce_set_flow_control(cfg,MDM_FC_XON); // need to add passthrough.. Not sure how. break; case 6: dce_set_flow_control(cfg,MDM_FC_XON | MDM_FC_RTS); break; default: cmd=AT_CMD_ERR; break; } break; default: break; } } cfg->cur_line_idx=0; return cmd; } int mdm_handle_char(modem_config* cfg, unsigned char ch) { if(cfg->echo == TRUE) mdm_write_char(cfg,ch); if(cfg->cmd_started == TRUE) { if(ch == (unsigned char)(cfg->s[5])) { if(cfg->cur_line_idx == 0 && cfg->echo == TRUE) { mdm_write_char(cfg,'T'); } else { cfg->cur_line_idx--; } } else if(ch == (unsigned char)(cfg->s[3])) { // we have a line, process. cfg->cur_line[cfg->cur_line_idx] = 0; strncpy(cfg->last_cmd,cfg->cur_line,sizeof(cfg->last_cmd) - 1); mdm_parse_cmd(cfg); cfg->found_a=FALSE; cfg->cmd_started=FALSE; } else { cfg->cur_line[cfg->cur_line_idx++ % sizeof(cfg->cur_line)]=ch; } } else if(cfg->found_a == TRUE) { if(ch == 't' || ch == 'T') { cfg->cmd_started=TRUE; LOG(LOG_ALL,"'T' parsed in serial stream, switching to command parse mode"); } else if(ch == '/') { LOG(LOG_ALL,"'/' parsed in the serial stream, replaying last command"); cfg->cur_line_idx=strlen(cfg->last_cmd); strncpy(cfg->cur_line,cfg->last_cmd,cfg->cur_line_idx); mdm_parse_cmd(cfg); cfg->cmd_started=FALSE; } else if(ch!='a' && ch!='A') { cfg->found_a=FALSE; } } else if(ch == 'a' || ch == 'A') { LOG(LOG_ALL,"'A' parsed in serial stream"); cfg->found_a=TRUE; } return 0; } int mdm_clear_break(modem_config* cfg) { cfg->break_len=0; cfg->pre_break_delay=FALSE; return 0; } int mdm_parse_data(modem_config* cfg,unsigned char* data, int len) { int i; if(cfg->cmd_mode==TRUE) { for(i=0;ipre_break_delay == TRUE) { for(i=0;is[2]) { LOG(LOG_DEBUG,"Break character received"); cfg->break_len++; if(cfg->break_len > 3) { // more than 3, considered invalid cfg->pre_break_delay=FALSE; cfg->break_len=0; } } else { LOG(LOG_ALL,"Found non-break character, cancelling break"); // chars past +++ mdm_clear_break(cfg); } } } } return 0; } int mdm_handle_timeout(modem_config* cfg) { if(cfg->pre_break_delay == TRUE && cfg->break_len == 3) { // pre and post break. LOG(LOG_INFO,"Break condition detected"); cfg->cmd_mode=TRUE; mdm_send_response(MDM_RESP_OK,cfg); mdm_clear_break(cfg); } else if(cfg->pre_break_delay == FALSE) { // pre break wait over. LOG(LOG_DEBUG,"Initial Break Delay detected"); cfg->pre_break_delay=TRUE; } else if(cfg->pre_break_delay == TRUE && cfg->break_len > 0 ) { LOG(LOG_ALL,"Inter-break-char delay time exceeded"); mdm_clear_break(cfg); } else if(cfg->s[30] != 0) { // timeout... LOG(LOG_INFO,"DTE communication inactivity timeout"); mdm_disconnect(cfg); } return 0; } int mdm_send_ring(modem_config *cfg) { LOG(LOG_DEBUG,"Sending 'RING' to modem"); cfg->line_ringing = TRUE; mdm_send_response(MDM_RESP_RING,cfg); cfg->rings++; LOG(LOG_ALL,"Sent #%d ring",cfg->rings); if(cfg->cmd_mode == FALSE || (cfg->s[0] != 0 &&cfg->rings>=cfg->s[0])) { mdm_answer(cfg); } return 0; } tcpser/src/modem_core.h0100644000076400010400000000745610443647776016342 0ustar brainAdministrators#ifndef MODEM_CORE_H #define MODEM_CORE_H 1 #define MDM_RESP_OK 0 #define MDM_RESP_CONNECT 1 #define MDM_RESP_RING 2 #define MDM_RESP_NO_CARRIER 3 #define MDM_RESP_ERROR 4 #define MDM_RESP_CONNECT_1200 5 #define MDM_RESP_NO_DIALTONE 6 #define MDM_RESP_BUSY 7 #define MDM_RESP_NO_ANSWER 8 #define MDM_RESP_CONNECT_0600 9 #define MDM_RESP_CONNECT_2400 10 #define MDM_RESP_CONNECT_4800 11 #define MDM_RESP_CONNECT_9600 12 #define MDM_RESP_CONNECT_7200 13 #define MDM_RESP_CONNECT_12000 14 #define MDM_RESP_CONNECT_14400 15 #define MDM_RESP_CONNECT_19200 16 #define MDM_RESP_CONNECT_38400 17 #define MDM_RESP_CONNECT_57600 18 #define MDM_RESP_CONNECT_115200 19 #define MDM_RESP_CONNECT_234000 20 #define MDM_CL_DSR_LOW 0 #define MDM_CL_DSR_HIGH 1 #define MDM_CL_DCD_LOW 0 #define MDM_CL_DCD_HIGH 2 #define MDM_CL_CTS_LOW 0 #define MDM_CL_CTS_HIGH 4 #define MDM_CL_DTR_LOW 0 #define MDM_CL_DTR_HIGH 8 #define MDM_FC_RTS 1 #define MDM_FC_XON 2 #define MDM_CONN_NONE 0 #define MDM_CONN_OUTGOING 1 #define MDM_CONN_INCOMING 2 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #include "nvt.h" #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif typedef struct line_config { int valid_conn; int fd; int sfd; int is_telnet; int first_char; nvt_vars nvt_data; } line_config; typedef struct x_config { int mp[2][2]; int cp[2][2]; int wp[2][2]; unsigned char no_answer[256]; unsigned char local_connect[256]; unsigned char remote_connect[256]; unsigned char local_answer[256]; unsigned char remote_answer[256]; unsigned char inactive[256]; unsigned int direct_conn; unsigned char direct_conn_num[256]; } x_config; typedef struct dce_config { int is_ip232; unsigned char tty[256]; int first_char; int fd; int dp[2][2]; int sSocket; int ip232_is_connected; int ip232_dtr; int ip232_dcd; int ip232_iac; } dce_config; typedef struct modem_config { // master configuration information // need to eventually change these dce_config dce_data; line_config line_data; x_config data; unsigned char config0[1024]; unsigned char config1[1024]; int dce_speed; int dte_speed; int conn_type; int line_ringing; int off_hook; int dsr_active; int dsr_on; int dcd_on; int invert_dsr; int invert_dcd; int allow_transmit; int rings; // command information int pre_break_delay; int found_a; int cmd_started; int cmd_mode; unsigned char last_cmd[1024]; unsigned char cur_line[1024]; int cur_line_idx; // dailing information unsigned char dialno[256]; unsigned char last_dialno[256]; unsigned char dial_type; unsigned char last_dial_type; int memory_dial; // modem config int connect_response; int response_code_level; int send_responses; int text_responses; int echo; int s[100]; int break_len; int disconnect_delay; unsigned char crlf[3]; } modem_config; int mdm_init(void); void mdm_init_config(modem_config* cfg); int get_new_cts_state(modem_config *cfg, int up); int get_new_dsr_state(modem_config *cfg, int up); int get_new_dcd_state(modem_config *cfg, int up); int mdm_set_control_lines(modem_config *cfg); void mdm_write_char(modem_config *cfg,unsigned char data); void mdm_write(modem_config *cfg,unsigned char data[], int len); void mdm_send_response(int msg,modem_config *cfg); int mdm_off_hook(modem_config *cfg); int mdm_answer(modem_config *cfg); int mdm_print_speed(modem_config *cfg); int mdm_connect(modem_config* cfg); int mdm_listen(modem_config *cfg); int mdm_disconnect(modem_config* cfg); int mdm_parse_cmd(modem_config* cfg); int mdm_handle_char(modem_config* cfg, unsigned char ch); int mdm_clear_break(modem_config* cfg); int mdm_parse_data(modem_config* cfg,unsigned char* data, int len); int mdm_handle_timeout(modem_config* cfg); int mdm_send_ring(modem_config *cfg); #include "line.h" #include "shared.h" #include "dce.h" #endif tcpser/src/nvt.c0100644000076400010400000000722410414144530014776 0ustar brainAdministrators#include #include "debug.h" #include "ip.h" #include "nvt.h" int nvt_init_config(nvt_vars *vars) { int i; vars->binary_xmit = FALSE; vars->binary_recv = FALSE; for (i = 0; i < 256; i++) vars->term[i] = 0; return 0; } unsigned char get_nvt_cmd_response(unsigned char action, unsigned char type) { unsigned char rc=0; if(type == TRUE) { switch (action) { case NVT_DO: rc=NVT_WILL_RESP; break; case NVT_DONT: rc=NVT_WONT_RESP; break; case NVT_WILL: rc=NVT_DO_RESP; break; case NVT_WONT: rc=NVT_DONT_RESP; break; } } else { switch (action) { case NVT_DO: case NVT_DONT: rc=NVT_WONT_RESP; break; case NVT_WILL: case NVT_WONT: rc=NVT_DONT_RESP; break; } } return rc; } int parse_nvt_subcommand(int fd, nvt_vars *vars , unsigned char * data, int len) { // overflow issue, again... int opt=data[2]; unsigned char resp[100]; unsigned char *response = resp + 3; int resp_len = 0; int response_len = 0; unsigned char tty_type[]="VT100"; int rc; int slen=0; for (rc = 2; rc < len - 1; rc++) { if (NVT_IAC == data[rc]) if (NVT_SE == data[rc + 1]) { rc += 2; break; } } if (rc > 5 && (NVT_SB_SEND == data[4])) { switch(opt) { case NVT_OPT_TERMINAL_TYPE: case NVT_OPT_X_DISPLAY_LOCATION: // should not have to have these case NVT_OPT_ENVIRON: // but telnet seems to expect. case NVT_OPT_NEW_ENVIRON: // them. case NVT_OPT_TERMINAL_SPEED: response[response_len++] = NVT_SB_IS; switch(opt) { case NVT_OPT_TERMINAL_TYPE: slen=strlen(tty_type); strncpy(response + response_len,tty_type,slen); response_len += slen; break; } break; } } if (response_len) { resp[resp_len++]=NVT_IAC; resp[resp_len++]=NVT_SB; resp[resp_len++]=opt; resp_len += response_len; resp[resp_len++]=NVT_IAC; resp[resp_len++]=NVT_SE; ip_write(fd,resp,resp_len); } return rc; } int send_nvt_command(int fd, nvt_vars *vars, unsigned char action, unsigned char opt) { unsigned char cmd[3]; cmd[0]= NVT_IAC; cmd[1] = action; cmd[2]= opt; ip_write(fd,cmd,3); vars->term[opt] = action; return 0; } int parse_nvt_command(int fd, nvt_vars *vars, unsigned char action, unsigned char opt) { unsigned char resp[3]; resp[0]= NVT_IAC; resp[2]= opt; switch (opt) { case NVT_OPT_TRANSMIT_BINARY : switch (action) { case NVT_DO : LOG(LOG_INFO,"Enabling telnet binary xmit"); vars->binary_xmit = TRUE; break; case NVT_DONT : LOG(LOG_INFO,"Disabling telnet binary xmit"); vars->binary_xmit = FALSE; break; case NVT_WILL : LOG(LOG_INFO,"Enabling telnet binary recv"); vars->binary_recv = TRUE; break; case NVT_WONT : LOG(LOG_INFO,"Disabling telnet binary recv"); vars->binary_recv = FALSE; break; } // fall through to get response case NVT_OPT_NAWS: case NVT_OPT_TERMINAL_TYPE: case NVT_OPT_SUPPRESS_GO_AHEAD: case NVT_OPT_ECHO: case NVT_OPT_X_DISPLAY_LOCATION: // should not have to have these case NVT_OPT_ENVIRON: // but telnet seems to expect. case NVT_OPT_NEW_ENVIRON: // them. case NVT_OPT_TERMINAL_SPEED: resp[1] = get_nvt_cmd_response(action,TRUE); break; default: resp[1] = get_nvt_cmd_response(action,FALSE); break; } ip_write(fd,resp,3); return 0; } tcpser/src/nvt.h0100644000076400010400000000243210413606554015007 0ustar brainAdministrators#ifndef NVT_H #define NVT_H 1 #define NVT_SE 240 #define NVT_NOP 241 #define NVT_DM 242 #define NVT_SB 250 #define NVT_WILL 251 #define NVT_WONT 252 #define NVT_DO 253 #define NVT_DONT 254 #define NVT_IAC 255 #define NVT_WILL_RESP 251 #define NVT_WONT_RESP 252 #define NVT_DO_RESP 253 #define NVT_DONT_RESP 254 #define NVT_OPT_TRANSMIT_BINARY 0 #define NVT_OPT_ECHO 1 #define NVT_OPT_SUPPRESS_GO_AHEAD 3 #define NVT_OPT_STATUS 5 #define NVT_OPT_RCTE 7 #define NVT_OPT_TIMING_MARK 6 #define NVT_OPT_NAOCRD 10 #define NVT_OPT_TERMINAL_TYPE 24 #define NVT_OPT_NAWS 31 #define NVT_OPT_TERMINAL_SPEED 32 #define NVT_OPT_LINEMODE 34 #define NVT_OPT_X_DISPLAY_LOCATION 35 #define NVT_OPT_ENVIRON 36 #define NVT_OPT_NEW_ENVIRON 39 #define NVT_SB_IS 0 #define NVT_SB_SEND 1 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif typedef struct nvt_vars { int binary_xmit; int binary_recv; unsigned char term[256]; } nvt_vars; unsigned char get_nvt_cmd_response(unsigned char action, unsigned char type); int parse_nvt_subcommand(int fd, nvt_vars *vars , unsigned char * data, int len); int parse_nvt_command(int fd, nvt_vars *vars, unsigned char action, unsigned char opt); int nvt_init_config(nvt_vars *vars); int send_nvt_command(int fd, nvt_vars *vars, unsigned char action, unsigned char opt); #endif tcpser/src/phone_book.c0100644000076400010400000000165010313726146016316 0ustar brainAdministrators#include #include #include "phone_book.h" #include "debug.h" #define PBSIZE 100 unsigned char phone_book[PBSIZE][2][128]; int size=0; int pb_init() { return 0; } int pb_add(unsigned char* from,unsigned char* to) { LOG_ENTER(); if(size < PBSIZE && from != NULL && to != NULL && strlen(from) > 0 && strlen(to) > 0 ) { // should really trim spaces. strncpy(phone_book[size][0],from,sizeof(phone_book[size][0])); strncpy(phone_book[size][1],to,sizeof(phone_book[size][1])); size++; LOG_EXIT(); return 0; } LOG_EXIT(); return -1; } unsigned char* pb_search(unsigned char *number) { int i=0; LOG_ENTER(); for(i=0;i #include #include #include #include #include #include "debug.h" #include "serial.h" int ser_get_bps_const(int speed) { int bps_rate=0; LOG_ENTER(); LOG(LOG_DEBUG,"Checking speed: %d",speed); switch (speed) { case 115200: bps_rate=B115200; break; case 57600: bps_rate=B57600; break; case 38400: bps_rate=B38400; break; case 19200: bps_rate=B19200; break; case 9600: bps_rate=B9600; break; case 4800: bps_rate=B4800; break; case 2400: bps_rate=B2400; break; case 1200: bps_rate=B1200; break; case 600: bps_rate=B600; break; case 300: bps_rate=B300; break; case 150: bps_rate=B150; break; case 134: bps_rate=B134; break; case 110: bps_rate=B110; break; case 75: bps_rate=B75; break; case 50: bps_rate=B50; break; case 0: bps_rate=B0; break; default: ELOG(LOG_FATAL,"Unknown baud rate"); bps_rate=-1; } LOG_EXIT(); return bps_rate; } int ser_init_conn(unsigned char* tty, int speed) { int fd = -1; struct termios tio; int bps_rate=0; LOG_ENTER(); bps_rate=ser_get_bps_const(speed); if(bps_rate > -1) { /* open the device to be non-blocking (read will return immediatly) */ LOG(LOG_INFO,"Opening serial device"); fd = open(tty, O_RDWR | O_NOCTTY); if (fd <0) { ELOG(LOG_FATAL,"TTY %s could not be opened",tty); } else { LOG(LOG_INFO,"Opened serial device %s at speed %d as fd %d",tty,speed,fd); /* Make the file descriptor asynchronous (the manual page says only O_APPEND and O_NONBLOCK, will work with F_SETFL...) */ fcntl(fd, F_SETFL, FASYNC); tio.c_cflag = bps_rate | CS8 | CLOCAL | CREAD | CRTSCTS; tio.c_iflag = (IGNBRK); tio.c_oflag = 0; tio.c_lflag = 0; tio.c_cc[VMIN]=1; tio.c_cc[VTIME]=0; tcflush(fd, TCIFLUSH); cfsetispeed(&tio, bps_rate); cfsetospeed(&tio, bps_rate); tcsetattr(fd,TCSANOW,&tio); LOG(LOG_INFO,"serial device configured"); } } LOG_EXIT(); return fd; } int ser_set_flow_control(int fd, int status) { struct termios tio; if(0 != tcgetattr(fd,&tio)) { ELOG(LOG_FATAL,"Could not get serial port attributes"); return -1; } // turn all off. tio.c_cflag &= ~(IXON | IXOFF | CRTSCTS); tio.c_cflag |= status; if(0 != tcsetattr(fd,TCSANOW,&tio)) { ELOG(LOG_FATAL,"Could not set serial port attributes"); return -1; } return 0; } int ser_get_control_lines(int fd) { int status; if(0 > ioctl(fd, TIOCMGET, &status)) { ELOG(LOG_FATAL,"Could not obtain serial port status"); return -1; } return status; } int ser_set_control_lines(int fd, int state) { unsigned int status; if(0 > (status=ser_get_control_lines(fd))) { return status; } status &= ~(TIOCM_RTS | TIOCM_DTR); status |= state; if(0 > ioctl(fd, TIOCMSET, &status)) { #ifndef WIN32 ELOG(LOG_FATAL,"Could not set serial port status"); return -1; #else ELOG(LOG_WARN,"Could not set serial port status, CYGWIN bug?"); #endif } return 0; } int ser_write(int fd, unsigned char* data,int len) { log_trace(TRACE_MODEM_OUT,data,len); return write(fd,data,len); } int ser_read(int fd, unsigned char* data, int len) { int res; res=read(fd,data,len); log_trace(TRACE_MODEM_IN,data,res); return res; } tcpser/src/serial.h0100644000076400010400000000063410066743622015463 0ustar brainAdministrators#ifndef SERIAL_H #define SERIAL_H 1 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif int ser_get_bps_const(int speed); int ser_init_conn(unsigned char* tty, int speed); int ser_set_flow_control(int fd, int status); int ser_get_control_lines(int fd); int ser_set_control_lines(int fd, int state); int ser_write(int fd, unsigned char* data,int len); int ser_read(int fd, unsigned char* data, int len); #endif tcpser/src/shared.c0100644000076400010400000000051010103126026015417 0ustar brainAdministrators#include "modem_core.h" int sh_init_config(modem_config *cfg) { cfg->data.local_connect[0]=0; cfg->data.remote_connect[0]=0; cfg->data.local_answer[0]=0; cfg->data.remote_answer[0]=0; cfg->data.no_answer[0]=0; cfg->data.inactive[0]=0; cfg->data.direct_conn=FALSE; cfg->data.direct_conn_num[0]=0; return 0; } tcpser/src/shared.h0100644000076400010400000000012510066743622015445 0ustar brainAdministrators#ifndef SHARED_H #define SHARED_H 1 int sh_init_config(modem_config *cfg); #endif tcpser/src/tcpmdm.c0100644000076400010400000000505310066743622015463 0ustar brainAdministrators#include #include #include #include #include #include #include "serial.h" #include "ip.h" #include "debug.h" #include "tcpser.h" int main(int argc, char* argv[]) { struct timeval timer; struct timeval* ptimer; unsigned char tty[255]="/dev/ttyS2"; //unsigned char addy[255]="dilbert:6400"; unsigned char init[255]="at"; unsigned char cr[1]="\x0d"; int speed=38400; int sfd=-1; int csd=-1; //int ssd=-1; int max_fd=0; fd_set readfs; int res=0; unsigned char buf[255]; int rc; log_init(); log_set_trace_flags(TRACE_MODEM_IN | TRACE_MODEM_OUT); log_set_level(7); // open serial port // config serial port if(0 > (sfd = ser_init_conn(tty,speed))) { ELOG(LOG_FATAL,"Could not open serial port"); exit(-1); } // send init string if(strlen(init) > 0) { ser_write(sfd,init,strlen(init)); ser_write(sfd,cr,1); } // if configured, listen on ip address // check for carrier detect line // when line goes high, connect to IP:port // when line goes low, disconnect for(;;) { FD_ZERO(&readfs); max_fd=sfd; FD_SET(sfd, &readfs); if(-1 < csd) { // we are connected. max_fd=MAX(max_fd,csd); FD_SET(csd, &readfs); } max_fd++; timer.tv_sec=0; timer.tv_usec=1000; ptimer=&timer; LOG(LOG_ALL,"csd=%d",csd); rc=select(max_fd, &readfs, NULL, NULL, ptimer); if(-1 == rc) { ELOG(LOG_WARN,"Select returned error"); } else if (0 == rc) { // timer popped. if(-1 == csd && (ser_get_control_lines(sfd) & TIOCM_CD) > 0) { // we need to connect // commented out for now. //csd=ip_connect(addy); } else if(-1 < csd && (ser_get_control_lines(sfd) & TIOCM_CD) == 0) { // we need to disconnect. ip_disconnect(csd); csd=-1; } } else if(rc > 0) { // we got data from someone. if (FD_ISSET(sfd,&readfs)) { // serial port LOG(LOG_DEBUG,"Data available on serial port"); res = ser_read(sfd,buf,sizeof(buf) -1); if(res > 0 && csd > -1) { ip_write(csd,buf,res); } } if (csd > -1 && FD_ISSET(csd,&readfs)) { // ip port LOG(LOG_DEBUG,"Data available on tcp/ip port"); res = ip_read(sfd,buf,sizeof(buf) -1); if(res==0) { // conn closed, disconnect. ip_disconnect(csd); csd=-1; } if(res > 0 && csd > -1) { ser_write(csd,buf,res); } } } } } tcpser/src/tcpmdm.h0100644000076400010400000000000110066743622015454 0ustar brainAdministrators tcpser/src/tcpser.c0100644000076400010400000000732010747412616015500 0ustar brainAdministrators#include #include #include #include #include #include #include #include "init.h" #include "ip.h" #include "modem_core.h" #include "bridge.h" #include "phone_book.h" #include "util.h" #include "debug.h" #include "tcpmdm.h" const unsigned char MDM_BUSY[]="BUSY\n"; int main(int argc, char *argv[]) { modem_config cfg[64]; int modem_count; int port=0; unsigned char all_busy[255]; pthread_t thread_id; int i; int rc; int sSocket = 0; fd_set readfs; int max_fd=0; int accept_pending=FALSE; int res=0; unsigned char buf[255]; int cSocket; log_init(); LOG_ENTER(); log_set_level(LOG_FATAL); mdm_init(); pb_init(); signal(SIGIO,SIG_IGN); /* Some Linux variant term on SIGIO by default */ modem_count = init(argc, argv, cfg, 64, &port,all_busy,sizeof(all_busy)); sSocket = ip_init_server_conn(port); for(i=0;idce_data.tty); exit(-1); } cfg[i].line_data.sfd=sSocket; rc=pthread_create(&thread_id,NULL,*run_bridge,(void *)&cfg[i]); if(rc < 0) { ELOG(LOG_FATAL,"IP thread could not be started"); exit(-1); } } for(;;) { FD_ZERO(&readfs); max_fd=0; for(i=0;i -1) { buf[res]=0; LOG(LOG_DEBUG,"modem core #%d sent response '%c'",i,buf[0]); accept_pending=FALSE; } } } if (FD_ISSET(sSocket,&readfs)) { // IP traffic if(!accept_pending) { LOG(LOG_DEBUG,"Incoming connection pending"); // first try for a modem that is listening. for(i=0;i -1) { if(strlen(all_busy) < 1) { ip_write(cSocket,(unsigned char*)MDM_BUSY,strlen(MDM_BUSY)); } else { writeFile(all_busy,cSocket); } close(cSocket); } } } } } LOG_EXIT(); return rc; } tcpser/src/tcpser.h0100644000076400010400000000000010066743622015467 0ustar brainAdministratorstcpser/src/util.c0100644000076400010400000000106510066743622015153 0ustar brainAdministrators#include #include #include "util.h" int writePipe(int fd,unsigned char msg) { unsigned char tmp[3]; tmp[0]=msg; tmp[1]='\n'; tmp[2]='\0'; //printf("Writing %c to pipe fd: %d\n",msg,fd); return write(fd,tmp,2); } int writeFile(unsigned char* name, int fd) { FILE* file; unsigned char buf[255]; size_t len; size_t size=1; size_t max=255; if(NULL != (file = fopen(name,"rb"))) { while(0 < (len = fread(buf,size,max,file))) { write(fd, buf, len); } fclose(file); return 0; } return -1; } tcpser/src/util.h0100644000076400010400000000012610443714300015143 0ustar brainAdministratorsint writePipe(int fd,unsigned char msg); int writeFile(unsigned char* name, int fd); tcpser/tcpser.exe0100755000076400010400000017657110747540171015270 0ustar brainAdministratorsMZ@ !L!This program cannot be run in DOS mode. $PELyG 8$f@@ 0.text `.rdata@@.bsse.idata0@U@t}E%fEE ?fEm$z@zÐUS]=@~.$D$ @D$@@${88$o(4ǃ0|uǃ$<ǃǃ$hN=@~6$.@D$ D$$D$$4@zD$+P$ f=@~.$D$ @D$Y@@$zL[]UWVS<} E@uiǀ@<< ШtL=@~6$U@D$ D$D$$n@zUǂ<E<|;]L<T==} ===@~6$@D$ D$D$$~@qyDD$ D$EDD$U4$OZE)؉D$ D$EDD$U4$M)EHt Ƅ.FC8.Fu&ED$D$U$8;]t9Ƅ5t$D$E$f8UT$|$E$N8<[^_]UWVS<uDž=@~.$>D$@D$@@$xB@vd <ƒuTtKuB4~90u04 <;}BD$D$ D$D$$9wup=@/$?@D$ D$D$$@wv$vD$D$@@$v0X49=@~6$@D$ D$D$$@nvD$ D$|$4$vÅa=@~6$:@D$ D$'D$$Ԡ@vD$D`$aDžk=@~*$\$D$@@$uPƄ\$D$$m\$|$4$dуFD$D$$t=@~6$3@D$ D$D$$@tDžUWVS}=@~.$D$)@D$@@$tL<$nÃ<$n9؃9uW=@~6$]@D$ D$D$$5@$tD$dp$9_U=@~6$@D$ D$D$$F@sqD$Dp$^=@~.$D$)@D$Y@@$s$sUSED$ D$:@D$E$rÃ=@~-$8ED$D$X@@$sys=@~^$@D$ D$ D$$l@rr$rD$D$@@$rA$,r[]USED$ D$@D$E$qÃ=@~-$UED$D$@@$5rys=@~^$@D$ D$D$$@qq$qD$D$@@$q^$Iq[]UWVS\]=@~.$D$@D$@@$mql$pus=@~^$D@D$ D$>D$$̡@ qp$pD$D$@@$p$rp\$Dpus=@~^$ @D$ D$0D$$ @pPp$VpD$D$@@$mp$od$ous=@~^$8 @D$ D$0D$$@@oo$oD$D$@@$o{ $fo$Z$5$.D$ D$$nǃ$2$3|:D$D$$n$ltK=@~6$ @D$ D$&D$$t@ns $^nǃǃ9=@~6$ @D$ D$"D$$@^n D$Nh$sYuD|t4D$|$yY|te4D$|$XYKuB|t4D$|$,Y|t4D$|$ Y9t"D$Nh$X=@~y$n @D$ D$4D$$@5m =@~:$/ D$ D$D$@@$m T9}Ƌl9}Ƌ\9}ƍB@vT  l \ Ut pud=@~6$ @D$ D$D$$@k{ Dži NSugp~^=@~6$@D$ D$-D$$<@ak DžDžX=@~6$/@D$ D$"D$$l@jXDžtukub0uY=@~6$@D$ D$D$$@yjDžDžFD$D$ D$D$4$#jup=@$)@D$ D$D$$@ii$iD$D$@@$ilu}ut0ukuX uO|u$@IL$T$$3e4D$|$T$`,$k<$:=@~6$@D$ D$D$$@hsD$D$$cƃ=@~*$t$D$ȣ@@$h$~Bu#u$+\$$](t$D$$8lуtmD$D$$gƄ=@~1$D$D$@@$gedu$*\уD$D$$ g=@~1$oD$D$@@$KgDun|u]=@~6$#@D$ D$OD$$,@fǃ|$)ǃ|$)T=@~6$@D$ D$#D$$|@ff D$D$T$e+$\}Uf@@@@t@@x@@@@@@D@@H@@L@@P@Ť@T@ʤ@X@Ф@\@ۤ@h@@D$$@-fu$@ f$dUE@]UE@]UE@]U@]UWVS@fE}f}U@E;]uu\$D$?@4$CeE <|$D$F@؅yC)RD0$eG^w؅yC)‰ЉT؅yC)D.؅yC)ƒuD$ -ED$ED$ Up@D$D$L@@$c؅yC)RfD0 C;]؅yC)Åi؅yC)Rf@ @؅yC)ƒt؅yC)RfD0 ؅yC)D C~$ AED$ED$ Up@D$D$L@@$ cČ[^_]UST$@icu$V@xci$:cEԍEԉ$ cD$ D$s@D$]؉$bbU@@T$D$ \$D$@@$mbT[]U@D$$ \b@$ob$@Sbu $V@bUWVSM }EU99u29G0}>t3 u9}uE;tSU;t@E@u92.}uU;}t E99gE[^_]UWVS}u EE9}D8l1ADt0E ;LHЍCU9}8l1ADu׸}tȃ[^_]U $t$|$}M u]91}88uB9}88t$t$|$]US MU@ED$T$ $ U؃ []UVSu ]ED$\$ ED$t$E$~ ;y¡l1ADt [^]UWVSu ]}|$ED$ \$t$M $@ED$ |$\$E$9;M@=t?tPdD$ |$\$E$E$D$E D$ED$ |$\$M $x3E8yUl1ADt Ѓ[^_]UWVS ] E}E}}I9 u0l1ADt փ:::3%t^%tK v&-p_SSDC\tx9_9 I}8l1ADt t u 1(L$ED$ \$D$u4$s9 |9 }8l1ADt t u 1L$ED$ \$D$u4$ 9 |9 w}8l1ADt t u 1VL$ED$ \$D$ u4$/9 |9 }8l1ADt t u 1L$ED$ \$D$u4$89 |9 }8l1ADt ZtZRt uInzD$ED$ut$L$}|$ \$D$E$ =L$ut$ \$D$}<$9 [}8l1ADt PtPLt$Tu}8l1ADt ED$}|$ED$ L$\$}<$E9 }ocD$ut$}|$L$ED$ \$D$u4$0L$}|$ \$D$E${ 9  [^_]USD@E衤@E졨@EEEEEED$ED$ E܉D$E؉D$E$YËED$ED$E܉D$ E؉D$\$$@ZuD[]ÐUWVSLuE}=@~.$D$@D$@@$Y==@~6$@D$ D$D$$ @ZYD$D$$ZÃup=@$-@D$ D$"D$$$@XX$XD$D$G@@$XpqED$EԉD$ D$D$$DZug=@~^$@D$ D$-D$$P@UX X$&XD$D$G@@$=XEfEƆfEڃ=@~*$t$D$@@$WD$E؉D$$hYuq=@~^$@D$ D$(D$$@WTW$ZWD$D$G@@$qW=@~6$Q@D$ D$D$$ͦ@WD$$Xǃ=@~6$@D$ D$'D$$@Vkul=@~^$@D$ D$&D$$@VNV$TVD$D$G@@$kV=@~.$PD$@D$;@@$/V؃L[^_]UWVS=@~5$E$RD$D$ @@$kQ=@~.$UD$է@D$;@@$4Q4_]UE~$RU]uu ]\$t$$\$t$E$Q]u]U]uu D$ ED$t$E$JPÉD$t$$\؋]u]ÐU%QUT$D$@@@ $KPQ@ D$ D$,D$$X@PP@ D$ D$&D$$@OP@ D$ D$D$$@OP@ D$ D$D$$ɨ@OfP@ D$ D$D$$@sO>P@ D$ D$D$$@KOP@ D$ D$9D$$@#OO@ D$ D$%D$$P@NO@ D$$ OO@ D$ D$7D$$x@NO@ D$ D$HD$$@N^O@ D$$ NFO@ D$ D$?D$$@SNO@ D$ D$DD$$<@+NN@ D$ D$-D$$@NN@ D$ D$6D$$@MN@ D$ D$D$$@M~N@ D$ D$,D$$@MVN@ D$ D$2D$$4@cM.N@ D$ D$3D$$h@;MN@ D$ D$3D$$@MM@ D$ D$4D$$Ы@LM@ D$ D$'D$$@LM@ D$ D$+D$$0@LfM@ D$ D$0D$$\@sL>M@ D$ D$QD$$@KLM@ D$ D$PD$$@#L$KUWVS,EEEE=@~.$D$5@D$:@@$KdEU$VMǁǁEЋU9UD$P@M L$E$=ME?7o$@ á1A‹8@0StSItitsu $F1A:I9rD$1AD$iE|U|$ JD$1AD$iE|M|$ID$1AD$iE|U|$ISD$1AD$iE|M|$vI"E D$1AD$U$TID$1AD$iE|M|$#ID$1AD$iE|U|$HD$1AD$iE|M $HmiE|UDŽS1A$JM:D$y@1A$JD$y@$lJD$$41A$t6Kt!tt]US]ǃǃǃǃǃǃǃǃǃǃDŽ@c~ǃ+ǃ ǃ ǃǃǃ2ǃǃǃǃ _ǃ2ƃx ƃy ƃzƃƃǃtǃǃpǃǃǃǃǃǃǃǃǃƃ ƃ $7$/$.=[]U]UEU u'u t uu]UEU u'u t uu]U(]u}}؉\$<$5Ɖ\$<$1 Ɖ\$<$m ƃ=@~F$D$D$ D$D$@@$u@ t$<$8]u}]UE ED$ED$E$UUuED$E D$$;UH]u}]u =@~1$@D$D$@@$?JD$xD$4$`ug=@~6$p@D$ D$D$$1@7?@IL$T$4$u=@~6$ @D$ D$D$$G@>t\$D$`@]ȉ$T?IL$\$4${D$xD$4$a]u}]US]=@~6$c@D$ D$D$$c@*>ǃǃ$;[]US]u$ǃ$k$$0#u$H$$[]US]uD$$b\$$j[]US]$u:$-:uǃ$$uǃ$[]UE$9UVSu=@~.$D$y@D$@@$<C=@~6$@D$ D$D$$@`<dždždžpdždž4$:uPdž4$ t"t$$it$=dž4$=@~.$D$y@D$@@$;?[^]UWVSlDžDžDžDžDž]=@~.$=D$ư@D$@@$;=@~*$\$D$԰@@$:}vD$D$ D$D$$=@~~$D$ D$D$D$D$D$ ~D$D$@@$:NdNBBGXKMAp,HqHDE L}MXXTSSOQ|VWnCCY0Z?3KSUT$$iMuL$$C}<$DžDž;)‰T$D$E$7+UƄ)ЉD$T$E$6+MƄǁL}IL$T$U$]6MǁD$xD$ $װIL$T$U$MƁƁƁƁ}t <$ E$uUǂuMǁDžu}<$uE$|DžmH]DžNADž2%DžuUǂuMǁu}LJDž)ЉD$T$$]4+Ƅ $/6Ut t<Mx(}yUD$ xD$D$@ $4IL$T$U$uMǁu}LJ|DžmwUPDžAwM$DžDžDžtt4}LJ<$Eǀ$Džwv$(@D$U$_)^D$M $J)ID$}<$5)4D$E$ )D$U$ ) DžMǁl[^_]U(]u}u] uÉD$4$:u2uuD$T4$:uOƄ0D$D$$04$dždž2@xtT ШtRdž=@B$@D$ D$<D$$D@0/=@~6$@D$ D$7D$$@0:IL$T$$/4$džzaAtgdž[aA ШtI=@~6$@D$ D$D$$@/dž]u}]UEǀpǀ]U(]u}u}u*9 U D$4$*C9||$E D$4$+9U 8ud=@~6$@D$ D$D$$ر@.pp~]dždžpG=@~6$@D$ D$+D$$@~."4$C9>]u}]US]uopuf=@~6$9@D$ D$D$$ @.ǃ\$$$uN=@~6$@D$ D$D$$9@-5ǃuRp~I=@~6$j@D$ D$$D$$X@1-$dPXtG=@~6$@D$ D$$D$$@,$[]US]=@~6$@D$ D$D$$@,'ǃ\$$t=@~0$]D$D$@@$:,tt;|$[]ÐUUBD@=~]UU} u?ҁt0 tCt t1-)%!ҁ|~ ]UWVSUMBdDžTв@hԲ@flA~<u |uC9zdwwtiTƄ/{GTduKh\H`D$T${T$)`TTtUƄ.xFƄ.xFd.xTt>Ƅ.xFƄ.xFt$xD$E$؁ļ[^_]US4]EEE]ED$ED$E$UE \4[]UVS u E]EE'y$H@===5=t =tO"=@~6$6@D$ D$D$$ֲ@(=@~6$@D$ D$D$$@(W=@~6$@D$ D$D$$@i( FF=@~6$Z@D$ D$D$$+@!(FD$$>ED$$&ED$ED$E$ [^]ÐUVS]=@~.$D$@D$@@$''=@~*$}\$D$@@$`'XXnn82y2gKT>%, %%? ` `  Y FKtytl=@~^$@D$ D$D$$*@%%$%D$D$<@@$%B=@~.$D$@D$C@@$r%[^]UWVS\]=@~.$BD$X@D$@@$!%E $Aƃ=@~6$@D$ D$D$$f@$`D$$'Džyd=@R$\$D$|@@$$:$$@$D$D$<@@$W$=@~5$<|$E D$ \$D$@@$$D$@D$<$G& EEEEEED$<$&t$]$%t$$%\$D$<$%=@~6$@D$ D$D$$Ŵ@G#=@~.$AD$X@D$C@@$ #\[^_]USD]EȉD$$$tq=@~^$@D$ D$$D$$@"u"${"D$D$<@@$"&E%k E EЍEȉD$D$$n$tl=@~^$D@D$ D$$D$$@ "!$!D$D$<@@$!臿ЃD[]UED$D$TE$#yn=@~^$謾@D$ D$#D$$0@s!>!$D!D$D$<@@$[!EUS]$WEeE EED$D$T$#yg=@~^$@D$ D$-D$$T@ $ D$D$<@@$ B[]U]uu ]\$t$$P\$t$E$E!]u]U]uu ED$t$E$ÉD$t$$؋]u]ÐUWVS<EDž=@~.$D$@D$@@$SB@v 4ƃu!у <9}փ=@~6$@@D$ D$&D$$@諼D$D$ D$T$F$#уtcD$D$$@=@~6$菻@D$ D$D$$۵@VDžx ti=@~6$@D$ D$,D$$@}$ $=@~6$詺@D$ D$D$$!@pD$+$DžUSED$ D$ l@D$E$Ã=@~-$ED$D$;@@$舺ys=@~^$ڹ@D$ D$!D$$P@l$rD$D$r@@$$[]UVS]=@~.$QD$y@D$@@$0Ĺ=@~6$@D$ D$D$$@腹C$A$ƅys=@~^$¸@D$ D$(D$$@T$ZD$D$r@@$q$ $us=@~^$<@D$ D$3D$$̶@$D$D$r@@$$j$<us=@~^$趷@D$ D$3D$$@}H$ND$D$r@@$e$ǃ  $=@~6$@D$ D$D$$4@芷=@~.$D$y@D$L@@$S[^]U]UU t$t]UM t?E 9(t-(EE@D$D$$(UWVS,}Dž|$E D$$ɳM 9tƄ+CDžF0E <0uƄ+CDžFM +Cu*D$D$U$S»9wt!\$D$M$!‰Ё,[^_]UWVS,}]Dž=@~.$D$a@D$@@$]vK=@~6$諴@D$ D$D$$l@r$ }D$ \$D$$Åh=@~6$)@D$ D$-D$$@蔴$ LJ =@~*$\$D$@@$8\$D$$]9Q5,tTLJ,t t Z=tQLJ$ELJ$9U @#D$\$ @`@$D$t$ @@$ @=@~.$TD$@D$,@@$3ǰ<=@~.$D$@D$,@@$艰[^]UWVS}=@~.$ǯD$A@D$@@$:; @}y`@|$$uU=@~4$h@D$ |$D$K@@$Aկ@D$<$ C; @|=@~.$ D$A@D$,@@$}[^_]ÐUEƀ|ƀ|ƀ|ƀ|ƀ|ƀ|ǀ|ƀ]ÐUWVS\a@3DžDž̞=@~.$4D$v@D${@@$觮$趫 D$$D$D$D$D$ @D$E D$E$}Ԟ$萶О;Ԟ8i|4$us=@~^$N@D$ D$2D$$@$D$D$ø@@$葭$|i|<$Gus=@~^$@D$ D$2D$$̸@S$YD$D$ø@@$p$i|$$yE=@~0$5D$D$@@$覬$i|О( D$ D$@D$$Eys=@~^$谫@D$ D$D$$ @wB$HD$D$ø@@$_$ C;Ԟ؞B@vDžĞ;Ԟ}B؞i|((H  <@ 9Ğ}ĞC;Ԟ|ă̞u4О9Ğ}ĞОО ؞=@~6$腪@D$ D$2D$$@@L D$D$ D$؞D$Ğ@$ ;Ԟi|(4у؞toD$D$$w ~PƄ=@~5$蹩D$ \$D$t@@$ %Dž̞C;Ԟ`ОО؞̞=@~6$4@D$ D$D$$@ 蟩;Ԟi|UЃteu\=@~*$Ǩ\$D$@@$ >D$+i|(@$Dž̞ C;Ԟz;Ԟ}ui|(xu\=@~*$A\$D$@@$$ 踨D$+i|(@$"Dž̞ C;Ԟ|;Ԟ=@~6$Ч@D$ D$/D$$ @ ;О<$rÃHu(p@IL$D$p@$PD$$$. U]U]uu=@~.$D$P@D$^@@$ y>t 4$fD$F$VÉ=@~.$衦D$P@D$s@@$ ؋]u]U(]u}}] =@~.$DD$@D$^@@$# 跦uH=@$@D$ D$D$$@ptE=@~6$輥@D$ D$D$$@'tE=@~6$m@D$ D$D$$Ӻ@4إ?tt$<$}t$$Ã=@~.$D$@D$s@@$x؋]u}]U(]u}u} =@~.$襤D$@D$^@@$tD=@~6$f@D$ D$D$$@-Ѥ?=@~6$"@D$ D$D$$@荤tD=@~6$ۣ@D$ D$D$$0@F?=@~6$藣@D$ D$D$$E@^>t\$4$\$$Ã=@~.$/D$@D$s@@$袣؋]u}]UE8t $=$‰Ѓ~%ЃUWVS }=@~.$蛢D$Y@D$^@@$z<$sÉƅx$$9<$W9u܃=@~.$0D$Y@D$s@@$裢؃ [^_]UEM U8tT$L$$T$L$$&UEM U8tT$L$$T$L$$+ÐUEǀ4ǀ<ǀ@ǀ0D$BUWVS,} uDžE<D9}tƄ*BDžC*<uƄ*BDžC8*Bu*D$D$U4$q9|t!T$D$U4$Ct$|$U4$$,[^_]U]U]UVSu=@~6$@D$ D$ D$$@X$É$荬4~D=@~*$葟\$D$@@$tdž0B=@~*$M\$D$@@$0ğdž0[^]US]=@~6$@D$ D$ D$$@e|uF=@~6$貞@D$ D$*D$$Ļ@y:ǃ<ǃ@0u4$+ǃ0[]ÐQ=r -) ̋@U1uu]D$4$t $1A\$\$4$$Ӑ%@2A%1A%1A%1A%2A%2A%`1A%82A%2A%1A%1A%1A%2A%1A% 2A%1A%<2A%T2A%2A%,2A%1A%2A%d1A%1A%\2A%1A%1A%1A%1A%1A%1A%1A%1A%D2A%1A%1A% 2A%(2A%t1A%1A%X2A%1A%L2A%P2A%1A%1A%H2A%p1A%|1A%1A%1A%42A%02A%h1A%$2AUVS] uC1CC C,@C0@C4@x1ACCxEs(CH`@CLP@CP@@CT0@C$0@C @C@C @CD@$C|C4@C8@C<@C@%Ae[^]$z1tBӸBB 1҉C,@C0@C4@x1A %1A%t1A%p1A%|1AUMVuS] Q9r[^]ÍU@@ T$D$$@Ð%1A%2A%1A%1AU]ÐU]ÐU]ÐU]Ð%1A%t2ANO ANSWER accept_connectionEntering %s functionInforming parent task that I am busyExitting %s functionDetected telnetParsing nvt commandip_threadSelect returned error (%s) Data available on socketNo socket data read, assume closed peerRead %d bytes from socketIP thread notifiedctrl_threadDTR has gone lowDTR has gone highCTRL thread ID=%dCTRL thread could not be startedIP thread ID=%dIP thread could not be startedrun_bridgeControl line watch task incoming IPC pipe could not be createdIP thread incoming IPC pipe could not be createdIP thread outgoing IPC pipe could not be createdCannot connect to Direct line address!Connection status change, handlingWaiting for modem/control line/timer/socket activityCommand Mode=%d, Connection status=%dSetting timer for break delaySetting timer for inter-break character delaySetting timer for inactivity delaySetting timer for ringsData available on serial portRead %d bytes from serial portReceived %c from Control line watch taskReceived %c from ip threadDirect Connection Link broken, disconnecting and awaiting new direct connectionData available on incoming IPC pipeRS<-RS->IP<-IP->FATALERRORWARNINFODEBUGENTER_EXITDEBUG_XCould not create Log Mutex%4.4x|%2.2x%s|%s|%s|Could not lock the log mutex%Y-%m-%d %H:%M:%S%s:%5.5d:%s:DT 555-1212Cmd: %c Index: %d Num: %d Start: %d End: %d ip_init_server_connEntering %s functionCreating server socketServer socket could not be created (%s) bind address checking could not be turned offBinding server socket to port %dServer socket could not be bound to portServer socket bound to portServer socket listening for connectionsServer socket could not listen on portExitting %s functionip_connect:Calling %sHost %s was invalidcould not create client socketcould not connect to addressConnection to %s establishedip_acceptCould not accept incoming connectionCould not obtain peer nameConnection accepted from %sUsage: %s -p port to listen on (defaults to 6400) -t trace flags: (can be combined) 's' = modem input 'S' = modem output 'i' = IP input 'I' = IP input -l 0 (NONE), 1 (FATAL) - 7 (DEBUG_X) (defaults to 0) -L log file (defaults to stderr) The following can be repeated for each modem desired (-s, -S, and -i will apply to any subsequent device if not set again) -d serial device (e.g. /dev/ttyS0). Cannot be used with -v -v tcp port for VICE RS232 (e.g. 25232). Cannot be used with -d -s serial port speed (defaults to 38400) -S speed modem will report (defaults to -s value) -I invert DCD pin -n add phone entry (number=replacement) -a filename to send to local side upon answer -A filename to send to remote side upon answer -c filename to send to local side upon connect -C filename to send to remote side upon connect -N filename to send when no answer -B filename to send when modem(s) busy -T filename to send upon inactivity timeout -i modem init string (defaults to '', leave off 'at' prefix when specifying) -D direct connection (follow with hostname:port for caller, : for receiver) initEntering %s functionp:s:S:d:v:hw:i:Il:L:t:n:a:A:c:C:N:B:T:D:=w+Setting DTE speed to %dMaximum modems defined - ignoring extraNo modems definedRead configuration for %i serial port(s)Exitting %s function D@AF@A@B@A@ F@AF@AF@AF@AF@B@AF@AF@aC@AF@AB@AF@AF@AF@AF@E@rB@AF@AF@AF@AF@AF@AF@AF@AF@AF@AF@AF@AF@[A@AF@A@D@AF@AF@AF@ D@B@AF@AF@EC@AF@C@AF@B@AF@AF@C@@@AF@D@OKRINGERRORCONNECTNO CARRIERCONNECT 1200NO DIALTONEBUSYNO ANSWERCONNECT 0600CONNECT 2400CONNECT 4800CONNECT 9600CONNECT 7200CONNECT 12000CONNECT 14400CONNECT 19200CONNECT 38400CONNECT 57600CONNECT 115200CONNECT 230400Control Lines: DSR:%d DCD:%d CTS:%dSending %s response to modemSending text responseSending numeric response%dtaking modem off hookmdm_disconnectEntering %s functionDisconnecting modemExitting %s functionmdm_parse_cmdEvaluating AT%sCommand: %c (%d), Flags: %d, index=%d, num=%d, data=%d-%d%s%3.3dOY@Y@Y@dY@yY@Y@Y@'T' parsed in serial stream, switching to command parse mode'/' parsed in the serial stream, replaying last command'A' parsed in serial streamBreak character receivedFound non-break character, cancelling breakBreak condition detectedInitial Break Delay detectedInter-break-char delay time exceededDTE communication inactivity timeoutSending 'RING' to modemSent #%d ringVT100Enabling telnet binary xmitDisabling telnet binary xmitEnabling telnet binary recvDisabling telnet binary recvb@ d@#d@ d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@#d@ d@#d@#d@#d@#d@#d@#d@ d@ d@#d@#d@ d@ d@#d@#d@ d@ser_get_bps_constEntering %s functionChecking speed: %dUnknown baud rate (%s) Exitting %s functionser_init_connOpening serial deviceTTY %s could not be openedOpened serial device %s at speed %d as fd %dserial device configuredCould not get serial port attributesCould not set serial port attributesCould not obtain serial port statusCould not set serial port status, CYGWIN bug?ip232_threadEntering %s functionWaiting for incoming ip232 connectionsip232 thread notifiedAlready have ip232 connection, rejecting newIncoming ip232 connectionip232 thread ID=%dip232 thread could not be started (%s) ip232_init_connOpening ip232 deviceCould not initialize ip232 server socketip232 thread incoming IPC pipe could not be createdip232 thread outgoing IPC pipe could not be createdip232 device configuredExitting %s functionip232_readip232_read: len > sizeof(buf)No ip232 socket data read, assume closed peerRead %d bytes from ip232 socketAccepting ip232 connection...rbpb_addEntering %s functionExitting %s functionpb_searchFound a match for '%s': '%s'BUSY mainEntering %s functionBridge task incoming IPC pipe could not be created (%s) Bridge task outgoing IPC pipe could not be createdCould not open serial port %sIP thread could not be startedWaiting for incoming connections and/or indicatorsmodem core #%d sent response '%c'Incoming connection pendingSending incoming connection to listening modem #%dSending incoming connection to non-connected modem #%dNo open modem to send to, send notice and closedce_init_connEntering %s functionExitting %s functiondce_set_flow_controlSetting NONE flow controlSetting RTSCTS flow controlSetting XON/XOFF flow controldce_set_control_linesSetting CTS pin highSetting CTS pin lowSetting DCD pin highSetting DCD pin lowdce_check_control_linesConnectingConnected to %sCould not connect to %sDisconnectingDirect connection active, maintaining link@06`1T17t2|222222222223 33,343@3T3p3x3333333333334 44$404<4H4P4\4p4444444445 55$505<5H5T5`5l5x555555555|222222222223 33,343@3T3p3x3333333333334 44$404<4H4P4\4p4444444445 55$505<5H5T5`5l5x555555555__errno/__getreent5__main_ctype__fcntl64_fopen64F_impure_ptr_open64}acceptatoibindcalloccfsetispeedcfsetospeedcloseconnectcygwin_internaldll_crt0__FP11per_process-exit:fcloseGfflushafprintfbfputcdfreadefreefwritegethostbynamegetoptgetpeernameinet_atoninet_ntoaioctl.listen2localtimeKmallocoptargperrorpipeprintfpthread_createpthread_mutex_initpthread_mutex_lockpthread_mutex_unlockpthread_selfreadreallocrecv1select`setsockopt~signalsocketsprintfstrcmpstrcpystrerrorstrftimestrncpystrtoktcflushtcgetattrtcsetattrtimeusleepPwrite_fcntl64_fopen64_open64QGetModuleHandleA0000000000000000000000000000000000000000000000000000000000000000cygwin1.dll0A0A0A0KERNEL32.dll  .textA.data.bss.filegbridge.c' 6P I Xg r):      .textPJ.data.bss.rdata.file2gdebug.c       _log_end )4 .textH.data.bss.rdata.fileEggetcmd.c_getData 4 _skipb ? K YA _getcmd= h! .text.data.bss .rdata9.fileYgip.c'u0" XP& r)  + &+ _ip_readi+ .text0" .data.bss .rdata\.filegginit.c+ '5 _init 0 .text+q .data.bss .rdata@8.filegmodem_core.c@7 8 8 :  : : 0(; G; W0< j= x"> > 1? 'yX@ I `L L M YO D? > "< .text@7.data.bss .rdata.filegnvt.c-0P >\P TP j;R |R .text0P/.data.bss .rdata(.filegserial.c'`T XXV Y OZ Z [ [ .text`T.data.bss .rdata.filegip232.c'  \ ^ Xy,_ =b Ub nb c rad .text \, .data.bss .rdataj.filegutil.cPg g .textPg.data.bss .rdata.filegphone_book.c_pb_inith '_pb_add h XALi .texthV8.data.bss .rdataX.filegshared.c`j .text`jH.data.bss0.filegtcpser.c'v_mainj .textjGo.data.bss0.rdatap.filegdce.cr 'P r Xr r`t 6v Y5xv N0w Ynw .textro.data.bss0.rdataP!.filegline.ccw uw  y y !y z .textwC%.data.bss0.rdataoprobe{done{.text{-.data.bss00{ .text0{X.data.bss0.text{.idata$7.idata$5@.idata$4 .idata$6T.text{.idata$7x.idata$5.idata$4.idata$6H.text{.idata$7.idata$5.idata$4.idata$6\.text{.idata$7,.idata$5.idata$4.idata$6p.text{.idata$7.idata$5.idata$4.idata$6.text{.idata$7.idata$5.idata$4.idata$6.text{.idata$7.idata$5`.idata$4@.idata$6|.text|.idata$7.idata$58.idata$4.idata$6<.text|.idata$7.idata$5.idata$4.idata$6.text |.idata$7H.idata$5.idata$4.idata$6.text0|.idata$78.idata$5.idata$4.idata$6.text@|.idata$7<.idata$5.idata$4.idata$6.textP|.idata$7.idata$5.idata$4.idata$6.text`|.idata$74.idata$5.idata$4.idata$6.textp|.idata$7.idata$5 .idata$4.idata$6.text|.idata$7h.idata$5.idata$4.idata$6.text|.idata$7.idata$5<.idata$4.idata$6H.text|.idata$7.idata$5T.idata$44.idata$6.text|.idata$7.idata$5.idata$4.idata$6.text|.idata$7.idata$5,.idata$4 .idata$6.text|.idata$7t.idata$5.idata$4.idata$6<.text|.idata$7.idata$5.idata$4.idata$6p.text|.idata$7.idata$5d.idata$4D.idata$6.text}.idata$7.idata$5l.idata$4L.idata$6.text}.idata$7|.idata$5.idata$4.idata$6P.text}.idata$7.idata$5\.idata$4<.idata$6.text }.idata$7.idata$5.idata$4x.idata$6,.text0}.idata$7\.idata$5.idata$4.idata$6.text@}.idata$7T.idata$5.idata$4.idata$6.textP}.idata$7.idata$5.idata$4`.idata$6.text`}.idata$7 .idata$5.idata$4|.idata$64.textp}.idata$7X.idata$5.idata$4.idata$6.text}.idata$7L.idata$5.idata$4.idata$6.text}.idata$7.idata$5.idata$4d.idata$6.text}.idata$7.idata$5D.idata$4$.idata$6`.text}.idata$7d.idata$5.idata$4.idata$6 .text}.idata$7 .idata$5.idata$4h.idata$6.text}.idata$7.idata$5 .idata$4.idata$6.text}.idata$7.idata$5(.idata$4.idata$6 .text}.idata$7p.idata$5.idata$4.idata$60.text}.data.bss0.idata$7.idata$5h.idata$4H.idata$6 .text~.idata$7P.idata$5.idata$4.idata$6.text~.idata$7.idata$5X.idata$48.idata$6.text ~.idata$7`.idata$5.idata$4.idata$6.text0~.idata$7.idata$5L.idata$4,.idata$6x.text@~.idata$7.idata$5P.idata$40.idata$6.textP~.idata$7.idata$5.idata$4t.idata$6.text`~.idata$7.idata$5.idata$4p.idata$6 .textp~.idata$7.idata$5H.idata$4(.idata$6l.text~.data.bss0.idata$7.idata$5d.idata$4D.idata$6 .text~.data.bss0.idata$7.idata$5l.idata$4L.idata$6 .text~.idata$70.idata$5.idata$4.idata$6x.text~.idata$7@.idata$5.idata$4.idata$6.text~.idata$7.idata$54.idata$4.idata$60.text~.idata$7.idata$50.idata$4.idata$6$.text~.idata$7.idata$5h.idata$4H.idata$6.text~.idata$7.idata$5$.idata$4.idata$6 .textP.data.bss0.textP.idata$7(.idata$5.idata$4.idata$6T.text`.idata$7.idata$5t.idata$4T.idata$6.textp.idata$7.idata$5p.idata$4P.idata$6.text.idata$7.idata$5|.idata$4\.idata$6.text.idata$7.idata$5x.idata$4X.idata$6  .textV.data.bss@.text.idata$7.idata$5.idata$4l.idata$6.text.idata$7.idata$5.idata$4.idata$6.text.idata$7D.idata$5.idata$4.idata$6.text .idata$7l.idata$5.idata$4.idata$6$ 0 .text0.data.bss@@ .text@.data.bss@.P .textP.data.bss@?` .text`.data.bss@.textp.idata$7$.idata$5.idata$4.idata$6@.text.data.bss@.idata$7.idata$5t.idata$4T.idata$6.filegfakehnameTfthunkt.text.data.bss@.idata$2.idata$5p.idata$4P.filegfake.text.data.bss@.idata$4X.idata$5x.idata$7 .text.data.bss@.idata$2.idata$5\.idata$4<.idata$4@.idata$5`.idata$7P^Dl| _usleep~ | L_sprintf| @ 0~ _free #_strcmp~ 5AdN[@AjvP @A)@A;{E@A_socket} _select| U0} `ll{@~ P| _fputc@| \ _environ4! @A3 _open~ ? pI @AY $__dll__g _fwrite | _strncpy{ | }  @  _atoi}  @}  _connect`}  }  x ` p  4 (B | L p| Z @g u ,_fflush`|   e @A___main~  X_fprintf0| __alloca{ p}  @A ` _fread~  _fopen} _calloc  l | _time|  @__fmode0% P6 C |R e x  0 |  h   T _realloc    @_bind} " 7 F pV d_size __end__@A_recv{ h t `~  { _signal~ _malloc   _fclose~   _pipe{ _strcpy~     @A  _perror| _strtok} 3 A ] 4k | v  p H  ` h   @A_acceptP} _listen} ___errno{ %85tE_write} Qiz<_ioctl ~ _read{ 0_exit{ _tcflushp~  _printf} "DZp_getopt~ ft~_fcntl~ __open64@A _close } P~ _WinMainCRTStartup_mainCRTStartup__FUNCTION__.0_accept_connection_parse_ip_data__FUNCTION__.1_ip_thread__FUNCTION__.2_ctrl_thread_spawn_ctrl_thread_spawn_ip_thread__FUNCTION__.3_run_bridge_log_init_log_set_file_log_set_level_log_set_trace_flags_log_get_trace_flags_log_trace_log_start_getNumber_getCommand_parseCommand_parseRegister_main_getcmd_ip_init_server_conn_ip_connect_ip_accept_ip_disconnect_ip_write_print_help_mdm_init_get_connect_response_mdm_init_config_get_new_cts_state_get_new_dsr_state_get_new_dcd_state_mdm_set_control_lines_mdm_write_char_mdm_send_response_mdm_off_hook_mdm_answer_mdm_connect_mdm_listen_mdm_parse_cmd_mdm_handle_char_mdm_clear_break_mdm_parse_data_mdm_handle_timeout_mdm_send_ring_mdm_disconnect_mdm_print_speed_mdm_write_nvt_init_config_get_nvt_cmd_response_parse_nvt_subcommand_send_nvt_command_parse_nvt_command_ser_get_bps_const_ser_init_conn_ser_set_flow_control_ser_get_control_lines_ser_set_control_lines_ser_write_ser_read_ip232_thread_spawn_ip232_thread_ip232_init_conn_ip232_set_flow_control_ip232_get_control_lines_ip232_set_control_lines_ip232_write_ip232_read_writePipe_writeFile_pb_search_sh_init_config_dce_init_config_dce_init_conn_dce_set_flow_control_dce_set_control_lines_dce_get_control_lines_dce_check_control_lines_dce_write_dce_read_line_init_config_line_write_line_listen_line_off_hook_line_connect_line_disconnect_cygwin_crt0__cygwin_crt0_common@8_do_pseudo_reloc__pei386_runtime_relocator_cygwin_premain3_cygwin_premain2_cygwin_premain1_cygwin_premain0__imp__getopt__imp__strtok_pthread_mutex_init__imp__ioctl___RUNTIME_PSEUDO_RELOC_LIST____imp__read_pthread_mutex_lock__imp__tcgetattr_log_level___cygwin_crt0_bp__data_start_____DTOR_LIST___tcgetattr__nm___impure_ptr__imp__bind__imp__fcntl_trace_flags___tls_start____imp__recv_dll_crt0__FP11per_process_BACK_LOG__imp__pthread_mutex_init__imp__getpeername__size_of_stack_commit____size_of_stack_reserve____major_subsystem_version_____crt_xl_start_____crt_xi_start_____chkstk___crt_xi_end___inet_ntoa__imp__open__imp__connect_GetModuleHandleA@4_tcsetattr_pthread_mutex_unlock__bss_start____imp__fputc___RUNTIME_PSEUDO_RELOC_LIST_END____imp__select__imp__write__size_of_heap_commit_____crt_xp_start____imp__pipe_MDM_BUSY___crt_xp_end____imp__signal__minor_os_version___gethostbyname__image_base____imp__exit__section_alignment___getpeername__imp__inet_aton_setsockopt__imp___impure_ptr_phone_book_cygwin_internal__RUNTIME_PSEUDO_RELOC_LIST____imp__socket_strerror_pthread_self__data_end____CTOR_LIST____imp__sprintf__imp__perror__bss_end_____crt_xc_end____imp__usleep_inet_aton___crt_xc_start____fopen64___CTOR_LIST____imp__accept__imp___ctype____getreent_log_desc__imp__tcsetattr__imp__fread__imp___open64_cygwin1_dll_iname__head_cygwin1_dll__imp__cfsetispeed__imp__strcmp_strftime__imp____main__imp__pthread_mutex_lock__file_alignment____imp__time_MDM_NO_ANSWER__imp__malloc__imp__atoi__imp__strncpy__major_os_version____imp__realloc__imp___fcntl64__imp____getreent__imp__GetModuleHandleA@4_cfsetispeed_pthread_create__DTOR_LIST____imp__listen__imp__fprintf__imp__fclose__imp__close__size_of_heap_reserve_____crt_xt_start____subsystem____imp__gethostbyname__imp__fflush__imp__pthread_mutex_unlock__imp__strcpy_localtime__imp__calloc__fcntl64__imp__tcflush__imp__localtime__imp____errno__imp__fopen__imp__pthread_create__imp__cygwin_internal___tls_end____imp__dll_crt0__FP11per_process__imp__strerror__imp___fopen64__imp__free__major_image_version____loader_flags____imp__strftime__imp__printf__head_libkernel32_a__minor_subsystem_version____minor_image_version____nm__optarg__imp__pthread_self__imp__inet_ntoa_mdm_responses__RUNTIME_PSEUDO_RELOC_LIST_END____libkernel32_a_iname_trace_type__imp__optarg_log_file__imp__cfsetospeed__nm___ctype__log_mutex___crt_xt_end____imp__setsockopt_cfsetospeed__imp__fwrite