2006-04-28 07:14:48 +00:00
|
|
|
/* pfkey interface to the kernel's IPsec mechanism
|
|
|
|
* Copyright (C) 1997 Angelos D. Keromytis.
|
|
|
|
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
|
|
|
|
* Copyright (C) 2003 Herbert Xu.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef KLIPS
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <sys/select.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/queue.h>
|
|
|
|
|
|
|
|
#include <freeswan.h>
|
|
|
|
#include <pfkeyv2.h>
|
|
|
|
#include <pfkey.h>
|
|
|
|
|
|
|
|
#include "constants.h"
|
|
|
|
#include "defs.h"
|
|
|
|
#include "kernel.h"
|
|
|
|
#include "kernel_pfkey.h"
|
|
|
|
#include "log.h"
|
2009-04-19 19:16:09 +00:00
|
|
|
#include "whack.h" /* for RC_LOG_SERIOUS */
|
2006-04-28 07:14:48 +00:00
|
|
|
#include "demux.h"
|
|
|
|
#include "nat_traversal.h"
|
|
|
|
#include "alg_info.h"
|
|
|
|
#include "kernel_alg.h"
|
|
|
|
|
|
|
|
|
|
|
|
static int pfkeyfd = NULL_FD;
|
|
|
|
|
|
|
|
typedef u_int32_t pfkey_seq_t;
|
2009-04-19 19:16:09 +00:00
|
|
|
static pfkey_seq_t pfkey_seq = 0; /* sequence number for our PF_KEY messages */
|
2006-04-28 07:14:48 +00:00
|
|
|
|
|
|
|
static pid_t pid;
|
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */
|
2006-04-28 07:14:48 +00:00
|
|
|
|
|
|
|
static sparse_names pfkey_type_names = {
|
2009-04-19 19:16:09 +00:00
|
|
|
NE(SADB_RESERVED),
|
|
|
|
NE(SADB_GETSPI),
|
|
|
|
NE(SADB_UPDATE),
|
|
|
|
NE(SADB_ADD),
|
|
|
|
NE(SADB_DELETE),
|
|
|
|
NE(SADB_GET),
|
|
|
|
NE(SADB_ACQUIRE),
|
|
|
|
NE(SADB_REGISTER),
|
|
|
|
NE(SADB_EXPIRE),
|
|
|
|
NE(SADB_FLUSH),
|
|
|
|
NE(SADB_DUMP),
|
|
|
|
NE(SADB_X_PROMISC),
|
|
|
|
NE(SADB_X_PCHANGE),
|
|
|
|
NE(SADB_X_GRPSA),
|
|
|
|
NE(SADB_X_ADDFLOW),
|
|
|
|
NE(SADB_X_DELFLOW),
|
|
|
|
NE(SADB_X_DEBUG),
|
|
|
|
NE(SADB_X_NAT_T_NEW_MAPPING),
|
2009-09-04 11:46:09 +00:00
|
|
|
NE(SADB_MAX),
|
2009-04-19 19:16:09 +00:00
|
|
|
{ 0, sparse_end }
|
2006-04-28 07:14:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef NEVER /* not needed yet */
|
|
|
|
static sparse_names pfkey_ext_names = {
|
2009-04-19 19:16:09 +00:00
|
|
|
NE(SADB_EXT_RESERVED),
|
|
|
|
NE(SADB_EXT_SA),
|
|
|
|
NE(SADB_EXT_LIFETIME_CURRENT),
|
|
|
|
NE(SADB_EXT_LIFETIME_HARD),
|
|
|
|
NE(SADB_EXT_LIFETIME_SOFT),
|
|
|
|
NE(SADB_EXT_ADDRESS_SRC),
|
|
|
|
NE(SADB_EXT_ADDRESS_DST),
|
|
|
|
NE(SADB_EXT_ADDRESS_PROXY),
|
|
|
|
NE(SADB_EXT_KEY_AUTH),
|
|
|
|
NE(SADB_EXT_KEY_ENCRYPT),
|
|
|
|
NE(SADB_EXT_IDENTITY_SRC),
|
|
|
|
NE(SADB_EXT_IDENTITY_DST),
|
|
|
|
NE(SADB_EXT_SENSITIVITY),
|
|
|
|
NE(SADB_EXT_PROPOSAL),
|
|
|
|
NE(SADB_EXT_SUPPORTED_AUTH),
|
|
|
|
NE(SADB_EXT_SUPPORTED_ENCRYPT),
|
|
|
|
NE(SADB_EXT_SPIRANGE),
|
|
|
|
NE(SADB_X_EXT_KMPRIVATE),
|
|
|
|
NE(SADB_X_EXT_SATYPE2),
|
|
|
|
NE(SADB_X_EXT_SA2),
|
|
|
|
NE(SADB_X_EXT_ADDRESS_DST2),
|
|
|
|
NE(SADB_X_EXT_ADDRESS_SRC_FLOW),
|
|
|
|
NE(SADB_X_EXT_ADDRESS_DST_FLOW),
|
|
|
|
NE(SADB_X_EXT_ADDRESS_SRC_MASK),
|
|
|
|
NE(SADB_X_EXT_ADDRESS_DST_MASK),
|
|
|
|
NE(SADB_X_EXT_DEBUG),
|
|
|
|
{ 0, sparse_end }
|
2006-04-28 07:14:48 +00:00
|
|
|
};
|
|
|
|
#endif /* NEVER */
|
|
|
|
|
|
|
|
#undef NE
|
|
|
|
|
|
|
|
void
|
|
|
|
init_pfkey(void)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
pid = getpid();
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
/* open PF_KEY socket */
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
pfkeyfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (pfkeyfd == -1)
|
|
|
|
exit_log_errno((e, "socket() in init_pfkeyfd()"));
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
#ifdef NEVER /* apparently unsupported! */
|
|
|
|
if (fcntl(pfkeyfd, F_SETFL, O_NONBLOCK) != 0)
|
|
|
|
exit_log_errno((e, "fcntl(O_NONBLOCK) in init_pfkeyfd()"));
|
2006-04-28 07:14:48 +00:00
|
|
|
#endif
|
2009-04-19 19:16:09 +00:00
|
|
|
if (fcntl(pfkeyfd, F_SETFD, FD_CLOEXEC) != 0)
|
|
|
|
exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_pfkeyfd()"));
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
DBG(DBG_KLIPS,
|
|
|
|
DBG_log("process %u listening for PF_KEY_V2 on file descriptor %d", (unsigned)pid, pfkeyfd));
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Kinds of PF_KEY message from the kernel:
|
|
|
|
* - response to a request from us
|
|
|
|
* + ACK/NAK
|
|
|
|
* + Register: indicates transforms supported by kernel
|
|
|
|
* + SPI requested by getspi
|
|
|
|
* - Acquire, requesting us to deal with trapped clear packet
|
|
|
|
* - expiration of of one of our SAs
|
|
|
|
* - messages to other processes
|
|
|
|
*
|
|
|
|
* To minimize the effect on the event-driven structure of Pluto,
|
|
|
|
* responses are dealt with synchronously. We hope that the Kernel
|
|
|
|
* produces them synchronously. We must "read ahead" in the PF_KEY
|
|
|
|
* stream, saving Acquire and Expiry messages that are encountered.
|
|
|
|
* We ignore messages to other processes.
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef union {
|
2009-04-19 19:16:09 +00:00
|
|
|
unsigned char bytes[PFKEYv2_MAX_MSGSIZE];
|
|
|
|
struct sadb_msg msg;
|
|
|
|
} pfkey_buf;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
|
|
|
/* queue of unprocessed PF_KEY messages input from kernel
|
|
|
|
* Note that the pfkey_buf may be partly allocated, reflecting
|
|
|
|
* the variable length nature of the messages. So the link field
|
|
|
|
* must come first.
|
|
|
|
*/
|
|
|
|
typedef struct pfkey_item {
|
2009-04-19 19:16:09 +00:00
|
|
|
struct pfkey_item *next;
|
|
|
|
pfkey_buf buf;
|
|
|
|
} pfkey_item;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
static pfkey_item *pfkey_iq_head = NULL; /* oldest */
|
|
|
|
static pfkey_item *pfkey_iq_tail; /* youngest */
|
2006-04-28 07:14:48 +00:00
|
|
|
|
|
|
|
static bool
|
|
|
|
pfkey_input_ready(void)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
fd_set readfds;
|
|
|
|
int ndes;
|
|
|
|
struct timeval tm;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
tm.tv_sec = 0; /* don't wait at all */
|
|
|
|
tm.tv_usec = 0;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
FD_ZERO(&readfds); /* we only care about pfkeyfd */
|
|
|
|
FD_SET(pfkeyfd, &readfds);
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
do {
|
|
|
|
ndes = select(pfkeyfd + 1, &readfds, NULL, NULL, &tm);
|
|
|
|
} while (ndes == -1 && errno == EINTR);
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (ndes < 0)
|
|
|
|
{
|
|
|
|
log_errno((e, "select() failed in pfkey_get()"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (ndes == 0)
|
|
|
|
return FALSE; /* nothing to read */
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
passert(ndes == 1 && FD_ISSET(pfkeyfd, &readfds));
|
|
|
|
return TRUE;
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* get a PF_KEY message from kernel.
|
|
|
|
* Returns TRUE is message found, FALSE if no message pending,
|
|
|
|
* and aborts or keeps trying when an error is encountered.
|
|
|
|
* The only validation of the message is that the message length
|
|
|
|
* received matches that in the message header, and that the message
|
|
|
|
* is for this process.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
pfkey_get(pfkey_buf *buf)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* len must be less than PFKEYv2_MAX_MSGSIZE,
|
|
|
|
* so it should fit in an int. We use this fact when printing it.
|
|
|
|
*/
|
|
|
|
ssize_t len;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (!pfkey_input_ready())
|
|
|
|
return FALSE;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
len = read(pfkeyfd, buf->bytes, sizeof(buf->bytes));
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (len < 0)
|
|
|
|
{
|
|
|
|
if (errno == EAGAIN)
|
|
|
|
return FALSE;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
log_errno((e, "read() failed in pfkey_get()"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if ((size_t) len < sizeof(buf->msg))
|
|
|
|
{
|
|
|
|
plog("pfkey_get read truncated PF_KEY message: %d bytes; ignoring message"
|
|
|
|
, (int) len);
|
|
|
|
}
|
|
|
|
else if ((size_t) len != buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN)
|
|
|
|
{
|
|
|
|
plog("pfkey_get read PF_KEY message with length %d that doesn't equal sadb_msg_len %u * %u; ignoring message"
|
|
|
|
, (int) len
|
|
|
|
, (unsigned) buf->msg.sadb_msg_len
|
|
|
|
, (unsigned) IPSEC_PFKEYv2_ALIGN);
|
|
|
|
}
|
|
|
|
else if (!(buf->msg.sadb_msg_pid == (unsigned)pid
|
|
|
|
|| (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_ACQUIRE)
|
|
|
|
|| (buf->msg.sadb_msg_type == SADB_REGISTER)
|
|
|
|
|| (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING)))
|
|
|
|
{
|
|
|
|
/* not for us: ignore */
|
|
|
|
DBG(DBG_KLIPS,
|
|
|
|
DBG_log("pfkey_get: ignoring PF_KEY %s message %u for process %u"
|
|
|
|
, sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
|
|
|
|
, buf->msg.sadb_msg_seq
|
|
|
|
, buf->msg.sadb_msg_pid));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG(DBG_KLIPS,
|
|
|
|
DBG_log("pfkey_get: %s message %u"
|
|
|
|
, sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
|
|
|
|
, buf->msg.sadb_msg_seq));
|
|
|
|
return TRUE;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get a response to a specific message */
|
|
|
|
static bool
|
|
|
|
pfkey_get_response(pfkey_buf *buf, pfkey_seq_t seq)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
while (pfkey_get(buf))
|
2006-04-28 07:14:48 +00:00
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
if (buf->msg.sadb_msg_pid == (unsigned)pid
|
|
|
|
&& buf->msg.sadb_msg_seq == seq)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Not for us: queue it. */
|
|
|
|
size_t bl = buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN;
|
|
|
|
pfkey_item *it = malloc(offsetof(pfkey_item, buf) + bl);
|
|
|
|
|
|
|
|
memcpy(&it->buf, buf, bl);
|
|
|
|
|
|
|
|
it->next = NULL;
|
|
|
|
if (pfkey_iq_head == NULL)
|
|
|
|
{
|
|
|
|
pfkey_iq_head = it;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pfkey_iq_tail->next = it;
|
|
|
|
}
|
|
|
|
pfkey_iq_tail = it;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
2009-04-19 19:16:09 +00:00
|
|
|
return FALSE;
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Process a SADB_REGISTER message from the kernel.
|
|
|
|
* This will be a response to one of ours, but it may be asynchronous
|
|
|
|
* (if kernel modules are loaded and unloaded).
|
|
|
|
* Some sanity checking has already been performed.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
klips_pfkey_register_response(const struct sadb_msg *msg)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
/* Find out what the kernel can support.
|
|
|
|
* In fact, the only question at the moment
|
|
|
|
* is whether it can support IPcomp.
|
|
|
|
* So we ignore the rest.
|
|
|
|
* ??? we really should pay attention to what transforms are supported.
|
|
|
|
*/
|
|
|
|
switch (msg->sadb_msg_satype)
|
|
|
|
{
|
|
|
|
case SADB_SATYPE_AH:
|
|
|
|
break;
|
|
|
|
case SADB_SATYPE_ESP:
|
2006-04-28 07:14:48 +00:00
|
|
|
#ifndef NO_KERNEL_ALG
|
2009-04-19 19:16:09 +00:00
|
|
|
kernel_alg_register_pfkey(msg, sizeof (pfkey_buf));
|
2006-04-28 07:14:48 +00:00
|
|
|
#endif
|
2009-04-19 19:16:09 +00:00
|
|
|
break;
|
|
|
|
case SADB_X_SATYPE_COMP:
|
|
|
|
/* ??? There ought to be an extension to list the
|
|
|
|
* supported algorithms, but RFC 2367 doesn't
|
|
|
|
* list one for IPcomp. KLIPS uses SADB_X_CALG_DEFLATE.
|
|
|
|
* Since we only implement deflate, we'll assume this.
|
|
|
|
*/
|
|
|
|
can_do_IPcomp = TRUE;
|
|
|
|
break;
|
|
|
|
case SADB_X_SATYPE_IPIP:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Processs a SADB_ACQUIRE message from KLIPS.
|
|
|
|
* Try to build an opportunistic connection!
|
|
|
|
* See RFC 2367 "PF_KEY Key Management API, Version 2" 3.1.6
|
|
|
|
* <base, address(SD), (address(P)), (identity(SD),) (sensitivity,) proposal>
|
|
|
|
* - extensions for source and data IP addresses
|
|
|
|
* - optional extensions for identity [not useful for us?]
|
|
|
|
* - optional extension for sensitivity [not useful for us?]
|
|
|
|
* - expension for proposal [not useful for us?]
|
|
|
|
*
|
|
|
|
* ??? We must use the sequence number in creating an SA.
|
|
|
|
* We actually need to create up to 4 SAs each way. Which one?
|
|
|
|
* I guess it depends on the protocol present in the sadb_msg_satype.
|
|
|
|
* For now, we'll ignore this requirement.
|
|
|
|
*
|
|
|
|
* ??? We need some mechanism to make sure that multiple ACQUIRE messages
|
|
|
|
* don't cause a whole bunch of redundant negotiations.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
process_pfkey_acquire(pfkey_buf *buf, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];
|
|
|
|
struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];
|
|
|
|
int src_proto = srcx->sadb_address_proto;
|
|
|
|
int dst_proto = dstx->sadb_address_proto;
|
|
|
|
ip_address *src = (ip_address*)&srcx[1];
|
|
|
|
ip_address *dst = (ip_address*)&dstx[1];
|
|
|
|
ip_subnet ours, his;
|
|
|
|
err_t ugh = NULL;
|
|
|
|
|
|
|
|
/* assumption: we're only catching our own outgoing packets
|
|
|
|
* so source is our end and destination is the other end.
|
|
|
|
* Verifying this is not actually convenient.
|
|
|
|
*
|
|
|
|
* This stylized control structure yields a complaint or
|
|
|
|
* desired results. For compactness, a pointer value is
|
|
|
|
* treated as a boolean. Logically, the structure is:
|
|
|
|
* keep going as long as things are OK.
|
|
|
|
*/
|
|
|
|
if (buf->msg.sadb_msg_pid == 0 /* we only wish to hear from kernel */
|
|
|
|
&& !(ugh = src_proto == dst_proto? NULL : "src and dst protocols differ")
|
|
|
|
&& !(ugh = addrtypeof(src) == addrtypeof(dst)? NULL : "conflicting address types")
|
|
|
|
&& !(ugh = addrtosubnet(src, &ours))
|
|
|
|
&& !(ugh = addrtosubnet(dst, &his)))
|
|
|
|
record_and_initiate_opportunistic(&ours, &his, src_proto, "%acquire");
|
|
|
|
|
|
|
|
if (ugh != NULL)
|
|
|
|
plog("SADB_ACQUIRE message from KLIPS malformed: %s", ugh);
|
2006-04-28 07:14:48 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle PF_KEY messages from the kernel that are not dealt with
|
|
|
|
* synchronously. In other words, all but responses to PF_KEY messages
|
|
|
|
* that we sent.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
pfkey_async(pfkey_buf *buf)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
struct sadb_ext *extensions[SADB_EXT_MAX + 1];
|
|
|
|
|
|
|
|
if (pfkey_msg_parse(&buf->msg, NULL, extensions, EXT_BITS_OUT))
|
2006-04-28 07:14:48 +00:00
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
plog("pfkey_async:"
|
|
|
|
" unparseable PF_KEY message:"
|
|
|
|
" %s len=%d, errno=%d, seq=%d, pid=%d; message ignored"
|
|
|
|
, sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
|
|
|
|
, buf->msg.sadb_msg_len
|
|
|
|
, buf->msg.sadb_msg_errno
|
|
|
|
, buf->msg.sadb_msg_seq
|
|
|
|
, buf->msg.sadb_msg_pid);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG(DBG_CONTROL | DBG_KLIPS, DBG_log("pfkey_async:"
|
|
|
|
" %s len=%u, errno=%u, satype=%u, seq=%u, pid=%u"
|
|
|
|
, sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
|
|
|
|
, buf->msg.sadb_msg_len
|
|
|
|
, buf->msg.sadb_msg_errno
|
|
|
|
, buf->msg.sadb_msg_satype
|
|
|
|
, buf->msg.sadb_msg_seq
|
|
|
|
, buf->msg.sadb_msg_pid));
|
|
|
|
|
|
|
|
switch (buf->msg.sadb_msg_type)
|
|
|
|
{
|
|
|
|
case SADB_REGISTER:
|
|
|
|
kernel_ops->pfkey_register_response(&buf->msg);
|
|
|
|
break;
|
|
|
|
case SADB_ACQUIRE:
|
|
|
|
/* to simulate loss of ACQUIRE, delete this call */
|
|
|
|
process_pfkey_acquire(buf, extensions);
|
|
|
|
break;
|
|
|
|
case SADB_X_NAT_T_NEW_MAPPING:
|
|
|
|
process_pfkey_nat_t_new_mapping(&(buf->msg), extensions);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* ignored */
|
|
|
|
break;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* asynchronous messages from our queue */
|
|
|
|
static void
|
|
|
|
pfkey_dequeue(void)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
while (pfkey_iq_head != NULL)
|
|
|
|
{
|
|
|
|
pfkey_item *it = pfkey_iq_head;
|
|
|
|
|
|
|
|
pfkey_async(&it->buf);
|
|
|
|
pfkey_iq_head = it->next;
|
|
|
|
free(it);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle any orphaned holds, but only if no pfkey input is pending.
|
|
|
|
* For each, we initiate Opportunistic.
|
|
|
|
* note: we don't need to advance the pointer because
|
|
|
|
* record_and_initiate_opportunistic will remove the current
|
|
|
|
* record each time we call it.
|
|
|
|
*/
|
|
|
|
while (orphaned_holds != NULL && !pfkey_input_ready())
|
|
|
|
record_and_initiate_opportunistic(&orphaned_holds->ours
|
|
|
|
, &orphaned_holds->his
|
|
|
|
, orphaned_holds->transport_proto
|
|
|
|
, "%hold found-pfkey");
|
2006-04-28 07:14:48 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* asynchronous messages directly from PF_KEY socket */
|
|
|
|
static void
|
|
|
|
pfkey_event(void)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
pfkey_buf buf;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (pfkey_get(&buf))
|
|
|
|
pfkey_async(&buf);
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
pfkey_build(int error
|
|
|
|
, const char *description
|
|
|
|
, const char *text_said
|
|
|
|
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
if (error == 0)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
loglog(RC_LOG_SERIOUS, "building of %s %s failed, code %d"
|
|
|
|
, description, text_said, error);
|
|
|
|
pfkey_extensions_free(extensions);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* pfkey_extensions_init + pfkey_build + pfkey_msg_hdr_build */
|
|
|
|
static bool
|
|
|
|
pfkey_msg_start(u_int8_t msg_type
|
|
|
|
, u_int8_t satype
|
|
|
|
, const char *description
|
|
|
|
, const char *text_said
|
|
|
|
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
pfkey_extensions_init(extensions);
|
|
|
|
return pfkey_build(pfkey_msg_hdr_build(&extensions[0], msg_type
|
|
|
|
, satype, 0, ++pfkey_seq, pid)
|
|
|
|
, description, text_said, extensions);
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* pfkey_build + pfkey_address_build */
|
|
|
|
static bool
|
|
|
|
pfkeyext_address(u_int16_t exttype
|
|
|
|
, const ip_address *address
|
|
|
|
, const char *description
|
|
|
|
, const char *text_said
|
|
|
|
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
/* the following variable is only needed to silence
|
|
|
|
* a warning caused by the fact that the argument
|
|
|
|
* to sockaddrof is NOT pointer to const!
|
|
|
|
*/
|
|
|
|
ip_address t = *address;
|
|
|
|
|
|
|
|
return pfkey_build(pfkey_address_build(extensions + exttype
|
|
|
|
, exttype, 0, 0, sockaddrof(&t))
|
|
|
|
, description, text_said, extensions);
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* pfkey_build + pfkey_x_protocol_build */
|
|
|
|
static bool
|
|
|
|
pfkeyext_protocol(int transport_proto
|
|
|
|
, const char *description
|
|
|
|
, const char *text_said
|
|
|
|
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
|
|
|
|
{
|
2009-09-04 11:46:09 +00:00
|
|
|
return (transport_proto == 0)? TRUE
|
2009-04-19 19:16:09 +00:00
|
|
|
: pfkey_build(
|
|
|
|
pfkey_x_protocol_build(extensions + SADB_X_EXT_PROTOCOL, transport_proto)
|
|
|
|
, description, text_said, extensions);
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Finish (building, sending, accepting response for) PF_KEY message.
|
|
|
|
* If response isn't NULL, the response from the kernel will be
|
|
|
|
* placed there (and its errno field will not be examined).
|
|
|
|
* Returns TRUE iff all appears well.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
finish_pfkey_msg(struct sadb_ext *extensions[SADB_EXT_MAX + 1]
|
|
|
|
, const char *description
|
|
|
|
, const char *text_said
|
|
|
|
, pfkey_buf *response)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
struct sadb_msg *pfkey_msg;
|
|
|
|
bool success = TRUE;
|
|
|
|
int error;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN);
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (error != 0)
|
2006-04-28 07:14:48 +00:00
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
loglog(RC_LOG_SERIOUS, "pfkey_msg_build of %s %s failed, code %d"
|
|
|
|
, description, text_said, error);
|
2006-04-28 07:14:48 +00:00
|
|
|
success = FALSE;
|
2009-04-19 19:16:09 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
size_t len = pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
DBG(DBG_KLIPS,
|
|
|
|
DBG_log("finish_pfkey_msg: %s message %u for %s %s"
|
|
|
|
, sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
|
|
|
|
, pfkey_msg->sadb_msg_seq
|
|
|
|
, description, text_said);
|
|
|
|
DBG_dump(NULL, (void *) pfkey_msg, len));
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (!no_klips)
|
2006-04-28 07:14:48 +00:00
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
ssize_t r = write(pfkeyfd, pfkey_msg, len);
|
|
|
|
|
|
|
|
if (r != (ssize_t)len)
|
|
|
|
{
|
|
|
|
if (r < 0)
|
|
|
|
{
|
|
|
|
log_errno((e
|
|
|
|
, "pfkey write() of %s message %u"
|
|
|
|
" for %s %s failed"
|
|
|
|
, sparse_val_show(pfkey_type_names
|
|
|
|
, pfkey_msg->sadb_msg_type)
|
|
|
|
, pfkey_msg->sadb_msg_seq
|
|
|
|
, description, text_said));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
loglog(RC_LOG_SERIOUS
|
|
|
|
, "ERROR: pfkey write() of %s message %u"
|
|
|
|
" for %s %s truncated: %ld instead of %ld"
|
|
|
|
, sparse_val_show(pfkey_type_names
|
|
|
|
, pfkey_msg->sadb_msg_type)
|
|
|
|
, pfkey_msg->sadb_msg_seq
|
|
|
|
, description, text_said
|
|
|
|
, (long)r, (long)len);
|
|
|
|
}
|
|
|
|
success = FALSE;
|
|
|
|
|
|
|
|
/* if we were compiled with debugging, but we haven't already
|
|
|
|
* dumped the KLIPS command, do so.
|
|
|
|
*/
|
|
|
|
#ifdef DEBUG
|
|
|
|
if ((cur_debugging & DBG_KLIPS) == 0)
|
|
|
|
DBG_dump(NULL, (void *) pfkey_msg, len);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Check response from KLIPS.
|
|
|
|
* It ought to be an echo, perhaps with additional info.
|
|
|
|
* If the caller wants it, response will point to space.
|
|
|
|
*/
|
|
|
|
pfkey_buf b;
|
|
|
|
pfkey_buf *bp = response != NULL? response : &b;
|
|
|
|
|
|
|
|
if (!pfkey_get_response(bp, ((struct sadb_msg *) extensions[0])->sadb_msg_seq))
|
|
|
|
{
|
|
|
|
loglog(RC_LOG_SERIOUS
|
|
|
|
, "ERROR: no response to our PF_KEY %s message for %s %s"
|
|
|
|
, sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
|
|
|
|
, description, text_said);
|
|
|
|
success = FALSE;
|
|
|
|
}
|
|
|
|
else if (pfkey_msg->sadb_msg_type != bp->msg.sadb_msg_type)
|
|
|
|
{
|
|
|
|
loglog(RC_LOG_SERIOUS
|
|
|
|
, "FreeS/WAN ERROR: response to our PF_KEY %s message for %s %s was of wrong type (%s)"
|
|
|
|
, sparse_name(pfkey_type_names, pfkey_msg->sadb_msg_type)
|
|
|
|
, description, text_said
|
|
|
|
, sparse_val_show(pfkey_type_names, bp->msg.sadb_msg_type));
|
|
|
|
success = FALSE;
|
|
|
|
}
|
|
|
|
else if (response == NULL && bp->msg.sadb_msg_errno != 0)
|
|
|
|
{
|
|
|
|
/* KLIPS is signalling a problem */
|
|
|
|
loglog(RC_LOG_SERIOUS
|
|
|
|
, "ERROR: PF_KEY %s response for %s %s included errno %u: %s"
|
|
|
|
, sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
|
|
|
|
, description, text_said
|
|
|
|
, (unsigned) bp->msg.sadb_msg_errno
|
|
|
|
, strerror(bp->msg.sadb_msg_errno));
|
|
|
|
success = FALSE;
|
|
|
|
}
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
/* all paths must exit this way to free resources */
|
|
|
|
pfkey_extensions_free(extensions);
|
|
|
|
pfkey_msg_free(&pfkey_msg);
|
|
|
|
return success;
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* register SA types that can be negotiated */
|
|
|
|
void
|
|
|
|
pfkey_register_proto(unsigned satype, const char *satypename)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
struct sadb_ext *extensions[SADB_EXT_MAX + 1];
|
|
|
|
pfkey_buf pfb;
|
|
|
|
|
|
|
|
if (!(pfkey_msg_start(SADB_REGISTER
|
|
|
|
, satype
|
|
|
|
, satypename, NULL, extensions)
|
|
|
|
&& finish_pfkey_msg(extensions, satypename, "", &pfb)))
|
|
|
|
{
|
|
|
|
/* ??? should this be loglog */
|
|
|
|
plog("no KLIPS support for %s", satypename);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kernel_ops->pfkey_register_response(&pfb.msg);
|
|
|
|
DBG(DBG_KLIPS,
|
|
|
|
DBG_log("%s registered with kernel.", satypename));
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
klips_pfkey_register(void)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
pfkey_register_proto(SADB_SATYPE_AH, "AH");
|
|
|
|
pfkey_register_proto(SADB_SATYPE_ESP, "ESP");
|
|
|
|
can_do_IPcomp = FALSE; /* until we get a response from KLIPS */
|
|
|
|
pfkey_register_proto(SADB_X_SATYPE_COMP, "IPCOMP");
|
|
|
|
pfkey_register_proto(SADB_X_SATYPE_IPIP, "IPIP");
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
pfkey_raw_eroute(const ip_address *this_host
|
2009-04-19 19:16:09 +00:00
|
|
|
, const ip_subnet *this_client
|
|
|
|
, const ip_address *that_host
|
|
|
|
, const ip_subnet *that_client
|
|
|
|
, ipsec_spi_t spi
|
|
|
|
, unsigned int satype
|
|
|
|
, unsigned int transport_proto
|
|
|
|
, const struct pfkey_proto_info *proto_info UNUSED
|
|
|
|
, time_t use_lifetime UNUSED
|
|
|
|
, unsigned int op
|
|
|
|
, const char *text_said)
|
2006-04-28 07:14:48 +00:00
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
struct sadb_ext *extensions[SADB_EXT_MAX + 1];
|
|
|
|
ip_address
|
|
|
|
sflow_ska,
|
|
|
|
dflow_ska,
|
|
|
|
smask_ska,
|
|
|
|
dmask_ska;
|
|
|
|
int sport = ntohs(portof(&this_client->addr));
|
|
|
|
int dport = ntohs(portof(&that_client->addr));
|
|
|
|
|
|
|
|
networkof(this_client, &sflow_ska);
|
|
|
|
maskof(this_client, &smask_ska);
|
|
|
|
setportof(sport ? ~0:0, &smask_ska);
|
|
|
|
|
|
|
|
networkof(that_client, &dflow_ska);
|
|
|
|
maskof(that_client, &dmask_ska);
|
|
|
|
setportof(dport ? ~0:0, &dmask_ska);
|
|
|
|
|
|
|
|
if (!pfkey_msg_start(op & ERO_MASK, satype
|
|
|
|
, "pfkey_msg_hdr flow", text_said, extensions))
|
2006-04-28 07:14:48 +00:00
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
return FALSE;
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (op != ERO_DELETE)
|
|
|
|
{
|
|
|
|
if (!(pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
|
|
|
|
, SADB_EXT_SA
|
|
|
|
, spi /* in network order */
|
|
|
|
, 0, 0, 0, 0, op >> ERO_FLAG_SHIFT)
|
|
|
|
, "pfkey_sa add flow", text_said, extensions)
|
|
|
|
|
|
|
|
&& pfkeyext_address(SADB_EXT_ADDRESS_SRC, this_host
|
|
|
|
, "pfkey_addr_s add flow", text_said, extensions)
|
|
|
|
|
|
|
|
&& pfkeyext_address(SADB_EXT_ADDRESS_DST, that_host
|
|
|
|
, "pfkey_addr_d add flow", text_said
|
|
|
|
, extensions)))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_FLOW, &sflow_ska
|
|
|
|
, "pfkey_addr_sflow", text_said, extensions))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_FLOW, &dflow_ska
|
|
|
|
, "pfkey_addr_dflow", text_said, extensions))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_MASK, &smask_ska
|
|
|
|
, "pfkey_addr_smask", text_said, extensions))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_MASK, &dmask_ska
|
|
|
|
, "pfkey_addr_dmask", text_said, extensions))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pfkeyext_protocol(transport_proto
|
|
|
|
, "pfkey_x_protocol", text_said, extensions))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
return finish_pfkey_msg(extensions, "flow", text_said, NULL);
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
pfkey_add_sa(const struct kernel_sa *sa, bool replace)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
struct sadb_ext *extensions[SADB_EXT_MAX + 1];
|
|
|
|
|
|
|
|
return pfkey_msg_start(replace ? SADB_UPDATE : SADB_ADD, sa->satype
|
|
|
|
, "pfkey_msg_hdr Add SA", sa->text_said, extensions)
|
|
|
|
|
|
|
|
&& pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
|
|
|
|
, SADB_EXT_SA
|
|
|
|
, sa->spi /* in network order */
|
|
|
|
, sa->replay_window, SADB_SASTATE_MATURE
|
|
|
|
, sa->authalg, sa->encalg ? sa->encalg: sa->compalg, 0)
|
|
|
|
, "pfkey_sa Add SA", sa->text_said, extensions)
|
|
|
|
|
|
|
|
&& pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src
|
|
|
|
, "pfkey_addr_s Add SA", sa->text_said, extensions)
|
|
|
|
|
|
|
|
&& pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst
|
|
|
|
, "pfkey_addr_d Add SA", sa->text_said, extensions)
|
|
|
|
|
|
|
|
&& (sa->authkeylen == 0
|
|
|
|
|| pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH]
|
|
|
|
, SADB_EXT_KEY_AUTH, sa->authkeylen * BITS_PER_BYTE
|
|
|
|
, sa->authkey)
|
|
|
|
, "pfkey_key_a Add SA", sa->text_said, extensions))
|
|
|
|
|
|
|
|
&& (sa->enckeylen == 0
|
|
|
|
|| pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT]
|
|
|
|
, SADB_EXT_KEY_ENCRYPT, sa->enckeylen * BITS_PER_BYTE
|
|
|
|
, sa->enckey)
|
|
|
|
, "pfkey_key_e Add SA", sa->text_said, extensions))
|
|
|
|
|
|
|
|
&& (sa->natt_type == 0
|
|
|
|
|| pfkey_build(pfkey_x_nat_t_type_build(
|
|
|
|
&extensions[SADB_X_EXT_NAT_T_TYPE], sa->natt_type),
|
|
|
|
"pfkey_nat_t_type Add ESP SA", sa->text_said, extensions))
|
|
|
|
&& (sa->natt_sport == 0
|
|
|
|
|| pfkey_build(pfkey_x_nat_t_port_build(
|
|
|
|
&extensions[SADB_X_EXT_NAT_T_SPORT], SADB_X_EXT_NAT_T_SPORT,
|
|
|
|
sa->natt_sport), "pfkey_nat_t_sport Add ESP SA", sa->text_said,
|
|
|
|
extensions))
|
|
|
|
&& (sa->natt_dport == 0
|
|
|
|
|| pfkey_build(pfkey_x_nat_t_port_build(
|
|
|
|
&extensions[SADB_X_EXT_NAT_T_DPORT], SADB_X_EXT_NAT_T_DPORT,
|
|
|
|
sa->natt_dport), "pfkey_nat_t_dport Add ESP SA", sa->text_said,
|
|
|
|
extensions))
|
|
|
|
&& (sa->natt_type == 0 || isanyaddr(sa->natt_oa)
|
|
|
|
|| pfkeyext_address(SADB_X_EXT_NAT_T_OA, sa->natt_oa
|
|
|
|
, "pfkey_nat_t_oa Add ESP SA", sa->text_said, extensions))
|
|
|
|
|
|
|
|
&& finish_pfkey_msg(extensions, "Add SA", sa->text_said, NULL);
|
2006-07-07 05:50:02 +00:00
|
|
|
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
pfkey_grp_sa(const struct kernel_sa *sa0, const struct kernel_sa *sa1)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
struct sadb_ext *extensions[SADB_EXT_MAX + 1];
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
return pfkey_msg_start(SADB_X_GRPSA, sa1->satype
|
|
|
|
, "pfkey_msg_hdr group", sa1->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
|
|
|
|
, SADB_EXT_SA
|
|
|
|
, sa1->spi /* in network order */
|
|
|
|
, 0, 0, 0, 0, 0)
|
|
|
|
, "pfkey_sa group", sa1->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& pfkeyext_address(SADB_EXT_ADDRESS_DST, sa1->dst
|
|
|
|
, "pfkey_addr_d group", sa1->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& pfkey_build(pfkey_x_satype_build(&extensions[SADB_X_EXT_SATYPE2]
|
|
|
|
, sa0->satype)
|
|
|
|
, "pfkey_satype group", sa0->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& pfkey_build(pfkey_sa_build(&extensions[SADB_X_EXT_SA2]
|
|
|
|
, SADB_X_EXT_SA2
|
|
|
|
, sa0->spi /* in network order */
|
|
|
|
, 0, 0, 0, 0, 0)
|
|
|
|
, "pfkey_sa2 group", sa0->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& pfkeyext_address(SADB_X_EXT_ADDRESS_DST2, sa0->dst
|
|
|
|
, "pfkey_addr_d2 group", sa0->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& finish_pfkey_msg(extensions, "group", sa1->text_said, NULL);
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
pfkey_del_sa(const struct kernel_sa *sa)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
struct sadb_ext *extensions[SADB_EXT_MAX + 1];
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
return pfkey_msg_start(SADB_DELETE, proto2satype(sa->proto)
|
|
|
|
, "pfkey_msg_hdr delete SA", sa->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
|
|
|
|
, SADB_EXT_SA
|
|
|
|
, sa->spi /* in host order */
|
|
|
|
, 0, SADB_SASTATE_MATURE, 0, 0, 0)
|
|
|
|
, "pfkey_sa delete SA", sa->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src
|
|
|
|
, "pfkey_addr_s delete SA", sa->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst
|
|
|
|
, "pfkey_addr_d delete SA", sa->text_said, extensions)
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
&& finish_pfkey_msg(extensions, "Delete SA", sa->text_said, NULL);
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pfkey_close(void)
|
|
|
|
{
|
2009-04-19 19:16:09 +00:00
|
|
|
while (pfkey_iq_head != NULL)
|
|
|
|
{
|
|
|
|
pfkey_item *it = pfkey_iq_head;
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
pfkey_iq_head = it->next;
|
|
|
|
free(it);
|
|
|
|
}
|
2006-04-28 07:14:48 +00:00
|
|
|
|
2009-04-19 19:16:09 +00:00
|
|
|
close(pfkeyfd);
|
|
|
|
pfkeyfd = NULL_FD;
|
2006-04-28 07:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const struct kernel_ops klips_kernel_ops = {
|
2009-04-19 19:16:09 +00:00
|
|
|
type: KERNEL_TYPE_KLIPS,
|
|
|
|
async_fdp: &pfkeyfd,
|
|
|
|
|
|
|
|
pfkey_register: klips_pfkey_register,
|
|
|
|
pfkey_register_response: klips_pfkey_register_response,
|
|
|
|
process_queue: pfkey_dequeue,
|
|
|
|
process_msg: pfkey_event,
|
|
|
|
raw_eroute: pfkey_raw_eroute,
|
|
|
|
add_sa: pfkey_add_sa,
|
|
|
|
grp_sa: pfkey_grp_sa,
|
|
|
|
del_sa: pfkey_del_sa,
|
|
|
|
get_sa: NULL,
|
|
|
|
get_spi: NULL,
|
|
|
|
inbound_eroute: FALSE,
|
|
|
|
policy_lifetime: FALSE,
|
|
|
|
init: NULL
|
2006-04-28 07:14:48 +00:00
|
|
|
};
|
|
|
|
#endif /* KLIPS */
|