d4f4bf004fe7b90cea4106d6aa5f5d651f9c434d
[feed/packages.git] / net / mwan3 / files / etc / hotplug.d / iface / 15-mwan3
1 #!/bin/sh
2
3 mwan3_get_iface_id()
4 {
5 let iface_count++
6 [ "$1" == "$INTERFACE" ] && iface_id=$iface_count
7 }
8
9 mwan3_set_general_iptables()
10 {
11 if ! $IPT -S mwan3_ifaces &> /dev/null; then
12 $IPT -N mwan3_ifaces
13 fi
14
15 if ! $IPT -S mwan3_rules &> /dev/null; then
16 $IPT -N mwan3_rules
17 fi
18
19 if ! $IPT -S mwan3_connected &> /dev/null; then
20 $IPT -N mwan3_connected
21 fi
22
23 if ! $IPT -S mwan3_hook &> /dev/null; then
24 $IPT -N mwan3_hook
25 $IPT -A mwan3_hook -j CONNMARK --restore-mark --nfmask 0xff00 --ctmask 0xff00
26 $IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_ifaces
27 $IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_connected
28 $IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_rules
29 $IPT -A mwan3_hook -j CONNMARK --save-mark --nfmask 0xff00 --ctmask 0xff00
30 $IPT -A mwan3_hook -m mark ! --mark 0xff00/0xff00 -j mwan3_connected
31 fi
32
33 if ! $IPT -S mwan3_output_hook &> /dev/null; then
34 $IPT -N mwan3_output_hook
35 fi
36
37 if ! $IPT -S PREROUTING | grep mwan3_hook &> /dev/null; then
38 $IPT -A PREROUTING -j mwan3_hook
39 fi
40
41 if ! $IPT -S OUTPUT | grep mwan3_hook &> /dev/null; then
42 $IPT -A OUTPUT -j mwan3_hook
43 fi
44
45 if ! $IPT -S OUTPUT | grep mwan3_output_hook &> /dev/null; then
46 $IPT -A OUTPUT -j mwan3_output_hook
47 fi
48
49 $IPT -F mwan3_rules
50 }
51
52 mwan3_set_general_rules()
53 {
54 if [ -z "$($IP rule list | awk '$1 == "2253:"')" ]; then
55 $IP rule add pref 2253 fwmark 0xfd00/0xff00 blackhole
56 fi
57
58 if [ -z "$($IP rule list | awk '$1 == "2254:"')" ]; then
59 $IP rule add pref 2254 fwmark 0xfe00/0xff00 unreachable
60 fi
61 }
62
63 mwan3_set_connected_iptables()
64 {
65 local connected_networks
66
67 if $IPT -S mwan3_connected &> /dev/null; then
68 $IPT -F mwan3_connected
69
70 for connected_networks in $($IP route | awk '{print $1}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do
71 $IPT -A mwan3_connected -d $connected_networks -j MARK --set-xmark 0xff00/0xff00
72 done
73
74 for connected_networks in $($IP route list table 0 | awk '{print $2}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do
75 $IPT -A mwan3_connected -d $connected_networks -j MARK --set-xmark 0xff00/0xff00
76 done
77
78 $IPT -I mwan3_connected -d 224.0.0.0/3 -j MARK --set-xmark 0xff00/0xff00
79 $IPT -I mwan3_connected -d 127.0.0.0/8 -j MARK --set-xmark 0xff00/0xff00
80 fi
81 }
82
83 mwan3_set_iface_iptables()
84 {
85 local local_net local_nets
86
87 if ! $IPT -S mwan3_iface_$INTERFACE &> /dev/null; then
88 $IPT -N mwan3_iface_$INTERFACE
89 fi
90
91 $IPT -F mwan3_iface_$INTERFACE
92 $IPT -D mwan3_ifaces -m mark --mark 0x0/0xff00 -j mwan3_iface_$INTERFACE &> /dev/null
93
94 if [ $ACTION == "ifup" ]; then
95 local_nets=$($IP route list dev $DEVICE scope link | awk '{print $1}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}')
96
97 if [ -n "$local_nets" ]; then
98 for local_net in $local_nets ; do
99 if [ $ACTION == "ifup" ]; then
100 $IPT -I mwan3_iface_$INTERFACE -i $DEVICE -s $local_net -m mark --mark 0x0/0xff00 -m comment --comment "default" -j MARK --set-xmark 0xff00/0xff00
101 fi
102 done
103 fi
104
105 $IPT -A mwan3_iface_$INTERFACE -i $DEVICE -m mark --mark 0x0/0xff00 -m comment --comment "$INTERFACE" -j MARK --set-xmark $(($iface_id*256))/0xff00
106 $IPT -A mwan3_ifaces -m mark --mark 0x0/0xff00 -j mwan3_iface_$INTERFACE
107 fi
108
109 if [ $ACTION == "ifdown" ]; then
110 $IPT -X mwan3_iface_$INTERFACE
111 fi
112 }
113
114 mwan3_set_iface_route()
115 {
116 $IP route flush table $iface_id
117 [ $ACTION == "ifup" ] && $IP route add table $iface_id default $route_args
118 }
119
120 mwan3_set_iface_rules()
121 {
122 while [ -n "$($IP rule list | awk '$1 == "'$(($iface_id+1000)):'"')" ]; do
123 $IP rule del pref $(($iface_id+1000))
124 done
125
126 while [ -n "$($IP rule list | awk '$1 == "'$(($iface_id+2000)):'"')" ]; do
127 $IP rule del pref $(($iface_id+2000))
128 done
129
130 [ $ACTION == "ifup" ] && $IP rule add pref $(($iface_id+1000)) iif $DEVICE lookup main
131 [ $ACTION == "ifup" ] && $IP rule add pref $(($iface_id+2000)) fwmark $(($iface_id*256))/0xff00 lookup $iface_id
132 }
133
134 mwan3_track()
135 {
136 local track_ip track_ips reliability count timeout interval down up
137
138 mwan3_list_track_ips()
139 {
140 track_ips="$1 $track_ips"
141 }
142 config_list_foreach $INTERFACE track_ip mwan3_list_track_ips
143
144 if [ -e /var/run/mwan3track-$INTERFACE.pid ] ; then
145 kill $(cat /var/run/mwan3track-$INTERFACE.pid) &> /dev/null
146 rm /var/run/mwan3track-$INTERFACE.pid &> /dev/null
147 fi
148
149 if [ -n "$track_ips" ]; then
150 config_get reliability $INTERFACE reliability 1
151 config_get count $INTERFACE count 1
152 config_get timeout $INTERFACE timeout 4
153 config_get interval $INTERFACE interval 10
154 config_get down $INTERFACE down 5
155 config_get up $INTERFACE up 5
156
157 if ! $IPT -S mwan3_track_$INTERFACE &> /dev/null; then
158 $IPT -N mwan3_track_$INTERFACE
159 $IPT -A mwan3_output_hook -p icmp -m icmp --icmp-type 8 -m length --length 32 -j mwan3_track_$INTERFACE
160 fi
161
162 $IPT -F mwan3_track_$INTERFACE
163
164 for track_ip in $track_ips; do
165 $IPT -A mwan3_track_$INTERFACE -d $track_ip -j MARK --set-xmark 0xff00/0xff00
166 done
167
168 [ -x /usr/sbin/mwan3track ] && /usr/sbin/mwan3track $INTERFACE $DEVICE $reliability $count $timeout $interval $down $up $track_ips &
169 else
170 $IPT -D mwan3_output_hook -p icmp -m icmp --icmp-type 8 -m length --length 32 -j mwan3_track_$INTERFACE &> /dev/null
171 $IPT -F mwan3_track_$INTERFACE &> /dev/null
172 $IPT -X mwan3_track_$INTERFACE &> /dev/null
173 fi
174 }
175
176 mwan3_set_policy()
177 {
178 local iface_count iface_id INTERFACE metric probability weight
179
180 config_get INTERFACE $1 interface
181 config_get metric $1 metric 1
182 config_get weight $1 weight 1
183
184 [ -n "$INTERFACE" ] || return 0
185
186 config_foreach mwan3_get_iface_id interface
187
188 [ -n "$iface_id" ] || return 0
189
190 if $IPT -S mwan3_iface_$INTERFACE &> /dev/null; then
191 if [ "$metric" -lt "$lowest_metric" ]; then
192
193 total_weight=$weight
194 $IPT -F mwan3_policy_$policy
195 $IPT -A mwan3_policy_$policy -m mark --mark 0x0/0xff00 -m comment --comment "$INTERFACE $weight $weight" -j MARK --set-xmark $(($iface_id*256))/0xff00
196
197 lowest_metric=$metric
198
199 elif [ "$metric" -eq "$lowest_metric" ]; then
200
201 total_weight=$(($total_weight+$weight))
202 probability=$(($weight*1000/$total_weight))
203
204 if [ "$probability" -lt 10 ]; then
205 probability="0.00$probability"
206 elif [ $probability -lt 100 ]; then
207 probability="0.0$probability"
208 elif [ $probability -lt 1000 ]; then
209 probability="0.$probability"
210 else
211 probability="1"
212 fi
213
214 probability="-m statistic --mode random --probability $probability"
215
216 $IPT -I mwan3_policy_$policy -m mark --mark 0x0/0xff00 $probability -m comment --comment "$INTERFACE $weight $total_weight" -j MARK --set-xmark $(($iface_id*256))/0xff00
217 fi
218 fi
219 }
220
221 mwan3_set_policies_iptables()
222 {
223 local last_resort lowest_metric policy total_weight
224
225 policy=$1
226
227 config_get last_resort $1 last_resort unreachable
228
229 if [ "$policy" != $(echo "$policy" | cut -c1-15) ]; then
230 $LOG warn "Policy $policy exceeds max of 15 chars. Not setting policy" && return 0
231 fi
232
233 if ! $IPT -S mwan3_policy_$policy &> /dev/null; then
234 $IPT -N mwan3_policy_$policy
235 fi
236
237 $IPT -F mwan3_policy_$policy
238
239 case "$last_resort" in
240 blackhole)
241 $IPT -A mwan3_policy_$policy -m mark --mark 0x0/0xff00 -m comment --comment "blackhole" -j MARK --set-xmark 0xfd00/0xff00
242 ;;
243 default)
244 $IPT -A mwan3_policy_$policy -m mark --mark 0x0/0xff00 -m comment --comment "default" -j MARK --set-xmark 0xff00/0xff00
245 ;;
246 *)
247 $IPT -A mwan3_policy_$policy -m mark --mark 0x0/0xff00 -m comment --comment "unreachable" -j MARK --set-xmark 0xfe00/0xff00
248 ;;
249 esac
250
251 lowest_metric=256
252 total_weight=0
253
254 config_list_foreach $policy use_member mwan3_set_policy
255 }
256
257 mwan3_set_user_rules_iptables()
258 {
259 local proto src_ip src_port dest_ip dest_port use_policy
260
261 config_get proto $1 proto all
262 config_get src_ip $1 src_ip 0.0.0.0/0
263 config_get src_port $1 src_port 0:65535
264 config_get dest_ip $1 dest_ip 0.0.0.0/0
265 config_get dest_port $1 dest_port 0:65535
266 config_get use_policy $1 use_policy
267
268 if [ -n "$use_policy" ]; then
269 if [ "$use_policy" == "default" ]; then
270 use_policy="MARK --set-xmark 0xff00/0xff00"
271 elif [ "$use_policy" == "unreachable" ]; then
272 use_policy="MARK --set-xmark 0xfe00/0xff00"
273 elif [ "$use_policy" == "blackhole" ]; then
274 use_policy="MARK --set-xmark 0xfd00/0xff00"
275 else
276 use_policy="mwan3_policy_$use_policy"
277 fi
278
279 case $proto in
280 tcp|udp)
281 $IPT -A mwan3_rules -p $proto -s $src_ip -d $dest_ip -m multiport --sports $src_port -m multiport --dports $dest_port -m mark --mark 0/0xff00 -m comment --comment "$1" -j $use_policy &> /dev/null
282 ;;
283 *)
284 $IPT -A mwan3_rules -p $proto -s $src_ip -d $dest_ip -m mark --mark 0/0xff00 -m comment --comment "$1" -j $use_policy &> /dev/null
285 ;;
286 esac
287 fi
288 }
289
290 mwan3_ifupdown()
291 {
292 local counter enabled iface_count iface_id route_args wan_metric
293
294 config_load mwan3
295 config_foreach mwan3_get_iface_id interface
296
297 [ -n "$iface_id" ] || return 0
298 [ "$iface_count" -le 250 ] || return 0
299 unset iface_count
300
301 config_get enabled $INTERFACE enabled 0
302
303 counter=0
304
305 if [ $ACTION == "ifup" ]; then
306 [ "$enabled" -eq 1 ] || return 0
307
308 while [ -z "$($IP route list dev $DEVICE default | head -1)" -a "$counter" -lt 10 ]; do
309 sleep 1
310 let counter++
311 if [ "$counter" -ge 10 ]; then
312 $LOG warn "Could not find gateway for interface $INTERFACE ($DEVICE)" && return 0
313 fi
314 done
315
316 route_args=$($IP route list dev $DEVICE default | head -1 | sed '/.*via \([^ ]*\) .*$/!d;s//via \1/;q' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}')
317 route_args="nexthop $route_args dev $DEVICE"
318 fi
319
320 while [ "$(pgrep -f -o hotplug-call)" -ne $$ -a "$counter" -lt 60 ]; do
321 sleep 1
322 let counter++
323 if [ "$counter" -ge 60 ]; then
324 $LOG warn "Timeout waiting for older hotplug processes to finish. $ACTION interface $INTERFACE (${DEVICE:-unknown}) aborted" && return 0
325 fi
326 done
327
328 $LOG notice "$ACTION interface $INTERFACE (${DEVICE:-unknown})"
329
330 mwan3_set_general_iptables
331 mwan3_set_general_rules
332 mwan3_set_iface_iptables
333 mwan3_set_iface_route
334 mwan3_set_iface_rules
335
336 [ $ACTION == "ifup" ] && mwan3_track
337
338 config_foreach mwan3_set_policies_iptables policy
339 config_foreach mwan3_set_user_rules_iptables rule
340 }
341
342 [ -n "$ACTION" ] || exit 0
343 [ -n "$INTERFACE" ] || exit 0
344
345 if [ $ACTION == "ifup" ]; then
346 [ -n "$DEVICE" ] || exit 0
347 fi
348
349 local IP IPT LOG
350
351 IP="/usr/sbin/ip -4"
352 IPT="/usr/sbin/iptables -t mangle -w"
353 LOG="/usr/bin/logger -t mwan3 -p"
354
355 case "$ACTION" in
356 ifup|ifdown)
357 mwan3_ifupdown
358 mwan3_set_connected_iptables
359 ;;
360 esac
361
362 exit 0