alias.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * netifd - network interface daemon
  3. * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2
  7. * as published by the Free Software Foundation
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include "netifd.h"
  18. #include "device.h"
  19. #include "interface.h"
  20. static struct avl_tree aliases;
  21. struct alias_device {
  22. struct avl_node avl;
  23. struct device dev;
  24. struct device_user dep;
  25. struct device_user new_dep;
  26. bool update;
  27. char name[];
  28. };
  29. static const struct device_type alias_device_type;
  30. static void alias_set_device(struct alias_device *alias, struct device *dev)
  31. {
  32. if (dev == alias->dep.dev)
  33. return;
  34. device_set_present(&alias->dev, false);
  35. device_remove_user(&alias->new_dep);
  36. if (alias->dev.active) {
  37. if (dev)
  38. device_add_user(&alias->new_dep, dev);
  39. alias->update = true;
  40. return;
  41. }
  42. alias->update = false;
  43. device_remove_user(&alias->dep);
  44. alias->dev.hidden = !dev;
  45. if (dev) {
  46. alias->dev.ifindex = dev->ifindex;
  47. strcpy(alias->dev.ifname, dev->ifname);
  48. device_broadcast_event(&alias->dev, DEV_EVENT_UPDATE_IFNAME);
  49. device_add_user(&alias->dep, dev);
  50. } else {
  51. alias->dev.ifname[0] = 0;
  52. device_broadcast_event(&alias->dev, DEV_EVENT_UPDATE_IFNAME);
  53. }
  54. }
  55. static int
  56. alias_device_set_state(struct device *dev, bool state)
  57. {
  58. struct alias_device *alias;
  59. alias = container_of(dev, struct alias_device, dev);
  60. if (!alias->dep.dev)
  61. return -1;
  62. if (state)
  63. return device_claim(&alias->dep);
  64. device_release(&alias->dep);
  65. if (alias->update)
  66. alias_set_device(alias, alias->new_dep.dev);
  67. return 0;
  68. }
  69. static void alias_device_cb(struct device_user *dep, enum device_event ev)
  70. {
  71. struct alias_device *alias;
  72. bool present = false;
  73. alias = container_of(dep, struct alias_device, dep);
  74. switch (ev) {
  75. case DEV_EVENT_ADD:
  76. present = true;
  77. case DEV_EVENT_REMOVE:
  78. device_set_present(&alias->dev, present);
  79. break;
  80. default:
  81. device_broadcast_event(&alias->dev, ev);
  82. break;
  83. }
  84. }
  85. static struct device *
  86. alias_device_create(const char *name, struct blob_attr *attr)
  87. {
  88. struct alias_device *alias;
  89. alias = calloc(1, sizeof(*alias) + strlen(name) + 1);
  90. strcpy(alias->name, name);
  91. alias->dev.set_state = alias_device_set_state;
  92. alias->dev.hidden = true;
  93. device_init_virtual(&alias->dev, &alias_device_type, NULL);
  94. alias->avl.key = alias->name;
  95. avl_insert(&aliases, &alias->avl);
  96. alias->dep.alias = true;
  97. alias->dep.cb = alias_device_cb;
  98. device_check_state(&alias->dev);
  99. return &alias->dev;
  100. }
  101. static void alias_device_free(struct device *dev)
  102. {
  103. struct alias_device *alias;
  104. alias = container_of(dev, struct alias_device, dev);
  105. avl_delete(&aliases, &alias->avl);
  106. free(alias);
  107. }
  108. static int alias_check_state(struct device *dev)
  109. {
  110. struct alias_device *alias;
  111. struct interface *iface;
  112. struct device *ndev = NULL;
  113. alias = container_of(dev, struct alias_device, dev);
  114. iface = vlist_find(&interfaces, alias->name, iface, node);
  115. if (iface && iface->state == IFS_UP)
  116. ndev = iface->l3_dev.dev;
  117. alias_set_device(alias, ndev);
  118. return 0;
  119. }
  120. static const struct device_type alias_device_type = {
  121. .name = "Network alias",
  122. .create = alias_device_create,
  123. .free = alias_device_free,
  124. .check_state = alias_check_state,
  125. };
  126. void
  127. alias_notify_device(const char *name, struct device *dev)
  128. {
  129. struct alias_device *alias;
  130. device_lock();
  131. alias = avl_find_element(&aliases, name, alias, avl);
  132. if (alias)
  133. alias_set_device(alias, dev);
  134. device_unlock();
  135. }
  136. struct device *
  137. device_alias_get(const char *name)
  138. {
  139. struct alias_device *alias;
  140. alias = avl_find_element(&aliases, name, alias, avl);
  141. if (alias)
  142. return &alias->dev;
  143. return alias_device_create(name, NULL);
  144. }
  145. static void __init alias_init(void)
  146. {
  147. avl_init(&aliases, avl_strcmp, false, NULL);
  148. }