Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 2 | * ip_vs_proto_ah_esp.c: AH/ESP IPSec load balancing support for IPVS |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3 | * |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4 | * Authors: Julian Anastasov <ja@ssi.bg>, February 2002 |
| 5 | * Wensong Zhang <wensong@linuxvirtualserver.org> |
| 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 | * version 2 as published by the Free Software Foundation; |
| 10 | * |
| 11 | */ |
| 12 | |
Hannes Eder | 9aada7a | 2009-07-30 14:29:44 -0700 | [diff] [blame] | 13 | #define KMSG_COMPONENT "IPVS" |
| 14 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
| 15 | |
Arnaldo Carvalho de Melo | 14c8502 | 2005-12-27 02:43:12 -0200 | [diff] [blame] | 16 | #include <linux/in.h> |
| 17 | #include <linux/ip.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 18 | #include <linux/module.h> |
| 19 | #include <linux/kernel.h> |
| 20 | #include <linux/netfilter.h> |
| 21 | #include <linux/netfilter_ipv4.h> |
| 22 | |
| 23 | #include <net/ip_vs.h> |
| 24 | |
| 25 | |
| 26 | /* TODO: |
| 27 | |
| 28 | struct isakmp_hdr { |
| 29 | __u8 icookie[8]; |
| 30 | __u8 rcookie[8]; |
| 31 | __u8 np; |
| 32 | __u8 version; |
| 33 | __u8 xchgtype; |
| 34 | __u8 flags; |
| 35 | __u32 msgid; |
| 36 | __u32 length; |
| 37 | }; |
| 38 | |
| 39 | */ |
| 40 | |
| 41 | #define PORT_ISAKMP 500 |
| 42 | |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 43 | static void |
Eric W. Biederman | 19913de | 2015-09-21 13:01:43 -0500 | [diff] [blame] | 44 | ah_esp_conn_fill_param_proto(struct netns_ipvs *ipvs, int af, |
Alex Gartrell | 802c41a | 2015-08-26 09:40:32 -0700 | [diff] [blame] | 45 | const struct ip_vs_iphdr *iph, |
Hans Schillstrom | 6e67e58 | 2011-01-03 14:44:57 +0100 | [diff] [blame] | 46 | struct ip_vs_conn_param *p) |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 47 | { |
Alex Gartrell | 802c41a | 2015-08-26 09:40:32 -0700 | [diff] [blame] | 48 | if (likely(!ip_vs_iph_inverse(iph))) |
Eric W. Biederman | 19913de | 2015-09-21 13:01:43 -0500 | [diff] [blame] | 49 | ip_vs_conn_fill_param(ipvs, af, IPPROTO_UDP, |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 50 | &iph->saddr, htons(PORT_ISAKMP), |
| 51 | &iph->daddr, htons(PORT_ISAKMP), p); |
| 52 | else |
Eric W. Biederman | 19913de | 2015-09-21 13:01:43 -0500 | [diff] [blame] | 53 | ip_vs_conn_fill_param(ipvs, af, IPPROTO_UDP, |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 54 | &iph->daddr, htons(PORT_ISAKMP), |
| 55 | &iph->saddr, htons(PORT_ISAKMP), p); |
| 56 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 57 | |
| 58 | static struct ip_vs_conn * |
Eric W. Biederman | ab16197 | 2015-09-21 13:02:38 -0500 | [diff] [blame] | 59 | ah_esp_conn_in_get(struct netns_ipvs *ipvs, int af, const struct sk_buff *skb, |
Alex Gartrell | 802c41a | 2015-08-26 09:40:32 -0700 | [diff] [blame] | 60 | const struct ip_vs_iphdr *iph) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 61 | { |
| 62 | struct ip_vs_conn *cp; |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 63 | struct ip_vs_conn_param p; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 64 | |
Eric W. Biederman | 19913de | 2015-09-21 13:01:43 -0500 | [diff] [blame] | 65 | ah_esp_conn_fill_param_proto(ipvs, af, iph, &p); |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 66 | cp = ip_vs_conn_in_get(&p); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 67 | if (!cp) { |
| 68 | /* |
| 69 | * We are not sure if the packet is from our |
| 70 | * service, so our conn_schedule hook should return NF_ACCEPT |
| 71 | */ |
Julius Volz | 51ef348 | 2008-09-02 15:55:40 +0200 | [diff] [blame] | 72 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet " |
| 73 | "%s%s %s->%s\n", |
Alex Gartrell | 802c41a | 2015-08-26 09:40:32 -0700 | [diff] [blame] | 74 | ip_vs_iph_icmp(iph) ? "ICMP+" : "", |
Hans Schillstrom | 9330419 | 2011-01-03 14:44:51 +0100 | [diff] [blame] | 75 | ip_vs_proto_get(iph->protocol)->name, |
Julius Volz | 51ef348 | 2008-09-02 15:55:40 +0200 | [diff] [blame] | 76 | IP_VS_DBG_ADDR(af, &iph->saddr), |
| 77 | IP_VS_DBG_ADDR(af, &iph->daddr)); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 78 | } |
| 79 | |
| 80 | return cp; |
| 81 | } |
| 82 | |
| 83 | |
| 84 | static struct ip_vs_conn * |
Eric W. Biederman | 0cf705c8c | 2015-09-21 13:02:39 -0500 | [diff] [blame] | 85 | ah_esp_conn_out_get(struct netns_ipvs *ipvs, int af, const struct sk_buff *skb, |
Alex Gartrell | 802c41a | 2015-08-26 09:40:32 -0700 | [diff] [blame] | 86 | const struct ip_vs_iphdr *iph) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 87 | { |
| 88 | struct ip_vs_conn *cp; |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 89 | struct ip_vs_conn_param p; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 90 | |
Eric W. Biederman | 19913de | 2015-09-21 13:01:43 -0500 | [diff] [blame] | 91 | ah_esp_conn_fill_param_proto(ipvs, af, iph, &p); |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 92 | cp = ip_vs_conn_out_get(&p); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 93 | if (!cp) { |
Julius Volz | 51ef348 | 2008-09-02 15:55:40 +0200 | [diff] [blame] | 94 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet " |
| 95 | "%s%s %s->%s\n", |
Alex Gartrell | 802c41a | 2015-08-26 09:40:32 -0700 | [diff] [blame] | 96 | ip_vs_iph_icmp(iph) ? "ICMP+" : "", |
Hans Schillstrom | 9330419 | 2011-01-03 14:44:51 +0100 | [diff] [blame] | 97 | ip_vs_proto_get(iph->protocol)->name, |
Julius Volz | 51ef348 | 2008-09-02 15:55:40 +0200 | [diff] [blame] | 98 | IP_VS_DBG_ADDR(af, &iph->saddr), |
| 99 | IP_VS_DBG_ADDR(af, &iph->daddr)); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | return cp; |
| 103 | } |
| 104 | |
| 105 | |
| 106 | static int |
Eric W. Biederman | d8f44c3 | 2015-09-21 13:02:43 -0500 | [diff] [blame] | 107 | ah_esp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, |
| 108 | struct ip_vs_proto_data *pd, |
Jesper Dangaard Brouer | d4383f0 | 2012-09-26 14:07:17 +0200 | [diff] [blame] | 109 | int *verdict, struct ip_vs_conn **cpp, |
| 110 | struct ip_vs_iphdr *iph) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 111 | { |
| 112 | /* |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 113 | * AH/ESP is only related traffic. Pass the packet to IP stack. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 114 | */ |
| 115 | *verdict = NF_ACCEPT; |
| 116 | return 0; |
| 117 | } |
| 118 | |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 119 | #ifdef CONFIG_IP_VS_PROTO_AH |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 120 | struct ip_vs_protocol ip_vs_protocol_ah = { |
| 121 | .name = "AH", |
| 122 | .protocol = IPPROTO_AH, |
Julian Anastasov | 2ad17de | 2008-04-29 03:21:23 -0700 | [diff] [blame] | 123 | .num_states = 1, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 124 | .dont_defrag = 1, |
Hans Schillstrom | 88fe2d3 | 2011-01-03 14:44:50 +0100 | [diff] [blame] | 125 | .init = NULL, |
| 126 | .exit = NULL, |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 127 | .conn_schedule = ah_esp_conn_schedule, |
| 128 | .conn_in_get = ah_esp_conn_in_get, |
| 129 | .conn_out_get = ah_esp_conn_out_get, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 130 | .snat_handler = NULL, |
| 131 | .dnat_handler = NULL, |
| 132 | .csum_check = NULL, |
| 133 | .state_transition = NULL, |
| 134 | .register_app = NULL, |
| 135 | .unregister_app = NULL, |
| 136 | .app_conn_bind = NULL, |
Julian Anastasov | 0d79641 | 2010-10-17 16:46:17 +0300 | [diff] [blame] | 137 | .debug_packet = ip_vs_tcpudp_debug_packet, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 138 | .timeout_change = NULL, /* ISAKMP */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 139 | }; |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 140 | #endif |
| 141 | |
| 142 | #ifdef CONFIG_IP_VS_PROTO_ESP |
| 143 | struct ip_vs_protocol ip_vs_protocol_esp = { |
| 144 | .name = "ESP", |
| 145 | .protocol = IPPROTO_ESP, |
| 146 | .num_states = 1, |
| 147 | .dont_defrag = 1, |
Hans Schillstrom | 88fe2d3 | 2011-01-03 14:44:50 +0100 | [diff] [blame] | 148 | .init = NULL, |
| 149 | .exit = NULL, |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 150 | .conn_schedule = ah_esp_conn_schedule, |
| 151 | .conn_in_get = ah_esp_conn_in_get, |
| 152 | .conn_out_get = ah_esp_conn_out_get, |
| 153 | .snat_handler = NULL, |
| 154 | .dnat_handler = NULL, |
| 155 | .csum_check = NULL, |
| 156 | .state_transition = NULL, |
| 157 | .register_app = NULL, |
| 158 | .unregister_app = NULL, |
| 159 | .app_conn_bind = NULL, |
Julian Anastasov | 0d79641 | 2010-10-17 16:46:17 +0300 | [diff] [blame] | 160 | .debug_packet = ip_vs_tcpudp_debug_packet, |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 161 | .timeout_change = NULL, /* ISAKMP */ |
| 162 | }; |
| 163 | #endif |