7 #include <sys/socket.h>
9 #include <linux/netlink.h>
10 #include <linux/rtnetlink.h>
11 #include <linux/neighbour.h>
12 #include <linux/if_addr.h>
13 #include <arpa/inet.h>
16 #ifndef NLM_F_DUMP_FILTERED
17 #define NLM_F_DUMP_FILTERED 0x20
31 unsigned short attr_type,
int attr_len,
const void* attr_data)
34 LOG(ERROR,
"NULL pointer in nl_msg in"
35 " void insert_attr, metadata_ipv6_netlink.cc");
38 if (attr_data == NULL) {
39 LOG(ERROR,
"NULL pointer in attr_data in"
40 " void insert_attr, metadata_ipv6_netlink.cc");
44 struct rtattr *payload =
45 (
struct rtattr*)(((
char*)nl_msg) + NLMSG_ALIGN(nl_msg->nlmsg_len));
46 payload->rta_type = attr_type;
47 payload->rta_len = RTA_LENGTH(attr_len);
52 nl_msg->nlmsg_len = NLMSG_ALIGN(nl_msg->nlmsg_len) + payload->rta_len;
76 if (this->
msg_len < NLMSG_LENGTH(
sizeof(T))) {
77 LOG(ERROR,
" too short msg_len, "
78 "NetlinkRequest::message, metadata_ipv6_netlink.cc, "<<
79 "this->msg_len = " << this->
msg_len <<
80 ", NLMSG_LENGTH(sizeof(T)) = " << NLMSG_LENGTH(
sizeof(T)));
86 std::memset(
msg_ptr_.get(), 0,
sizeof(msghdr));
88 msg_ptr_->msg_namelen =
sizeof(s_nl);
98 int attr_len,
const void* attr_data) {
157 socket_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
159 LOG(ERROR,
"An error has occured during opening the socket"
160 "NetlinkSocket::NetlinkSocket, metadata_ipv6_netlink.cc, "
161 "errno = " << errno << std::endl);
172 LOG(ERROR,
"An error has occured during binding the socket"
173 "NetlinkSocket::NetlinkSocket, metadata_ipv6_netlink.cc, "
174 "errno = " << errno << std::endl);
183 LOG(ERROR,
"An error has occured during closing the socket"
184 "NetlinkSocket::NetlinkSocket, metadata_ipv6_netlink.cc, "
185 "errno = " << errno << std::endl);
190 const int&
fd()
const {
231 msg_.msg_name = req_msg->msg_name;
232 msg_.msg_namelen = req_msg->msg_namelen;
239 LOG(ERROR,
"Error receiving message from netlink: "
240 << strerror(errno) << std::endl);
255 int handle_res = handler_func(
resp_nh_);
256 if (handle_res >= 0) {
276 struct rtattr *resp_attr = NULL;
277 struct ifaddrmsg *ifa_resp = NULL;
279 if (resp_nh->nlmsg_type != RTM_NEWADDR) {
282 ifa_resp =
static_cast<struct ifaddrmsg *
>(NLMSG_DATA(resp_nh));
283 if (ifa_resp == NULL) {
289 attr_len = resp_nh->nlmsg_len - NLMSG_LENGTH(
sizeof(*ifa_resp));
290 for (resp_attr = IFA_RTA(ifa_resp);
291 RTA_OK(resp_attr, attr_len);
292 resp_attr = RTA_NEXT(resp_attr, attr_len)) {
293 if (resp_attr->rta_type == IFA_ADDRESS) {
295 memset(addr_str, 0, 256);
297 RTA_DATA(resp_attr), addr_str, 256);
298 if (addr_str[0] != 0) {
327 const char* func_name) {
333 if (msg && send_n > 0 && ack) {
334 recv_n = recvmsg(nl_sock.
fd(), ack, MSG_WAITALL);
336 LOG(ERROR,
"Recvmsg failed,"<<
337 func_name <<
", metadata_ipv6_netlink.cc, "
338 "errno = " << errno << std::endl);
344 || ack_err == EEXIST || ack_err == EADDRNOTAVAIL) {
349 LOG(ERROR,
"Error in the Netlink message, "<<
350 func_name <<
", metadata_ipv6_netlink.cc, "
351 "error code = " << ack_err);
367 <<
" has not been found "
372 std::cout<<
"dev_idx = " << dev_idx
382 ifaddrmsg &nl_req_param = addr_nl_req.
nl_req_hdr;
383 nl_req_param.ifa_family = AF_INET6;
384 nl_req_param.ifa_prefixlen = 128;
385 nl_req_param.ifa_index = dev_idx;
388 msg_hdr.nlmsg_type = RTM_GETADDR;
389 msg_hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
390 addr_nl_req.
msg_len = NLMSG_LENGTH(
sizeof(nl_req_param));
399 send_n = sendmsg(nl_sock.
fd(), msg, 0);
401 LOG(ERROR,
"sendmsg failed (address request), "
402 "MetadataProxy::NetlinkAddVhostIp, metadata_ipv6_netlink.cc, "
403 "errno = " << errno << std::endl);
422 if (!nb_ip.is_v6()) {
428 int addr_res = inet_pton(AF_INET6, nb_ip.to_string().c_str(), &addr6);
430 LOG(ERROR,
"An error has occured during address initialization,"
431 "MetadataProxy::NetlinkAddVhostNb, metadata_ipv6_netlink.cc, "
432 "errno = " << errno << std::endl);
436 LOG(ERROR,
"A wrong address has been specified,"
437 "MetadataProxy::NetlinkAddVhostNb, metadata_ipv6_netlink.cc, "
438 "address = " << nb_ip.to_string().c_str() << std::endl);
443 unsigned char nb_mac_addr[] = {0,0,0,0,0,0};
444 via_mac.
ToArray(nb_mac_addr,
sizeof(nb_mac_addr));
450 LOG(ERROR,
"Error while retreiving device index,"
451 "MetadataProxy::NetlinkAddVhostNb, metadata_ipv6_netlink.cc, "
452 "dev_idx = " << dev_idx << std::endl);
461 nd_message_hdr.ndm_family = AF_INET6;
462 nd_message_hdr.ndm_ifindex = dev_idx;
463 nd_message_hdr.ndm_state = NUD_PERMANENT;
466 nl_message_hdr.nlmsg_type = RTM_NEWNEIGH;
467 nl_message_hdr.nlmsg_flags =
468 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE
471 nd_req.
msg_len = NLMSG_LENGTH(
sizeof(nd_message_hdr));
474 nd_req.
insert_attr(NDA_LLADDR,
sizeof(nb_mac_addr), &nb_mac_addr[0]);
476 nd_req.
insert_attr(NDA_DST,
sizeof(addr6), &addr6);
482 send_n = sendmsg(nl_sock.
fd(), msg, 0);
484 LOG(ERROR,
"Sendmsg failed,"
485 "MetadataProxy::NetlinkAddVhostNb, metadata_ipv6_netlink.cc, "
486 "errno = " << errno << std::endl);
494 if (!intf_addr.is_v6()) {
500 int addr_res = inet_pton(AF_INET6, intf_addr.to_string().c_str(), &addr6);
502 LOG(ERROR,
"An error has occured during address initialization,"
503 "MetadataProxy::NetlinkAddInterfaceRoute, metadata_ipv6_netlink.cc, "
504 "errno = " << errno << std::endl);
508 LOG(ERROR,
"A wrong address has been specified,"
509 "MetadataProxy::NetlinkAddInterfaceRoute, metadata_ipv6_netlink.cc, "
510 "address = " << intf_addr.to_string().c_str() << std::endl);
518 LOG(ERROR,
"Error while retreiving device index,"
519 "MetadataProxy::NetlinkAddInterfaceRoute, metadata_ipv6_netlink.cc, "
520 "dev_idx = " << dev_idx << std::endl);
529 std::memset(&rt_message_hdr, 0,
sizeof(rt_message_hdr));
530 rt_message_hdr.rtm_family = AF_INET6;
531 rt_message_hdr.rtm_table = RT_TABLE_MAIN;
532 rt_message_hdr.rtm_protocol = RTPROT_STATIC;
533 rt_message_hdr.rtm_scope = RT_SCOPE_UNIVERSE;
534 rt_message_hdr.rtm_type = RTN_UNICAST;
535 rt_message_hdr.rtm_dst_len = 128;
539 nl_message_hdr.nlmsg_type = RTM_NEWROUTE;
540 nl_message_hdr.nlmsg_flags =
541 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE
544 rt_req.
msg_len = NLMSG_LENGTH(
sizeof(rt_message_hdr));
546 rt_req.
insert_attr(RTA_DST,
sizeof(addr6), &addr6);
547 rt_req.
insert_attr(RTA_OIF,
sizeof(dev_idx), &dev_idx);
553 send_n = sendmsg(nl_sock.
fd(), msg, 0);
555 LOG(ERROR,
"Sendmsg failed,"
556 "MetadataProxy::NetlinkAddInterfaceRoute,"
557 " metadata_ipv6_netlink.cc, "
558 "errno = " << errno << std::endl);
struct nlmsghdr * resp_nh_
A pointer to the begin of the response.
void insert_attr(unsigned short attr_type, int attr_len, const void *attr_data)
Inserts an attribute stored in attr_data into this Netlink reequest.
unsigned int & msg_len
A reference to the total length of this Netlink request.
NetlinkResponse(msghdr *req_msg, NetlinkSocket &nl_sock)
Construct a NetlinkResponse object from the request message and the Netlink socket.
int n_recv_
The number of received bytes in the response.
~NetlinkResponse()
NetlinkResponse dtor.
bool ToArray(u_int8_t *p, size_t s) const
IPv6Reader(const unsigned int itf_idx)
int response_iterate(const T &handler_func)
Iterates over all response parts.
boost::asio::ip::address IpAddress
void insert_attr(nlmsghdr *nl_msg, unsigned short attr_type, int attr_len, const void *attr_data)
A wrapper function to insert an attribute into a netlink message.
char buffer_[16384]
A buffer for response data.
nlmsghdr nl_message_hdr
A structure carrying the main netlink header.
iovec iov_
An iovec struct to keep headers with data.
const std::string & vhost_interface_name() const
char payload[16384]
A block of memory of memory carrying attributes of this request.
int socket_fd
A Netlink socket ID (descriptor)
std::unique_ptr< msghdr > msg_ptr_
A pointer to the Netlink message header.
struct iovec iov_
Contains response data.
const NetlinkRequest & operator=(const NetlinkRequest< T > &)
Disallow assignment operator.
A class template to store Netlink request data.
const NetlinkSocket & operator=(const NetlinkSocket &nl)
Forbid the copy assignment.
boost::asio::ip::address_v6 Ip6Address
sockaddr_nl & netlink_socket()
Returns a reference to the Netlink socket sockaddr struct.
T nl_req_hdr
A structure carrying the request-specific header.
struct msghdr msg_
contains message with response
sockaddr_nl local_sock_addr
A Netlink socket sockaddr structure.
NetlinkResponse()
Forbid default ctor for NetlinkResponse.
NetlinkRequest()
Creates new blank request.
int operator()(const struct nlmsghdr *resp_nh) const
const int & fd() const
Returns a reference to the Netlink socket descriptor.
#define LOG(_Level, _Msg)
int read_ipv6_address(const struct nlmsghdr *resp_nh) const
NetlinkSocket()
Creates a socket and binds it with AF_NETLINK family.
A storage for the Netlink socket descriptor.
msghdr * message(sockaddr_nl &s_nl)
Returns a pointer to the Netlink message, generated using this class.
~NetlinkRequest()
NetlinkRequest dtor.
static bool read_ack_response(const msghdr *msg, int send_n, NetlinkSocket &nl_sock, const char *func_name)
Reads a response (ack/nock) after a Netlink request.
~NetlinkSocket()
Closes the Netlink connection.