mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-04 00:00:14 -04:00
kernel-netlink: Use event socket wrapper for XFRM and networking events
This commit is contained in:
parent
cb0bdb847d
commit
77a5c9514c
@ -108,11 +108,6 @@
|
|||||||
*/
|
*/
|
||||||
#define XFRM_LIMIT(x) ((x) == 0 ? XFRM_INF : (x))
|
#define XFRM_LIMIT(x) ((x) == 0 ? XFRM_INF : (x))
|
||||||
|
|
||||||
/**
|
|
||||||
* Create ORable bitfield of XFRM NL groups
|
|
||||||
*/
|
|
||||||
#define XFRMNLGRP(x) (1<<(XFRMNLGRP_##x-1))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a pointer to the first rtattr following the nlmsghdr *nlh and the
|
* Returns a pointer to the first rtattr following the nlmsghdr *nlh and the
|
||||||
* 'usual' netlink data x like 'struct xfrm_usersa_info'
|
* 'usual' netlink data x like 'struct xfrm_usersa_info'
|
||||||
@ -344,7 +339,7 @@ struct private_kernel_netlink_ipsec_t {
|
|||||||
/**
|
/**
|
||||||
* Netlink xfrm socket to receive acquire and expire events
|
* Netlink xfrm socket to receive acquire and expire events
|
||||||
*/
|
*/
|
||||||
int socket_xfrm_events;
|
netlink_event_socket_t *socket_xfrm_events;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to install routes along policies
|
* Whether to install routes along policies
|
||||||
@ -1111,67 +1106,28 @@ static void process_mapping(private_kernel_netlink_ipsec_t *this,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
CALLBACK(receive_events, void,
|
||||||
* Receives events from kernel
|
private_kernel_netlink_ipsec_t *this, struct nlmsghdr *hdr)
|
||||||
*/
|
|
||||||
static bool receive_events(private_kernel_netlink_ipsec_t *this, int fd,
|
|
||||||
watcher_event_t event)
|
|
||||||
{
|
{
|
||||||
char response[netlink_get_buflen()];
|
switch (hdr->nlmsg_type)
|
||||||
struct nlmsghdr *hdr = (struct nlmsghdr*)response;
|
|
||||||
struct sockaddr_nl addr;
|
|
||||||
socklen_t addr_len = sizeof(addr);
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = recvfrom(this->socket_xfrm_events, response, sizeof(response),
|
|
||||||
MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len);
|
|
||||||
if (len < 0)
|
|
||||||
{
|
{
|
||||||
switch (errno)
|
case XFRM_MSG_ACQUIRE:
|
||||||
{
|
process_acquire(this, hdr);
|
||||||
case EINTR:
|
break;
|
||||||
/* interrupted, try again */
|
case XFRM_MSG_EXPIRE:
|
||||||
return TRUE;
|
process_expire(this, hdr);
|
||||||
case EAGAIN:
|
break;
|
||||||
/* no data ready, select again */
|
case XFRM_MSG_MIGRATE:
|
||||||
return TRUE;
|
process_migrate(this, hdr);
|
||||||
default:
|
break;
|
||||||
DBG1(DBG_KNL, "unable to receive from XFRM event socket: %s "
|
case XFRM_MSG_MAPPING:
|
||||||
"(%d)", strerror(errno), errno);
|
process_mapping(this, hdr);
|
||||||
sleep(1);
|
break;
|
||||||
return TRUE;
|
default:
|
||||||
}
|
DBG1(DBG_KNL, "received unknown event from XFRM event "
|
||||||
|
"socket: %d", hdr->nlmsg_type);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr.nl_pid != 0)
|
|
||||||
{ /* not from kernel. not interested, try another one */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (NLMSG_OK(hdr, len))
|
|
||||||
{
|
|
||||||
switch (hdr->nlmsg_type)
|
|
||||||
{
|
|
||||||
case XFRM_MSG_ACQUIRE:
|
|
||||||
process_acquire(this, hdr);
|
|
||||||
break;
|
|
||||||
case XFRM_MSG_EXPIRE:
|
|
||||||
process_expire(this, hdr);
|
|
||||||
break;
|
|
||||||
case XFRM_MSG_MIGRATE:
|
|
||||||
process_migrate(this, hdr);
|
|
||||||
break;
|
|
||||||
case XFRM_MSG_MAPPING:
|
|
||||||
process_mapping(this, hdr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DBG1(DBG_KNL, "received unknown event from XFRM event "
|
|
||||||
"socket: %d", hdr->nlmsg_type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
hdr = NLMSG_NEXT(hdr, len);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
||||||
@ -3637,11 +3593,7 @@ METHOD(kernel_ipsec_t, destroy, void,
|
|||||||
|
|
||||||
array_destroy_function(this->bypass,
|
array_destroy_function(this->bypass,
|
||||||
(array_callback_t)remove_port_bypass, this);
|
(array_callback_t)remove_port_bypass, this);
|
||||||
if (this->socket_xfrm_events > 0)
|
DESTROY_IF(this->socket_xfrm_events);
|
||||||
{
|
|
||||||
lib->watcher->remove(lib->watcher, this->socket_xfrm_events);
|
|
||||||
close(this->socket_xfrm_events);
|
|
||||||
}
|
|
||||||
DESTROY_IF(this->socket_xfrm);
|
DESTROY_IF(this->socket_xfrm);
|
||||||
enumerator = this->policies->create_enumerator(this->policies);
|
enumerator = this->policies->create_enumerator(this->policies);
|
||||||
while (enumerator->enumerate(enumerator, &policy, &policy))
|
while (enumerator->enumerate(enumerator, &policy, &policy))
|
||||||
@ -3764,7 +3716,7 @@ static void setup_spd_hash_thresh(private_kernel_netlink_ipsec_t *this,
|
|||||||
kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
|
kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
|
||||||
{
|
{
|
||||||
private_kernel_netlink_ipsec_t *this;
|
private_kernel_netlink_ipsec_t *this;
|
||||||
struct sockaddr_nl addr;
|
uint32_t groups;
|
||||||
|
|
||||||
INIT(this,
|
INIT(this,
|
||||||
.public = {
|
.public = {
|
||||||
@ -3816,29 +3768,15 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
|
|||||||
setup_spd_hash_thresh(this, "ipv4", XFRMA_SPD_IPV4_HTHRESH, 32);
|
setup_spd_hash_thresh(this, "ipv4", XFRMA_SPD_IPV4_HTHRESH, 32);
|
||||||
setup_spd_hash_thresh(this, "ipv6", XFRMA_SPD_IPV6_HTHRESH, 128);
|
setup_spd_hash_thresh(this, "ipv6", XFRMA_SPD_IPV6_HTHRESH, 128);
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
groups = nl_group(XFRMNLGRP_ACQUIRE) | nl_group(XFRMNLGRP_EXPIRE) |
|
||||||
addr.nl_family = AF_NETLINK;
|
nl_group(XFRMNLGRP_MIGRATE) | nl_group(XFRMNLGRP_MAPPING);
|
||||||
|
this->socket_xfrm_events = netlink_event_socket_create(NETLINK_XFRM, groups,
|
||||||
/* create and bind XFRM socket for ACQUIRE, EXPIRE, MIGRATE & MAPPING */
|
receive_events, this);
|
||||||
this->socket_xfrm_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
|
if (!this->socket_xfrm_events)
|
||||||
if (this->socket_xfrm_events <= 0)
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "unable to create XFRM event socket: %s (%d)",
|
|
||||||
strerror(errno), errno);
|
|
||||||
destroy(this);
|
destroy(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) |
|
|
||||||
XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING);
|
|
||||||
if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "unable to bind XFRM event socket: %s (%d)",
|
|
||||||
strerror(errno), errno);
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
lib->watcher->add(lib->watcher, this->socket_xfrm_events, WATCHER_READ,
|
|
||||||
(watcher_cb_t)receive_events, this);
|
|
||||||
|
|
||||||
netlink_find_offload_feature(lib->settings->get_str(lib->settings,
|
netlink_find_offload_feature(lib->settings->get_str(lib->settings,
|
||||||
"%s.plugins.kernel-netlink.hw_offload_feature_interface",
|
"%s.plugins.kernel-netlink.hw_offload_feature_interface",
|
||||||
|
@ -340,9 +340,9 @@ struct private_kernel_netlink_net_t {
|
|||||||
netlink_socket_t *socket;
|
netlink_socket_t *socket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Netlink rt socket to receive address change events
|
* Netlink rt event socket
|
||||||
*/
|
*/
|
||||||
int socket_events;
|
netlink_event_socket_t *socket_events;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* earliest time of the next roam event
|
* earliest time of the next roam event
|
||||||
@ -1448,76 +1448,36 @@ static void process_rule(private_kernel_netlink_net_t *this,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
CALLBACK(receive_events, void,
|
||||||
* Receives events from kernel
|
private_kernel_netlink_net_t *this, struct nlmsghdr *hdr)
|
||||||
*/
|
|
||||||
static bool receive_events(private_kernel_netlink_net_t *this, int fd,
|
|
||||||
watcher_event_t event)
|
|
||||||
{
|
{
|
||||||
char response[netlink_get_buflen()];
|
switch (hdr->nlmsg_type)
|
||||||
struct nlmsghdr *hdr = (struct nlmsghdr*)response;
|
|
||||||
struct sockaddr_nl addr;
|
|
||||||
socklen_t addr_len = sizeof(addr);
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = recvfrom(this->socket_events, response, sizeof(response),
|
|
||||||
MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len);
|
|
||||||
if (len < 0)
|
|
||||||
{
|
{
|
||||||
switch (errno)
|
case RTM_NEWADDR:
|
||||||
{
|
case RTM_DELADDR:
|
||||||
case EINTR:
|
process_addr(this, hdr, TRUE);
|
||||||
/* interrupted, try again */
|
break;
|
||||||
return TRUE;
|
case RTM_NEWLINK:
|
||||||
case EAGAIN:
|
case RTM_DELLINK:
|
||||||
/* no data ready, select again */
|
process_link(this, hdr, TRUE);
|
||||||
return TRUE;
|
break;
|
||||||
default:
|
case RTM_NEWROUTE:
|
||||||
DBG1(DBG_KNL, "unable to receive from RT event socket %s (%d)",
|
case RTM_DELROUTE:
|
||||||
strerror(errno), errno);
|
if (this->process_route)
|
||||||
sleep(1);
|
{
|
||||||
return TRUE;
|
process_route(this, hdr);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case RTM_NEWRULE:
|
||||||
|
case RTM_DELRULE:
|
||||||
|
if (this->process_rules)
|
||||||
|
{
|
||||||
|
process_rule(this, hdr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr.nl_pid != 0)
|
|
||||||
{ /* not from kernel. not interested, try another one */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (NLMSG_OK(hdr, len))
|
|
||||||
{
|
|
||||||
/* looks good so far, dispatch netlink message */
|
|
||||||
switch (hdr->nlmsg_type)
|
|
||||||
{
|
|
||||||
case RTM_NEWADDR:
|
|
||||||
case RTM_DELADDR:
|
|
||||||
process_addr(this, hdr, TRUE);
|
|
||||||
break;
|
|
||||||
case RTM_NEWLINK:
|
|
||||||
case RTM_DELLINK:
|
|
||||||
process_link(this, hdr, TRUE);
|
|
||||||
break;
|
|
||||||
case RTM_NEWROUTE:
|
|
||||||
case RTM_DELROUTE:
|
|
||||||
if (this->process_route)
|
|
||||||
{
|
|
||||||
process_route(this, hdr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RTM_NEWRULE:
|
|
||||||
case RTM_DELRULE:
|
|
||||||
if (this->process_rules)
|
|
||||||
{
|
|
||||||
process_rule(this, hdr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
hdr = NLMSG_NEXT(hdr, len);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** enumerator over addresses */
|
/** enumerator over addresses */
|
||||||
@ -3053,11 +3013,7 @@ METHOD(kernel_net_t, destroy, void,
|
|||||||
manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table,
|
manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table,
|
||||||
this->routing_table_prio);
|
this->routing_table_prio);
|
||||||
}
|
}
|
||||||
if (this->socket_events > 0)
|
DESTROY_IF(this->socket_events);
|
||||||
{
|
|
||||||
lib->watcher->remove(lib->watcher, this->socket_events);
|
|
||||||
close(this->socket_events);
|
|
||||||
}
|
|
||||||
enumerator = this->routes->ht.create_enumerator(&this->routes->ht);
|
enumerator = this->routes->ht.create_enumerator(&this->routes->ht);
|
||||||
while (enumerator->enumerate(enumerator, NULL, (void**)&route))
|
while (enumerator->enumerate(enumerator, NULL, (void**)&route))
|
||||||
{
|
{
|
||||||
@ -3093,7 +3049,7 @@ kernel_netlink_net_t *kernel_netlink_net_create()
|
|||||||
{
|
{
|
||||||
private_kernel_netlink_net_t *this;
|
private_kernel_netlink_net_t *this;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
struct sockaddr_nl addr;
|
uint32_t groups;
|
||||||
char *exclude;
|
char *exclude;
|
||||||
|
|
||||||
INIT(this,
|
INIT(this,
|
||||||
@ -3186,40 +3142,26 @@ kernel_netlink_net_t *kernel_netlink_net_create()
|
|||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
groups = nl_group(RTNLGRP_IPV4_IFADDR) |
|
||||||
addr.nl_family = AF_NETLINK;
|
nl_group(RTNLGRP_IPV6_IFADDR) |
|
||||||
|
nl_group(RTNLGRP_LINK);
|
||||||
/* create and bind RT socket for events (address/interface/route changes) */
|
|
||||||
this->socket_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
|
||||||
if (this->socket_events < 0)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "unable to create RT event socket: %s (%d)",
|
|
||||||
strerror(errno), errno);
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
addr.nl_groups = nl_group(RTNLGRP_IPV4_IFADDR) |
|
|
||||||
nl_group(RTNLGRP_IPV6_IFADDR) |
|
|
||||||
nl_group(RTNLGRP_LINK);
|
|
||||||
if (this->process_route)
|
if (this->process_route)
|
||||||
{
|
{
|
||||||
addr.nl_groups |= nl_group(RTNLGRP_IPV4_ROUTE) |
|
groups |= nl_group(RTNLGRP_IPV4_ROUTE) |
|
||||||
nl_group(RTNLGRP_IPV6_ROUTE);
|
nl_group(RTNLGRP_IPV6_ROUTE);
|
||||||
}
|
}
|
||||||
if (this->process_rules)
|
if (this->process_rules)
|
||||||
{
|
{
|
||||||
addr.nl_groups |= nl_group(RTNLGRP_IPV4_RULE) |
|
groups |= nl_group(RTNLGRP_IPV4_RULE) |
|
||||||
nl_group(RTNLGRP_IPV6_RULE);
|
nl_group(RTNLGRP_IPV6_RULE);
|
||||||
}
|
}
|
||||||
if (bind(this->socket_events, (struct sockaddr*)&addr, sizeof(addr)))
|
this->socket_events = netlink_event_socket_create(NETLINK_ROUTE, groups,
|
||||||
|
receive_events, this);
|
||||||
|
if (!this->socket_events)
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "unable to bind RT event socket: %s (%d)",
|
|
||||||
strerror(errno), errno);
|
|
||||||
destroy(this);
|
destroy(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ,
|
|
||||||
(watcher_cb_t)receive_events, this);
|
|
||||||
|
|
||||||
if (init_address_list(this) != SUCCESS)
|
if (init_address_list(this) != SUCCESS)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user