1 #include "ncsi_sockio.h" 2 3 #include "common_defs.h" 4 #include "net_iface.h" 5 6 #include <linux/filter.h> 7 #include <netinet/in.h> 8 #include <poll.h> 9 #include <sys/socket.h> 10 #include <sys/types.h> 11 12 #include <cstdio> 13 #include <cstring> 14 15 namespace ncsi 16 { 17 18 int SockIO::init() 19 { 20 RETURN_IF_ERROR(sockfd_ = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)), 21 "ncsi::SockIO::init() failed"); 22 return 0; 23 } 24 25 int SockIO::bind_to_iface(const net::IFaceBase& iface) 26 { 27 iface.set_sock_flags(sockfd_, IFF_PROMISC); 28 29 std::memset(&sock_addr_, 0, sizeof(sock_addr_)); 30 31 sock_addr_.sll_family = AF_PACKET; 32 sock_addr_.sll_protocol = htons(ETH_P_ALL); 33 34 RETURN_IF_ERROR(iface.bind_sock(sockfd_, &sock_addr_), 35 "ncsi::SockIO::bind_to_iface failed"); 36 37 return 0; 38 } 39 40 /** 41 * Drops VLAN tagged packets from a socket 42 * 43 * ld vlant 44 * jneq #0, drop 45 * ld proto 46 * jneq #0x88f8, drop 47 * ret #-1 48 * drop: ret #0 49 */ 50 struct sock_filter vlan_remove_code[] = { 51 {0x20, 0, 0, 0xfffff02c}, {0x15, 0, 3, 0x00000000}, 52 {0x20, 0, 0, 0xfffff000}, {0x15, 0, 1, 0x000088f8}, 53 {0x6, 0, 0, 0xffffffff}, {0x6, 0, 0, 0x00000000}}; 54 55 struct sock_fprog vlan_remove_bpf = { 56 std::size(vlan_remove_code), 57 vlan_remove_code, 58 }; 59 60 int SockIO::filter_vlans() 61 { 62 return setsockopt(sockfd_, SOL_SOCKET, SO_ATTACH_FILTER, &vlan_remove_bpf, 63 sizeof(vlan_remove_bpf)); 64 } 65 66 int SockIO::recv(void* buf, size_t maxlen) 67 { 68 struct pollfd sock_pollfd 69 { 70 sockfd_, POLLIN | POLLPRI, 0 71 }; 72 73 int ret = poll(&sock_pollfd, 1, kpoll_timeout_); 74 if (ret > 0) 75 { 76 return ::recv(sockfd_, buf, maxlen, 0); 77 } 78 79 return ret; 80 } 81 82 } // namespace ncsi 83