xref: /openbmc/google-misc/subprojects/ncsid/src/ncsi_sockio.cpp (revision 7c15db6f4dcd1da68967ca2a463ef890d4521f56)
11285115cSWilliam A. Kennington III // Copyright 2021 Google LLC
21285115cSWilliam A. Kennington III //
31285115cSWilliam A. Kennington III // Licensed under the Apache License, Version 2.0 (the "License");
41285115cSWilliam A. Kennington III // you may not use this file except in compliance with the License.
51285115cSWilliam A. Kennington III // You may obtain a copy of the License at
61285115cSWilliam A. Kennington III //
71285115cSWilliam A. Kennington III //      http://www.apache.org/licenses/LICENSE-2.0
81285115cSWilliam A. Kennington III //
91285115cSWilliam A. Kennington III // Unless required by applicable law or agreed to in writing, software
101285115cSWilliam A. Kennington III // distributed under the License is distributed on an "AS IS" BASIS,
111285115cSWilliam A. Kennington III // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121285115cSWilliam A. Kennington III // See the License for the specific language governing permissions and
131285115cSWilliam A. Kennington III // limitations under the License.
141285115cSWilliam A. Kennington III 
151285115cSWilliam A. Kennington III #include "ncsi_sockio.h"
161285115cSWilliam A. Kennington III 
171285115cSWilliam A. Kennington III #include "common_defs.h"
181285115cSWilliam A. Kennington III #include "net_iface.h"
191285115cSWilliam A. Kennington III 
201285115cSWilliam A. Kennington III #include <linux/filter.h>
21adb8ffe4SWilly Tu #include <linux/if.h>
22adb8ffe4SWilly Tu #include <linux/if_ether.h>
231285115cSWilliam A. Kennington III #include <netinet/in.h>
241285115cSWilliam A. Kennington III #include <poll.h>
251285115cSWilliam A. Kennington III #include <sys/socket.h>
261285115cSWilliam A. Kennington III 
271285115cSWilliam A. Kennington III #include <cstring>
28adb8ffe4SWilly Tu #include <iterator>
291285115cSWilliam A. Kennington III 
301285115cSWilliam A. Kennington III namespace ncsi
311285115cSWilliam A. Kennington III {
321285115cSWilliam A. Kennington III 
init()331285115cSWilliam A. Kennington III int SockIO::init()
341285115cSWilliam A. Kennington III {
351285115cSWilliam A. Kennington III     RETURN_IF_ERROR(sockfd_ = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)),
361285115cSWilliam A. Kennington III                     "ncsi::SockIO::init() failed");
371285115cSWilliam A. Kennington III     return 0;
381285115cSWilliam A. Kennington III }
391285115cSWilliam A. Kennington III 
bind_to_iface(const net::IFaceBase & iface)401285115cSWilliam A. Kennington III int SockIO::bind_to_iface(const net::IFaceBase& iface)
411285115cSWilliam A. Kennington III {
42*7c15db6fSWilliam A. Kennington III     struct packet_mreq mreq = {};
43*7c15db6fSWilliam A. Kennington III     RETURN_IF_ERROR(mreq.mr_ifindex = iface.get_index(),
44*7c15db6fSWilliam A. Kennington III                     "ncsi::SockIO::bind_to_iface get_index");
45*7c15db6fSWilliam A. Kennington III     mreq.mr_type = PACKET_MR_PROMISC;
46*7c15db6fSWilliam A. Kennington III     RETURN_IF_ERROR(setsockopt(sockfd_, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
47*7c15db6fSWilliam A. Kennington III                                &mreq, sizeof(mreq)),
48*7c15db6fSWilliam A. Kennington III                     "ncsi::SockIO::bind_to_iface setsockopt failed");
491285115cSWilliam A. Kennington III 
50a9a98258SWilly Tu     RETURN_IF_ERROR(iface.bind_sock(sockfd_),
511285115cSWilliam A. Kennington III                     "ncsi::SockIO::bind_to_iface failed");
521285115cSWilliam A. Kennington III 
531285115cSWilliam A. Kennington III     return 0;
541285115cSWilliam A. Kennington III }
551285115cSWilliam A. Kennington III 
561285115cSWilliam A. Kennington III /**
571285115cSWilliam A. Kennington III  * Drops VLAN tagged packets from a socket
581285115cSWilliam A. Kennington III  *
591285115cSWilliam A. Kennington III  * ld vlant
601285115cSWilliam A. Kennington III  * jneq #0, drop
611285115cSWilliam A. Kennington III  * ld proto
621285115cSWilliam A. Kennington III  * jneq #0x88f8, drop
631285115cSWilliam A. Kennington III  * ret #-1
641285115cSWilliam A. Kennington III  * drop: ret #0
651285115cSWilliam A. Kennington III  */
661285115cSWilliam A. Kennington III struct sock_filter vlan_remove_code[] = {
671285115cSWilliam A. Kennington III     {0x20, 0, 0, 0xfffff02c}, {0x15, 0, 3, 0x00000000},
681285115cSWilliam A. Kennington III     {0x20, 0, 0, 0xfffff000}, {0x15, 0, 1, 0x000088f8},
691285115cSWilliam A. Kennington III     {0x6, 0, 0, 0xffffffff},  {0x6, 0, 0, 0x00000000}};
701285115cSWilliam A. Kennington III 
711285115cSWilliam A. Kennington III struct sock_fprog vlan_remove_bpf = {
721285115cSWilliam A. Kennington III     std::size(vlan_remove_code),
731285115cSWilliam A. Kennington III     vlan_remove_code,
741285115cSWilliam A. Kennington III };
751285115cSWilliam A. Kennington III 
filter_vlans()761285115cSWilliam A. Kennington III int SockIO::filter_vlans()
771285115cSWilliam A. Kennington III {
781285115cSWilliam A. Kennington III     return setsockopt(sockfd_, SOL_SOCKET, SO_ATTACH_FILTER, &vlan_remove_bpf,
791285115cSWilliam A. Kennington III                       sizeof(vlan_remove_bpf));
801285115cSWilliam A. Kennington III }
811285115cSWilliam A. Kennington III 
recv(void * buf,size_t maxlen)821285115cSWilliam A. Kennington III int SockIO::recv(void* buf, size_t maxlen)
831285115cSWilliam A. Kennington III {
84d980e4fcSPatrick Williams     struct pollfd sock_pollfd{sockfd_, POLLIN | POLLPRI, 0};
851285115cSWilliam A. Kennington III 
861285115cSWilliam A. Kennington III     int ret = poll(&sock_pollfd, 1, kpoll_timeout_);
871285115cSWilliam A. Kennington III     if (ret > 0)
881285115cSWilliam A. Kennington III     {
891285115cSWilliam A. Kennington III         return ::recv(sockfd_, buf, maxlen, 0);
901285115cSWilliam A. Kennington III     }
911285115cSWilliam A. Kennington III 
921285115cSWilliam A. Kennington III     return ret;
931285115cSWilliam A. Kennington III }
941285115cSWilliam A. Kennington III 
951285115cSWilliam A. Kennington III } // namespace ncsi
96