Get local ip in C on linux

简介:

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 :

1 cat /proc/net/route
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

1 $ route -n
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 :

1 FILE *f;
2 char line[100] , *p , *c;
3  
4 f = fopen("/proc/net/route" "r");
5  
6 while(fgets(line , 100 , f))
7 {
8     p = strtok(line , " \t");
9     c = strtok(NULL , " \t");
10      
11     if(p!=NULL && c!=NULL)
12     {
13         if(strcmp(c , "00000000") == 0)
14         {
15             printf("Default interface is : %s \n" , p);
16             break;
17         }
18     }
19 }

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 :

1 /*
2  * Find local ip used as source ip in ip packets.
3  * Read the /proc/net/route file
4  */
5  
6 #include<stdio.h> //printf
7 #include<string.h>    //memset
8 #include<errno.h> //errno
9 #include<sys/socket.h>
10 #include<netdb.h>
11 #include<ifaddrs.h>
12 #include<stdlib.h>
13 #include<unistd.h>
14  
15 int main ( int argc , char *argv[] )
16 {
17     FILE *f;
18     char line[100] , *p , *c;
19      
20     f = fopen("/proc/net/route" "r");
21      
22     while(fgets(line , 100 , f))
23     {
24         p = strtok(line , " \t");
25         c = strtok(NULL , " \t");
26          
27         if(p!=NULL && c!=NULL)
28         {
29             if(strcmp(c , "00000000") == 0)
30             {
31                 printf("Default interface is : %s \n" , p);
32                 break;
33             }
34         }
35     }
36      
37     //which family do we require , AF_INET or AF_INET6
38     int fm = AF_INET;
39     struct ifaddrs *ifaddr, *ifa;
40     int family , s;
41     char host[NI_MAXHOST];
42  
43     if (getifaddrs(&ifaddr) == -1)
44     {
45         perror("getifaddrs");
46         exit(EXIT_FAILURE);
47     }
48  
49     //Walk through linked list, maintaining head pointer so we can free list later
50     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
51     {
52         if (ifa->ifa_addr == NULL)
53         {
54             continue;
55         }
56  
57         family = ifa->ifa_addr->sa_family;
58  
59         if(strcmp( ifa->ifa_name , p) == 0)
60         {
61             if (family == fm)
62             {
63                 s = getnameinfo( ifa->ifa_addr, (family == AF_INET) ? sizeof(structsockaddr_in) : sizeof(struct sockaddr_in6) , host , NI_MAXHOST , NULL , 0 , NI_NUMERICHOST);
64                  
65                 if (s != 0)
66                 {
67                     printf("getnameinfo() failed: %s\n", gai_strerror(s));
68                     exit(EXIT_FAILURE);
69                 }
70                  
71                 printf("address: %s", host);
72             }
73             printf("\n");
74         }
75     }
76  
77     freeifaddrs(ifaddr);
78      
79     return 0;
80 }

Output

1 Default interface is : eth0
2  
3 address: 192.168.0.6

Another method is to open a connection to a remote server and call getsockname

Code

1 /*
2  * Find local ip used as source ip in ip packets.
3  * Use getsockname and a udp connection
4  */
5  
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
13  
14 int main ( int argc , char *argv[] )
15 {
16     const char* google_dns_server = "8.8.8.8";
17     int dns_port = 53;
18      
19     struct sockaddr_in serv;
20      
21     int sock = socket ( AF_INET, SOCK_DGRAM, 0);
22      
23     //Socket could not be created
24     if(sock < 0)
25     {
26         perror("Socket error");
27     }
28      
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 );
33  
34     int err = connect( sock , (const struct sockaddr*) &serv , sizeof(serv) );
35      
36     struct sockaddr_in name;
37     socklen_t namelen = sizeof(name);
38     err = getsockname(sock, (struct sockaddr*) &name, &namelen);
39          
40     char buffer[100];
41     const char* p = inet_ntop(AF_INET, &name.sin_addr, buffer, 100);
42          
43     if(p != NULL)
44     {
45         printf("Local ip is : %s \n" , buffer);
46     }
47     else
48     {
49         //Some error
50         printf ("Error number : %d . Error message : %s \n" errno strerror(errno));
51     }
52  
53     close(sock);
54      
55     return 0;
56 }

Output

1 Local ip is : 192.168.0.6
目录
相关文章
|
Ubuntu Linux 网络安全
在Linux云服务器上限制特定IP进行SSH远程连接的设置
温馨提示,修改iptables规则时要格外小心,否则可能导致无法远程访问你的服务器。最好在掌握足够技术知识和理解清楚操作含义之后再进行。另外,在已经配置了防火墙的情况下,例如ufw(Ubuntu Firewall)或firewalld,需要按照相应的防火墙的规则来设置。
678 24
|
安全 Linux
阿里云linux服务器使用脚本通过安全组屏蔽异常海外访问ip
公网网站可能会遭受黑客攻击导致访问异常,使用此脚本可以屏蔽掉异常IP 恢复访问。也可自行设置定时任务定期检测屏蔽。
883 28
|
人工智能 Kubernetes Ubuntu
linux配置IP
linux配置IP
5325 1
|
网络协议 Unix Linux
深入解析:Linux网络配置工具ifconfig与ip命令的全面对比
虽然 `ifconfig`作为一个经典的网络配置工具,简单易用,但其功能已经不能满足现代网络配置的需求。相比之下,`ip`命令不仅功能全面,而且提供了一致且简洁的语法,适用于各种网络配置场景。因此,在实际使用中,推荐逐步过渡到 `ip`命令,以更好地适应现代网络管理需求。
868 11
|
Web App开发 资源调度 网络协议
Linux系统之部署IP工具箱MyIP
【10月更文挑战第5天】使用Docker部署Radicale日历和联系人应用Linux系统之部署IP工具箱MyIP
943 1
Linux系统之部署IP工具箱MyIP
|
缓存 网络协议 Linux
Linux ip命令常用操作
Linux的 `ip`命令是一个强大且灵活的网络管理工具,能够执行从基本的网络接口配置到高级的路由和VLAN管理等多种操作。通过熟练掌握这些常用操作,用户可以更加高效地管理和配置Linux系统的网络环境。无论是在日常管理还是故障排除中,`ip`命令都是必不可少的工具。
424 2
|
网络协议 Linux
在Linux中,如何改IP、主机名、DNS?
在Linux中,如何改IP、主机名、DNS?
|
网络协议 Ubuntu Linux
在Linux中,如何将本地80端口的请求转发到8080端口,当前主机IP为192.168.16.1,其中本地网卡eth0。
在Linux中,如何将本地80端口的请求转发到8080端口,当前主机IP为192.168.16.1,其中本地网卡eth0。
|
监控 网络协议 Linux
在Linux中,如何查看当前系统每个 IP 的连接数?
在Linux中,如何查看当前系统每个 IP 的连接数?
|
域名解析 缓存 负载均衡
在Linux中,自定义解析域名的时候,可以编辑哪个⽂件?是否可以⼀个ip对应多个域名?是否⼀个域名对应多个ip?
在Linux中,自定义解析域名的时候,可以编辑哪个⽂件?是否可以⼀个ip对应多个域名?是否⼀个域名对应多个ip?