blob: 21582647aa34ab22820cfa9ee57fcdf83c0a4297 [file] [log] [blame]
Brandon Kimdab96f12021-02-18 11:21:37 -08001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
William A. Kennington III7d6fa422021-02-08 17:04:02 -080015#include "ncsi_sockio.h"
16
17#include "common_defs.h"
18#include "net_iface.h"
19
20#include <linux/filter.h>
21#include <netinet/in.h>
22#include <poll.h>
23#include <sys/socket.h>
24#include <sys/types.h>
25
26#include <cstdio>
27#include <cstring>
28
29namespace ncsi
30{
31
32int SockIO::init()
33{
34 RETURN_IF_ERROR(sockfd_ = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)),
35 "ncsi::SockIO::init() failed");
36 return 0;
37}
38
39int SockIO::bind_to_iface(const net::IFaceBase& iface)
40{
41 iface.set_sock_flags(sockfd_, IFF_PROMISC);
42
43 std::memset(&sock_addr_, 0, sizeof(sock_addr_));
44
45 sock_addr_.sll_family = AF_PACKET;
46 sock_addr_.sll_protocol = htons(ETH_P_ALL);
47
48 RETURN_IF_ERROR(iface.bind_sock(sockfd_, &sock_addr_),
49 "ncsi::SockIO::bind_to_iface failed");
50
51 return 0;
52}
53
54/**
55 * Drops VLAN tagged packets from a socket
56 *
57 * ld vlant
58 * jneq #0, drop
59 * ld proto
60 * jneq #0x88f8, drop
61 * ret #-1
62 * drop: ret #0
63 */
64struct sock_filter vlan_remove_code[] = {
65 {0x20, 0, 0, 0xfffff02c}, {0x15, 0, 3, 0x00000000},
66 {0x20, 0, 0, 0xfffff000}, {0x15, 0, 1, 0x000088f8},
67 {0x6, 0, 0, 0xffffffff}, {0x6, 0, 0, 0x00000000}};
68
69struct sock_fprog vlan_remove_bpf = {
70 std::size(vlan_remove_code),
71 vlan_remove_code,
72};
73
74int SockIO::filter_vlans()
75{
76 return setsockopt(sockfd_, SOL_SOCKET, SO_ATTACH_FILTER, &vlan_remove_bpf,
77 sizeof(vlan_remove_bpf));
78}
79
80int SockIO::recv(void* buf, size_t maxlen)
81{
82 struct pollfd sock_pollfd
83 {
84 sockfd_, POLLIN | POLLPRI, 0
85 };
86
87 int ret = poll(&sock_pollfd, 1, kpoll_timeout_);
88 if (ret > 0)
89 {
90 return ::recv(sockfd_, buf, maxlen, 0);
91 }
92
93 return ret;
94}
95
96} // namespace ncsi