Reputation: 1
With the following snapshot of C code, I understand that, the address that bind()
call binds to listfd
, is the logical address of the local machine where this server program is running. Subsequently, server listens on listfd
socket of that same machine.
struct sockaddr_in serv_addr;
listfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(8000);
retval = bind(listfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listfd)
I learnt at coursera ---
that, bind()
call also allow you to bind socket to remote address and port.
I would like to understand this point.
I mean,
listfd = socket(AF_INET, SOCK_STREAM, 0);
provides a file descriptor from the program process where this program is running(local machine).
My question:
If bind() call binds this local socket listfd
to a remote address instead of INADDR_ANY
, then which machine is actually listening? Because listfd
is an entry from local process file descriptor table of that local machine where this program is running and this socket listfd
is getting bind to remote machine IP address? How do i interpret that? How does this work under the hood?
Upvotes: 2
Views: 5961
Reputation: 2020
I agree the Coursera material is probably wrong or at least misleading for introduction level learning about network programming.
However, I can not suppress a pedantic comment. It is possible (on Linux) to bind to a non-local IP address. Please see option IP_TRANSPARENT at http://man7.org/linux/man-pages/man7/ip.7.html. This probably has very little to do with the issue at hand, though. Also i appreciate the question is tagged bsd.
More on the point, bind()
does not have anything to do with listening. It simply associates the fd with an address. It is the listen()
call that enables "listening". It is possible to bind()
a socket used for outgoing connections.
Upvotes: 1
Reputation: 293
You cannot bind()
to a remote address, at least not in the AF_INET
family. According to the man page of bind, you will get a EADDRNOTAVAIL
error, saying that the address you wanted to bind to is not local.
Edit: bind()
may work for remote addresses but it certainly does not in the AF_INET
family. Please note that there is more than this. There are probably some families that do indeed support binding to remote addresses, probably some clustering protocols. Even if there are not, bind()
may work on those theoretically in case some protocols emerge where this makes sense at all.
Edit2: As thuovila pointed out, there actually is a case where binding on remote addresses in AF_INET
works. That is, setting the IP_TRANSPARENT
socket option before binding. The man page of ip(7) tells us:
IP_TRANSPARENT (since Linux 2.6.24)
Setting this boolean option enables transparent proxying on
this socket. This socket option allows the calling
application to bind to a nonlocal IP address and operate both
as a client and a server with the foreign address as the local
endpoint. NOTE: this requires that routing be set up in a way
that packets going to the foreign address are routed through
the TProxy box (i.e., the system hosting the application that
employs the IP_TRANSPARENT socket option). Enabling this
socket option requires superuser privileges (the CAP_NET_ADMIN
capability).
TProxy redirection with the iptables TPROXY target also
requires that this option be set on the redirected socket.
So, with a lot of extra work, you can build a transparent proxy by tieing a local and a remote socket together with that socket option set (if I understand correctly).
Upvotes: 5