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