BAddr.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /**
  2. * @file BAddr.h
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. *
  22. * @section DESCRIPTION
  23. *
  24. * Network address abstractions used by {@link BSocket}.
  25. */
  26. #ifndef BADVPN_SYSTEM_BADDR_H
  27. #define BADVPN_SYSTEM_BADDR_H
  28. #include <stdint.h>
  29. #include <limits.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <stdio.h>
  33. #include <inttypes.h>
  34. #ifdef BADVPN_USE_WINAPI
  35. #include <ws2tcpip.h>
  36. #else
  37. #include <sys/types.h>
  38. #include <sys/socket.h>
  39. #include <netdb.h>
  40. #endif
  41. #include <misc/byteorder.h>
  42. #include <misc/debug.h>
  43. #define BADDR_TYPE_NONE 0
  44. #define BADDR_TYPE_IPV4 1
  45. #define BADDR_TYPE_IPV6 2
  46. #ifndef BADVPN_USE_WINAPI
  47. #define BADDR_TYPE_UNIX 3 // only a domain number for BSocket
  48. #endif
  49. #define BADDR_MAX_ADDR_LEN 128
  50. #define BIPADDR_MAX_PRINT_LEN 40
  51. #define BADDR_MAX_PRINT_LEN 46
  52. typedef struct {
  53. int type;
  54. union {
  55. uint32_t ipv4;
  56. uint8_t ipv6[16];
  57. };
  58. } BIPAddr;
  59. static void BIPAddr_InitInvalid (BIPAddr *addr);
  60. static void BIPAddr_InitIPv4 (BIPAddr *addr, uint32_t ip);
  61. static void BIPAddr_InitIPv6 (BIPAddr *addr, uint8_t *ip);
  62. static int BIPAddr_IsRecognized (BIPAddr *addr);
  63. static int BIPAddr_IsInvalid (BIPAddr *addr);
  64. static int BIPAddr_Resolve (BIPAddr *addr, char *str, int noresolve) WARN_UNUSED;
  65. static int BIPAddr_Compare (BIPAddr *addr1, BIPAddr *addr2);
  66. /**
  67. * Converts an IP address to human readable form.
  68. *
  69. * @param addr IP address to convert
  70. * @param out destination buffer. Must be at least BIPADDR_MAX_PRINT_LEN characters long.
  71. */
  72. static void BIPAddr_Print (BIPAddr *addr, char *out);
  73. /**
  74. * Socket address - IP address and transport protocol port number
  75. */
  76. typedef struct {
  77. int type;
  78. union {
  79. struct {
  80. uint32_t ip;
  81. uint16_t port;
  82. } ipv4;
  83. struct {
  84. uint8_t ip[16];
  85. uint16_t port;
  86. } ipv6;
  87. };
  88. } BAddr;
  89. /**
  90. * Initializes an invalid address.
  91. */
  92. static void BAddr_InitNone (BAddr *addr);
  93. /**
  94. * Initializes an IPv4 address.
  95. *
  96. * @param addr the object
  97. * @param ip IP address in network byte order
  98. * @param port port number in network byte order
  99. */
  100. static void BAddr_InitIPv4 (BAddr *addr, uint32_t ip, uint16_t port);
  101. /**
  102. * Initializes an IPv6 address.
  103. *
  104. * @param addr the object
  105. * @param ip 16-byte IP address in network byte order
  106. * @param port port number in network byte order
  107. */
  108. static void BAddr_InitIPv6 (BAddr *addr, uint8_t *ip, uint16_t port);
  109. /**
  110. * Determines whether the address is recognized.
  111. *
  112. * @param addr the object
  113. * @return 1 if recognized, 0 if not
  114. */
  115. static int BAddr_IsRecognized (BAddr *addr);
  116. /**
  117. * Determines whether the address is an invalid address.
  118. *
  119. * @param addr the object. Must be recognized according to {@link BAddr_IsRecognized}.
  120. * @return 1 if invalid, 0 if invalid
  121. **/
  122. static int BAddr_IsInvalid (BAddr *addr);
  123. /**
  124. * Returns the port number in the address.
  125. *
  126. * @param addr the object. Must be recognized according to {@link BAddr_IsRecognized},
  127. * Must be an IPv4 or IPv6 address.
  128. * @return port number, in network byte order
  129. */
  130. static uint16_t BAddr_GetPort (BAddr *addr);
  131. /**
  132. * Returns the IP address in the address.
  133. *
  134. * @param addr the object. Must be recognized according to {@link BAddr_IsRecognized},
  135. * Must be an IPv4 or IPv6 address.
  136. * @param ipaddr IP address will be returned here
  137. */
  138. static void BAddr_GetIPAddr (BAddr *addr, BIPAddr *ipaddr);
  139. /**
  140. * Sets the port number in the address.
  141. *
  142. * @param addr the object. Must be recognized according to {@link BAddr_IsRecognized},
  143. * Must be an IPv4 or IPv6 address.
  144. * @param port port number, in network byte order
  145. */
  146. static void BAddr_SetPort (BAddr *addr, uint16_t port);
  147. /**
  148. * Converts an IP address to human readable form.
  149. *
  150. * @param addr address to convert
  151. * @param out destination buffer. Must be at least BADDR_MAX_PRINT_LEN characters long.
  152. */
  153. static void BAddr_Print (BAddr *addr, char *out);
  154. /**
  155. * Resolves an address string.
  156. * Format is "addr:port" for IPv4, "[addr]:port" for IPv6.
  157. * addr is be a numeric address or a name.
  158. * port is a numeric port number.
  159. *
  160. * @param addr output address
  161. * @param name if not NULL, the name portion of the address will be
  162. * stored here
  163. * @param name_len if name is not NULL, the size of the name buffer
  164. * @param noresolve only accept numeric addresses. Avoids blocking the caller.
  165. * @return 1 on success, 0 on parse error
  166. */
  167. static int BAddr_Parse2 (BAddr *addr, char *str, char *name, int name_len, int noresolve) WARN_UNUSED;
  168. /**
  169. * Resolves an address string.
  170. * IPv4 input format is "a.b.c.d:p", where a.b.c.d is the IP address
  171. * and d is the port number.
  172. * IPv6 input format is "[addr]:p", where addr is an IPv6 addres in
  173. * standard notation and p is the port number.
  174. *
  175. * @param addr output address
  176. * @param name if not NULL, the name portion of the address will be
  177. * stored here
  178. * @param name_len if name is not NULL, the size of the name buffer
  179. * @return 1 on success, 0 on parse error
  180. */
  181. static int BAddr_Parse (BAddr *addr, char *str, char *name, int name_len) WARN_UNUSED;
  182. void BIPAddr_InitInvalid (BIPAddr *addr)
  183. {
  184. addr->type = BADDR_TYPE_NONE;
  185. }
  186. void BIPAddr_InitIPv4 (BIPAddr *addr, uint32_t ip)
  187. {
  188. addr->type = BADDR_TYPE_IPV4;
  189. addr->ipv4 = ip;
  190. }
  191. void BIPAddr_InitIPv6 (BIPAddr *addr, uint8_t *ip)
  192. {
  193. addr->type = BADDR_TYPE_IPV6;
  194. memcpy(addr->ipv6, ip, 16);
  195. }
  196. int BIPAddr_IsRecognized (BIPAddr *addr)
  197. {
  198. switch (addr->type) {
  199. case BADDR_TYPE_NONE:
  200. case BADDR_TYPE_IPV4:
  201. case BADDR_TYPE_IPV6:
  202. return 1;
  203. default:
  204. return 0;
  205. }
  206. }
  207. int BIPAddr_IsInvalid (BIPAddr *addr)
  208. {
  209. ASSERT(BIPAddr_IsRecognized(addr))
  210. return (addr->type == BADDR_TYPE_NONE);
  211. }
  212. int BIPAddr_Resolve (BIPAddr *addr, char *str, int noresolve)
  213. {
  214. int len = strlen(str);
  215. char *addr_start;
  216. int addr_len;
  217. // determine address type
  218. if (len >= 1 && str[0] == '[' && str[len - 1] == ']') {
  219. addr->type = BADDR_TYPE_IPV6;
  220. addr_start = str + 1;
  221. addr_len = len - 2;
  222. } else {
  223. addr->type = BADDR_TYPE_IPV4;
  224. addr_start = str;
  225. addr_len = len;
  226. }
  227. // copy
  228. char addr_str[BADDR_MAX_ADDR_LEN + 1];
  229. if (addr_len > BADDR_MAX_ADDR_LEN) {
  230. return 0;
  231. }
  232. memcpy(addr_str, addr_start, addr_len);
  233. addr_str[addr_len] = '\0';
  234. // initialize hints
  235. struct addrinfo hints;
  236. memset(&hints, 0, sizeof(hints));
  237. switch (addr->type) {
  238. case BADDR_TYPE_IPV6:
  239. hints.ai_family = AF_INET6;
  240. break;
  241. case BADDR_TYPE_IPV4:
  242. hints.ai_family = AF_INET;
  243. break;
  244. }
  245. if (noresolve) {
  246. hints.ai_flags |= AI_NUMERICHOST;
  247. }
  248. // call getaddrinfo
  249. struct addrinfo *addrs;
  250. int res;
  251. if ((res = getaddrinfo(addr_str, NULL, &hints, &addrs)) != 0) {
  252. return 0;
  253. }
  254. // set address
  255. switch (addr->type) {
  256. case BADDR_TYPE_IPV6:
  257. memcpy(addr->ipv6, ((struct sockaddr_in6 *)addrs->ai_addr)->sin6_addr.s6_addr, sizeof(addr->ipv6));
  258. break;
  259. case BADDR_TYPE_IPV4:
  260. addr->ipv4 = ((struct sockaddr_in *)addrs->ai_addr)->sin_addr.s_addr;
  261. break;
  262. }
  263. freeaddrinfo(addrs);
  264. return 1;
  265. }
  266. int BIPAddr_Compare (BIPAddr *addr1, BIPAddr *addr2)
  267. {
  268. ASSERT(BIPAddr_IsRecognized(addr1))
  269. ASSERT(BIPAddr_IsRecognized(addr2))
  270. if (addr1->type != addr2->type) {
  271. return 0;
  272. }
  273. switch (addr1->type) {
  274. case BADDR_TYPE_NONE:
  275. return 0;
  276. case BADDR_TYPE_IPV4:
  277. return (addr1->ipv4 == addr2->ipv4);
  278. case BADDR_TYPE_IPV6:
  279. return (!memcmp(addr1->ipv6, addr2->ipv6, sizeof(addr1->ipv6)));
  280. default:
  281. ASSERT(0)
  282. return 0;
  283. }
  284. }
  285. uint16_t BAddr_GetPort (BAddr *addr)
  286. {
  287. ASSERT(BAddr_IsRecognized(addr))
  288. ASSERT(addr->type == BADDR_TYPE_IPV4 || addr->type == BADDR_TYPE_IPV6)
  289. switch (addr->type) {
  290. case BADDR_TYPE_IPV4:
  291. return addr->ipv4.port;
  292. case BADDR_TYPE_IPV6:
  293. return addr->ipv6.port;
  294. default:
  295. ASSERT(0)
  296. return 0;
  297. }
  298. }
  299. void BAddr_GetIPAddr (BAddr *addr, BIPAddr *ipaddr)
  300. {
  301. ASSERT(BAddr_IsRecognized(addr))
  302. ASSERT(addr->type == BADDR_TYPE_IPV4 || addr->type == BADDR_TYPE_IPV6)
  303. switch (addr->type) {
  304. case BADDR_TYPE_IPV4:
  305. BIPAddr_InitIPv4(ipaddr, addr->ipv4.ip);
  306. return;
  307. case BADDR_TYPE_IPV6:
  308. BIPAddr_InitIPv6(ipaddr, addr->ipv6.ip);
  309. return;
  310. default:
  311. ASSERT(0);
  312. }
  313. }
  314. void BAddr_SetPort (BAddr *addr, uint16_t port)
  315. {
  316. ASSERT(BAddr_IsRecognized(addr))
  317. ASSERT(addr->type == BADDR_TYPE_IPV4 || addr->type == BADDR_TYPE_IPV6)
  318. switch (addr->type) {
  319. case BADDR_TYPE_IPV4:
  320. addr->ipv4.port = port;
  321. break;
  322. case BADDR_TYPE_IPV6:
  323. addr->ipv6.port = port;
  324. break;
  325. default:
  326. ASSERT(0);
  327. }
  328. }
  329. struct _BAddr_ipv6_addr
  330. {
  331. uint16_t addr[8];
  332. } __attribute__((packed));
  333. void BIPAddr_Print (BIPAddr *addr, char *out)
  334. {
  335. switch (addr->type) {
  336. case BADDR_TYPE_NONE:
  337. sprintf(out, "(none)");
  338. break;
  339. case BADDR_TYPE_IPV4:
  340. sprintf(out, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8,
  341. *((uint8_t *)&addr->ipv4 + 0),
  342. *((uint8_t *)&addr->ipv4 + 1),
  343. *((uint8_t *)&addr->ipv4 + 2),
  344. *((uint8_t *)&addr->ipv4 + 3)
  345. );
  346. break;
  347. case BADDR_TYPE_IPV6: {
  348. struct _BAddr_ipv6_addr *s = (struct _BAddr_ipv6_addr *)addr->ipv6;
  349. sprintf(out,
  350. "%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16":"
  351. "%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16,
  352. ntoh16(s->addr[0]),
  353. ntoh16(s->addr[1]),
  354. ntoh16(s->addr[2]),
  355. ntoh16(s->addr[3]),
  356. ntoh16(s->addr[4]),
  357. ntoh16(s->addr[5]),
  358. ntoh16(s->addr[6]),
  359. ntoh16(s->addr[7])
  360. );
  361. } break;
  362. default:
  363. ASSERT(0);
  364. }
  365. }
  366. void BAddr_InitNone (BAddr *addr)
  367. {
  368. addr->type = BADDR_TYPE_NONE;
  369. }
  370. void BAddr_InitIPv4 (BAddr *addr, uint32_t ip, uint16_t port)
  371. {
  372. addr->type = BADDR_TYPE_IPV4;
  373. addr->ipv4.ip = ip;
  374. addr->ipv4.port = port;
  375. }
  376. void BAddr_InitIPv6 (BAddr *addr, uint8_t *ip, uint16_t port)
  377. {
  378. addr->type = BADDR_TYPE_IPV6;
  379. memcpy(addr->ipv6.ip, ip, 16);
  380. addr->ipv6.port = port;
  381. }
  382. int BAddr_IsRecognized (BAddr *addr)
  383. {
  384. switch (addr->type) {
  385. case BADDR_TYPE_NONE:
  386. case BADDR_TYPE_IPV4:
  387. case BADDR_TYPE_IPV6:
  388. return 1;
  389. default:
  390. return 0;
  391. }
  392. }
  393. int BAddr_IsInvalid (BAddr *addr)
  394. {
  395. ASSERT(BAddr_IsRecognized(addr))
  396. return (addr->type == BADDR_TYPE_NONE);
  397. }
  398. void BAddr_Print (BAddr *addr, char *out)
  399. {
  400. ASSERT(BAddr_IsRecognized(addr))
  401. BIPAddr ipaddr;
  402. switch (addr->type) {
  403. case BADDR_TYPE_NONE:
  404. sprintf(out, "(none)");
  405. break;
  406. case BADDR_TYPE_IPV4:
  407. BIPAddr_InitIPv4(&ipaddr, addr->ipv4.ip);
  408. BIPAddr_Print(&ipaddr, out);
  409. sprintf(out + strlen(out), ":%"PRIu16, ntoh16(addr->ipv4.port));
  410. break;
  411. case BADDR_TYPE_IPV6:
  412. BIPAddr_InitIPv6(&ipaddr, addr->ipv6.ip);
  413. BIPAddr_Print(&ipaddr, out);
  414. sprintf(out + strlen(out), ":%"PRIu16, ntoh16(addr->ipv6.port));
  415. break;
  416. default:
  417. ASSERT(0);
  418. }
  419. }
  420. int BAddr_Parse2 (BAddr *addr, char *str, char *name, int name_len, int noresolve)
  421. {
  422. BAddr result;
  423. int len = strlen(str);
  424. if (len < 1 || len > 1000) {
  425. return 0;
  426. }
  427. int addr_start;
  428. int addr_len;
  429. int port_start;
  430. int port_len;
  431. // leading '[' indicates an IPv6 address
  432. if (str[0] == '[') {
  433. addr->type = BADDR_TYPE_IPV6;
  434. // find ']'
  435. int i=1;
  436. while (i < len && str[i] != ']') i++;
  437. if (i >= len) {
  438. return 0;
  439. }
  440. addr_start = 1;
  441. addr_len = i - addr_start;
  442. // follows ':' and port number
  443. if (i + 1 >= len || str[i + 1] != ':') {
  444. return 0;
  445. }
  446. port_start = i + 2;
  447. port_len = len - port_start;
  448. }
  449. // otherwise it's an IPv4 address
  450. else {
  451. addr->type = BADDR_TYPE_IPV4;
  452. // find ':'
  453. int i=0;
  454. while (i < len && str[i] != ':') i++;
  455. if (i >= len) {
  456. return 0;
  457. }
  458. addr_start = 0;
  459. addr_len = i - addr_start;
  460. port_start = i + 1;
  461. port_len = len - port_start;
  462. }
  463. // copy address and port to zero-terminated buffers
  464. char addr_str[128];
  465. if (addr_len >= sizeof(addr_str)) {
  466. return 0;
  467. }
  468. memcpy(addr_str, str + addr_start, addr_len);
  469. addr_str[addr_len] = '\0';
  470. char port_str[6];
  471. if (port_len >= sizeof(port_str)) {
  472. return 0;
  473. }
  474. memcpy(port_str, str + port_start, port_len);
  475. port_str[port_len] = '\0';
  476. // parse port
  477. char *err;
  478. long int conv_res = strtol(port_str, &err, 10);
  479. if (port_str[0] == '\0' || *err != '\0') {
  480. return 0;
  481. }
  482. if (conv_res < 0 || conv_res > UINT16_MAX) {
  483. return 0;
  484. }
  485. uint16_t port = conv_res;
  486. port = hton16(port);
  487. // initialize hints
  488. struct addrinfo hints;
  489. memset(&hints, 0, sizeof(hints));
  490. switch (addr->type) {
  491. case BADDR_TYPE_IPV6:
  492. hints.ai_family = AF_INET6;
  493. break;
  494. case BADDR_TYPE_IPV4:
  495. hints.ai_family = AF_INET;
  496. break;
  497. }
  498. if (noresolve) {
  499. hints.ai_flags |= AI_NUMERICHOST;
  500. }
  501. // call getaddrinfo
  502. struct addrinfo *addrs;
  503. int res;
  504. if ((res = getaddrinfo(addr_str, NULL, &hints, &addrs)) != 0) {
  505. return 0;
  506. }
  507. // set address
  508. switch (addr->type) {
  509. case BADDR_TYPE_IPV6:
  510. memcpy(addr->ipv6.ip, ((struct sockaddr_in6 *)addrs->ai_addr)->sin6_addr.s6_addr, sizeof(addr->ipv6.ip));
  511. addr->ipv6.port = port;
  512. break;
  513. case BADDR_TYPE_IPV4:
  514. addr->ipv4.ip = ((struct sockaddr_in *)addrs->ai_addr)->sin_addr.s_addr;
  515. addr->ipv4.port = port;
  516. break;
  517. }
  518. freeaddrinfo(addrs);
  519. if (name) {
  520. snprintf(name, name_len, "%s", addr_str);
  521. }
  522. return 1;
  523. }
  524. int BAddr_Parse (BAddr *addr, char *str, char *name, int name_len)
  525. {
  526. return BAddr_Parse2(addr, str, name, name_len, 0);
  527. }
  528. #endif