7 #include <bits/sockaddr.h>
8 #include <linux/netlink.h>
9 #include <linux/rtnetlink.h>
30 int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
33 LOG(ERROR,
"Error <" << errno <<
": " << strerror(errno) <<
39 struct sockaddr_nl addr;
40 memset (&addr, 0,
sizeof(addr));
41 addr.nl_family = AF_NETLINK;
42 addr.nl_groups = (RTMGRP_IPV4_ROUTE | RTMGRP_LINK | RTMGRP_IPV4_IFADDR);
43 if (bind(s, (
struct sockaddr *)&addr,
sizeof(addr)) == -1) {
44 LOG(ERROR,
"Error <" << errno <<
": " << strerror(errno) <<
45 "> binding to netlink address family. BackTrace: "
74 nlh = (
struct nlmsghdr *)
tx_buf_;
77 nlh->nlmsg_len = NLMSG_LENGTH(
sizeof(
struct rtgenmsg));
78 nlh->nlmsg_type =
type;
80 nlh->nlmsg_flags = (NLM_F_DUMP | NLM_F_REQUEST);
81 nlh->nlmsg_seq = seqno;
83 struct rtgenmsg *rt_gen = (
struct rtgenmsg *) NLMSG_DATA (nlh);
84 rt_gen->rtgen_family = AF_PACKET;
86 boost::system::error_code ec;
87 sock_.send(boost::asio::buffer(nlh,nlh->nlmsg_len), 0, ec);
88 assert(ec.value() == 0);
90 uint8_t read_buf[buf_size];
98 memset(read_buf, 0, buf_size);
99 std::size_t len =
sock_.receive(boost::asio::buffer(read_buf,
101 assert(ec.value() == 0);
102 struct nlmsghdr *nl = (
struct nlmsghdr *)read_buf;
112 boost::asio::placeholders::error,
113 boost::asio::placeholders::bytes_transferred));
118 const boost::system::error_code &error, std::size_t len) {
119 struct nlmsghdr *nlh;
125 LOG(ERROR,
"Error < : " << error.message() <<
126 "> reading packet on netlink sock");
141 struct nlmsghdr *n = (
struct nlmsghdr *)buff;
142 int len = RTA_LENGTH(alen);
147 struct rtattr *rta = (
struct rtattr*)(((
char*)n)+NLMSG_ALIGN(n->nlmsg_len));
148 rta->rta_type =
type;
150 memcpy(RTA_DATA(rta), data, alen);
151 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
158 struct nlmsghdr *nlh;
164 nlh = (
struct nlmsghdr *)
tx_buf_;
165 rtm = (
struct rtmsg *) NLMSG_DATA (nlh);
168 nlh->nlmsg_len = NLMSG_LENGTH(
sizeof(
struct rtmsg));
170 nlh->nlmsg_type = RTM_DELROUTE;
171 nlh->nlmsg_flags = NLM_F_REQUEST;
173 nlh->nlmsg_type = RTM_NEWROUTE;
174 nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
176 nlh->nlmsg_seq = ++
seqno_;
177 rtm = (
struct rtmsg *) NLMSG_DATA (nlh);
178 rtm->rtm_table = RT_TABLE_MAIN;
179 rtm->rtm_family = AF_INET;
180 rtm->rtm_type = RTN_UNICAST;
182 rtm->rtm_scope = RT_SCOPE_LINK;
183 rtm->rtm_dst_len = plen;
184 ipaddr = RT_TABLE_MAIN;
186 ipaddr = htonl(addr.to_ulong());
191 boost::system::error_code ec;
192 sock_.send(boost::asio::buffer(nlh,nlh->nlmsg_len), 0, ec);
193 assert(ec.value() == 0);
205 return "RTM_NEWADDR";
207 return "RTM_DELADDR";
209 return "RTM_NEWROUTE";
211 return "RTM_DELROUTE";
213 return "RTM_NEWLINK";
215 return "RTM_DELLINK";
219 std::stringstream str;
220 str <<
"UNHANDLED <" << type <<
">";
226 struct rtmsg *rtm = (
struct rtmsg *) NLMSG_DATA (nlh);
228 if (rtm->rtm_family != AF_INET || rtm->rtm_table != RT_TABLE_MAIN
229 || rtm->rtm_type != RTN_UNICAST || rtm->rtm_scope != RT_SCOPE_LINK) {
230 LOG(DEBUG,
"Ignoring Netlink route with family "
231 << (uint32_t)rtm->rtm_family
232 <<
" table " << (uint32_t)rtm->rtm_table
233 <<
" type " << (uint32_t)rtm->rtm_type
234 <<
" scope " << (uint32_t)rtm->rtm_scope);
243 int rtl = RTM_PAYLOAD(nlh);
246 for (
struct rtattr *rth = (
struct rtattr *) RTM_RTA(rtm);
247 RTA_OK(rth, rtl); rth = RTA_NEXT(rth, rtl)) {
249 if (rth->rta_type == RTA_DST) {
250 dst_ip = *((
int *)RTA_DATA(rth));
252 if (rth->rta_type == RTA_GATEWAY) {
253 gw_ip = *((
int *)RTA_DATA(rth));
255 if (rth->rta_type == RTA_OIF) {
256 oif = *((
int *)RTA_DATA(rth));
265 if_indextoname(oif, name);
266 Ip4Address dst_addr((
unsigned long)ntohl(dst_ip));
267 Ip4Address gw_addr((
unsigned long)ntohl(gw_ip));
268 LOG(DEBUG,
"Handle netlink route message "
270 <<
" : " << dst_addr.to_string() <<
"/"
271 << (
unsigned short)rtm->rtm_dst_len
272 <<
" Interface " << name <<
" GW " << gw_addr.to_string());
275 if (nlh->nlmsg_type == RTM_DELROUTE) {
281 return new Event(type, dst_addr, rtm->rtm_dst_len, name, gw_addr,
282 rtm->rtm_protocol, rtm->rtm_flags);
288 int rtl = RTM_PAYLOAD(nlh);
290 const char *port_name = NULL;
291 struct ifinfomsg *ifi = (
struct ifinfomsg *) NLMSG_DATA (nlh);
293 for (
struct rtattr *rth = IFLA_RTA(ifi); RTA_OK(rth, rtl);
294 rth = RTA_NEXT(rth, rtl)) {
296 if (rth->rta_type == IFLA_IFNAME) {
297 port_name = (
char *) RTA_DATA(rth);
301 assert(port_name != NULL);
302 LOG(DEBUG,
"Handle netlink interface message "
304 <<
" for interface " << port_name <<
" flags " << ifi->ifi_flags);
307 if (nlh->nlmsg_type == RTM_DELLINK) {
312 return new Event(type, port_name, ifi->ifi_flags, ifi->ifi_type);
317 struct ifaddrmsg *ifa = (
struct ifaddrmsg *) NLMSG_DATA (nlh);
321 if_indextoname(ifa->ifa_index, name);
323 LOG(DEBUG,
"Handle netlink address message "
327 int rtl = IFA_PAYLOAD(nlh);
328 for (
struct rtattr *rth = IFA_RTA(ifa); rtl && RTA_OK(rth, rtl);
329 rth = RTA_NEXT(rth,rtl)) {
330 if (rth->rta_type != IFA_LOCAL) {
334 ipaddr = ntohl(* ((uint32_t *)RTA_DATA(rth)));
342 if (nlh->nlmsg_type == RTM_DELADDR) {
348 ifa->ifa_flags,
false);
352 std::size_t len, uint32_t seq_no) {
354 struct nlmsghdr *nlh = nl;
355 for (; (NLMSG_OK(nlh, len)); nlh = NLMSG_NEXT(nlh, len)) {
357 switch (nlh->nlmsg_type) {
359 if (nlh->nlmsg_seq == seq_no) {
376 LOG(DEBUG,
"VnswInterfaceListenerLinux got message : "
int NlMsgDecode(struct nlmsghdr *nl, std::size_t len, uint32_t seq_no)
WorkQueue< Event * > * revent_queue_
Event * HandleNetlinkAddrMsg(struct nlmsghdr *)
static const int kVnswRtmProto
const std::string & vhost_interface_name() const
uint8_t tx_buf_[kMaxBufferSize]
int AddAttr(uint8_t *, int, void *, int)
void ReadHandler(const boost::system::error_code &, std::size_t length)
void InitNetlinkScan(uint32_t type, uint32_t seqno)
local::datagram_protocol::socket sock_
Event * HandleNetlinkIntfMsg(struct nlmsghdr *)
VnswInterfaceListenerLinux(Agent *agent)
virtual ~VnswInterfaceListenerLinux()
void UpdateLinkLocalRoute(const Ip4Address &addr, uint8_t plen, bool del_rt)
boost::asio::ip::address_v4 Ip4Address
std::string AgentBackTrace(int skip=1)
static const uint32_t kMaxBufferSize
#define LOG(_Level, _Msg)
string NetlinkTypeToString(uint32_t)
virtual void SyncCurrentState()
virtual void RegisterAsyncReadHandler()
Event * HandleNetlinkRouteMsg(struct nlmsghdr *)