acl.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2006, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Various sorts of access control
  21. *
  22. * \author Mark Spencer <markster@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <support_level>core</support_level>
  26. ***/
  27. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include "asterisk/network.h"
  30. #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
  31. #include <fcntl.h>
  32. #include <net/route.h>
  33. #endif
  34. #if defined(SOLARIS)
  35. #include <sys/sockio.h>
  36. #include <net/if.h>
  37. #elif defined(HAVE_GETIFADDRS)
  38. #include <ifaddrs.h>
  39. #endif
  40. #include "asterisk/acl.h"
  41. #include "asterisk/channel.h"
  42. #include "asterisk/utils.h"
  43. #include "asterisk/lock.h"
  44. #include "asterisk/srv.h"
  45. #if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
  46. static int get_local_address(struct ast_sockaddr *ourip)
  47. {
  48. return -1;
  49. }
  50. #else
  51. static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
  52. {
  53. const char *address;
  54. int score;
  55. address = ast_inet_ntoa(sin->sin_addr);
  56. /* RFC 1700 alias for the local network */
  57. if (address[0] == '0') {
  58. score = -25;
  59. /* RFC 1700 localnet */
  60. } else if (strncmp(address, "127", 3) == 0) {
  61. score = -20;
  62. /* RFC 1918 non-public address space */
  63. } else if (strncmp(address, "10.", 3) == 0) {
  64. score = -5;
  65. /* RFC 1918 non-public address space */
  66. } else if (strncmp(address, "172", 3) == 0) {
  67. /* 172.16.0.0 - 172.19.255.255, but not 172.160.0.0 - 172.169.255.255 */
  68. if (address[4] == '1' && address[5] >= '6' && address[6] == '.') {
  69. score = -5;
  70. /* 172.20.0.0 - 172.29.255.255, but not 172.200.0.0 - 172.255.255.255 nor 172.2.0.0 - 172.2.255.255 */
  71. } else if (address[4] == '2' && address[6] == '.') {
  72. score = -5;
  73. /* 172.30.0.0 - 172.31.255.255, but not 172.3.0.0 - 172.3.255.255 */
  74. } else if (address[4] == '3' && (address[5] == '0' || address[5] == '1')) {
  75. score = -5;
  76. /* All other 172 addresses are public */
  77. } else {
  78. score = 0;
  79. }
  80. /* RFC 2544 Benchmark test range (198.18.0.0 - 198.19.255.255, but not 198.180.0.0 - 198.199.255.255) */
  81. } else if (strncmp(address, "198.1", 5) == 0 && address[5] >= '8' && address[6] == '.') {
  82. score = -10;
  83. /* RFC 1918 non-public address space */
  84. } else if (strncmp(address, "192.168", 7) == 0) {
  85. score = -5;
  86. /* RFC 3330 Zeroconf network */
  87. } else if (strncmp(address, "169.254", 7) == 0) {
  88. /*!\note Better score than a test network, but not quite as good as RFC 1918
  89. * address space. The reason is that some Linux distributions automatically
  90. * configure a Zeroconf address before trying DHCP, so we want to prefer a
  91. * DHCP lease to a Zeroconf address.
  92. */
  93. score = -10;
  94. /* RFC 3330 Test network */
  95. } else if (strncmp(address, "192.0.2.", 8) == 0) {
  96. score = -15;
  97. /* Every other address should be publically routable */
  98. } else {
  99. score = 0;
  100. }
  101. if (score > *best_score) {
  102. *best_score = score;
  103. memcpy(best_addr, &sin->sin_addr, sizeof(*best_addr));
  104. }
  105. }
  106. static int get_local_address(struct ast_sockaddr *ourip)
  107. {
  108. int s, res = -1;
  109. #ifdef SOLARIS
  110. struct lifreq *ifr = NULL;
  111. struct lifnum ifn;
  112. struct lifconf ifc;
  113. struct sockaddr_in *sa;
  114. char *buf = NULL;
  115. int bufsz, x;
  116. #endif /* SOLARIS */
  117. #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
  118. struct ifaddrs *ifap, *ifaphead;
  119. int rtnerr;
  120. const struct sockaddr_in *sin;
  121. #endif /* BSD_OR_LINUX */
  122. struct in_addr best_addr;
  123. int best_score = -100;
  124. memset(&best_addr, 0, sizeof(best_addr));
  125. #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
  126. rtnerr = getifaddrs(&ifaphead);
  127. if (rtnerr) {
  128. perror(NULL);
  129. return -1;
  130. }
  131. #endif /* BSD_OR_LINUX */
  132. s = socket(AF_INET, SOCK_STREAM, 0);
  133. if (s > 0) {
  134. #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
  135. for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
  136. if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) {
  137. sin = (const struct sockaddr_in *) ifap->ifa_addr;
  138. score_address(sin, &best_addr, &best_score);
  139. res = 0;
  140. if (best_score == 0) {
  141. break;
  142. }
  143. }
  144. }
  145. #endif /* BSD_OR_LINUX */
  146. /* There is no reason whatsoever that this shouldn't work on Linux or BSD also. */
  147. #ifdef SOLARIS
  148. /* Get a count of interfaces on the machine */
  149. ifn.lifn_family = AF_INET;
  150. ifn.lifn_flags = 0;
  151. ifn.lifn_count = 0;
  152. if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
  153. close(s);
  154. return -1;
  155. }
  156. bufsz = ifn.lifn_count * sizeof(struct lifreq);
  157. if (!(buf = malloc(bufsz))) {
  158. close(s);
  159. return -1;
  160. }
  161. memset(buf, 0, bufsz);
  162. /* Get a list of interfaces on the machine */
  163. ifc.lifc_len = bufsz;
  164. ifc.lifc_buf = buf;
  165. ifc.lifc_family = AF_INET;
  166. ifc.lifc_flags = 0;
  167. if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
  168. close(s);
  169. free(buf);
  170. return -1;
  171. }
  172. for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) {
  173. sa = (struct sockaddr_in *)&(ifr->lifr_addr);
  174. score_address(sa, &best_addr, &best_score);
  175. res = 0;
  176. if (best_score == 0) {
  177. break;
  178. }
  179. }
  180. free(buf);
  181. #endif /* SOLARIS */
  182. close(s);
  183. }
  184. #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
  185. freeifaddrs(ifaphead);
  186. #endif /* BSD_OR_LINUX */
  187. if (res == 0 && ourip) {
  188. ast_sockaddr_setnull(ourip);
  189. ourip->ss.ss_family = AF_INET;
  190. ((struct sockaddr_in *)&ourip->ss)->sin_addr = best_addr;
  191. }
  192. return res;
  193. }
  194. #endif /* HAVE_GETIFADDRS */
  195. /* Free HA structure */
  196. void ast_free_ha(struct ast_ha *ha)
  197. {
  198. struct ast_ha *hal;
  199. while (ha) {
  200. hal = ha;
  201. ha = ha->next;
  202. ast_free(hal);
  203. }
  204. }
  205. /* Copy HA structure */
  206. void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
  207. {
  208. ast_sockaddr_copy(&to->addr, &from->addr);
  209. ast_sockaddr_copy(&to->netmask, &from->netmask);
  210. to->sense = from->sense;
  211. }
  212. /* Create duplicate of ha structure */
  213. static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
  214. {
  215. struct ast_ha *new_ha;
  216. if ((new_ha = ast_calloc(1, sizeof(*new_ha)))) {
  217. /* Copy from original to new object */
  218. ast_copy_ha(original, new_ha);
  219. }
  220. return new_ha;
  221. }
  222. /* Create duplicate HA link list */
  223. /* Used in chan_sip2 templates */
  224. struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
  225. {
  226. struct ast_ha *start = original;
  227. struct ast_ha *ret = NULL;
  228. struct ast_ha *current, *prev = NULL;
  229. while (start) {
  230. current = ast_duplicate_ha(start); /* Create copy of this object */
  231. if (prev) {
  232. prev->next = current; /* Link previous to this object */
  233. }
  234. if (!ret) {
  235. ret = current; /* Save starting point */
  236. }
  237. start = start->next; /* Go to next object */
  238. prev = current; /* Save pointer to this object */
  239. }
  240. return ret; /* Return start of list */
  241. }
  242. /*!
  243. * \brief
  244. * Isolate a 32-bit section of an IPv6 address
  245. *
  246. * An IPv6 address can be divided into 4 32-bit chunks. This gives
  247. * easy access to one of these chunks.
  248. *
  249. * \param sin6 A pointer to a struct sockaddr_in6
  250. * \param index Which 32-bit chunk to operate on. Must be in the range 0-3.
  251. */
  252. #define V6_WORD(sin6, index) ((uint32_t *)&((sin6)->sin6_addr))[(index)]
  253. /*!
  254. * \brief
  255. * Apply a netmask to an address and store the result in a separate structure.
  256. *
  257. * When dealing with IPv6 addresses, one cannot apply a netmask with a simple
  258. * logical and operation. Furthermore, the incoming address may be an IPv4 address
  259. * and need to be mapped properly before attempting to apply a rule.
  260. *
  261. * \param addr The IP address to apply the mask to.
  262. * \param netmask The netmask configured in the host access rule.
  263. * \param result The resultant address after applying the netmask to the given address
  264. * \retval 0 Successfully applied netmask
  265. * \reval -1 Failed to apply netmask
  266. */
  267. static int apply_netmask(const struct ast_sockaddr *addr, const struct ast_sockaddr *netmask,
  268. struct ast_sockaddr *result)
  269. {
  270. int res = 0;
  271. if (ast_sockaddr_is_ipv4(addr)) {
  272. struct sockaddr_in result4 = { 0, };
  273. struct sockaddr_in *addr4 = (struct sockaddr_in *) &addr->ss;
  274. struct sockaddr_in *mask4 = (struct sockaddr_in *) &netmask->ss;
  275. result4.sin_family = AF_INET;
  276. result4.sin_addr.s_addr = addr4->sin_addr.s_addr & mask4->sin_addr.s_addr;
  277. ast_sockaddr_from_sin(result, &result4);
  278. } else if (ast_sockaddr_is_ipv6(addr)) {
  279. struct sockaddr_in6 result6 = { 0, };
  280. struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &addr->ss;
  281. struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *) &netmask->ss;
  282. int i;
  283. result6.sin6_family = AF_INET6;
  284. for (i = 0; i < 4; ++i) {
  285. V6_WORD(&result6, i) = V6_WORD(addr6, i) & V6_WORD(mask6, i);
  286. }
  287. memcpy(&result->ss, &result6, sizeof(result6));
  288. result->len = sizeof(result6);
  289. } else {
  290. /* Unsupported address scheme */
  291. res = -1;
  292. }
  293. return res;
  294. }
  295. /*!
  296. * \brief
  297. * Parse a netmask in CIDR notation
  298. *
  299. * \details
  300. * For a mask of an IPv4 address, this should be a number between 0 and 32. For
  301. * a mask of an IPv6 address, this should be a number between 0 and 128. This
  302. * function creates an IPv6 ast_sockaddr from the given netmask. For masks of
  303. * IPv4 addresses, this is accomplished by adding 96 to the original netmask.
  304. *
  305. * \param[out] addr The ast_sockaddr produced from the CIDR netmask
  306. * \param is_v4 Tells if the address we are masking is IPv4.
  307. * \param mask_str The CIDR mask to convert
  308. * \retval -1 Failure
  309. * \retval 0 Success
  310. */
  311. static int parse_cidr_mask(struct ast_sockaddr *addr, int is_v4, const char *mask_str)
  312. {
  313. int mask;
  314. if (sscanf(mask_str, "%30d", &mask) != 1) {
  315. return -1;
  316. }
  317. if (is_v4) {
  318. struct sockaddr_in sin;
  319. if (mask < 0 || mask > 32) {
  320. return -1;
  321. }
  322. memset(&sin, 0, sizeof(sin));
  323. sin.sin_family = AF_INET;
  324. /* If mask is 0, then we already have the
  325. * appropriate all 0s address in sin from
  326. * the above memset.
  327. */
  328. if (mask != 0) {
  329. sin.sin_addr.s_addr = htonl(0xFFFFFFFF << (32 - mask));
  330. }
  331. ast_sockaddr_from_sin(addr, &sin);
  332. } else {
  333. struct sockaddr_in6 sin6;
  334. int i;
  335. if (mask < 0 || mask > 128) {
  336. return -1;
  337. }
  338. memset(&sin6, 0, sizeof(sin6));
  339. sin6.sin6_family = AF_INET6;
  340. for (i = 0; i < 4; ++i) {
  341. /* Once mask reaches 0, we don't have
  342. * to explicitly set anything anymore
  343. * since sin6 was zeroed out already
  344. */
  345. if (mask > 0) {
  346. V6_WORD(&sin6, i) = htonl(0xFFFFFFFF << (mask < 32 ? (32 - mask) : 0));
  347. mask -= mask < 32 ? mask : 32;
  348. }
  349. }
  350. memcpy(&addr->ss, &sin6, sizeof(sin6));
  351. addr->len = sizeof(sin6);
  352. }
  353. return 0;
  354. }
  355. struct ast_ha *ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
  356. {
  357. struct ast_ha *ha;
  358. struct ast_ha *prev = NULL;
  359. struct ast_ha *ret;
  360. char *tmp = ast_strdupa(stuff);
  361. char *address = NULL, *mask = NULL;
  362. int addr_is_v4;
  363. ret = path;
  364. while (path) {
  365. prev = path;
  366. path = path->next;
  367. }
  368. if (!(ha = ast_calloc(1, sizeof(*ha)))) {
  369. if (error) {
  370. *error = 1;
  371. }
  372. return ret;
  373. }
  374. address = strsep(&tmp, "/");
  375. if (!address) {
  376. address = tmp;
  377. } else {
  378. mask = tmp;
  379. }
  380. if (!ast_sockaddr_parse(&ha->addr, address, PARSE_PORT_FORBID)) {
  381. ast_log(LOG_WARNING, "Invalid IP address: %s\n", address);
  382. ast_free_ha(ha);
  383. if (error) {
  384. *error = 1;
  385. }
  386. return ret;
  387. }
  388. /* If someone specifies an IPv4-mapped IPv6 address,
  389. * we just convert this to an IPv4 ACL
  390. */
  391. if (ast_sockaddr_ipv4_mapped(&ha->addr, &ha->addr)) {
  392. ast_log(LOG_NOTICE, "IPv4-mapped ACL network address specified. "
  393. "Converting to an IPv4 ACL network address.\n");
  394. }
  395. addr_is_v4 = ast_sockaddr_is_ipv4(&ha->addr);
  396. if (!mask) {
  397. parse_cidr_mask(&ha->netmask, addr_is_v4, addr_is_v4 ? "32" : "128");
  398. } else if (strchr(mask, ':') || strchr(mask, '.')) {
  399. int mask_is_v4;
  400. /* Mask is of x.x.x.x or x:x:x:x:x:x:x:x variety */
  401. if (!ast_sockaddr_parse(&ha->netmask, mask, PARSE_PORT_FORBID)) {
  402. ast_log(LOG_WARNING, "Invalid netmask: %s\n", mask);
  403. ast_free_ha(ha);
  404. if (error) {
  405. *error = 1;
  406. }
  407. return ret;
  408. }
  409. /* If someone specifies an IPv4-mapped IPv6 netmask,
  410. * we just convert this to an IPv4 ACL
  411. */
  412. if (ast_sockaddr_ipv4_mapped(&ha->netmask, &ha->netmask)) {
  413. ast_log(LOG_NOTICE, "IPv4-mapped ACL netmask specified. "
  414. "Converting to an IPv4 ACL netmask.\n");
  415. }
  416. mask_is_v4 = ast_sockaddr_is_ipv4(&ha->netmask);
  417. if (addr_is_v4 ^ mask_is_v4) {
  418. ast_log(LOG_WARNING, "Address and mask are not using same address scheme.\n");
  419. ast_free_ha(ha);
  420. if (error) {
  421. *error = 1;
  422. }
  423. return ret;
  424. }
  425. } else if (parse_cidr_mask(&ha->netmask, addr_is_v4, mask)) {
  426. ast_log(LOG_WARNING, "Invalid CIDR netmask: %s\n", mask);
  427. ast_free_ha(ha);
  428. if (error) {
  429. *error = 1;
  430. }
  431. return ret;
  432. }
  433. if (apply_netmask(&ha->addr, &ha->netmask, &ha->addr)) {
  434. /* This shouldn't happen because ast_sockaddr_parse would
  435. * have failed much earlier on an unsupported address scheme
  436. */
  437. char *failmask = ast_strdupa(ast_sockaddr_stringify(&ha->netmask));
  438. char *failaddr = ast_strdupa(ast_sockaddr_stringify(&ha->addr));
  439. ast_log(LOG_WARNING, "Unable to apply netmask %s to address %s\n", failmask, failaddr);
  440. ast_free_ha(ha);
  441. if (error) {
  442. *error = 1;
  443. }
  444. return ret;
  445. }
  446. ha->sense = strncasecmp(sense, "p", 1) ? AST_SENSE_DENY : AST_SENSE_ALLOW;
  447. ha->next = NULL;
  448. if (prev) {
  449. prev->next = ha;
  450. } else {
  451. ret = ha;
  452. }
  453. {
  454. const char *addr = ast_strdupa(ast_sockaddr_stringify(&ha->addr));
  455. const char *mask = ast_strdupa(ast_sockaddr_stringify(&ha->netmask));
  456. ast_debug(1, "%s/%s sense %d appended to acl for peer\n", addr, mask, ha->sense);
  457. }
  458. return ret;
  459. }
  460. int ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr)
  461. {
  462. /* Start optimistic */
  463. int res = AST_SENSE_ALLOW;
  464. const struct ast_ha *current_ha;
  465. for (current_ha = ha; current_ha; current_ha = current_ha->next) {
  466. struct ast_sockaddr result;
  467. struct ast_sockaddr mapped_addr;
  468. const struct ast_sockaddr *addr_to_use;
  469. #if 0 /* debugging code */
  470. char iabuf[INET_ADDRSTRLEN];
  471. char iabuf2[INET_ADDRSTRLEN];
  472. /* DEBUG */
  473. ast_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf));
  474. ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
  475. ast_debug(1, "##### Testing %s with %s\n", iabuf, iabuf2);
  476. #endif
  477. if (ast_sockaddr_is_ipv4(&current_ha->addr)) {
  478. if (ast_sockaddr_is_ipv6(addr)) {
  479. if (ast_sockaddr_is_ipv4_mapped(addr)) {
  480. /* IPv4 ACLs apply to IPv4-mapped addresses */
  481. if (!ast_sockaddr_ipv4_mapped(addr, &mapped_addr)) {
  482. ast_log(LOG_ERROR, "%s provided to ast_sockaddr_ipv4_mapped could not be converted. That shouldn't be possible.\n",
  483. ast_sockaddr_stringify(addr));
  484. continue;
  485. }
  486. addr_to_use = &mapped_addr;
  487. } else {
  488. /* An IPv4 ACL does not apply to an IPv6 address */
  489. continue;
  490. }
  491. } else {
  492. /* Address is IPv4 and ACL is IPv4. No biggie */
  493. addr_to_use = addr;
  494. }
  495. } else {
  496. if (ast_sockaddr_is_ipv6(addr) && !ast_sockaddr_is_ipv4_mapped(addr)) {
  497. addr_to_use = addr;
  498. } else {
  499. /* Address is IPv4 or IPv4 mapped but ACL is IPv6. Skip */
  500. continue;
  501. }
  502. }
  503. /* For each rule, if this address and the netmask = the net address
  504. apply the current rule */
  505. if (apply_netmask(addr_to_use, &current_ha->netmask, &result)) {
  506. /* Unlikely to happen since we know the address to be IPv4 or IPv6 */
  507. continue;
  508. }
  509. if (!ast_sockaddr_cmp_addr(&result, &current_ha->addr)) {
  510. res = current_ha->sense;
  511. }
  512. }
  513. return res;
  514. }
  515. static int resolve_first(struct ast_sockaddr *addr, const char *name, int flag,
  516. int family)
  517. {
  518. struct ast_sockaddr *addrs;
  519. int addrs_cnt;
  520. addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family);
  521. if (addrs_cnt > 0) {
  522. if (addrs_cnt > 1) {
  523. ast_debug(1, "Multiple addresses. Using the first only\n");
  524. }
  525. ast_sockaddr_copy(addr, &addrs[0]);
  526. ast_free(addrs);
  527. } else {
  528. ast_log(LOG_WARNING, "Unable to lookup '%s'\n", name);
  529. return -1;
  530. }
  531. return 0;
  532. }
  533. int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service)
  534. {
  535. char srv[256];
  536. char host[256];
  537. int srv_ret = 0;
  538. int tportno;
  539. if (service) {
  540. snprintf(srv, sizeof(srv), "%s.%s", service, hostname);
  541. if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, srv)) > 0) {
  542. hostname = host;
  543. }
  544. }
  545. if (resolve_first(addr, hostname, PARSE_PORT_FORBID, addr->ss.ss_family) != 0) {
  546. return -1;
  547. }
  548. if (srv_ret > 0) {
  549. ast_sockaddr_set_port(addr, tportno);
  550. }
  551. return 0;
  552. }
  553. struct dscp_codepoint {
  554. char *name;
  555. unsigned int space;
  556. };
  557. /* IANA registered DSCP codepoints */
  558. static const struct dscp_codepoint dscp_pool1[] = {
  559. { "CS0", 0x00 },
  560. { "CS1", 0x08 },
  561. { "CS2", 0x10 },
  562. { "CS3", 0x18 },
  563. { "CS4", 0x20 },
  564. { "CS5", 0x28 },
  565. { "CS6", 0x30 },
  566. { "CS7", 0x38 },
  567. { "AF11", 0x0A },
  568. { "AF12", 0x0C },
  569. { "AF13", 0x0E },
  570. { "AF21", 0x12 },
  571. { "AF22", 0x14 },
  572. { "AF23", 0x16 },
  573. { "AF31", 0x1A },
  574. { "AF32", 0x1C },
  575. { "AF33", 0x1E },
  576. { "AF41", 0x22 },
  577. { "AF42", 0x24 },
  578. { "AF43", 0x26 },
  579. { "EF", 0x2E },
  580. };
  581. int ast_str2cos(const char *value, unsigned int *cos)
  582. {
  583. int fval;
  584. if (sscanf(value, "%30d", &fval) == 1) {
  585. if (fval < 8) {
  586. *cos = fval;
  587. return 0;
  588. }
  589. }
  590. return -1;
  591. }
  592. int ast_str2tos(const char *value, unsigned int *tos)
  593. {
  594. int fval;
  595. unsigned int x;
  596. if (sscanf(value, "%30i", &fval) == 1) {
  597. *tos = fval & 0xFF;
  598. return 0;
  599. }
  600. for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
  601. if (!strcasecmp(value, dscp_pool1[x].name)) {
  602. *tos = dscp_pool1[x].space << 2;
  603. return 0;
  604. }
  605. }
  606. return -1;
  607. }
  608. const char *ast_tos2str(unsigned int tos)
  609. {
  610. unsigned int x;
  611. for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
  612. if (dscp_pool1[x].space == (tos >> 2)) {
  613. return dscp_pool1[x].name;
  614. }
  615. }
  616. return "unknown";
  617. }
  618. int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
  619. {
  620. return ast_get_ip_or_srv(addr, hostname, NULL);
  621. }
  622. int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
  623. {
  624. int port;
  625. int s;
  626. port = ast_sockaddr_port(us);
  627. if ((s = socket(ast_sockaddr_is_ipv6(them) ? AF_INET6 : AF_INET,
  628. SOCK_DGRAM, 0)) < 0) {
  629. ast_log(LOG_ERROR, "Cannot create socket\n");
  630. return -1;
  631. }
  632. if (ast_connect(s, them)) {
  633. ast_log(LOG_WARNING, "Cannot connect\n");
  634. close(s);
  635. return -1;
  636. }
  637. if (ast_getsockname(s, us)) {
  638. ast_log(LOG_WARNING, "Cannot get socket name\n");
  639. close(s);
  640. return -1;
  641. }
  642. close(s);
  643. {
  644. const char *them_addr = ast_strdupa(ast_sockaddr_stringify_addr(them));
  645. const char *us_addr = ast_strdupa(ast_sockaddr_stringify_addr(us));
  646. ast_debug(3, "For destination '%s', our source address is '%s'.\n",
  647. them_addr, us_addr);
  648. }
  649. ast_sockaddr_set_port(us, port);
  650. return 0;
  651. }
  652. int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
  653. {
  654. char ourhost[MAXHOSTNAMELEN] = "";
  655. struct ast_sockaddr root;
  656. int res, port = ast_sockaddr_port(ourip);
  657. /* just use the bind address if it is nonzero */
  658. if (!ast_sockaddr_is_any(bindaddr)) {
  659. ast_sockaddr_copy(ourip, bindaddr);
  660. ast_debug(3, "Attached to given IP address\n");
  661. return 0;
  662. }
  663. /* try to use our hostname */
  664. if (gethostname(ourhost, sizeof(ourhost) - 1)) {
  665. ast_log(LOG_WARNING, "Unable to get hostname\n");
  666. } else {
  667. if (resolve_first(ourip, ourhost, PARSE_PORT_FORBID, family) == 0) {
  668. /* reset port since resolve_first wipes this out */
  669. ast_sockaddr_set_port(ourip, port);
  670. return 0;
  671. }
  672. }
  673. ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n");
  674. /* A.ROOT-SERVERS.NET. */
  675. if (!resolve_first(&root, "A.ROOT-SERVERS.NET", PARSE_PORT_FORBID, 0) &&
  676. !ast_ouraddrfor(&root, ourip)) {
  677. /* reset port since resolve_first wipes this out */
  678. ast_sockaddr_set_port(ourip, port);
  679. return 0;
  680. }
  681. res = get_local_address(ourip);
  682. ast_sockaddr_set_port(ourip, port);
  683. return res;
  684. }