3

IFF_UP 与 IFF_RUNNING

 2 years ago
source link: http://bean-li.github.io/if-is-up/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

IFF_UP 与 IFF_RUNNING

首页 分类 标签 留言 关于 订阅 2021-10-23

|

分类 Linux 

|

标签 Linux 

近期,发现判断网卡是否Ready的程序出了一些问题,有些网卡明明没有插线,依然会被判定为active的网卡。我去跟踪了下代码:

# struct ifreq { // FOR SIOCGIFFLAGS:
#   char ifrn_name[IFNAMSIZ]
#   short ifru_flags
# };
my $STRUCT_IFREQ_SIOCGIFFLAGS = 'Z' . IFNAMSIZ . 's1';
sub get_active_network_interfaces {
    # Use the interface name list from /proc/net/dev
    open my $fh, '<', '/proc/net/dev'
	or die "failed to open /proc/net/dev: $!\n";
    # And filter by IFF_UP flag fetched via a PF_INET6 socket ioctl:
    my $sock;
    socket($sock, PF_INET6, SOCK_DGRAM, &IPPROTO_IP)
    or socket($sock, PF_INET, SOCK_DGRAM, &IPPROTO_IP)
    or return [];

    my $ifaces = [];
    while(defined(my $line = <$fh>)) {
	next if $line !~ /^\s*([^:\s]+):/;
	my $ifname = $1;
	my $ifreq = pack($STRUCT_IFREQ_SIOCGIFFLAGS, $ifname, 0);
	if (!defined(ioctl($sock, SIOCGIFFLAGS, $ifreq))) {
	    warn "failed to get interface flags for: $ifname\n";
	    next;
	}
	my ($name, $flags) = unpack($STRUCT_IFREQ_SIOCGIFFLAGS, $ifreq);
	push @$ifaces, $ifname if ($flags & IFF_UP);
    }
    close $fh;
    close $sock;
    return $ifaces;
}

发现源码使用通过调用 ioctl SIOCGIFFLAGS 来判定网卡是否已经ready。

关于SIOCGIFFLAGS

Linux ioctl支持一下两个标志位:

  • SIOCGIFFLAGS: 获取设备的活动标志位
  • SIOCSIFFLAGS: 修改设备的活动标志位
       SIOCGIFFLAGS, SIOCSIFFLAGS
              Get or set the active flag word of the device.  ifr_flags contains a bit mask of the following values:

                                           Device flags
              IFF_UP            Interface is running.
              IFF_BROADCAST     Valid broadcast address set.
              IFF_DEBUG         Internal debugging flag.
              IFF_LOOPBACK      Interface is a loopback interface.

              IFF_POINTOPOINT   Interface is a point-to-point link.
              IFF_RUNNING       Resources allocated.
              IFF_NOARP         No arp protocol, L2 destination address not set.
              IFF_PROMISC       Interface is in promiscuous mode.
              IFF_NOTRAILERS    Avoid use of trailers.
              IFF_ALLMULTI      Receive all multicast packets.
              IFF_MASTER        Master of a load balancing bundle.
              IFF_SLAVE         Slave of a load balancing bundle.
              IFF_MULTICAST     Supports multicast
              IFF_PORTSEL       Is able to select media type via ifmap.
              IFF_AUTOMEDIA     Auto media selection active.
              IFF_DYNAMIC       The addresses are lost when the interface goes down.
              IFF_LOWER_UP      Driver signals L1 up (since Linux 2.6.17)
              IFF_DORMANT       Driver signals dormant (since Linux 2.6.17)
              IFF_ECHO          Echo sent packets (since Linux 2.6.25)本次我们重点介绍IFF_UP和 IFF_RUNNING。

IFF_UP: 这个标志位表示的是从管理上讲,这个网口是UP的,是Ready的,但是并不代表连接状态。即网卡已经准备好了,但是并不意味着网线已插。

IFF_RUNNING: 这个标志位表示operational state,如果置位的话,表示CONNECTED的。

做个简单验证:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>

#define BUFSIZE 1024

int main(int argc, char *argv[])
{
	struct ifreq ifr;
	int sfd ;

	memset(&ifr, '\0' , sizeof(struct ifreq));
	strcpy(ifr.ifr_name, argv[1]);
	sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);

	int ret = ioctl(sfd, SIOCGIFFLAGS, (char *)&ifr);
	if(ret !=0)
	{
		printf("failed to exec ioctl");
		goto out;
	}

	printf("%10s IFF_UP: %d\n", argv[1], !!(ifr.ifr_flags & IFF_UP));
	printf("%10s IFF_RUNNING: %d \n",argv[1], !!(ifr.ifr_flags & IFF_RUNNING));

out:
	close(sfd);
	exit(ret);
}

我的笔记本的网口情况如下:

manu-latitude3510 CODE/C » cat /proc/net/dev
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo: 1503282   11818    0    0    0     0          0         0  1503282   11818    0    0    0     0       0          0
  eno1:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
wlp1s0: 14947732561 40405691    0 822774    0     0          0         0 650855154 3591298    0    0    0     0       0          0
manu-latitude3510 CODE/C »

其中eno1 是有线,并未插线,wlp1s0是无线,已经连接的状态。

manu-latitude3510 CODE/C » ./nettool eno1                                                                                                                
      eno1 IFF_UP: 1
      eno1 IFF_RUNNING: 0
manu-latitude3510 CODE/C » ./nettool wlp1s0
    wlp1s0 IFF_UP: 1
    wlp1s0 IFF_RUNNING: 1
manu-latitude3510 CODE/C » ./nettool lo
        lo IFF_UP: 1
        lo IFF_RUNNING: 1
manu-latitude3510 CODE/C

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK