[package] firewall: Initial alias interface support. This allows to define zones...
[openwrt.git] / package / firewall / files / lib / core_interface.sh
1 # Copyright (C) 2009-2010 OpenWrt.org
2
3 fw_configure_interface() {
4         local iface=$1
5         local action=$2
6         local ifname=$3
7         local aliasnet=$4
8
9         [ "$action" == "add" ] && {
10                 local status=$(uci_get_state network "$iface" up 0)
11                 [ "$status" == 1 ] || [ -n "$aliasnet" ] || return 0
12         }
13
14         [ -n "$ifname" ] || ifname=$(uci_get_state network "$iface" ifname "$iface")
15         [ "$ifname" == "lo" ] && return 0
16
17         fw_callback pre interface
18
19         fw__do_rules() {
20                 local action=$1
21                 local zone=$2
22                 local chain=zone_${zone}
23                 local ifname=$3
24                 local subnet=$4
25
26                 local inet onet
27                 local mode=$(fw_get_family_mode x $zone i)
28
29                 case "$mode/$subnet" in
30                         # Zone supports v6 only or dual, need v6
31                         6/*:*|i/*:*)
32                                 inet="{ -s $subnet -d ::/0 }"
33                                 onet="{ -s ::/0 -d $subnet }"
34                                 mode=6
35                         ;;
36
37                         # Zone supports v4 only or dual, need v4
38                         4/*.*.*.*|i/*.*.*.*)
39                                 inet="{ -s $subnet -d 0.0.0.0/0 }"
40                                 onet="{ -s 0.0.0.0/0 -d $subnet }"
41                                 mode=4
42                         ;;
43
44                         # Need v6 while zone is v4
45                         */*:*) fw_log info "zone $zone does not support IPv6 address family, skipping"; return ;;
46
47                         # Need v4 while zone is v6
48                         */*.*) fw_log info "zone $zone does not support IPv4 address family, skipping"; return ;;
49                 esac
50
51                 fw $action $mode f ${chain}_ACCEPT ACCEPT ^ $onet { -o "$ifname" }
52                 fw $action $mode f ${chain}_ACCEPT ACCEPT ^ $inet { -i "$ifname" }
53                 fw $action $mode f ${chain}_DROP   DROP   ^ $onet { -o "$ifname" }
54                 fw $action $mode f ${chain}_DROP   DROP   ^ $inet { -i "$ifname" }
55                 fw $action $mode f ${chain}_REJECT reject ^ $onet { -o "$ifname" }
56                 fw $action $mode f ${chain}_REJECT reject ^ $inet { -i "$ifname" }
57
58                 fw $action $mode n ${chain}_nat MASQUERADE ^ $onet { -o "$ifname" }
59                 fw $action $mode f ${chain}_MSSFIX TCPMSS  ^ $onet { -o "$ifname" -p tcp --tcp-flags SYN,RST SYN --clamp-mss-to-pmtu }
60
61                 fw $action $mode f input   ${chain}         $ $inet { -i "$ifname" }
62                 fw $action $mode f forward ${chain}_forward $ $inet { -i "$ifname" }
63                 fw $action $mode n PREROUTING ${chain}_prerouting ^ $inet { -i "$ifname" }
64                 fw $action $mode r PREROUTING ${chain}_notrack    ^ $inet { -i "$ifname" }
65         }
66
67         local old_zones old_ifname old_subnet
68         config_get old_zones core "${iface}_zone"
69         [ -n "$old_zones" ] && {
70                 config_get old_ifname core "${iface}_ifname"
71                 config_get old_subnet core "${iface}_subnet"
72
73                 local z
74                 for z in $old_zones; do
75                         fw_log info "removing $iface ($old_ifname${old_subnet:+ alias $old_subnet}) from zone $z"
76                         fw__do_rules del $z $old_ifname $old_subnet
77
78                         [ -n "$old_subnet" ] || ACTION=remove ZONE="$z" INTERFACE="$iface" DEVICE="$ifname" /sbin/hotplug-call firewall
79                 done
80
81                 local old_aliases
82                 config_get old_aliases core "${iface}_aliases"
83
84                 local a
85                 for a in $old_aliases; do
86                         fw_configure_interface "$a" del "$old_ifname"
87                 done
88
89                 uci_revert_state firewall core "${iface}_zone"
90                 uci_revert_state firewall core "${iface}_ifname"
91                 uci_revert_state firewall core "${iface}_subnet"
92                 uci_revert_state firewall core "${iface}_aliases"
93         }
94
95         [ "$action" == del ] && return
96
97         local new_zones=
98         load_zone() {
99                 fw_config_get_zone "$1"
100                 list_contains zone_network "$iface" || return
101
102                 fw_log info "adding $iface ($ifname${aliasnet:+ alias $aliasnet}) to zone $zone_name"
103                 fw__do_rules add ${zone_name} "$ifname" $aliasnet
104                 append new_zones $zone_name
105
106                 [ -n "$aliasnet" ] || ACTION=add ZONE="$zone_name" INTERFACE="$iface" DEVICE="$ifname" /sbin/hotplug-call firewall
107         }
108         config_foreach load_zone zone
109
110         [ -z "$aliasnet" ] && {
111                 local aliases
112                 config_get aliases "$iface" aliases
113
114                 local a
115                 for a in $aliases; do
116                         local ipaddr netmask ip6addr
117                         config_get ipaddr "$a" ipaddr
118                         config_get netmask "$a" netmask
119                         config_get ip6addr "$a" ip6addr
120
121                         [ -n "$ipaddr" ] && fw_configure_interface "$a" add "$ifname" "$ipaddr${netmask:+/$netmask}"
122                         [ -n "$ip6addr" ] && fw_configure_interface "$a" add "$ifname" "$ip6addr"
123                 done
124
125                 fw_sysctl_interface $ifname
126                 fw_callback post interface
127
128                 uci_set_state firewall core "${iface}_aliases" "$aliases"
129         }
130
131         uci_set_state firewall core "${iface}_zone" "$new_zones"
132         uci_set_state firewall core "${iface}_ifname" "$ifname"
133         uci_set_state firewall core "${iface}_subnet" "$aliasnet"
134 }
135
136 fw_sysctl_interface() {
137         local ifname=$1
138         {
139                 sysctl -w net.ipv4.conf.${ifname}.accept_redirects=$FW_ACCEPT_REDIRECTS
140                 sysctl -w net.ipv6.conf.${ifname}.accept_redirects=$FW_ACCEPT_REDIRECTS
141                 sysctl -w net.ipv4.conf.${ifname}.accept_source_route=$FW_ACCEPT_SRC_ROUTE
142                 sysctl -w net.ipv6.conf.${ifname}.accept_source_route=$FW_ACCEPT_SRC_ROUTE
143         } >/dev/null 2>/dev/null
144 }
145