| 1 | #!/bin/sh |
| 2 | # 6to4.sh - IPv6-in-IPv4 tunnel backend |
| 3 | # Copyright (c) 2010-2012 OpenWrt.org |
| 4 | |
| 5 | [ -n "$INCLUDE_ONLY" ] || { |
| 6 | . /lib/functions.sh |
| 7 | . /lib/functions/network.sh |
| 8 | . ../netifd-proto.sh |
| 9 | init_proto "$@" |
| 10 | } |
| 11 | |
| 12 | find_6to4_prefix() { |
| 13 | local ip4="$1" |
| 14 | local oIFS="$IFS"; IFS="."; set -- $ip4; IFS="$oIFS" |
| 15 | |
| 16 | printf "2002:%02x%02x:%02x%02x\n" $1 $2 $3 $4 |
| 17 | } |
| 18 | |
| 19 | test_6to4_rfc1918() |
| 20 | { |
| 21 | local oIFS="$IFS"; IFS="."; set -- $1; IFS="$oIFS" |
| 22 | [ $1 -eq 10 ] && return 0 |
| 23 | [ $1 -eq 192 ] && [ $2 -eq 168 ] && return 0 |
| 24 | [ $1 -eq 172 ] && [ $2 -ge 16 ] && [ $2 -le 31 ] && return 0 |
| 25 | |
| 26 | # RFC 6598 |
| 27 | [ $1 -eq 100 ] && [ $2 -ge 64 ] && [ $2 -le 127 ] && return 0 |
| 28 | |
| 29 | return 1 |
| 30 | } |
| 31 | |
| 32 | set_6to4_radvd_interface() { |
| 33 | local cfgid="$1" |
| 34 | local lanif="${2:-lan}" |
| 35 | local ifmtu="${3:-1280}" |
| 36 | local ifsection="" |
| 37 | |
| 38 | find_ifsection() { |
| 39 | local net |
| 40 | local cfg="$1" |
| 41 | config_get net "$cfg" interface |
| 42 | |
| 43 | [ "$net" = "$lanif" ] && { |
| 44 | ifsection="$cfg" |
| 45 | return 1 |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | config_foreach find_ifsection interface |
| 50 | |
| 51 | [ -z "$ifsection" ] && { |
| 52 | ifsection="iface_$sid" |
| 53 | uci_set_state radvd "$ifsection" "" interface |
| 54 | uci_set_state radvd "$ifsection" interface "$lanif" |
| 55 | } |
| 56 | |
| 57 | uci_set_state radvd "$ifsection" ignore 0 |
| 58 | uci_set_state radvd "$ifsection" IgnoreIfMissing 1 |
| 59 | uci_set_state radvd "$ifsection" AdvSendAdvert 1 |
| 60 | uci_set_state radvd "$ifsection" MaxRtrAdvInterval 30 |
| 61 | uci_set_state radvd "$ifsection" AdvLinkMTU "$ifmtu" |
| 62 | } |
| 63 | |
| 64 | set_6to4_radvd_prefix() { |
| 65 | local cfgid="$1" |
| 66 | local lanif="${2:-lan}" |
| 67 | local wanif="${3:-wan}" |
| 68 | local prefix="${4:-0:0:0:1::/64}" |
| 69 | local vlt="${5:-300}" |
| 70 | local plt="${6:-120}" |
| 71 | local pfxsection="" |
| 72 | |
| 73 | find_pfxsection() { |
| 74 | local net base |
| 75 | local cfg="$1" |
| 76 | config_get net "$cfg" interface |
| 77 | config_get base "$cfg" Base6to4Interface |
| 78 | |
| 79 | [ "$net" = "$lanif" ] && [ "$base" = "$wanif" ] && { |
| 80 | pfxsection="$cfg" |
| 81 | return 1 |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | config_foreach find_pfxsection prefix |
| 86 | |
| 87 | [ -z "$pfxsection" ] && { |
| 88 | pfxsection="prefix_${sid}_${lanif}" |
| 89 | uci_set_state radvd "$pfxsection" "" prefix |
| 90 | uci_set_state radvd "$pfxsection" ignore 0 |
| 91 | uci_set_state radvd "$pfxsection" interface "$lanif" |
| 92 | uci_set_state radvd "$pfxsection" prefix "$prefix" |
| 93 | uci_set_state radvd "$pfxsection" AdvOnLink 1 |
| 94 | uci_set_state radvd "$pfxsection" AdvAutonomous 1 |
| 95 | uci_set_state radvd "$pfxsection" AdvValidLifetime "$vlt" |
| 96 | uci_set_state radvd "$pfxsection" AdvPreferredLifetime "$plt" |
| 97 | uci_set_state radvd "$pfxsection" Base6to4Interface "$wanif" |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | proto_6to4_setup() { |
| 102 | local cfg="$1" |
| 103 | local iface="$2" |
| 104 | local link="6to4-$cfg" |
| 105 | |
| 106 | local mtu ttl ipaddr adv_subnet adv_interface adv_valid_lifetime adv_preferred_lifetime |
| 107 | json_get_vars mtu ttl ipaddr adv_subnet adv_interface adv_valid_lifetime adv_preferred_lifetime |
| 108 | |
| 109 | ( proto_add_host_dependency "$cfg" 0.0.0.0 ) |
| 110 | |
| 111 | local wanif |
| 112 | if ! network_find_wan wanif; then |
| 113 | proto_notify_error "$cfg" "NO_WAN_LINK" |
| 114 | return |
| 115 | fi |
| 116 | |
| 117 | [ -z "$ipaddr" ] && { |
| 118 | if ! network_get_ipaddr ipaddr "$wanif"; then |
| 119 | proto_notify_error "$cfg" "NO_WAN_ADDRESS" |
| 120 | return |
| 121 | fi |
| 122 | } |
| 123 | |
| 124 | test_6to4_rfc1918 "$ipaddr" && { |
| 125 | proto_notify_error "$cfg" "INVALID_LOCAL_ADDRESS" |
| 126 | return |
| 127 | } |
| 128 | |
| 129 | # find our local prefix |
| 130 | local prefix6=$(find_6to4_prefix "$ipaddr") |
| 131 | local local6="$prefix6::1" |
| 132 | |
| 133 | proto_init_update "$link" 1 |
| 134 | proto_add_ipv6_address "$local6" 16 |
| 135 | proto_add_ipv6_route "::" 0 "::192.88.99.1" |
| 136 | |
| 137 | proto_add_tunnel |
| 138 | json_add_string mode sit |
| 139 | json_add_int mtu "${mtu:-1280}" |
| 140 | json_add_int ttl "${ttl:-64}" |
| 141 | json_add_string local "$ipaddr" |
| 142 | proto_close_tunnel |
| 143 | |
| 144 | proto_send_update "$cfg" |
| 145 | |
| 146 | [ -f /etc/config/radvd ] && /etc/init.d/radvd enabled && { |
| 147 | local sid="6to4_$cfg" |
| 148 | |
| 149 | uci_revert_state radvd |
| 150 | config_load radvd |
| 151 | |
| 152 | adv_subnet=$((0x${adv_subnet:-1})) |
| 153 | |
| 154 | local adv_subnets="" |
| 155 | |
| 156 | for adv_interface in ${adv_interface:-lan}; do |
| 157 | local adv_ifname |
| 158 | network_get_device adv_ifname "${adv_interface:-lan}" || continue |
| 159 | |
| 160 | local subnet6="$(printf "%s:%x::1/64" "$prefix6" $adv_subnet)" |
| 161 | |
| 162 | logger -t "$link" " * Advertising IPv6 subnet $subnet6 on ${adv_interface:-lan} ($adv_ifname)" |
| 163 | ip -6 addr add $subnet6 dev $adv_ifname |
| 164 | |
| 165 | set_6to4_radvd_interface "$sid" "$adv_interface" "$mtu" |
| 166 | set_6to4_radvd_prefix "$sid" "$adv_interface" \ |
| 167 | "$wanif" "$(printf "0:0:0:%x::/64" $adv_subnet)" \ |
| 168 | "$adv_valid_lifetime" "$adv_preferred_lifetime" |
| 169 | |
| 170 | adv_subnets="${adv_subnets:+$adv_subnets }$adv_ifname:$subnet6" |
| 171 | adv_subnet=$(($adv_subnet + 1)) |
| 172 | done |
| 173 | |
| 174 | uci_set_state network "$cfg" adv_subnets "$adv_subnets" |
| 175 | |
| 176 | /etc/init.d/radvd restart |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | proto_6to4_teardown() { |
| 181 | local cfg="$1" |
| 182 | local link="6to4-$cfg" |
| 183 | |
| 184 | local adv_subnets=$(uci_get_state network "$cfg" adv_subnets) |
| 185 | |
| 186 | grep -qs "^ *$link:" /proc/net/dev && { |
| 187 | [ -n "$adv_subnets" ] && { |
| 188 | uci_revert_state radvd |
| 189 | /etc/init.d/radvd enabled && /etc/init.d/radvd restart |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | proto_6to4_init_config() { |
| 195 | no_device=1 |
| 196 | available=1 |
| 197 | |
| 198 | proto_config_add_string "ipaddr" |
| 199 | proto_config_add_int "mtu" |
| 200 | proto_config_add_int "ttl" |
| 201 | proto_config_add_string "adv_interface" |
| 202 | proto_config_add_string "adv_subnet" |
| 203 | proto_config_add_int "adv_valid_lifetime" |
| 204 | proto_config_add_int "adv_preferred_lifetime" |
| 205 | } |
| 206 | |
| 207 | [ -n "$INCLUDE_ONLY" ] || { |
| 208 | add_protocol 6to4 |
| 209 | } |
| 210 | |