xref: /openbmc/google-misc/acpi-power-state-daemon/subprojects/ncsid/src/net_iface.cpp (revision dab96f131fb3a46d93f1093feccc9095d8589ece)
1* // 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* 
15* #include "net_iface.h"
16* 
17* #include <linux/if_packet.h>
18* #include <net/ethernet.h>
19* #include <sys/socket.h>
20* #include <unistd.h>
21* 
22* #include <cstdio>
23* #include <cstring>
24* #include <stdexcept>
25* 
26* namespace net
27* {
28* 
29* IFaceBase::IFaceBase(const std::string& name) : name_{name}
30* {
31*     if (name.size() >= IFNAMSIZ)
32*     {
33*         throw std::length_error("Interface name is too long");
34*     }
35* }
36* 
37* int IFaceBase::get_index() const
38* {
39*     struct ifreq ifr;
40*     std::memset(&ifr, 0, sizeof(ifr));
41*     int ret = ioctl(SIOCGIFINDEX, &ifr);
42*     if (ret < 0)
43*     {
44*         return ret;
45*     }
46* 
47*     return ifr.ifr_ifindex;
48* }
49* 
50* int IFaceBase::set_sock_flags(int sockfd, short flags) const
51* {
52*     return mod_sock_flags(sockfd, flags, true);
53* }
54* 
55* int IFaceBase::clear_sock_flags(int sockfd, short flags) const
56* {
57*     return mod_sock_flags(sockfd, flags, false);
58* }
59* 
60* int IFaceBase::mod_sock_flags(int sockfd, short flags, bool set) const
61* {
62*     struct ifreq ifr;
63*     std::memset(&ifr, 0, sizeof(ifr));
64* 
65*     int ret = ioctl_sock(sockfd, SIOCGIFFLAGS, &ifr);
66*     if (ret < 0)
67*     {
68*         return ret;
69*     }
70* 
71*     if (set)
72*     {
73*         ifr.ifr_flags |= flags;
74*     }
75*     else
76*     {
77*         ifr.ifr_flags &= ~flags;
78*     }
79*     return ioctl_sock(sockfd, SIOCSIFFLAGS, &ifr);
80* }
81* 
82* int IFace::ioctl_sock(int sockfd, int request, struct ifreq* ifr) const
83* {
84*     if (ifr == nullptr)
85*     {
86*         return -1;
87*     }
88* 
89*     /* Avoid string truncation. */
90*     size_t len = name_.length();
91*     if (len + 1 >= sizeof(ifr->ifr_name))
92*     {
93*         return -1;
94*     }
95* 
96*     std::memcpy(ifr->ifr_name, name_.c_str(), len);
97*     ifr->ifr_name[len] = 0;
98* 
99*     return ::ioctl(sockfd, request, ifr);
100* }
101* 
102* int IFace::bind_sock(int sockfd, struct sockaddr_ll* saddr) const
103* {
104*     if (saddr == nullptr)
105*     {
106*         return -1;
107*     }
108* 
109*     saddr->sll_ifindex = get_index();
110* 
111*     return bind(sockfd, reinterpret_cast<struct sockaddr*>(saddr),
112*                 sizeof(*saddr));
113* }
114* 
115* int IFace::ioctl(int request, struct ifreq* ifr) const
116* {
117*     if (ifr == nullptr)
118*     {
119*         return -1;
120*     }
121* 
122*     int tempsock = socket(AF_INET, SOCK_DGRAM, 0);
123*     if (tempsock < 0)
124*     {
125*         return tempsock;
126*     }
127* 
128*     int ret = ioctl_sock(tempsock, request, ifr);
129*     close(tempsock);
130* 
131*     return ret;
132* }
133* 
134* } // namespace net
135*