[package] base-files: fix udhcpc address acquisition on network restart (patch by...
[openwrt.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