labunix's blog

labunixのラボUnix

flagからプロミスキャスモードのインターフェイスを探す。

■flagからプロミスキャスモードのインターフェイスを探す。

$ lsb_release -d
Description:	Debian GNU/Linux 8.3 (jessie)

■ifconfig、ipコマンドを使用する。

$ ip a list | awk '/PROMISC/{print $2}'
eth1:

$ env LANG=C /sbin/ifconfig | awk '/^[a-z]|PROMISC/{print $1,$4}'
eth0 HWaddr
eth1 HWaddr
UP PROMISC
lo Loopback
vmnet1 HWaddr
vmnet8 HWaddr

$ /sbin/ifconfig | awk '/^[a-z]|PROMISC/{print $1,$4}'
eth0 ハードウェアアドレス
eth1 ハードウェアアドレス
UP PROMISC
lo 
vmnet1 ハードウェアアドレス
vmnet8 ハードウェアアドレス

■netstatのフラグを利用する。
 ioctl経由で呼び出していることが分かる。

$ netstat -in | awk '/BMPRU/{print $1}'
eth1

$ sudo strace netstat -i 2>&1 | grep -i promisc --color
ioctl(5, SIOCGIFFLAGS, {ifr_name="eth1", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_PROMISC|IFF_MULTICAST}) = 0

■/sysのフラグを利用する。

$ grep . /sys/class/net/*/flags | awk '/0x1103/'
/sys/class/net/eth1/flags:0x1103

■それぞれのフラグの意味は以下。

$ man netdevice | awk '/^ *IFF_/ && (/LOOPBACK/ || /CAST/ || /PROMISC/ || /RUNNING/ || /UP/){print}'
              IFF_UP            インターフェースは動作中。
              IFF_BROADCAST     有効なブロードキャストアドレスがセットされている。
              IFF_LOOPBACK      インターフェースはループバックである。
              IFF_RUNNING       リソースが割り当て済み。
              IFF_PROMISC       インターフェースは promiscuous モードである。
              IFF_MULTICAST     マルチキャストをサポートしている。
              IFF_LOWER_UP      ドライバからの L1 アップの通知 (Linux 2.6.17 以降)

■if.hのソースからフラグを確認してみる。

$ man netdevice | grep include
       #include <sys/ioctl.h>
       #include <net/if.h>
$ apt-get source --download-only linux-headers-3.16.0-4-common
$ apt-file search /linux/if.h 
dietlibc-dev: /usr/include/diet/linux/if.h
linux-headers-3.16.0-4-common: /usr/src/linux-headers-3.16.0-4-common/include/uapi/linux/if.h
linux-libc-dev: /usr/include/linux/if.h
$ tar Jtvf linux_3.16.7-ckt20.orig.tar.xz | awk '/\/if.h$/{print $NF}'
linux-3.16.7-ckt20/include/uapi/linux/if.h
$ tar Jxvf linux_3.16.7-ckt20.orig.tar.xz linux-3.16.7-ckt20/include/uapi/linux/if.h
linux-3.16.7-ckt20/include/uapi/linux/if.h
$ awk '/IFF_.*1<</' linux-3.16.7-ckt20/include/uapi/linux/if.h 

IFF_UP = 1<<0, /* sysfs */
IFF_BROADCAST = 1<<1, /* volatile */
IFF_DEBUG = 1<<2, /* sysfs */
IFF_LOOPBACK = 1<<3, /* volatile */
IFF_POINTOPOINT = 1<<4, /* volatile */
IFF_NOTRAILERS = 1<<5, /* sysfs */
IFF_RUNNING = 1<<6, /* volatile */
IFF_NOARP = 1<<7, /* sysfs */
IFF_PROMISC = 1<<8, /* sysfs */
IFF_ALLMULTI = 1<<9, /* sysfs */
IFF_MASTER = 1<<10, /* volatile */
IFF_SLAVE = 1<<11, /* volatile */
IFF_MULTICAST = 1<<12, /* sysfs */
IFF_PORTSEL = 1<<13, /* sysfs */
IFF_AUTOMEDIA = 1<<14, /* sysfs */
IFF_DYNAMIC = 1<<15, /* sysfs */
IFF_LOWER_UP = 1<<16, /* volatile */
IFF_DORMANT = 1<<17, /* volatile */
IFF_ECHO = 1<<18, /* volatile */

■左シフトビットなので、以下の数値の和になるはず。

$ awk '/IFF_.*1<</{sub(",","");print "echo "$1,"$(("$3"))"}' linux-3.16.7-ckt20/include/uapi/linux/if.h | bash
IFF_UP 1
IFF_BROADCAST 2
IFF_DEBUG 4
IFF_LOOPBACK 8
IFF_POINTOPOINT 16
IFF_NOTRAILERS 32
IFF_RUNNING 64
IFF_NOARP 128
IFF_PROMISC 256
IFF_ALLMULTI 512
IFF_MASTER 1024
IFF_SLAVE 2048
IFF_MULTICAST 4096
IFF_PORTSEL 8192
IFF_AUTOMEDIA 16384
IFF_DYNAMIC 32768
IFF_LOWER_UP 65536
IFF_DORMANT 131072
IFF_ECHO 262144

■ん?0x40も違う。。。64はRUNNING分?

$ awk '/IFF_.*1<</{sub(",","");print "echo "$1,"$(("$3"))"}' linux-3.16.7-ckt20/include/uapi/linux/if.h | bash | \
    awk '{if(/IFF_UP/ || /IFF_.*CAST/ || /PROMISC/ || /RUNNING/){sum+=$2;print $1}};END{printf "0x%x\n",sum}'
IFF_UP
IFF_BROADCAST
IFF_RUNNING
IFF_PROMISC
IFF_MULTICAST
0x1143

$ awk '/IFF_.*1<</{sub(",","");print "echo "$1,"$(("$3"))"}' linux-3.16.7-ckt20/include/uapi/linux/if.h | bash | \
    awk '{if(/IFF_UP/ || /IFF_.*CAST/ || /PROMISC/ ){sum+=$2;print $1}};END{printf "0x%x\n",sum}'IFF_UP
IFF_BROADCAST
IFF_PROMISC
IFF_MULTICAST
0x1103

■「IFF_UP」はdownで消せる。「IFF_RUNNING」フラグも消えているが、
 そもそも「IFF_RUNNING」と「IFF_LOWERUP」は計算されていないように見える。

$ awk '/IFF_.*1<</{sub(",","");print "echo "$1,"$(("$3"))"}' linux-3.16.7-ckt20/include/uapi/linux/if.h | bash | \
    awk '{if(/IFF_.*UP/ || /RUNNING/){printf "%s,%d,0x%x\n",$1,$2,$2}}'
IFF_UP,1,0x1
IFF_RUNNING,64,0x40
IFF_LOWER_UP,65536,0x10000

$ sudo ifconfig eth1 down
$ ip a list eth1 | grep "<" | sed -e 's/.*<//g' -e 's/>.*//g'
BROADCAST,MULTICAST,PROMISC
$ cat /sys/class/net/eth1/flags 
0x1102

■「IFF_PROMISC」は256なので、「0x100」分減るのは想定通り。

$ echo 256 | awk '{printf "0x%x\n",$1}'
0x100

$ sudo ifconfig eth1 -promisc down
$ ip a list eth1 | grep "<" | sed -e 's/.*<//g' -e 's/>.*//g'
BROADCAST,MULTICAST
$ cat /sys/class/net/eth1/flags 
0x1002

$ sudo ifconfig eth1 promisc down
$ ip a list eth1 | grep "<" | sed -e 's/.*<//g' -e 's/>.*//g'
BROADCAST,MULTICAST,PROMISC
$ cat /sys/class/net/eth1/flags
0x1102

$ sudo ifconfig eth1 promisc up
$ ip a list eth1 | grep "<" | sed -e 's/.*<//g' -e 's/>.*//g'
BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP
$ cat /sys/class/net/eth1/flags
0x1103