PageRenderTime 25ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/net/netfilter/ipvs/ip_vs_proto.c

https://gitlab.com/kush/linux
C | 389 lines | 283 code | 59 blank | 47 comment | 58 complexity | c7b7cfef90ce47c84d60fd7e0b5a7588 MD5 | raw file
  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. #define KMSG_COMPONENT "IPVS"
  16. #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/skbuff.h>
  20. #include <linux/gfp.h>
  21. #include <linux/in.h>
  22. #include <linux/ip.h>
  23. #include <net/protocol.h>
  24. #include <net/tcp.h>
  25. #include <net/udp.h>
  26. #include <linux/stat.h>
  27. #include <linux/proc_fs.h>
  28. #include <net/ip_vs.h>
  29. /*
  30. * IPVS protocols can only be registered/unregistered when the ipvs
  31. * module is loaded/unloaded, so no lock is needed in accessing the
  32. * ipvs protocol table.
  33. */
  34. #define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */
  35. #define IP_VS_PROTO_HASH(proto) ((proto) & (IP_VS_PROTO_TAB_SIZE-1))
  36. static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE];
  37. /* States for conn templates: NONE or words separated with ",", max 15 chars */
  38. static const char *ip_vs_ctpl_state_name_table[IP_VS_CTPL_S_LAST] = {
  39. [IP_VS_CTPL_S_NONE] = "NONE",
  40. [IP_VS_CTPL_S_ASSURED] = "ASSURED",
  41. };
  42. /*
  43. * register an ipvs protocol
  44. */
  45. static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)
  46. {
  47. unsigned int hash = IP_VS_PROTO_HASH(pp->protocol);
  48. pp->next = ip_vs_proto_table[hash];
  49. ip_vs_proto_table[hash] = pp;
  50. if (pp->init != NULL)
  51. pp->init(pp);
  52. return 0;
  53. }
  54. /*
  55. * register an ipvs protocols netns related data
  56. */
  57. static int
  58. register_ip_vs_proto_netns(struct netns_ipvs *ipvs, struct ip_vs_protocol *pp)
  59. {
  60. unsigned int hash = IP_VS_PROTO_HASH(pp->protocol);
  61. struct ip_vs_proto_data *pd =
  62. kzalloc(sizeof(struct ip_vs_proto_data), GFP_KERNEL);
  63. if (!pd)
  64. return -ENOMEM;
  65. pd->pp = pp; /* For speed issues */
  66. pd->next = ipvs->proto_data_table[hash];
  67. ipvs->proto_data_table[hash] = pd;
  68. atomic_set(&pd->appcnt, 0); /* Init app counter */
  69. if (pp->init_netns != NULL) {
  70. int ret = pp->init_netns(ipvs, pd);
  71. if (ret) {
  72. /* unlink an free proto data */
  73. ipvs->proto_data_table[hash] = pd->next;
  74. kfree(pd);
  75. return ret;
  76. }
  77. }
  78. return 0;
  79. }
  80. /*
  81. * unregister an ipvs protocol
  82. */
  83. static int unregister_ip_vs_protocol(struct ip_vs_protocol *pp)
  84. {
  85. struct ip_vs_protocol **pp_p;
  86. unsigned int hash = IP_VS_PROTO_HASH(pp->protocol);
  87. pp_p = &ip_vs_proto_table[hash];
  88. for (; *pp_p; pp_p = &(*pp_p)->next) {
  89. if (*pp_p == pp) {
  90. *pp_p = pp->next;
  91. if (pp->exit != NULL)
  92. pp->exit(pp);
  93. return 0;
  94. }
  95. }
  96. return -ESRCH;
  97. }
  98. /*
  99. * unregister an ipvs protocols netns data
  100. */
  101. static int
  102. unregister_ip_vs_proto_netns(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd)
  103. {
  104. struct ip_vs_proto_data **pd_p;
  105. unsigned int hash = IP_VS_PROTO_HASH(pd->pp->protocol);
  106. pd_p = &ipvs->proto_data_table[hash];
  107. for (; *pd_p; pd_p = &(*pd_p)->next) {
  108. if (*pd_p == pd) {
  109. *pd_p = pd->next;
  110. if (pd->pp->exit_netns != NULL)
  111. pd->pp->exit_netns(ipvs, pd);
  112. kfree(pd);
  113. return 0;
  114. }
  115. }
  116. return -ESRCH;
  117. }
  118. /*
  119. * get ip_vs_protocol object by its proto.
  120. */
  121. struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto)
  122. {
  123. struct ip_vs_protocol *pp;
  124. unsigned int hash = IP_VS_PROTO_HASH(proto);
  125. for (pp = ip_vs_proto_table[hash]; pp; pp = pp->next) {
  126. if (pp->protocol == proto)
  127. return pp;
  128. }
  129. return NULL;
  130. }
  131. EXPORT_SYMBOL(ip_vs_proto_get);
  132. /*
  133. * get ip_vs_protocol object data by netns and proto
  134. */
  135. struct ip_vs_proto_data *
  136. ip_vs_proto_data_get(struct netns_ipvs *ipvs, unsigned short proto)
  137. {
  138. struct ip_vs_proto_data *pd;
  139. unsigned int hash = IP_VS_PROTO_HASH(proto);
  140. for (pd = ipvs->proto_data_table[hash]; pd; pd = pd->next) {
  141. if (pd->pp->protocol == proto)
  142. return pd;
  143. }
  144. return NULL;
  145. }
  146. EXPORT_SYMBOL(ip_vs_proto_data_get);
  147. /*
  148. * Propagate event for state change to all protocols
  149. */
  150. void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags)
  151. {
  152. struct ip_vs_proto_data *pd;
  153. int i;
  154. for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
  155. for (pd = ipvs->proto_data_table[i]; pd; pd = pd->next) {
  156. if (pd->pp->timeout_change)
  157. pd->pp->timeout_change(pd, flags);
  158. }
  159. }
  160. }
  161. int *
  162. ip_vs_create_timeout_table(int *table, int size)
  163. {
  164. return kmemdup(table, size, GFP_KERNEL);
  165. }
  166. const char *ip_vs_state_name(const struct ip_vs_conn *cp)
  167. {
  168. unsigned int state = cp->state;
  169. struct ip_vs_protocol *pp;
  170. if (cp->flags & IP_VS_CONN_F_TEMPLATE) {
  171. if (state >= IP_VS_CTPL_S_LAST)
  172. return "ERR!";
  173. return ip_vs_ctpl_state_name_table[state] ? : "?";
  174. }
  175. pp = ip_vs_proto_get(cp->protocol);
  176. if (pp == NULL || pp->state_name == NULL)
  177. return (cp->protocol == IPPROTO_IP) ? "NONE" : "ERR!";
  178. return pp->state_name(state);
  179. }
  180. static void
  181. ip_vs_tcpudp_debug_packet_v4(struct ip_vs_protocol *pp,
  182. const struct sk_buff *skb,
  183. int offset,
  184. const char *msg)
  185. {
  186. char buf[128];
  187. struct iphdr _iph, *ih;
  188. ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
  189. if (ih == NULL)
  190. sprintf(buf, "TRUNCATED");
  191. else if (ih->frag_off & htons(IP_OFFSET))
  192. sprintf(buf, "%pI4->%pI4 frag", &ih->saddr, &ih->daddr);
  193. else {
  194. __be16 _ports[2], *pptr;
  195. pptr = skb_header_pointer(skb, offset + ih->ihl*4,
  196. sizeof(_ports), _ports);
  197. if (pptr == NULL)
  198. sprintf(buf, "TRUNCATED %pI4->%pI4",
  199. &ih->saddr, &ih->daddr);
  200. else
  201. sprintf(buf, "%pI4:%u->%pI4:%u",
  202. &ih->saddr, ntohs(pptr[0]),
  203. &ih->daddr, ntohs(pptr[1]));
  204. }
  205. pr_debug("%s: %s %s\n", msg, pp->name, buf);
  206. }
  207. #ifdef CONFIG_IP_VS_IPV6
  208. static void
  209. ip_vs_tcpudp_debug_packet_v6(struct ip_vs_protocol *pp,
  210. const struct sk_buff *skb,
  211. int offset,
  212. const char *msg)
  213. {
  214. char buf[192];
  215. struct ipv6hdr _iph, *ih;
  216. ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
  217. if (ih == NULL)
  218. sprintf(buf, "TRUNCATED");
  219. else if (ih->nexthdr == IPPROTO_FRAGMENT)
  220. sprintf(buf, "%pI6c->%pI6c frag", &ih->saddr, &ih->daddr);
  221. else {
  222. __be16 _ports[2], *pptr;
  223. pptr = skb_header_pointer(skb, offset + sizeof(struct ipv6hdr),
  224. sizeof(_ports), _ports);
  225. if (pptr == NULL)
  226. sprintf(buf, "TRUNCATED %pI6c->%pI6c",
  227. &ih->saddr, &ih->daddr);
  228. else
  229. sprintf(buf, "%pI6c:%u->%pI6c:%u",
  230. &ih->saddr, ntohs(pptr[0]),
  231. &ih->daddr, ntohs(pptr[1]));
  232. }
  233. pr_debug("%s: %s %s\n", msg, pp->name, buf);
  234. }
  235. #endif
  236. void
  237. ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
  238. const struct sk_buff *skb,
  239. int offset,
  240. const char *msg)
  241. {
  242. #ifdef CONFIG_IP_VS_IPV6
  243. if (af == AF_INET6)
  244. ip_vs_tcpudp_debug_packet_v6(pp, skb, offset, msg);
  245. else
  246. #endif
  247. ip_vs_tcpudp_debug_packet_v4(pp, skb, offset, msg);
  248. }
  249. /*
  250. * per network name-space init
  251. */
  252. int __net_init ip_vs_protocol_net_init(struct netns_ipvs *ipvs)
  253. {
  254. int i, ret;
  255. static struct ip_vs_protocol *protos[] = {
  256. #ifdef CONFIG_IP_VS_PROTO_TCP
  257. &ip_vs_protocol_tcp,
  258. #endif
  259. #ifdef CONFIG_IP_VS_PROTO_UDP
  260. &ip_vs_protocol_udp,
  261. #endif
  262. #ifdef CONFIG_IP_VS_PROTO_SCTP
  263. &ip_vs_protocol_sctp,
  264. #endif
  265. #ifdef CONFIG_IP_VS_PROTO_AH
  266. &ip_vs_protocol_ah,
  267. #endif
  268. #ifdef CONFIG_IP_VS_PROTO_ESP
  269. &ip_vs_protocol_esp,
  270. #endif
  271. };
  272. for (i = 0; i < ARRAY_SIZE(protos); i++) {
  273. ret = register_ip_vs_proto_netns(ipvs, protos[i]);
  274. if (ret < 0)
  275. goto cleanup;
  276. }
  277. return 0;
  278. cleanup:
  279. ip_vs_protocol_net_cleanup(ipvs);
  280. return ret;
  281. }
  282. void __net_exit ip_vs_protocol_net_cleanup(struct netns_ipvs *ipvs)
  283. {
  284. struct ip_vs_proto_data *pd;
  285. int i;
  286. /* unregister all the ipvs proto data for this netns */
  287. for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
  288. while ((pd = ipvs->proto_data_table[i]) != NULL)
  289. unregister_ip_vs_proto_netns(ipvs, pd);
  290. }
  291. }
  292. int __init ip_vs_protocol_init(void)
  293. {
  294. char protocols[64];
  295. #define REGISTER_PROTOCOL(p) \
  296. do { \
  297. register_ip_vs_protocol(p); \
  298. strcat(protocols, ", "); \
  299. strcat(protocols, (p)->name); \
  300. } while (0)
  301. protocols[0] = '\0';
  302. protocols[2] = '\0';
  303. #ifdef CONFIG_IP_VS_PROTO_TCP
  304. REGISTER_PROTOCOL(&ip_vs_protocol_tcp);
  305. #endif
  306. #ifdef CONFIG_IP_VS_PROTO_UDP
  307. REGISTER_PROTOCOL(&ip_vs_protocol_udp);
  308. #endif
  309. #ifdef CONFIG_IP_VS_PROTO_SCTP
  310. REGISTER_PROTOCOL(&ip_vs_protocol_sctp);
  311. #endif
  312. #ifdef CONFIG_IP_VS_PROTO_AH
  313. REGISTER_PROTOCOL(&ip_vs_protocol_ah);
  314. #endif
  315. #ifdef CONFIG_IP_VS_PROTO_ESP
  316. REGISTER_PROTOCOL(&ip_vs_protocol_esp);
  317. #endif
  318. pr_info("Registered protocols (%s)\n", &protocols[2]);
  319. return 0;
  320. }
  321. void ip_vs_protocol_cleanup(void)
  322. {
  323. struct ip_vs_protocol *pp;
  324. int i;
  325. /* unregister all the ipvs protocols */
  326. for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
  327. while ((pp = ip_vs_proto_table[i]) != NULL)
  328. unregister_ip_vs_protocol(pp);
  329. }
  330. }