Consider the following R script:
con <- socketConnection(host = "localhost", port = 8, server = TRUE, blocking = TRUE, open = "a+b")
close(con = con)
Saving these lines as a .R file, and subsequently running it from command line produces (on Windows) a firewall warning. At least, if there is no rule for R under "Windows Firewall with Advanced Security", which appears after the first time. I've been told the same happens on a Mac, but I couldn't verify this myself. How can this be altered to allow for a localhost loopback, but avoid the popup?
Context: I've written some code for people that uses parallel processing (on one single local machine). However, this warning popped up on their screens, and they got suspicious. The silly thing is, that even if people click no or ignore the popup, the parallel processing still seems to works. I take that as a sign that it's possible to modify this code to not give this popup and still function.
I've seen very similar questions in other languages (1, 2, 3), and I was wondering whether it is possible to do the same with R.
Windows 10 Firewall First Time Prompt Example:
My sense is that the easiest way to navigate this problem is to add a firewall rule as part of the application install process.
You can use netsh to add a rule (administrator privileges are required) to enable firewall access programmatically.
I provide an example script below, and I hope this helps point you in the right direction.
Example firewall configuration script
netsh advfirewall firewall add rule name="RScript" action=allow program="C:\Program Files\Microsoft\R Client\R_SERVER\bin\x64\Rscript.exe" enable=yes Localip="127.0.0.1" localport="9999" protocol=tcp interfacetype=any profile=private dir=in
Command Output:
PS <hidden>\dev\stackoverflow\47353848> netsh advfirewall firewall add rule name="RScript" action=allow program="C
:\Program Files\Microsoft\R Client\R_SERVER\bin\x64\Rscript.exe" enable=yes Localip="127.0.0.1" localport="9999" protoco
l=tcp interfacetype=any profile=private dir=in
Ok.
Firewall Rule Added
Assuming you run the R file using RScript, the above netsh script will enable the RScript application to be able to access the loopback address 127.0.0.1 on port 9999 using TCP on a private network. From this point on you should not get a firewall prompt.
Command line with no prompt for firewall
c:\<hidden>\dev\stackoverflow\47353848> Rscript.exe .\server.R
Listening...
Why do this? Well, as far as I have been able to ascertain there is no way to use R's base::socketConnection on Windows without triggering the Windows Defender firewall prompt, even when using the loopback connector. Interesting to note is that if you use Java you don't get prompted. I looked at both implementations, but I couldn't determine why not.
Test Server Code:
server <- function() {
while (TRUE) {
writeLines("Listening...")
con <- socketConnection(host = "loopback",
port = 9999,
server = TRUE,
blocking = TRUE,
timeout = 0,
open = "r+")
data <- readLines(con, 1)
print(data)
response <- toupper(data)
writeLines(response, con)
close(con)
}
}
server()
Test Client Code
client <- function() {
while (TRUE) {
con <- socketConnection(host = "loopback",
port = 9999,
server = FALSE,
blocking = TRUE,
open = "r+")
f <- file("stdin")
open(f)
print("Enter text to be upper-cased, q to quit")
sendme <- readLines(f, n = 1)
if (tolower(sendme) == "q") {
break
}
write_resp <- writeLines(sendme, con)
server_resp <- readLines(con, 1)
print(paste("Your upper cased text: ", server_resp))
close(con)
}
}
client()
(For my take on the firewall rule, see the very end)
The functionality simply does not seem to exist.
In C you create a server socket with socket, bind and listen calls, and get the incoming connection with an accept call.
src\modules\internet\sock.c is the socket handler code, it has two functions for opening a socket, Sock_connect opens and connects a socket, so this is for client side, and int Sock_open(Sock_port_t port, Sock_error_t perr) is the one which opens a server socket (and the actual accept call is in Sock_listen). The problem is that this Sock_open has a port argument only, and the host/interface is hardcoded:
/* open a socket for listening */
int Sock_open(Sock_port_t port, Sock_error_t perr)
{
int sock;
struct sockaddr_in server;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return Sock_error(perr, errno, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons((short)port);
if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) ||
(listen(sock, MAXBACKLOG) < 0)) {
close(sock);
return Sock_error(perr, errno, 0);
}
return sock;
}
It binds to and listens on INADDR_ANY, which means all interfaces of your PC (not just the loopback), and it triggers the firewall for sure.
The function is called from the neighboring Rsock.c, still with a single port argument, and where everything else is lost seems to be one step earlier, in sockconn.c:
static Rboolean sock_open(Rconnection con)
{
Rsockconn this = (Rsockconn)con->private;
int sock, sock1, mlen;
int timeout = this->timeout;
char buf[256];
if(timeout == NA_INTEGER || timeout <= 0) timeout = 60;
this->pend = this->pstart = this->inbuf;
if(this->server) {
sock1 = R_SockOpen(this->port);
This last line is where host part of RSockconn is disregarded, though it contains such field:
/* used in internet module */
typedef struct sockconn {
int port;
int server;
int fd;
int timeout;
char *host;
char inbuf[4096], *pstart, *pend;
} *Rsockconn;
(This is defined outside, in src\include\Rconnections.h)
Unfortunately this will not solve your problem, just this is why you have it. You may consider raising an error report for the developers of R. Comments suggest they got the net code from ancient times, when firewalls and internet security were not that much of a concern like they are now:
/* Simple sockets interface derived from the sockets UICI
implementation in Appendix B of Practical UNIX Programming,
K. A. Robbins and S. Robbins, Prentice Hall, 1996. */
Which is nice, just it was 21 years ago.
Originally I did not want to steal the netsh thing from others, but I think you may get wrong suggestions. Actually you should not allow anything, but block everything:
netsh advfirewall firewall add rule name="Rtest" dir=in action=block program="<location and name of your executable>"
And that is it. The thing is that the loopback interface is not firewalled at all (so connections to 127.0.0.1 always work - I tested it too, just to be on the safe side), and you do not want anyone else to reach your program. I saw 'allow'-s in other answers, and you do not want that. Depending on other uses, you may have to restrict the rule with 'localport=8' and/or 'protocol=tcp', but the block part is sure.
You are basically forced to use Windows Firewall, as it comes with Windows. So maybe include a .bat file with your .R file that creates an exception and tells the user to run it? Or maybe make a .exe installer with IExpress? That might do the trick.
I would recommend the .exe installer route though, as a .bat file seems a tad suspicious too, as non-tech-savvy users will cry wolf when it asks for administrator privileges. The netsh command can create firewall exceptions for any program if you would rather the .bat file route.
This one accepts outgoing connections by using the dir=out switch, and enabling the exception via the action=allow switch
netsh advfirewall firewall add rule name="PROGRAM_NAME" dir=out action=allow program="C:\PROGRAMPATH" enable=yes
This one accepts incoming connections by using the dir=in switch, and enabling the exception via the action=allow switch
netsh advfirewall firewall add rule name="PROGRAM_NAME" dir=out action=allow program="C:\PROGRAMPATH" enable=yes
How to add a rule to Windows Firewall - DigitalCitizen
Online Tech Tips - Adjust Windows 10 Firewall Rules & Settings
An alternative to using PSOCK clusters is to use callr for running multiple R sessions in the background. The future.callr package (*) provides parallel backend for the future framework (disclaimer: I'm the author). It'll allow you to parallelize all OSes including Windows without going through sockets (and therefore no firewall). Example:
library("future")
plan(future.callr::callr)
y <- future_lapply(x, FUN = my_fcn_in_parallel)
It also works with doFuture for the foreach framework. Example:
library("doFuture")
plan(future.callr::callr)
registerDoFuture()
y <- foreach(i in seq_along(x)) %dopar% my_fcn_in_parallel(x[[i]])
FYI, for PSOCK clusters, use plan(multisession).
(*) future.callr is on CRAN as of 2018-02-13 will be submitted to CRAN as soon as the developer's version of callr that it depends on is submitted to CRAN.
Related
I'm trying to query a MySQL server through an R/Tidyverse/dbplyr workflow. My MySQL access requires configuring SSH and port forwarding.
I have this code working using python (below), but I'm struggling to get started with the SSH/port forwarding equivalent in R. Any pointers to solutions or equivalent R packages appreciated. thanks.
import pymysql
import paramiko
import pandas as pd
from paramiko import SSHClient
from sshtunnel import SSHTunnelForwarder
from os.path import expanduser
pkeyfilepath = '/.ssh/id_ed25519'
home = expanduser('~')
mypkey = paramiko.Ed25519Key.from_private_key_file(home + pkeyfilepath)
sql_hostname = 'mycompany.com'
sql_username = 'me'
sql_password = '***'
sql_main_database = 'my_db'
sql_port = 3306
ssh_host = 'jumphost.mycompany.com'
ssh_user = 'me'
ssh_port = 22
with SSHTunnelForwarder(
(ssh_host, ssh_port),
ssh_username=ssh_user,
ssh_pkey=mypkey,
remote_bind_address=(sql_hostname, sql_port)) as tunnel:
conn = pymysql.connect(host='127.0.0.1', user=sql_username,
passwd=sql_password, db=sql_main_database,
port=tunnel.local_bind_port)
query = '''SELECT VERSION();'''
data = pd.read_sql_query(query, conn)
print(data)
conn.close()
There are several ways to do ssh port forwarding for R. In no particular order:
I forward it externally to R. All of my work is remote, and for one particular client I need access to various instances of SQL Server, Redis, MongoDB, remote filesystems, and a tunnel-hop to another network only accessible from the ssh bastion host. I tend to do work in more than R, so it's important to me that I generalize this. It is not for everybody or every task.
For this, I used a mismash of autossh and my ssh-agent (in KeePass/KeeAgent).
The ssh package does have a function to Create a Tunnel. The premise is that you have already created a "session" to which you can add a forwarding rule(s). When using ssh::ssh_tunnel, it is blocking, meaning you cannot use it in the same R process and continue to work. Demo:
# R session 1
sess <- ssh::ssh_connect("user#remote")
# insert passphrase
ssh::ssh_tunnel(sess, 21433, "otherremote:1433")
# / Waiting for connection on port 21433...
# R session 2
con <- DBI::dbConnect(..., port=21433)
DBI::dbGetQuery(con, "select 1 as n")
# n
# 1 1
This connection will stay alive so long as con is not closed and the remote end does not close it (e.g., activity timeout).
Note: I cannot get the ssh package to use my ssh-agent, so all passwords must be typed in or otherwise passed in not-ideal ways. There are many ways to not have to type it, such as using the keyring package (secure) or envvars, both of which would pass the password to ssh_connect(..., passwd=<>).
The above, but using callr so that you don't need to explicit sessions active (though you will still have another R session.
bgr <- callr::r_bg(function() {
ssh <- ssh::ssh_connect("r2#remote", passwd=keyring::key_get("r2", "remote"))
ssh::ssh_tunnel(ssh, port=21433, "otherremote:1433")
}, supervise = TRUE)
DBI::dbGetQuery(con, "select 1 as n")
# n
# 1 1
### when your work is done
bgr$kill()
If you do this, I strongly recommend the use of supervise=TRUE, which ensures the background R process is killed when this (primary) R session exits. This will reduce the risk of having phantom unused R sessions hanging around; in addition to just clogging up the process tree, if one of these phantom R processes is actively forwarding a port, that means nothing else can forward that port. This allows you to continue working, but you are not longer in control of the process doing the forwarding ... and subsequent attempts to tunnel will fail.
FYI, I generally prefer using keyring::key_get("r2", "remote") for password management in situations like this: (1) it prevents me from having to set that envvar each time I start R ... which will inadvertently store the plain-string password in ~/.Rhistory, if saved; (2) it prevents me from having to set that envvar in the global environment permanently, which is prone to other stupid mistakes I make; and (3) is much better protected since it is using the native credentials of your base OS. Having said that, you can replace the above use of keyring::key_get(..) with Sys.getenv("mypass") in a pinch, or in a case where the code is running on a headless system where a credentials manager is unavailable.
And if you want this to be a little more resilient to timeout disconnects, you can instead use
bgr <- callr::r_bg(function() {
ssh <- ssh::ssh_connect("r2#remote", passwd=keyring::key_get("r2", "remote"))
while (!inherits(try(ssh::ssh_tunnel(ssh, port=21433, "otherremote:1433"), silent=TRUE), "try-error")) Sys.sleep(1)
}, supervise = TRUE)
which will repeatedly make the tunnel so long as the attempt does not error. You may need to experiment with this to get it "perfect".
callr is really just using processx under the hood to start a background R process and allow you to continue working. If you don't want the "weight" of another R process solely to forward ports, you can use processx to start an explicit call to ssh that does everything you need it to do.
proc <- processx::process$new("ssh", c("-L", "21433:otherremote:1433", "r2#remote", "-N"))
### prompts for password
DBI::dbGetQuery(con, "select 1 as n")
# n
# 1 1
### when done
proc$kill()
# [1] TRUE
How do I ssh ipv6 address in R ssh package
library(ssh)
# works
session <- ssh_connect("user#10.1.1.0")
# gives error
session <- ssh_connect("user#24:022f:0313:112:0::2")
Error in parse_host(host, default_port = 22) :
host string contains multiple ':' characters
Since you can't install source packages, one super hacky way to do this is to call the C function ssh_connect() calls directly:
.Call(
ssh:::C_start_session, "2405:0200:0313:112:41::42", 22, "user", NULL, ssh:::askpass, FALSE
)
That C interface is highly unlikely to change so it should be a pretty safe hack until the package eventually supports IPv6.
For those that stumble on this before the rOpenSci folks make any changes, the fork : https://github.com/hrbrmstr/ssh : also adds support for using a local SSH config file. Which means you can add a Host entry for IPv6 addresses (along with any other config options) and they'll be looked up.
i.e. if one has:
Host awickedcoolhost
User boringusername
Hostname ::1
IdentityFile ~/.ssh/id_rsa
Port 22222
in ~/.ssh/config, one can (with the fork) do:
ssh_connect("awickedcoolhost", config="~/.ssh/config")
and all the overrides in that entry should work.
I am searching for a robust solution to perform extensive computations on a remote server, dedicated to computational tasks. The server is on Windows 2008 R2 and has R x64 3.4.1 installed on it. I've searched for free solutions and am now focusing on the Rserver/RSclient packages solutions.
However, I can't connect any client (using RSclient) to the instanced server.
This is how I'm proceeding at the moment from the server side:
library(Rserve)
run.Rserve(config.file = "Rserv.conf")
using the following Rserv.conf file:
port 6311
remote enable
plaintext enable
control enable
r-control enable
The server is now intanciated using the Rsession (It's a bit ugly, but will change that latter on):
running Rserve in this R session (pid=...), 1 server(s)
Now, i'm trying to connect using a remote computer (Client-side) using:
library(RSclient)
c = RS.connect(host = "...")
The connection then seems to succeed, checking for c:
> c
Rserve QAP1 connection 0x000000000fbe9f50 (socket 764, queue length 0)
The error occurs when i try to eval anything, for example:
> RS.server.eval(c,"0<1")
Error in RS.server.eval(c, "0<1") : command failed with status code 0x4e: no control line present (control commands disabled or server shutdown)
I've read the available guides but still failed in connecting. What is wrong? It seems to be related to control lines but I authorized them in the config file.
for me the problem was solved by initiating the Rserve instance with the command:
R CMD Rserve --RS-port 9000 --RS-enable-remote --RS-enable-control
instead of starting it in the R environment (library(Rserve), run.Rserve(config.file = "Rserv.conf")). You may try this on Windows as well.
Refer https://github.com/s-u/Rserve/wiki/rserve.conf.
port 6311
remote enable -> it should be remote true
plaintext enable
control enable
r-control enable
Likewise refer the link and try with actual values
I am trying to scan a large set of domain names using nmap. I used the following command:
Nmap -PN -p443 -sS -T5 -oX out.xml -iL in.csv
I get the following warning:
Warning: xx.xx.xx.xx giving up on port because retransmission cap hit (2).
Why does this happen? How to resolve the issue ?
The option -T5 instructs nmap to use "insane" timing settings. Here's the relevant part of the current source code that illustrates what settings this implies:
} else if (*optarg == '5' || (strcasecmp(optarg, "Insane") == 0)) {
o.timing_level = 5;
o.setMinRttTimeout(50);
o.setMaxRttTimeout(300);
o.setInitialRttTimeout(250);
o.host_timeout = 900000;
o.setMaxTCPScanDelay(5);
o.setMaxSCTPScanDelay(5);
o.setMaxRetransmissions(2);
}
As you can see, the maximum number of retransmissions is 2. The warning you saw gets printed when there is a non-default cap on the number of retransmissions (set with -T5, -T4, or manually with --max-retries), and that cap is hit.
To avoid this problem, try scaling back your timing settings. -T4 is still very fast, and should work for nearby networks. -T3 is the default. If you are certain that your latency and bandwidth are not a problem, but that you may be dropping packets due to faulty hardware, you can manually set --max-retries to a higher value, and keep the rest of the -T5 settings.
I had the same problem and changing T parameter and --max-retries didn't changed anything.
The problem for me was my network adapter in VirtualBox was configured asNAT and notbridge.
It maybe happen because the virtual card is satured by all the packet.
This configuration solve the problem for my case.
Basically, I want to put my computer in the middle of a serial line and record the conversation going across it. I'm trying to reverse engineer this conversation and eventually emulate one end of the conversation.
Rough Diagram of what I'm trying to do:
Normally, I have this:
__________ __________
| | | |
|Device 1|<======>|Device 2|
|________| |________|
I want to do this:
__________ __________ __________
| | | | | |
|Device 1|<===>|Computer|<===>|Device 2|
|________| |________| |________|
With the computer in the middle basically bridging the connection between the two devices and logging the data that goes across.
Answers using any programming language are probably useful. Preferably I would be able to do this on either Windows or Linux (or both if someone has a general solution to this problem).
Well, a programmatic way to do it would be to just open the relevant devices, and start forwarding data between them, simultaneously saving to a file.
Most any language can do it. There are nice libraries for things like java and python.
Several implementations exist on the web, I found a python one called Telnet Serial Bridge (TSB) by googling, which would allow you to bridge connections together over ethernet, and log using telnet tools like putty.
Though in the past, I've used the java rxtx serial comm library from rxtx.qbang.org to do it myself, though I suspect there's an updated version now, or maybe something built into the JVM proper.
Adapted from an example on that site:
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class TwoWaySerialComm
{
void bridge( String portName1, String portName2 ) throws Exception
{
CommPortIdentifier portIdentifier1 = CommPortIdentifier.getPortIdentifier(portName1);
CommPortIdentifier portIdentifier2 = CommPortIdentifier.getPortIdentifier(portName2);
if ( portIdentifier1.isCurrentlyOwned() || portIdentifier2.isCurrentlyOwned())
{
System.out.println("Error: Port is currently in use");
}
else
{
CommPort commPort1 = portIdentifier1.open(this.getClass().getName(),2000);
CommPort commPort2 = portIdentifier2.open(this.getClass().getName(),2000);
if ( commPort instanceof SerialPort && commPort2 instanceof SerialPort )
{
SerialPort serialPort1 = (SerialPort) commPort1;
serialPort1.setSerialPortParams(57600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
InputStream in1 = serialPort1.getInputStream();
OutputStream out1 = serialPort1.getOutputStream();
SerialPort serialPort2 = (SerialPort) commPort2;
serialPort2.setSerialPortParams(57600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
InputStream in2 = serialPort2.getInputStream();
OutputStream out2 = serialPort2.getOutputStream();
(new Thread(new SerialReader(in1, out2))).start();
(new Thread(new SerialReader(in2, out1))).start();
}
else
{
System.out.println("Error: Only serial ports are handled by this example.");
}
}
}
/** */
public static class SerialReaderWriter implements Runnable
{
InputStream in;
OutputStream out;
public SerialReader ( InputStream in, OutputStream out )
{
this.in = in;
this.out = out;
}
public void run ()
{
byte[] buffer = new byte[1024];
int len = -1;
try
{
while ( ( len = this.in.read(buffer)) > -1 )
{
out.write(buffer,0, len);
System.out.print(new String(buffer,0,len));
}
}
catch ( IOException e )
{
e.printStackTrace();
}
}
}
public static void main ( String[] args )
{
try
{
(new TwoWaySerialComm()).bridge("COM1", "COM3");
}
catch ( Exception e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This is a small python script to bridge between two physical ports` #!/usr/bin/python
import time, sys, serial
import collections
import re
from serial import SerialException
from termcolor import colored
SERIALPORT1 = "/dev/rfcomm0" # the default com/serial port the receiver is connected to
BAUDRATE1 = 115200 # default baud rate we talk to Moteino
SERIALPORT2 = "/dev/ttyUSB0" # the default com/serial port the receiver is connected to
BAUDRATE2 = 9600 # default baud rate we talk to Moteino
# MAIN()
if __name__ == "__main__":
try:
# open up the FTDI serial port to get data transmitted to Moteino
ser1 = serial.Serial(SERIALPORT1, BAUDRATE1, timeout=1) #timeout=0 means nonblocking
ser1.flushInput();
print "\nCOM Port [", SERIALPORT1, "] found \n"
except (IOError, SerialException) as e:
print "\nCOM Port [", SERIALPORT1, "] not found, exiting...\n"
exit(1)
try:
# open up the FTDI serial port to get data transmitted to Moteino
ser2 = serial.Serial(SERIALPORT2, BAUDRATE2, timeout=1) #timeout=0 means nonblocking
ser2.flushInput();
print "\nCOM Port [", SERIALPORT2, "] found \n"
except (IOError, SerialException) as e:
print "\nCOM Port [", SERIALPORT2, "] not found, exiting...\n"
exit(1)
try:
while 1:
ser1_waiting = ser1.inWaiting()
if ser1_waiting > 0:
#rx1 = ser1.read(ser1_waiting)
rx1 = ser1.readline()
ser2.write(rx1)
print colored(rx1, 'red')
ser2_waiting = ser2.inWaiting()
if ser2_waiting > 0:
#rx2 = ser2.read(ser2_waiting)
rx2 = ser2.readline()
ser1.write(rx2)
print rx2
except IOError:
print "Some IO Error found, exiting..." `
I can offer a solution for Windows using 2 software utilities:
TCP COM Bridge - can connect 2 COM port over internal TCP connection.
Advanced Serial Port Monitor - can monitor and record the conversation between devices.
Both utilities are here:
http://www.aggsoft.com/
Well, I'm a novice and since you didn't say anything about the platform you’re on, I'll tell you what I did, but I'll warn you in advance, this depends on software you may or may not have and this may not actually be an answer at all, so caveat lector.
My hardware is a MacBook Pro 2.4 GHZ running 10.7.5 with 4GB ram.
What I was trying to do was read the serial comm chatter from an application that was running in Wine (since the application was windows based, but I didn’t want to use windows (icky poo). Heck , I didn’t want to use mac either, but I wasn’t making the headway I wanted to in virtual linux either, add to that Ubuntu is a little weird in the direction they’ve taken with some of the nitty gritty command-line “schtuff”.
Required software to start.
Parallels Desktop Build 7.0.15107 (Might be able to do this in Virtual Box, I haven't tried)
MultiCom (Freeware By Martin Louis for Mac)
http://members.iinet.net.au/~mgl/MartysPlace/MultiCom.html
Ubuntu 8.0.4 Hardy Heron
There maybe other ways, I must have chased down about a dozen ways to do what I wanted to do and I'm not happy yet with the output so this maybe a huge waste of time.
This solution doesn't use
strace
ttysnoop
gpspipe
socat
pyserial
And to be honest, ttysnoop seemed to be exactly what I wanted, socat seemed like a distant 2nd but a little too much for a novice imo.
The problems I ran into with other clients (possibly due to my inability to figure out how to change features about com connections) had to do with blocking. What you want, when you monitor a serial port, is a non-blocking connection. So you just listen to the port chatter and don’t interfere.
If you make a connection to it with clients like...
jpnevulator
minicom
cutecom
screen, etc.
...it seems that they take over the com port and the serial port is suddenly not available for you to monitor. There must be a way to configure them so this isn’t the case but I couldn’t figure it out. Add to that the complication that if you try to monitor from the mac side what the ports in your virtual machine are doing, it’s a little stickier still or trying to use any way you can to get past this “bump” of how to send the same data to 2 serial ports. So if you're smarter than me, I invite you to please make me less dumb.
On the Mac Side…
Launch MultiCom
Set – Port A
a) Configure as a Serial
b) Serial Device /dev/cu.KeySerial (in my case, you’ll need to discover what port you need heuristically using Terminal and typing ls /dev/tty.*
c) Click “Ok” and select the enable check box.
Set – Port B
a) Socket File Server
b) Socket File : /Users/shadowwraith/Desktop/socket.txt
On Virtual Machine Side (Parallels Ubuntu 8.0.4)
a) With the VM shutdown configure add 2 serial ports that reference the same socket file as CLIENTS (not servers) by specifying the full path.
b) Enable both by selecting the check box (Note: remember as far as the VM is concerned there is no USB connection to the serial device. You’re making that connection via the MultiCom software (or someother means if you know of one, what MultiCom is doing is acting as a conduit for the single port connection to the USB serial connector then duplicating all I/O to the socket file server which all the clients can connect to which can be multiple VMs or multiple serial ports in the same VM.)
c) Boot VM and set one serial port for your program and the other serial port for your sniffing. And POOF..there you go.
See below for more technical minutia about what to do...
Linux
How to display a serial port?
dmesg | grep tty
This is what you would type in to get the sniffer to read the input assuming the serial port you chose to actively use a serial connection was on the other socketed port, ttyS0 at com 1 for instance (ttyS1 is at com 3 in this but you can figure this out by using dmesg | grep tty).
Seeing the information…
jpnevulator --ascii --timing-print --tty "/dev/ttyS1" –read
Unrelated information that you shouldn’t use, but lead-up to me understanding why it was the wrong way to do this…
How to map a com port in linux (when you’re not worried about sniffing a port or using configure to add the serial ports)?
ln -s /dev/ttyUSB0 com3
To undo this type
unlink com3
Where ttyUSB0 is the port found from dmesg | grp tty and com3 is the desired port for Wine. This is done in the ~/.wine/dosdevices directory.
For example take a cable from rx/tx of devices to the computer com port rx pin and run a terminal or serial port logger. Just that.