util.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /**
  2. * nmrpflash - Netgear Unbrick Utility
  3. * Copyright (C) 2016-2020 Joseph Lehner <joseph.c.lehner@gmail.com>
  4. *
  5. * nmrpflash is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * nmrpflash is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with nmrpflash. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. #ifndef NMRPFLASH_UTIL_H
  20. #define NMRPFLASH_UTIL_H
  21. #include <boost/format.hpp>
  22. #include <boost/predef.h>
  23. #include <sys/socket.h>
  24. #include <netinet/in.h>
  25. #include <arpa/inet.h>
  26. #include <functional>
  27. #include <unistd.h>
  28. #include <iostream>
  29. #include <cstdint>
  30. #include <cstring>
  31. #include <sstream>
  32. #include <cerrno>
  33. #include <vector>
  34. #include <string>
  35. #include <memory>
  36. #include <pcap.h>
  37. namespace nmrpflash {
  38. class scoped_fd
  39. {
  40. int m_fd;
  41. public:
  42. scoped_fd(int fd = -1)
  43. : m_fd(fd) {}
  44. ~scoped_fd()
  45. { close(m_fd); }
  46. void reset(int fd)
  47. { m_fd = fd; }
  48. int operator*() const
  49. { return m_fd; }
  50. };
  51. #if 0
  52. template<class R, class... Args> class cleaner
  53. {
  54. const std::function<R(Args...)> m_func;
  55. bool m_invalid;
  56. cleaner(std::function<R(Args...)>&& func)
  57. : m_func(func), m_invalid(false)
  58. {}
  59. public:
  60. ~cleaner()
  61. {
  62. if (!m_invalid) {
  63. m_func();
  64. }
  65. }
  66. void invalidate(bool invalid = true)
  67. { m_invalid = invalid; }
  68. template<class R2, class... Args2> friend auto make_cleaner(std::function<R2(Args2...)>&& f)
  69. {
  70. return cleaner<R2(Args2...)>(f);
  71. }
  72. };
  73. #endif
  74. class mac_addr
  75. {
  76. uint8_t m_mac[6];
  77. public:
  78. mac_addr()
  79. : mac_addr({0, 0, 0, 0, 0, 0})
  80. {}
  81. mac_addr(const uint8_t (&mac)[6])
  82. { memcpy(m_mac, mac, sizeof(m_mac)); }
  83. template<class T> mac_addr(const T (&mac)[6])
  84. {
  85. init(mac);
  86. }
  87. explicit mac_addr(const void* raw)
  88. { memcpy(m_mac, raw, sizeof(m_mac)); }
  89. mac_addr(const std::string& mac);
  90. template<class T> void apply_to(T* other) const
  91. {
  92. memcpy(other, m_mac, sizeof(m_mac));
  93. }
  94. std::string to_string(char delim = ':') const;
  95. bool operator==(const mac_addr& other) const
  96. { return !memcmp(m_mac, other.m_mac, sizeof(m_mac)); }
  97. bool operator!=(const mac_addr& other) const
  98. { return !operator==(other); }
  99. bool operator<(const mac_addr& other) const
  100. { return memcmp(m_mac, other.m_mac, sizeof(m_mac)) < 0; }
  101. explicit operator bool() const
  102. { return operator!=(none); }
  103. friend std::ostream& operator<<(std::ostream& os, const mac_addr& other)
  104. { return os << other.to_string(); }
  105. static const mac_addr broadcast;
  106. static const mac_addr none;
  107. private:
  108. template<class T> void init(const T (&mac)[6])
  109. {
  110. for (int i = 0; i < sizeof(m_mac); ++i) {
  111. m_mac[i] = mac[i] & 0xff;
  112. }
  113. }
  114. };
  115. class ip_addr
  116. {
  117. uint32_t m_ip;
  118. int m_prefix;
  119. public:
  120. ip_addr()
  121. : ip_addr(0)
  122. {}
  123. explicit ip_addr(uint32_t ip)
  124. : ip_addr(ip, 0)
  125. {}
  126. ip_addr(uint32_t ip, int prefix)
  127. : m_ip(htonl(ip))
  128. {
  129. this->prefix(m_prefix);
  130. }
  131. ip_addr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, int prefix = 0)
  132. : ip_addr(htonl(a << 24 | b << 16 | c << 8 | d), prefix)
  133. {}
  134. ip_addr(const std::string& ip);
  135. int prefix() const
  136. { return m_prefix; }
  137. ip_addr address() const;
  138. ip_addr netmask() const;
  139. ip_addr broadcast() const;
  140. void apply_to(in_addr& other) const
  141. { other.s_addr = m_ip; }
  142. void apply_to(sockaddr_in& other) const
  143. {
  144. other.sin_family = AF_INET;
  145. apply_to(other.sin_addr);
  146. }
  147. void apply_to(sockaddr& other) const
  148. { apply_to(*reinterpret_cast<sockaddr_in*>(&other)); }
  149. uint32_t to_uint() const
  150. { return ntohl(m_ip); }
  151. bool operator==(const ip_addr& other) const
  152. { return m_ip == other.m_ip && m_prefix == other.m_prefix; }
  153. bool operator!=(const ip_addr& other) const
  154. { return !operator==(other); }
  155. bool operator<(const ip_addr& other) const
  156. {
  157. if (m_ip == other.m_ip) {
  158. return m_prefix < other.m_prefix;
  159. } else {
  160. return m_ip < other.m_ip;
  161. }
  162. }
  163. explicit operator bool() const
  164. { return m_ip != 0; }
  165. friend std::ostream& operator<<(std::ostream& os, const ip_addr& ip);
  166. private:
  167. void prefix(int prefix);
  168. };
  169. template<class T, class D>
  170. auto wrap_unique(T* ptr, D&& del) -> std::unique_ptr<T, D>
  171. {
  172. return std::unique_ptr<T, D>(ptr, del);
  173. }
  174. int xsocket(int domain, int type, int protocol);
  175. bool select_readfd(int fd, unsigned timeout);
  176. template<class T> std::string stringify(const T& t)
  177. {
  178. std::ostringstream ostr;
  179. ostr << t;
  180. return ostr.str();
  181. }
  182. std::vector<std::string> split(const std::string& str, char delim, bool empties = true, size_t limit = 0);
  183. template<class CharT> std::basic_string<CharT> quote(const std::basic_string<CharT>& str);
  184. #if BOOST_OS_WINDOWS
  185. typedef boost::wformat cmdfmt;
  186. std::wstring quote(const std::wstring& str);
  187. #else
  188. typedef boost::format cmdfmt;
  189. std::string quote(const std::string& str);
  190. #endif
  191. int run(const cmdfmt& cmd, bool throw_on_error = true);
  192. class errno_error : public std::system_error
  193. {
  194. public:
  195. errno_error(const std::string& what, int error = errno)
  196. : std::system_error(error, std::system_category(), what), m_interrupted(error == EINTR)
  197. {}
  198. bool interrupted() const noexcept
  199. { return m_interrupted; }
  200. private:
  201. bool m_interrupted;
  202. };
  203. class pcap_error : public std::runtime_error
  204. {
  205. public:
  206. pcap_error(const std::string& what, pcap_t* p)
  207. : std::runtime_error(what + ": " + pcap_geterr(p))
  208. {}
  209. };
  210. class log
  211. {
  212. public:
  213. static void w(const std::string& msg);
  214. };
  215. }
  216. #endif