You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.2 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /*
  2. * acl.c - Manage the ACL (Access Control List)
  3. *
  4. * Copyright (C) 2013 - 2015, Max Lv <max.c.lv@gmail.com>
  5. *
  6. * This file is part of the shadowsocks-libev.
  7. *
  8. * shadowsocks-libev is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * shadowsocks-libev 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
  19. * along with shadowsocks-libev; see the file COPYING. If not, see
  20. * <http://www.gnu.org/licenses/>.
  21. */
  22. #include <ipset/ipset.h>
  23. #include "utils.h"
  24. static struct ip_set acl_ipv4_set;
  25. static struct ip_set acl_ipv6_set;
  26. static void parse_addr_cidr(const char *str, char *host, int *cidr)
  27. {
  28. int ret = -1, n = 0;
  29. char *pch;
  30. pch = strchr(str, '/');
  31. while (pch != NULL) {
  32. n++;
  33. ret = pch - str;
  34. pch = strchr(pch + 1, '/');
  35. }
  36. if (ret == -1) {
  37. strcpy(host, str);
  38. *cidr = -1;
  39. } else {
  40. memcpy(host, str, ret);
  41. host[ret] = '\0';
  42. *cidr = atoi(str + ret + 1);
  43. }
  44. }
  45. int init_acl(const char *path)
  46. {
  47. // initialize ipset
  48. ipset_init_library();
  49. ipset_init(&acl_ipv4_set);
  50. ipset_init(&acl_ipv6_set);
  51. FILE *f = fopen(path, "r");
  52. if (f == NULL) {
  53. LOGE("Invalid acl path.");
  54. return -1;
  55. }
  56. char line[256];
  57. while (!feof(f)) {
  58. if (fgets(line, 256, f)) {
  59. // Trim the newline
  60. int len = strlen(line);
  61. if (len > 0 && line[len - 1] == '\n') {
  62. line[len - 1] = '\0';
  63. }
  64. char host[256];
  65. int cidr;
  66. parse_addr_cidr(line, host, &cidr);
  67. struct cork_ip addr;
  68. int err = cork_ip_init(&addr, host);
  69. if (!err) {
  70. if (addr.version == 4) {
  71. if (cidr >= 0) {
  72. ipset_ipv4_add_network(&acl_ipv4_set, &(addr.ip.v4), cidr);
  73. } else {
  74. ipset_ipv4_add(&acl_ipv4_set, &(addr.ip.v4));
  75. }
  76. } else if (addr.version == 6) {
  77. if (cidr >= 0) {
  78. ipset_ipv6_add_network(&acl_ipv6_set, &(addr.ip.v6), cidr);
  79. } else {
  80. ipset_ipv6_add(&acl_ipv6_set, &(addr.ip.v6));
  81. }
  82. }
  83. }
  84. }
  85. }
  86. fclose(f);
  87. return 0;
  88. }
  89. void free_acl(void)
  90. {
  91. ipset_done(&acl_ipv4_set);
  92. ipset_done(&acl_ipv6_set);
  93. }
  94. int acl_contains_ip(const char * host)
  95. {
  96. struct cork_ip addr;
  97. int err = cork_ip_init(&addr, host);
  98. if (err) {
  99. return 0;
  100. }
  101. if (addr.version == 4) {
  102. return ipset_contains_ipv4(&acl_ipv4_set, &(addr.ip.v4));
  103. } else if (addr.version == 6) {
  104. return ipset_contains_ipv6(&acl_ipv6_set, &(addr.ip.v6));
  105. }
  106. return 0;
  107. }