Reputation: 1097
Using socket programming APIs (e.g., socket(), connect(), accept() ...), how can I know if a TCP connection is between two processes on the same machine? Say, I have the socket file descriptor, and the remote ip. Can I simply inspect if the remote ip is 127.0.0.1?
Upvotes: 10
Views: 2061
Reputation: 71605
Here is the approach I have used. The idea is to attempt to bind a listener to that IP address and use the failure/success codes to decide whether the address is local.
I am not claiming this is particularly efficient, but it should be fairly reliable, and for my application it was appropriate.
#include <sys/socket.h>
#include <errno.h>
/* ...probably need some other headers I am forgetting... */
int
is_local(const struct sockaddr *addr, socklen_t addr_len)
{
const char *func = "is_local()";
int result = 0;
int tmp = socket(addr->sa_family, SOCK_STREAM, 0);
if (tmp < 0) {
printf("%s: socket(%d,SOCK_STREAM,0) failed, errno %d\n",
func, addr->sa_family);
goto out;
}
/* If bind() succeeds, or if it fails because the address is in
use, then the address must be local to this system. */
if (bind(tmp, addr, addr_len) < 0) {
if (errno == EADDRINUSE)
result = 1;
else if (errno == EADDRNOTAVAIL)
; /* do nothing; address is remote */
else
printf("%s: bind() unexpected error %d\n", func, errno);
}
else {
result = 1;
}
close(tmp);
out:
return result;
}
You call it like this:
struct sockaddr_storage client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int fd = accept(listener, &client_addr, &client_addr_len);
if (is_local((struct sockaddr *)&client_addr, client_addr_len))
/* peer is local */
Upvotes: 2
Reputation: 598011
Use getsockname()
and getpeername()
to retreive the two IPs associated with the connection, then use gethostname()
and gethostbyname()
(or other platform-specific APIs, like GetAdaptersInfo()
and GetAdapterAddresses()
on Windows) to determine the IPs that belong to the local machine, then you can compare the connection IPs to the local machine IPs to see if they both match. A machine can have multiple IPs assigned to it, and multiple IPs on the same machine can communicate with each other.
Upvotes: 3
Reputation: 7213
If you already have the remote ip address, you can check if it is the loopback address or if it is the ip address of the host, because, as cnicutar points out, it doesn't have to be over the loopback address to be a local connection.
Upvotes: 2
Reputation: 231383
There's no really reliable way to determine this - you can connect to local processes using a globally routed IP address (ie, local processes can use IPs other than 127.0.0.1
). It's also possible for a process to run in a different virtual machine on the same physical hardware, if you're in a virtualized environment.
Note, however, that if the remote IP (via getpeername
) or local IP (via getsockname
) starts with 127
(including 127.0.0.1
), then it is indeed a local connection; however, you can't rule out the possibility that it might be a local connection if it's a different pair of addresses.
Upvotes: 7