BAddr.h 15 KB

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