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