The local ip is the source ip in IP packets send out from a system. The kernal maintains routing tables which it uses to decide the default gateway , its interface and the local ip configured for that interface. The /proc/net/route file (not really a file but appears like one) has more information about it.
A typical /proc/net/route output would look like :
2 |
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT |
3 |
eth0 0000A8C0 00000000 0001 0 0 1 00FFFFFF 0 0 0 |
4 |
eth0 0000FEA9 00000000 0001 0 0 1000 0000FFFF 0 0 0 |
5 |
eth0 00000000 0100A8C0 0003 0 0 0 00000000 0 0 0 |
The above lists the interface , destination , gateway etc. The interface (Iface) whose destination is 00000000 is the interface of the default gateway.
Now have a look at the route command output
2 |
Kernel IP routing table |
3 |
Destination Gateway Genmask Flags Metric Ref Use Iface |
4 |
192.168.0.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0 |
5 |
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 eth0 |
6 |
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 eth0 |
Now the gateway for the destination 0.0.0.0 is the default gateway. So from the /proc/net/route output this line is of interest :
1 |
eth0 00000000 0100A8C0 0003 0 0 0 00000000 0 0 0 |
Its destination is 00000000 and gateway is 0100A8C0. The gateway is actually the IP address of the gateway in hex format in reverse order (little endian). Its 01.00.A8.C0 or 1.0.168.192
So by reading that line in a C program we can find out the default gateway and its interface. The IP address of this interface shall be the source ip in IP packets send out from this system.
The code for this is pretty simple as we can see :
2 |
char line[100] , *p , *c;
|
4 |
f = fopen ( "/proc/net/route" , "r" );
|
6 |
while ( fgets (line , 100 , f))
|
8 |
p = strtok (line , " \t" );
|
9 |
c = strtok (NULL , " \t" );
|
11 |
if (p!=NULL && c!=NULL)
|
13 |
if ( strcmp (c , "00000000" ) == 0)
|
15 |
printf ( "Default interface is : %s \n" , p);
|
The above code prints : “Default interface is : eth0″
Now we need to get the ip address of the default interface eth0. The getnameinfo function can be used for this.
Sample code is found here.
Combining that with our previous code we get :
6 |
#include<stdio.h> //printf |
7 |
#include<string.h> //memset |
8 |
#include<errno.h> //errno |
15 |
int main ( int argc , char *argv[] )
|
18 |
char line[100] , *p , *c;
|
20 |
f = fopen ( "/proc/net/route" , "r" );
|
22 |
while ( fgets (line , 100 , f))
|
24 |
p = strtok (line , " \t" );
|
25 |
c = strtok (NULL , " \t" );
|
27 |
if (p!=NULL && c!=NULL)
|
29 |
if ( strcmp (c , "00000000" ) == 0)
|
31 |
printf ( "Default interface is : %s \n" , p);
|
39 |
struct ifaddrs *ifaddr, *ifa;
|
41 |
char host[NI_MAXHOST];
|
43 |
if (getifaddrs(&ifaddr) == -1)
|
50 |
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
|
52 |
if (ifa->ifa_addr == NULL)
|
57 |
family = ifa->ifa_addr->sa_family;
|
59 |
if ( strcmp ( ifa->ifa_name , p) == 0)
|
63 |
s = getnameinfo( ifa->ifa_addr, (family == AF_INET) ? sizeof ( struct sockaddr_in) : sizeof ( struct sockaddr_in6) , host , NI_MAXHOST , NULL , 0 , NI_NUMERICHOST);
|
67 |
printf ( "getnameinfo() failed: %s\n" , gai_strerror(s));
|
71 |
printf ( "address: %s" , host);
|
Output
1 |
Default interface is : eth0 |
Another method is to open a connection to a remote server and call getsockname
Code
6 |
#include<stdio.h> //printf |
7 |
#include<string.h> //memset |
8 |
#include<errno.h> //errno |
9 |
#include<sys/socket.h> //socket |
10 |
#include<netinet/in.h> //sockaddr_in |
11 |
#include<arpa/inet.h> //getsockname |
12 |
#include<unistd.h> //close |
14 |
int main ( int argc , char *argv[] )
|
16 |
const char * google_dns_server = "8.8.8.8" ;
|
19 |
struct sockaddr_in serv;
|
21 |
int sock = socket ( AF_INET, SOCK_DGRAM, 0);
|
26 |
perror ( "Socket error" );
|
29 |
memset ( &serv, 0, sizeof (serv) );
|
30 |
serv.sin_family = AF_INET;
|
31 |
serv.sin_addr.s_addr = inet_addr( google_dns_server );
|
32 |
serv.sin_port = htons( dns_port );
|
34 |
int err = connect( sock , ( const struct sockaddr*) &serv , sizeof (serv) );
|
36 |
struct sockaddr_in name;
|
37 |
socklen_t namelen = sizeof (name);
|
38 |
err = getsockname(sock, ( struct sockaddr*) &name, &namelen);
|
41 |
const char * p = inet_ntop(AF_INET, &name.sin_addr, buffer, 100);
|
45 |
printf ( "Local ip is : %s \n" , buffer);
|
50 |
printf ( "Error number : %d . Error message : %s \n" , errno , strerror ( errno ));
|
Output
1 |
Local ip is : 192.168.0.6 |