[Ilugc] Find IP address of a machine

  • From: girishvenkatachalam@xxxxxxxxx (Girish Venkatachalam)
  • Date: Tue Oct 24 20:32:39 2006

On Tue, Oct 24, 2006 at 07:59:08AM +0200, Binand Sethumadhavan wrote:

On 24/10/06, Girish Venkatachalam <girishvenkatachalam@xxxxxxxxx> wrote:
Well, a given machine could have several different IP addresses, so
you need to be a bit more specific than that.
There are both multi homed and single interface having mutiple IP 
addresses problem.

There are also NAT, multicasting, hot-standby protocols like
VRRP/CARP, load-balancing etc. that causes an IP address to be
associated with a given machine.

The point is that an IP address is not a property of the machine, so a
question like "how do I figure out the OP address of a machine?" is
meaningless. IP addresses are properties of TCP/IP connections, not of
machines/computers/hardware.

Given that, the way to figure out IP addresses at both ends of a
connection are the pair of system calls getsockname/getpeername
(perldoc -f for their usage details).
I created a lot of noise in misc@openbsd over this trivial issue.

http://marc.theaimsgroup.com/?l=openbsd-misc&m=116167876510367&w=2

And no one could give a proper solution. There are couple of possibilities , 
none of them elegant.

1) http://libdnet.sourceforge.net/
2)

in_addr_t 
defip(in_addr_t dst)
{
        int s, slen = sizeof(struct sockaddr);
        struct sockaddr_in sin;

        s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (s < 0) {
                perror("socket");
                return -1;
        }
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(60);
        memcpy(&sin.sin_addr.s_addr, (char *)&dst, sizeof(in_addr_t));
        if (connect(s, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) {
                perror("connect");
                return -1;
        }
        if (getsockname(s, (struct sockaddr *)&sin, &slen) < 0)
                return -1;
        close(s);

        return (sin.sin_addr.s_addr);
}

The best and most interesting one of course is using getifaddrs(3) system call 
but it is too complex to use and only available on *BSD systems. There is 
something similar for linux. Too bad I don't recollect now.

The explanation for the above code is attached snipped from an e-mail from 
Germany personally sent to me.

<<<<<<<cut>>>>>
The process of defip() is pretty well as you described only difference is       
that the UDP socket gets connected.  This doesn't change any functionality      
of a UDP socket except that the socket will now listen to ICMP unreach          
messages and return an error upon the next write/read if such was received.     
(Since UDP sockets can't really be connected.. they're stateless).              
<<<<<<<cut>>>>>
                                                                    

But as I said I don't like this. :-)

HTH,
Girish

Other related posts: