overexchange
overexchange

Reputation: 1

Can bind() socket to remote address?

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.

enter image description here 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

Answers (2)

thuovila
thuovila

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

Jan
Jan

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

Related Questions