1 /******************************************************************************* 2 * 3 * Copyright (c) 2020 Jean-Francois Dockes 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * - Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * - Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * - Neither name of Intel Corporation nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 ******************************************************************************/ 30 #ifndef _NETIF_H_INCLUDED_ 31 #define _NETIF_H_INCLUDED_ 32 33 /** @file netif.h 34 * 35 * @brief Implement a simplified and system-idependant interface to a 36 * system's network interfaces. 37 */ 38 #include <stdio.h> 39 #include <string> 40 #include <ostream> 41 #include <vector> 42 #ifdef _WIN32 43 #include <winsock2.h> 44 #else 45 #include <sys/socket.h> 46 #include <netinet/in.h> 47 #endif 48 49 #include "UpnpGlobal.h" 50 51 namespace NetIF { 52 53 /** @brief Represent an IPV4 or IPV6 address */ 54 class EXPORT_SPEC IPAddr { 55 public: 56 /** @brief address family types. The values are identifal to the 57 * system's definitions */ 58 enum class Family {Invalid = -1, IPV4 = AF_INET, IPV6 = AF_INET6}; 59 /** @brief IPV6 address scope type */ 60 enum class Scope {Invalid = -1, LINK, SITE, GLOBAL}; 61 IPAddr(); 62 /** @brief Build from textual representation (e.g. 192.168.4.4) */ 63 explicit IPAddr(const char *); 64 /** @brief Build from textual representation (e.g. 192.168.4.4) */ IPAddr(const std::string & s)65 explicit IPAddr(const std::string& s) 66 : IPAddr(s.c_str()) {} 67 /** @brief Build from binary address in network byte order. 68 * @param unmapv4 if true we test for a v6 mapped v4 address and, if found, store it as v4 69 */ 70 explicit IPAddr(const struct sockaddr *sa, bool unmapv4=true); 71 72 IPAddr(const IPAddr&); 73 IPAddr& operator=(const IPAddr&); 74 ~IPAddr(); 75 76 /** @brief Check constructor success */ 77 bool ok() const; 78 /** Set the scopeidx from other address. Only does anything for ipv6 link-local addresses */ 79 bool setScopeIdx(const IPAddr& other); 80 /** @brief Returns the address family */ 81 Family family() const; 82 /** @brief Returns the scope type of IPV6 address */ 83 Scope scopetype() const; 84 /** @brief Copies out for use with a system interface 85 * Zeroes out up to sizeof(sockaddr_storage) */ 86 bool copyToStorage(struct sockaddr_storage *dest) const; 87 /** @brief Copies out for use with a system interface 88 * Copies exactly the needed size */ 89 bool copyToAddr(struct sockaddr *dest) const; 90 91 /** @brief Get reference to the internal binary address */ 92 const struct sockaddr_storage& getaddr() const; 93 94 /** @brief Convert to textual representation. */ 95 std::string straddr() const; 96 /** @brief Convert to textual representation. 97 * Possibly add scope id, possibly url-encode it. */ 98 std::string straddr(bool setscope, bool forurl) const; 99 100 friend class Interface; 101 class Internal; 102 private: 103 Internal *m; 104 }; 105 106 /** @brief Represent a system network interface, its attributes and its 107 * addresses. Usually built by the module internal code by 108 * querying the system interfaces. */ 109 class EXPORT_SPEC Interface { 110 public: 111 /** @brief Interface attributes */ 112 enum class Flags {NONE = 0, HASIPV4 = 1, HASIPV6 = 2, LOOPBACK=4, 113 UP=8, MULTICAST=0x10, HASHWADDR=0x20}; 114 Interface(); 115 /** @brief Construct empty interface with just the name set */ 116 Interface(const char *nm); 117 /** @brief Construct empty interface with just the name set */ 118 Interface(const std::string &nm); 119 ~Interface(); 120 Interface(const Interface&); 121 Interface& operator=(const Interface&); 122 123 /** @brief Return the interface name */ 124 const std::string& getname() const; 125 /** @brief Return the interface friendly name (same as name except 126 * on Windows). */ 127 const std::string& getfriendlyname() const; 128 129 /** Return the hardware (ethernet) address as a binary string (can have 130 * embedded null characters). Empty if no hardware address was 131 * found for this interface */ 132 const std::string& gethwaddr() const; 133 /** @brief Return hardware address in traditional colon-separated hex */ 134 std::string gethexhwaddr() const; 135 /** @brief test if flag is set */ 136 bool hasflag(Flags f) const; 137 /** @brief Remove all addresses not in the input vector */ 138 bool trimto(const std::vector<IPAddr>& keep); 139 /** @brief Return the first ipv4 address if any, or nullptr */ 140 const IPAddr *firstipv4addr() const; 141 /** @brief Return the first ipv6 address if any, or nullptr */ 142 const IPAddr *firstipv6addr( 143 IPAddr::Scope scope = IPAddr::Scope::Invalid) const; 144 /** @brief Return the interface addresses and the corresponding 145 * netmasks, as parallel arrays */ 146 std::pair<const std::vector<IPAddr>&, const std::vector<IPAddr>&> 147 getaddresses() const; 148 /** @brief Return the interface index */ 149 int getindex() const; 150 151 /** @brief Print out, a bit like "ip addr" output */ 152 std::ostream& print(std::ostream&) const; 153 154 class Internal; 155 friend class Interfaces; 156 private: 157 Internal *m{nullptr}; 158 }; 159 160 161 /** @brief Represent the system's network interfaces. Singleton class. */ 162 class EXPORT_SPEC Interfaces { 163 public: 164 /** @brief Return the Interfaces singleton after possibly building 165 * it by querying the system */ 166 static Interfaces *theInterfaces(); 167 168 /** @brief Read the state from the system again */ 169 bool refresh(); 170 171 /** @brief Find interface by name or friendlyname */ 172 Interface *findByName(const char*nm) const; 173 /** @brief Find interface by name or friendlyname */ findByName(const std::string & nm)174 Interface *findByName(const std::string& nm) const{ 175 return findByName(nm.c_str()); 176 } 177 178 /** @brief Argument to the select() method: flags which we want or don't */ 179 struct Filter { 180 /** @brief flags we want. */ 181 std::vector<Interface::Flags> needs; 182 /** @brief flags we don't want.*/ 183 std::vector<Interface::Flags> rejects; 184 }; 185 186 /** @brief Return Interface objects satisfying the criteria in f. */ 187 std::vector<Interface> select(const Filter& f) const; 188 189 /** @brief Print out, a bit like "ip addr" output */ 190 std::ostream& print(std::ostream&); 191 192 /** @brief Find the interface to which the input address' subnet 193 * belongs to in a vector of @ref Interface. 194 * @param addr the address we're looking for 195 * @param vifs the interfaces to search 196 * @param[out] hostaddr the found interface address. 197 * @return both the interface and the address inside the interface. 198 */ 199 static const Interface *interfaceForAddress( 200 const IPAddr& addr, const std::vector<Interface>& vifs,IPAddr& hostaddr); 201 202 /** @brief Find the interface to which the input address' subnet 203 * belongs to among all the system interfaces. 204 * @param addr the address we're looking for 205 * @param[out] hostaddr the found interface address. 206 * @return Both the interface and the address inside the interface. */ 207 const Interface *interfaceForAddress(const IPAddr& addr, IPAddr& hostaddr); 208 209 /** debug */ 210 static void setlogfp(FILE *fp); 211 212 private: 213 Interfaces(const Interfaces &) = delete; 214 Interfaces& operator=(const Interfaces &) = delete; 215 Interfaces(); 216 ~Interfaces(); 217 218 class Internal; 219 Internal *m{nullptr}; 220 }; 221 222 } /* namespace NetIF */ 223 224 #endif /* _NETIF_H_INCLUDED_ */ 225