OpenWrt – Diff between revs 2 and 3
?pathlinks?
Rev 2 | Rev 3 | |||
---|---|---|---|---|
1 | #!/bin/sh |
1 | #!/bin/sh |
|
2 | # map.sh - IPv4-in-IPv6 tunnel backend |
2 | # map.sh - IPv4-in-IPv6 tunnel backend |
|
3 | # |
3 | # |
|
4 | # Author: Steven Barth <cyrus@openwrt.org> |
4 | # Author: Steven Barth <cyrus@openwrt.org> |
|
5 | # Copyright (c) 2014 cisco Systems, Inc. |
5 | # Copyright (c) 2014 cisco Systems, Inc. |
|
6 | # |
6 | # |
|
7 | # This program is free software; you can redistribute it and/or modify |
7 | # This program is free software; you can redistribute it and/or modify |
|
8 | # it under the terms of the GNU General Public License version 2 |
8 | # it under the terms of the GNU General Public License version 2 |
|
9 | # as published by the Free Software Foundation |
9 | # as published by the Free Software Foundation |
|
10 | # |
10 | # |
|
11 | # This program is distributed in the hope that it will be useful, |
11 | # This program is distributed in the hope that it will be useful, |
|
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 | # GNU General Public License for more details. |
14 | # GNU General Public License for more details. |
|
15 | |
15 | |
|
16 | [ -n "$INCLUDE_ONLY" ] || { |
16 | [ -n "$INCLUDE_ONLY" ] || { |
|
17 | . /lib/functions.sh |
17 | . /lib/functions.sh |
|
18 | . /lib/functions/network.sh |
18 | . /lib/functions/network.sh |
|
19 | . ../netifd-proto.sh |
19 | . ../netifd-proto.sh |
|
20 | init_proto "$@" |
20 | init_proto "$@" |
|
21 | } |
21 | } |
|
22 | |
22 | |
|
23 | proto_map_setup() { |
23 | proto_map_setup() { |
|
24 | local cfg="$1" |
24 | local cfg="$1" |
|
25 | local iface="$2" |
25 | local iface="$2" |
|
26 | local link="map-$cfg" |
26 | local link="map-$cfg" |
|
27 | |
27 | |
|
28 | # uncomment for legacy MAP0 mode |
28 | # uncomment for legacy MAP0 mode |
|
29 | #export LEGACY=1 |
29 | #export LEGACY=1 |
|
30 | |
30 | |
|
31 | local type mtu ttl tunlink zone encaplimit |
31 | local type mtu ttl tunlink zone encaplimit |
|
32 | local rule ipaddr ip4prefixlen ip6prefix ip6prefixlen peeraddr ealen psidlen psid offset |
32 | local rule ipaddr ip4prefixlen ip6prefix ip6prefixlen peeraddr ealen psidlen psid offset |
|
33 | json_get_vars type mtu ttl tunlink zone encaplimit |
33 | json_get_vars type mtu ttl tunlink zone encaplimit |
|
34 | json_get_vars rule ipaddr ip4prefixlen ip6prefix ip6prefixlen peeraddr ealen psidlen psid offset |
34 | json_get_vars rule ipaddr ip4prefixlen ip6prefix ip6prefixlen peeraddr ealen psidlen psid offset |
|
35 | |
35 | |
|
36 | [ -z "$zone" ] && zone="wan" |
36 | [ -z "$zone" ] && zone="wan" |
|
37 | [ -z "$type" ] && type="map-e" |
37 | [ -z "$type" ] && type="map-e" |
|
38 | [ -z "$ip4prefixlen" ] && ip4prefixlen=32 |
38 | [ -z "$ip4prefixlen" ] && ip4prefixlen=32 |
|
39 | |
39 | |
|
40 | ( proto_add_host_dependency "$cfg" "::" "$tunlink" ) |
40 | ( proto_add_host_dependency "$cfg" "::" "$tunlink" ) |
|
41 | |
41 | |
|
42 | # fixme: handle RA/DHCPv6 address race for LW |
42 | # fixme: handle RA/DHCPv6 address race for LW |
|
43 | [ "$type" = lw4o6 ] && sleep 5 |
43 | [ "$type" = lw4o6 ] && sleep 5 |
|
44 | |
44 | |
|
45 | if [ -z "$rule" ]; then |
45 | if [ -z "$rule" ]; then |
|
46 | rule="type=$type,ipv6prefix=$ip6prefix,prefix6len=$ip6prefixlen,ipv4prefix=$ipaddr,prefix4len=$ip4prefixlen" |
46 | rule="type=$type,ipv6prefix=$ip6prefix,prefix6len=$ip6prefixlen,ipv4prefix=$ipaddr,prefix4len=$ip4prefixlen" |
|
47 | [ -n "$psid" ] && rule="$rule,psid=$psid" |
47 | [ -n "$psid" ] && rule="$rule,psid=$psid" |
|
48 | [ -n "$psidlen" ] && rule="$rule,psidlen=$psidlen" |
48 | [ -n "$psidlen" ] && rule="$rule,psidlen=$psidlen" |
|
49 | [ -n "$offset" ] && rule="$rule,offset=$offset" |
49 | [ -n "$offset" ] && rule="$rule,offset=$offset" |
|
50 | [ -n "$ealen" ] && rule="$rule,ealen=$ealen" |
50 | [ -n "$ealen" ] && rule="$rule,ealen=$ealen" |
|
51 | if [ "$type" = "map-t" ]; then |
51 | if [ "$type" = "map-t" ]; then |
|
52 | rule="$rule,dmr=$peeraddr" |
52 | rule="$rule,dmr=$peeraddr" |
|
53 | else |
53 | else |
|
54 | rule="$rule,br=$peeraddr" |
54 | rule="$rule,br=$peeraddr" |
|
55 | fi |
55 | fi |
|
56 | fi |
56 | fi |
|
57 | |
57 | |
|
58 | echo "rule=$rule" > /tmp/map-$cfg.rules |
58 | echo "rule=$rule" > /tmp/map-$cfg.rules |
|
59 | RULE_DATA=$(mapcalc ${tunlink:-\*} $rule) |
59 | RULE_DATA=$(mapcalc ${tunlink:-\*} $rule) |
|
60 | if [ "$?" != 0 ]; then |
60 | if [ "$?" != 0 ]; then |
|
61 | proto_notify_error "$cfg" "INVALID_MAP_RULE" |
61 | proto_notify_error "$cfg" "INVALID_MAP_RULE" |
|
62 | proto_block_restart "$cfg" |
62 | proto_block_restart "$cfg" |
|
63 | return |
63 | return |
|
64 | fi |
64 | fi |
|
65 | |
65 | |
|
66 | echo "$RULE_DATA" >> /tmp/map-$cfg.rules |
66 | echo "$RULE_DATA" >> /tmp/map-$cfg.rules |
|
67 | eval $RULE_DATA |
67 | eval $RULE_DATA |
|
68 | |
68 | |
|
69 | if [ -z "$RULE_BMR" ]; then |
69 | if [ -z "$RULE_BMR" ]; then |
|
70 | proto_notify_error "$cfg" "NO_MATCHING_PD" |
70 | proto_notify_error "$cfg" "NO_MATCHING_PD" |
|
71 | proto_block_restart "$cfg" |
71 | proto_block_restart "$cfg" |
|
72 | return |
72 | return |
|
73 | fi |
73 | fi |
|
74 | |
74 | |
|
75 | k=$RULE_BMR |
75 | k=$RULE_BMR |
|
76 | if [ "$type" = "lw4o6" -o "$type" = "map-e" ]; then |
76 | if [ "$type" = "lw4o6" -o "$type" = "map-e" ]; then |
|
77 | proto_init_update "$link" 1 |
77 | proto_init_update "$link" 1 |
|
78 | proto_add_ipv4_address $(eval "echo \$RULE_${k}_IPV4ADDR") "" "" "" |
78 | proto_add_ipv4_address $(eval "echo \$RULE_${k}_IPV4ADDR") "" "" "" |
|
79 | |
79 | |
|
80 | proto_add_tunnel |
80 | proto_add_tunnel |
|
81 | json_add_string mode ipip6 |
81 | json_add_string mode ipip6 |
|
82 | json_add_int mtu "${mtu:-1280}" |
82 | json_add_int mtu "${mtu:-1280}" |
|
83 | json_add_int ttl "${ttl:-64}" |
83 | json_add_int ttl "${ttl:-64}" |
|
84 | json_add_string local $(eval "echo \$RULE_${k}_IPV6ADDR") |
84 | json_add_string local $(eval "echo \$RULE_${k}_IPV6ADDR") |
|
85 | json_add_string remote $(eval "echo \$RULE_${k}_BR") |
85 | json_add_string remote $(eval "echo \$RULE_${k}_BR") |
|
86 | json_add_string link $(eval "echo \$RULE_${k}_PD6IFACE") |
86 | json_add_string link $(eval "echo \$RULE_${k}_PD6IFACE") |
|
87 | json_add_object "data" |
87 | json_add_object "data" |
|
88 | [ -n "$encaplimit" ] && json_add_string encaplimit "$encaplimit" |
88 | json_add_string encaplimit "${encaplimit:-4}" |
|
89 | if [ "$type" = "map-e" ]; then |
89 | if [ "$type" = "map-e" ]; then |
|
90 | json_add_array "fmrs" |
90 | json_add_array "fmrs" |
|
91 | for i in $(seq $RULE_COUNT); do |
91 | for i in $(seq $RULE_COUNT); do |
|
92 | [ "$(eval "echo \$RULE_${i}_FMR")" != 1 ] && continue |
92 | [ "$(eval "echo \$RULE_${i}_FMR")" != 1 ] && continue |
|
93 | json_add_object "" |
93 | json_add_object "" |
|
94 | json_add_string prefix6 "$(eval "echo \$RULE_${i}_IPV6PREFIX")/$(eval "echo \$RULE_${i}_PREFIX6LEN")" |
94 | json_add_string prefix6 "$(eval "echo \$RULE_${i}_IPV6PREFIX")/$(eval "echo \$RULE_${i}_PREFIX6LEN")" |
|
95 | json_add_string prefix4 "$(eval "echo \$RULE_${i}_IPV4PREFIX")/$(eval "echo \$RULE_${i}_PREFIX4LEN")" |
95 | json_add_string prefix4 "$(eval "echo \$RULE_${i}_IPV4PREFIX")/$(eval "echo \$RULE_${i}_PREFIX4LEN")" |
|
96 | json_add_int ealen $(eval "echo \$RULE_${i}_EALEN") |
96 | json_add_int ealen $(eval "echo \$RULE_${i}_EALEN") |
|
97 | json_add_int offset $(eval "echo \$RULE_${i}_OFFSET") |
97 | json_add_int offset $(eval "echo \$RULE_${i}_OFFSET") |
|
98 | json_close_object |
98 | json_close_object |
|
99 | done |
99 | done |
|
100 | json_close_array |
100 | json_close_array |
|
101 | fi |
101 | fi |
|
102 | json_close_object |
102 | json_close_object |
|
103 | |
103 | |
|
104 | |
104 | |
|
105 | proto_close_tunnel |
105 | proto_close_tunnel |
|
106 | elif [ "$type" = "map-t" -a -f "/proc/net/nat46/control" ]; then |
106 | elif [ "$type" = "map-t" -a -f "/proc/net/nat46/control" ]; then |
|
107 | proto_init_update "$link" 1 |
107 | proto_init_update "$link" 1 |
|
108 | local style="MAP" |
108 | local style="MAP" |
|
109 | [ "$LEGACY" = 1 ] && style="MAP0" |
109 | [ "$LEGACY" = 1 ] && style="MAP0" |
|
110 | |
110 | |
|
111 | echo add $link > /proc/net/nat46/control |
111 | echo add $link > /proc/net/nat46/control |
|
112 | local cfgstr="local.style $style local.v4 $(eval "echo \$RULE_${k}_IPV4PREFIX")/$(eval "echo \$RULE_${k}_PREFIX4LEN")" |
112 | local cfgstr="local.style $style local.v4 $(eval "echo \$RULE_${k}_IPV4PREFIX")/$(eval "echo \$RULE_${k}_PREFIX4LEN")" |
|
113 | cfgstr="$cfgstr local.v6 $(eval "echo \$RULE_${k}_IPV6PREFIX")/$(eval "echo \$RULE_${k}_PREFIX6LEN")" |
113 | cfgstr="$cfgstr local.v6 $(eval "echo \$RULE_${k}_IPV6PREFIX")/$(eval "echo \$RULE_${k}_PREFIX6LEN")" |
|
114 | cfgstr="$cfgstr local.ea-len $(eval "echo \$RULE_${k}_EALEN") local.psid-offset $(eval "echo \$RULE_${k}_OFFSET")" |
114 | cfgstr="$cfgstr local.ea-len $(eval "echo \$RULE_${k}_EALEN") local.psid-offset $(eval "echo \$RULE_${k}_OFFSET")" |
|
115 | cfgstr="$cfgstr remote.v4 0.0.0.0/0 remote.v6 $(eval "echo \$RULE_${k}_DMR") remote.style RFC6052 remote.ea-len 0 remote.psid-offset 0" |
115 | cfgstr="$cfgstr remote.v4 0.0.0.0/0 remote.v6 $(eval "echo \$RULE_${k}_DMR") remote.style RFC6052 remote.ea-len 0 remote.psid-offset 0" |
|
116 | echo config $link $cfgstr > /proc/net/nat46/control |
116 | echo config $link $cfgstr > /proc/net/nat46/control |
|
117 | |
117 | |
|
118 | for i in $(seq $RULE_COUNT); do |
118 | for i in $(seq $RULE_COUNT); do |
|
119 | [ "$(eval "echo \$RULE_${i}_FMR")" != 1 ] && continue |
119 | [ "$(eval "echo \$RULE_${i}_FMR")" != 1 ] && continue |
|
120 | local cfgstr="remote.style $style remote.v4 $(eval "echo \$RULE_${i}_IPV4PREFIX")/$(eval "echo \$RULE_${i}_PREFIX4LEN")" |
120 | local cfgstr="remote.style $style remote.v4 $(eval "echo \$RULE_${i}_IPV4PREFIX")/$(eval "echo \$RULE_${i}_PREFIX4LEN")" |
|
121 | cfgstr="$cfgstr remote.v6 $(eval "echo \$RULE_${i}_IPV6PREFIX")/$(eval "echo \$RULE_${i}_PREFIX6LEN")" |
121 | cfgstr="$cfgstr remote.v6 $(eval "echo \$RULE_${i}_IPV6PREFIX")/$(eval "echo \$RULE_${i}_PREFIX6LEN")" |
|
122 | cfgstr="$cfgstr remote.ea-len $(eval "echo \$RULE_${i}_EALEN") remote.psid-offset $(eval "echo \$RULE_${i}_OFFSET")" |
122 | cfgstr="$cfgstr remote.ea-len $(eval "echo \$RULE_${i}_EALEN") remote.psid-offset $(eval "echo \$RULE_${i}_OFFSET")" |
|
123 | echo insert $link $cfgstr > /proc/net/nat46/control |
123 | echo insert $link $cfgstr > /proc/net/nat46/control |
|
124 | done |
124 | done |
|
125 | else |
125 | else |
|
126 | proto_notify_error "$cfg" "UNSUPPORTED_TYPE" |
126 | proto_notify_error "$cfg" "UNSUPPORTED_TYPE" |
|
127 | proto_block_restart "$cfg" |
127 | proto_block_restart "$cfg" |
|
128 | fi |
128 | fi |
|
129 | |
129 | |
|
130 | proto_add_ipv4_route "0.0.0.0" 0 |
130 | proto_add_ipv4_route "0.0.0.0" 0 |
|
131 | proto_add_data |
131 | proto_add_data |
|
132 | [ "$zone" != "-" ] && json_add_string zone "$zone" |
132 | [ "$zone" != "-" ] && json_add_string zone "$zone" |
|
133 | |
133 | |
|
134 | json_add_array firewall |
134 | json_add_array firewall |
|
135 | if [ -z "$(eval "echo \$RULE_${k}_PORTSETS")" ]; then |
135 | if [ -z "$(eval "echo \$RULE_${k}_PORTSETS")" ]; then |
|
136 | json_add_object "" |
136 | json_add_object "" |
|
137 | json_add_string type nat |
137 | json_add_string type nat |
|
138 | json_add_string target SNAT |
138 | json_add_string target SNAT |
|
139 | json_add_string family inet |
139 | json_add_string family inet |
|
140 | json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR") |
140 | json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR") |
|
141 | json_close_object |
141 | json_close_object |
|
142 | else |
142 | else |
|
143 | for portset in $(eval "echo \$RULE_${k}_PORTSETS"); do |
143 | for portset in $(eval "echo \$RULE_${k}_PORTSETS"); do |
|
144 | for proto in icmp tcp udp; do |
144 | for proto in icmp tcp udp; do |
|
145 | json_add_object "" |
145 | json_add_object "" |
|
146 | json_add_string type nat |
146 | json_add_string type nat |
|
147 | json_add_string target SNAT |
147 | json_add_string target SNAT |
|
148 | json_add_string family inet |
148 | json_add_string family inet |
|
149 | json_add_string proto "$proto" |
149 | json_add_string proto "$proto" |
|
150 | json_add_boolean connlimit_ports 1 |
150 | json_add_boolean connlimit_ports 1 |
|
151 | json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR") |
151 | json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR") |
|
152 | json_add_string snat_port "$portset" |
152 | json_add_string snat_port "$portset" |
|
153 | json_close_object |
153 | json_close_object |
|
154 | done |
154 | done |
|
155 | done |
155 | done |
|
156 | fi |
156 | fi |
|
157 | if [ "$type" = "map-t" ]; then |
157 | if [ "$type" = "map-t" ]; then |
|
158 | json_add_object "" |
158 | json_add_object "" |
|
159 | json_add_string type rule |
159 | json_add_string type rule |
|
160 | json_add_string family inet6 |
160 | json_add_string family inet6 |
|
161 | json_add_string proto all |
161 | json_add_string proto all |
|
162 | json_add_string direction in |
162 | json_add_string direction in |
|
163 | json_add_string dest "$zone" |
163 | json_add_string dest "$zone" |
|
164 | json_add_string src "$zone" |
164 | json_add_string src "$zone" |
|
165 | json_add_string src_ip $(eval "echo \$RULE_${k}_IPV6ADDR") |
165 | json_add_string src_ip $(eval "echo \$RULE_${k}_IPV6ADDR") |
|
166 | json_add_string target ACCEPT |
166 | json_add_string target ACCEPT |
|
167 | json_close_object |
167 | json_close_object |
|
168 | json_add_object "" |
168 | json_add_object "" |
|
169 | json_add_string type rule |
169 | json_add_string type rule |
|
170 | json_add_string family inet6 |
170 | json_add_string family inet6 |
|
171 | json_add_string proto all |
171 | json_add_string proto all |
|
172 | json_add_string direction out |
172 | json_add_string direction out |
|
173 | json_add_string dest "$zone" |
173 | json_add_string dest "$zone" |
|
174 | json_add_string src "$zone" |
174 | json_add_string src "$zone" |
|
175 | json_add_string dest_ip $(eval "echo \$RULE_${k}_IPV6ADDR") |
175 | json_add_string dest_ip $(eval "echo \$RULE_${k}_IPV6ADDR") |
|
176 | json_add_string target ACCEPT |
176 | json_add_string target ACCEPT |
|
177 | json_close_object |
177 | json_close_object |
|
178 | proto_add_ipv6_route $(eval "echo \$RULE_${k}_IPV6ADDR") 128 |
178 | proto_add_ipv6_route $(eval "echo \$RULE_${k}_IPV6ADDR") 128 |
|
179 | fi |
179 | fi |
|
180 | json_close_array |
180 | json_close_array |
|
181 | proto_close_data |
181 | proto_close_data |
|
182 | |
182 | |
|
183 | proto_send_update "$cfg" |
183 | proto_send_update "$cfg" |
|
184 | |
184 | |
|
185 | if [ "$type" = "lw4o6" -o "$type" = "map-e" ]; then |
185 | if [ "$type" = "lw4o6" -o "$type" = "map-e" ]; then |
|
186 | json_init |
186 | json_init |
|
187 | json_add_string name "${cfg}_" |
187 | json_add_string name "${cfg}_" |
|
188 | json_add_string ifname "@$(eval "echo \$RULE_${k}_PD6IFACE")" |
188 | json_add_string ifname "@$(eval "echo \$RULE_${k}_PD6IFACE")" |
|
189 | json_add_string proto "static" |
189 | json_add_string proto "static" |
|
190 | json_add_array ip6addr |
190 | json_add_array ip6addr |
|
191 | json_add_string "" "$(eval "echo \$RULE_${k}_IPV6ADDR")" |
191 | json_add_string "" "$(eval "echo \$RULE_${k}_IPV6ADDR")" |
|
192 | json_close_array |
192 | json_close_array |
|
193 | json_close_object |
193 | json_close_object |
|
194 | ubus call network add_dynamic "$(json_dump)" |
194 | ubus call network add_dynamic "$(json_dump)" |
|
195 | fi |
195 | fi |
|
196 | } |
196 | } |
|
197 | |
197 | |
|
198 | proto_map_teardown() { |
198 | proto_map_teardown() { |
|
199 | local cfg="$1" |
199 | local cfg="$1" |
|
200 | local link="map-$cfg" |
200 | local link="map-$cfg" |
|
201 | |
201 | |
|
202 | json_get_var type type |
202 | json_get_var type type |
|
203 | |
203 | |
|
204 | [ -z "$type" ] && type="map-e" |
204 | [ -z "$type" ] && type="map-e" |
|
205 | |
205 | |
|
206 | case "$type" in |
206 | case "$type" in |
|
207 | "map-e"|"lw4o6") ifdown "${cfg}_" ;; |
207 | "map-e"|"lw4o6") ifdown "${cfg}_" ;; |
|
208 | "map-t") [ -f "/proc/net/nat46/control" ] && echo del $link > /proc/net/nat46/control ;; |
208 | "map-t") [ -f "/proc/net/nat46/control" ] && echo del $link > /proc/net/nat46/control ;; |
|
209 | esac |
209 | esac |
|
210 | |
210 | |
|
211 | rm -f /tmp/map-$cfg.rules |
211 | rm -f /tmp/map-$cfg.rules |
|
212 | } |
212 | } |
|
213 | |
213 | |
|
214 | proto_map_init_config() { |
214 | proto_map_init_config() { |
|
215 | no_device=1 |
215 | no_device=1 |
|
216 | available=1 |
216 | available=1 |
|
217 | |
217 | |
|
218 | proto_config_add_string "rule" |
218 | proto_config_add_string "rule" |
|
219 | proto_config_add_string "ipaddr" |
219 | proto_config_add_string "ipaddr" |
|
220 | proto_config_add_int "ip4prefixlen" |
220 | proto_config_add_int "ip4prefixlen" |
|
221 | proto_config_add_string "ip6prefix" |
221 | proto_config_add_string "ip6prefix" |
|
222 | proto_config_add_int "ip6prefixlen" |
222 | proto_config_add_int "ip6prefixlen" |
|
223 | proto_config_add_string "peeraddr" |
223 | proto_config_add_string "peeraddr" |
|
224 | proto_config_add_int "ealen" |
224 | proto_config_add_int "ealen" |
|
225 | proto_config_add_int "psidlen" |
225 | proto_config_add_int "psidlen" |
|
226 | proto_config_add_int "psid" |
226 | proto_config_add_int "psid" |
|
227 | proto_config_add_int "offset" |
227 | proto_config_add_int "offset" |
|
228 | |
228 | |
|
229 | proto_config_add_string "tunlink" |
229 | proto_config_add_string "tunlink" |
|
230 | proto_config_add_int "mtu" |
230 | proto_config_add_int "mtu" |
|
231 | proto_config_add_int "ttl" |
231 | proto_config_add_int "ttl" |
|
232 | proto_config_add_string "zone" |
232 | proto_config_add_string "zone" |
|
233 | proto_config_add_string "encaplimit" |
233 | proto_config_add_string "encaplimit" |
|
234 | } |
234 | } |
|
235 | |
235 | |
|
236 | [ -n "$INCLUDE_ONLY" ] || { |
236 | [ -n "$INCLUDE_ONLY" ] || { |
|
237 | add_protocol map |
237 | add_protocol map |
|
238 | } |
238 | } |
|
239 | |
239 | |