#include "babd.h" #include #include #include #include #include #include #include "netlink.h" #include "bvirt_ns.h" bnetlink_t::bnetlink_t(bvirt_ns_t *netns) { struct sockaddr_nl sa; m_netns = netns; nl_fd = netns_socket(netns, PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (nl_fd == -1) { perror("socket(PF_NETLINK)"); return; } sa.nl_family = AF_NETLINK; sa.nl_pad = 0; sa.nl_pid = getpid(); sa.nl_groups = RTMGRP_LINK; if (-1 == bind(nl_fd, (struct sockaddr *)&sa, sizeof sa)) { perror("bind(netlink"); close(nl_fd); nl_fd = -1; return; } int bufsize = 1024*1024*4; if (setsockopt(nl_fd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) < 0) perror("bnetlink_h::bnetlink_t setsockopt(SO_RCVBUF)"); make_nonblock(nl_fd); SelectAddEvent(nl_fd, SEL_READ); } bnetlink_t::~bnetlink_t() { SelectSetEvents(nl_fd, SEL_NONE); } void bnetlink_t::SelectEvent(int fd, SelectEventType event) { static char buf[1024*1024]; int size; do { size = read(fd, buf, sizeof buf); if (size < 0) { if (EAGAIN != errno) perror("bnetlink_t::SelectEvents: read"); return; } if (size > 0) parse_netlink(buf, size); } while (size > 0); } void bnetlink_t::parse_newlink(struct nlmsghdr *nlh) { struct ifinfomsg *ifm = (struct ifinfomsg *)(nlh + 1); iface_change_flags(m_netns, ifm->ifi_index, ifm->ifi_flags, ifm->ifi_change); } void bnetlink_t::parse_netlink(void *buf, size_t size) { if (size < sizeof(struct nlmsghdr)) return; struct nlmsghdr *nlmsg = (struct nlmsghdr *)buf; if (nlmsg->nlmsg_len != size) return; switch(nlmsg->nlmsg_type) { case RTM_NEWLINK: parse_newlink(nlmsg); return; case RTM_DELLINK: return; } } bnetlink_t *bnetlink; void init_netlink(void) { bnetlink = new bnetlink_t(NULL); }