summaryrefslogtreecommitdiff
path: root/programs/eroute
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2006-05-22 05:12:18 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2006-05-22 05:12:18 +0000
commitaa0f5b38aec14428b4b80e06f90ff781f8bca5f1 (patch)
tree95f3d0c8cb0d59d88900dbbd72110d7ab6e15b2a /programs/eroute
parent7c383bc22113b23718be89fe18eeb251942d7356 (diff)
downloadvyos-strongswan-aa0f5b38aec14428b4b80e06f90ff781f8bca5f1.tar.gz
vyos-strongswan-aa0f5b38aec14428b4b80e06f90ff781f8bca5f1.zip
Import initial strongswan 2.7.0 version into SVN.
Diffstat (limited to 'programs/eroute')
-rw-r--r--programs/eroute/.cvsignore1
-rw-r--r--programs/eroute/Makefile52
-rw-r--r--programs/eroute/eroute.5272
-rw-r--r--programs/eroute/eroute.8354
-rw-r--r--programs/eroute/eroute.c1044
5 files changed, 1723 insertions, 0 deletions
diff --git a/programs/eroute/.cvsignore b/programs/eroute/.cvsignore
new file mode 100644
index 000000000..133c4b456
--- /dev/null
+++ b/programs/eroute/.cvsignore
@@ -0,0 +1 @@
+eroute
diff --git a/programs/eroute/Makefile b/programs/eroute/Makefile
new file mode 100644
index 000000000..6d8f68033
--- /dev/null
+++ b/programs/eroute/Makefile
@@ -0,0 +1,52 @@
+# Makefile for the KLIPS interface utilities
+# Copyright (C) 1998, 1999 Henry Spencer.
+# Copyright (C) 1999, 2000, 2001 Richard Guy Briggs
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# RCSID $Id: Makefile,v 1.1 2004/03/15 20:35:27 as Exp $
+
+FREESWANSRCDIR=../..
+include ${FREESWANSRCDIR}/Makefile.inc
+
+PROGRAM:=eroute
+EXTRA5PROC=eroute.5
+
+LIBS:=${FREESWANLIB}
+
+include ../Makefile.program
+
+#
+# $Log: Makefile,v $
+# Revision 1.1 2004/03/15 20:35:27 as
+# added files from freeswan-2.04-x509-1.5.3
+#
+# Revision 1.4 2002/06/03 20:25:31 mcr
+# man page for files actually existant in /proc/net changed back to
+# ipsec_foo via new EXTRA5PROC process.
+#
+# Revision 1.3 2002/06/02 22:02:14 mcr
+# changed TOPDIR->FREESWANSRCDIR in all Makefiles.
+# (note that linux/net/ipsec/Makefile uses TOPDIR because this is the
+# kernel sense.)
+#
+# Revision 1.2 2002/04/26 01:21:26 mcr
+# while tracking down a missing (not installed) /etc/ipsec.conf,
+# MCR has decided that it is not okay for each program subdir to have
+# some subset (determined with -f) of possible files.
+# Each subdir that defines $PROGRAM, MUST have a PROGRAM.8 file as well as a PROGRAM file.
+# Optional PROGRAM.5 files have been added to the makefiles.
+#
+# Revision 1.1 2002/04/24 07:55:32 mcr
+# #include patches and Makefiles for post-reorg compilation.
+#
+#
+#
diff --git a/programs/eroute/eroute.5 b/programs/eroute/eroute.5
new file mode 100644
index 000000000..52b3f4d25
--- /dev/null
+++ b/programs/eroute/eroute.5
@@ -0,0 +1,272 @@
+.TH IPSEC_EROUTE 5 "20 Sep 2001"
+.\"
+.\" RCSID $Id: eroute.5,v 1.1 2004/03/15 20:35:27 as Exp $
+.\"
+.SH NAME
+ipsec_eroute \- list of existing eroutes
+.SH SYNOPSIS
+.B ipsec
+.B eroute
+.PP
+.B cat
+.B /proc/net/ipsec_eroute
+.SH DESCRIPTION
+.I /proc/net/ipsec_eroute
+lists the IPSEC extended routing tables,
+which control what (if any) processing is applied
+to non-encrypted packets arriving for IPSEC processing and forwarding.
+At this point it is a read-only file.
+.PP
+A table entry consists of:
+.IP + 3
+packet count,
+.IP +
+source address with mask and source port (0 if all ports or not applicable)
+.IP +
+a '->' separator for visual and automated parsing between src and dst
+.IP +
+destination address with mask and destination port (0 if all ports or
+not applicable)
+.IP +
+a '=>' separator for visual and automated parsing between selection
+criteria and SAID to use
+.IP +
+SAID (Security Association IDentifier), comprised of:
+.IP + 6
+protocol
+(\fIproto\fR),
+.IP +
+address family
+(\fIaf\fR),
+where '.' stands for IPv4 and ':' for IPv6
+.IP +
+Security Parameters Index
+(\fISPI\fR),
+.IP +
+effective destination
+(\fIedst\fR),
+where the packet should be forwarded after processing
+(normally the other security gateway)
+together indicate which Security Association should be used to process
+the packet,
+.IP + 3
+a ':' separating the SAID from the transport protocol (0 if all protocols)
+.IP +
+source identity text string with no whitespace, in parens,
+.IP +
+destination identity text string with no whitespace, in parens
+.PP
+Addresses are written as IPv4 dotted quads or IPv6 coloned hex,
+protocol is one of "ah", "esp", "comp" or "tun"
+and
+SPIs are prefixed hexadecimal numbers where the prefix '.' is for IPv4 and the prefix ':' is for IPv6
+.
+.PP
+SAIDs are written as "protoafSPI@edst". There are also 5
+"magic" SAIDs which have special meaning:
+.IP + 3
+.B %drop
+means that matches are to be dropped
+.IP +
+.B %reject
+means that matches are to be dropped and an ICMP returned, if
+possible to inform
+.IP +
+.B %trap
+means that matches are to trigger an ACQUIRE message to the Key
+Management daemon(s) and a hold eroute will be put in place to
+prevent subsequent packets also triggering ACQUIRE messages.
+.IP +
+.B %hold
+means that matches are to stored until the eroute is replaced or
+until that eroute gets reaped
+.IP +
+.B %pass
+means that matches are to allowed to pass without IPSEC processing
+.br
+.ne 5
+.SH EXAMPLES
+.LP
+.B "1867 172.31.252.0/24:0 -> 0.0.0.0/0:0 => tun0x130@192.168.43.1:0 "
+.br
+.B " () ()"
+.LP
+means that 1,867 packets have been sent to an
+.BR eroute
+that has been set up to protect traffic between the subnet
+.BR 172.31.252.0
+with a subnet mask of
+.BR 24
+bits and the default address/mask represented by an address of
+.BR 0.0.0.0
+with a subnet mask of
+.BR 0
+bits using the local machine as a security gateway on this end of the
+tunnel and the machine
+.BR 192.168.43.1
+on the other end of the tunnel with a Security Association IDentifier of
+.BR tun0x130@192.168.43.1
+which means that it is a tunnel mode connection (4, IPPROTO_IPIP) with a
+Security Parameters Index of
+.BR 130
+in hexadecimal with no identies defined for either end.
+.LP
+.B "746 192.168.2.110/32:0 -> 192.168.2.120/32:25 => esp0x130@192.168.2.120:6 "
+.br
+.B " () ()"
+.LP
+means that 746 packets have been sent to an
+.BR eroute
+that has been set up to protect traffic sent from any port on the host
+.BR 192.168.2.110
+to the SMTP (TCP, port 25) port on the host
+.BR 192.168.2.120
+with a Security Association IDentifier of
+.BR tun0x130@192.168.2.120
+which means that it is a transport mode connection with a
+Security Parameters Index of
+.BR 130
+in hexadecimal with no identies defined for either end.
+.LP
+.B 125 3049:1::/64 -> 0:0/0 => tun:130@3058:4::5 () ()
+.LP
+means that 125 packets have been sent to an
+.BR eroute
+that has been set up to protect traffic between the subnet
+.BR 3049:1::
+with a subnet mask of
+.BR 64
+bits and the default address/mask represented by an address of
+.BR 0:0
+with a subnet mask of
+.BR 0
+bits using the local machine as a security gateway on this end of the
+tunnel and the machine
+.BR 3058:4::5
+on the other end of the tunnel with a Security Association IDentifier of
+.BR tun:130@3058:4::5
+which means that it is a tunnel mode connection with a
+Security Parameters Index of
+.BR 130
+in hexadecimal with no identies defined for either end.
+.LP
+.B 42 192.168.6.0/24:0 -> 192.168.7.0/24:0 => %passthrough
+.LP
+means that 42 packets have been sent to an
+.BR eroute
+that has been set up to pass the traffic from the subnet
+.BR 192.168.6.0
+with a subnet mask of
+.BR 24
+bits and to subnet
+.BR 192.168.7.0
+with a subnet mask of
+.BR 24
+bits without any IPSEC processing with no identies defined for either end.
+.LP
+.B 2112 192.168.8.55/32:0 -> 192.168.9.47/24:0 => %hold (east) ()
+.LP
+means that 2112 packets have been sent to an
+.BR eroute
+that has been set up to hold the traffic from the host
+.BR 192.168.8.55
+and to host
+.BR 192.168.9.47
+until a key exchange from a Key Management daemon
+succeeds and puts in an SA or fails and puts in a pass
+or drop eroute depending on the default configuration with the local client
+defined as "east" and no identy defined for the remote end.
+.LP
+.B "2001 192.168.2.110/32:0 -> 192.168.2.120/32:0 => "
+.br
+.B " esp0xe6de@192.168.2.120:0 () ()"
+.LP
+means that 2001 packets have been sent to an
+.BR eroute
+that has been set up to protect traffic between the host
+.BR 192.168.2.110
+and the host
+.BR 192.168.2.120
+using
+.BR 192.168.2.110
+as a security gateway on this end of the
+connection and the machine
+.BR 192.168.2.120
+on the other end of the connection with a Security Association IDentifier of
+.BR esp0xe6de@192.168.2.120
+which means that it is a transport mode connection with a Security
+Parameters Index of
+.BR e6de
+in hexadecimal using Encapsuation Security Payload protocol (50,
+IPPROTO_ESP) with no identies defined for either end.
+.LP
+.B "1984 3049:1::110/128 -> 3049:1::120/128 => "
+.br
+.B " ah:f5ed@3049:1::120 () ()"
+.LP
+means that 1984 packets have been sent to an
+.BR eroute
+that has been set up to authenticate traffic between the host
+.BR 3049:1::110
+and the host
+.BR 3049:1::120
+using
+.BR 3049:1::110
+as a security gateway on this end of the
+connection and the machine
+.BR 3049:1::120
+on the other end of the connection with a Security Association IDentifier of
+.BR ah:f5ed@3049:1::120
+which means that it is a transport mode connection with a Security
+Parameters Index of
+.BR f5ed
+in hexadecimal using Authentication Header protocol (51,
+IPPROTO_AH) with no identies defined for either end.
+.SH FILES
+/proc/net/ipsec_eroute, /usr/local/bin/ipsec
+.SH "SEE ALSO"
+ipsec(8), ipsec_manual(8), ipsec_tncfg(5), ipsec_spi(5),
+ipsec_spigrp(5), ipsec_klipsdebug(5), ipsec_eroute(8), ipsec_version(5),
+ipsec_pf_key(5)
+.SH HISTORY
+Written for the Linux FreeS/WAN project
+<http://www.freeswan.org/>
+by Richard Guy Briggs.
+.\"
+.\" $Log: eroute.5,v $
+.\" Revision 1.1 2004/03/15 20:35:27 as
+.\" added files from freeswan-2.04-x509-1.5.3
+.\"
+.\" Revision 1.9 2002/04/24 07:35:38 mcr
+.\" Moved from ./klips/utils/eroute.5,v
+.\"
+.\" Revision 1.8 2001/09/20 15:33:13 rgb
+.\" PF_KEYv2 ident extension output documentation.
+.\"
+.\" Revision 1.7 2001/05/29 05:15:31 rgb
+.\" Added packet count field at beginning of line.
+.\"
+.\" Revision 1.6 2001/02/26 19:58:32 rgb
+.\" Put SAID elements in order they appear in SAID.
+.\" Implement magic SAs %drop, %reject, %trap, %hold, %pass as part
+.\" of the new SPD and to support opportunistic.
+.\"
+.\" Revision 1.5 2000/09/17 18:56:48 rgb
+.\" Added IPCOMP support.
+.\"
+.\" Revision 1.4 2000/09/13 15:54:31 rgb
+.\" Added Gerhard's ipv6 updates.
+.\"
+.\" Revision 1.3 2000/06/30 18:21:55 rgb
+.\" Update SEE ALSO sections to include ipsec_version(5) and ipsec_pf_key(5)
+.\" and correct FILES sections to no longer refer to /dev/ipsec which has
+.\" been removed since PF_KEY does not use it.
+.\"
+.\" Revision 1.2 2000/06/28 12:44:11 henry
+.\" format touchup
+.\"
+.\" Revision 1.1 2000/06/28 05:43:00 rgb
+.\" Added manpages for all 5 klips utils.
+.\"
+.\"
+.\"
diff --git a/programs/eroute/eroute.8 b/programs/eroute/eroute.8
new file mode 100644
index 000000000..d9449632b
--- /dev/null
+++ b/programs/eroute/eroute.8
@@ -0,0 +1,354 @@
+.TH IPSEC_EROUTE 8 "21 Jun 2000"
+.\"
+.\" RCSID $Id: eroute.8,v 1.1 2004/03/15 20:35:27 as Exp $
+.\"
+.SH NAME
+ipsec eroute \- manipulate IPSEC extended routing tables
+.SH SYNOPSIS
+.B ipsec
+.B eroute
+.PP
+.B ipsec
+.B eroute
+.B \-\-add
+.B \-\-eraf (inet | inet6)
+.B \-\-src
+src/srcmaskbits|srcmask
+.B \-\-dst
+dst/dstmaskbits|dstmask
+[
+.B \-\-transport\-proto
+transport-protocol
+]
+[
+.B \-\-src\-port
+source-port
+]
+[
+.B \-\-dst\-port
+dest-port
+]
+<SAID>
+.PP
+.B ipsec
+.B eroute
+.B \-\-replace
+.B \-\-eraf (inet | inet6)
+.B \-\-src
+src/srcmaskbits|srcmask
+.B \-\-dst
+dst/dstmaskbits|dstmask
+[
+.B \-\-transport\-proto
+transport-protocol
+]
+[
+.B \-\-src\-port
+source-port
+]
+[
+.B \-\-dst\-port
+dest-port
+]
+<SAID>
+.PP
+.B ipsec
+.B eroute
+.B \-\-del
+.B \-\-eraf (inet | inet6)
+.B \-\-src
+src/srcmaskbits|srcmask
+.B \-\-dst
+dst/dstmaskbits|dstmask
+[
+.B \-\-transport\-proto
+transport-protocol
+]
+[
+.B \-\-src\-port
+source-port
+]
+[
+.B \-\-dst\-port
+dest-port
+]
+.PP
+.B ipsec
+.B eroute
+.B \-\-clear
+.PP
+.B ipsec
+.B eroute
+.B \-\-help
+.PP
+.B ipsec
+.B eroute
+.B \-\-version
+.PP
+Where <SAID> is
+.B \-\-af
+(inet | inet6)
+.B \-\-edst
+edst
+.B \-\-spi
+spi
+.B \-\-proto
+proto
+OR
+.B \-\-said
+said
+OR
+.B \-\-said
+.B (%passthrough | %passthrough4 | %passthrough6 | %drop | %reject | %trap | %hold | %pass )
+.SH DESCRIPTION
+.I Eroute
+manages the IPSEC extended routing tables,
+which control what (if any) processing is applied
+to non-encrypted packets arriving for IPSEC processing and forwarding.
+The form with no additional arguments lists the contents of
+/proc/net/ipsec_eroute.
+The
+.B \-\-add
+form adds a table entry, the
+.B \-\-replace
+form replaces a table entry, while the
+.B \-\-del
+form deletes one. The
+.B \-\-clear
+form deletes the entire table.
+.PP
+A table entry consists of:
+.IP + 3
+source and destination addresses,
+with masks, source and destination ports and protocol
+for selection of packets. The source and destination ports are only
+legal if the transport protocol is
+.BR TCP
+or
+.BR UDP.
+A port can be specified as either decimal, hexadecimal (leading 0x),
+octal (leading 0) or a name listed in the first column of /etc/services.
+A transport protocol can be specified as either decimal, hexadecimal
+(leading 0x), octal (leading 0) or a name listed in the first column
+of /etc/protocols. If a transport protocol or port is not specified
+then it defaults to 0 which means all protocols or all ports
+respectively.
+.IP +
+Security Association IDentifier, comprised of:
+.IP + 6
+protocol
+(\fIproto\fR), indicating (together with the
+effective destination and the security parameters index)
+which Security Association should be used to process the packet
+.IP +
+address family
+(\fIaf\fR),
+.IP +
+Security Parameters Index
+(\fIspi\fR), indicating (together with the
+effective destination and protocol)
+which Security Association should be used to process the packet
+(must be larger than or equal to 0x100)
+.IP +
+effective destination
+(\fIedst\fR),
+where the packet should be forwarded after processing
+(normally the other security gateway)
+.IP + 3
+OR
+.IP + 6
+SAID
+(\fIsaid\fR), indicating
+which Security Association should be used to process the packet
+.PP
+Addresses are written as IPv4 dotted quads or IPv6 coloned hex,
+protocol is one of "ah", "esp", "comp" or "tun" and SPIs are
+prefixed hexadecimal numbers where '.' represents IPv4 and ':'
+stands for IPv6.
+.PP
+SAIDs are written as "protoafSPI@address". There are also 5
+"magic" SAIDs which have special meaning:
+.IP + 3
+.B %drop
+means that matches are to be dropped
+.IP +
+.B %reject
+means that matches are to be dropped and an ICMP returned, if
+possible to inform
+.IP +
+.B %trap
+means that matches are to trigger an ACQUIRE message to the Key
+Management daemon(s) and a hold eroute will be put in place to
+prevent subsequent packets also triggering ACQUIRE messages.
+.IP +
+.B %hold
+means that matches are to stored until the eroute is replaced or
+until that eroute gets reaped
+.IP +
+.B %pass
+means that matches are to allowed to pass without IPSEC processing
+.PP
+The format of /proc/net/ipsec_eroute is listed in ipsec_eroute(5).
+.br
+.ne 5
+.SH EXAMPLES
+.LP
+.B "ipsec eroute \-\-add \-\-eraf inet \-\-src 192.168.0.1/32 \e"
+.br
+.B " \-\-dst 192.168.2.0/24 \-\-af inet \-\-edst 192.168.0.2 \e"
+.br
+.B " \-\-spi 0x135 \-\-proto tun"
+.LP
+sets up an
+.BR eroute
+on a Security Gateway to protect traffic between the host
+.BR 192.168.0.1
+and the subnet
+.BR 192.168.2.0
+with
+.BR 24
+bits of subnet mask via Security Gateway
+.BR 192.168.0.2
+using the Security Association with address
+.BR 192.168.0.2 ,
+Security Parameters Index
+.BR 0x135
+and protocol
+.BR tun
+(50, IPPROTO_ESP).
+.LP
+.B "ipsec eroute \-\-add \-\-eraf inet6 \-\-src 3049:1::1/128 \e"
+.br
+.B " \-\-dst 3049:2::/64 \-\-af inet6 \-\-edst 3049:1::2 \e"
+.br
+.B " \-\-spi 0x145 \-\-proto tun"
+.LP
+sets up an
+.BR eroute
+on a Security Gateway to protect traffic between the host
+.BR 3049:1::1
+and the subnet
+.BR 3049:2::
+with
+.BR 64
+bits of subnet mask via Security Gateway
+.BR 3049:1::2
+using the Security Association with address
+.BR 3049:1::2 ,
+Security Parameters Index
+.BR 0x145
+and protocol
+.BR tun
+(50, IPPROTO_ESP).
+.LP
+.B "ipsec eroute \-\-replace \-\-eraf inet \-\-src company.com/24 \e"
+.br
+.B " \-\-dst ftp.ngo.org/32 \-\-said tun.135@gw.ngo.org"
+.LP
+replaces an
+.BR eroute
+on a Security Gateway to protect traffic between the subnet
+.BR company.com
+with
+.BR 24
+bits of subnet mask and the host
+.BR ftp.ngo.org
+via Security Gateway
+.BR gw.ngo.org
+using the Security Association with Security Association ID
+.BR tun0x135@gw.ngo.org
+.LP
+.B "ipsec eroute \-\-del \-\-eraf inet \-\-src company.com/24 \e"
+.br
+.B " \-\-dst www.ietf.org/32 \-\-said %passthrough4"
+.LP
+deletes an
+.BR eroute
+on a Security Gateway that allowed traffic between the subnet
+.BR company.com
+with
+.BR 24
+bits of subnet mask and the host
+.BR www.ietf.org
+to pass in the clear, unprocessed.
+.LP
+.B "ipsec eroute \-\-add \-\-eraf inet \-\-src company.com/24 \e"
+.br
+.B " \-\-dst mail.ngo.org/32 \-\-transport-proto 6 \e"
+.br
+.B " \-\-dst\-port 110 \-\-said tun.135@mail.ngo.org"
+.LP
+sets up an
+.BR eroute
+on on a Security Gateway to protect only TCP traffic on port 110
+(pop3) between the subnet
+.BR company.com
+with
+.BR 24
+bits of subnet mask and the host
+.BR ftp.ngo.org
+via Security Gateway
+.BR mail.ngo.org
+using the Security Association with Security Association ID
+.BR tun0x135@mail.ngo.org.
+Note that any other traffic bound for
+.BR mail.ngo.org
+that is routed via the ipsec device will be dropped. If you wish to
+allow other traffic to pass through then you must add a %pass rule.
+For example the following rule when combined with the above will
+ensure that POP3 messages read from
+.BR mail.ngo.org
+will be encrypted but all other traffic to/from
+.BR mail.ngo.org
+will be in clear text.
+.LP
+.B "ipsec eroute \-\-add \-\-eraf inet \-\-src company.com/24 \e"
+.br
+.B " \-\-dst mail.ngo.org/32 \-\-said %pass"
+.br
+.LP
+.SH FILES
+/proc/net/ipsec_eroute, /usr/local/bin/ipsec
+.SH "SEE ALSO"
+ipsec(8), ipsec_manual(8), ipsec_tncfg(8), ipsec_spi(8),
+ipsec_spigrp(8), ipsec_klipsdebug(8), ipsec_eroute(5)
+.SH HISTORY
+Written for the Linux FreeS/WAN project
+<http://www.freeswan.org/>
+by Richard Guy Briggs.
+.\"
+.\" $Log: eroute.8,v $
+.\" Revision 1.1 2004/03/15 20:35:27 as
+.\" added files from freeswan-2.04-x509-1.5.3
+.\"
+.\" Revision 1.25 2002/04/24 07:35:38 mcr
+.\" Moved from ./klips/utils/eroute.8,v
+.\"
+.\" Revision 1.24 2001/02/26 19:58:49 rgb
+.\" Added a comment on the restriction of spi > 0x100.
+.\" Implement magic SAs %drop, %reject, %trap, %hold, %pass as part
+.\" of the new SPD and to support opportunistic.
+.\"
+.\" Revision 1.23 2000/09/17 18:56:48 rgb
+.\" Added IPCOMP support.
+.\"
+.\" Revision 1.22 2000/09/13 15:54:31 rgb
+.\" Added Gerhard's ipv6 updates.
+.\"
+.\" Revision 1.21 2000/06/30 18:21:55 rgb
+.\" Update SEE ALSO sections to include ipsec_version(5) and ipsec_pf_key(5)
+.\" and correct FILES sections to no longer refer to /dev/ipsec which has
+.\" been removed since PF_KEY does not use it.
+.\"
+.\" Revision 1.20 2000/06/21 16:54:57 rgb
+.\" Added 'no additional args' text for listing contents of
+.\" /proc/net/ipsec_* files.
+.\"
+.\" Revision 1.19 1999/07/19 18:47:24 henry
+.\" fix slightly-misformed comments
+.\"
+.\" Revision 1.18 1999/04/06 04:54:37 rgb
+.\" Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
+.\" patch shell fixes.
+.\"
+.\"
diff --git a/programs/eroute/eroute.c b/programs/eroute/eroute.c
new file mode 100644
index 000000000..d1b2bff0a
--- /dev/null
+++ b/programs/eroute/eroute.c
@@ -0,0 +1,1044 @@
+/*
+ * manipulate eroutes
+ * Copyright (C) 1996 John Ioannidis.
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001 Richard Guy Briggs.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+char eroute_c_version[] = "RCSID $Id: eroute.c,v 1.3 2005/02/24 20:03:46 as Exp $";
+
+
+#include <sys/types.h>
+#include <linux/types.h> /* new */
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h> /* system(), strtoul() */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <netdb.h>
+
+
+#include <unistd.h>
+#include <freeswan.h>
+#if 0
+#include <linux/autoconf.h> /* CONFIG_IPSEC_PFKEYv2 */
+#endif
+/* permanently turn it on since netlink support has been disabled */
+
+#include <signal.h>
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#include "freeswan/radij.h"
+#include "freeswan/ipsec_encap.h"
+
+#include <stdio.h>
+#include <getopt.h>
+
+char *program_name;
+char me[] = "ipsec eroute";
+extern char *optarg;
+extern int optind, opterr, optopt;
+char *eroute_af_opt, *said_af_opt, *edst_opt, *spi_opt, *proto_opt, *said_opt, *dst_opt, *src_opt;
+char *transport_proto_opt, *src_port_opt, *dst_port_opt;
+int action_type = 0;
+
+int pfkey_sock;
+fd_set pfkey_socks;
+uint32_t pfkey_seq = 0;
+
+#define EMT_IFADDR 1 /* set enc if addr */
+#define EMT_SETSPI 2 /* Set SPI properties */
+#define EMT_DELSPI 3 /* Delete an SPI */
+#define EMT_GRPSPIS 4 /* Group SPIs (output order) */
+#define EMT_SETEROUTE 5 /* set an extended route */
+#define EMT_DELEROUTE 6 /* del an extended route */
+#define EMT_TESTROUTE 7 /* try to find route, print to console */
+#define EMT_SETDEBUG 8 /* set debug level if active */
+#define EMT_UNGRPSPIS 9 /* UnGroup SPIs (output order) */
+#define EMT_CLREROUTE 10 /* clear the extended route table */
+#define EMT_CLRSPIS 11 /* clear the spi table */
+#define EMT_REPLACEROUTE 12 /* set an extended route */
+#define EMT_GETDEBUG 13 /* get debug level if active */
+#define EMT_INEROUTE 14 /* set incoming policy for IPIP on a chain */
+
+static void
+add_port(int af, ip_address * addr, short port)
+{
+ switch (af)
+ {
+ case AF_INET:
+ addr->u.v4.sin_port = port;
+ break;
+ case AF_INET6:
+ addr->u.v6.sin6_port = port;
+ break;
+ }
+}
+
+static void
+usage(char* arg)
+{
+ fprintf(stdout, "usage: %s --{add,addin,replace} --eraf <inet | inet6> --src <src>/<srcmaskbits>|<srcmask> --dst <dst>/<dstmaskbits>|<dstmask> [ --transport-proto <protocol> ] [ --src-port <source-port> ] [ --dst-port <dest-port> ] <SA>\n", arg);
+ fprintf(stdout, " where <SA> is '--af <inet | inet6> --edst <edst> --spi <spi> --proto <proto>'\n");
+ fprintf(stdout, " OR '--said <said>'\n");
+ fprintf(stdout, " OR '--said <%%passthrough | %%passthrough4 | %%passthrough6 | %%drop | %%reject | %%trap | %%hold | %%pass>'.\n");
+ fprintf(stdout, " %s --del --eraf <inet | inet6>--src <src>/<srcmaskbits>|<srcmask> --dst <dst>/<dstmaskbits>|<dstmask> [ --transport-proto <protocol> ] [ --src-port <source-port> ] [ --dst-port <dest-port> ]\n", arg);
+ fprintf(stdout, " %s --clear\n", arg);
+ fprintf(stdout, " %s --help\n", arg);
+ fprintf(stdout, " %s --version\n", arg);
+ fprintf(stdout, " %s\n", arg);
+ fprintf(stdout, " [ --debug ] is optional to any %s command.\n", arg);
+ fprintf(stdout, " [ --label <label> ] is optional to any %s command.\n", arg);
+ exit(1);
+}
+
+static struct option const longopts[] =
+{
+ {"dst", 1, 0, 'D'},
+ {"src", 1, 0, 'S'},
+ {"eraf", 1, 0, 'f'},
+ {"add", 0, 0, 'a'},
+ {"addin", 0, 0, 'A'},
+ {"replace", 0, 0, 'r'},
+ {"clear", 0, 0, 'c'},
+ {"del", 0, 0, 'd'},
+ {"af", 1, 0, 'i'},
+ {"edst", 1, 0, 'e'},
+ {"proto", 1, 0, 'p'},
+ {"transport-proto", 1, 0, 'P'},
+ {"src-port", 1, 0, 'Q'},
+ {"dst-port", 1, 0, 'R'},
+ {"help", 0, 0, 'h'},
+ {"spi", 1, 0, 's'},
+ {"said", 1, 0, 'I'},
+ {"version", 0, 0, 'v'},
+ {"label", 1, 0, 'l'},
+ {"optionsfrom", 1, 0, '+'},
+ {"debug", 0, 0, 'g'},
+ {0, 0, 0, 0}
+};
+
+int
+main(int argc, char **argv)
+{
+ /* int fd; */
+ char *endptr;
+ /* int ret; */
+ int c, previous = -1;
+ const char* error_s;
+ int debug = 0;
+
+ int error = 0;
+
+ char ipaddr_txt[ADDRTOT_BUF];
+ struct sadb_ext *extensions[SADB_EXT_MAX + 1];
+ struct sadb_msg *pfkey_msg;
+ ip_address pfkey_address_s_ska;
+ /*struct sockaddr_in pfkey_address_d_ska;*/
+ ip_address pfkey_address_sflow_ska;
+ ip_address pfkey_address_dflow_ska;
+ ip_address pfkey_address_smask_ska;
+ ip_address pfkey_address_dmask_ska;
+
+ int transport_proto = 0;
+ int src_port = 0;
+ int dst_port = 0;
+ ip_said said;
+ ip_subnet s_subnet, d_subnet;
+ int eroute_af = 0;
+ int said_af = 0;
+
+ int argcount = argc;
+
+ const char permitted_options[] =
+ "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n";
+
+ program_name = argv[0];
+ eroute_af_opt = said_af_opt = edst_opt = spi_opt = proto_opt = said_opt = dst_opt = src_opt = NULL;
+
+ while((c = getopt_long(argc, argv, ""/*"acdD:e:i:hprs:S:f:vl:+:g"*/, longopts, 0)) != EOF)
+ {
+ switch(c)
+ {
+ case 'g':
+ debug = 1;
+ pfkey_lib_debug = PF_KEY_DEBUG_PARSE_MAX;
+ argcount--;
+ break;
+ case 'a':
+ if (action_type)
+ {
+ fprintf(stderr, permitted_options, program_name);
+ exit(1);
+ }
+ action_type = EMT_SETEROUTE;
+ break;
+ case 'A':
+ if (action_type)
+ {
+ fprintf(stderr, permitted_options, program_name);
+ exit(1);
+ }
+ action_type = EMT_INEROUTE;
+ break;
+ case 'r':
+ if (action_type)
+ {
+ fprintf(stderr, permitted_options, program_name);
+ exit(1);
+ }
+ action_type = EMT_REPLACEROUTE;
+ break;
+ case 'c':
+ if (action_type)
+ {
+ fprintf(stderr, permitted_options, program_name);
+ exit(1);
+ }
+ action_type = EMT_CLREROUTE;
+ break;
+ case 'd':
+ if (action_type)
+ {
+ fprintf(stderr, permitted_options, program_name);
+ exit(1);
+ }
+ action_type = EMT_DELEROUTE;
+ break;
+ case 'e':
+ if (said_opt)
+ {
+ fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined in SA:%s\n"
+ , program_name, optarg, said_opt);
+ exit (1);
+ }
+ if (edst_opt)
+ {
+ fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined as:%s\n"
+ , program_name, optarg, edst_opt);
+ exit (1);
+ }
+ error_s = ttoaddr(optarg, 0, said_af, &said.dst);
+ if (error_s != NULL)
+ {
+ fprintf(stderr, "%s: Error, %s converting --edst argument:%s\n"
+ , program_name, error_s, optarg);
+ exit (1);
+ }
+ edst_opt = optarg;
+ break;
+ case 'h':
+ case '?':
+ usage(program_name);
+ exit(1);
+ case 's':
+ if (said_opt)
+ {
+ fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined in SA:%s\n"
+ , program_name, optarg, said_opt);
+ exit (1);
+ }
+ if (spi_opt)
+ {
+ fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined as:%s\n"
+ , program_name, optarg, spi_opt);
+ exit (1);
+ }
+ said.spi = htonl(strtoul(optarg, &endptr, 0));
+ if (!(endptr == optarg + strlen(optarg)))
+ {
+ fprintf(stderr, "%s: Invalid character in SPI parameter: %s\n"
+ , program_name, optarg);
+ exit (1);
+ }
+ if (ntohl(said.spi) < 0x100)
+ {
+ fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than 0x100.\n"
+ , program_name, optarg, ntohl(said.spi));
+ exit(1);
+ }
+ spi_opt = optarg;
+ break;
+ case 'p':
+ if (said_opt)
+ {
+ fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined in SA:%s\n"
+ , program_name, optarg, said_opt);
+ exit (1);
+ }
+ if (proto_opt)
+ {
+ fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined as:%s\n"
+ , program_name, optarg, proto_opt);
+ exit (1);
+ }
+#if 0
+ if (said.proto)
+ {
+ fprintf(stderr, "%s: Warning, PROTO parameter redefined:%s\n"
+ , program_name, optarg);
+ exit (1);
+ }
+#endif
+ if (!strcmp(optarg, "ah"))
+ said.proto = SA_AH;
+ if (!strcmp(optarg, "esp"))
+ said.proto = SA_ESP;
+ if (!strcmp(optarg, "tun"))
+ said.proto = SA_IPIP;
+ if (!strcmp(optarg, "comp"))
+ said.proto = SA_COMP;
+ if (said.proto == 0)
+ {
+ fprintf(stderr, "%s: Invalid PROTO parameter: %s\n"
+ , program_name, optarg);
+ exit (1);
+ }
+ proto_opt = optarg;
+ break;
+ case 'I':
+ if (said_opt)
+ {
+ fprintf(stderr, "%s: Error, SAID parameter redefined:%s, already defined in SA:%s\n"
+ , program_name, optarg, said_opt);
+ exit (1);
+ }
+ if (proto_opt)
+ {
+ fprintf(stderr, "%s: Error, PROTO parameter redefined in SA:%s, already defined as:%s\n"
+ , program_name, optarg, proto_opt);
+ exit (1);
+ }
+ if (edst_opt)
+ {
+ fprintf(stderr, "%s: Error, EDST parameter redefined in SA:%s, already defined as:%s\n"
+ , program_name, optarg, edst_opt);
+ exit (1);
+ }
+ if (spi_opt)
+ {
+ fprintf(stderr, "%s: Error, SPI parameter redefined in SA:%s, already defined as:%s\n"
+ , program_name, optarg, spi_opt);
+ exit (1);
+ }
+ if (said_af_opt)
+ {
+ fprintf(stderr, "%s: Error, address family parameter redefined in SA:%s, already defined as:%s\n"
+ , program_name, optarg, said_af_opt);
+ exit (1);
+ }
+ error_s = ttosa(optarg, 0, &said);
+ if (error_s != NULL)
+ {
+ fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n"
+ , program_name, error_s, optarg);
+ exit (1);
+ }
+ else if (ntohl(said.spi) < 0x100)
+ {
+ fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than or equal to 0x100.\n"
+ , program_name, optarg, said.spi);
+ exit(1);
+ }
+ said_af = addrtypeof(&said.dst);
+ said_opt = optarg;
+ break;
+ case 'v':
+ fprintf(stdout, "%s %s\n", me, ipsec_version_code());
+ fprintf(stdout, "See `ipsec --copyright' for copyright information.\n");
+ exit(1);
+ case 'D':
+ if (dst_opt)
+ {
+ fprintf(stderr, "%s: Error, --dst parameter redefined:%s, already defined as:%s\n"
+ , program_name, optarg, dst_opt);
+ exit (1);
+ }
+ error_s = ttosubnet(optarg, 0, eroute_af, &d_subnet);
+ if (error_s != NULL)
+ {
+ fprintf(stderr, "%s: Error, %s converting --dst argument: %s\n"
+ , program_name, error_s, optarg);
+ exit (1);
+ }
+ dst_opt = optarg;
+ break;
+ case 'S':
+ if (src_opt)
+ {
+ fprintf(stderr, "%s: Error, --src parameter redefined:%s, already defined as:%s\n"
+ , program_name, optarg, src_opt);
+ exit (1);
+ }
+ error_s = ttosubnet(optarg, 0, eroute_af, &s_subnet);
+ if (error_s != NULL)
+ {
+ fprintf(stderr, "%s: Error, %s converting --src argument: %s\n"
+ , program_name, error_s, optarg);
+ exit (1);
+ }
+ src_opt = optarg;
+ break;
+ case 'P':
+ if (transport_proto_opt)
+ {
+ fprintf(stderr, "%s: Error, --transport-proto parameter redefined:%s, already defined as:%s\n"
+ , program_name, optarg, transport_proto_opt);
+ exit(1);
+ }
+ transport_proto_opt = optarg;
+ break;
+ case 'Q':
+ if (src_port_opt)
+ {
+ fprintf(stderr, "%s: Error, --src-port parameter redefined:%s, already defined as:%s\n"
+ , program_name, optarg, src_port_opt);
+ exit(1);
+ }
+ src_port_opt = optarg;
+ break;
+ case 'R':
+ if (dst_port_opt)
+ {
+ fprintf(stderr, "%s: Error, --dst-port parameter redefined:%s, already defined as:%s\n"
+ , program_name, optarg, dst_port_opt);
+ exit(1);
+ }
+ dst_port_opt = optarg;
+ break;
+ case 'l':
+ program_name = malloc(strlen(argv[0])
+ + 10 /* update this when changing the sprintf() */
+ + strlen(optarg));
+ sprintf(program_name, "%s --label %s", argv[0], optarg);
+ argcount -= 2;
+ break;
+ case 'i': /* specifies the address family of the SAID, stored in said_af */
+ if (said_af_opt)
+ {
+ fprintf(stderr, "%s: Error, address family of SAID redefined:%s, already defined as:%s\n"
+ , program_name, optarg, said_af_opt);
+ exit (1);
+ }
+ if (!strcmp(optarg, "inet"))
+ said_af = AF_INET;
+ if (!strcmp(optarg, "inet6"))
+ said_af = AF_INET6;
+ if (said_af == 0)
+ {
+ fprintf(stderr, "%s: Invalid address family parameter for SAID: %s\n"
+ , program_name, optarg);
+ exit (1);
+ }
+ said_af_opt = optarg;
+ break;
+ case 'f': /* specifies the address family of the eroute, stored in eroute_af */
+ if (eroute_af_opt)
+ {
+ fprintf(stderr, "%s: Error, address family of eroute redefined:%s, already defined as:%s\n"
+ , program_name, optarg, eroute_af_opt);
+ exit (1);
+ }
+ if (!strcmp(optarg, "inet"))
+ eroute_af = AF_INET;
+ if (!strcmp(optarg, "inet6"))
+ eroute_af = AF_INET6;
+ if (eroute_af == 0)
+ {
+ fprintf(stderr, "%s: Invalid address family parameter for eroute: %s\n"
+ , program_name, optarg);
+ exit (1);
+ }
+ eroute_af_opt = optarg;
+ break;
+ case '+': /* optionsfrom */
+ optionsfrom(optarg, &argc, &argv, optind, stderr);
+ /* no return on error */
+ break;
+ default:
+ break;
+ }
+ previous = c;
+ }
+
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: argc=%d\n", program_name, argc);
+ }
+
+ if (argcount == 1)
+ {
+ system("cat /proc/net/ipsec_eroute");
+ exit(0);
+ }
+
+ /* Sanity checks */
+
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: action_type=%d\n", program_name, action_type);
+ }
+
+ if (transport_proto_opt != 0)
+ {
+ struct protoent * proto = getprotobyname(transport_proto_opt);
+
+ if (proto != 0)
+ {
+ transport_proto = proto->p_proto;
+ }
+ else
+ {
+ transport_proto = strtoul(transport_proto_opt, &endptr, 0);
+
+ if ((*endptr != '\0')
+ || (transport_proto == 0 && endptr == transport_proto_opt))
+ {
+ fprintf(stderr, "%s: Invalid character in --transport-proto parameter: %s\n"
+ , program_name, transport_proto_opt);
+ exit (1);
+ }
+ if (transport_proto > 255)
+ {
+ fprintf(stderr, "%s: --transport-proto parameter: %s must be in the range 0 to 255 inclusive\n"
+ , program_name, transport_proto_opt);
+ exit (1);
+ }
+ }
+ }
+
+ if (src_port_opt != 0 || dst_port_opt != 0)
+ {
+ switch (transport_proto)
+ {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ break;
+ default:
+ fprintf(stderr, "%s: --transport-proto with either UDP or TCP must be specified if --src-port or --dst-port is used\n"
+ , program_name);
+ exit(1);
+ }
+ }
+
+ if (src_port_opt)
+ {
+ struct servent * ent = getservbyname(src_port_opt, 0);
+
+ if (ent != 0)
+ {
+ src_port = ent->s_port;
+ }
+ else
+ {
+ src_port = strtoul(src_port_opt, &endptr, 0);
+
+ if ((*endptr != '\0')
+ || (src_port == 0 && endptr == src_port_opt))
+ {
+ fprintf(stderr, "%s: Invalid character in --src-port parameter: %s\n"
+ , program_name, src_port_opt);
+ exit (1);
+ }
+ if (src_port > 65535)
+ {
+ fprintf(stderr, "%s: --src-port parameter: %s must be in the range 0 to 65535 inclusive\n"
+ , program_name, src_port_opt);
+ }
+ src_port = htons(src_port);
+ }
+ }
+
+ if (dst_port_opt)
+ {
+ struct servent * ent = getservbyname(dst_port_opt, 0);
+
+ if (ent != 0)
+ {
+ dst_port = ent->s_port;
+ }
+ else
+ {
+ dst_port = strtoul(dst_port_opt, &endptr, 0);
+
+ if ((*endptr != '\0')
+ || (dst_port == 0 && endptr == dst_port_opt))
+ {
+ fprintf(stderr, "%s: Invalid character in --dst-port parameter: %s\n"
+ , program_name, dst_port_opt);
+ exit (1);
+ }
+ if (dst_port > 65535)
+ {
+ fprintf(stderr, "%s: --dst-port parameter: %s must be in the range 0 to 65535 inclusive\n"
+ , program_name, dst_port_opt);
+ }
+ dst_port = htons(dst_port);
+ }
+ }
+
+ switch(action_type)
+ {
+ case EMT_SETEROUTE:
+ case EMT_REPLACEROUTE:
+ case EMT_INEROUTE:
+ if (!(said_af_opt && edst_opt && spi_opt && proto_opt) && !(said_opt))
+ {
+ fprintf(stderr, "%s: add and addin options must have SA specified.\n"
+ , program_name);
+ exit(1);
+ }
+ case EMT_DELEROUTE:
+ if (!src_opt)
+ {
+ fprintf(stderr, "%s: Error -- %s option '--src' is required.\n"
+ , program_name, (action_type == EMT_SETEROUTE) ? "add" : "del");
+ exit(1);
+ }
+ if (!dst_opt)
+ {
+ fprintf(stderr, "%s: Error -- %s option '--dst' is required.\n"
+ , program_name, (action_type == EMT_SETEROUTE) ? "add" : "del");
+ exit(1);
+ }
+ case EMT_CLREROUTE:
+ break;
+ default:
+ fprintf(stderr, "%s: exactly one of '--add', '--addin', '--replace', '--del' or '--clear' options must be specified.\n"
+ "Try %s --help' for usage information.\n"
+ , program_name, program_name);
+ exit(1);
+ }
+
+ if ((pfkey_sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0)
+ {
+ fprintf(stderr, "%s: Trouble opening PF_KEY family socket with error: "
+ , program_name);
+ switch(errno)
+ {
+ case ENOENT:
+ fprintf(stderr, "device does not exist. See FreeS/WAN installation procedure.\n");
+ break;
+ case EACCES:
+ fprintf(stderr, "access denied. ");
+ if (getuid() == 0)
+ {
+ fprintf(stderr, "Check permissions. Should be 600.\n");
+ }
+ else
+ {
+ fprintf(stderr, "You must be root to open this file.\n");
+ }
+ break;
+ case EUNATCH:
+ fprintf(stderr, "KLIPS not loaded.\n");
+ break;
+ case ENODEV:
+ fprintf(stderr, "KLIPS not loaded or enabled.\n");
+ break;
+ case EBUSY:
+ fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. "
+ "Please report as much detail as possible to development team.\n");
+ break;
+ case EINVAL:
+ fprintf(stderr, "Invalid argument, KLIPS not loaded or check kernel log messages for specifics.\n");
+ break;
+ case ENOBUFS:
+ case ENOMEM:
+ case ENFILE:
+ fprintf(stderr, "No kernel memory to allocate socket.\n");
+ break;
+ case EMFILE:
+ fprintf(stderr, "Process file table overflow.\n");
+ break;
+ case ESOCKTNOSUPPORT:
+ fprintf(stderr, "Socket type not supported.\n");
+ break;
+ case EPROTONOSUPPORT:
+ fprintf(stderr, "Protocol version not supported.\n");
+ break;
+ case EAFNOSUPPORT:
+ fprintf(stderr, "KLIPS not loaded or enabled.\n");
+ break;
+ default:
+ fprintf(stderr, "Unknown file open error %d. Please report as much detail as possible to development team.\n"
+ , errno);
+ }
+ exit(1);
+ }
+
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: PFKEYv2 socket successfully openned=%d.\n"
+ , program_name, pfkey_sock);
+ }
+
+ /* Build an SADB_X_ADDFLOW or SADB_X_DELFLOW message to send down. */
+ /* It needs <base, SA, address(SD), flow(SD), mask(SD)> minimum. */
+ pfkey_extensions_init(extensions);
+
+ error = pfkey_msg_hdr_build(&extensions[0]
+ , (action_type == EMT_SETEROUTE || action_type == EMT_REPLACEROUTE
+ || action_type == EMT_INEROUTE)? SADB_X_ADDFLOW : SADB_X_DELFLOW
+ , proto2satype(said.proto)
+ , 0
+ , ++pfkey_seq
+ , getpid()
+ );
+
+ if (error)
+ {
+ fprintf(stderr, "%s: Trouble building message header, error=%d.\n"
+ , program_name, error);
+ pfkey_extensions_free(extensions);
+ exit(1);
+ }
+
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey_msg_hdr_build successfull.\n"
+ , program_name);
+ }
+
+ switch (action_type)
+ {
+ case EMT_SETEROUTE:
+ case EMT_REPLACEROUTE:
+ case EMT_INEROUTE:
+ case EMT_CLREROUTE:
+ error = pfkey_sa_build(&extensions[SADB_EXT_SA]
+ , SADB_EXT_SA
+ , said.spi /* in network order */
+ , 0
+ , 0
+ , 0
+ , 0
+ , (action_type == EMT_CLREROUTE) ? SADB_X_SAFLAGS_CLEARFLOW : 0
+ );
+
+ if (error)
+ {
+ fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n"
+ , program_name, error);
+ pfkey_extensions_free(extensions);
+ exit(1);
+ }
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey_sa_build successful.\n"
+ , program_name);
+ }
+ default:
+ break;
+ }
+
+ switch (action_type)
+ {
+ case EMT_SETEROUTE:
+ case EMT_REPLACEROUTE:
+ case EMT_INEROUTE:
+ anyaddr(said_af, &pfkey_address_s_ska);
+ error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC]
+ , SADB_EXT_ADDRESS_SRC
+ , 0
+ , 0
+ , sockaddrof(&pfkey_address_s_ska)
+ );
+ if (error)
+ {
+ addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
+ fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n"
+ , program_name, ipaddr_txt, error);
+ pfkey_extensions_free(extensions);
+ exit(1);
+ }
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src.\n"
+ , program_name);
+ }
+
+ error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST]
+ , SADB_EXT_ADDRESS_DST
+ , 0
+ , 0
+ , sockaddrof(&said.dst)
+ );
+
+ if (error)
+ {
+ addrtot(&said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt));
+ fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n"
+ , program_name, ipaddr_txt, error);
+ pfkey_extensions_free(extensions);
+ exit(1);
+ }
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst.\n"
+ , program_name);
+ }
+ default:
+ break;
+ }
+
+ switch (action_type)
+ {
+ case EMT_SETEROUTE:
+ case EMT_REPLACEROUTE:
+ case EMT_INEROUTE:
+ case EMT_DELEROUTE:
+ networkof(&s_subnet, &pfkey_address_sflow_ska); /* src flow */
+ add_port(eroute_af, &pfkey_address_sflow_ska, src_port);
+
+ error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_FLOW]
+ , SADB_X_EXT_ADDRESS_SRC_FLOW
+ , 0
+ , 0
+ , sockaddrof(&pfkey_address_sflow_ska)
+ );
+
+ if (error)
+ {
+ addrtot(&pfkey_address_sflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
+ fprintf(stderr, "%s: Trouble building address_sflow extension (%s), error=%d.\n",
+ program_name, ipaddr_txt, error);
+ pfkey_extensions_free(extensions);
+ exit(1);
+ }
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src flow.\n"
+ , program_name);
+ }
+
+ networkof(&d_subnet, &pfkey_address_dflow_ska); /* dst flow */
+ add_port(eroute_af, &pfkey_address_dflow_ska, dst_port);
+
+ error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_FLOW]
+ , SADB_X_EXT_ADDRESS_DST_FLOW
+ , 0
+ , 0
+ , sockaddrof(&pfkey_address_dflow_ska)
+ );
+
+ if (error)
+ {
+ addrtot(&pfkey_address_dflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
+ fprintf(stderr, "%s: Trouble building address_dflow extension (%s), error=%d.\n"
+ , program_name, ipaddr_txt, error);
+ pfkey_extensions_free(extensions);
+ exit(1);
+ }
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst flow.\n"
+ , program_name);
+ }
+
+ maskof(&s_subnet, &pfkey_address_smask_ska); /* src mask */
+ add_port(eroute_af, &pfkey_address_smask_ska, src_port ? ~0:0);
+
+ error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_MASK]
+ , SADB_X_EXT_ADDRESS_SRC_MASK
+ , 0
+ , 0
+ , sockaddrof(&pfkey_address_smask_ska)
+ );
+
+ if (error)
+ {
+ addrtot(&pfkey_address_smask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
+ fprintf(stderr, "%s: Trouble building address_smask extension (%s), error=%d.\n"
+ , program_name, ipaddr_txt, error);
+ pfkey_extensions_free(extensions);
+ exit(1);
+ }
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src mask.\n"
+ , program_name);
+ }
+
+ maskof(&d_subnet, &pfkey_address_dmask_ska); /* dst mask */
+ add_port(eroute_af, &pfkey_address_dmask_ska, dst_port ? ~0:0);
+
+ error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_MASK]
+ , SADB_X_EXT_ADDRESS_DST_MASK
+ , 0
+ , 0
+ , sockaddrof(&pfkey_address_dmask_ska)
+ );
+
+ if (error)
+ {
+ addrtot(&pfkey_address_dmask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
+ fprintf(stderr, "%s: Trouble building address_dmask extension (%s), error=%d.\n"
+ , program_name, ipaddr_txt, error);
+ pfkey_extensions_free(extensions);
+ exit(1);
+ }
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst mask.\n"
+ , program_name);
+ }
+ }
+
+ if (transport_proto != 0)
+ {
+ error = pfkey_x_protocol_build(&extensions[SADB_X_EXT_PROTOCOL]
+ , transport_proto);
+
+ if (error)
+ {
+ fprintf(stderr, "%s: Trouble building transport protocol extension, error=%d.\n"
+ , program_name, error);
+ exit(1);
+ }
+ }
+
+ error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN);
+
+ if (error)
+ {
+ fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n"
+ , program_name, error);
+ pfkey_extensions_free(extensions);
+ pfkey_msg_free(&pfkey_msg);
+ exit(1);
+ }
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey_msg_build successful.\n"
+ , program_name);
+ }
+
+ error = write(pfkey_sock
+ , pfkey_msg
+ , pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN
+ )
+ != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
+
+ if (error)
+ {
+ fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n"
+ , program_name, error, errno);
+ pfkey_extensions_free(extensions);
+ pfkey_msg_free(&pfkey_msg);
+
+ switch (errno)
+ {
+ case EINVAL:
+ fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
+ break;
+ case ENXIO:
+ if (action_type == EMT_SETEROUTE || action_type == EMT_REPLACEROUTE)
+ {
+ fprintf(stderr, "Invalid mask.\n");
+ break;
+ }
+ if (action_type == EMT_DELEROUTE)
+ {
+ fprintf(stderr, "Mask not found.\n");
+ break;
+ }
+ case EFAULT:
+ if (action_type == EMT_SETEROUTE || action_type == EMT_REPLACEROUTE)
+ {
+ fprintf(stderr, "Invalid address.\n");
+ break;
+ }
+ if (action_type == EMT_DELEROUTE)
+ {
+ fprintf(stderr, "Address not found.\n");
+ break;
+ }
+ case EACCES:
+ fprintf(stderr, "access denied. ");
+ if (getuid() == 0)
+ {
+ fprintf(stderr, "Check permissions. Should be 600.\n");
+ }
+ else
+ {
+ fprintf(stderr, "You must be root to open this file.\n");
+ }
+ break;
+ case EUNATCH:
+ fprintf(stderr, "KLIPS not loaded.\n");
+ break;
+ case EBUSY:
+ fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. "
+ "Please report as much detail as possible to development team.\n");
+ break;
+ case ENODEV:
+ fprintf(stderr, "KLIPS not loaded or enabled.\n");
+ fprintf(stderr, "No device?!?\n");
+ break;
+ case ENOBUFS:
+ fprintf(stderr, "No kernel memory to allocate SA.\n");
+ break;
+ case ESOCKTNOSUPPORT:
+ fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n");
+ break;
+ case EEXIST:
+ fprintf(stderr, "eroute already in use. Delete old one first.\n");
+ break;
+ case ENOENT:
+ if (action_type == EMT_INEROUTE)
+ {
+ fprintf(stderr, "non-existant IPIP SA.\n");
+ break;
+ }
+ fprintf(stderr, "eroute doesn't exist. Can't delete.\n");
+ break;
+ case ENOSPC:
+ fprintf(stderr, "no room in kernel SAref table. Cannot process request.\n");
+ break;
+ case ESPIPE:
+ fprintf(stderr, "kernel SAref table internal error. Cannot process request.\n");
+ break;
+ default:
+ fprintf(stderr, "Unknown socket write error %d. Please report as much detail as possible to development team.\n"
+ , errno);
+ }
+/* fprintf(stderr, "%s: socket write returned errno %d\n",
+ program_name, errno);*/
+ exit(1);
+ }
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: pfkey write successful.\n"
+ , program_name);
+ }
+
+ if (pfkey_msg)
+ {
+ pfkey_extensions_free(extensions);
+ pfkey_msg_free(&pfkey_msg);
+ }
+
+ (void) close(pfkey_sock); /* close the socket */
+
+ if (debug)
+ {
+ fprintf(stdout, "%s: DEBUG: write ok\n", program_name);
+ }
+
+ exit(0);
+}