blob: 7c3ee31d5451525d467e3cb6dc996ec592209be9 [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>
Willy Tuadb8ffe2023-07-17 13:44:22 -070021#include <linux/if.h>
22#include <linux/if_ether.h>
William A. Kennington III7d6fa422021-02-08 17:04:02 -080023#include <netinet/in.h>
24#include <poll.h>
25#include <sys/socket.h>
William A. Kennington III7d6fa422021-02-08 17:04:02 -080026
William A. Kennington III7d6fa422021-02-08 17:04:02 -080027#include <cstring>
Willy Tuadb8ffe2023-07-17 13:44:22 -070028#include <iterator>
William A. Kennington III7d6fa422021-02-08 17:04:02 -080029
30namespace ncsi
31{
32
33int SockIO::init()
34{
35 RETURN_IF_ERROR(sockfd_ = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)),
36 "ncsi::SockIO::init() failed");
37 return 0;
38}
39
40int SockIO::bind_to_iface(const net::IFaceBase& iface)
41{
William A. Kennington III7c15db62025-02-19 15:35:44 -080042 struct packet_mreq mreq = {};
43 RETURN_IF_ERROR(mreq.mr_ifindex = iface.get_index(),
44 "ncsi::SockIO::bind_to_iface get_index");
45 mreq.mr_type = PACKET_MR_PROMISC;
46 RETURN_IF_ERROR(setsockopt(sockfd_, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
47 &mreq, sizeof(mreq)),
48 "ncsi::SockIO::bind_to_iface setsockopt failed");
William A. Kennington III7d6fa422021-02-08 17:04:02 -080049
Willy Tua9a98252023-09-18 14:49:23 -070050 RETURN_IF_ERROR(iface.bind_sock(sockfd_),
William A. Kennington III7d6fa422021-02-08 17:04:02 -080051 "ncsi::SockIO::bind_to_iface failed");
52
53 return 0;
54}
55
56/**
57 * Drops VLAN tagged packets from a socket
58 *
59 * ld vlant
60 * jneq #0, drop
61 * ld proto
62 * jneq #0x88f8, drop
63 * ret #-1
64 * drop: ret #0
65 */
66struct sock_filter vlan_remove_code[] = {
67 {0x20, 0, 0, 0xfffff02c}, {0x15, 0, 3, 0x00000000},
68 {0x20, 0, 0, 0xfffff000}, {0x15, 0, 1, 0x000088f8},
69 {0x6, 0, 0, 0xffffffff}, {0x6, 0, 0, 0x00000000}};
70
71struct sock_fprog vlan_remove_bpf = {
72 std::size(vlan_remove_code),
73 vlan_remove_code,
74};
75
76int SockIO::filter_vlans()
77{
78 return setsockopt(sockfd_, SOL_SOCKET, SO_ATTACH_FILTER, &vlan_remove_bpf,
79 sizeof(vlan_remove_bpf));
80}
81
82int SockIO::recv(void* buf, size_t maxlen)
83{
Patrick Williamsd980e4f2024-12-18 11:22:27 -050084 struct pollfd sock_pollfd{sockfd_, POLLIN | POLLPRI, 0};
William A. Kennington III7d6fa422021-02-08 17:04:02 -080085
86 int ret = poll(&sock_pollfd, 1, kpoll_timeout_);
87 if (ret > 0)
88 {
89 return ::recv(sockfd_, buf, maxlen, 0);
90 }
91
92 return ret;
93}
94
95} // namespace ncsi