RouteGen_admin.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "benc/String.h"
  16. #include "benc/Dict.h"
  17. #include "benc/List.h"
  18. #include "exception/Jmp.h"
  19. #include "memory/Allocator.h"
  20. #include "tunnel/RouteGen.h"
  21. #include "admin/Admin.h"
  22. #include "tunnel/RouteGen_admin.h"
  23. #include "util/Base10.h"
  24. #include "util/Identity.h"
  25. struct RouteGen_admin_Ctx
  26. {
  27. struct RouteGen* rg;
  28. struct Admin* admin;
  29. Identity
  30. };
  31. static int getIntVal(Dict* d, String* name)
  32. {
  33. int64_t* valP = Dict_getInt(d, name);
  34. return (valP && (*valP > 0)) ? *valP : 0;
  35. }
  36. #define ROUTES_PER_PAGE 20
  37. static void getSomething(Dict* args,
  38. struct RouteGen_admin_Ctx* ctx,
  39. String* txid,
  40. struct Allocator* requestAlloc,
  41. Dict* genRoutes)
  42. {
  43. int page = getIntVal(args, String_CONST("page"));
  44. List* routes;
  45. if (getIntVal(args, String_CONST("ip6"))) {
  46. routes = Dict_getListC(genRoutes, "ipv6");
  47. } else {
  48. routes = Dict_getListC(genRoutes, "ipv4");
  49. }
  50. Assert_true(routes);
  51. List* outList = List_new(requestAlloc);
  52. bool more = false;
  53. for (int i = page * ROUTES_PER_PAGE, j = 0; i < List_size(routes) && j < ROUTES_PER_PAGE; j++) {
  54. String* route = List_getString(routes, i);
  55. Assert_true(route);
  56. List_addString(outList, route, requestAlloc);
  57. if (++i >= List_size(routes)) {
  58. more = false;
  59. break;
  60. }
  61. more = true;
  62. }
  63. Dict* out = Dict_new(requestAlloc);
  64. if (more) {
  65. Dict_putInt(out, String_new("more", requestAlloc), 1, requestAlloc);
  66. }
  67. Dict_putList(out, String_new("routes", requestAlloc), outList, requestAlloc);
  68. Admin_sendMessage(out, txid, ctx->admin);
  69. }
  70. #define GET_SOMETHING(name) \
  71. static void name(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) \
  72. { \
  73. struct RouteGen_admin_Ctx* ctx = Identity_check((struct RouteGen_admin_Ctx*) vcontext); \
  74. Dict* genRoutes = RouteGen_ ## name (ctx->rg, requestAlloc); \
  75. getSomething(args, ctx, txid, requestAlloc, genRoutes); \
  76. }
  77. GET_SOMETHING(getPrefixes)
  78. GET_SOMETHING(getLocalPrefixes)
  79. GET_SOMETHING(getExceptions)
  80. GET_SOMETHING(getGeneratedRoutes)
  81. #define REGISTER_GET_SOMETHING(_name, ctx, admin) \
  82. Admin_registerFunction("RouteGen_" #_name, _name, ctx, true, \
  83. ((struct Admin_FunctionArg[]) { \
  84. { .name = "page", .required = 0, .type = "Int" }, \
  85. { .name = "ip6", .required = 0, .type = "Int" } \
  86. }), admin)
  87. enum addRemoveSomething_What {
  88. addRemoveSomething_What_ADD_EXCEPTION,
  89. addRemoveSomething_What_RM_EXCEPTION,
  90. addRemoveSomething_What_ADD_PREFIX,
  91. addRemoveSomething_What_RM_PREFIX,
  92. addRemoveSomething_What_ADD_LOCALPREFIX,
  93. addRemoveSomething_What_RM_LOCALPREFIX,
  94. };
  95. static void addRemoveSomething(Dict* args,
  96. void* vcontext,
  97. String* txid,
  98. struct Allocator* requestAlloc,
  99. enum addRemoveSomething_What what)
  100. {
  101. struct RouteGen_admin_Ctx* ctx = Identity_check((struct RouteGen_admin_Ctx*) vcontext);
  102. String* route = Dict_getStringC(args, "route");
  103. char* error = NULL;
  104. struct Sockaddr_storage ss;
  105. if (route->len > 63) {
  106. error = "parse_failed";
  107. }
  108. if (!error) {
  109. if (Sockaddr_parse(route->bytes, &ss)) {
  110. error = "parse_failed";
  111. } else {
  112. int family = Sockaddr_getFamily(&ss.addr);
  113. if (family != Sockaddr_AF_INET && family != Sockaddr_AF_INET6) {
  114. error = "unexpected_af";
  115. }
  116. }
  117. }
  118. int retVal = -1;
  119. Dict* out = Dict_new(requestAlloc);
  120. if (!error) {
  121. switch (what) {
  122. case addRemoveSomething_What_ADD_EXCEPTION:
  123. RouteGen_addException(ctx->rg, &ss.addr); break;
  124. case addRemoveSomething_What_ADD_PREFIX:
  125. RouteGen_addPrefix(ctx->rg, &ss.addr); break;
  126. case addRemoveSomething_What_ADD_LOCALPREFIX:
  127. RouteGen_addLocalPrefix(ctx->rg, &ss.addr); break;
  128. case addRemoveSomething_What_RM_EXCEPTION:
  129. retVal = RouteGen_removeException(ctx->rg, &ss.addr); break;
  130. case addRemoveSomething_What_RM_PREFIX:
  131. retVal = RouteGen_removePrefix(ctx->rg, &ss.addr); break;
  132. case addRemoveSomething_What_RM_LOCALPREFIX:
  133. retVal = RouteGen_removeLocalPrefix(ctx->rg, &ss.addr); break;
  134. default: Assert_failure("invalid op");
  135. }
  136. if (!retVal) {
  137. error = "no_such_route";
  138. } else {
  139. error = "none";
  140. }
  141. }
  142. Dict_putString(out,
  143. String_new("error", requestAlloc),
  144. String_new(error, requestAlloc),
  145. requestAlloc);
  146. Admin_sendMessage(out, txid, ctx->admin);
  147. }
  148. #define ADD_REMOVE_SOMETHING(name, op) \
  149. static void name(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) \
  150. { \
  151. addRemoveSomething(args, vcontext, txid, requestAlloc, op); \
  152. }
  153. ADD_REMOVE_SOMETHING(addException, addRemoveSomething_What_ADD_EXCEPTION)
  154. ADD_REMOVE_SOMETHING(addPrefix, addRemoveSomething_What_ADD_PREFIX)
  155. ADD_REMOVE_SOMETHING(addLocalPrefix, addRemoveSomething_What_ADD_LOCALPREFIX)
  156. ADD_REMOVE_SOMETHING(removePrefix, addRemoveSomething_What_RM_PREFIX)
  157. ADD_REMOVE_SOMETHING(removeLocalPrefix, addRemoveSomething_What_RM_LOCALPREFIX)
  158. ADD_REMOVE_SOMETHING(removeException, addRemoveSomething_What_RM_EXCEPTION)
  159. #define REGISTER_ADD_REMOVE_SOMETHING(_name, ctx, admin) \
  160. Admin_registerFunction("RouteGen_" #_name, _name, ctx, true, \
  161. ((struct Admin_FunctionArg[]) { \
  162. { .name = "route", .required = 1, .type = "String" }, \
  163. }), admin)
  164. static void commit(Dict* args,
  165. void* vcontext,
  166. String* txid,
  167. struct Allocator* requestAlloc)
  168. {
  169. struct RouteGen_admin_Ctx* const ctx = Identity_check((struct RouteGen_admin_Ctx*) vcontext);
  170. String* const tunName = Dict_getStringC(args, "tunName");
  171. Dict* const ret = Dict_new(requestAlloc);
  172. char* error;
  173. struct Jmp j;
  174. Jmp_try(j) {
  175. RouteGen_commit(ctx->rg, tunName->bytes, requestAlloc, &j.handler);
  176. error = "none";
  177. } Jmp_catch {
  178. error = j.message;
  179. }
  180. Dict_putString(ret,
  181. String_new("error", requestAlloc),
  182. String_new(error, requestAlloc),
  183. requestAlloc);
  184. Admin_sendMessage(ret, txid, ctx->admin);
  185. }
  186. void RouteGen_admin_register(struct RouteGen* rg, struct Admin* admin, struct Allocator* alloc)
  187. {
  188. struct RouteGen_admin_Ctx* ctx = Allocator_calloc(alloc, sizeof(struct RouteGen_admin_Ctx), 1);
  189. ctx->rg = rg;
  190. ctx->admin = admin;
  191. Identity_set(ctx);
  192. REGISTER_GET_SOMETHING(getPrefixes, ctx, admin);
  193. REGISTER_GET_SOMETHING(getLocalPrefixes, ctx, admin);
  194. REGISTER_GET_SOMETHING(getExceptions, ctx, admin);
  195. REGISTER_GET_SOMETHING(getGeneratedRoutes, ctx, admin);
  196. REGISTER_ADD_REMOVE_SOMETHING(addException, ctx, admin);
  197. REGISTER_ADD_REMOVE_SOMETHING(addPrefix, ctx, admin);
  198. REGISTER_ADD_REMOVE_SOMETHING(addLocalPrefix, ctx, admin);
  199. REGISTER_ADD_REMOVE_SOMETHING(removePrefix, ctx, admin);
  200. REGISTER_ADD_REMOVE_SOMETHING(removeLocalPrefix, ctx, admin);
  201. REGISTER_ADD_REMOVE_SOMETHING(removeException, ctx, admin);
  202. Admin_registerFunction("RouteGen_commit", commit, ctx, true,
  203. ((struct Admin_FunctionArg[]) {
  204. { .name = "tunName", .required = 1, .type = "String" },
  205. }), admin);
  206. }