]> git.ipfire.org Git - people/ms/network.git/blob - src/functions/functions.ip-tunnel
ip-tunnel: Set TTL to 255 by default
[people/ms/network.git] / src / functions / functions.ip-tunnel
1 #!/bin/bash
2 ###############################################################################
3 # #
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2012-2013 IPFire Network Development Team #
6 # #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
11 # #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
16 # #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 # #
20 ###############################################################################
21
22 IP_TUNNEL_MODES="gre gretap sit vti"
23
24 ip_tunnel_protocol_to_name() {
25 local protocol="${1}"
26
27 case "${protocol}" in
28 gre)
29 print "Generic Routing Encapsulation"
30 ;;
31 sit)
32 print "Simple Internet Transition"
33 ;;
34 vti)
35 print "Virtual Tunnel Interface"
36 ;;
37 *)
38 print "${protocol}"
39 ;;
40 esac
41 }
42
43 # This function converts our modes into the type
44 # the iproute2 tool uses
45 ip_tunnel_convert_mode_to_iproute2_mode() {
46 local mode=${1}
47 local protocol=${2}
48
49 if ! isset mode || ! isset protocol; then
50 log ERROR "Did not get mode and/or protocol"
51 return ${EXIT_ERROR}
52 fi
53
54 if [[ "${protocol}" = "ipv4" ]]; then
55 # When we use IPv4 we can use our modes
56 echo "${mode}"
57 fi
58
59 if [[ "${protocol}" = "ipv6" ]]; then
60 # When we use IPv6 we have to convert
61 case "${mode}" in
62 "vti")
63 echo "vti6"
64 ;;
65 "gre")
66 echo "ip6gre"
67 ;;
68 "gretap")
69 echo "ip6gretap"
70 ;;
71 esac
72 fi
73 }
74
75 ip_tunnel_add() {
76 local device="${1}"
77 shift
78
79 local mode
80 local ttl=255
81
82 local address
83 local remote_address
84 local local_address
85
86 local ikey
87 local okey
88
89 while [ $# -gt 0 ]; do
90 case "${1}" in
91 --address=*)
92 address="$(cli_get_val "${1}")"
93
94 # Validate input
95 if ! isset address || ! mac_is_valid "${address}"; then
96 error "Invalid MAC address: ${address}"
97 return ${EXIT_ERROR}
98 fi
99 ;;
100 --mode=*)
101 mode="$(cli_get_val "${1}")"
102 ;;
103 --ttl=*)
104 ttl="$(cli_get_val "${1}")"
105 ;;
106 --remote-address=*)
107 remote_address="$(cli_get_val "${1}")"
108 ;;
109 --local-address=*)
110 local_address="$(cli_get_val "${1}")"
111 ;;
112
113 # Keys for VTI
114 --ikey=*)
115 ikey="$(cli_get_val "${1}")"
116 ;;
117 --okey=*)
118 okey="$(cli_get_val "${1}")"
119 ;;
120 esac
121 shift
122 done
123
124 if ! isset mode; then
125 error "--mode= is not set. Must be one of ${IP_TUNNEL_MODES}"
126 return ${EXIT_ERROR}
127 fi
128
129 if ! isoneof mode ${IP_TUNNEL_MODES}; then
130 error "Invalid mode: ${mode}"
131 return ${EXIT_ERROR}
132 fi
133
134 # We cannot mix IPv6 and IPv4
135 if isset local_address && ! ip_protocol_match "${remote_address}" "${local_address}"; then
136 log ERROR "Local and remote address are not of the same IP protocol"
137 return ${EXIT_ERROR}
138 fi
139
140 # ikey and okey must be set for VTI devices
141 if [ "${mode}" = "vti" ] && (! isset ikey || ! isset okey); then
142 error "--ikey= and --okey= must be set for VTI device"
143 return ${EXIT_ERROR}
144 fi
145
146 # Custom checks for certain modes
147 case "${mode}" in
148 gretap)
149 # Generate a random MAC address if none was passed
150 if ! isset address; then
151 address="$(mac_generate)"
152 fi
153 ;;
154 esac
155
156 # If TTL is set, make sure it is an integer.
157 if isset ttl && ! isinteger ttl; then
158 error "TTL must be an integer: ${ttl}"
159 return ${EXIT_ERROR}
160 fi
161
162 # Determine the mode based on the IP protocol
163 local remote_address_protocol="$(ip_detect_protocol "${remote_address}")"
164 mode=$(ip_tunnel_convert_mode_to_iproute2_mode "${mode}" "${remote_address_protocol}")
165
166 local cmd_args=( name "${device}" )
167
168 if isset address; then
169 cmd_args=( "${cmd_args[@]}" "address" "${address}" )
170 fi
171
172 # Mode
173 cmd_args=( "${cmd_args[@]}" "type" "${mode}" )
174
175 # Apply TTL if a value has been set.
176 if isset ttl; then
177 cmd_args=( "${cmd_args[@]}" "ttl" "${ttl}" )
178 fi
179
180 # Apply local address if a value has been set.
181 if isset local_address; then
182 cmd_args=( "${cmd_args[@]}" "local" "${local_address}" )
183 fi
184
185 # Apply remote address if a value has been set.
186 if isset remote_address; then
187 cmd_args=( "${cmd_args[@]}" "remote" "${remote_address}" )
188 fi
189
190 # Add ikey and okey for VTI devices
191 if [ "${mode}" = "vti" ]; then
192 cmd_args=( "${cmd_args[@]}" "ikey" "${ikey}" "okey" "${okey}" )
193 fi
194
195 log DEBUG "Creating tunnel device '${device}' (mode=${mode})..."
196
197 # Create the device.
198 if ! cmd ip link add "${cmd_args[@]}"; then
199 error "Could not create tunnel device ${device}"
200 return ${EXIT_ERROR}
201 fi
202
203 # Disable policy lookups for VTI devices
204 if [ "${mode}" = "vti" ]; then
205 sysctl_set "net.ipv4.conf.${device}.disable_policy" "1"
206 fi
207
208 return ${EXIT_OK}
209 }
210
211 ip_tunnel_del() {
212 device_delete "$@"
213 }
214
215 ip_tunnel_change() {
216 local device="${1}"
217 shift
218
219 if ! device_exists "${device}"; then
220 log ERROR "No such device: ${device}"
221 return ${EXIT_ERROR}
222 fi
223
224 # Determine the device type
225 local type="$(device_tunnel_get_type ${device})"
226
227 local local
228 local remote
229
230 while [ $# -gt 0 ]; do
231 case "${1}" in
232 --local=*)
233 local="$(cli_get_val "${1}")"
234
235 if ! ip_is_valid "${local}"; then
236 error "Invalid IP address for --local: ${local}"
237 return ${EXIT_ERROR}
238 fi
239
240 if ! isoneof "type" gre gre6 vti vti6; then
241 log ERROR "Cannot change --local for devices of type ${type}"
242 return ${EXIT_ERROR}
243 fi
244 ;;
245 --remote=*)
246 remote="$(cli_get_val "${1}")"
247
248 if ! ip_is_valid "${remote}"; then
249 error "Invalid IP address for --remote: ${remote}"
250 return ${EXIT_ERROR}
251 fi
252
253 if ! isoneof "type" gre gre6 vti vti6; then
254 log ERROR "Cannot change --remote for devices of type ${type}"
255 return ${EXIT_ERROR}
256 fi
257 ;;
258 esac
259 shift
260 done
261
262 # XXX If a device is of an IP protocol and the protocol of remote and local
263 # have changed, we will need to destroy the interface and recreate it with
264 # the correct type
265
266 local cmd_args
267
268 if isset local; then
269 cmd_args="${cmd_args} local ${local}"
270 fi
271
272 if isset remote; then
273 cmd_args="${cmd_args} remote ${remote}"
274 fi
275
276 # Exit if there is nothing to do
277 if ! isset cmd_args; then
278 return ${EXIT_OK}
279 fi
280
281 # Run ip command
282 cmd ip link change dev "${device}" type "${type}" ${cmd_args}
283 }