implemented get_iface() using RTM_GETADDR
added support for multi-header netlink messages really ugly now, need a lot of refactoring
This commit is contained in:
@@ -1620,11 +1620,11 @@ static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
|
|||||||
DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip);
|
DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip);
|
||||||
charon->kernel_interface->del_ip(charon->kernel_interface,
|
charon->kernel_interface->del_ip(charon->kernel_interface,
|
||||||
this->my_virtual_ip,
|
this->my_virtual_ip,
|
||||||
this->other_host);
|
this->my_host);
|
||||||
this->my_virtual_ip->destroy(this->my_virtual_ip);
|
this->my_virtual_ip->destroy(this->my_virtual_ip);
|
||||||
}
|
}
|
||||||
if (charon->kernel_interface->add_ip(charon->kernel_interface, ip,
|
if (charon->kernel_interface->add_ip(charon->kernel_interface, ip,
|
||||||
this->other_host) == SUCCESS)
|
this->my_host) == SUCCESS)
|
||||||
{
|
{
|
||||||
this->my_virtual_ip = ip->clone(ip);
|
this->my_virtual_ip = ip->clone(ip);
|
||||||
}
|
}
|
||||||
@@ -1848,7 +1848,7 @@ static void destroy(private_ike_sa_t *this)
|
|||||||
if (this->my_virtual_ip)
|
if (this->my_virtual_ip)
|
||||||
{
|
{
|
||||||
charon->kernel_interface->del_ip(charon->kernel_interface,
|
charon->kernel_interface->del_ip(charon->kernel_interface,
|
||||||
this->my_virtual_ip, this->other_host);
|
this->my_virtual_ip, this->my_host);
|
||||||
this->my_virtual_ip->destroy(this->my_virtual_ip);
|
this->my_virtual_ip->destroy(this->my_virtual_ip);
|
||||||
}
|
}
|
||||||
DESTROY_IF(this->other_virtual_ip);
|
DESTROY_IF(this->other_virtual_ip);
|
||||||
|
|||||||
@@ -308,30 +308,24 @@ static status_t send_message(private_kernel_interface_t *this,
|
|||||||
addr.nl_pid = 0;
|
addr.nl_pid = 0;
|
||||||
addr.nl_groups = 0;
|
addr.nl_groups = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
// set timeout to 10 secs
|
|
||||||
struct timespec tm;
|
|
||||||
tm.tv_sec = 10;
|
|
||||||
*/
|
|
||||||
|
|
||||||
length = sendto(socket,(void *)request, request->nlmsg_len, 0,
|
length = sendto(socket,(void *)request, request->nlmsg_len, 0,
|
||||||
(struct sockaddr *)&addr, sizeof(addr));
|
(struct sockaddr *)&addr, sizeof(addr));
|
||||||
DBG2(DBG_IKE, "%d bytes sent to kernel", length);
|
|
||||||
|
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE,"0 byte could be sent");
|
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
else if (length != request->nlmsg_len)
|
else if (length != request->nlmsg_len)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE,"Request length %d does not match the sent bytes %d",
|
DBG1(DBG_KNL, "error sending to netlink socket: %m");
|
||||||
request->nlmsg_len, length);
|
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&(this->rep_mutex));
|
pthread_mutex_lock(&(this->rep_mutex));
|
||||||
|
|
||||||
|
DBG3(DBG_KNL, "waiting for netlink message with seq: %d",
|
||||||
|
request->nlmsg_seq);
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
@@ -358,8 +352,6 @@ static status_t send_message(private_kernel_interface_t *this,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* TODO: we should time out, if something goes wrong!??? */
|
/* TODO: we should time out, if something goes wrong!??? */
|
||||||
//if(pthread_cond_timedwait(&(this->condvar), &(this->rep_mutex), &tm) == ETIMEDOUT)
|
|
||||||
// return FAILED;
|
|
||||||
pthread_cond_wait(&(this->condvar), &(this->rep_mutex));
|
pthread_cond_wait(&(this->condvar), &(this->rep_mutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,6 +360,8 @@ static status_t send_message(private_kernel_interface_t *this,
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int supersocket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads from a netlink socket and returns the message in a buffer.
|
* Reads from a netlink socket and returns the message in a buffer.
|
||||||
*/
|
*/
|
||||||
@@ -379,13 +373,14 @@ static void netlink_package_receiver(int socket, unsigned char *response, int re
|
|||||||
socklen_t addr_length;
|
socklen_t addr_length;
|
||||||
size_t length;
|
size_t length;
|
||||||
addr_length = sizeof(addr);
|
addr_length = sizeof(addr);
|
||||||
|
|
||||||
length = recvfrom(socket, response, response_size, 0, (struct sockaddr*)&addr, &addr_length);
|
length = recvfrom(socket, response, response_size, 0, (struct sockaddr*)&addr, &addr_length);
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
{
|
{
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
{
|
{
|
||||||
/* interrupted, try again */
|
/* interrupted, try again */
|
||||||
|
DBG1(DBG_IKE, "wtf1");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
charon->kill(charon, "receiving from netlink socket failed\n");
|
charon->kill(charon, "receiving from netlink socket failed\n");
|
||||||
@@ -498,9 +493,9 @@ static void receive_xfrm_messages(private_kernel_interface_t *this)
|
|||||||
* updating SAs.
|
* updating SAs.
|
||||||
* XFRM_MSG_NEWPOLICY is returned when we query a policy.
|
* XFRM_MSG_NEWPOLICY is returned when we query a policy.
|
||||||
*/
|
*/
|
||||||
else if (hdr->nlmsg_type == NLMSG_ERROR
|
else if (hdr->nlmsg_type == NLMSG_ERROR ||
|
||||||
|| hdr->nlmsg_type == XFRM_MSG_NEWSA
|
hdr->nlmsg_type == XFRM_MSG_NEWSA ||
|
||||||
|| hdr->nlmsg_type == XFRM_MSG_NEWPOLICY)
|
hdr->nlmsg_type == XFRM_MSG_NEWPOLICY)
|
||||||
{
|
{
|
||||||
add_to_package_list(this, response);
|
add_to_package_list(this, response);
|
||||||
}
|
}
|
||||||
@@ -518,16 +513,19 @@ static void receive_rt_messages(private_kernel_interface_t *this)
|
|||||||
{
|
{
|
||||||
while(TRUE)
|
while(TRUE)
|
||||||
{
|
{
|
||||||
unsigned char response[BUFFER_SIZE];
|
unsigned char response[BUFFER_SIZE*3];
|
||||||
struct nlmsghdr *hdr;
|
struct nlmsghdr *hdr;
|
||||||
netlink_package_receiver(this->rt_socket,response,BUFFER_SIZE);
|
supersocket = this->rt_socket;
|
||||||
|
netlink_package_receiver(this->rt_socket,response, sizeof(response));
|
||||||
|
|
||||||
hdr = (struct nlmsghdr*)response;
|
hdr = (struct nlmsghdr*)response;
|
||||||
/* NLMSG_ERROR is sent back for acknowledge (or on error).
|
/* NLMSG_ERROR is sent back for acknowledge (or on error).
|
||||||
* RTM_NEWROUTE is returned when we add a route.
|
* RTM_NEWROUTE is returned when we add a route.
|
||||||
*/
|
*/
|
||||||
if (hdr->nlmsg_type == NLMSG_ERROR ||
|
if (hdr->nlmsg_type == NLMSG_ERROR ||
|
||||||
hdr->nlmsg_type == RTM_NEWROUTE)
|
hdr->nlmsg_type == RTM_NEWROUTE ||
|
||||||
|
hdr->nlmsg_type == RTM_NEWLINK ||
|
||||||
|
hdr->nlmsg_type == RTM_NEWADDR)
|
||||||
{
|
{
|
||||||
add_to_package_list(this, response);
|
add_to_package_list(this, response);
|
||||||
}
|
}
|
||||||
@@ -1338,7 +1336,7 @@ static status_t add_policy(private_kernel_interface_t *this,
|
|||||||
policy->route = malloc_thing(rt_refcount_t);
|
policy->route = malloc_thing(rt_refcount_t);
|
||||||
if (find_addr_by_ts(dst_ts, &policy->route->src_ip) == SUCCESS)
|
if (find_addr_by_ts(dst_ts, &policy->route->src_ip) == SUCCESS)
|
||||||
{
|
{
|
||||||
policy->route->if_index = get_iface(this, src);
|
policy->route->if_index = get_iface(this, dst);
|
||||||
policy->route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16);
|
policy->route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16);
|
||||||
memcpy(policy->route->dst_net.ptr, &policy->sel.saddr, policy->route->dst_net.len);
|
memcpy(policy->route->dst_net.ptr, &policy->sel.saddr, policy->route->dst_net.len);
|
||||||
policy->route->prefixlen = policy->sel.prefixlen_s;
|
policy->route->prefixlen = policy->sel.prefixlen_s;
|
||||||
@@ -1610,65 +1608,173 @@ static status_t manage_ipaddr(private_kernel_interface_t *this, int nlmsg_type,
|
|||||||
return send_rtrequest(this, hdr);
|
return send_rtrequest(this, hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* send a netlink message and wait for a reply
|
||||||
|
*/
|
||||||
|
static status_t netlink_send(int socket, struct nlmsghdr *in,
|
||||||
|
struct nlmsghdr **out, size_t *out_len)
|
||||||
|
{
|
||||||
|
int len, addr_len;
|
||||||
|
struct sockaddr_nl addr;
|
||||||
|
chunk_t result = chunk_empty, tmp;
|
||||||
|
struct nlmsghdr *msg, peek;
|
||||||
|
|
||||||
|
static int seq = 200;
|
||||||
|
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
|
||||||
|
in->nlmsg_seq = ++seq;
|
||||||
|
in->nlmsg_pid = getpid();
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.nl_family = AF_NETLINK;
|
||||||
|
addr.nl_pid = 0;
|
||||||
|
addr.nl_groups = 0;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
len = sendto(socket, in, in->nlmsg_len, 0,
|
||||||
|
(struct sockaddr*)&addr, sizeof(addr));
|
||||||
|
|
||||||
|
if (len != in->nlmsg_len)
|
||||||
|
{
|
||||||
|
if (errno == EINTR)
|
||||||
|
{
|
||||||
|
/* interrupted, try again */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
DBG1(DBG_KNL, "error sending to netlink socket: %m");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
tmp = chunk_alloca(2048);
|
||||||
|
msg = (struct nlmsghdr*)tmp.ptr;
|
||||||
|
|
||||||
|
len = recvfrom(socket, tmp.ptr, tmp.len, 0,
|
||||||
|
(struct sockaddr*)&addr, &addr_len);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
if (errno == EINTR)
|
||||||
|
{
|
||||||
|
/* interrupted, try again */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DBG1(DBG_IKE, "error reading from netlink socket: %m");
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (!NLMSG_OK(msg, len))
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "received corrupted netlink message");
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (msg->nlmsg_seq != seq)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "received invalid netlink sequence number");
|
||||||
|
if (msg->nlmsg_seq < seq)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp.len = len;
|
||||||
|
result = chunk_cata("cc", result, tmp);
|
||||||
|
|
||||||
|
/* NLM_F_MULTI flag does not seem to be set correctly, we use sequence
|
||||||
|
* numbers to detect multi header messages */
|
||||||
|
len = recvfrom(socket, &peek, sizeof(peek), MSG_PEEK | MSG_DONTWAIT,
|
||||||
|
(struct sockaddr*)&addr, &addr_len);
|
||||||
|
|
||||||
|
if (len == sizeof(peek) && peek.nlmsg_seq == seq)
|
||||||
|
{
|
||||||
|
/* seems to be multipart */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_len = result.len;
|
||||||
|
*out = (struct nlmsghdr*)clalloc(result.ptr, result.len);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int get_iface(private_kernel_interface_t *this, host_t* ip)
|
static int get_iface(private_kernel_interface_t *this, host_t* ip)
|
||||||
{
|
{
|
||||||
unsigned char request[BUFFER_SIZE];
|
unsigned char request[BUFFER_SIZE];
|
||||||
struct nlmsghdr *hdr;
|
struct nlmsghdr *hdr, *tofree;
|
||||||
struct rtmsg *msg;
|
struct rtgenmsg *msg;
|
||||||
struct rtattr* rta;
|
|
||||||
chunk_t chunk;
|
|
||||||
int ifindex = 0;
|
int ifindex = 0;
|
||||||
|
size_t len;
|
||||||
DBG2(DBG_KNL, "getting interface for %H", ip);
|
chunk_t target, current;
|
||||||
|
|
||||||
memset(&request, 0, sizeof(request));
|
memset(&request, 0, sizeof(request));
|
||||||
|
|
||||||
chunk = ip->get_address(ip);
|
|
||||||
|
|
||||||
hdr = (struct nlmsghdr*)request;
|
hdr = (struct nlmsghdr*)request;
|
||||||
hdr->nlmsg_flags = NLM_F_REQUEST;
|
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
|
||||||
hdr->nlmsg_type = RTM_GETROUTE;
|
hdr->nlmsg_type = RTM_GETADDR;
|
||||||
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT;
|
||||||
|
|
||||||
msg = (struct rtmsg*)NLMSG_DATA(hdr);
|
msg = (struct rtgenmsg*)NLMSG_DATA(hdr);
|
||||||
msg->rtm_family = ip->get_family(ip);
|
msg->rtgen_family = AF_UNSPEC;
|
||||||
msg->rtm_table = 0;
|
|
||||||
msg->rtm_protocol = 0;
|
target = ip->get_address(ip);
|
||||||
msg->rtm_scope = 0;
|
|
||||||
msg->rtm_type = 0;
|
if (netlink_send(this->rt_socket, hdr, &hdr, &len) == SUCCESS)
|
||||||
msg->rtm_src_len = 0;
|
|
||||||
msg->rtm_dst_len = 8 * chunk.len;
|
|
||||||
msg->rtm_tos = 0;
|
|
||||||
msg->rtm_flags = RT_TABLE_UNSPEC | RTPROT_UNSPEC;
|
|
||||||
|
|
||||||
if (add_rtattr(hdr, sizeof(request), RTA_DST,
|
|
||||||
chunk.ptr, chunk.len) != SUCCESS)
|
|
||||||
{
|
{
|
||||||
return 0;
|
tofree = hdr;
|
||||||
}
|
while (NLMSG_OK(hdr, len))
|
||||||
|
|
||||||
if(send_message(this, hdr, &hdr, this->rt_socket) != SUCCESS)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
rta = (struct rtattr*)(NLMSG_DATA(hdr) + NLMSG_LENGTH(sizeof(struct rtmsg)));
|
|
||||||
|
|
||||||
DBG1(DBG_KNL, "listing attributes:");
|
|
||||||
while(RTA_OK(rta, hdr->nlmsg_len))
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, " found rtattr: %d, data %b", rta->rta_type,
|
|
||||||
RTA_DATA(rta), rta->rta_len - 4);
|
|
||||||
if(rta->rta_type == RTA_OIF)
|
|
||||||
{
|
{
|
||||||
ifindex = *((int*)RTA_DATA(rta));
|
switch (hdr->nlmsg_type)
|
||||||
|
{
|
||||||
|
case RTM_NEWADDR:
|
||||||
|
{
|
||||||
|
struct ifaddrmsg* msg = (struct ifaddrmsg*)(NLMSG_DATA(hdr));
|
||||||
|
struct rtattr *rta = IFA_RTA(msg);
|
||||||
|
size_t rtasize = IFA_PAYLOAD (hdr);
|
||||||
|
|
||||||
|
while(RTA_OK(rta, rtasize))
|
||||||
|
{
|
||||||
|
if (rta->rta_type == IFA_ADDRESS)
|
||||||
|
{
|
||||||
|
current.len = rta->rta_len - 4;
|
||||||
|
current.ptr = RTA_DATA(rta);
|
||||||
|
if (chunk_equals(current, target))
|
||||||
|
{
|
||||||
|
ifindex = msg->ifa_index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rta = RTA_NEXT(rta, rtasize);
|
||||||
|
}
|
||||||
|
hdr = NLMSG_NEXT(hdr, len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
hdr = NLMSG_NEXT(hdr, len);
|
||||||
|
continue;
|
||||||
|
case NLMSG_DONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rta = RTA_NEXT(rta, hdr->nlmsg_len);
|
free(tofree);
|
||||||
}
|
}
|
||||||
free(hdr);
|
else
|
||||||
if (ifindex == 0)
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "address %H not reachable, unable to get interface", ip);
|
DBG1(DBG_IKE, "unable to get interface address for %H", ip);
|
||||||
}
|
}
|
||||||
return ifindex;
|
return ifindex;
|
||||||
}
|
}
|
||||||
@@ -1765,7 +1871,7 @@ static void vip_refcount_destroy(vip_refcount_t *this)
|
|||||||
* Implementation of kernel_interface_t.add_ip.
|
* Implementation of kernel_interface_t.add_ip.
|
||||||
*/
|
*/
|
||||||
static status_t add_ip(private_kernel_interface_t *this,
|
static status_t add_ip(private_kernel_interface_t *this,
|
||||||
host_t *virtual_ip, host_t *dst_ip)
|
host_t *virtual_ip, host_t *iface_ip)
|
||||||
{
|
{
|
||||||
int targetif;
|
int targetif;
|
||||||
vip_refcount_t *listed;
|
vip_refcount_t *listed;
|
||||||
@@ -1773,7 +1879,7 @@ static status_t add_ip(private_kernel_interface_t *this,
|
|||||||
|
|
||||||
DBG2(DBG_KNL, "adding ip addr: %H", virtual_ip);
|
DBG2(DBG_KNL, "adding ip addr: %H", virtual_ip);
|
||||||
|
|
||||||
targetif = get_iface(this, dst_ip);
|
targetif = get_iface(this, iface_ip);
|
||||||
if (targetif == 0)
|
if (targetif == 0)
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
@@ -1811,7 +1917,7 @@ static status_t add_ip(private_kernel_interface_t *this,
|
|||||||
* Implementation of kernel_interface_t.del_ip.
|
* Implementation of kernel_interface_t.del_ip.
|
||||||
*/
|
*/
|
||||||
static status_t del_ip(private_kernel_interface_t *this,
|
static status_t del_ip(private_kernel_interface_t *this,
|
||||||
host_t *virtual_ip, host_t *dst_ip)
|
host_t *virtual_ip, host_t *iface_ip)
|
||||||
{
|
{
|
||||||
int targetif;
|
int targetif;
|
||||||
vip_refcount_t *listed;
|
vip_refcount_t *listed;
|
||||||
@@ -1819,7 +1925,7 @@ static status_t del_ip(private_kernel_interface_t *this,
|
|||||||
|
|
||||||
DBG2(DBG_KNL, "deleting ip addr: %H", virtual_ip);
|
DBG2(DBG_KNL, "deleting ip addr: %H", virtual_ip);
|
||||||
|
|
||||||
targetif = get_iface(this, dst_ip);
|
targetif = get_iface(this, iface_ip);
|
||||||
if (targetif == 0)
|
if (targetif == 0)
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
@@ -1909,7 +2015,7 @@ kernel_interface_t *kernel_interface_create()
|
|||||||
|
|
||||||
/* bind the xfrm socket and reqister for ACQUIRE & EXPIRE */
|
/* bind the xfrm socket and reqister for ACQUIRE & EXPIRE */
|
||||||
addr_xfrm.nl_family = AF_NETLINK;
|
addr_xfrm.nl_family = AF_NETLINK;
|
||||||
addr_xfrm.nl_pid = getpid();
|
addr_xfrm.nl_pid = 0;
|
||||||
addr_xfrm.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE;
|
addr_xfrm.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE;
|
||||||
if (bind(this->xfrm_socket, (struct sockaddr*)&addr_xfrm, sizeof(addr_xfrm)))
|
if (bind(this->xfrm_socket, (struct sockaddr*)&addr_xfrm, sizeof(addr_xfrm)))
|
||||||
{
|
{
|
||||||
@@ -1934,7 +2040,7 @@ kernel_interface_t *kernel_interface_create()
|
|||||||
|
|
||||||
/* bind the socket_rt */
|
/* bind the socket_rt */
|
||||||
addr_rt.nl_family = AF_NETLINK;
|
addr_rt.nl_family = AF_NETLINK;
|
||||||
addr_rt.nl_pid = getpid();
|
addr_rt.nl_pid = 0;
|
||||||
addr_rt.nl_groups = 0;
|
addr_rt.nl_groups = 0;
|
||||||
if (bind(this->rt_socket, (struct sockaddr*)&addr_rt, sizeof(addr_rt)))
|
if (bind(this->rt_socket, (struct sockaddr*)&addr_rt, sizeof(addr_rt)))
|
||||||
{
|
{
|
||||||
@@ -1942,7 +2048,7 @@ kernel_interface_t *kernel_interface_create()
|
|||||||
goto kill_rt;
|
goto kill_rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pthread_create(&this->rt_thread, NULL,
|
if (pthread_create(&this->rt_thread, NULL,
|
||||||
(void*(*)(void*))receive_rt_messages, this))
|
(void*(*)(void*))receive_rt_messages, this))
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "Unable to create rt netlink thread");
|
DBG1(DBG_KNL, "Unable to create rt netlink thread");
|
||||||
|
|||||||
Reference in New Issue
Block a user