2 # user interface to manual keying
3 # Copyright (C) 1998, 1999 Henry Spencer.
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>.
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
15 # RCSID $Id: manual,v 1.79 2002/03/11 20:42:27 henry Exp $
19 $me [--showonly] --{up|down|route|unroute} name
20 $me [--showonly] --{up|down|route|unroute} --union partname ...
22 other options: [--config ipsecconfigfile] [--other] [--show]
23 [--iam ipaddress@interface]"
25 # make sure outputs of (e.g.) ifconfig are in English
26 unset LANG LANGUAGE LC_ALL LC_MESSAGES
30 info=/var/run/ipsec.info
41 --help) echo "$usage" ; exit 0 ;;
42 --version) echo "$me $IPSEC_VERSION" ; exit 0 ;;
44 --showonly) showonly=yes ;;
47 --config) config="--config $2" ; shift ;;
48 --noinclude) noinclude=--noinclude ;;
49 --iam) interfs="$2" ; shift ;;
50 --up|--down|--route|--unroute)
59 -*) echo "$me: unknown option \`$1'" >&2 ; exit 2 ;;
65 case "$op$#:$union" in
66 [01]:*) echo "$usage" >&2 ; exit 2 ;;
67 2:0) echo "$me: warning: obsolete command syntax used" >&2
79 *) echo "$usage" >&2 ; exit 2 ;;
83 # --union obsolete-syntax case, op is last argument
84 echo "$me: warning: obsolete command syntax used" >&2
95 --up|--down|--route|--unroute) ;;
96 *) echo "$usage" >&2 ; exit 2 ;;
100 '') interfs="`ifconfig |
101 awk ' /^ipsec/ { interf = $1 ; next }
102 /^[^ \t]/ { interf = "" ; next }
116 ipsec _confread $config $noinclude $names |
124 interfs = "'"$interfs"'"
125 ni = split(interfs, terfs, " ")
127 fail("no IPsec-enabled interfaces found")
128 for (i = 1; i <= ni; i++) {
129 nc = split(terfs[i], cpts, "@")
131 fail("internal error on " terfs[i])
132 interface[cpts[1]] = cpts[2]
134 draddr = "'"$defaultrouteaddr"'"
135 drnexthop = "'"$defaultroutenexthop"'"
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"
183 fail("internal error, unknown type code \"" $1 "\"")
190 print myname ": fatal error in " q(names) ": " m |err
194 function swap(k, t, l, r) {
197 if ((l in s) && (r in s)) {
201 } else if (l in s) { # but not r
204 } else if (r in s) { # but not l
210 if ((k in s) && s[k] != "yes" && s[k] != "no")
211 fail("parameter \"" k "\" must be \"yes\" or \"no\"")
213 function default(k, v) {
219 fail("connection has no \"" k "\" parameter specified")
221 fail("parameter \"" k "\" value must be non-empty")
223 function integer(k) {
226 if (s[k] !~ /^[0-9]+$/)
227 fail("parameter \"" k "\" value must be integer")
229 function nexthopset(dir, val, k) {
232 fail("non-default value of " k " is being overridden")
238 function leftward( t) {
246 function rightward( t) {
254 function netfix(dir, n, t) {
259 fail(dir "subnet=" n " has no mask specified")
260 t = split(n, netfixarray, "/")
262 fail("bad syntax in " dir "subnet=" n)
263 s[dir "net"] = netfixarray[1]
264 s[dir "mask"] = mask(netfixarray[2])
269 if (!(m in maskbits))
270 fail("unknown mask syntax \"" m "\"")
273 function bidir(name, l, r) {
276 if (!(l in s) && (name in s))
278 if (!(r in s) && (name in s))
280 if ((l in s) != (r in s))
281 fail("must give both or neither \"" l "\" and \"" \
284 function espspi(src, dest, spi, dir) {
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"], "&&"
300 function ahspi(src, dest, spi, dir) {
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"], "&&"
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")
320 cmd = "ipsec _updown"
321 if (s["leftfirewall"] == "yes")
324 print "PLUTO_VERB=" verb verbsuf " " cmd " " suffix
330 default("type", "tunnel")
331 if (s["type"] == "transport") {
332 if ("leftsubnet" in s)
333 fail("type=transport incompatible with leftsubnet")
334 if ("rightsubnet" in s)
335 fail("type=transport incompatible with rightsubnet")
336 } else if (s["type"] != "tunnel" && s["type"] != "passthrough")
337 fail("only know how to do types tunnel/transport/passthrough")
339 if (s["type"] == "passthrough") {
340 if (("ah" in s) || ("esp" in s))
341 fail("passthrough connection may not specify AH or ESP")
344 if (!("ah" in s) && !("esp" in s))
345 fail("neither AH nor ESP specified for connection")
350 if (s["left"] == "%defaultroute") {
351 if (s["right"] == "%defaultroute")
352 fail("left and right cannot both be %defaultroute")
354 fail("%defaultroute requested but not known")
356 nexthopset("left", drnexthop)
357 } else if (s["right"] == "%defaultroute") {
359 fail("%defaultroute requested but not known")
361 nexthopset("right", drnexthop)
364 leftsub = ("leftsubnet" in s) ? 1 : 0
365 default("leftsubnet", s["left"] "/32")
366 rightsub = ("rightsubnet" in s) ? 1 : 0
367 default("rightsubnet", s["right"] "/32")
368 default("leftfirewall", "no")
369 default("rightfirewall", "no")
370 yesno("leftfirewall")
371 yesno("rightfirewall")
372 integer("espreplay_window")
373 if (("espreplay_window" in s) && s["espreplay_window"] == 0)
374 delete s["espreplay_window"]
375 integer("ahreplay_window")
376 if (("ahreplay_window" in s) && s["ahreplay_window"] == 0)
377 delete s["ahreplay_window"]
381 default("leftnexthop", s["right"])
382 default("rightnexthop", s["left"])
383 if (s["leftnexthop"] == s["left"])
384 fail("left and leftnexthop must not be the same")
385 if (s["rightnexthop"] == s["right"])
386 fail("right and rightnexthop must not be the same")
391 if ("spi" in s && "spibase" in s)
392 fail("cannot specify both spi and spibase")
394 if ("spibase" in s) {
396 if (b !~ /^0x[0-9a-fA-F]+0$/)
397 fail("bad syntax in spibase -- must be 0x...0")
398 spibase = substr(b, 1, length(b)-1)
401 if (s["spi"] !~ /^0x[0-9a-fA-F]+$/)
402 fail("bad syntax in spi -- must be 0x...")
410 for (addr in interface) {
411 if (addr == s["left"] || addr == s["right"]) {
413 fail("ambiguous: could be on \"" iface \
414 "\" or \"" interface[addr] "\"")
416 iface = interface[addr]
420 fail("cannot find interface for " s["left"] " or " s["right"])
424 else if (s["right"] == me)
427 havesubnet = leftsubnet
428 if (s["right"] == me) {
429 swap("") # swaps "left" and "right"
444 havesubnet = rightsubnet
448 if (s["leftnexthop"] == "%defaultroute") {
450 fail("%defaultroute requested but not known")
451 s["leftnexthop"] = drnexthop
455 if (s["type"] == "tunnel") {
460 if (s["rightespspi"] != "")
461 espi = s["rightespspi"]
463 if (s["leftespspi"] != "")
464 respi = s["leftespspi"]
473 if (s["rightahspi"] != "")
474 aspi = s["rightahspi"]
475 if (s["leftahspi"] != "")
476 raspi = s["leftahspi"]
478 routeid = "-net " s["rightnet"] " netmask " s["rightmask"]
479 if (s["rightmask"] == "255.255.255.255")
480 routeid = "-host " s["rightnet"]
482 print "PATH=\"'"$PATH"'\""
484 print "PLUTO_VERSION=1.1"
485 verbsuf = (havesubnet) ? "-client" : "-host"
486 print "PLUTO_CONNECTION=" q(names)
487 print "PLUTO_NEXT_HOP=" s["leftnexthop"]
488 print "PLUTO_INTERFACE=" iface
490 print "PLUTO_MY_CLIENT=" s["leftsubnet"]
491 print "PLUTO_MY_CLIENT_NET=" s["leftnet"]
492 print "PLUTO_MY_CLIENT_MASK=" s["leftmask"]
493 print "PLUTO_PEER=" him
494 print "PLUTO_PEER_CLIENT=" s["rightsubnet"]
495 print "PLUTO_PEER_CLIENT_NET=" s["rightnet"]
496 print "PLUTO_PEER_CLIENT_MASK=" s["rightmask"]
497 print "export PLUTO_VERSION PLUTO_CONNECTION PLUTO_NEXT_HOP"
498 print "export PLUTO_INTERFACE PLUTO_ME PLUTO_MY_CLIENT"
499 print "export PLUTO_MY_CLIENT_NET PLUTO_MY_CLIENT_MASK PLUTO_PEER"
500 print "export PLUTO_PEER_CLIENT PLUTO_PEER_CLIENT_NET"
501 print "export PLUTO_PEER_CLIENT_MASK"
505 # first, the outbound SAs
506 if (s["type"] == "tunnel") {
507 print "ipsec spi --label", q(names), "--af inet",
508 "--said", ("tun" tspi "@" him), "\\"
509 print "\t--ip4", "--src", me, "--dst", him, "&&"
511 espspi(me, him, espi)
515 printf "ipsec spigrp --label %s --said ", q(names)
516 if (s["type"] == "tunnel")
517 printf "tun%s@%s ", tspi, him
519 printf "esp%s@%s ", espi, him
521 printf "ah%s@%s ", aspi, him
525 if (s["type"] == "tunnel") {
526 print "ipsec spi --label", q(names), "--af inet",
527 "--said", ("tun" intspi "@" me), "\\"
528 print "\t--ip4", "--src", him, "--dst", me, "&&"
530 espspi(him, me, respi)
531 ahspi(him, me, raspi)
534 printf "ipsec spigrp --label %s --said ", q(names)
535 if (s["type"] == "tunnel")
536 printf "tun%s@%s ", intspi, me
538 printf "esp%s@%s ", respi, me
540 printf "ah%s@%s ", raspi, me
543 # with the SAs in place, eroute to them
544 print "ipsec eroute --label", q(names),
545 "--eraf inet --replace", "\\"
549 if (s["type"] == "tunnel")
551 else if (("esp" in s))
557 print "\t--src", s["leftsubnet"], "--dst", s["rightsubnet"],
559 # with the eroute in place, NOW we can route to it
560 #print "{ route del", routeid, "2>/dev/null ; true ; } &&"
561 updown("prepare", "&&")
562 #print "route add", routeid, "dev", iface, "gw",
563 # s["leftnexthop"], "&&"
564 updown("route", "&&")
565 # and with all processing in place, we can penetrate firewall
566 #if (s["leftfirewall"] == "yes") {
567 # print "ipfwadm -F -i accept -b -S", s["leftsubnet"],
568 # "-D", s["rightsubnet"], "&&"
573 } else if (op == "--route") {
574 #print "{ route del", routeid, "2>/dev/null ; true ; } &&"
575 updown("prepare", "&&")
576 #print "route add", routeid, "dev", iface, "gw",
580 } else if (op == "--unroute") {
581 #print "route del", routeid, "dev", iface, "gw",
588 # now do "down", unconditionally, since the desired output for "up"
589 # is { up && up && up && true } || { down ; down ; down }
590 # tear things down in fairly strict reverse order
591 #if (s["leftfirewall"] == "yes")
592 # print "ipfwadm -F -d accept -b -S", s["leftsubnet"],
593 # "-D", s["rightsubnet"]
595 #print "route del", routeid, "dev", iface, "gw", s["leftnexthop"]
596 print "# do not delete route"
597 print "ipsec eroute --label", q(names), "--eraf inet --del", "\\"
598 print "\t--src", s["leftsubnet"], "--dst", s["rightsubnet"]
600 # print "ipsec spi --label", q(names), "--af inet", "--del",
601 # "--said", ("ah" raspi "@" me)
604 # print "ipsec spi --label", q(names), "--af inet", "--del",
605 # "--said", ("esp" respi "@" me)
608 if (s["type"] == "tunnel")
610 else if (("esp" in s))
614 print "ipsec spi --label", q(names), "--af inet", "--del",
615 "--said", (p tspi "@" him),
617 print "ipsec spi --label", q(names), "--af inet", "--del",
618 "--said", (p intspi "@" me),
623 print "} 2>/dev/null"