2008-11-17 09:29:27 +00:00
|
|
|
/*
|
2013-11-07 16:48:40 +00:00
|
|
|
* Copyright (C) 2013 Tobias Brunner
|
2008-11-17 09:29:27 +00:00
|
|
|
* Copyright (C) 2008 Martin Willi
|
2016-03-03 12:29:59 +00:00
|
|
|
* Copyright (C) 2016 Andreas Steffen
|
|
|
|
* HSR Hochschule fuer Technik Rapperswil
|
2008-11-17 09:29:27 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <stdio.h>
|
2014-10-02 09:48:50 +00:00
|
|
|
#include <unistd.h>
|
2008-11-17 09:29:27 +00:00
|
|
|
|
|
|
|
#include "updown_listener.h"
|
|
|
|
|
2014-10-02 09:48:50 +00:00
|
|
|
#include <utils/process.h>
|
2008-11-17 09:29:27 +00:00
|
|
|
#include <daemon.h>
|
|
|
|
#include <config/child_cfg.h>
|
|
|
|
|
|
|
|
typedef struct private_updown_listener_t private_updown_listener_t;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Private data of an updown_listener_t object.
|
|
|
|
*/
|
|
|
|
struct private_updown_listener_t {
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2008-11-17 09:29:27 +00:00
|
|
|
/**
|
|
|
|
* Public updown_listener_t interface.
|
|
|
|
*/
|
|
|
|
updown_listener_t public;
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2008-11-17 09:29:27 +00:00
|
|
|
/**
|
|
|
|
* List of cached interface names
|
|
|
|
*/
|
|
|
|
linked_list_t *iface_cache;
|
2012-07-31 13:21:11 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* DNS attribute handler
|
|
|
|
*/
|
|
|
|
updown_handler_t *handler;
|
2008-11-17 09:29:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct cache_entry_t cache_entry_t;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cache line in the interface name cache.
|
|
|
|
*/
|
|
|
|
struct cache_entry_t {
|
|
|
|
/** requid of the CHILD_SA */
|
2016-03-22 12:22:01 +00:00
|
|
|
uint32_t reqid;
|
2008-11-17 09:29:27 +00:00
|
|
|
/** cached interface name */
|
|
|
|
char *iface;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert an interface name to the cache
|
|
|
|
*/
|
2016-03-22 12:22:01 +00:00
|
|
|
static void cache_iface(private_updown_listener_t *this, uint32_t reqid,
|
2008-11-17 09:29:27 +00:00
|
|
|
char *iface)
|
|
|
|
{
|
|
|
|
cache_entry_t *entry = malloc_thing(cache_entry_t);
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2008-11-17 09:29:27 +00:00
|
|
|
entry->reqid = reqid;
|
|
|
|
entry->iface = strdup(iface);
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2008-11-17 09:29:27 +00:00
|
|
|
this->iface_cache->insert_first(this->iface_cache, entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove a cached interface name and return it.
|
|
|
|
*/
|
2016-03-22 12:22:01 +00:00
|
|
|
static char* uncache_iface(private_updown_listener_t *this, uint32_t reqid)
|
2008-11-17 09:29:27 +00:00
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
cache_entry_t *entry;
|
|
|
|
char *iface = NULL;
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2008-11-17 09:29:27 +00:00
|
|
|
enumerator = this->iface_cache->create_enumerator(this->iface_cache);
|
|
|
|
while (enumerator->enumerate(enumerator, &entry))
|
|
|
|
{
|
|
|
|
if (entry->reqid == reqid)
|
|
|
|
{
|
|
|
|
this->iface_cache->remove_at(this->iface_cache, enumerator);
|
|
|
|
iface = entry->iface;
|
|
|
|
free(entry);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
return iface;
|
|
|
|
}
|
|
|
|
|
2012-07-31 13:21:11 +00:00
|
|
|
/**
|
2014-10-02 09:48:50 +00:00
|
|
|
* Allocate and push a format string to the environment
|
2012-07-31 13:21:11 +00:00
|
|
|
*/
|
2014-10-02 09:48:50 +00:00
|
|
|
static bool push_env(char *envp[], u_int count, char *fmt, ...)
|
2012-07-31 13:21:11 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
int i = 0;
|
|
|
|
char *str;
|
|
|
|
va_list args;
|
2012-07-31 13:21:11 +00:00
|
|
|
|
2014-10-02 09:48:50 +00:00
|
|
|
while (envp[i])
|
2012-07-31 13:21:11 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
if (++i + 1 >= count)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2012-07-31 13:21:11 +00:00
|
|
|
}
|
2014-10-02 09:48:50 +00:00
|
|
|
va_start(args, fmt);
|
|
|
|
if (vasprintf(&str, fmt, args) >= 0)
|
|
|
|
{
|
|
|
|
envp[i] = str;
|
|
|
|
}
|
|
|
|
va_end(args);
|
|
|
|
return envp[i] != NULL;
|
|
|
|
}
|
2012-07-31 13:21:11 +00:00
|
|
|
|
2014-10-02 09:48:50 +00:00
|
|
|
/**
|
|
|
|
* Free all allocated environment strings
|
|
|
|
*/
|
|
|
|
static void free_env(char *envp[])
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; envp[i]; i++)
|
2012-07-31 13:21:11 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
free(envp[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Push variables for handled DNS attributes
|
|
|
|
*/
|
|
|
|
static void push_dns_env(private_updown_listener_t *this, ike_sa_t *ike_sa,
|
|
|
|
char *envp[], u_int count)
|
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
host_t *host;
|
|
|
|
int v4 = 0, v6 = 0;
|
|
|
|
|
|
|
|
if (this->handler)
|
|
|
|
{
|
|
|
|
enumerator = this->handler->create_dns_enumerator(this->handler,
|
|
|
|
ike_sa->get_unique_id(ike_sa));
|
|
|
|
while (enumerator->enumerate(enumerator, &host))
|
2012-07-31 13:21:11 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
switch (host->get_family(host))
|
|
|
|
{
|
|
|
|
case AF_INET:
|
|
|
|
push_env(envp, count, "PLUTO_DNS4_%d=%H", ++v4, host);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
push_env(envp, count, "PLUTO_DNS6_%d=%H", ++v6, host);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
2012-07-31 13:21:11 +00:00
|
|
|
}
|
2014-10-02 09:48:50 +00:00
|
|
|
enumerator->destroy(enumerator);
|
2012-07-31 13:21:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-21 11:50:32 +00:00
|
|
|
/**
|
2015-06-25 15:19:12 +00:00
|
|
|
* Push variables for local/remote virtual IPs
|
2012-08-21 11:50:32 +00:00
|
|
|
*/
|
2014-10-02 09:48:50 +00:00
|
|
|
static void push_vip_env(private_updown_listener_t *this, ike_sa_t *ike_sa,
|
2015-06-25 15:19:12 +00:00
|
|
|
char *envp[], u_int count, bool local)
|
2012-08-21 11:50:32 +00:00
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
host_t *host;
|
|
|
|
int v4 = 0, v6 = 0;
|
|
|
|
bool first = TRUE;
|
|
|
|
|
2015-06-25 15:19:12 +00:00
|
|
|
enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
|
2012-08-21 11:50:32 +00:00
|
|
|
while (enumerator->enumerate(enumerator, &host))
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
{ /* legacy variable for first VIP */
|
2014-10-02 09:48:50 +00:00
|
|
|
first = FALSE;
|
2015-06-25 15:19:12 +00:00
|
|
|
push_env(envp, count, "PLUTO_%s_SOURCEIP=%H",
|
|
|
|
local ? "MY" : "PEER", host);
|
2012-08-21 11:50:32 +00:00
|
|
|
}
|
|
|
|
switch (host->get_family(host))
|
|
|
|
{
|
|
|
|
case AF_INET:
|
2015-06-25 15:19:12 +00:00
|
|
|
push_env(envp, count, "PLUTO_%s_SOURCEIP4_%d=%H",
|
|
|
|
local ? "MY" : "PEER", ++v4, host);
|
2012-08-21 11:50:32 +00:00
|
|
|
break;
|
|
|
|
case AF_INET6:
|
2015-06-25 15:19:12 +00:00
|
|
|
push_env(envp, count, "PLUTO_%s_SOURCEIP6_%d=%H",
|
|
|
|
local ? "MY" : "PEER", ++v6, host);
|
2012-08-21 11:50:32 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
}
|
|
|
|
|
2016-03-03 12:29:59 +00:00
|
|
|
#define PORT_BUF_LEN 12
|
|
|
|
|
2013-10-14 15:08:09 +00:00
|
|
|
/**
|
|
|
|
* Determine proper values for port env variable
|
|
|
|
*/
|
2016-03-03 12:29:59 +00:00
|
|
|
static char* get_port(traffic_selector_t *me, traffic_selector_t *other,
|
|
|
|
char *port_buf, bool local)
|
2013-10-14 15:08:09 +00:00
|
|
|
{
|
2016-03-03 12:29:59 +00:00
|
|
|
uint16_t port, to, from;
|
|
|
|
|
2013-10-14 15:08:09 +00:00
|
|
|
switch (max(me->get_protocol(me), other->get_protocol(other)))
|
|
|
|
{
|
|
|
|
case IPPROTO_ICMP:
|
|
|
|
case IPPROTO_ICMPV6:
|
|
|
|
{
|
2016-03-03 12:29:59 +00:00
|
|
|
port = max(me->get_from_port(me), other->get_from_port(other));
|
|
|
|
snprintf(port_buf, PORT_BUF_LEN, "%u",
|
|
|
|
local ? traffic_selector_icmp_type(port)
|
|
|
|
: traffic_selector_icmp_code(port));
|
|
|
|
return port_buf;
|
2013-10-14 15:08:09 +00:00
|
|
|
}
|
|
|
|
}
|
2016-03-03 12:29:59 +00:00
|
|
|
if (local)
|
|
|
|
{
|
|
|
|
from = me->get_from_port(me);
|
|
|
|
to = me->get_to_port(me);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
from = other->get_from_port(other);
|
|
|
|
to = other->get_to_port(other);
|
|
|
|
}
|
2016-03-04 11:52:35 +00:00
|
|
|
if (from == to || (from == 0 && to == 65535))
|
2016-03-03 12:29:59 +00:00
|
|
|
{
|
|
|
|
snprintf(port_buf, PORT_BUF_LEN, "%u", from);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
snprintf(port_buf, PORT_BUF_LEN, "%u:%u", from, to);
|
|
|
|
}
|
|
|
|
return port_buf;
|
2013-10-14 15:08:09 +00:00
|
|
|
}
|
|
|
|
|
2014-10-02 09:48:50 +00:00
|
|
|
/**
|
|
|
|
* Invoke the updown script once for given traffic selectors
|
|
|
|
*/
|
|
|
|
static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa,
|
|
|
|
child_sa_t *child_sa, child_cfg_t *config, bool up,
|
|
|
|
traffic_selector_t *my_ts, traffic_selector_t *other_ts)
|
2008-11-17 09:29:27 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
host_t *me, *other, *host;
|
|
|
|
char *iface;
|
2016-03-22 12:22:01 +00:00
|
|
|
uint8_t mask;
|
2019-02-12 11:11:10 +00:00
|
|
|
uint32_t if_id;
|
2014-10-02 09:48:50 +00:00
|
|
|
mark_t mark;
|
|
|
|
bool is_host, is_ipv6;
|
|
|
|
int out;
|
|
|
|
FILE *shell;
|
|
|
|
process_t *process;
|
2016-03-03 12:29:59 +00:00
|
|
|
char port_buf[PORT_BUF_LEN];
|
2014-10-02 09:48:50 +00:00
|
|
|
char *envp[128] = {};
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2008-11-17 09:29:27 +00:00
|
|
|
me = ike_sa->get_my_host(ike_sa);
|
|
|
|
other = ike_sa->get_other_host(ike_sa);
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2014-10-22 12:50:09 +00:00
|
|
|
push_env(envp, countof(envp), "PATH=%s", getenv("PATH"));
|
2014-10-02 09:48:50 +00:00
|
|
|
push_env(envp, countof(envp), "PLUTO_VERSION=1.1");
|
|
|
|
is_host = my_ts->is_host(my_ts, me);
|
|
|
|
if (is_host)
|
2008-11-17 09:29:27 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
is_ipv6 = me->get_family(me) == AF_INET6;
|
2008-11-17 09:29:27 +00:00
|
|
|
}
|
2014-10-02 09:48:50 +00:00
|
|
|
else
|
2008-11-17 09:29:27 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
is_ipv6 = my_ts->get_type(my_ts) == TS_IPV6_ADDR_RANGE;
|
|
|
|
}
|
|
|
|
push_env(envp, countof(envp), "PLUTO_VERB=%s%s%s",
|
|
|
|
up ? "up" : "down",
|
|
|
|
is_host ? "-host" : "-client",
|
|
|
|
is_ipv6 ? "-v6" : "");
|
|
|
|
push_env(envp, countof(envp), "PLUTO_CONNECTION=%s",
|
|
|
|
config->get_name(config));
|
|
|
|
if (up)
|
|
|
|
{
|
2019-06-20 08:02:21 +00:00
|
|
|
host = charon->kernel->get_nexthop(charon->kernel, other, -1, me,
|
|
|
|
&iface);
|
|
|
|
if (host && iface)
|
2010-07-17 11:27:19 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
cache_iface(this, child_sa->get_reqid(child_sa), iface);
|
2010-07-17 11:27:19 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
iface = NULL;
|
2010-07-17 11:27:19 +00:00
|
|
|
}
|
2019-06-20 08:02:21 +00:00
|
|
|
DESTROY_IF(host);
|
2014-10-02 09:48:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
iface = uncache_iface(this, child_sa->get_reqid(child_sa));
|
|
|
|
}
|
|
|
|
push_env(envp, countof(envp), "PLUTO_INTERFACE=%s",
|
|
|
|
iface ? iface : "unknown");
|
|
|
|
push_env(envp, countof(envp), "PLUTO_REQID=%u",
|
|
|
|
child_sa->get_reqid(child_sa));
|
|
|
|
push_env(envp, countof(envp), "PLUTO_PROTO=%s",
|
|
|
|
child_sa->get_protocol(child_sa) == PROTO_ESP ? "esp" : "ah");
|
|
|
|
push_env(envp, countof(envp), "PLUTO_UNIQUEID=%u",
|
|
|
|
ike_sa->get_unique_id(ike_sa));
|
|
|
|
push_env(envp, countof(envp), "PLUTO_ME=%H", me);
|
|
|
|
push_env(envp, countof(envp), "PLUTO_MY_ID=%Y", ike_sa->get_my_id(ike_sa));
|
2016-03-10 11:00:56 +00:00
|
|
|
if (!my_ts->to_subnet(my_ts, &host, &mask))
|
2014-10-02 09:48:50 +00:00
|
|
|
{
|
2016-03-10 11:00:56 +00:00
|
|
|
DBG1(DBG_CHD, "updown approximates local TS %R "
|
|
|
|
"by next larger subnet", my_ts);
|
2014-10-02 09:48:50 +00:00
|
|
|
}
|
2016-03-10 11:00:56 +00:00
|
|
|
push_env(envp, countof(envp), "PLUTO_MY_CLIENT=%+H/%u", host, mask);
|
|
|
|
host->destroy(host);
|
2016-03-03 12:29:59 +00:00
|
|
|
push_env(envp, countof(envp), "PLUTO_MY_PORT=%s",
|
|
|
|
get_port(my_ts, other_ts, port_buf, TRUE));
|
2014-10-02 09:48:50 +00:00
|
|
|
push_env(envp, countof(envp), "PLUTO_MY_PROTOCOL=%u",
|
|
|
|
my_ts->get_protocol(my_ts));
|
|
|
|
push_env(envp, countof(envp), "PLUTO_PEER=%H", other);
|
|
|
|
push_env(envp, countof(envp), "PLUTO_PEER_ID=%Y",
|
|
|
|
ike_sa->get_other_id(ike_sa));
|
2016-03-10 11:00:56 +00:00
|
|
|
if (!other_ts->to_subnet(other_ts, &host, &mask))
|
2014-10-02 09:48:50 +00:00
|
|
|
{
|
2016-03-10 11:00:56 +00:00
|
|
|
DBG1(DBG_CHD, "updown approximates remote TS %R "
|
|
|
|
"by next larger subnet", other_ts);
|
2014-10-02 09:48:50 +00:00
|
|
|
}
|
2016-03-10 11:00:56 +00:00
|
|
|
push_env(envp, countof(envp), "PLUTO_PEER_CLIENT=%+H/%u", host, mask);
|
|
|
|
host->destroy(host);
|
2016-03-03 12:29:59 +00:00
|
|
|
push_env(envp, countof(envp), "PLUTO_PEER_PORT=%s",
|
|
|
|
get_port(my_ts, other_ts, port_buf, FALSE));
|
2014-10-02 09:48:50 +00:00
|
|
|
push_env(envp, countof(envp), "PLUTO_PEER_PROTOCOL=%u",
|
|
|
|
other_ts->get_protocol(other_ts));
|
|
|
|
if (ike_sa->has_condition(ike_sa, COND_EAP_AUTHENTICATED) ||
|
|
|
|
ike_sa->has_condition(ike_sa, COND_XAUTH_AUTHENTICATED))
|
|
|
|
{
|
|
|
|
push_env(envp, countof(envp), "PLUTO_XAUTH_ID=%Y",
|
|
|
|
ike_sa->get_other_eap_id(ike_sa));
|
|
|
|
}
|
2015-06-25 15:19:12 +00:00
|
|
|
push_vip_env(this, ike_sa, envp, countof(envp), TRUE);
|
|
|
|
push_vip_env(this, ike_sa, envp, countof(envp), FALSE);
|
2016-03-12 15:05:01 +00:00
|
|
|
mark = child_sa->get_mark(child_sa, TRUE);
|
2014-10-02 09:48:50 +00:00
|
|
|
if (mark.value)
|
|
|
|
{
|
|
|
|
push_env(envp, countof(envp), "PLUTO_MARK_IN=%u/0x%08x",
|
|
|
|
mark.value, mark.mask);
|
|
|
|
}
|
2016-03-12 15:05:01 +00:00
|
|
|
mark = child_sa->get_mark(child_sa, FALSE);
|
2014-10-02 09:48:50 +00:00
|
|
|
if (mark.value)
|
|
|
|
{
|
|
|
|
push_env(envp, countof(envp), "PLUTO_MARK_OUT=%u/0x%08x",
|
|
|
|
mark.value, mark.mask);
|
|
|
|
}
|
2019-02-12 11:11:10 +00:00
|
|
|
if_id = child_sa->get_if_id(child_sa, TRUE);
|
|
|
|
if (if_id)
|
|
|
|
{
|
|
|
|
push_env(envp, countof(envp), "PLUTO_IF_ID_IN=%u", if_id);
|
|
|
|
}
|
|
|
|
if_id = child_sa->get_if_id(child_sa, FALSE);
|
|
|
|
if (if_id)
|
|
|
|
{
|
|
|
|
push_env(envp, countof(envp), "PLUTO_IF_ID_OUT=%u", if_id);
|
|
|
|
}
|
2014-10-02 09:48:50 +00:00
|
|
|
if (ike_sa->has_condition(ike_sa, COND_NAT_ANY))
|
|
|
|
{
|
|
|
|
push_env(envp, countof(envp), "PLUTO_UDP_ENC=%u",
|
|
|
|
other->get_port(other));
|
|
|
|
}
|
|
|
|
if (child_sa->get_ipcomp(child_sa) != IPCOMP_NONE)
|
|
|
|
{
|
|
|
|
push_env(envp, countof(envp), "PLUTO_IPCOMP=1");
|
|
|
|
}
|
|
|
|
push_dns_env(this, ike_sa, envp, countof(envp));
|
2017-05-10 17:04:25 +00:00
|
|
|
if (config->has_option(config, OPT_HOSTACCESS))
|
2014-10-02 09:48:50 +00:00
|
|
|
{
|
|
|
|
push_env(envp, countof(envp), "PLUTO_HOST_ACCESS=1");
|
|
|
|
}
|
2010-07-17 11:27:19 +00:00
|
|
|
|
2014-10-02 09:48:50 +00:00
|
|
|
process = process_start_shell(envp, NULL, &out, NULL, "2>&1 %s",
|
|
|
|
config->get_updown(config));
|
|
|
|
if (process)
|
|
|
|
{
|
|
|
|
shell = fdopen(out, "r");
|
|
|
|
if (shell)
|
2012-11-16 08:56:05 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
while (TRUE)
|
2012-11-16 08:56:05 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
char resp[128];
|
2012-11-16 08:56:05 +00:00
|
|
|
|
2014-10-02 09:48:50 +00:00
|
|
|
if (fgets(resp, sizeof(resp), shell) == NULL)
|
|
|
|
{
|
|
|
|
if (ferror(shell))
|
|
|
|
{
|
|
|
|
DBG1(DBG_CHD, "error reading from updown script");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *e = resp + strlen(resp);
|
|
|
|
if (e > resp && e[-1] == '\n')
|
|
|
|
{
|
|
|
|
e[-1] = '\0';
|
|
|
|
}
|
|
|
|
DBG1(DBG_CHD, "updown: %s", resp);
|
|
|
|
}
|
2013-10-30 02:48:51 +00:00
|
|
|
}
|
2014-10-02 09:48:50 +00:00
|
|
|
fclose(shell);
|
2008-11-17 09:29:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
close(out);
|
2008-11-17 09:29:27 +00:00
|
|
|
}
|
2014-10-02 09:48:50 +00:00
|
|
|
process->wait(process, NULL);
|
|
|
|
}
|
|
|
|
free(iface);
|
|
|
|
free_env(envp);
|
|
|
|
}
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2014-10-02 09:48:50 +00:00
|
|
|
METHOD(listener_t, child_updown, bool,
|
|
|
|
private_updown_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
|
|
|
|
bool up)
|
|
|
|
{
|
|
|
|
traffic_selector_t *my_ts, *other_ts;
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
child_cfg_t *config;
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2014-10-02 09:48:50 +00:00
|
|
|
config = child_sa->get_config(child_sa);
|
|
|
|
if (config->get_updown(config))
|
|
|
|
{
|
|
|
|
enumerator = child_sa->create_policy_enumerator(child_sa);
|
|
|
|
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
|
2008-11-17 09:29:27 +00:00
|
|
|
{
|
2014-10-02 09:48:50 +00:00
|
|
|
invoke_once(this, ike_sa, child_sa, config, up, my_ts, other_ts);
|
2008-11-17 09:29:27 +00:00
|
|
|
}
|
2014-10-02 09:48:50 +00:00
|
|
|
enumerator->destroy(enumerator);
|
2008-11-17 09:29:27 +00:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-02-03 10:04:18 +00:00
|
|
|
METHOD(updown_listener_t, destroy, void,
|
|
|
|
private_updown_listener_t *this)
|
2008-11-17 09:29:27 +00:00
|
|
|
{
|
|
|
|
this->iface_cache->destroy(this->iface_cache);
|
|
|
|
free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* See header
|
|
|
|
*/
|
2012-07-31 13:21:11 +00:00
|
|
|
updown_listener_t *updown_listener_create(updown_handler_t *handler)
|
2008-11-17 09:29:27 +00:00
|
|
|
{
|
2010-02-03 10:04:18 +00:00
|
|
|
private_updown_listener_t *this;
|
|
|
|
|
|
|
|
INIT(this,
|
|
|
|
.public = {
|
2010-06-24 14:23:54 +00:00
|
|
|
.listener = {
|
|
|
|
.child_updown = _child_updown,
|
|
|
|
},
|
2010-02-03 10:04:18 +00:00
|
|
|
.destroy = _destroy,
|
|
|
|
},
|
|
|
|
.iface_cache = linked_list_create(),
|
2012-07-31 13:21:11 +00:00
|
|
|
.handler = handler,
|
2010-02-03 10:04:18 +00:00
|
|
|
);
|
2009-09-04 11:46:09 +00:00
|
|
|
|
2008-11-17 09:29:27 +00:00
|
|
|
return &this->public;
|
|
|
|
}
|