b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | #!/bin/sh |
| 2 | [ -z "$2" ] && echo "Error: should be run by odhcpc6c" && exit 1 |
| 3 | . /lib/functions.sh |
| 4 | . /lib/netifd/netifd-proto.sh |
| 5 | |
| 6 | setup_interface () { |
| 7 | local device="$1" |
| 8 | local prefsig="" |
| 9 | local addrsig="" |
| 10 | |
| 11 | # Apply IPv6 / ND configuration |
| 12 | HOPLIMIT=$(cat /proc/sys/net/ipv6/conf/$device/hop_limit) |
| 13 | [ -n "$RA_HOPLIMIT" -a -n "$HOPLIMIT" ] && [ "$RA_HOPLIMIT" -gt "$HOPLIMIT" ] && echo "$RA_HOPLIMIT" > /proc/sys/net/ipv6/conf/$device/hop_limit |
| 14 | [ -n "$RA_MTU" ] && [ "$RA_MTU" -ge 1280 ] && echo "$RA_MTU" > /proc/sys/net/ipv6/conf/$device/mtu 2>/dev/null |
| 15 | [ -n "$RA_REACHABLE" ] && [ "$RA_REACHABLE" -gt 0 ] && echo "$RA_REACHABLE" > /proc/sys/net/ipv6/neigh/$device/base_reachable_time_ms |
| 16 | [ -n "$RA_RETRANSMIT" ] && [ "$RA_RETRANSMIT" -gt 0 ] && echo "$RA_RETRANSMIT" > /proc/sys/net/ipv6/neigh/$device/retrans_time_ms |
| 17 | |
| 18 | proto_init_update "*" 1 |
| 19 | |
| 20 | # Merge RA-DNS |
| 21 | for radns in $RA_DNS; do |
| 22 | local duplicate=0 |
| 23 | for dns in $RDNSS; do |
| 24 | [ "$radns" = "$dns" ] && duplicate=1 |
| 25 | done |
| 26 | [ "$duplicate" = 0 ] && RDNSS="$RDNSS $radns" |
| 27 | done |
| 28 | |
| 29 | for dns in $RDNSS; do |
| 30 | proto_add_dns_server "$dns" |
| 31 | done |
| 32 | |
| 33 | for radomain in $RA_DOMAINS; do |
| 34 | local duplicate=0 |
| 35 | for domain in $DOMAINS; do |
| 36 | [ "$radomain" = "$domain" ] && duplicate=1 |
| 37 | done |
| 38 | [ "$duplicate" = 0 ] && DOMAINS="$DOMAINS $radomain" |
| 39 | done |
| 40 | |
| 41 | for domain in $DOMAINS; do |
| 42 | proto_add_dns_search "$domain" |
| 43 | done |
| 44 | |
| 45 | for prefix in $PREFIXES; do |
| 46 | proto_add_ipv6_prefix "$prefix" |
| 47 | prefsig="$prefsig ${prefix%%,*}" |
| 48 | local entry="${prefix#*/}" |
| 49 | entry="${entry#*,}" |
| 50 | entry="${entry#*,}" |
| 51 | local valid="${entry%%,*}" |
| 52 | |
| 53 | if [ -z "$RA_ADDRESSES" -a -z "$RA_ROUTES" -a \ |
| 54 | -z "$RA_DNS" -a "$FAKE_ROUTES" = 1 ]; then |
| 55 | RA_ROUTES="::/0,$SERVER,$valid,4096" |
| 56 | fi |
| 57 | done |
| 58 | |
| 59 | for prefix in $USERPREFIX; do |
| 60 | proto_add_ipv6_prefix "$prefix" |
| 61 | done |
| 62 | |
| 63 | # Merge addresses |
| 64 | for entry in $RA_ADDRESSES; do |
| 65 | local duplicate=0 |
| 66 | local addr="${entry%%/*}" |
| 67 | for dentry in $ADDRESSES; do |
| 68 | local daddr="${dentry%%/*}" |
| 69 | [ "$addr" = "$daddr" ] && duplicate=1 |
| 70 | done |
| 71 | [ "$duplicate" = "0" ] && ADDRESSES="$ADDRESSES $entry" |
| 72 | done |
| 73 | |
| 74 | for entry in $ADDRESSES; do |
| 75 | local addr="${entry%%/*}" |
| 76 | entry="${entry#*/}" |
| 77 | local mask="${entry%%,*}" |
| 78 | entry="${entry#*,}" |
| 79 | local preferred="${entry%%,*}" |
| 80 | entry="${entry#*,}" |
| 81 | local valid="${entry%%,*}" |
| 82 | |
| 83 | proto_add_ipv6_address "$addr" "$mask" "$preferred" "$valid" 1 |
| 84 | addrsig="$addrsig $addr/$mask" |
| 85 | |
| 86 | if [ -z "$RA_ADDRESSES" -a -z "$RA_ROUTES" -a \ |
| 87 | -z "$RA_DNS" -a "$FAKE_ROUTES" = 1 ]; then |
| 88 | RA_ROUTES="::/0,$SERVER,$valid,4096" |
| 89 | fi |
| 90 | |
| 91 | # RFC 7278 |
| 92 | if [ "$mask" -eq 64 -a -z "$PREFIXES" -a -n "$EXTENDPREFIX" ]; then |
| 93 | proto_add_ipv6_prefix "$addr/$mask,$preferred,$valid" |
| 94 | |
| 95 | local raroutes="" |
| 96 | for route in $RA_ROUTES; do |
| 97 | local prefix="${route%%/*}" |
| 98 | local entry="${route#*/}" |
| 99 | local pmask="${entry%%,*}" |
| 100 | entry="${entry#*,}" |
| 101 | local gw="${entry%%,*}" |
| 102 | |
| 103 | [ -z "$gw" -a "$mask" = "$pmask" ] && { |
| 104 | case "$addr" in |
| 105 | "${prefix%*::}"*) continue;; |
| 106 | esac |
| 107 | } |
| 108 | raroutes="$raroutes $route" |
| 109 | done |
| 110 | RA_ROUTES="$raroutes" |
| 111 | fi |
| 112 | done |
| 113 | |
| 114 | for entry in $RA_ROUTES; do |
| 115 | local duplicate=$NOSOURCEFILTER |
| 116 | local addr="${entry%%/*}" |
| 117 | entry="${entry#*/}" |
| 118 | local mask="${entry%%,*}" |
| 119 | entry="${entry#*,}" |
| 120 | local gw="${entry%%,*}" |
| 121 | entry="${entry#*,}" |
| 122 | local valid="${entry%%,*}" |
| 123 | entry="${entry#*,}" |
| 124 | local metric="${entry%%,*}" |
| 125 | |
| 126 | for xentry in $RA_ROUTES; do |
| 127 | local xprefix="${xentry%%,*}" |
| 128 | xentry="${xentry#*,}" |
| 129 | local xgw="${xentry%%,*}" |
| 130 | |
| 131 | [ -n "$gw" -a -z "$xgw" -a "$addr/$mask" = "$xprefix" ] && duplicate=1 |
| 132 | done |
| 133 | |
| 134 | if [ -z "$gw" -o "$duplicate" = 1 ]; then |
| 135 | proto_add_ipv6_route "$addr" "$mask" "$gw" "$metric" "$valid" |
| 136 | else |
| 137 | proto_add_ipv6_route "$addr" "$mask" "$gw" "$metric" "$valid" "::/128" |
| 138 | for prefix in $PREFIXES $ADDRESSES; do |
| 139 | local paddr="${prefix%%,*}" |
| 140 | proto_add_ipv6_route "$addr" "$mask" "$gw" "$metric" "$valid" "$paddr" |
| 141 | done |
| 142 | fi |
| 143 | done |
| 144 | |
| 145 | proto_add_data |
| 146 | [ -n "$CER" ] && json_add_string cer "$CER" |
| 147 | [ -n "$PASSTHRU" ] && json_add_string passthru "$PASSTHRU" |
| 148 | [ -n "$ZONE" ] && json_add_string zone "$ZONE" |
| 149 | proto_close_data |
| 150 | |
| 151 | proto_send_update "$INTERFACE" |
| 152 | |
| 153 | MAPTYPE="" |
| 154 | MAPRULE="" |
| 155 | |
| 156 | if [ -n "$MAPE" -a -f /lib/netifd/proto/map.sh ]; then |
| 157 | MAPTYPE="map-e" |
| 158 | MAPRULE="$MAPE" |
| 159 | elif [ -n "$MAPT" -a -f /lib/netifd/proto/map.sh -a -f /proc/net/nat46/control ]; then |
| 160 | MAPTYPE="map-t" |
| 161 | MAPRULE="$MAPT" |
| 162 | elif [ -n "$LW4O6" -a -f /lib/netifd/proto/map.sh ]; then |
| 163 | MAPTYPE="lw4o6" |
| 164 | MAPRULE="$LW4O6" |
| 165 | fi |
| 166 | |
| 167 | [ -n "$ZONE" ] || ZONE=$(fw3 -q network $INTERFACE 2>/dev/null) |
| 168 | |
| 169 | if [ "$IFACE_MAP" != 0 -a -n "$MAPTYPE" -a -n "$MAPRULE" ]; then |
| 170 | [ -z "$IFACE_MAP" -o "$IFACE_MAP" = 1 ] && IFACE_MAP=${INTERFACE}_4 |
| 171 | json_init |
| 172 | json_add_string name "$IFACE_MAP" |
| 173 | json_add_string ifname "@$INTERFACE" |
| 174 | json_add_string proto map |
| 175 | json_add_string type "$MAPTYPE" |
| 176 | json_add_string _prefsig "$prefsig" |
| 177 | [ "$MAPTYPE" = lw4o6 ] && json_add_string _addrsig "$addrsig" |
| 178 | json_add_string rule "$MAPRULE" |
| 179 | json_add_string tunlink "$INTERFACE" |
| 180 | [ -n "$ZONE_MAP" ] || ZONE_MAP=$ZONE |
| 181 | [ -n "$ZONE_MAP" ] && json_add_string zone "$ZONE_MAP" |
| 182 | [ -n "$ENCAPLIMIT_MAP" ] && json_add_string encaplimit "$ENCAPLIMIT_MAP" |
| 183 | [ -n "$IFACE_MAP_DELEGATE" ] && json_add_boolean delegate "$IFACE_MAP_DELEGATE" |
| 184 | json_close_object |
| 185 | ubus call network add_dynamic "$(json_dump)" |
| 186 | elif [ -n "$AFTR" -a "$IFACE_DSLITE" != 0 -a -f /lib/netifd/proto/dslite.sh ]; then |
| 187 | [ -z "$IFACE_DSLITE" -o "$IFACE_DSLITE" = 1 ] && IFACE_DSLITE=${INTERFACE}_4 |
| 188 | json_init |
| 189 | json_add_string name "$IFACE_DSLITE" |
| 190 | json_add_string ifname "@$INTERFACE" |
| 191 | json_add_string proto "dslite" |
| 192 | json_add_string peeraddr "$AFTR" |
| 193 | json_add_string tunlink "$INTERFACE" |
| 194 | [ -n "$ZONE_DSLITE" ] || ZONE_DSLITE=$ZONE |
| 195 | [ -n "$ZONE_DSLITE" ] && json_add_string zone "$ZONE_DSLITE" |
| 196 | [ -n "$ENCAPLIMIT_DSLITE" ] && json_add_string encaplimit "$ENCAPLIMIT_DSLITE" |
| 197 | [ -n "$IFACE_DSLITE_DELEGATE" ] && json_add_boolean delegate "$IFACE_DSLITE_DELEGATE" |
| 198 | json_close_object |
| 199 | ubus call network add_dynamic "$(json_dump)" |
| 200 | fi |
| 201 | |
| 202 | # TODO: $SNTP_IP $SIP_IP $SNTP_FQDN $SIP_DOMAIN |
| 203 | } |
| 204 | |
| 205 | teardown_interface() { |
| 206 | proto_init_update "*" 0 |
| 207 | proto_send_update "$INTERFACE" |
| 208 | } |
| 209 | |
| 210 | case "$2" in |
| 211 | bound) |
| 212 | teardown_interface "$1" |
| 213 | setup_interface "$1" |
| 214 | ;; |
| 215 | informed|updated|rebound) |
| 216 | setup_interface "$1" |
| 217 | ;; |
| 218 | ra-updated) |
| 219 | [ -n "$ADDRESSES$RA_ADDRESSES$PREFIXES$USERPREFIX" ] && setup_interface "$1" |
| 220 | ;; |
| 221 | started|stopped|unbound) |
| 222 | teardown_interface "$1" |
| 223 | ;; |
| 224 | esac |
| 225 | |
| 226 | # user rules |
| 227 | [ -f /etc/odhcp6c.user ] && . /etc/odhcp6c.user "$@" |
| 228 | for f in /etc/odhcp6c.user.d/*; do |
| 229 | [ -f "$f" ] && (. "$f" "$@") |
| 230 | done |
| 231 | |
| 232 | exit 0 |