1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ip_vs_proto_ah_esp.c: AH/ESP IPSec load balancing support for IPVS |
4 | * |
5 | * Authors: Julian Anastasov <ja@ssi.bg>, February 2002 |
6 | * Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | */ |
8 | |
9 | #define KMSG_COMPONENT "IPVS" |
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
11 | |
12 | #include <linux/in.h> |
13 | #include <linux/ip.h> |
14 | #include <linux/module.h> |
15 | #include <linux/kernel.h> |
16 | #include <linux/netfilter.h> |
17 | #include <linux/netfilter_ipv4.h> |
18 | |
19 | #include <net/ip_vs.h> |
20 | |
21 | |
22 | /* TODO: |
23 | |
24 | struct isakmp_hdr { |
25 | __u8 icookie[8]; |
26 | __u8 rcookie[8]; |
27 | __u8 np; |
28 | __u8 version; |
29 | __u8 xchgtype; |
30 | __u8 flags; |
31 | __u32 msgid; |
32 | __u32 length; |
33 | }; |
34 | |
35 | */ |
36 | |
37 | #define PORT_ISAKMP 500 |
38 | |
39 | static void |
40 | ah_esp_conn_fill_param_proto(struct netns_ipvs *ipvs, int af, |
41 | const struct ip_vs_iphdr *iph, |
42 | struct ip_vs_conn_param *p) |
43 | { |
44 | if (likely(!ip_vs_iph_inverse(iph))) |
45 | ip_vs_conn_fill_param(ipvs, af, IPPROTO_UDP, |
46 | caddr: &iph->saddr, htons(PORT_ISAKMP), |
47 | vaddr: &iph->daddr, htons(PORT_ISAKMP), p); |
48 | else |
49 | ip_vs_conn_fill_param(ipvs, af, IPPROTO_UDP, |
50 | caddr: &iph->daddr, htons(PORT_ISAKMP), |
51 | vaddr: &iph->saddr, htons(PORT_ISAKMP), p); |
52 | } |
53 | |
54 | static struct ip_vs_conn * |
55 | ah_esp_conn_in_get(struct netns_ipvs *ipvs, int af, const struct sk_buff *skb, |
56 | const struct ip_vs_iphdr *iph) |
57 | { |
58 | struct ip_vs_conn *cp; |
59 | struct ip_vs_conn_param p; |
60 | |
61 | ah_esp_conn_fill_param_proto(ipvs, af, iph, p: &p); |
62 | cp = ip_vs_conn_in_get(p: &p); |
63 | if (!cp) { |
64 | /* |
65 | * We are not sure if the packet is from our |
66 | * service, so our conn_schedule hook should return NF_ACCEPT |
67 | */ |
68 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet " |
69 | "%s%s %s->%s\n" , |
70 | ip_vs_iph_icmp(iph) ? "ICMP+" : "" , |
71 | ip_vs_proto_get(iph->protocol)->name, |
72 | IP_VS_DBG_ADDR(af, &iph->saddr), |
73 | IP_VS_DBG_ADDR(af, &iph->daddr)); |
74 | } |
75 | |
76 | return cp; |
77 | } |
78 | |
79 | |
80 | static struct ip_vs_conn * |
81 | ah_esp_conn_out_get(struct netns_ipvs *ipvs, int af, const struct sk_buff *skb, |
82 | const struct ip_vs_iphdr *iph) |
83 | { |
84 | struct ip_vs_conn *cp; |
85 | struct ip_vs_conn_param p; |
86 | |
87 | ah_esp_conn_fill_param_proto(ipvs, af, iph, p: &p); |
88 | cp = ip_vs_conn_out_get(p: &p); |
89 | if (!cp) { |
90 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet " |
91 | "%s%s %s->%s\n" , |
92 | ip_vs_iph_icmp(iph) ? "ICMP+" : "" , |
93 | ip_vs_proto_get(iph->protocol)->name, |
94 | IP_VS_DBG_ADDR(af, &iph->saddr), |
95 | IP_VS_DBG_ADDR(af, &iph->daddr)); |
96 | } |
97 | |
98 | return cp; |
99 | } |
100 | |
101 | |
102 | static int |
103 | ah_esp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, |
104 | struct ip_vs_proto_data *pd, |
105 | int *verdict, struct ip_vs_conn **cpp, |
106 | struct ip_vs_iphdr *iph) |
107 | { |
108 | /* |
109 | * AH/ESP is only related traffic. Pass the packet to IP stack. |
110 | */ |
111 | *verdict = NF_ACCEPT; |
112 | return 0; |
113 | } |
114 | |
115 | #ifdef CONFIG_IP_VS_PROTO_AH |
116 | struct ip_vs_protocol ip_vs_protocol_ah = { |
117 | .name = "AH" , |
118 | .protocol = IPPROTO_AH, |
119 | .num_states = 1, |
120 | .dont_defrag = 1, |
121 | .init = NULL, |
122 | .exit = NULL, |
123 | .conn_schedule = ah_esp_conn_schedule, |
124 | .conn_in_get = ah_esp_conn_in_get, |
125 | .conn_out_get = ah_esp_conn_out_get, |
126 | .snat_handler = NULL, |
127 | .dnat_handler = NULL, |
128 | .state_transition = NULL, |
129 | .register_app = NULL, |
130 | .unregister_app = NULL, |
131 | .app_conn_bind = NULL, |
132 | .debug_packet = ip_vs_tcpudp_debug_packet, |
133 | .timeout_change = NULL, /* ISAKMP */ |
134 | }; |
135 | #endif |
136 | |
137 | #ifdef CONFIG_IP_VS_PROTO_ESP |
138 | struct ip_vs_protocol ip_vs_protocol_esp = { |
139 | .name = "ESP" , |
140 | .protocol = IPPROTO_ESP, |
141 | .num_states = 1, |
142 | .dont_defrag = 1, |
143 | .init = NULL, |
144 | .exit = NULL, |
145 | .conn_schedule = ah_esp_conn_schedule, |
146 | .conn_in_get = ah_esp_conn_in_get, |
147 | .conn_out_get = ah_esp_conn_out_get, |
148 | .snat_handler = NULL, |
149 | .dnat_handler = NULL, |
150 | .state_transition = NULL, |
151 | .register_app = NULL, |
152 | .unregister_app = NULL, |
153 | .app_conn_bind = NULL, |
154 | .debug_packet = ip_vs_tcpudp_debug_packet, |
155 | .timeout_change = NULL, /* ISAKMP */ |
156 | }; |
157 | #endif |
158 | |