]> git.ipfire.org Git - thirdparty/strongswan.git/blob - programs/manual/manual.in
- import of strongswan-2.7.0
[thirdparty/strongswan.git] / programs / manual / manual.in
1 #! /bin/sh
2 # user interface to manual keying
3 # Copyright (C) 1998, 1999 Henry Spencer.
4 #
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2 of the License, or (at your
8 # option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 # for more details.
14 #
15 # RCSID $Id: manual.in,v 1.1 2004/03/15 20:35:28 as Exp $
16
17 me='ipsec manual'
18 usage="Usage:
19 $me [--showonly] --{up|down|route|unroute} name
20 $me [--showonly] --{up|down|route|unroute} --union partname ...
21
22 other options: [--config ipsecconfigfile] [--other] [--show]
23 [--iam ipaddress@interface]"
24
25 # make sure outputs of (e.g.) ifconfig are in English
26 unset LANG LANGUAGE LC_ALL LC_MESSAGES
27
28 showonly=
29 config=
30 info=/var/run/ipsec.info
31 shopts=
32 other=0
33 union=0
34 noinclude=
35 interfs=
36 op=
37
38 for dummy
39 do
40 case "$1" in
41 --help) echo "$usage" ; exit 0 ;;
42 --version) echo "$me $IPSEC_VERSION" ; exit 0 ;;
43 --show) shopts=-x ;;
44 --showonly) showonly=yes ;;
45 --other) other=1 ;;
46 --union) union=1 ;;
47 --config) config="--config $2" ; shift ;;
48 --noinclude) noinclude=--noinclude ;;
49 --iam) interfs="$2" ; shift ;;
50 --up|--down|--route|--unroute)
51 if test " $op" != " "
52 then
53 echo "$usage" >&2
54 exit 2
55 fi
56 op="$1"
57 ;;
58 --) shift ; break ;;
59 -*) echo "$me: unknown option \`$1'" >&2 ; exit 2 ;;
60 *) break ;;
61 esac
62 shift
63 done
64
65 case "$op$#:$union" in
66 [01]:*) echo "$usage" >&2 ; exit 2 ;;
67 2:0) echo "$me: warning: obsolete command syntax used" >&2
68 op="--$2"
69 names="$1"
70 ;;
71 [0-9]*:1) ;;
72 --*) if test $# -eq 0
73 then
74 echo "$usage" >&2
75 exit 2
76 fi
77 names="$*"
78 ;;
79 *) echo "$usage" >&2 ; exit 2 ;;
80 esac
81 if test " $op" = " "
82 then
83 # --union obsolete-syntax case, op is last argument
84 echo "$me: warning: obsolete command syntax used" >&2
85 names=
86 prev=
87 for arg
88 do
89 names="$names $prev"
90 prev="$arg"
91 done
92 op="--$prev"
93 fi
94 case "$op" in
95 --up|--down|--route|--unroute) ;;
96 *) echo "$usage" >&2 ; exit 2 ;;
97 esac
98
99 case "$interfs" in
100 '') interfs="`ifconfig |
101 awk ' /^ipsec/ { interf = $1 ; next }
102 /^[^ \t]/ { interf = "" ; next }
103 /^[ \t]*inet addr/ {
104 sub(/:/, " ", $0)
105 if (interf != "")
106 print $3 "@" interf
107 }' | tr '\n' ' '`"
108 ;;
109 esac
110
111 if test -s $info
112 then
113 . $info
114 fi
115
116 ipsec _confread $config $noinclude $names |
117 awk ' BEGIN {
118 FS = "\t"
119 myname = "'"$me"'"
120 err = "cat >&2"
121 op = "'"$op"'"
122 other = '"$other"'
123 names = "'"$names"'"
124 interfs = "'"$interfs"'"
125 ni = split(interfs, terfs, " ")
126 if (ni == 0)
127 fail("no IPsec-enabled interfaces found")
128 for (i = 1; i <= ni; i++) {
129 nc = split(terfs[i], cpts, "@")
130 if (nc != 2)
131 fail("internal error on " terfs[i])
132 interface[cpts[1]] = cpts[2]
133 }
134 draddr = "'"$defaultrouteaddr"'"
135 drnexthop = "'"$defaultroutenexthop"'"
136 s[""] = ""
137 nlspi = 0
138 nrspi = 0
139 failed = 0
140 maskbits[0] = "0.0.0.0"
141 maskbits[1] = "128.0.0.0"
142 maskbits[2] = "192.0.0.0"
143 maskbits[3] = "224.0.0.0"
144 maskbits[4] = "240.0.0.0"
145 maskbits[5] = "248.0.0.0"
146 maskbits[6] = "252.0.0.0"
147 maskbits[7] = "254.0.0.0"
148 maskbits[8] = "255.0.0.0"
149 maskbits[9] = "255.128.0.0"
150 maskbits[10] = "255.192.0.0"
151 maskbits[11] = "255.224.0.0"
152 maskbits[12] = "255.240.0.0"
153 maskbits[13] = "255.248.0.0"
154 maskbits[14] = "255.252.0.0"
155 maskbits[15] = "255.254.0.0"
156 maskbits[16] = "255.255.0.0"
157 maskbits[17] = "255.255.128.0"
158 maskbits[18] = "255.255.192.0"
159 maskbits[19] = "255.255.224.0"
160 maskbits[20] = "255.255.240.0"
161 maskbits[21] = "255.255.248.0"
162 maskbits[22] = "255.255.252.0"
163 maskbits[23] = "255.255.254.0"
164 maskbits[24] = "255.255.255.0"
165 maskbits[25] = "255.255.255.128"
166 maskbits[26] = "255.255.255.192"
167 maskbits[27] = "255.255.255.224"
168 maskbits[28] = "255.255.255.240"
169 maskbits[29] = "255.255.255.248"
170 maskbits[30] = "255.255.255.252"
171 maskbits[31] = "255.255.255.254"
172 maskbits[32] = "255.255.255.255"
173 }
174 $1 == "=" {
175 next
176 }
177 $1 == "!" {
178 if ($2 != "")
179 fail($2)
180 next
181 }
182 $1 != ":" {
183 fail("internal error, unknown type code \"" $1 "\"")
184 }
185 { s[$2] = $3 }
186 function q(s) {
187 return "\"" s "\""
188 }
189 function fail(m) {
190 print myname ": fatal error in " q(names) ": " m |err
191 failed = 1
192 exit
193 }
194 function swap(k, t, l, r) {
195 l = "left" k
196 r = "right" k
197 if ((l in s) && (r in s)) {
198 t = s[l]
199 s[l] = s[r]
200 s[r] = t
201 } else if (l in s) { # but not r
202 s[r] = s[l]
203 delete s[l]
204 } else if (r in s) { # but not l
205 s[l] = s[r]
206 delete s[r]
207 }
208 }
209 function yesno(k) {
210 if ((k in s) && s[k] != "yes" && s[k] != "no")
211 fail("parameter \"" k "\" must be \"yes\" or \"no\"")
212 }
213 function default(k, v) {
214 if (!(k in s))
215 s[k] = v
216 }
217 function need(k) {
218 if (!(k in s))
219 fail("connection has no \"" k "\" parameter specified")
220 if (s[k] == "")
221 fail("parameter \"" k "\" value must be non-empty")
222 }
223 function integer(k) {
224 if (!(k in s))
225 return
226 if (s[k] !~ /^[0-9]+$/)
227 fail("parameter \"" k "\" value must be integer")
228 }
229 function nexthopset(dir, val, k) {
230 k = dir "nexthop"
231 if (k in s)
232 fail("non-default value of " k " is being overridden")
233 if (val != "")
234 s[k] = val
235 else if (k in s)
236 delete s[k]
237 }
238 function leftward( t) {
239 nlspi++
240 if ("spi" in s)
241 return s["spi"]
242 t = spibase spil
243 spil += 2
244 return t
245 }
246 function rightward( t) {
247 nrspi++
248 if ("spi" in s)
249 return s["spi"]
250 t = spibase spir
251 spir += 2
252 return t
253 }
254 function netfix(dir, n, t) {
255 n = s[dir "subnet"]
256 if (n == "%default")
257 n = "0.0.0.0/0"
258 if (n !~ /\//)
259 fail(dir "subnet=" n " has no mask specified")
260 t = split(n, netfixarray, "/")
261 if (t != 2)
262 fail("bad syntax in " dir "subnet=" n)
263 s[dir "net"] = netfixarray[1]
264 s[dir "mask"] = mask(netfixarray[2])
265 }
266 function mask(m) {
267 if (m ~ /\./)
268 return m
269 if (!(m in maskbits))
270 fail("unknown mask syntax \"" m "\"")
271 return maskbits[m]
272 }
273 function bidir(name, l, r) {
274 l = "left" name
275 r = "right" name
276 if (!(l in s) && (name in s))
277 s[l] = s[name]
278 if (!(r in s) && (name in s))
279 s[r] = s[name]
280 if ((l in s) != (r in s))
281 fail("must give both or neither \"" l "\" and \"" \
282 r "\"")
283 }
284 function espspi(src, dest, spi, dir) {
285 if (!("esp" in s))
286 return
287 dir = (dest == me) ? "left" : "right"
288 print "ipsec spi --label", q(names), "--af inet",
289 "--said", ("esp" spi "@" dest), "\\"
290 print "\t--esp", s["esp"], "--src", src, "\\"
291 if ((dir "espauthkey") in s)
292 print "\t--authkey", s[dir "espauthkey"], "\\"
293 if ("espreplay_window" in s)
294 print "\t--replay_window", s["espreplay_window"], "\\"
295 if ((dir "espenckey") in s)
296 print "\t--enckey", s[dir "espenckey"], "&&"
297 else
298 print "\t&&"
299 }
300 function ahspi(src, dest, spi, dir) {
301 if (!("ah" in s))
302 return
303 dir = (dest == me) ? "left" : "right"
304 if (!((dir "ahkey") in s))
305 fail("AH specified but no ahkey= given")
306 print "ipsec spi --label", q(names), "--af inet",
307 "--said", ("ah" spi "@" dest), "\\"
308 print "\t--ah", s["ah"], "--src", src, "\\"
309 if ("ahreplay_window" in s)
310 print "\t--replay_window", s["ahreplay_window"], "\\"
311 print "\t--authkey", s[dir "ahkey"], "&&"
312 }
313 # issue a suitable invocation of updown command
314 function updown(verb, suffix, cmd) {
315 if ("leftupdown" in s) {
316 cmd = s["leftupdown"]
317 if (s["leftfirewall"] == "yes")
318 fail("cannot specify both updown and firewall")
319 } else {
320 cmd = "ipsec _updown"
321 if (s["leftfirewall"] == "yes")
322 cmd = cmd " ipfwadm"
323 }
324 print "PLUTO_VERB=" verb verbsuf " " cmd " " suffix
325 }
326 END {
327 #########
328 if (failed)
329 exit 1
330 default("type", "tunnel")
331 type = s["type"]
332 shunt = 0
333 if (type == "transport") {
334 if ("leftsubnet" in s)
335 fail("type=transport incompatible with leftsubnet")
336 if ("rightsubnet" in s)
337 fail("type=transport incompatible with rightsubnet")
338 } else if (type == "passthrough") {
339 shunt = 1;
340 p = "%pass"
341 } else if (type == "drop" || type == "reject") {
342 shunt = 1;
343 p = "%" type
344 } else if (type != "tunnel")
345 fail("only know how to do types tunnel/transport/passthrough")
346 if (shunt) {
347 if (("ah" in s) || ("esp" in s))
348 fail(type " connection may not specify AH or ESP")
349 } else {
350 if (!("ah" in s) && !("esp" in s))
351 fail("neither AH nor ESP specified for connection")
352 }
353
354 need("left")
355 need("right")
356 if (s["left"] == "%defaultroute") {
357 if (s["right"] == "%defaultroute")
358 fail("left and right cannot both be %defaultroute")
359 if (draddr == "")
360 fail("%defaultroute requested but not known")
361 s["left"] = draddr
362 nexthopset("left", drnexthop)
363 } else if (s["right"] == "%defaultroute") {
364 if (draddr == "")
365 fail("%defaultroute requested but not known")
366 s["right"] = draddr
367 nexthopset("right", drnexthop)
368 }
369
370 leftsub = ("leftsubnet" in s) ? 1 : 0
371 default("leftsubnet", s["left"] "/32")
372 rightsub = ("rightsubnet" in s) ? 1 : 0
373 default("rightsubnet", s["right"] "/32")
374 default("leftfirewall", "no")
375 default("rightfirewall", "no")
376 yesno("leftfirewall")
377 yesno("rightfirewall")
378 integer("espreplay_window")
379 if (("espreplay_window" in s) && s["espreplay_window"] == 0)
380 delete s["espreplay_window"]
381 integer("ahreplay_window")
382 if (("ahreplay_window" in s) && s["ahreplay_window"] == 0)
383 delete s["ahreplay_window"]
384 netfix("left")
385 netfix("right")
386
387 default("leftnexthop", s["right"])
388 default("rightnexthop", s["left"])
389 if (s["leftnexthop"] == s["left"])
390 fail("left and leftnexthop must not be the same")
391 if (s["rightnexthop"] == s["right"])
392 fail("right and rightnexthop must not be the same")
393
394 bidir("espenckey")
395 bidir("espauthkey")
396 bidir("ahkey")
397 if ("spi" in s && "spibase" in s)
398 fail("cannot specify both spi and spibase")
399 if (!shunt) {
400 if ("spibase" in s) {
401 b = s["spibase"]
402 if (b !~ /^0x[0-9a-fA-F]+0$/)
403 fail("bad syntax in spibase -- must be 0x...0")
404 spibase = substr(b, 1, length(b)-1)
405 } else {
406 need("spi")
407 if (s["spi"] !~ /^0x[0-9a-fA-F]+$/)
408 fail("bad syntax in spi -- must be 0x...")
409 }
410 }
411 spir = 0
412 spil = 1
413
414 # who am I?
415 me = ""
416 for (addr in interface) {
417 if (addr == s["left"] || addr == s["right"]) {
418 if (me != "")
419 fail("ambiguous: could be on \"" iface \
420 "\" or \"" interface[addr] "\"")
421 me = addr
422 iface = interface[addr]
423 }
424 }
425 if (me == "")
426 fail("cannot find interface for " s["left"] " or " s["right"])
427 if (other) {
428 if (s["left"] == me)
429 me = s["right"]
430 else if (s["right"] == me)
431 me = s["left"]
432 }
433 havesubnet = leftsubnet
434 if (s["right"] == me) {
435 swap("") # swaps "left" and "right"
436 swap("subnet")
437 swap("nexthop")
438 swap("net")
439 swap("mask")
440 swap("firewall")
441 swap("espspi")
442 swap("ahspi")
443 swap("espenckey")
444 swap("espauthkey")
445 swap("ahkey")
446 swap("updown")
447 t = spil
448 spil = spir
449 spir = t
450 havesubnet = rightsubnet
451 }
452 him = s["right"]
453
454 if (s["leftnexthop"] == "%defaultroute") {
455 if (drnexthop == "")
456 fail("%defaultroute requested but not known")
457 s["leftnexthop"] = drnexthop
458 }
459
460 tspi = rightward()
461 if (type == "tunnel") {
462 espi = rightward()
463 intspi = leftward()
464 } else
465 espi = tspi
466 if (s["rightespspi"] != "")
467 espi = s["rightespspi"]
468 respi = leftward()
469 if (s["leftespspi"] != "")
470 respi = s["leftespspi"]
471 if ("ah" in s) {
472 if ("esp" in s) {
473 aspi = rightward()
474 raspi = leftward()
475 } else {
476 aspi = espi
477 raspi = respi
478 }
479 if (s["rightahspi"] != "")
480 aspi = s["rightahspi"]
481 if (s["leftahspi"] != "")
482 raspi = s["leftahspi"]
483 }
484 routeid = "-net " s["rightnet"] " netmask " s["rightmask"]
485 if (s["rightmask"] == "255.255.255.255")
486 routeid = "-host " s["rightnet"]
487
488 print "PATH=\"'"$PATH"'\""
489 print "export PATH"
490 print "PLUTO_VERSION=1.1"
491 verbsuf = (havesubnet) ? "-client" : "-host"
492 print "PLUTO_CONNECTION=" q(names)
493 print "PLUTO_NEXT_HOP=" s["leftnexthop"]
494 print "PLUTO_INTERFACE=" iface
495 print "PLUTO_ME=" me
496 print "PLUTO_MY_CLIENT=" s["leftsubnet"]
497 print "PLUTO_MY_CLIENT_NET=" s["leftnet"]
498 print "PLUTO_MY_CLIENT_MASK=" s["leftmask"]
499 print "PLUTO_PEER=" him
500 print "PLUTO_PEER_CLIENT=" s["rightsubnet"]
501 print "PLUTO_PEER_CLIENT_NET=" s["rightnet"]
502 print "PLUTO_PEER_CLIENT_MASK=" s["rightmask"]
503 print "export PLUTO_VERSION PLUTO_CONNECTION PLUTO_NEXT_HOP"
504 print "export PLUTO_INTERFACE PLUTO_ME PLUTO_MY_CLIENT"
505 print "export PLUTO_MY_CLIENT_NET PLUTO_MY_CLIENT_MASK PLUTO_PEER"
506 print "export PLUTO_PEER_CLIENT PLUTO_PEER_CLIENT_NET"
507 print "export PLUTO_PEER_CLIENT_MASK"
508
509 if (op == "--up") {
510 print "{"
511 # first, the outbound SAs
512 if (type == "tunnel") {
513 print "ipsec spi --label", q(names), "--af inet",
514 "--said", ("tun" tspi "@" him), "\\"
515 print "\t--ip4", "--src", me, "--dst", him, "&&"
516 }
517 espspi(me, him, espi)
518 ahspi(me, him, aspi)
519 if (nrspi > 1) {
520 # group them
521 printf "ipsec spigrp --label %s --said ", q(names)
522 if (type == "tunnel")
523 printf "tun%s@%s ", tspi, him
524 if (("esp" in s))
525 printf "esp%s@%s ", espi, him
526 if ("ah" in s)
527 printf "ah%s@%s ", aspi, him
528 printf " &&\n"
529 }
530 # inbound SAs
531 if (type == "tunnel") {
532 print "ipsec spi --label", q(names), "--af inet",
533 "--said", ("tun" intspi "@" me), "\\"
534 print "\t--ip4", "--src", him, "--dst", me, "&&"
535 }
536 espspi(him, me, respi)
537 ahspi(him, me, raspi)
538 if (nlspi > 1) {
539 # group them
540 printf "ipsec spigrp --label %s --said ", q(names)
541 if (type == "tunnel")
542 printf "tun%s@%s ", intspi, me
543 if (("esp" in s))
544 printf "esp%s@%s ", respi, me
545 if ("ah" in s)
546 printf "ah%s@%s ", raspi, me
547 printf " &&\n"
548 }
549 # with the SAs in place, eroute to them
550 print "ipsec eroute --label", q(names),
551 "--eraf inet --replace", "\\"
552 if (!shunt) {
553 if (type == "tunnel")
554 p = "tun"
555 else if (("esp" in s))
556 p = "esp"
557 else
558 p = "ah"
559 p = p tspi "@" him
560 }
561 print "\t--src", s["leftsubnet"], "--dst", s["rightsubnet"],
562 "--said", p, "&&"
563 # with the eroute in place, NOW we can route to it
564 #print "{ route del", routeid, "2>/dev/null ; true ; } &&"
565 updown("prepare", "&&")
566 #print "route add", routeid, "dev", iface, "gw",
567 # s["leftnexthop"], "&&"
568 updown("route", "&&")
569 # and with all processing in place, we can penetrate firewall
570 #if (s["leftfirewall"] == "yes") {
571 # print "ipfwadm -F -i accept -b -S", s["leftsubnet"],
572 # "-D", s["rightsubnet"], "&&"
573 #}
574 updown("up", "&&")
575 print "true"
576 print "} || {"
577 } else if (op == "--route") {
578 #print "{ route del", routeid, "2>/dev/null ; true ; } &&"
579 updown("prepare", "&&")
580 #print "route add", routeid, "dev", iface, "gw",
581 # s["leftnexthop"]
582 updown("route")
583 exit 0
584 } else if (op == "--unroute") {
585 #print "route del", routeid, "dev", iface, "gw",
586 # s["leftnexthop"]
587 updown("unroute")
588 exit 0
589 } else # down
590 print "{"
591
592 # now do "down", unconditionally, since the desired output for "up"
593 # is { up && up && up && true } || { down ; down ; down }
594 # tear things down in fairly strict reverse order
595 #if (s["leftfirewall"] == "yes")
596 # print "ipfwadm -F -d accept -b -S", s["leftsubnet"],
597 # "-D", s["rightsubnet"]
598 updown("down")
599 #print "route del", routeid, "dev", iface, "gw", s["leftnexthop"]
600 print "# do not delete route"
601 print "ipsec eroute --label", q(names), "--eraf inet --del", "\\"
602 print "\t--src", s["leftsubnet"], "--dst", s["rightsubnet"]
603 #if ("ah" in s) {
604 # print "ipsec spi --label", q(names), "--af inet", "--del",
605 # "--said", ("ah" raspi "@" me)
606 #}
607 #if ("esp" in s) {
608 # print "ipsec spi --label", q(names), "--af inet", "--del",
609 # "--said", ("esp" respi "@" me)
610 #}
611 if (!shunt) {
612 if (type == "tunnel")
613 p = "tun"
614 else if (("esp" in s))
615 p = "esp"
616 else
617 p = "ah"
618 print "ipsec spi --label", q(names), "--af inet", "--del",
619 "--said", (p tspi "@" him),
620 " # outbound"
621 print "ipsec spi --label", q(names), "--af inet", "--del",
622 "--said", (p intspi "@" me),
623 " # inbound"
624 }
625
626 if (op == "--up")
627 print "} 2>/dev/null"
628 else
629 print "}"
630 #########
631 }' |
632 if test $showonly
633 then
634 cat
635 else
636 sh $shopts
637 fi