Openwrt 修改默认ip脚本分析
/etc/board.json生成
etc/init.d/bootboot() { /bin/config_generate }
/bin/config_generate#!/bin/sh CFG=/etc/board.json . /usr/share/libubox/jshn.sh # /etc/board.json文件存在不存在或者为空,则调用 board_detect 生成该文件,否则往下进行 # 第一次启动肯定不会存在该文件,所以肯定执行 board_detect [ -s $CFG ] || /bin/board_detect || exit 1 [ -s /etc/config/network -a -s /etc/config/system ] && exit 0
/bin/board_detect#!/bin/sh CFG=$1 [ -n "$CFG" ] || CFG=/etc/board.json # 如果/etc/board.d/是个目录,且 /etc/board.json 文件存在不存在或者为空 # 变量/etc/board.d/下面的脚本,然后执行 [ -d "/etc/board.d/" -a ! -s "$CFG" ] && { for a in $(ls /etc/board.d/*); do [ -x $a ] || continue; $(. $a) done } [ -s "$CFG" ] || return 1
在
/etc/board.d/目录下脚本如下:02_network:来源 target/linux/mpc85xx/base-files/etc/board.d/02_network
#!/bin/sh # Copyright (C) 2014-2015 OpenWrt.org . /lib/functions/uci-defaults.sh . /lib/functions.sh . /lib/functions/system.sh board_config_update # board=fsl,P2020RDB 来源dts compatible = "fsl,P2020RDB"; board=$(board_name) case "$board" in fsl,P2020RDB) # 这里把eth0 eth1 都设置为lan口 ucidef_set_interface_lan "eth0 eth1" ;; *) # 这里把eth0设置为lan口,把eth1 设置为wan口 ucidef_set_interfaces_lan_wan "eth0" "eth1" ;; esac board_config_flush exit 0
注意:ucidef_set_interface_lan和ucidef_set_interfaces_lan_wan函数会生成
/etc/board.json文件。这两个函数存放位置:package/base-files/files/lib/functions/uci-defaults.shucidef_set_interface_lan函数ucidef_set_interface_lan() { ucidef_set_interface "lan" device "$1" protocol "${2:-static}" }
ucidef_set_interfaces_lan_wan函数ucidef_set_interfaces_lan_wan() { local lan_if="$1" local wan_if="$2" ucidef_set_interface_lan "$lan_if" ucidef_set_interface_wan "$wan_if" }
ucidef_set_interface函数以ucidef_set_interface_lan "eth0 eth1" 为例说明该函数功能: - ucidef_set_interface "lan" device "eth0 eth1" protocol "${2:-static}" - $1 = lan - $2 = device - $3 = "eth0 eth1" - $4 = protocol - $5 = static下面分析代码
ucidef_set_interface() { # network=lan local network=$1; shift # 选中/etc/board.json 里面的 network下的lan节点 json_select_object network json_select_object "$network" # 此时$1=device while [ -n "$1" ]; do local opt=$1; shift # opt=device local val=$1; shift # val = "eth0 eth1" [ -n "$opt" -a -n "$val" ] || break # 如果 val是列表,会添加json数组 # 大概是这个样子 "ports": ["eth0", "eth1"], [ "$opt" = "device" -a "$val" != "${val/ //}" ] && { # 这里处理device 多个网口 桥接到lan json_select_array "ports" for e in $val; do json_add_string "" "$e"; done json_close_array } || { # lan下的"protocol"节点 json_add_string "$opt" "$val" } done # 下面如果 没有protocol 设置默认的值, if ! json_is_a protocol string; then case "$network" in lan) json_add_string protocol static ;; wan) json_add_string protocol dhcp ;; *) json_add_string protocol none ;; esac fi json_select .. json_select .. }
经过上面的代码后,就会生成
/etc/board.json{ "model": { "id": "fsl,P2020RDB", "name": "Freescale P2020RDB" }, "network": { "lan": { "ports": [ "eth0", "eth1" ], "protocol": "static" } } }
99-default_network:来源 package/base-files/files/etc/board.d/99-default_network
#!/bin/sh # # Copyright (C) 2013-2015 OpenWrt.org # . /lib/functions/uci-defaults.sh board_config_update # 判断/etc/board.json里面是否有 network 节点,如果有直接退出,没有的话往下 json_is_a network object && exit 0 # 理论上不会到这,因为在 02_network 中肯定生成了 /etc/board.json中的network节点 # 能跑到这说明没有network 节点,这里会设置节点, # ucidef_set_interface_lan 'eth0' [ -d /sys/class/net/eth1 ] && ucidef_set_interface_wan 'eth1' board_config_flush exit 0
config_generate继续分析
在上个章节第2步骤,通过[ -s $CFG ] || /bin/board_detect || exit 1 会生成默认的/etc/board.json文件,接下来会继续根据给json文件生成/etc/config/network,下面继续分析。
/bin/config_generate文件下面的内容:
# 加载/etc/board.json文件到shell
json_init
json_load "$(cat ${CFG})"
umask 077
# 如果network不存在或者为空
if [ ! -s /etc/config/network ]; then
bridge_name=""
# 创建该文件
touch /etc/config/network
# 生成config interface 'loopback'和config globals 'globals'节点
generate_static_network
# 获取json中的bridge 这里是空的,json里面没有bridge
json_get_vars bridge
[ -n "$bridge" ] && {
# 由于是空的,所以不会到这里,但是如果不是空的
json_select bridge
json_get_vars name macaddr
generate_bridge "$name" "$macaddr"
json_select ..
bridge_name=$name
}
# 按照上面提到的json文件,这里keys=lan
# 所以执行的是 bridge_name=""
# generate_network lan $bridge_name
json_get_keys keys network
for key in $keys; do generate_network $key $bridge_name; done
json_get_keys keys switch
for key in $keys; do generate_switch $key; done
fi
generate_network代码如下:
addr_offset=2
generate_network() {
local ports device macaddr protocol type ipaddr netmask vlan
local bridge=$2
json_select network
json_select "$1"
json_get_vars device macaddr metric protocol ipaddr netmask vlan
json_get_values ports ports
json_select ..
json_select ..
[ -n "$device" -o -n "$ports" ] || return
# Force bridge for "lan" as it may have other devices (e.g. wireless)
# bridged
[ "$1" = "lan" -a -z "$ports" ] && {
ports="$device"
}
[ -n "$ports" -a -z "$bridge" ] && {
uci -q batch <<-EOF
add network device
set network.@device[-1].name='br-$1'
set network.@device[-1].type='bridge'
EOF
for port in $ports; do uci add_list network.@device[-1].ports="$port"; done
[ -n "$macaddr" ] && {
for port in $ports; do
uci -q batch <<-EOF
add network device
set network.@device[-1].name='$port'
set network.@device[-1].macaddr='$macaddr'
EOF
done
}
device=br-$1
type=
macaddr=""
}
[ -n "$bridge" ] && {
[ -z "$ports" ] && ports="$device"
if [ -z "$vlan" ]; then
bridge_vlan_id=$((bridge_vlan_id + 1))
vlan=$bridge_vlan_id
fi
generate_bridge_vlan $1 $bridge "$ports" $vlan
device=$bridge.$vlan
type=""
}
if [ -n "$macaddr" ]; then
uci -q batch <<-EOF
add network device
set network.@device[-1].name='$device'
set network.@device[-1].macaddr='$macaddr'
EOF
fi
uci -q batch <<-EOF
delete network.$1
set network.$1='interface'
set network.$1.type='$type'
set network.$1.device='$device'
set network.$1.metric='$metric'
set network.$1.proto='none'
EOF
case "$protocol" in
static)
local ipad
case "$1" in
lan) ipad=${ipaddr:-"192.168.10.1"} ;;
*) ipad=${ipaddr:-"192.168.$((addr_offset++)).1"} ;;
esac
netm=${netmask:-"255.255.255.0"}
uci -q batch <<-EOF
set network.$1.proto='static'
set network.$1.ipaddr='$ipad'
set network.$1.netmask='$netm'
EOF
[ -e /proc/sys/net/ipv6 ] && uci set network.$1.ip6assign='60'
;;
dhcp)
# fixup IPv6 slave interface if parent is a bridge
[ "$type" = "bridge" ] && device="br-$1"
uci set network.$1.proto='dhcp'
[ -e /proc/sys/net/ipv6 ] && {
uci -q batch <<-EOF
delete network.${1}6
set network.${1}6='interface'
set network.${1}6.device='$device'
set network.${1}6.proto='dhcpv6'
EOF
}
;;
pppoe)
uci -q batch <<-EOF
set network.$1.proto='pppoe'
set network.$1.username='username'
set network.$1.password='password'
EOF
[ -e /proc/sys/net/ipv6 ] && {
uci -q batch <<-EOF
set network.$1.ipv6='1'
delete network.${1}6
set network.${1}6='interface'
set network.${1}6.device='@${1}'
set network.${1}6.proto='dhcpv6'
EOF
}
;;
esac
}