打印出本地的非 loopback的IP地址

这个是参考了网上的和工作中的一些代码写成的。

内容如下:

#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXNIC 20

int main(void)
{

	int sockfd = socket(AF_INET, SOCK_STREAM, 0);

	struct ifconf ifconfig;
	struct ifreq ifr[MAXNIC];
	memset(ifr, 0, sizeof(ifr));
	memset(&ifconfig, 0, sizeof(ifconfig));

	ifconfig.ifc_req = ifr;
	ifconfig.ifc_len = sizeof(ifr);

	if(ioctl(sockfd, SIOCGIFCONF, &ifconfig) == -1)
	{
		perror("ioctl SIOCGIFCONF: ");
		exit(1);
	}	

	int nNIC = ifconfig.ifc_len / sizeof(ifr[0]);
	printf("number if NIC is %d\n", nNIC);
	int i;
	for( i = 0; i < nNIC; i++)
	{

		//!!! We must make a copy of the previous ifreq structure before 
		//calling ioctl with SIOCGIFFLAGS, because this function can change
		//the other fields of ifreq.
		struct ifreq ifreq_copy;
		memcpy(&ifreq_copy, &ifconfig.ifc_req[i], sizeof(ifreq_copy));

		if(ioctl(sockfd, SIOCGIFFLAGS, &ifreq_copy) == -1)
		{
			perror("ioctl SIOCGIFFLAGS: ");
			exit(2);
		}
	
//		ifconfig.ifc_req[i].ifr_flags = ifreq_copy.ifr_flags;

//		printf("checking %s\n", ifconfig.ifc_req[i].ifr_name);	
//		printf("family = %hd\n",  ifconfig.ifc_req[i].ifr_addr.sa_family);
		//printf("up flag: %x,  %x\n", ifconfig.ifc_req[i].ifr_flags & IFF_UP, IFF_UP);
		//printf("is loopback :%x, %x\n", ifconfig.ifc_req[i].ifr_flags & IFF_LOOPBACK ,  IFF_LOOPBACK);
		if((ifreq_copy.ifr_flags & IFF_UP) == IFF_UP
		&& (ifreq_copy.ifr_flags & IFF_LOOPBACK) != IFF_LOOPBACK
		&& ifconfig.ifc_req[i].ifr_addr.sa_family == AF_INET )
		{
			char ip[INET_ADDRSTRLEN];
			struct sockaddr_in *address = (struct sockaddr_in *)&ifconfig.ifc_req[i].ifr_addr;			
			inet_ntop(AF_INET, &address->sin_addr, ip, sizeof(ip));
			printf("%s\t%s\n", ifconfig.ifc_req[i].ifr_name, ip);
		}
	}
}

第37行的memcpy是非常必要的,因为i后面的那个ioctl会改变ifreq其他成员的值!

原因是因为struct ifreq 里面有一个 union:

           struct ifreq {
               char ifr_name[IFNAMSIZ]; /* Interface name */
               union {
                   struct sockaddr ifr_addr;
                   struct sockaddr ifr_dstaddr;
                   struct sockaddr ifr_broadaddr;
                   struct sockaddr ifr_netmask;
                   struct sockaddr ifr_hwaddr;
                   short           ifr_flags;
                   int             ifr_ifindex;
                   int             ifr_metric;
                   int             ifr_mtu;
                   struct ifmap    ifr_map;
                   char            ifr_slave[IFNAMSIZ];
                   char            ifr_newname[IFNAMSIZ];
                   char           *ifr_data;
               };
           };


39行的代码会改变ifr_flags的值,这样也就改变了其它成员的值。

我开始的时候,没有加这个memcpy,结果,打印出来的 ifr_addr.sa_family怎么都不对, 查了半天才发现原因。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值