[package] base-files: fix udhcpc address acquisition on network restart (patch by...
[openwrt/svn-archive/archive.git] / package / base-files / files / usr / share / udhcpc / default.script
1 #!/bin/sh
2 [ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
3
4 . /etc/functions.sh
5 include /lib/network
6 RESOLV_CONF="/tmp/resolv.conf.auto"
7
8 change_state () {
9 [ -n "$ifc" ] || return
10 uci_revert_state "$1" "$2" "$3" "$4"
11 uci_set_state "$1" "$2" "$3" "$4"
12 }
13
14 uci_get() {
15 [ -n "$ifc" ] || return
16 uci -P /dev/null get "$1" 2>/dev/null
17 }
18
19 setup_interface () {
20 local old_ip
21 local old_broadcast
22 local old_subnet
23 local old_router
24 local old_dns
25 local user_dns
26 local user_router
27
28 [ -n "$ifc" ] && {
29 config_get old_ip "$ifc" ipaddr
30 config_get old_broadcast "$ifc" broadcast
31 config_get old_subnet "$ifc" netmask
32 }
33
34 [ "$1" = "ifup" ] \
35 || [ "$ip" != "$old_ip" ] \
36 || [ "${broadcast:-+}" != "$old_broadcast" ] \
37 || [ "${subnet:-255.255.255.0}" != "$old_subnet" ] && {
38 echo "udhcpc: ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}"
39 ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}
40
41 change_state network "$ifc" ipaddr "$ip"
42 change_state network "$ifc" broadcast "${broadcast:-+}"
43 change_state network "$ifc" netmask "${subnet:-255.255.255.0}"
44 }
45
46
47 # Default Route
48 [ -n "$ifc" ] && {
49 change_state network "$ifc" lease_gateway "$router"
50 config_get old_router "$ifc" gateway
51 user_router=$(uci_get "network.$ifc.gateway")
52 [ -n "$user_router" ] && router="$user_router"
53 }
54
55 [ -n "$router" ] && [ "$router" != "0.0.0.0" ] && [ "$router" != "255.255.255.255" ] && [ "$router" != "$old_router" ] && {
56 echo "udhcpc: setting default routers: $router"
57
58 local valid_gw=""
59 for i in $router ; do
60 route add default gw $i dev $interface
61 valid_gw="${valid_gw:+$valid_gw|}$i"
62 done
63
64 eval $(route -n | awk '
65 /^0.0.0.0\W{9}('$valid_gw')\W/ {next}
66 /^0.0.0.0/ {print "route del -net "$1" gw "$2";"}
67 ')
68
69 change_state network "$ifc" gateway "$router"
70 }
71
72 # CIDR STATIC ROUTES (rfc3442)
73 [ -n "$cidrroute" ] && {
74 # This defines how many CIDR Routes can be assigned so that we do not enter
75 # an endless loop on malformed data
76 MAXCIDRROUTES=24;
77 while [ ${MAXCIDRROUTES} -gt "0" ]; do
78 # Format is
79 # $MASK $NW $GW
80 # $NW == AAA.BBB.CCC.DDD
81 # $GW == EEE.FFF.CCC.DDD
82 # $MASK AAA.[BBB].[CCC].[DDD] EEE.FFF.GGG.HHH
83 # 1 2 3 4 5 6 7 8 9
84 MASK=$(echo $cidrroute | awk '{ print $1 }')
85 if [ ${MASK} = "0" ] ; then
86 # $MASK EEE.FFF.GGG.HHH
87 # 1 2 3 5 6
88 NW="0"
89 GW=$(echo $cidrroute | awk '{ print $2"."$3"."$4"."$5 }' )
90 elif [ ${MASK} -le "8" ] ; then
91 # $MASK AAA EEE.FFF.GGG.HHH
92 # 1 2 3 5 6 7
93 NW=$(echo $cidrroute | awk '{ print $2 }' )
94 GW=$(echo $cidrroute | awk '{ print $3"."$4"."$5"."$6 }' )
95 elif [ ${MASK} -le "16" ] ; then
96 # $MASK AAA.BBB EEE.FFF.GGG.HHH
97 # 1 2 3 5 6 7 8
98 NW=$(echo $cidrroute | awk '{ print $2"."$3 }' )
99 GW=$(echo $cidrroute | awk '{ print $4"."$5"."$6"."$7 }' )
100 elif [ ${MASK} -le "24" ] ; then
101 # $MASK AAA.BBB.CCC EEE.FFF.GGG.HHH
102 # 1 2 3 4 5 6 7 8
103 NW=$(echo $cidrroute | awk '{ print $2"."$3"."$4 }' )
104 GW=$(echo $cidrroute | awk '{ print $5"."$6"."$7"."$8 }' )
105
106 else
107 # $MASK AAA.BBB.CCC.DDD EEE.FFF.GGG.HHH
108 # 1 2 3 4 5 6 7 8 9
109 NW=$(echo $cidrroute | awk '{ print $2"."$3"."$4"."$5 }' )
110 GW=$(echo $cidrroute | awk '{ print $6"."$7"."$8"."$9 }' )
111 fi
112 echo [$ROUTECOUNTER] Route Network: $NW/$MASK Gateway: $GW on $interface
113
114 # TODO: Check for malformed data here to eliminate counter workaround
115 # Malformed data is: ... or xxx... or xxx.yyy.. or xxx.yyy.zzz.
116
117 [ -n "$NW" ] && [ -n "$GW" ] && {
118 route add $NW gw $GW dev $interface
119 }
120
121 # Clear the strings incase they don't get set next time around
122 if [ ${NW} = "0" ]; then
123 NW=""
124 fi
125 TMP="$MASK $NW $GW "
126 NW=""
127 GW=""
128
129 # Remove the '.' so that we can delete them from the input with sed
130 TMP=$(echo $TMP | sed "s/\./ /g")
131
132 # Remove the previous entry from cidrroute
133 cidrroute=$(echo $cidrroute | sed "s/$TMP//g")
134
135 # Add to counter
136 let ROUTECOUNTER=$ROUTECOUNTER+1;
137 let MAXCIDRROUTES=$MAXCIDRROUTES-1;
138
139 # Leave the loop if cidrroutes is empty (we've parsed everything)
140 [ ! -n "$cidrroute" ] && break
141
142 done
143
144 echo "done."
145 }
146
147 # DNS
148 config_get old_dns "$ifc" dns
149 user_dns=$(uci_get "network.$ifc.dns")
150 [ -n "$user_dns" ] && dns="$user_dns"
151
152 [ -n "$dns" ] && [ ! -s "${RESOLV_CONF}" -o "$dns" != "$old_dns" ] && {
153 echo "udhcpc: setting dns servers: $dns"
154 echo -n > "${RESOLV_CONF}.tmp"
155 for i in $dns ; do
156 echo "nameserver $i" >> "${RESOLV_CONF}.tmp"
157 done
158 ${domain:+echo search $domain} >> "${RESOLV_CONF}.tmp"
159 mv "${RESOLV_CONF}.tmp" "$RESOLV_CONF"
160
161 change_state network "$ifc" dnsdomain "$domain"
162 change_state network "$ifc" dns "$dns"
163 }
164
165 [ -n "$ifc" ] || return
166
167 # UCI State
168 change_state network "$ifc" lease_server "$serverid"
169 change_state network "$ifc" lease_acquired "$(date '+%s')"
170 change_state network "$ifc" lease_lifetime "$lease"
171 [ -n "$ntpsrv" ] && change_state network "$ifc" lease_ntpsrv "$ntpsrv"
172 [ -n "$timesvr" ] && change_state network "$ifc" lease_timesrv "$timesvr"
173 [ -n "$hostname" ] && change_state network "$ifc" lease_hostname "$hostname"
174 [ -n "$timezone" ] && change_state network "$ifc" lease_timezone "$timezone"
175
176
177 # Hotplug
178 env -i ACTION="$1" INTERFACE="$ifc" DEVICE="$ifname" PROTO=dhcp /sbin/hotplug-call iface
179 }
180
181
182 scan_interfaces
183 applied=
184 for ifc in $interfaces __default; do
185 if [ "$ifc" = __default ]; then
186 ifc=""
187 [ -n "$applied" ] && continue
188 else
189 config_get ifname "$ifc" ifname
190 [ "$ifname" = "$interface" ] || continue
191
192 config_get proto "$ifc" proto
193 [ "$proto" = "dhcp" ] || continue
194 applied=true
195 fi
196
197 case "$1" in
198 deconfig)
199 ifconfig "$interface" 0.0.0.0
200 [ -n "$ifc" ] && {
201 env -i ACTION="ifdown" INTERFACE="$ifc" DEVICE="$ifname" PROTO=dhcp /sbin/hotplug-call iface
202
203 config_get device "$ifc" device
204 config_get ifname "$ifc" ifname
205 config_get aliases "$ifc" aliases
206 uci_revert_state network "$ifc"
207 [ -n "$device" ] && uci_set_state network "$ifc" device "$device"
208 [ -n "$ifname" ] && uci_set_state network "$ifc" ifname "$ifname"
209 [ -n "$aliases" ] && uci_set_state network "$ifc" aliases "$aliases"
210 }
211 ;;
212 renew)
213 setup_interface update
214 ;;
215 bound)
216 setup_interface ifup
217 ;;
218 esac
219 done
220
221 # user rules
222 [ -f /etc/udhcpc.user ] && . /etc/udhcpc.user
223
224 exit 0