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 |
Hans Schillstrom | 6e67e58 | 2011-01-03 14:44:57 +0100 | [diff] [blame] | 44 | ah_esp_conn_fill_param_proto(struct net *net, int af, |
| 45 | const struct ip_vs_iphdr *iph, int inverse, |
| 46 | struct ip_vs_conn_param *p) |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 47 | { |
| 48 | if (likely(!inverse)) |
Hans Schillstrom | 6e67e58 | 2011-01-03 14:44:57 +0100 | [diff] [blame] | 49 | ip_vs_conn_fill_param(net, 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 |
Hans Schillstrom | 6e67e58 | 2011-01-03 14:44:57 +0100 | [diff] [blame] | 53 | ip_vs_conn_fill_param(net, 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 * |
Hans Schillstrom | 9330419 | 2011-01-03 14:44:51 +0100 | [diff] [blame] | 59 | ah_esp_conn_in_get(int af, const struct sk_buff *skb, |
Jesper Dangaard Brouer | d4383f0 | 2012-09-26 14:07:17 +0200 | [diff] [blame] | 60 | const struct ip_vs_iphdr *iph, |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 61 | int inverse) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 62 | { |
| 63 | struct ip_vs_conn *cp; |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 64 | struct ip_vs_conn_param p; |
Hans Schillstrom | 6e67e58 | 2011-01-03 14:44:57 +0100 | [diff] [blame] | 65 | struct net *net = skb_net(skb); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 66 | |
Hans Schillstrom | 6e67e58 | 2011-01-03 14:44:57 +0100 | [diff] [blame] | 67 | ah_esp_conn_fill_param_proto(net, af, iph, inverse, &p); |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 68 | cp = ip_vs_conn_in_get(&p); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 69 | if (!cp) { |
| 70 | /* |
| 71 | * We are not sure if the packet is from our |
| 72 | * service, so our conn_schedule hook should return NF_ACCEPT |
| 73 | */ |
Julius Volz | 51ef348 | 2008-09-02 15:55:40 +0200 | [diff] [blame] | 74 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet " |
| 75 | "%s%s %s->%s\n", |
| 76 | inverse ? "ICMP+" : "", |
Hans Schillstrom | 9330419 | 2011-01-03 14:44:51 +0100 | [diff] [blame] | 77 | ip_vs_proto_get(iph->protocol)->name, |
Julius Volz | 51ef348 | 2008-09-02 15:55:40 +0200 | [diff] [blame] | 78 | IP_VS_DBG_ADDR(af, &iph->saddr), |
| 79 | IP_VS_DBG_ADDR(af, &iph->daddr)); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | return cp; |
| 83 | } |
| 84 | |
| 85 | |
| 86 | static struct ip_vs_conn * |
Julius Volz | 51ef348 | 2008-09-02 15:55:40 +0200 | [diff] [blame] | 87 | ah_esp_conn_out_get(int af, const struct sk_buff *skb, |
Jesper Dangaard Brouer | d4383f0 | 2012-09-26 14:07:17 +0200 | [diff] [blame] | 88 | const struct ip_vs_iphdr *iph, int inverse) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 89 | { |
| 90 | struct ip_vs_conn *cp; |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 91 | struct ip_vs_conn_param p; |
Hans Schillstrom | 6e67e58 | 2011-01-03 14:44:57 +0100 | [diff] [blame] | 92 | struct net *net = skb_net(skb); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 93 | |
Hans Schillstrom | 6e67e58 | 2011-01-03 14:44:57 +0100 | [diff] [blame] | 94 | ah_esp_conn_fill_param_proto(net, af, iph, inverse, &p); |
Simon Horman | f11017e | 2010-08-22 21:37:52 +0900 | [diff] [blame] | 95 | cp = ip_vs_conn_out_get(&p); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 96 | if (!cp) { |
Julius Volz | 51ef348 | 2008-09-02 15:55:40 +0200 | [diff] [blame] | 97 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet " |
| 98 | "%s%s %s->%s\n", |
| 99 | inverse ? "ICMP+" : "", |
Hans Schillstrom | 9330419 | 2011-01-03 14:44:51 +0100 | [diff] [blame] | 100 | ip_vs_proto_get(iph->protocol)->name, |
Julius Volz | 51ef348 | 2008-09-02 15:55:40 +0200 | [diff] [blame] | 101 | IP_VS_DBG_ADDR(af, &iph->saddr), |
| 102 | IP_VS_DBG_ADDR(af, &iph->daddr)); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | return cp; |
| 106 | } |
| 107 | |
| 108 | |
| 109 | static int |
Hans Schillstrom | 9330419 | 2011-01-03 14:44:51 +0100 | [diff] [blame] | 110 | ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, |
Jesper Dangaard Brouer | d4383f0 | 2012-09-26 14:07:17 +0200 | [diff] [blame] | 111 | int *verdict, struct ip_vs_conn **cpp, |
| 112 | struct ip_vs_iphdr *iph) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 113 | { |
| 114 | /* |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 115 | * AH/ESP is only related traffic. Pass the packet to IP stack. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 116 | */ |
| 117 | *verdict = NF_ACCEPT; |
| 118 | return 0; |
| 119 | } |
| 120 | |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 121 | #ifdef CONFIG_IP_VS_PROTO_AH |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 122 | struct ip_vs_protocol ip_vs_protocol_ah = { |
| 123 | .name = "AH", |
| 124 | .protocol = IPPROTO_AH, |
Julian Anastasov | 2ad17de | 2008-04-29 03:21:23 -0700 | [diff] [blame] | 125 | .num_states = 1, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 126 | .dont_defrag = 1, |
Hans Schillstrom | 88fe2d3 | 2011-01-03 14:44:50 +0100 | [diff] [blame] | 127 | .init = NULL, |
| 128 | .exit = NULL, |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 129 | .conn_schedule = ah_esp_conn_schedule, |
| 130 | .conn_in_get = ah_esp_conn_in_get, |
| 131 | .conn_out_get = ah_esp_conn_out_get, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 132 | .snat_handler = NULL, |
| 133 | .dnat_handler = NULL, |
| 134 | .csum_check = NULL, |
| 135 | .state_transition = NULL, |
| 136 | .register_app = NULL, |
| 137 | .unregister_app = NULL, |
| 138 | .app_conn_bind = NULL, |
Julian Anastasov | 0d79641 | 2010-10-17 16:46:17 +0300 | [diff] [blame] | 139 | .debug_packet = ip_vs_tcpudp_debug_packet, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 140 | .timeout_change = NULL, /* ISAKMP */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 141 | }; |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 142 | #endif |
| 143 | |
| 144 | #ifdef CONFIG_IP_VS_PROTO_ESP |
| 145 | struct ip_vs_protocol ip_vs_protocol_esp = { |
| 146 | .name = "ESP", |
| 147 | .protocol = IPPROTO_ESP, |
| 148 | .num_states = 1, |
| 149 | .dont_defrag = 1, |
Hans Schillstrom | 88fe2d3 | 2011-01-03 14:44:50 +0100 | [diff] [blame] | 150 | .init = NULL, |
| 151 | .exit = NULL, |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 152 | .conn_schedule = ah_esp_conn_schedule, |
| 153 | .conn_in_get = ah_esp_conn_in_get, |
| 154 | .conn_out_get = ah_esp_conn_out_get, |
| 155 | .snat_handler = NULL, |
| 156 | .dnat_handler = NULL, |
| 157 | .csum_check = NULL, |
| 158 | .state_transition = NULL, |
| 159 | .register_app = NULL, |
| 160 | .unregister_app = NULL, |
| 161 | .app_conn_bind = NULL, |
Julian Anastasov | 0d79641 | 2010-10-17 16:46:17 +0300 | [diff] [blame] | 162 | .debug_packet = ip_vs_tcpudp_debug_packet, |
Julius Volz | 409a196 | 2008-08-22 14:06:12 +0200 | [diff] [blame] | 163 | .timeout_change = NULL, /* ISAKMP */ |
| 164 | }; |
| 165 | #endif |