*/
#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
* 'usual' netlink data x like 'struct xfrm_usersa_info'
/**
* 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
}
}
-/**
- * Receives events from kernel
- */
-static bool receive_events(private_kernel_netlink_ipsec_t *this, int fd,
- watcher_event_t event)
-{
- char response[netlink_get_buflen()];
- 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 EINTR:
- /* interrupted, try again */
- return TRUE;
- case EAGAIN:
- /* no data ready, select again */
- return TRUE;
- default:
- DBG1(DBG_KNL, "unable to receive from XFRM event socket: %s "
- "(%d)", strerror(errno), errno);
- sleep(1);
- return TRUE;
- }
- }
-
- if (addr.nl_pid != 0)
- { /* not from kernel. not interested, try another one */
- return TRUE;
- }
-
- while (NLMSG_OK(hdr, len))
+CALLBACK(receive_events, void,
+ private_kernel_netlink_ipsec_t *this, struct nlmsghdr *hdr)
+{
+ switch (hdr->nlmsg_type)
{
- 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);
+ 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;
}
- return TRUE;
}
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
array_destroy_function(this->bypass,
(array_callback_t)remove_port_bypass, this);
- if (this->socket_xfrm_events > 0)
- {
- lib->watcher->remove(lib->watcher, this->socket_xfrm_events);
- close(this->socket_xfrm_events);
- }
+ DESTROY_IF(this->socket_xfrm_events);
DESTROY_IF(this->socket_xfrm);
enumerator = this->policies->create_enumerator(this->policies);
while (enumerator->enumerate(enumerator, &policy, &policy))
kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
{
private_kernel_netlink_ipsec_t *this;
- struct sockaddr_nl addr;
+ uint32_t groups;
INIT(this,
.public = {
setup_spd_hash_thresh(this, "ipv4", XFRMA_SPD_IPV4_HTHRESH, 32);
setup_spd_hash_thresh(this, "ipv6", XFRMA_SPD_IPV6_HTHRESH, 128);
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
-
- /* create and bind XFRM socket for ACQUIRE, EXPIRE, MIGRATE & MAPPING */
- this->socket_xfrm_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
- if (this->socket_xfrm_events <= 0)
+ groups = nl_group(XFRMNLGRP_ACQUIRE) | nl_group(XFRMNLGRP_EXPIRE) |
+ nl_group(XFRMNLGRP_MIGRATE) | nl_group(XFRMNLGRP_MAPPING);
+ this->socket_xfrm_events = netlink_event_socket_create(NETLINK_XFRM, groups,
+ receive_events, this);
+ if (!this->socket_xfrm_events)
{
- DBG1(DBG_KNL, "unable to create XFRM event socket: %s (%d)",
- strerror(errno), errno);
- destroy(this);
- 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,
"%s.plugins.kernel-netlink.hw_offload_feature_interface",
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
#endif
}
-/**
- * Receives events from kernel
- */
-static bool receive_events(private_kernel_netlink_net_t *this, int fd,
- watcher_event_t event)
+CALLBACK(receive_events, void,
+ private_kernel_netlink_net_t *this, struct nlmsghdr *hdr)
{
- char response[netlink_get_buflen()];
- 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 EINTR:
- /* interrupted, try again */
- return TRUE;
- case EAGAIN:
- /* no data ready, select again */
- return TRUE;
- default:
- DBG1(DBG_KNL, "unable to receive from RT event socket %s (%d)",
- strerror(errno), errno);
- sleep(1);
- return TRUE;
- }
- }
-
- if (addr.nl_pid != 0)
- { /* not from kernel. not interested, try another one */
- return TRUE;
- }
-
- while (NLMSG_OK(hdr, len))
+ switch (hdr->nlmsg_type)
{
- /* 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);
+ 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;
}
- return TRUE;
}
/** enumerator over addresses */
manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table,
this->routing_table_prio);
}
- if (this->socket_events > 0)
- {
- lib->watcher->remove(lib->watcher, this->socket_events);
- close(this->socket_events);
- }
+ DESTROY_IF(this->socket_events);
enumerator = this->routes->ht.create_enumerator(&this->routes->ht);
while (enumerator->enumerate(enumerator, NULL, (void**)&route))
{
{
private_kernel_netlink_net_t *this;
enumerator_t *enumerator;
- struct sockaddr_nl addr;
+ uint32_t groups;
char *exclude;
INIT(this,
enumerator->destroy(enumerator);
}
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
-
- /* 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);
+ groups = nl_group(RTNLGRP_IPV4_IFADDR) |
+ nl_group(RTNLGRP_IPV6_IFADDR) |
+ nl_group(RTNLGRP_LINK);
if (this->process_route)
{
- addr.nl_groups |= nl_group(RTNLGRP_IPV4_ROUTE) |
- nl_group(RTNLGRP_IPV6_ROUTE);
+ groups |= nl_group(RTNLGRP_IPV4_ROUTE) |
+ nl_group(RTNLGRP_IPV6_ROUTE);
}
if (this->process_rules)
{
- addr.nl_groups |= nl_group(RTNLGRP_IPV4_RULE) |
- nl_group(RTNLGRP_IPV6_RULE);
+ groups |= nl_group(RTNLGRP_IPV4_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);
return NULL;
}
- lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ,
- (watcher_cb_t)receive_events, this);
if (init_address_list(this) != SUCCESS)
{