xref: /openbmc/phosphor-networkd/src/util.hpp (revision c38b0710)
1 #pragma once
2 
3 #include "config.h"
4 
5 #include "ethernet_interface.hpp"
6 #include "types.hpp"
7 
8 #include <netinet/ether.h>
9 #include <unistd.h>
10 
11 #include <cstring>
12 #include <optional>
13 #include <sdbusplus/bus.hpp>
14 #include <string>
15 #include <string_view>
16 #include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
17 
18 namespace phosphor
19 {
20 namespace network
21 {
22 
23 using EthernetInterfaceIntf =
24     sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface;
25 
26 constexpr auto IPV4_MIN_PREFIX_LENGTH = 1;
27 constexpr auto IPV4_MAX_PREFIX_LENGTH = 32;
28 constexpr auto IPV6_MAX_PREFIX_LENGTH = 128;
29 constexpr auto IPV4_PREFIX = "169.254";
30 constexpr auto IPV6_PREFIX = "fe80";
31 
32 namespace mac_address
33 {
34 
35 /** @brief gets the MAC address from the Inventory.
36  *  @param[in] bus - DBUS Bus Object.
37  *  @param[in] intfName - Interface name
38  */
39 ether_addr getfromInventory(sdbusplus::bus_t& bus, const std::string& intfName);
40 
41 /** @brief Converts the given mac address into byte form
42  *  @param[in] str - The mac address in human readable form
43  *  @returns A mac address in network byte order
44  *  @throws std::runtime_error for bad mac
45  */
46 ether_addr fromString(const char* str);
47 inline ether_addr fromString(const std::string& str)
48 {
49     return fromString(str.c_str());
50 }
51 
52 /** @brief Converts the given mac address bytes into a string
53  *  @param[in] mac - The mac address
54  *  @returns A valid mac address string
55  */
56 std::string toString(const ether_addr& mac);
57 
58 /** @brief Determines if the mac address is empty
59  *  @param[in] mac - The mac address
60  *  @return True if 00:00:00:00:00:00
61  */
62 bool isEmpty(const ether_addr& mac);
63 
64 /** @brief Determines if the mac address is a multicast address
65  *  @param[in] mac - The mac address
66  *  @return True if multicast bit is set
67  */
68 bool isMulticast(const ether_addr& mac);
69 
70 /** @brief Determines if the mac address is a unicast address
71  *  @param[in] mac - The mac address
72  *  @return True if not multicast or empty
73  */
74 bool isUnicast(const ether_addr& mac);
75 
76 } // namespace mac_address
77 
78 constexpr auto networkdService = "systemd-networkd.service";
79 constexpr auto timeSynchdService = "systemd-timesyncd.service";
80 
81 /* @brief converts the given subnet into prefix notation.
82  * @param[in] addressFamily - IP address family(AF_INET/AF_INET6).
83  * @param[in] mask - Subnet Mask.
84  * @returns prefix.
85  */
86 uint8_t toCidr(int addressFamily, const std::string& mask);
87 
88 /* @brief converts a sockaddr for the specified address family into
89  *        a type_safe InAddrAny.
90  * @param[in] addressFamily - The address family of the buf
91  * @param[in] buf - The network byte order address
92  */
93 InAddrAny addrFromBuf(int addressFamily, std::string_view buf);
94 
95 /* @brief converts the ip bytes into a string representation
96  * @param[in] addr - input ip address to convert.
97  * @returns String representation of the ip.
98  */
99 std::string toString(const InAddrAny& addr);
100 std::string toString(const struct in_addr& addr);
101 std::string toString(const struct in6_addr& addr);
102 
103 /* @brief converts the prefix into subnetmask.
104  * @param[in] addressFamily - IP address family(AF_INET/AF_INET6).
105  * @param[in] prefix - prefix length.
106  * @returns subnet mask.
107  */
108 std::string toMask(int addressFamily, uint8_t prefix);
109 
110 /* @brief checks that the given ip address is link local or not.
111  * @param[in] address - IP address.
112  * @returns true if it is linklocal otherwise false.
113  */
114 bool isLinkLocalIP(const std::string& address);
115 
116 /* @brief checks that the given ip address valid or not.
117  * @param[in] addressFamily - IP address family(AF_INET/AF_INET6).
118  * @param[in] address - IP address.
119  * @returns true if it is valid otherwise false.
120  */
121 bool isValidIP(int addressFamily, const std::string& address);
122 
123 /* @brief checks that the given prefix is valid or not.
124  * @param[in] addressFamily - IP address family(AF_INET/AF_INET6).
125  * @param[in] prefix - prefix length.
126  * @returns true if it is valid otherwise false.
127  */
128 bool isValidPrefix(int addressFamily, uint8_t prefixLength);
129 
130 /** @brief Gets the map of interface and the associated
131  *         address.
132  *  @returns map of interface and the address.
133  */
134 IntfAddrMap getInterfaceAddrs();
135 
136 /** @brief Get all the interfaces from the system.
137  *  @returns list of interface names.
138  */
139 InterfaceList getInterfaces();
140 
141 /** @brief Delete the given interface.
142  *  @param[in] intf - interface name.
143  */
144 void deleteInterface(const std::string& intf);
145 
146 /** @brief Converts the interface name into a u-boot environment
147  *         variable that would hold its ethernet address.
148  *
149  *  @param[in] intf - interface name
150  *  @return The name of th environment key
151  */
152 std::optional<std::string> interfaceToUbootEthAddr(const char* intf);
153 
154 /** @brief read the DHCP value from the configuration file
155  *  @param[in] confDir - Network configuration directory.
156  *  @param[in] intf - Interface name.
157  */
158 EthernetInterfaceIntf::DHCPConf getDHCPValue(const std::string& confDir,
159                                              const std::string& intf);
160 
161 namespace internal
162 {
163 
164 /* @brief runs the given command in child process.
165  * @param[in] path - path of the binary file which needs to be execeuted.
166  * @param[in] args - arguments of the command.
167  */
168 void executeCommandinChildProcess(const char* path, char** args);
169 
170 /** @brief Get ignored interfaces from environment */
171 std::string_view getIgnoredInterfacesEnv();
172 
173 /** @brief Parse the comma separated interface names */
174 std::set<std::string_view> parseInterfaces(std::string_view interfaces);
175 
176 /** @brief Get the ignored interfaces */
177 const std::set<std::string_view>& getIgnoredInterfaces();
178 
179 } // namespace internal
180 
181 /* @brief runs the given command in child process.
182  * @param[in] path -path of the binary file which needs to be execeuted.
183  * @param[in] tArgs - arguments of the command.
184  */
185 template <typename... ArgTypes>
186 void execute(const char* path, ArgTypes&&... tArgs)
187 {
188     using expandType = char*[];
189 
190     expandType args = {const_cast<char*>(tArgs)..., nullptr};
191 
192     internal::executeCommandinChildProcess(path, args);
193 }
194 
195 } // namespace network
196 
197 class Descriptor
198 {
199   private:
200     /** default value */
201     int fd = -1;
202 
203   public:
204     Descriptor() = default;
205     Descriptor(const Descriptor&) = delete;
206     Descriptor& operator=(const Descriptor&) = delete;
207     Descriptor(Descriptor&&) = delete;
208     Descriptor& operator=(Descriptor&&) = delete;
209 
210     explicit Descriptor(int fd) : fd(fd)
211     {
212     }
213 
214     /* @brief sets the internal file descriptor with the given descriptor
215      *        and closes the old descriptor.
216      * @param[in] descriptor - File/Socket descriptor.
217      */
218     void set(int descriptor)
219     {
220         // same descriptor given
221         if (fd == descriptor)
222         {
223             return;
224         }
225 
226         // close the old descriptor
227         if (fd >= 0)
228         {
229             close(fd);
230         }
231 
232         fd = descriptor;
233     }
234 
235     ~Descriptor()
236     {
237         if (fd >= 0)
238         {
239             close(fd);
240         }
241     }
242 
243     int operator()() const
244     {
245         return fd;
246     }
247 };
248 
249 } // namespace phosphor
250