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