ip_vs_proto.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * ip_vs_proto.c: transport protocol load balancing support for IPVS
  3. *
  4. * Authors: Wensong Zhang <wensong@linuxvirtualserver.org>
  5. * Julian Anastasov <ja@ssi.bg>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version
  10. * 2 of the License, or (at your option) any later version.
  11. *
  12. * Changes:
  13. *
  14. */
  15. #include <linux/module.h>
  16. #include <linux/kernel.h>
  17. #include <linux/skbuff.h>
  18. #include <linux/in.h>
  19. #include <linux/ip.h>
  20. #include <net/protocol.h>
  21. #include <net/tcp.h>
  22. #include <net/udp.h>
  23. #include <asm/system.h>
  24. #include <linux/stat.h>
  25. #include <linux/proc_fs.h>
  26. #include <net/ip_vs.h>
  27. /*
  28. * IPVS protocols can only be registered/unregistered when the ipvs
  29. * module is loaded/unloaded, so no lock is needed in accessing the
  30. * ipvs protocol table.
  31. */
  32. #define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */
  33. #define IP_VS_PROTO_HASH(proto) ((proto) & (IP_VS_PROTO_TAB_SIZE-1))
  34. static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE];
  35. /*
  36. * register an ipvs protocol
  37. */
  38. static int __used register_ip_vs_protocol(struct ip_vs_protocol *pp)
  39. {
  40. unsigned hash = IP_VS_PROTO_HASH(pp->protocol);
  41. pp->next = ip_vs_proto_table[hash];
  42. ip_vs_proto_table[hash] = pp;
  43. if (pp->init != NULL)
  44. pp->init(pp);
  45. return 0;
  46. }
  47. /*
  48. * unregister an ipvs protocol
  49. */
  50. static int unregister_ip_vs_protocol(struct ip_vs_protocol *pp)
  51. {
  52. struct ip_vs_protocol **pp_p;
  53. unsigned hash = IP_VS_PROTO_HASH(pp->protocol);
  54. pp_p = &ip_vs_proto_table[hash];
  55. for (; *pp_p; pp_p = &(*pp_p)->next) {
  56. if (*pp_p == pp) {
  57. *pp_p = pp->next;
  58. if (pp->exit != NULL)
  59. pp->exit(pp);
  60. return 0;
  61. }
  62. }
  63. return -ESRCH;
  64. }
  65. /*
  66. * get ip_vs_protocol object by its proto.
  67. */
  68. struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto)
  69. {
  70. struct ip_vs_protocol *pp;
  71. unsigned hash = IP_VS_PROTO_HASH(proto);
  72. for (pp = ip_vs_proto_table[hash]; pp; pp = pp->next) {
  73. if (pp->protocol == proto)
  74. return pp;
  75. }
  76. return NULL;
  77. }
  78. /*
  79. * Propagate event for state change to all protocols
  80. */
  81. void ip_vs_protocol_timeout_change(int flags)
  82. {
  83. struct ip_vs_protocol *pp;
  84. int i;
  85. for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
  86. for (pp = ip_vs_proto_table[i]; pp; pp = pp->next) {
  87. if (pp->timeout_change)
  88. pp->timeout_change(pp, flags);
  89. }
  90. }
  91. }
  92. int *
  93. ip_vs_create_timeout_table(int *table, int size)
  94. {
  95. return kmemdup(table, size, GFP_ATOMIC);
  96. }
  97. /*
  98. * Set timeout value for state specified by name
  99. */
  100. int
  101. ip_vs_set_state_timeout(int *table, int num, char **names, char *name, int to)
  102. {
  103. int i;
  104. if (!table || !name || !to)
  105. return -EINVAL;
  106. for (i = 0; i < num; i++) {
  107. if (strcmp(names[i], name))
  108. continue;
  109. table[i] = to * HZ;
  110. return 0;
  111. }
  112. return -ENOENT;
  113. }
  114. const char * ip_vs_state_name(__u16 proto, int state)
  115. {
  116. struct ip_vs_protocol *pp = ip_vs_proto_get(proto);
  117. if (pp == NULL || pp->state_name == NULL)
  118. return (IPPROTO_IP == proto) ? "NONE" : "ERR!";
  119. return pp->state_name(state);
  120. }
  121. void
  122. ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp,
  123. const struct sk_buff *skb,
  124. int offset,
  125. const char *msg)
  126. {
  127. char buf[128];
  128. struct iphdr _iph, *ih;
  129. ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
  130. if (ih == NULL)
  131. sprintf(buf, "%s TRUNCATED", pp->name);
  132. else if (ih->frag_off & htons(IP_OFFSET))
  133. sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
  134. pp->name, NIPQUAD(ih->saddr),
  135. NIPQUAD(ih->daddr));
  136. else {
  137. __be16 _ports[2], *pptr
  138. ;
  139. pptr = skb_header_pointer(skb, offset + ih->ihl*4,
  140. sizeof(_ports), _ports);
  141. if (pptr == NULL)
  142. sprintf(buf, "%s TRUNCATED %u.%u.%u.%u->%u.%u.%u.%u",
  143. pp->name,
  144. NIPQUAD(ih->saddr),
  145. NIPQUAD(ih->daddr));
  146. else
  147. sprintf(buf, "%s %u.%u.%u.%u:%u->%u.%u.%u.%u:%u",
  148. pp->name,
  149. NIPQUAD(ih->saddr),
  150. ntohs(pptr[0]),
  151. NIPQUAD(ih->daddr),
  152. ntohs(pptr[1]));
  153. }
  154. printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
  155. }
  156. int ip_vs_protocol_init(void)
  157. {
  158. char protocols[64];
  159. #define REGISTER_PROTOCOL(p) \
  160. do { \
  161. register_ip_vs_protocol(p); \
  162. strcat(protocols, ", "); \
  163. strcat(protocols, (p)->name); \
  164. } while (0)
  165. protocols[0] = '\0';
  166. protocols[2] = '\0';
  167. #ifdef CONFIG_IP_VS_PROTO_TCP
  168. REGISTER_PROTOCOL(&ip_vs_protocol_tcp);
  169. #endif
  170. #ifdef CONFIG_IP_VS_PROTO_UDP
  171. REGISTER_PROTOCOL(&ip_vs_protocol_udp);
  172. #endif
  173. #ifdef CONFIG_IP_VS_PROTO_AH
  174. REGISTER_PROTOCOL(&ip_vs_protocol_ah);
  175. #endif
  176. #ifdef CONFIG_IP_VS_PROTO_ESP
  177. REGISTER_PROTOCOL(&ip_vs_protocol_esp);
  178. #endif
  179. IP_VS_INFO("Registered protocols (%s)\n", &protocols[2]);
  180. return 0;
  181. }
  182. void ip_vs_protocol_cleanup(void)
  183. {
  184. struct ip_vs_protocol *pp;
  185. int i;
  186. /* unregister all the ipvs protocols */
  187. for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
  188. while ((pp = ip_vs_proto_table[i]) != NULL)
  189. unregister_ip_vs_protocol(pp);
  190. }
  191. }