(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.