service.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
  4. */
  5. #include <libubox/avl-cmp.h>
  6. #include "unetd.h"
  7. enum {
  8. SERVICE_ATTR_TYPE,
  9. SERVICE_ATTR_CONFIG,
  10. SERVICE_ATTR_MEMBERS,
  11. __SERVICE_ATTR_MAX
  12. };
  13. static const struct blobmsg_policy service_policy[__SERVICE_ATTR_MAX] = {
  14. [SERVICE_ATTR_TYPE] = { "type", BLOBMSG_TYPE_STRING },
  15. [SERVICE_ATTR_CONFIG] = { "config", BLOBMSG_TYPE_TABLE },
  16. [SERVICE_ATTR_MEMBERS] = { "members", BLOBMSG_TYPE_ARRAY },
  17. };
  18. void network_services_free(struct network *net)
  19. {
  20. vlist_flush_all(&net->services);
  21. }
  22. static int
  23. __service_add_member(struct network_host **list, int *n, struct network_host *member)
  24. {
  25. int i;
  26. for (i = 0; i < *n; i++) {
  27. if (list[i] == member)
  28. return 0;
  29. }
  30. list[(*n)++] = member;
  31. return 1;
  32. }
  33. static int
  34. __service_add_group(struct network_host **list, int *n, struct network_group *group)
  35. {
  36. int i, count = 0;
  37. for (i = 0; i < group->n_members; i++)
  38. count += __service_add_member(list, n, group->members[i]);
  39. return count;
  40. }
  41. static int
  42. __service_parse_members(struct network *net, struct network_service *s,
  43. const char *name)
  44. {
  45. struct network_group *group;
  46. struct network_host *host;
  47. if (name[0] != '@') {
  48. host = avl_find_element(&net->hosts, name, host, node);
  49. if (!host)
  50. return 0;
  51. if (s)
  52. __service_add_member(s->members, &s->n_members, host);
  53. return 1;
  54. }
  55. name++;
  56. group = avl_find_element(&net->groups, name, group, node);
  57. if (!group)
  58. return 0;
  59. if (s)
  60. return __service_add_group(s->members, &s->n_members, group);
  61. else
  62. return group->n_members;
  63. }
  64. static int
  65. service_parse_members(struct network *net, struct network_service *s,
  66. struct blob_attr *data)
  67. {
  68. struct blob_attr *cur;
  69. int rem;
  70. int n = 0;
  71. blobmsg_for_each_attr(cur, data, rem)
  72. n += __service_parse_members(net, s, blobmsg_get_string(cur));
  73. return n;
  74. }
  75. static void
  76. service_add(struct network *net, struct blob_attr *data)
  77. {
  78. struct network_service *s;
  79. struct blob_attr *tb[__SERVICE_ATTR_MAX];
  80. struct blob_attr *cur, *config;
  81. const char *name = blobmsg_name(data);
  82. const char *type = NULL;
  83. char *name_buf, *type_buf;
  84. void *config_buf;
  85. int n_members;
  86. blobmsg_parse(service_policy, __SERVICE_ATTR_MAX, tb,
  87. blobmsg_data(data), blobmsg_len(data));
  88. if ((cur = tb[SERVICE_ATTR_TYPE]) != NULL)
  89. type = blobmsg_get_string(cur);
  90. if (blobmsg_check_array(tb[SERVICE_ATTR_MEMBERS], BLOBMSG_TYPE_STRING) < 0)
  91. return;
  92. config = tb[SERVICE_ATTR_CONFIG];
  93. n_members = service_parse_members(net, NULL, tb[SERVICE_ATTR_MEMBERS]);
  94. s = calloc_a(sizeof(*s) + n_members * sizeof(s->members[0]),
  95. &name_buf, strlen(name) + 1,
  96. &type_buf, type ? strlen(type) + 1 : 0,
  97. &config_buf, config ? blob_pad_len(config) : 0);
  98. strcpy(name_buf, name);
  99. if (type)
  100. s->type = strcpy(type_buf, type);
  101. if (config)
  102. s->config = memcpy(config_buf, config, blob_pad_len(config));
  103. #ifdef VXLAN_SUPPORT
  104. if (type && !strcmp(type, "vxlan"))
  105. s->ops = &vxlan_ops;
  106. #endif
  107. service_parse_members(net, s, tb[SERVICE_ATTR_MEMBERS]);
  108. vlist_add(&net->services, &s->node, name_buf);
  109. }
  110. void network_services_add(struct network *net, struct blob_attr *data)
  111. {
  112. struct blob_attr *cur;
  113. int rem;
  114. blobmsg_for_each_attr(cur, data, rem)
  115. service_add(net, cur);
  116. }
  117. static void
  118. service_update(struct vlist_tree *tree, struct vlist_node *node_new,
  119. struct vlist_node *node_old)
  120. {
  121. struct network *net = container_of(tree, struct network, services);
  122. struct network_service *s_old, *s_new;
  123. s_new = container_of_safe(node_new, struct network_service, node);
  124. s_old = container_of_safe(node_old, struct network_service, node);
  125. if (s_new && s_old && s_new->ops && s_new->ops == s_old->ops) {
  126. s_new->ops->init(net, s_new, s_old);
  127. goto out;
  128. }
  129. if (s_new && s_new->ops)
  130. s_new->ops->init(net, s_new, NULL);
  131. if (s_old && s_old->ops)
  132. s_old->ops->free(net, s_old);
  133. out:
  134. free(s_old);
  135. }
  136. void network_services_peer_update(struct network *net, struct network_peer *peer)
  137. {
  138. struct network_service *s;
  139. vlist_for_each_element(&net->services, s, node) {
  140. if (!s->ops || !s->ops->peer_update)
  141. continue;
  142. s->ops->peer_update(net, s, peer);
  143. }
  144. }
  145. void network_services_init(struct network *net)
  146. {
  147. vlist_init(&net->services, avl_strcmp, service_update);
  148. }