Mat*_*ner 39 python linux networking ipv4 procfs
如何仅使用proc获取所有网络接口的(IPv4)地址?经过一番广泛调查后,我发现了以下内容:
ifconfig利用SIOCGIFADDR,需要打开套接字并提前了解所有接口名称.它也没有记录在Linux上的任何手册页中.proc包含/proc/net/dev,但这是一个接口统计信息列表.proc包含/proc/net/if_inet6,这正是我所需要的,但对于IPv6.proc,但实际地址很少使用,除非明确部分连接.getifaddrs,这是一个非常"神奇"的功能,你期望在Windows中看到它.它也在BSD上实现.然而,它不是非常面向文本的,这使得很难使用非C语言.xch*_*nge 19
/proc/net/fib_trie 拥有网络地形
只需打印所有适配器的地址:
$ awk '/32 host/ { print f } {f=$2}' <<< "$(</proc/net/fib_trie)"
127.0.0.1
192.168.0.5
192.168.1.14
Run Code Online (Sandbox Code Playgroud)
要确定这些地址的适配器(a)请咨询适配器的目标网络/proc/net/route,(b)将这些网络与以下网络匹配,/proc/net/fib_trie并且(c)打印这些网络下列出的相应/ 32主机地址.
同样没有python遗憾的,但相当awky bash的方法:
#!/bin/bash
ft_local=$(awk '$1=="Local:" {flag=1} flag' <<< "$(</proc/net/fib_trie)")
for IF in $(ls /sys/class/net/); do
networks=$(awk '$1=="'$IF'" && $3=="00000000" && $8!="FFFFFFFF" {printf $2 $8 "\n"}' <<< "$(</proc/net/route)" )
for net_hex in $networks; do
net_dec=$(awk '{gsub(/../, "0x& "); printf "%d.%d.%d.%d\n", $4, $3, $2, $1}' <<< $net_hex)
mask_dec=$(awk '{gsub(/../, "0x& "); printf "%d.%d.%d.%d\n", $8, $7, $6, $5}' <<< $net_hex)
awk '/'$net_dec'/{flag=1} /32 host/{flag=0} flag {a=$2} END {print "'$IF':\t" a "\n\t'$mask_dec'\n"}' <<< "$ft_local"
done
done
exit 0
Run Code Online (Sandbox Code Playgroud)
输出:
eth0: 192.168.0.5
255.255.255.0
lo: 127.0.0.1
255.0.0.0
wlan0: 192.168.1.14
255.255.255.0
Run Code Online (Sandbox Code Playgroud)
已知限制:
对于与其他主机地址共享网络的主机地址,此方法无法可靠地工作.这种网络唯一性的丢失使得无法从fib_trie确定正确的主机地址,因为这些地址的顺序不一定与路由网络的顺序相匹配.
话虽如此,我不确定为什么你想要首先属于同一网络的多个主机地址.因此在大多数用例中,这种方法应该可以正常工作.
sar*_*old 14
您可能会发现输出ip addr show比其他工具的输出更容易解析:
$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:24:1d:ce:47:05 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.121/24 brd 192.168.0.255 scope global eth0
inet6 fe80::224:1dff:fece:4705/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN qlen 1000
link/ether 00:24:1d:ce:35:d5 brd ff:ff:ff:ff:ff:ff
4: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 92:e3:6c:08:1f:af brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
inet6 fe80::90e3:6cff:fe08:1faf/64 scope link
valid_lft forever preferred_lft forever
Run Code Online (Sandbox Code Playgroud)
另一种选择是文件/proc/net/tcp.它显示了所有当前打开的TCP会话,这与您要求的不同,但可能是足够好的.
$ cat tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 13536 1 ffff88019f0a1380 300 0 0 2 -1
1: 00000000:1355 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 19877854 1 ffff880016e69380 300 0 0 2 -1
2: 017AA8C0:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 13633 1 ffff88019f0a1a00 300 0 0 2 -1
3: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8971 1 ffff88019f0a0000 300 0 0 2 -1
4: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 12952880 1 ffff880030e30680 300 0 0 2 -1
5: 00000000:0539 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 14332 1 ffff88019f0a2080 300 0 0 2 -1
6: 00000000:C000 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 14334 1 ffff88019f0a2700 300 0 0 2 -1
7: 0100007F:0A44 00000000:0000 0A 00000000:00000000 00:00000000 00000000 119 0 51794804 1 ffff880016e6a700 300 0 0 2 -1
8: 7900A8C0:B094 53D50E48:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 64877487 1 ffff880100502080 23 4 16 4 -1
9: 7900A8C0:9576 537F7D4A:01BB 06 00000000:00000000 03:00000E5D 00000000 0 0 0 3 ffff880100c84600
10: 7900A8C0:CC84 0CC181AE:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 61775908 1 ffff880198715480 35 4 11 4 -1
$ irb
irb(main):001:0> [0x79, 0x00, 0xa8, 0xc0]
=> [121, 0, 168, 192]
Run Code Online (Sandbox Code Playgroud)
我的IP是192.168.0.121; 注意有趣的算术让它出来正确.:)
F. *_*uri 11
/proc:不幸的是,这是bash(仅限bash,没有任何fork),而不是python.但我希望这是可读的:
#!/bin/bash
# ip functions that set variables instead of returning to STDOUT
hexToInt() {
printf -v $1 "%d\n" 0x${2:6:2}${2:4:2}${2:2:2}${2:0:2}
}
intToIp() {
local var=$1 iIp
shift
for iIp ;do
printf -v $var "%s %s.%s.%s.%s" "${!var}" $(($iIp>>24)) \
$(($iIp>>16&255)) $(($iIp>>8&255)) $(($iIp&255))
done
}
maskLen() {
local i
for ((i=0; i<32 && ( 1 & $2 >> (31-i) ) ;i++));do :;done
printf -v $1 "%d" $i
}
# The main loop.
while read -a rtLine ;do
if [ ${rtLine[2]} == "00000000" ] && [ ${rtLine[7]} != "00000000" ] ;then
hexToInt netInt ${rtLine[1]}
hexToInt maskInt ${rtLine[7]}
if [ $((netInt&maskInt)) == $netInt ] ;then
for procConnList in /proc/net/{tcp,udp} ;do
while IFS=': \t\n' read -a conLine ;do
if [[ ${conLine[1]} =~ ^[0-9a-fA-F]*$ ]] ;then
hexToInt ipInt ${conLine[1]}
[ $((ipInt&maskInt)) == $netInt ] && break 3
fi
done < $procConnList
done
fi
fi
done < /proc/net/route
# And finaly the printout of what's found
maskLen maskBits $maskInt
intToIp addrLine $ipInt $netInt $maskInt
printf -v outForm '%-12s: %%s\\n' Interface Address Network Netmask Masklen
printf "$outForm" $rtLine $addrLine $maskBits\ bits
Run Code Online (Sandbox Code Playgroud)
有一个输出样本:
Interface : eth0
Address : 192.168.1.32
Network : 192.168.1.0
Netmask : 255.255.255.0
Masklen : 24 bits
Run Code Online (Sandbox Code Playgroud)
说明:
我使用IPV4的整数值来检查IP & MASK == NETWORK.
我首先阅读/proc/net/route路由配置,搜索可以在没有任何网关(gw==000000)的情况下到达的路由.
对于这样的路由,我搜索所有连接(TCP,如果在TCP中找不到UDP),使用此路由进行连接,第一个端点是我的主机地址.
注意:这不适用于PPP连接
注意:如果没有任何打开的网络连接,这将无法在完全安静的主机上运行.你可以做些什么echo -ne '' | nc -q 0 -w 1 8.8.8.8 80 & sleep .2 && ./retrieveIp.sh来确保找到的东西/proc/net/tcp.
Nota3,2016-09.23:新的bash版本使用 功能>(command)语法.此implie一个错误在管线18:的空间必须是之间存在和!!multiple inline pipe >(
有一个补丁:一旦你创建了一个getIPv4.sh通过复制以前的脚本调用的文件,你可以将以下内容粘贴到命令:patch -p0
--- getIPv4.sh
+++ getIPv4.sh
@@ -35,13 +35,16 @@
done < $procConnList
done
fi
+ elif [ ${rtLine[1]} == "00000000" ] && [ ${rtLine[7]} == "00000000" ] ;then
+ hexToInt netGw ${rtLine[2]}
fi
done < /proc/net/route
# And finaly the printout of what's found
maskLen maskBits $maskInt
-intToIp addrLine $ipInt $netInt $maskInt
-printf -v outForm '%-12s: %%s\\n' Interface Address Network Netmask Masklen
+intToIp addrLine $ipInt $netInt $netGw $maskInt
+printf -v outForm '%-12s: %%s\\n' \
+ Interface Address Network Gateway Netmask Masklen
printf "$outForm" $rtLine $addrLine $maskBits\ bits
Run Code Online (Sandbox Code Playgroud)
结束Ctrld,这可能会输出:
patching file getIPv4.sh
Run Code Online (Sandbox Code Playgroud)
有可能
Hunk #1 succeeded at 35 with fuzz 2.
Run Code Online (Sandbox Code Playgroud)
然后重新运行您的脚本:
getIPv4.sh
Interface : eth0
Address : 192.168.1.32
Network : 192.168.1.0
Gateway : 192.168.1.1
Netmask : 255.255.255.0
Masklen : 24 bits
Run Code Online (Sandbox Code Playgroud)
没有/ proc/net/if_inet6的IPv4模拟
ifconfig做:
fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)
ioctl(fd, SIOCGIFCONF, ...)
Run Code Online (Sandbox Code Playgroud)
你会得到这样的东西:
ioctl(4, SIOCGIFCONF, {120, {{"lo", {AF_INET, inet_addr("127.0.0.1")}}, {"eth0", {AF_INET, inet_addr("10.6.23.69")}}, {"tun0", {AF_INET, inet_addr("10.253.10.151")}}}})
Run Code Online (Sandbox Code Playgroud)
小智 5
ip addr show dev eth0 | grep "inet " | cut -d ' ' -f 6 | cut -f 1 -d '/'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
39954 次 |
| 最近记录: |