]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
409a1966 | 2 | * ip_vs_proto_ah_esp.c: AH/ESP IPSec load balancing support for IPVS |
1da177e4 | 3 | * |
1da177e4 LT |
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 | ||
14c85021 ACM |
13 | #include <linux/in.h> |
14 | #include <linux/ip.h> | |
1da177e4 LT |
15 | #include <linux/module.h> |
16 | #include <linux/kernel.h> | |
17 | #include <linux/netfilter.h> | |
18 | #include <linux/netfilter_ipv4.h> | |
19 | ||
20 | #include <net/ip_vs.h> | |
21 | ||
22 | ||
23 | /* TODO: | |
24 | ||
25 | struct isakmp_hdr { | |
26 | __u8 icookie[8]; | |
27 | __u8 rcookie[8]; | |
28 | __u8 np; | |
29 | __u8 version; | |
30 | __u8 xchgtype; | |
31 | __u8 flags; | |
32 | __u32 msgid; | |
33 | __u32 length; | |
34 | }; | |
35 | ||
36 | */ | |
37 | ||
38 | #define PORT_ISAKMP 500 | |
39 | ||
40 | ||
41 | static struct ip_vs_conn * | |
51ef348b JV |
42 | ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, |
43 | const struct ip_vs_iphdr *iph, unsigned int proto_off, | |
409a1966 | 44 | int inverse) |
1da177e4 LT |
45 | { |
46 | struct ip_vs_conn *cp; | |
47 | ||
48 | if (likely(!inverse)) { | |
28364a59 JV |
49 | cp = ip_vs_conn_in_get(af, IPPROTO_UDP, |
50 | &iph->saddr, | |
4412ec49 | 51 | htons(PORT_ISAKMP), |
28364a59 | 52 | &iph->daddr, |
4412ec49 | 53 | htons(PORT_ISAKMP)); |
1da177e4 | 54 | } else { |
28364a59 JV |
55 | cp = ip_vs_conn_in_get(af, IPPROTO_UDP, |
56 | &iph->daddr, | |
4412ec49 | 57 | htons(PORT_ISAKMP), |
28364a59 | 58 | &iph->saddr, |
4412ec49 | 59 | htons(PORT_ISAKMP)); |
1da177e4 LT |
60 | } |
61 | ||
62 | if (!cp) { | |
63 | /* | |
64 | * We are not sure if the packet is from our | |
65 | * service, so our conn_schedule hook should return NF_ACCEPT | |
66 | */ | |
51ef348b JV |
67 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet " |
68 | "%s%s %s->%s\n", | |
69 | inverse ? "ICMP+" : "", | |
70 | pp->name, | |
71 | IP_VS_DBG_ADDR(af, &iph->saddr), | |
72 | IP_VS_DBG_ADDR(af, &iph->daddr)); | |
1da177e4 LT |
73 | } |
74 | ||
75 | return cp; | |
76 | } | |
77 | ||
78 | ||
79 | static struct ip_vs_conn * | |
51ef348b JV |
80 | ah_esp_conn_out_get(int af, const struct sk_buff *skb, |
81 | struct ip_vs_protocol *pp, | |
82 | const struct ip_vs_iphdr *iph, | |
83 | unsigned int proto_off, | |
84 | int inverse) | |
1da177e4 LT |
85 | { |
86 | struct ip_vs_conn *cp; | |
87 | ||
88 | if (likely(!inverse)) { | |
28364a59 JV |
89 | cp = ip_vs_conn_out_get(af, IPPROTO_UDP, |
90 | &iph->saddr, | |
4412ec49 | 91 | htons(PORT_ISAKMP), |
28364a59 | 92 | &iph->daddr, |
4412ec49 | 93 | htons(PORT_ISAKMP)); |
1da177e4 | 94 | } else { |
28364a59 JV |
95 | cp = ip_vs_conn_out_get(af, IPPROTO_UDP, |
96 | &iph->daddr, | |
4412ec49 | 97 | htons(PORT_ISAKMP), |
28364a59 | 98 | &iph->saddr, |
4412ec49 | 99 | htons(PORT_ISAKMP)); |
1da177e4 LT |
100 | } |
101 | ||
102 | if (!cp) { | |
51ef348b JV |
103 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet " |
104 | "%s%s %s->%s\n", | |
105 | inverse ? "ICMP+" : "", | |
106 | pp->name, | |
107 | IP_VS_DBG_ADDR(af, &iph->saddr), | |
108 | IP_VS_DBG_ADDR(af, &iph->daddr)); | |
1da177e4 LT |
109 | } |
110 | ||
111 | return cp; | |
112 | } | |
113 | ||
114 | ||
115 | static int | |
51ef348b | 116 | ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, |
409a1966 | 117 | int *verdict, struct ip_vs_conn **cpp) |
1da177e4 LT |
118 | { |
119 | /* | |
409a1966 | 120 | * AH/ESP is only related traffic. Pass the packet to IP stack. |
1da177e4 LT |
121 | */ |
122 | *verdict = NF_ACCEPT; | |
123 | return 0; | |
124 | } | |
125 | ||
126 | ||
127 | static void | |
3b047d9d JV |
128 | ah_esp_debug_packet_v4(struct ip_vs_protocol *pp, const struct sk_buff *skb, |
129 | int offset, const char *msg) | |
1da177e4 LT |
130 | { |
131 | char buf[256]; | |
132 | struct iphdr _iph, *ih; | |
133 | ||
134 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); | |
135 | if (ih == NULL) | |
136 | sprintf(buf, "%s TRUNCATED", pp->name); | |
137 | else | |
138 | sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u", | |
139 | pp->name, NIPQUAD(ih->saddr), | |
140 | NIPQUAD(ih->daddr)); | |
141 | ||
142 | printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf); | |
143 | } | |
144 | ||
3b047d9d JV |
145 | #ifdef CONFIG_IP_VS_IPV6 |
146 | static void | |
147 | ah_esp_debug_packet_v6(struct ip_vs_protocol *pp, const struct sk_buff *skb, | |
148 | int offset, const char *msg) | |
149 | { | |
150 | char buf[256]; | |
151 | struct ipv6hdr _iph, *ih; | |
152 | ||
153 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); | |
154 | if (ih == NULL) | |
155 | sprintf(buf, "%s TRUNCATED", pp->name); | |
156 | else | |
5b095d98 | 157 | sprintf(buf, "%s %pI6->%pI6", |
38ff4fa4 | 158 | pp->name, &ih->saddr, &ih->daddr); |
3b047d9d JV |
159 | |
160 | printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf); | |
161 | } | |
162 | #endif | |
163 | ||
164 | static void | |
165 | ah_esp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb, | |
166 | int offset, const char *msg) | |
167 | { | |
168 | #ifdef CONFIG_IP_VS_IPV6 | |
d286600e | 169 | if (skb->protocol == htons(ETH_P_IPV6)) |
3b047d9d JV |
170 | ah_esp_debug_packet_v6(pp, skb, offset, msg); |
171 | else | |
172 | #endif | |
173 | ah_esp_debug_packet_v4(pp, skb, offset, msg); | |
174 | } | |
175 | ||
1da177e4 | 176 | |
409a1966 | 177 | static void ah_esp_init(struct ip_vs_protocol *pp) |
1da177e4 LT |
178 | { |
179 | /* nothing to do now */ | |
180 | } | |
181 | ||
182 | ||
409a1966 | 183 | static void ah_esp_exit(struct ip_vs_protocol *pp) |
1da177e4 LT |
184 | { |
185 | /* nothing to do now */ | |
186 | } | |
187 | ||
188 | ||
409a1966 | 189 | #ifdef CONFIG_IP_VS_PROTO_AH |
1da177e4 LT |
190 | struct ip_vs_protocol ip_vs_protocol_ah = { |
191 | .name = "AH", | |
192 | .protocol = IPPROTO_AH, | |
2ad17def | 193 | .num_states = 1, |
1da177e4 | 194 | .dont_defrag = 1, |
409a1966 JV |
195 | .init = ah_esp_init, |
196 | .exit = ah_esp_exit, | |
197 | .conn_schedule = ah_esp_conn_schedule, | |
198 | .conn_in_get = ah_esp_conn_in_get, | |
199 | .conn_out_get = ah_esp_conn_out_get, | |
1da177e4 LT |
200 | .snat_handler = NULL, |
201 | .dnat_handler = NULL, | |
202 | .csum_check = NULL, | |
203 | .state_transition = NULL, | |
204 | .register_app = NULL, | |
205 | .unregister_app = NULL, | |
206 | .app_conn_bind = NULL, | |
409a1966 | 207 | .debug_packet = ah_esp_debug_packet, |
1da177e4 LT |
208 | .timeout_change = NULL, /* ISAKMP */ |
209 | .set_state_timeout = NULL, | |
210 | }; | |
409a1966 JV |
211 | #endif |
212 | ||
213 | #ifdef CONFIG_IP_VS_PROTO_ESP | |
214 | struct ip_vs_protocol ip_vs_protocol_esp = { | |
215 | .name = "ESP", | |
216 | .protocol = IPPROTO_ESP, | |
217 | .num_states = 1, | |
218 | .dont_defrag = 1, | |
219 | .init = ah_esp_init, | |
220 | .exit = ah_esp_exit, | |
221 | .conn_schedule = ah_esp_conn_schedule, | |
222 | .conn_in_get = ah_esp_conn_in_get, | |
223 | .conn_out_get = ah_esp_conn_out_get, | |
224 | .snat_handler = NULL, | |
225 | .dnat_handler = NULL, | |
226 | .csum_check = NULL, | |
227 | .state_transition = NULL, | |
228 | .register_app = NULL, | |
229 | .unregister_app = NULL, | |
230 | .app_conn_bind = NULL, | |
231 | .debug_packet = ah_esp_debug_packet, | |
232 | .timeout_change = NULL, /* ISAKMP */ | |
233 | }; | |
234 | #endif |