Linux之通过udev规则指定网络设备

sudo udevadm control --reload // 任何规则文件及相关脚本修改后都需要执行 ...
// 查询udev数据库中的设备信息
udevadm info -a -p /sys/class/net/eth0


// 获取到的设备信息 ...
looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.1/1-1.1.1:1.0/net/eth0':
KERNEL=="eth0"
SUBSYSTEM=="net"
DRIVER==""
ATTR{addr_assign_type}=="0"
ATTR{addr_len}=="6"
ATTR{address}=="b8:27:eb:a7:c3:e6"
ATTR{broadcast}=="ff:ff:ff:ff:ff:ff"
ATTR{carrier}=="0"
ATTR{carrier_changes}=="1"
ATTR{dev_id}=="0x0"
ATTR{dev_port}=="0"
ATTR{dormant}=="0"
ATTR{duplex}=="half"
ATTR{flags}=="0x1003"
ATTR{gro_flush_timeout}=="0"
ATTR{ifalias}==""
ATTR{ifindex}=="2"
ATTR{iflink}=="2"
ATTR{link_mode}=="0"
ATTR{mtu}=="1500"
ATTR{netdev_group}=="0"
ATTR{operstate}=="down"
ATTR{proto_down}=="0"
ATTR{speed}=="10"
ATTR{tx_queue_len}=="1000"
ATTR{type}=="1"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.1/1-1.1.1:1.0':
KERNELS=="1-1.1.1:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="lan78xx"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceProtocol}=="ff"
ATTRS{bInterfaceSubClass}=="00"
ATTRS{bNumEndpoints}=="03"
ATTRS{supports_autosuspend}=="1"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.1':
KERNELS=="1-1.1.1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="ff"
ATTRS{bDeviceProtocol}=="ff"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="2mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0300"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="4"
ATTRS{devpath}=="1.1.1"
ATTRS{idProduct}=="7800"
ATTRS{idVendor}=="0424"
ATTRS{ltm_capable}=="no"
ATTRS{maxchild}=="0"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="fixed"
ATTRS{speed}=="480"
ATTRS{urbnum}=="1332"
ATTRS{version}==" 2.10"

...
// add rndis_host 设备时执行脚本 ...

# /etc/udev/rules.d/90-local.rules 
ACTION=="add", SUBSYSTEMS=="usb", DRIVERS=="rndis_host", RUN+="/danoo/bin/addnet.sh"

# /danoo/bin/addnet.sh 
#!/bin/bash

for interface in /sys/class/net/*; do
    if [[ ${interface} == /sys/class/net/eth* ]]; then
    ok=$(udevadm info ${interface} |grep -v grep |grep rndis_host |wc -l)
    if [ ${ok} -ne 0 ];then
         name=$(basename ${interface})
         echo ${name} > /dev/shm/rndis_host
         ifconfig ${name} 192.168.0.99 netmask 255.255.255.0
         ifconfig ${name} mtu 1400
         route del default; route add default gw 192.168.0.1
         echo 'nameserver 114.114.114.114' > /etc/resolv.conf
    fi
    fi
done
// 指定命名规则
SUBSYSTEM=="net",ACTION=="add",DRIVERS=="?*",ATTR{address}=="00:00:00:00:00:01",ATTR{dev_id}=="0x0",ATTR{type}=="1",KERNEL=="eth*",NAME="eth1"
SUBSYSTEM=="net",ACTION=="add",DRIVERS=="?*",ATTR{address}=="00:e0:40:68:4b:36",ATTR{type}=="1",KERNEL=="eth*",NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}!="00:00:00:00:00:00", ATTRS{modalias}=="usb:*", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}!="00:00:00:00:00:00", ATTRS{modalias}=="pci:*", ATTRS{vendor}=="0x10ec", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}!="00:00:00:00:00:01", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="wlan*", NAME="eth1"
// 参考

In an ideal situation? Rewrite that as a udev rule so that it triggers automatically on connection. It will have to be evaluated after other rules so that any interface renaming has already happened by the time it gets evaluated (/etc/udev/rules.d/99-x-local.conf is probably the place to put it), but the basic rule should look similar to this:

SUBSYSTEM=="net", ENV{ID_BUS}=="usb", ENV{ID_USB_DRIVER}=="rndis_host", ACTION=="add", RUN{program}+="/bin/sh -c 'echo $env{INTERFACE} > /var/tmp/myfile'"

The first four parts match the exact event generated when the device gets connected, more specifically:

SUBSYSTEM=="net" matches networking devices
ENV{ID_BUS}=="usb" matches only those networking devices that are connected via USB.
ENV{ID_USB_DRIVER}=="rndis_host" matches only USB devices that use the RNDIS host device driver (the standard one used by Android phones (and I think Windows and Blackberry too) for USB tethering.
ACTION=="add" matches on the hotplug events only (so this only gets run when the device gets connected, though you could just as easily add a second similar rule matching on the "remove" action to do something when the phone gets unplugged).
The final item adds a command to the queue of things that udev will invoke when the rule processing is done,. In this case, it's adding a shell invocation that will write out the interface name to the desired location (udev itself will substitute the $env{INTERFACE} for the actual interface name).

I can't guarantee that that will work in all cases, but it at least seems to work for my Nexus 6P and should in theory work for most Android phones.