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