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