Blame view
net/netfilter/ipvs/ip_vs_core.c
56.9 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 |
/* * IPVS An implementation of the IP virtual server support for the * LINUX operating system. IPVS is now implemented as a module * over the Netfilter framework. IPVS can be used to build a * high-performance and highly available server based on a * cluster of servers. * |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
* Authors: Wensong Zhang <wensong@linuxvirtualserver.org> * Peter Kese <peter.kese@ijs.si> * Julian Anastasov <ja@ssi.bg> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * The IPVS code for kernel 2.2 was done by Wensong Zhang and Peter Kese, * with changes/fixes from Julian Anastasov, Lars Marowsky-Bree, Horms * and others. * * Changes: * Paul `Rusty' Russell properly handle non-linear skbs |
6869c4d8e [NETFILTER]: redu... |
23 |
* Harald Welte don't use nfcache |
1da177e4c Linux-2.6.12-rc2 |
24 25 |
* */ |
9aada7ac0 IPVS: use pr_fmt |
26 27 |
#define KMSG_COMPONENT "IPVS" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
1da177e4c Linux-2.6.12-rc2 |
28 29 30 31 |
#include <linux/module.h> #include <linux/kernel.h> #include <linux/ip.h> #include <linux/tcp.h> |
2906f66a5 ipvs: SCTP Traspo... |
32 |
#include <linux/sctp.h> |
1da177e4c Linux-2.6.12-rc2 |
33 |
#include <linux/icmp.h> |
5a0e3ad6a include cleanup: ... |
34 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
35 36 37 38 39 40 |
#include <net/ip.h> #include <net/tcp.h> #include <net/udp.h> #include <net/icmp.h> /* for icmp_send */ #include <net/route.h> |
2c70b5196 IPVS: include net... |
41 |
#include <net/ip6_checksum.h> |
61b1ab458 IPVS: netns, add ... |
42 |
#include <net/netns/generic.h> /* net_generic() */ |
1da177e4c Linux-2.6.12-rc2 |
43 44 45 |
#include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> |
2a3b791e6 IPVS: Add/adjust ... |
46 47 48 |
#ifdef CONFIG_IP_VS_IPV6 #include <net/ipv6.h> #include <linux/netfilter_ipv6.h> |
489fdedae ipvs: stop ICMP f... |
49 |
#include <net/ip6_route.h> |
2a3b791e6 IPVS: Add/adjust ... |
50 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
51 52 53 54 55 |
#include <net/ip_vs.h> EXPORT_SYMBOL(register_ip_vs_scheduler); EXPORT_SYMBOL(unregister_ip_vs_scheduler); |
1da177e4c Linux-2.6.12-rc2 |
56 57 58 59 60 61 62 63 64 65 66 |
EXPORT_SYMBOL(ip_vs_proto_name); EXPORT_SYMBOL(ip_vs_conn_new); EXPORT_SYMBOL(ip_vs_conn_in_get); EXPORT_SYMBOL(ip_vs_conn_out_get); #ifdef CONFIG_IP_VS_PROTO_TCP EXPORT_SYMBOL(ip_vs_tcp_conn_listen); #endif EXPORT_SYMBOL(ip_vs_conn_put); #ifdef CONFIG_IP_VS_DEBUG EXPORT_SYMBOL(ip_vs_get_debug_level); #endif |
1da177e4c Linux-2.6.12-rc2 |
67 |
|
b962abdc6 ipvs: fix some sp... |
68 |
static int ip_vs_net_id __read_mostly; |
61b1ab458 IPVS: netns, add ... |
69 70 |
/* netns cnt used for uniqueness */ static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0); |
1da177e4c Linux-2.6.12-rc2 |
71 72 73 |
/* ID used in ICMP lookups */ #define icmp_id(icmph) (((icmph)->un).echo.id) |
2a3b791e6 IPVS: Add/adjust ... |
74 |
#define icmpv6_id(icmph) (icmph->icmp6_dataun.u_echo.identifier) |
1da177e4c Linux-2.6.12-rc2 |
75 |
|
95c961747 net: cleanup unsi... |
76 |
const char *ip_vs_proto_name(unsigned int proto) |
1da177e4c Linux-2.6.12-rc2 |
77 78 79 80 81 82 83 84 85 86 |
{ static char buf[20]; switch (proto) { case IPPROTO_IP: return "IP"; case IPPROTO_UDP: return "UDP"; case IPPROTO_TCP: return "TCP"; |
2906f66a5 ipvs: SCTP Traspo... |
87 88 |
case IPPROTO_SCTP: return "SCTP"; |
1da177e4c Linux-2.6.12-rc2 |
89 90 |
case IPPROTO_ICMP: return "ICMP"; |
2a3b791e6 IPVS: Add/adjust ... |
91 92 93 94 |
#ifdef CONFIG_IP_VS_IPV6 case IPPROTO_ICMPV6: return "ICMPv6"; #endif |
1da177e4c Linux-2.6.12-rc2 |
95 |
default: |
1404c3ab9 netfilter: Fix fo... |
96 |
sprintf(buf, "IP_%u", proto); |
1da177e4c Linux-2.6.12-rc2 |
97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
return buf; } } void ip_vs_init_hash_table(struct list_head *table, int rows) { while (--rows >= 0) INIT_LIST_HEAD(&table[rows]); } static inline void ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb) { struct ip_vs_dest *dest = cp->dest; |
7c08d78e6 ipvs: Better deri... |
111 |
struct netns_ipvs *ipvs = cp->ipvs; |
b17fc9963 IPVS: netns, ip_v... |
112 |
|
1da177e4c Linux-2.6.12-rc2 |
113 |
if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) { |
b17fc9963 IPVS: netns, ip_v... |
114 |
struct ip_vs_cpu_stats *s; |
bcbde4c0a ipvs: make the se... |
115 |
struct ip_vs_service *svc; |
b17fc9963 IPVS: netns, ip_v... |
116 117 |
s = this_cpu_ptr(dest->stats.cpustats); |
b17fc9963 IPVS: netns, ip_v... |
118 |
u64_stats_update_begin(&s->syncp); |
cd67cd5eb ipvs: use 64-bit ... |
119 120 |
s->cnt.inpkts++; s->cnt.inbytes += skb->len; |
b17fc9963 IPVS: netns, ip_v... |
121 |
u64_stats_update_end(&s->syncp); |
bcbde4c0a ipvs: make the se... |
122 123 124 |
rcu_read_lock(); svc = rcu_dereference(dest->svc); s = this_cpu_ptr(svc->stats.cpustats); |
b17fc9963 IPVS: netns, ip_v... |
125 |
u64_stats_update_begin(&s->syncp); |
cd67cd5eb ipvs: use 64-bit ... |
126 127 |
s->cnt.inpkts++; s->cnt.inbytes += skb->len; |
b17fc9963 IPVS: netns, ip_v... |
128 |
u64_stats_update_end(&s->syncp); |
bcbde4c0a ipvs: make the se... |
129 |
rcu_read_unlock(); |
b17fc9963 IPVS: netns, ip_v... |
130 |
|
2a0751af0 ipvs: reorganize ... |
131 |
s = this_cpu_ptr(ipvs->tot_stats.cpustats); |
b17fc9963 IPVS: netns, ip_v... |
132 |
u64_stats_update_begin(&s->syncp); |
cd67cd5eb ipvs: use 64-bit ... |
133 134 |
s->cnt.inpkts++; s->cnt.inbytes += skb->len; |
b17fc9963 IPVS: netns, ip_v... |
135 |
u64_stats_update_end(&s->syncp); |
1da177e4c Linux-2.6.12-rc2 |
136 137 138 139 140 141 142 143 |
} } static inline void ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb) { struct ip_vs_dest *dest = cp->dest; |
7c08d78e6 ipvs: Better deri... |
144 |
struct netns_ipvs *ipvs = cp->ipvs; |
b17fc9963 IPVS: netns, ip_v... |
145 |
|
1da177e4c Linux-2.6.12-rc2 |
146 |
if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) { |
b17fc9963 IPVS: netns, ip_v... |
147 |
struct ip_vs_cpu_stats *s; |
bcbde4c0a ipvs: make the se... |
148 |
struct ip_vs_service *svc; |
b17fc9963 IPVS: netns, ip_v... |
149 150 |
s = this_cpu_ptr(dest->stats.cpustats); |
b17fc9963 IPVS: netns, ip_v... |
151 |
u64_stats_update_begin(&s->syncp); |
cd67cd5eb ipvs: use 64-bit ... |
152 153 |
s->cnt.outpkts++; s->cnt.outbytes += skb->len; |
b17fc9963 IPVS: netns, ip_v... |
154 |
u64_stats_update_end(&s->syncp); |
bcbde4c0a ipvs: make the se... |
155 156 157 |
rcu_read_lock(); svc = rcu_dereference(dest->svc); s = this_cpu_ptr(svc->stats.cpustats); |
b17fc9963 IPVS: netns, ip_v... |
158 |
u64_stats_update_begin(&s->syncp); |
cd67cd5eb ipvs: use 64-bit ... |
159 160 |
s->cnt.outpkts++; s->cnt.outbytes += skb->len; |
b17fc9963 IPVS: netns, ip_v... |
161 |
u64_stats_update_end(&s->syncp); |
bcbde4c0a ipvs: make the se... |
162 |
rcu_read_unlock(); |
b17fc9963 IPVS: netns, ip_v... |
163 |
|
2a0751af0 ipvs: reorganize ... |
164 |
s = this_cpu_ptr(ipvs->tot_stats.cpustats); |
b17fc9963 IPVS: netns, ip_v... |
165 |
u64_stats_update_begin(&s->syncp); |
cd67cd5eb ipvs: use 64-bit ... |
166 167 |
s->cnt.outpkts++; s->cnt.outbytes += skb->len; |
b17fc9963 IPVS: netns, ip_v... |
168 |
u64_stats_update_end(&s->syncp); |
1da177e4c Linux-2.6.12-rc2 |
169 170 171 172 173 174 175 |
} } static inline void ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc) { |
3109d2f2d ipvs: Store ipvs ... |
176 |
struct netns_ipvs *ipvs = svc->ipvs; |
b17fc9963 IPVS: netns, ip_v... |
177 |
struct ip_vs_cpu_stats *s; |
1da177e4c Linux-2.6.12-rc2 |
178 |
|
b17fc9963 IPVS: netns, ip_v... |
179 |
s = this_cpu_ptr(cp->dest->stats.cpustats); |
cd67cd5eb ipvs: use 64-bit ... |
180 181 182 |
u64_stats_update_begin(&s->syncp); s->cnt.conns++; u64_stats_update_end(&s->syncp); |
1da177e4c Linux-2.6.12-rc2 |
183 |
|
b17fc9963 IPVS: netns, ip_v... |
184 |
s = this_cpu_ptr(svc->stats.cpustats); |
cd67cd5eb ipvs: use 64-bit ... |
185 186 187 |
u64_stats_update_begin(&s->syncp); s->cnt.conns++; u64_stats_update_end(&s->syncp); |
b17fc9963 IPVS: netns, ip_v... |
188 |
|
2a0751af0 ipvs: reorganize ... |
189 |
s = this_cpu_ptr(ipvs->tot_stats.cpustats); |
cd67cd5eb ipvs: use 64-bit ... |
190 191 192 |
u64_stats_update_begin(&s->syncp); s->cnt.conns++; u64_stats_update_end(&s->syncp); |
1da177e4c Linux-2.6.12-rc2 |
193 |
} |
4a516f110 ipvs: Remove unus... |
194 |
static inline void |
1da177e4c Linux-2.6.12-rc2 |
195 196 |
ip_vs_set_state(struct ip_vs_conn *cp, int direction, const struct sk_buff *skb, |
9330419d9 IPVS: netns, use ... |
197 |
struct ip_vs_proto_data *pd) |
1da177e4c Linux-2.6.12-rc2 |
198 |
{ |
4a516f110 ipvs: Remove unus... |
199 200 |
if (likely(pd->pp->state_transition)) pd->pp->state_transition(cp, direction, skb, pd); |
1da177e4c Linux-2.6.12-rc2 |
201 |
} |
a5959d53d IPVS: Handle Sche... |
202 |
static inline int |
85999283a IPVS: Add struct ... |
203 204 205 206 207 208 |
ip_vs_conn_fill_param_persist(const struct ip_vs_service *svc, struct sk_buff *skb, int protocol, const union nf_inet_addr *caddr, __be16 cport, const union nf_inet_addr *vaddr, __be16 vport, struct ip_vs_conn_param *p) { |
3109d2f2d ipvs: Store ipvs ... |
209 |
ip_vs_conn_fill_param(svc->ipvs, svc->af, protocol, caddr, cport, vaddr, |
6e67e586e IPVS: netns, conn... |
210 |
vport, p); |
ceec4c381 ipvs: convert ser... |
211 |
p->pe = rcu_dereference(svc->pe); |
85999283a IPVS: Add struct ... |
212 |
if (p->pe && p->pe->fill_param) |
a5959d53d IPVS: Handle Sche... |
213 214 215 |
return p->pe->fill_param(p, skb); return 0; |
85999283a IPVS: Add struct ... |
216 |
} |
1da177e4c Linux-2.6.12-rc2 |
217 |
|
1da177e4c Linux-2.6.12-rc2 |
218 219 220 221 222 223 224 225 226 |
/* * IPVS persistent scheduling function * It creates a connection entry according to its template if exists, * or selects a server and creates a connection entry plus a template. * Locking: we are svc user (svc->refcnt), so we hold all dests too * Protocols supported: TCP, UDP */ static struct ip_vs_conn * ip_vs_sched_persist(struct ip_vs_service *svc, |
d4383f04d ipvs: API change ... |
227 228 |
struct sk_buff *skb, __be16 src_port, __be16 dst_port, int *ignored, struct ip_vs_iphdr *iph) |
1da177e4c Linux-2.6.12-rc2 |
229 230 |
{ struct ip_vs_conn *cp = NULL; |
1da177e4c Linux-2.6.12-rc2 |
231 232 |
struct ip_vs_dest *dest; struct ip_vs_conn *ct; |
5b57a98c1 IPVS: compact ip_... |
233 |
__be16 dport = 0; /* destination port to forward */ |
3575792e0 ipvs: extend conn... |
234 |
unsigned int flags; |
f11017ec2 IPVS: Add struct ... |
235 |
struct ip_vs_conn_param param; |
e0aac52e1 ipvs: fix matchin... |
236 |
const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) }; |
28364a59f IPVS: Extend func... |
237 238 |
union nf_inet_addr snet; /* source network of the client, after masking */ |
ee78378f9 ipvs: Make ip_vs_... |
239 240 241 242 243 244 245 246 247 |
const union nf_inet_addr *src_addr, *dst_addr; if (likely(!ip_vs_iph_inverse(iph))) { src_addr = &iph->saddr; dst_addr = &iph->daddr; } else { src_addr = &iph->daddr; dst_addr = &iph->saddr; } |
cd17f9ed0 IPVS: Extend sche... |
248 |
|
1da177e4c Linux-2.6.12-rc2 |
249 |
/* Mask saddr with the netmask to adjust template granularity */ |
cd17f9ed0 IPVS: Extend sche... |
250 251 |
#ifdef CONFIG_IP_VS_IPV6 if (svc->af == AF_INET6) |
ee78378f9 ipvs: Make ip_vs_... |
252 |
ipv6_addr_prefix(&snet.in6, &src_addr->in6, |
0a925864c ipvs: fix sparse ... |
253 |
(__force __u32) svc->netmask); |
cd17f9ed0 IPVS: Extend sche... |
254 255 |
else #endif |
ee78378f9 ipvs: Make ip_vs_... |
256 |
snet.ip = src_addr->ip & svc->netmask; |
1da177e4c Linux-2.6.12-rc2 |
257 |
|
cd17f9ed0 IPVS: Extend sche... |
258 259 260 |
IP_VS_DBG_BUF(6, "p-schedule: src %s:%u dest %s:%u " "mnet %s ", |
ee78378f9 ipvs: Make ip_vs_... |
261 262 |
IP_VS_DBG_ADDR(svc->af, src_addr), ntohs(src_port), IP_VS_DBG_ADDR(svc->af, dst_addr), ntohs(dst_port), |
cd17f9ed0 IPVS: Extend sche... |
263 |
IP_VS_DBG_ADDR(svc->af, &snet)); |
1da177e4c Linux-2.6.12-rc2 |
264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
/* * As far as we know, FTP is a very complicated network protocol, and * it uses control connection and data connections. For active FTP, * FTP server initialize data connection to the client, its source port * is often 20. For passive FTP, FTP server tells the clients the port * that it passively listens to, and the client issues the data * connection. In the tunneling or direct routing mode, the load * balancer is on the client-to-server half of connection, the port * number is unknown to the load balancer. So, a conn template like * <caddr, 0, vaddr, 0, daddr, 0> is created for persistent FTP * service, and a template like <caddr, 0, vaddr, vport, daddr, dport> * is created for other persistent services. */ |
5b57a98c1 IPVS: compact ip_... |
278 |
{ |
d4383f04d ipvs: API change ... |
279 |
int protocol = iph->protocol; |
ee78378f9 ipvs: Make ip_vs_... |
280 |
const union nf_inet_addr *vaddr = dst_addr; |
f11017ec2 IPVS: Add struct ... |
281 |
__be16 vport = 0; |
ce144f249 IPVS: Split ports... |
282 |
if (dst_port == svc->port) { |
5b57a98c1 IPVS: compact ip_... |
283 284 285 286 |
/* non-FTP template: * <protocol, caddr, 0, vaddr, vport, daddr, dport> * FTP template: * <protocol, caddr, 0, vaddr, 0, daddr, 0> |
1da177e4c Linux-2.6.12-rc2 |
287 288 |
*/ if (svc->port != FTPPORT) |
ce144f249 IPVS: Split ports... |
289 |
vport = dst_port; |
1da177e4c Linux-2.6.12-rc2 |
290 |
} else { |
5b57a98c1 IPVS: compact ip_... |
291 292 293 294 295 296 |
/* Note: persistent fwmark-based services and * persistent port zero service are handled here. * fwmark template: * <IPPROTO_IP,caddr,0,fwmark,0,daddr,0> * port zero template: * <protocol,caddr,0,vaddr,0,daddr,0> |
1da177e4c Linux-2.6.12-rc2 |
297 |
*/ |
28364a59f IPVS: Extend func... |
298 |
if (svc->fwmark) { |
5b57a98c1 IPVS: compact ip_... |
299 300 301 |
protocol = IPPROTO_IP; vaddr = &fwmark; } |
1da177e4c Linux-2.6.12-rc2 |
302 |
} |
a5959d53d IPVS: Handle Sche... |
303 304 305 306 307 308 |
/* return *ignored = -1 so NF_DROP can be used */ if (ip_vs_conn_fill_param_persist(svc, skb, protocol, &snet, 0, vaddr, vport, ¶m) < 0) { *ignored = -1; return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
309 |
} |
5b57a98c1 IPVS: compact ip_... |
310 |
/* Check if a template already exists */ |
f11017ec2 IPVS: Add struct ... |
311 |
ct = ip_vs_ct_in_get(¶m); |
5b57a98c1 IPVS: compact ip_... |
312 |
if (!ct || !ip_vs_check_template(ct)) { |
ceec4c381 ipvs: convert ser... |
313 |
struct ip_vs_scheduler *sched; |
a5959d53d IPVS: Handle Sche... |
314 315 |
/* * No template found or the dest of the connection |
5b57a98c1 IPVS: compact ip_... |
316 |
* template is not available. |
a5959d53d IPVS: Handle Sche... |
317 |
* return *ignored=0 i.e. ICMP and NF_DROP |
5b57a98c1 IPVS: compact ip_... |
318 |
*/ |
ceec4c381 ipvs: convert ser... |
319 |
sched = rcu_dereference(svc->scheduler); |
05f00505a ipvs: fix crash i... |
320 321 322 323 324 325 326 |
if (sched) { /* read svc->sched_data after svc->scheduler */ smp_rmb(); dest = sched->schedule(svc, skb, iph); } else { dest = NULL; } |
5b57a98c1 IPVS: compact ip_... |
327 328 329 |
if (!dest) { IP_VS_DBG(1, "p-schedule: no dest found. "); |
85999283a IPVS: Add struct ... |
330 |
kfree(param.pe_data); |
a5959d53d IPVS: Handle Sche... |
331 |
*ignored = 0; |
5b57a98c1 IPVS: compact ip_... |
332 333 |
return NULL; } |
ce144f249 IPVS: Split ports... |
334 |
if (dst_port == svc->port && svc->port != FTPPORT) |
5b57a98c1 IPVS: compact ip_... |
335 |
dport = dest->port; |
85999283a IPVS: Add struct ... |
336 337 338 339 |
/* Create a template * This adds param.pe_data to the template, * and thus param.pe_data will be destroyed * when the template expires */ |
ba38528aa ipvs: Supply dest... |
340 |
ct = ip_vs_conn_new(¶m, dest->af, &dest->addr, dport, |
0e051e683 IPVS: Backup, Pre... |
341 |
IP_VS_CONN_F_TEMPLATE, dest, skb->mark); |
85999283a IPVS: Add struct ... |
342 343 |
if (ct == NULL) { kfree(param.pe_data); |
a5959d53d IPVS: Handle Sche... |
344 |
*ignored = -1; |
5b57a98c1 IPVS: compact ip_... |
345 |
return NULL; |
85999283a IPVS: Add struct ... |
346 |
} |
5b57a98c1 IPVS: compact ip_... |
347 348 |
ct->timeout = svc->timeout; |
85999283a IPVS: Add struct ... |
349 |
} else { |
5b57a98c1 IPVS: compact ip_... |
350 351 |
/* set destination with the found template */ dest = ct->dest; |
85999283a IPVS: Add struct ... |
352 353 |
kfree(param.pe_data); } |
5b57a98c1 IPVS: compact ip_... |
354 |
|
ce144f249 IPVS: Split ports... |
355 |
dport = dst_port; |
5b57a98c1 IPVS: compact ip_... |
356 357 |
if (dport == svc->port && dest->port) dport = dest->port; |
26ec037f9 IPVS: one-packet ... |
358 |
flags = (svc->flags & IP_VS_SVC_F_ONEPACKET |
d4383f04d ipvs: API change ... |
359 |
&& iph->protocol == IPPROTO_UDP) ? |
26ec037f9 IPVS: one-packet ... |
360 |
IP_VS_CONN_F_ONE_PACKET : 0; |
1da177e4c Linux-2.6.12-rc2 |
361 362 363 |
/* * Create a new connection according to the template */ |
3109d2f2d ipvs: Store ipvs ... |
364 |
ip_vs_conn_fill_param(svc->ipvs, svc->af, iph->protocol, src_addr, |
ee78378f9 ipvs: Make ip_vs_... |
365 |
src_port, dst_addr, dst_port, ¶m); |
ce144f249 IPVS: Split ports... |
366 |
|
ba38528aa ipvs: Supply dest... |
367 368 |
cp = ip_vs_conn_new(¶m, dest->af, &dest->addr, dport, flags, dest, skb->mark); |
1da177e4c Linux-2.6.12-rc2 |
369 370 |
if (cp == NULL) { ip_vs_conn_put(ct); |
a5959d53d IPVS: Handle Sche... |
371 |
*ignored = -1; |
1da177e4c Linux-2.6.12-rc2 |
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
return NULL; } /* * Add its control */ ip_vs_control_add(cp, ct); ip_vs_conn_put(ct); ip_vs_conn_stats(cp, svc); return cp; } /* * IPVS main scheduling function * It selects a server according to the virtual service, and * creates a connection entry. * Protocols supported: TCP, UDP |
a5959d53d IPVS: Handle Sche... |
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 |
* * Usage of *ignored * * 1 : protocol tried to schedule (eg. on SYN), found svc but the * svc/scheduler decides that this packet should be accepted with * NF_ACCEPT because it must not be scheduled. * * 0 : scheduler can not find destination, so try bypass or * return ICMP and then NF_DROP (ip_vs_leave). * * -1 : scheduler tried to schedule but fatal error occurred, eg. * ip_vs_conn_new failure (ENOMEM) or ip_vs_sip_fill_param * failure such as missing Call-ID, ENOMEM on skb_linearize * or pe_data. In this case we should return NF_DROP without * any attempts to send ICMP with ip_vs_leave. |
1da177e4c Linux-2.6.12-rc2 |
406 407 |
*/ struct ip_vs_conn * |
190ecd27c ipvs: do not sche... |
408 |
ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, |
d4383f04d ipvs: API change ... |
409 410 |
struct ip_vs_proto_data *pd, int *ignored, struct ip_vs_iphdr *iph) |
1da177e4c Linux-2.6.12-rc2 |
411 |
{ |
9330419d9 IPVS: netns, use ... |
412 |
struct ip_vs_protocol *pp = pd->pp; |
1da177e4c Linux-2.6.12-rc2 |
413 |
struct ip_vs_conn *cp = NULL; |
ceec4c381 ipvs: convert ser... |
414 |
struct ip_vs_scheduler *sched; |
1da177e4c Linux-2.6.12-rc2 |
415 |
struct ip_vs_dest *dest; |
ee78378f9 ipvs: Make ip_vs_... |
416 417 |
__be16 _ports[2], *pptr, cport, vport; const void *caddr, *vaddr; |
3575792e0 ipvs: extend conn... |
418 |
unsigned int flags; |
1da177e4c Linux-2.6.12-rc2 |
419 |
|
190ecd27c ipvs: do not sche... |
420 |
*ignored = 1; |
2f74713d1 ipvs: Complete IP... |
421 422 423 |
/* * IPv6 frags, only the first hit here. */ |
d4383f04d ipvs: API change ... |
424 |
pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph); |
1da177e4c Linux-2.6.12-rc2 |
425 426 |
if (pptr == NULL) return NULL; |
ee78378f9 ipvs: Make ip_vs_... |
427 428 429 430 431 432 433 434 435 436 437 |
if (likely(!ip_vs_iph_inverse(iph))) { cport = pptr[0]; caddr = &iph->saddr; vport = pptr[1]; vaddr = &iph->daddr; } else { cport = pptr[1]; caddr = &iph->daddr; vport = pptr[0]; vaddr = &iph->saddr; } |
1da177e4c Linux-2.6.12-rc2 |
438 |
/* |
190ecd27c ipvs: do not sche... |
439 440 441 442 443 |
* FTPDATA needs this check when using local real server. * Never schedule Active FTPDATA connections from real server. * For LVS-NAT they must be already created. For other methods * with persistence the connection is created on SYN+ACK. */ |
ee78378f9 ipvs: Make ip_vs_... |
444 |
if (cport == FTPDATA) { |
b0e010c52 ipvs: replace ip_... |
445 |
IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off, |
0d79641a9 ipvs: provide add... |
446 |
"Not scheduling FTPDATA"); |
190ecd27c ipvs: do not sche... |
447 448 449 450 |
return NULL; } /* |
a5959d53d IPVS: Handle Sche... |
451 |
* Do not schedule replies from local real server. |
190ecd27c ipvs: do not sche... |
452 |
*/ |
802c41adc ipvs: drop invers... |
453 454 |
if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK)) { iph->hdr_flags ^= IP_VS_HDR_INVERSE; |
ab1619764 ipvs: Pass ipvs i... |
455 |
cp = pp->conn_in_get(svc->ipvs, svc->af, skb, iph); |
802c41adc ipvs: drop invers... |
456 457 458 459 460 461 462 463 464 |
iph->hdr_flags ^= IP_VS_HDR_INVERSE; if (cp) { IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off, "Not scheduling reply for existing" " connection"); __ip_vs_conn_put(cp); return NULL; } |
190ecd27c ipvs: do not sche... |
465 466 467 |
} /* |
1da177e4c Linux-2.6.12-rc2 |
468 469 |
* Persistent service */ |
a5959d53d IPVS: Handle Sche... |
470 |
if (svc->flags & IP_VS_SVC_F_PERSISTENT) |
ee78378f9 ipvs: Make ip_vs_... |
471 |
return ip_vs_sched_persist(svc, skb, cport, vport, ignored, |
d4383f04d ipvs: API change ... |
472 |
iph); |
a5959d53d IPVS: Handle Sche... |
473 474 |
*ignored = 0; |
1da177e4c Linux-2.6.12-rc2 |
475 476 477 478 |
/* * Non-persistent service */ |
ee78378f9 ipvs: Make ip_vs_... |
479 |
if (!svc->fwmark && vport != svc->port) { |
1da177e4c Linux-2.6.12-rc2 |
480 |
if (!svc->port) |
1e3e238e9 IPVS: use pr_err ... |
481 482 483 484 |
pr_err("Schedule: port zero only supported " "in persistent services, " "check your ipvs configuration "); |
1da177e4c Linux-2.6.12-rc2 |
485 486 |
return NULL; } |
ceec4c381 ipvs: convert ser... |
487 |
sched = rcu_dereference(svc->scheduler); |
05f00505a ipvs: fix crash i... |
488 489 490 491 492 493 494 |
if (sched) { /* read svc->sched_data after svc->scheduler */ smp_rmb(); dest = sched->schedule(svc, skb, iph); } else { dest = NULL; } |
1da177e4c Linux-2.6.12-rc2 |
495 496 497 498 499 |
if (dest == NULL) { IP_VS_DBG(1, "Schedule: no dest found. "); return NULL; } |
26ec037f9 IPVS: one-packet ... |
500 |
flags = (svc->flags & IP_VS_SVC_F_ONEPACKET |
d4383f04d ipvs: API change ... |
501 |
&& iph->protocol == IPPROTO_UDP) ? |
26ec037f9 IPVS: one-packet ... |
502 |
IP_VS_CONN_F_ONE_PACKET : 0; |
1da177e4c Linux-2.6.12-rc2 |
503 504 505 |
/* * Create a connection entry. */ |
f11017ec2 IPVS: Add struct ... |
506 507 |
{ struct ip_vs_conn_param p; |
6e67e586e IPVS: netns, conn... |
508 |
|
3109d2f2d ipvs: Store ipvs ... |
509 |
ip_vs_conn_fill_param(svc->ipvs, svc->af, iph->protocol, |
ee78378f9 ipvs: Make ip_vs_... |
510 |
caddr, cport, vaddr, vport, &p); |
ba38528aa ipvs: Supply dest... |
511 |
cp = ip_vs_conn_new(&p, dest->af, &dest->addr, |
ee78378f9 ipvs: Make ip_vs_... |
512 |
dest->port ? dest->port : vport, |
0e051e683 IPVS: Backup, Pre... |
513 |
flags, dest, skb->mark); |
a5959d53d IPVS: Handle Sche... |
514 515 |
if (!cp) { *ignored = -1; |
f11017ec2 IPVS: Add struct ... |
516 |
return NULL; |
a5959d53d IPVS: Handle Sche... |
517 |
} |
f11017ec2 IPVS: Add struct ... |
518 |
} |
1da177e4c Linux-2.6.12-rc2 |
519 |
|
cd17f9ed0 IPVS: Extend sche... |
520 521 522 523 |
IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u " "d:%s:%u conn->flags:%X conn->refcnt:%d ", ip_vs_fwd_tag(cp), |
f18ae7206 ipvs: use the new... |
524 525 526 |
IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport), IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport), IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport), |
cd17f9ed0 IPVS: Extend sche... |
527 |
cp->flags, atomic_read(&cp->refcnt)); |
1da177e4c Linux-2.6.12-rc2 |
528 529 530 531 |
ip_vs_conn_stats(cp, svc); return cp; } |
0b7290212 ipvs: Handle inve... |
532 533 534 535 536 537 538 539 540 541 542 |
#ifdef CONFIG_SYSCTL static inline int ip_vs_addr_is_unicast(struct net *net, int af, union nf_inet_addr *addr) { #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) return ipv6_addr_type(&addr->in6) & IPV6_ADDR_UNICAST; #endif return (inet_addr_type(net, addr->ip) == RTN_UNICAST); } #endif |
1da177e4c Linux-2.6.12-rc2 |
543 544 545 546 547 548 549 |
/* * Pass or drop the packet. * Called by ip_vs_in, when the virtual service is available but * no destination is available for a new connection. */ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, |
d4383f04d ipvs: API change ... |
550 |
struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph) |
1da177e4c Linux-2.6.12-rc2 |
551 |
{ |
0b7290212 ipvs: Handle inve... |
552 |
__be16 _ports[2], *pptr, dport; |
51efbcbbb ipvs: Simplify ip... |
553 554 |
struct netns_ipvs *ipvs = svc->ipvs; struct net *net = ipvs->net; |
9330419d9 IPVS: netns, use ... |
555 |
|
d4383f04d ipvs: API change ... |
556 |
pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph); |
0b7290212 ipvs: Handle inve... |
557 |
if (!pptr) |
1da177e4c Linux-2.6.12-rc2 |
558 |
return NF_DROP; |
0b7290212 ipvs: Handle inve... |
559 |
dport = likely(!ip_vs_iph_inverse(iph)) ? pptr[1] : pptr[0]; |
a7a86b861 IPVS: Minimise ip... |
560 |
|
1da177e4c Linux-2.6.12-rc2 |
561 |
/* if it is fwmark-based service, the cache_bypass sysctl is up |
2a3b791e6 IPVS: Add/adjust ... |
562 |
and the destination is a non-local unicast, then create |
1da177e4c Linux-2.6.12-rc2 |
563 |
a cache_bypass connection entry */ |
570329487 ipvs: Wrap sysctl... |
564 |
if (sysctl_cache_bypass(ipvs) && svc->fwmark && |
0b7290212 ipvs: Handle inve... |
565 566 |
!(iph->hdr_flags & (IP_VS_HDR_INVERSE | IP_VS_HDR_ICMP)) && ip_vs_addr_is_unicast(net, svc->af, &iph->daddr)) { |
ad542ced2 ipvs: Remove unus... |
567 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
568 |
struct ip_vs_conn *cp; |
3575792e0 ipvs: extend conn... |
569 |
unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET && |
d4383f04d ipvs: API change ... |
570 |
iph->protocol == IPPROTO_UDP) ? |
3575792e0 ipvs: extend conn... |
571 |
IP_VS_CONN_F_ONE_PACKET : 0; |
dff630dda ipvs: supply a va... |
572 |
union nf_inet_addr daddr = { .all = { 0, 0, 0, 0 } }; |
1da177e4c Linux-2.6.12-rc2 |
573 |
|
1da177e4c Linux-2.6.12-rc2 |
574 |
/* create a new connection entry */ |
1e3e238e9 IPVS: use pr_err ... |
575 576 |
IP_VS_DBG(6, "%s(): create a cache_bypass entry ", __func__); |
f11017ec2 IPVS: Add struct ... |
577 578 |
{ struct ip_vs_conn_param p; |
3109d2f2d ipvs: Store ipvs ... |
579 |
ip_vs_conn_fill_param(svc->ipvs, svc->af, iph->protocol, |
d4383f04d ipvs: API change ... |
580 581 |
&iph->saddr, pptr[0], &iph->daddr, pptr[1], &p); |
ba38528aa ipvs: Supply dest... |
582 |
cp = ip_vs_conn_new(&p, svc->af, &daddr, 0, |
f11017ec2 IPVS: Add struct ... |
583 |
IP_VS_CONN_F_BYPASS | flags, |
0e051e683 IPVS: Backup, Pre... |
584 |
NULL, skb->mark); |
f11017ec2 IPVS: Add struct ... |
585 586 587 |
if (!cp) return NF_DROP; } |
1da177e4c Linux-2.6.12-rc2 |
588 589 590 591 592 |
/* statistics */ ip_vs_in_stats(cp, skb); /* set state */ |
4a516f110 ipvs: Remove unus... |
593 |
ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd); |
1da177e4c Linux-2.6.12-rc2 |
594 595 |
/* transmit the first SYN packet */ |
d4383f04d ipvs: API change ... |
596 |
ret = cp->packet_xmit(skb, cp, pd->pp, iph); |
1da177e4c Linux-2.6.12-rc2 |
597 598 599 600 601 602 603 604 605 606 607 608 609 |
/* do not touch skb anymore */ atomic_inc(&cp->in_pkts); ip_vs_conn_put(cp); return ret; } /* * When the virtual ftp service is presented, packets destined * for other services on the VIP may get here (except services * listed in the ipvs table), pass the packets, because it is * not ipvs job to decide to drop the packets. */ |
0b7290212 ipvs: Handle inve... |
610 |
if (svc->port == FTPPORT && dport != FTPPORT) |
1da177e4c Linux-2.6.12-rc2 |
611 |
return NF_ACCEPT; |
0b7290212 ipvs: Handle inve... |
612 613 614 |
if (unlikely(ip_vs_iph_icmp(iph))) return NF_DROP; |
1da177e4c Linux-2.6.12-rc2 |
615 616 617 618 619 620 621 622 |
/* * Notify the client that the destination is unreachable, and * release the socket buffer. * Since it is in IP layer, the TCP socket is not actually * created, the TCP RST packet cannot be sent, instead that * ICMP_PORT_UNREACH is sent here no matter it is TCP/UDP. --WZ */ |
2a3b791e6 IPVS: Add/adjust ... |
623 |
#ifdef CONFIG_IP_VS_IPV6 |
cb59155f2 ipvs: changes for... |
624 |
if (svc->af == AF_INET6) { |
570329487 ipvs: Wrap sysctl... |
625 626 |
if (!skb->dev) skb->dev = net->loopback_dev; |
3ffe533c8 ipv6: drop unused... |
627 |
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); |
cb59155f2 ipvs: changes for... |
628 |
} else |
2a3b791e6 IPVS: Add/adjust ... |
629 630 |
#endif icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); |
1da177e4c Linux-2.6.12-rc2 |
631 632 |
return NF_DROP; } |
84b3cee39 IPVS: Add sysctl_... |
633 634 635 636 637 638 639 |
#ifdef CONFIG_SYSCTL static int sysctl_snat_reroute(struct sk_buff *skb) { struct netns_ipvs *ipvs = net_ipvs(skb_net(skb)); return ipvs->sysctl_snat_reroute; } |
2300f0451 ipvs: Pass ipvs n... |
640 |
static int sysctl_nat_icmp_send(struct netns_ipvs *ipvs) |
0cfa558e2 IPVS: Add sysctl_... |
641 |
{ |
0cfa558e2 IPVS: Add sysctl_... |
642 643 |
return ipvs->sysctl_nat_icmp_send; } |
71a8ab6ca IPVS: Add sysctl_... |
644 645 646 647 |
static int sysctl_expire_nodest_conn(struct netns_ipvs *ipvs) { return ipvs->sysctl_expire_nodest_conn; } |
84b3cee39 IPVS: Add sysctl_... |
648 649 650 |
#else static int sysctl_snat_reroute(struct sk_buff *skb) { return 0; } |
2300f0451 ipvs: Pass ipvs n... |
651 |
static int sysctl_nat_icmp_send(struct netns_ipvs *ipvs) { return 0; } |
71a8ab6ca IPVS: Add sysctl_... |
652 |
static int sysctl_expire_nodest_conn(struct netns_ipvs *ipvs) { return 0; } |
84b3cee39 IPVS: Add sysctl_... |
653 654 |
#endif |
b1550f221 [NET]: Annotate i... |
655 |
__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) |
1da177e4c Linux-2.6.12-rc2 |
656 |
{ |
d3bc23e7e [NET]: Annotate c... |
657 |
return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); |
1da177e4c Linux-2.6.12-rc2 |
658 |
} |
1ca5bb545 ipvs: create ip_v... |
659 660 661 662 663 664 665 666 |
static inline enum ip_defrag_users ip_vs_defrag_user(unsigned int hooknum) { if (NF_INET_LOCAL_IN == hooknum) return IP_DEFRAG_VS_IN; if (NF_INET_FORWARD == hooknum) return IP_DEFRAG_VS_FWD; return IP_DEFRAG_VS_OUT; } |
776c729e8 [IPV4]: Change ip... |
667 |
static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) |
1da177e4c Linux-2.6.12-rc2 |
668 |
{ |
ac69269a4 ipvs: do not disa... |
669 |
int err; |
776c729e8 [IPV4]: Change ip... |
670 |
|
ac69269a4 ipvs: do not disa... |
671 672 673 |
local_bh_disable(); err = ip_defrag(skb, user); local_bh_enable(); |
776c729e8 [IPV4]: Change ip... |
674 |
if (!err) |
eddc9ec53 [SK_BUFF]: Introd... |
675 |
ip_send_check(ip_hdr(skb)); |
776c729e8 [IPV4]: Change ip... |
676 677 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
678 |
} |
579eb62ac ipvs: rerouting t... |
679 680 |
static int ip_vs_route_me_harder(int af, struct sk_buff *skb, unsigned int hooknum) |
ba4fd7e96 IPVS: Add ip_vs_r... |
681 |
{ |
579eb62ac ipvs: rerouting t... |
682 683 684 685 686 |
if (!sysctl_snat_reroute(skb)) return 0; /* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */ if (NF_INET_LOCAL_IN == hooknum) return 0; |
ba4fd7e96 IPVS: Add ip_vs_r... |
687 688 |
#ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { |
579eb62ac ipvs: rerouting t... |
689 690 691 692 |
struct dst_entry *dst = skb_dst(skb); if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) && ip6_route_me_harder(skb) != 0) |
ba4fd7e96 IPVS: Add ip_vs_r... |
693 694 695 |
return 1; } else #endif |
579eb62ac ipvs: rerouting t... |
696 |
if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) && |
ba4fd7e96 IPVS: Add ip_vs_r... |
697 698 699 700 701 |
ip_route_me_harder(skb, RTN_LOCAL) != 0) return 1; return 0; } |
1da177e4c Linux-2.6.12-rc2 |
702 703 704 705 706 707 708 |
/* * Packet has been made sufficiently writable in caller * - inout: 1=in->out, 0=out->in */ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, struct ip_vs_conn *cp, int inout) { |
eddc9ec53 [SK_BUFF]: Introd... |
709 |
struct iphdr *iph = ip_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
710 |
unsigned int icmp_offset = iph->ihl*4; |
d56f90a7c [SK_BUFF]: Introd... |
711 712 |
struct icmphdr *icmph = (struct icmphdr *)(skb_network_header(skb) + icmp_offset); |
1da177e4c Linux-2.6.12-rc2 |
713 714 715 |
struct iphdr *ciph = (struct iphdr *)(icmph + 1); if (inout) { |
e7ade46a5 IPVS: Change IPVS... |
716 |
iph->saddr = cp->vaddr.ip; |
1da177e4c Linux-2.6.12-rc2 |
717 |
ip_send_check(iph); |
e7ade46a5 IPVS: Change IPVS... |
718 |
ciph->daddr = cp->vaddr.ip; |
1da177e4c Linux-2.6.12-rc2 |
719 720 |
ip_send_check(ciph); } else { |
e7ade46a5 IPVS: Change IPVS... |
721 |
iph->daddr = cp->daddr.ip; |
1da177e4c Linux-2.6.12-rc2 |
722 |
ip_send_check(iph); |
e7ade46a5 IPVS: Change IPVS... |
723 |
ciph->saddr = cp->daddr.ip; |
1da177e4c Linux-2.6.12-rc2 |
724 725 |
ip_send_check(ciph); } |
2906f66a5 ipvs: SCTP Traspo... |
726 727 728 |
/* the TCP/UDP/SCTP port */ if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol || IPPROTO_SCTP == ciph->protocol) { |
014d730d5 [IPVS]: ipvs anno... |
729 |
__be16 *ports = (void *)ciph + ciph->ihl*4; |
1da177e4c Linux-2.6.12-rc2 |
730 731 732 733 734 735 736 737 738 739 740 741 742 |
if (inout) ports[1] = cp->vport; else ports[0] = cp->dport; } /* And finally the ICMP checksum */ icmph->checksum = 0; icmph->checksum = ip_vs_checksum_complete(skb, icmp_offset); skb->ip_summed = CHECKSUM_UNNECESSARY; if (inout) |
0d79641a9 ipvs: provide add... |
743 |
IP_VS_DBG_PKT(11, AF_INET, pp, skb, (void *)ciph - (void *)iph, |
1da177e4c Linux-2.6.12-rc2 |
744 745 |
"Forwarding altered outgoing ICMP"); else |
0d79641a9 ipvs: provide add... |
746 |
IP_VS_DBG_PKT(11, AF_INET, pp, skb, (void *)ciph - (void *)iph, |
1da177e4c Linux-2.6.12-rc2 |
747 748 |
"Forwarding altered incoming ICMP"); } |
b3cdd2a73 IPVS: Add and bin... |
749 750 751 752 753 |
#ifdef CONFIG_IP_VS_IPV6 void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, struct ip_vs_conn *cp, int inout) { struct ipv6hdr *iph = ipv6_hdr(skb); |
63dca2c0b ipvs: Fix faulty ... |
754 755 756 757 758 759 760 761 762 763 764 765 766 |
unsigned int icmp_offset = 0; unsigned int offs = 0; /* header offset*/ int protocol; struct icmp6hdr *icmph; struct ipv6hdr *ciph; unsigned short fragoffs; ipv6_find_hdr(skb, &icmp_offset, IPPROTO_ICMPV6, &fragoffs, NULL); icmph = (struct icmp6hdr *)(skb_network_header(skb) + icmp_offset); offs = icmp_offset + sizeof(struct icmp6hdr); ciph = (struct ipv6hdr *)(skb_network_header(skb) + offs); protocol = ipv6_find_hdr(skb, &offs, -1, &fragoffs, NULL); |
b3cdd2a73 IPVS: Add and bin... |
767 768 769 770 771 772 773 774 |
if (inout) { iph->saddr = cp->vaddr.in6; ciph->daddr = cp->vaddr.in6; } else { iph->daddr = cp->daddr.in6; ciph->saddr = cp->daddr.in6; } |
2906f66a5 ipvs: SCTP Traspo... |
775 |
/* the TCP/UDP/SCTP port */ |
63dca2c0b ipvs: Fix faulty ... |
776 777 778 |
if (!fragoffs && (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol || IPPROTO_SCTP == protocol)) { __be16 *ports = (void *)(skb_network_header(skb) + offs); |
b3cdd2a73 IPVS: Add and bin... |
779 |
|
63dca2c0b ipvs: Fix faulty ... |
780 781 782 783 |
IP_VS_DBG(11, "%s() changed port %d to %d ", __func__, ntohs(inout ? ports[1] : ports[0]), ntohs(inout ? cp->vport : cp->dport)); |
b3cdd2a73 IPVS: Add and bin... |
784 785 786 787 788 789 790 |
if (inout) ports[1] = cp->vport; else ports[0] = cp->dport; } /* And finally the ICMP checksum */ |
8870f8427 IPVS: ICMPv6 chec... |
791 792 793 794 795 796 |
icmph->icmp6_cksum = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, skb->len - icmp_offset, IPPROTO_ICMPV6, 0); skb->csum_start = skb_network_header(skb) - skb->head + icmp_offset; skb->csum_offset = offsetof(struct icmp6hdr, icmp6_cksum); skb->ip_summed = CHECKSUM_PARTIAL; |
b3cdd2a73 IPVS: Add and bin... |
797 798 |
if (inout) |
0d79641a9 ipvs: provide add... |
799 800 801 |
IP_VS_DBG_PKT(11, AF_INET6, pp, skb, (void *)ciph - (void *)iph, "Forwarding altered outgoing ICMPv6"); |
b3cdd2a73 IPVS: Add and bin... |
802 |
else |
0d79641a9 ipvs: provide add... |
803 804 805 |
IP_VS_DBG_PKT(11, AF_INET6, pp, skb, (void *)ciph - (void *)iph, "Forwarding altered incoming ICMPv6"); |
b3cdd2a73 IPVS: Add and bin... |
806 807 |
} #endif |
4856c84c1 ipvs: load balanc... |
808 |
/* Handle relevant response ICMP messages - forward to the right |
6cb90db50 ipvs: remove extr... |
809 |
* destination host. |
4856c84c1 ipvs: load balanc... |
810 |
*/ |
f2428ed5e ipvs: load balanc... |
811 812 813 |
static int handle_response_icmp(int af, struct sk_buff *skb, union nf_inet_addr *snet, __u8 protocol, struct ip_vs_conn *cp, |
4856c84c1 ipvs: load balanc... |
814 |
struct ip_vs_protocol *pp, |
579eb62ac ipvs: rerouting t... |
815 816 |
unsigned int offset, unsigned int ihl, unsigned int hooknum) |
4856c84c1 ipvs: load balanc... |
817 818 819 820 |
{ unsigned int verdict = NF_DROP; if (IP_VS_FWD_METHOD(cp) != 0) { |
1e3e238e9 IPVS: use pr_err ... |
821 822 823 |
pr_err("shouldn't reach here, because the box is on the " "half connection in the tun/dr module. "); |
4856c84c1 ipvs: load balanc... |
824 825 826 827 828 |
} /* Ensure the checksum is correct */ if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) { /* Failed checksum! */ |
f2428ed5e ipvs: load balanc... |
829 830 831 |
IP_VS_DBG_BUF(1, "Forward ICMP: failed checksum from %s! ", IP_VS_DBG_ADDR(af, snet)); |
4856c84c1 ipvs: load balanc... |
832 833 |
goto out; } |
2906f66a5 ipvs: SCTP Traspo... |
834 835 |
if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol || IPPROTO_SCTP == protocol) |
4856c84c1 ipvs: load balanc... |
836 837 838 |
offset += 2 * sizeof(__u16); if (!skb_make_writable(skb, offset)) goto out; |
f2428ed5e ipvs: load balanc... |
839 840 841 842 843 844 |
#ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) ip_vs_nat_icmp_v6(skb, pp, cp, 1); else #endif ip_vs_nat_icmp(skb, pp, cp, 1); |
4856c84c1 ipvs: load balanc... |
845 |
|
579eb62ac ipvs: rerouting t... |
846 |
if (ip_vs_route_me_harder(af, skb, hooknum)) |
ba4fd7e96 IPVS: Add ip_vs_r... |
847 |
goto out; |
f5a41847a ipvs: move ip_rou... |
848 |
|
4856c84c1 ipvs: load balanc... |
849 850 |
/* do the statistics and put it back */ ip_vs_out_stats(cp, skb); |
cf356d69d ipvs: switch to n... |
851 |
skb->ipvs_property = 1; |
f4bc17cdd ipvs: netfilter c... |
852 |
if (!(cp->flags & IP_VS_CONN_F_NFCT)) |
cf356d69d ipvs: switch to n... |
853 |
ip_vs_notrack(skb); |
f4bc17cdd ipvs: netfilter c... |
854 855 |
else ip_vs_update_conntrack(skb, cp, 0); |
4856c84c1 ipvs: load balanc... |
856 857 858 859 860 861 862 |
verdict = NF_ACCEPT; out: __ip_vs_conn_put(cp); return verdict; } |
1da177e4c Linux-2.6.12-rc2 |
863 864 |
/* * Handle ICMP messages in the inside-to-outside direction (outgoing). |
4856c84c1 ipvs: load balanc... |
865 |
* Find any that might be relevant, check against existing connections. |
1da177e4c Linux-2.6.12-rc2 |
866 |
* Currently handles error types - unreachable, quench, ttl exceeded. |
1da177e4c Linux-2.6.12-rc2 |
867 |
*/ |
7b5f689a2 ipvs: Pass ipvs i... |
868 869 |
static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, unsigned int hooknum) |
1da177e4c Linux-2.6.12-rc2 |
870 |
{ |
1da177e4c Linux-2.6.12-rc2 |
871 872 873 |
struct iphdr *iph; struct icmphdr _icmph, *ic; struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ |
51ef348b1 IPVS: Add 'af' ar... |
874 |
struct ip_vs_iphdr ciph; |
1da177e4c Linux-2.6.12-rc2 |
875 876 |
struct ip_vs_conn *cp; struct ip_vs_protocol *pp; |
4856c84c1 ipvs: load balanc... |
877 |
unsigned int offset, ihl; |
f2428ed5e ipvs: load balanc... |
878 |
union nf_inet_addr snet; |
1da177e4c Linux-2.6.12-rc2 |
879 880 881 882 |
*related = 1; /* reassemble IP fragments */ |
56f8a75c1 ip: introduce ip_... |
883 |
if (ip_is_fragment(ip_hdr(skb))) { |
1ca5bb545 ipvs: create ip_v... |
884 |
if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum))) |
1da177e4c Linux-2.6.12-rc2 |
885 |
return NF_STOLEN; |
1da177e4c Linux-2.6.12-rc2 |
886 |
} |
eddc9ec53 [SK_BUFF]: Introd... |
887 |
iph = ip_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
888 889 890 891 |
offset = ihl = iph->ihl * 4; ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph); if (ic == NULL) return NF_DROP; |
14d5e834f net: replace NIPQ... |
892 893 |
IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %pI4->%pI4 ", |
1da177e4c Linux-2.6.12-rc2 |
894 |
ic->type, ntohs(icmp_id(ic)), |
14d5e834f net: replace NIPQ... |
895 |
&iph->saddr, &iph->daddr); |
1da177e4c Linux-2.6.12-rc2 |
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 |
/* * Work through seeing if this is for us. * These checks are supposed to be in an order that means easy * things are checked first to speed up processing.... however * this means that some packets will manage to get a long way * down this stack and then be rejected, but that's life. */ if ((ic->type != ICMP_DEST_UNREACH) && (ic->type != ICMP_SOURCE_QUENCH) && (ic->type != ICMP_TIME_EXCEEDED)) { *related = 0; return NF_ACCEPT; } /* Now find the contained IP header */ offset += sizeof(_icmph); cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph); if (cih == NULL) return NF_ACCEPT; /* The packet looks wrong, ignore */ pp = ip_vs_proto_get(cih->protocol); if (!pp) return NF_ACCEPT; /* Is the embedded protocol header present? */ |
4412ec494 [NET] IPV4: Use h... |
922 |
if (unlikely(cih->frag_off & htons(IP_OFFSET) && |
1da177e4c Linux-2.6.12-rc2 |
923 924 |
pp->dont_defrag)) return NF_ACCEPT; |
0d79641a9 ipvs: provide add... |
925 926 |
IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset, "Checking outgoing ICMP for"); |
1da177e4c Linux-2.6.12-rc2 |
927 |
|
4fd9beef3 ipvs: Add hdr_fla... |
928 |
ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph); |
b0e010c52 ipvs: replace ip_... |
929 |
|
1da177e4c Linux-2.6.12-rc2 |
930 |
/* The embedded headers contain source and dest in reverse order */ |
0cf705c8c ipvs: Pass ipvs i... |
931 |
cp = pp->conn_out_get(ipvs, AF_INET, skb, &ciph); |
1da177e4c Linux-2.6.12-rc2 |
932 933 |
if (!cp) return NF_ACCEPT; |
f2428ed5e ipvs: load balanc... |
934 935 |
snet.ip = iph->saddr; return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp, |
579eb62ac ipvs: rerouting t... |
936 |
pp, ciph.len, ihl, hooknum); |
1da177e4c Linux-2.6.12-rc2 |
937 |
} |
2a3b791e6 IPVS: Add/adjust ... |
938 |
#ifdef CONFIG_IP_VS_IPV6 |
7b5f689a2 ipvs: Pass ipvs i... |
939 940 941 |
static int ip_vs_out_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, unsigned int hooknum, struct ip_vs_iphdr *ipvsh) |
2a3b791e6 IPVS: Add/adjust ... |
942 |
{ |
2a3b791e6 IPVS: Add/adjust ... |
943 |
struct icmp6hdr _icmph, *ic; |
63dca2c0b ipvs: Fix faulty ... |
944 |
struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */ |
2a3b791e6 IPVS: Add/adjust ... |
945 946 |
struct ip_vs_conn *cp; struct ip_vs_protocol *pp; |
f2428ed5e ipvs: load balanc... |
947 |
union nf_inet_addr snet; |
b0e010c52 ipvs: replace ip_... |
948 |
unsigned int offset; |
2a3b791e6 IPVS: Add/adjust ... |
949 |
|
63dca2c0b ipvs: Fix faulty ... |
950 |
*related = 1; |
2f74713d1 ipvs: Complete IP... |
951 |
ic = frag_safe_skb_hp(skb, ipvsh->len, sizeof(_icmph), &_icmph, ipvsh); |
2a3b791e6 IPVS: Add/adjust ... |
952 953 |
if (ic == NULL) return NF_DROP; |
2a3b791e6 IPVS: Add/adjust ... |
954 955 956 957 958 959 960 |
/* * Work through seeing if this is for us. * These checks are supposed to be in an order that means easy * things are checked first to speed up processing.... however * this means that some packets will manage to get a long way * down this stack and then be rejected, but that's life. */ |
2fab8917f ipvs: IPv6 extend... |
961 |
if (ic->icmp6_type & ICMPV6_INFOMSG_MASK) { |
2a3b791e6 IPVS: Add/adjust ... |
962 963 964 |
*related = 0; return NF_ACCEPT; } |
2f74713d1 ipvs: Complete IP... |
965 966 967 |
/* Fragment header that is before ICMP header tells us that: * it's not an error message since they can't be fragmented. */ |
e7165030d Merge branch 'mas... |
968 |
if (ipvsh->flags & IP6_FH_F_FRAG) |
2f74713d1 ipvs: Complete IP... |
969 |
return NF_DROP; |
2a3b791e6 IPVS: Add/adjust ... |
970 |
|
63dca2c0b ipvs: Fix faulty ... |
971 972 973 974 |
IP_VS_DBG(8, "Outgoing ICMPv6 (%d,%d) %pI6c->%pI6c ", ic->icmp6_type, ntohs(icmpv6_id(ic)), &ipvsh->saddr, &ipvsh->daddr); |
4fd9beef3 ipvs: Add hdr_fla... |
975 976 |
if (!ip_vs_fill_iph_skb_icmp(AF_INET6, skb, ipvsh->len + sizeof(_icmph), true, &ciph)) |
2a3b791e6 IPVS: Add/adjust ... |
977 |
return NF_ACCEPT; /* The packet looks wrong, ignore */ |
63dca2c0b ipvs: Fix faulty ... |
978 979 |
pp = ip_vs_proto_get(ciph.protocol); |
2a3b791e6 IPVS: Add/adjust ... |
980 981 |
if (!pp) return NF_ACCEPT; |
2a3b791e6 IPVS: Add/adjust ... |
982 |
/* The embedded headers contain source and dest in reverse order */ |
0cf705c8c ipvs: Pass ipvs i... |
983 |
cp = pp->conn_out_get(ipvs, AF_INET6, skb, &ciph); |
2a3b791e6 IPVS: Add/adjust ... |
984 985 |
if (!cp) return NF_ACCEPT; |
63dca2c0b ipvs: Fix faulty ... |
986 |
snet.in6 = ciph.saddr.in6; |
b0e010c52 ipvs: replace ip_... |
987 |
offset = ciph.len; |
63dca2c0b ipvs: Fix faulty ... |
988 |
return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, |
b0e010c52 ipvs: replace ip_... |
989 |
pp, offset, sizeof(struct ipv6hdr), |
579eb62ac ipvs: rerouting t... |
990 |
hooknum); |
2a3b791e6 IPVS: Add/adjust ... |
991 992 |
} #endif |
2906f66a5 ipvs: SCTP Traspo... |
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 |
/* * Check if sctp chunc is ABORT chunk */ static inline int is_sctp_abort(const struct sk_buff *skb, int nh_len) { sctp_chunkhdr_t *sch, schunk; sch = skb_header_pointer(skb, nh_len + sizeof(sctp_sctphdr_t), sizeof(schunk), &schunk); if (sch == NULL) return 0; if (sch->type == SCTP_CID_ABORT) return 1; return 0; } |
2a3b791e6 IPVS: Add/adjust ... |
1007 |
static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len) |
1da177e4c Linux-2.6.12-rc2 |
1008 1009 |
{ struct tcphdr _tcph, *th; |
2a3b791e6 IPVS: Add/adjust ... |
1010 |
th = skb_header_pointer(skb, nh_len, sizeof(_tcph), &_tcph); |
1da177e4c Linux-2.6.12-rc2 |
1011 1012 1013 1014 |
if (th == NULL) return 0; return th->rst; } |
dc7b3eb90 ipvs: Fix reuse c... |
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 |
static inline bool is_new_conn(const struct sk_buff *skb, struct ip_vs_iphdr *iph) { switch (iph->protocol) { case IPPROTO_TCP: { struct tcphdr _tcph, *th; th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph); if (th == NULL) return false; return th->syn; } case IPPROTO_SCTP: { sctp_chunkhdr_t *sch, schunk; sch = skb_header_pointer(skb, iph->len + sizeof(sctp_sctphdr_t), sizeof(schunk), &schunk); if (sch == NULL) return false; return sch->type == SCTP_CID_INIT; } default: return false; } } |
d752c3645 ipvs: allow resch... |
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 |
static inline bool is_new_conn_expected(const struct ip_vs_conn *cp, int conn_reuse_mode) { /* Controlled (FTP DATA or persistence)? */ if (cp->control) return false; switch (cp->protocol) { case IPPROTO_TCP: return (cp->state == IP_VS_TCP_S_TIME_WAIT) || ((conn_reuse_mode & 2) && (cp->state == IP_VS_TCP_S_FIN_WAIT) && (cp->flags & IP_VS_CONN_F_NOOUTPUT)); case IPPROTO_SCTP: return cp->state == IP_VS_SCTP_S_CLOSED; default: return false; } } |
4856c84c1 ipvs: load balanc... |
1059 |
/* Handle response packets: rewrite addresses and send away... |
4856c84c1 ipvs: load balanc... |
1060 1061 |
*/ static unsigned int |
9330419d9 IPVS: netns, use ... |
1062 |
handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, |
579eb62ac ipvs: rerouting t... |
1063 1064 |
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph, unsigned int hooknum) |
4856c84c1 ipvs: load balanc... |
1065 |
{ |
9330419d9 IPVS: netns, use ... |
1066 |
struct ip_vs_protocol *pp = pd->pp; |
b0e010c52 ipvs: replace ip_... |
1067 |
IP_VS_DBG_PKT(11, af, pp, skb, iph->off, "Outgoing packet"); |
4856c84c1 ipvs: load balanc... |
1068 |
|
d4383f04d ipvs: API change ... |
1069 |
if (!skb_make_writable(skb, iph->len)) |
4856c84c1 ipvs: load balanc... |
1070 1071 1072 |
goto drop; /* mangle the packet */ |
d4383f04d ipvs: API change ... |
1073 |
if (pp->snat_handler && !pp->snat_handler(skb, pp, cp, iph)) |
4856c84c1 ipvs: load balanc... |
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 |
goto drop; #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) ipv6_hdr(skb)->saddr = cp->vaddr.in6; else #endif { ip_hdr(skb)->saddr = cp->vaddr.ip; ip_send_check(ip_hdr(skb)); } |
8a8030407 ipvs: make rerout... |
1085 1086 1087 1088 1089 1090 1091 1092 |
/* * nf_iterate does not expect change in the skb->dst->dev. * It looks like it is not fatal to enable this code for hooks * where our handlers are at the end of the chain list and * when all next handlers use skb->dst->dev and not outdev. * It will definitely route properly the inout NAT traffic * when multiple paths are used. */ |
4856c84c1 ipvs: load balanc... |
1093 1094 1095 1096 1097 1098 |
/* For policy routing, packets originating from this * machine itself may be routed differently to packets * passing through. We want this packet to be routed as * if it came from this machine itself. So re-compute * the routing information. */ |
579eb62ac ipvs: rerouting t... |
1099 |
if (ip_vs_route_me_harder(af, skb, hooknum)) |
ba4fd7e96 IPVS: Add ip_vs_r... |
1100 |
goto drop; |
4856c84c1 ipvs: load balanc... |
1101 |
|
b0e010c52 ipvs: replace ip_... |
1102 |
IP_VS_DBG_PKT(10, af, pp, skb, iph->off, "After SNAT"); |
4856c84c1 ipvs: load balanc... |
1103 1104 |
ip_vs_out_stats(cp, skb); |
9330419d9 IPVS: netns, use ... |
1105 |
ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd); |
cf356d69d ipvs: switch to n... |
1106 |
skb->ipvs_property = 1; |
f4bc17cdd ipvs: netfilter c... |
1107 |
if (!(cp->flags & IP_VS_CONN_F_NFCT)) |
cf356d69d ipvs: switch to n... |
1108 |
ip_vs_notrack(skb); |
f4bc17cdd ipvs: netfilter c... |
1109 1110 |
else ip_vs_update_conntrack(skb, cp, 0); |
4856c84c1 ipvs: load balanc... |
1111 |
ip_vs_conn_put(cp); |
4856c84c1 ipvs: load balanc... |
1112 1113 1114 1115 1116 1117 |
LeaveFunction(11); return NF_ACCEPT; drop: ip_vs_conn_put(cp); kfree_skb(skb); |
f4bc17cdd ipvs: netfilter c... |
1118 |
LeaveFunction(11); |
4856c84c1 ipvs: load balanc... |
1119 1120 |
return NF_STOLEN; } |
1da177e4c Linux-2.6.12-rc2 |
1121 |
/* |
4856c84c1 ipvs: load balanc... |
1122 |
* Check if outgoing packet belongs to the established ip_vs_conn. |
1da177e4c Linux-2.6.12-rc2 |
1123 1124 |
*/ static unsigned int |
1b75097dd ipvs: Pass ipvs i... |
1125 |
ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int af) |
1da177e4c Linux-2.6.12-rc2 |
1126 |
{ |
1b75097dd ipvs: Pass ipvs i... |
1127 |
struct net *net = ipvs->net; |
51ef348b1 IPVS: Add 'af' ar... |
1128 |
struct ip_vs_iphdr iph; |
1da177e4c Linux-2.6.12-rc2 |
1129 |
struct ip_vs_protocol *pp; |
9330419d9 IPVS: netns, use ... |
1130 |
struct ip_vs_proto_data *pd; |
1da177e4c Linux-2.6.12-rc2 |
1131 |
struct ip_vs_conn *cp; |
1da177e4c Linux-2.6.12-rc2 |
1132 1133 |
EnterFunction(11); |
fc6047676 ipvs: changes for... |
1134 |
/* Already marked as IPVS request or reply? */ |
6869c4d8e [NETFILTER]: redu... |
1135 |
if (skb->ipvs_property) |
1da177e4c Linux-2.6.12-rc2 |
1136 |
return NF_ACCEPT; |
fc6047676 ipvs: changes for... |
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 |
/* Bad... Do not break raw sockets */ if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT && af == AF_INET)) { struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(skb->sk); if (inet && sk->sk_family == PF_INET && inet->nodefrag) return NF_ACCEPT; } if (unlikely(!skb_dst(skb))) return NF_ACCEPT; |
48aed1b02 ipvs: Pass ipvs n... |
1149 |
if (!ipvs->enable) |
7a4f0761f IPVS: init and cl... |
1150 |
return NF_ACCEPT; |
4fd9beef3 ipvs: Add hdr_fla... |
1151 |
ip_vs_fill_iph_skb(af, skb, false, &iph); |
2a3b791e6 IPVS: Add/adjust ... |
1152 1153 1154 |
#ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { |
1ca5bb545 ipvs: create ip_v... |
1155 |
int related; |
7b5f689a2 ipvs: Pass ipvs i... |
1156 |
int verdict = ip_vs_out_icmp_v6(ipvs, skb, &related, |
d4383f04d ipvs: API change ... |
1157 |
hooknum, &iph); |
1da177e4c Linux-2.6.12-rc2 |
1158 |
|
f5a41847a ipvs: move ip_rou... |
1159 |
if (related) |
2a3b791e6 IPVS: Add/adjust ... |
1160 |
return verdict; |
2a3b791e6 IPVS: Add/adjust ... |
1161 1162 1163 1164 |
} } else #endif if (unlikely(iph.protocol == IPPROTO_ICMP)) { |
1ca5bb545 ipvs: create ip_v... |
1165 |
int related; |
7b5f689a2 ipvs: Pass ipvs i... |
1166 |
int verdict = ip_vs_out_icmp(ipvs, skb, &related, hooknum); |
2a3b791e6 IPVS: Add/adjust ... |
1167 |
|
f5a41847a ipvs: move ip_rou... |
1168 |
if (related) |
2a3b791e6 IPVS: Add/adjust ... |
1169 |
return verdict; |
2a3b791e6 IPVS: Add/adjust ... |
1170 |
} |
1da177e4c Linux-2.6.12-rc2 |
1171 |
|
18d6ade63 ipvs: Pass ipvs n... |
1172 |
pd = ip_vs_proto_data_get(ipvs, iph.protocol); |
9330419d9 IPVS: netns, use ... |
1173 |
if (unlikely(!pd)) |
1da177e4c Linux-2.6.12-rc2 |
1174 |
return NF_ACCEPT; |
9330419d9 IPVS: netns, use ... |
1175 |
pp = pd->pp; |
1da177e4c Linux-2.6.12-rc2 |
1176 1177 |
/* reassemble IP fragments */ |
2a3b791e6 IPVS: Add/adjust ... |
1178 |
#ifdef CONFIG_IP_VS_IPV6 |
63dca2c0b ipvs: Fix faulty ... |
1179 |
if (af == AF_INET) |
2a3b791e6 IPVS: Add/adjust ... |
1180 |
#endif |
56f8a75c1 ip: introduce ip_... |
1181 |
if (unlikely(ip_is_fragment(ip_hdr(skb)) && !pp->dont_defrag)) { |
1ca5bb545 ipvs: create ip_v... |
1182 1183 |
if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum))) |
2a3b791e6 IPVS: Add/adjust ... |
1184 |
return NF_STOLEN; |
4fd9beef3 ipvs: Add hdr_fla... |
1185 |
ip_vs_fill_iph_skb(AF_INET, skb, false, &iph); |
2a3b791e6 IPVS: Add/adjust ... |
1186 |
} |
1da177e4c Linux-2.6.12-rc2 |
1187 1188 1189 1190 |
/* * Check if the packet belongs to an existing entry */ |
0cf705c8c ipvs: Pass ipvs i... |
1191 |
cp = pp->conn_out_get(ipvs, af, skb, &iph); |
1da177e4c Linux-2.6.12-rc2 |
1192 |
|
cb59155f2 ipvs: changes for... |
1193 |
if (likely(cp)) |
579eb62ac ipvs: rerouting t... |
1194 |
return handle_response(af, skb, pd, cp, &iph, hooknum); |
2300f0451 ipvs: Pass ipvs n... |
1195 |
if (sysctl_nat_icmp_send(ipvs) && |
cb59155f2 ipvs: changes for... |
1196 1197 1198 1199 |
(pp->protocol == IPPROTO_TCP || pp->protocol == IPPROTO_UDP || pp->protocol == IPPROTO_SCTP)) { __be16 _ports[2], *pptr; |
2f74713d1 ipvs: Complete IP... |
1200 1201 |
pptr = frag_safe_skb_hp(skb, iph.len, sizeof(_ports), _ports, &iph); |
cb59155f2 ipvs: changes for... |
1202 1203 |
if (pptr == NULL) return NF_ACCEPT; /* Not for me */ |
48aed1b02 ipvs: Pass ipvs n... |
1204 |
if (ip_vs_has_real_service(ipvs, af, iph.protocol, &iph.saddr, |
276472eae ipvs: remove rs_l... |
1205 |
pptr[0])) { |
cb59155f2 ipvs: changes for... |
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 |
/* * Notify the real server: there is no * existing entry if it is not RST * packet or not TCP packet. */ if ((iph.protocol != IPPROTO_TCP && iph.protocol != IPPROTO_SCTP) || ((iph.protocol == IPPROTO_TCP && !is_tcp_reset(skb, iph.len)) || (iph.protocol == IPPROTO_SCTP && !is_sctp_abort(skb, iph.len)))) { |
2a3b791e6 IPVS: Add/adjust ... |
1218 |
#ifdef CONFIG_IP_VS_IPV6 |
cb59155f2 ipvs: changes for... |
1219 |
if (af == AF_INET6) { |
cb59155f2 ipvs: changes for... |
1220 1221 1222 1223 1224 1225 1226 |
if (!skb->dev) skb->dev = net->loopback_dev; icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); } else |
2a3b791e6 IPVS: Add/adjust ... |
1227 |
#endif |
cb59155f2 ipvs: changes for... |
1228 1229 1230 1231 |
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); return NF_DROP; |
1da177e4c Linux-2.6.12-rc2 |
1232 1233 |
} } |
1da177e4c Linux-2.6.12-rc2 |
1234 |
} |
b0e010c52 ipvs: replace ip_... |
1235 |
IP_VS_DBG_PKT(12, af, pp, skb, iph.off, |
cb59155f2 ipvs: changes for... |
1236 1237 |
"ip_vs_out: packet continues traversal as normal"); return NF_ACCEPT; |
1da177e4c Linux-2.6.12-rc2 |
1238 |
} |
fc6047676 ipvs: changes for... |
1239 |
/* |
cb59155f2 ipvs: changes for... |
1240 1241 |
* It is hooked at the NF_INET_FORWARD and NF_INET_LOCAL_IN chain, * used only for VS/NAT. |
fc6047676 ipvs: changes for... |
1242 1243 1244 |
* Check if packet is reply for established ip_vs_conn. */ static unsigned int |
06198b34a netfilter: Pass p... |
1245 |
ip_vs_reply4(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1246 |
const struct nf_hook_state *state) |
fc6047676 ipvs: changes for... |
1247 |
{ |
1b75097dd ipvs: Pass ipvs i... |
1248 |
return ip_vs_out(net_ipvs(state->net), state->hook, skb, AF_INET); |
fc6047676 ipvs: changes for... |
1249 1250 1251 1252 1253 1254 1255 |
} /* * It is hooked at the NF_INET_LOCAL_OUT chain, used only for VS/NAT. * Check if packet is reply for established ip_vs_conn. */ static unsigned int |
06198b34a netfilter: Pass p... |
1256 |
ip_vs_local_reply4(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1257 |
const struct nf_hook_state *state) |
fc6047676 ipvs: changes for... |
1258 |
{ |
1b75097dd ipvs: Pass ipvs i... |
1259 |
return ip_vs_out(net_ipvs(state->net), state->hook, skb, AF_INET); |
fc6047676 ipvs: changes for... |
1260 1261 1262 1263 1264 |
} #ifdef CONFIG_IP_VS_IPV6 /* |
cb59155f2 ipvs: changes for... |
1265 1266 |
* It is hooked at the NF_INET_FORWARD and NF_INET_LOCAL_IN chain, * used only for VS/NAT. |
fc6047676 ipvs: changes for... |
1267 1268 1269 |
* Check if packet is reply for established ip_vs_conn. */ static unsigned int |
06198b34a netfilter: Pass p... |
1270 |
ip_vs_reply6(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1271 |
const struct nf_hook_state *state) |
fc6047676 ipvs: changes for... |
1272 |
{ |
1b75097dd ipvs: Pass ipvs i... |
1273 |
return ip_vs_out(net_ipvs(state->net), state->hook, skb, AF_INET6); |
fc6047676 ipvs: changes for... |
1274 1275 1276 1277 1278 1279 1280 |
} /* * It is hooked at the NF_INET_LOCAL_OUT chain, used only for VS/NAT. * Check if packet is reply for established ip_vs_conn. */ static unsigned int |
06198b34a netfilter: Pass p... |
1281 |
ip_vs_local_reply6(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1282 |
const struct nf_hook_state *state) |
fc6047676 ipvs: changes for... |
1283 |
{ |
1b75097dd ipvs: Pass ipvs i... |
1284 |
return ip_vs_out(net_ipvs(state->net), state->hook, skb, AF_INET6); |
fc6047676 ipvs: changes for... |
1285 1286 1287 |
} #endif |
1da177e4c Linux-2.6.12-rc2 |
1288 |
|
3b5ca6176 ipvs: pull out ip... |
1289 |
static unsigned int |
d8f44c335 ipvs: Pass ipvs i... |
1290 1291 |
ip_vs_try_to_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, |
3b5ca6176 ipvs: pull out ip... |
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 |
int *verdict, struct ip_vs_conn **cpp, struct ip_vs_iphdr *iph) { struct ip_vs_protocol *pp = pd->pp; if (!iph->fragoffs) { /* No (second) fragments need to enter here, as nf_defrag_ipv6 * replayed fragment zero will already have created the cp */ /* Schedule and create new connection entry into cpp */ |
d8f44c335 ipvs: Pass ipvs i... |
1303 |
if (!pp->conn_schedule(ipvs, af, skb, pd, verdict, cpp, iph)) |
3b5ca6176 ipvs: pull out ip... |
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 |
return 0; } if (unlikely(!*cpp)) { /* sorry, all this trouble for a no-hit :) */ IP_VS_DBG_PKT(12, af, pp, skb, iph->off, "ip_vs_in: packet continues traversal as normal"); if (iph->fragoffs) { /* Fragment that couldn't be mapped to a conn entry * is missing module nf_defrag_ipv6 */ IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6 "); IP_VS_DBG_PKT(7, af, pp, skb, iph->off, "unhandled fragment"); } *verdict = NF_ACCEPT; return 0; } return 1; } |
1da177e4c Linux-2.6.12-rc2 |
1326 1327 1328 1329 1330 1331 |
/* * Handle ICMP messages in the outside-to-inside direction (incoming). * Find any that might be relevant, check against existing connections, * forward to the right destination host if relevant. * Currently handles error types - unreachable, quench, ttl exceeded. */ |
e905a9eda [NET] IPV4: Fix w... |
1332 |
static int |
6f2bcea99 ipvs: Pass ipvs i... |
1333 1334 |
ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, unsigned int hooknum) |
1da177e4c Linux-2.6.12-rc2 |
1335 |
{ |
1da177e4c Linux-2.6.12-rc2 |
1336 1337 1338 |
struct iphdr *iph; struct icmphdr _icmph, *ic; struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ |
51ef348b1 IPVS: Add 'af' ar... |
1339 |
struct ip_vs_iphdr ciph; |
1da177e4c Linux-2.6.12-rc2 |
1340 1341 |
struct ip_vs_conn *cp; struct ip_vs_protocol *pp; |
9330419d9 IPVS: netns, use ... |
1342 |
struct ip_vs_proto_data *pd; |
f2edb9f77 ipvs: implement p... |
1343 |
unsigned int offset, offset2, ihl, verdict; |
6044eeffa ipvs: attempt to ... |
1344 |
bool ipip, new_cp = false; |
1da177e4c Linux-2.6.12-rc2 |
1345 1346 1347 1348 |
*related = 1; /* reassemble IP fragments */ |
56f8a75c1 ip: introduce ip_... |
1349 |
if (ip_is_fragment(ip_hdr(skb))) { |
1ca5bb545 ipvs: create ip_v... |
1350 |
if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum))) |
1da177e4c Linux-2.6.12-rc2 |
1351 |
return NF_STOLEN; |
1da177e4c Linux-2.6.12-rc2 |
1352 |
} |
eddc9ec53 [SK_BUFF]: Introd... |
1353 |
iph = ip_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
1354 1355 1356 1357 |
offset = ihl = iph->ihl * 4; ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph); if (ic == NULL) return NF_DROP; |
14d5e834f net: replace NIPQ... |
1358 1359 |
IP_VS_DBG(12, "Incoming ICMP (%d,%d) %pI4->%pI4 ", |
1da177e4c Linux-2.6.12-rc2 |
1360 |
ic->type, ntohs(icmp_id(ic)), |
14d5e834f net: replace NIPQ... |
1361 |
&iph->saddr, &iph->daddr); |
1da177e4c Linux-2.6.12-rc2 |
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 |
/* * Work through seeing if this is for us. * These checks are supposed to be in an order that means easy * things are checked first to speed up processing.... however * this means that some packets will manage to get a long way * down this stack and then be rejected, but that's life. */ if ((ic->type != ICMP_DEST_UNREACH) && (ic->type != ICMP_SOURCE_QUENCH) && (ic->type != ICMP_TIME_EXCEEDED)) { *related = 0; return NF_ACCEPT; } /* Now find the contained IP header */ offset += sizeof(_icmph); cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph); if (cih == NULL) return NF_ACCEPT; /* The packet looks wrong, ignore */ |
f2edb9f77 ipvs: implement p... |
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 |
/* Special case for errors for IPIP packets */ ipip = false; if (cih->protocol == IPPROTO_IPIP) { if (unlikely(cih->frag_off & htons(IP_OFFSET))) return NF_ACCEPT; /* Error for our IPIP must arrive at LOCAL_IN */ if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL)) return NF_ACCEPT; offset += cih->ihl * 4; cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph); if (cih == NULL) return NF_ACCEPT; /* The packet looks wrong, ignore */ ipip = true; } |
18d6ade63 ipvs: Pass ipvs n... |
1396 |
pd = ip_vs_proto_data_get(ipvs, cih->protocol); |
9330419d9 IPVS: netns, use ... |
1397 |
if (!pd) |
1da177e4c Linux-2.6.12-rc2 |
1398 |
return NF_ACCEPT; |
9330419d9 IPVS: netns, use ... |
1399 |
pp = pd->pp; |
1da177e4c Linux-2.6.12-rc2 |
1400 1401 |
/* Is the embedded protocol header present? */ |
4412ec494 [NET] IPV4: Use h... |
1402 |
if (unlikely(cih->frag_off & htons(IP_OFFSET) && |
1da177e4c Linux-2.6.12-rc2 |
1403 1404 |
pp->dont_defrag)) return NF_ACCEPT; |
0d79641a9 ipvs: provide add... |
1405 1406 |
IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset, "Checking incoming ICMP for"); |
1da177e4c Linux-2.6.12-rc2 |
1407 |
|
f2edb9f77 ipvs: implement p... |
1408 |
offset2 = offset; |
4fd9beef3 ipvs: Add hdr_fla... |
1409 |
ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !ipip, &ciph); |
63dca2c0b ipvs: Fix faulty ... |
1410 |
offset = ciph.len; |
b0e010c52 ipvs: replace ip_... |
1411 |
|
f2edb9f77 ipvs: implement p... |
1412 1413 1414 |
/* The embedded headers contain source and dest in reverse order. * For IPIP this is error for request, not for reply. */ |
ab1619764 ipvs: Pass ipvs i... |
1415 |
cp = pp->conn_in_get(ipvs, AF_INET, skb, &ciph); |
6044eeffa ipvs: attempt to ... |
1416 1417 1418 |
if (!cp) { int v; |
a47b43008 ipvs: Cache ipvs ... |
1419 |
if (!sysctl_schedule_icmp(ipvs)) |
6044eeffa ipvs: attempt to ... |
1420 |
return NF_ACCEPT; |
d8f44c335 ipvs: Pass ipvs i... |
1421 |
if (!ip_vs_try_to_schedule(ipvs, AF_INET, skb, pd, &v, &cp, &ciph)) |
6044eeffa ipvs: attempt to ... |
1422 1423 1424 |
return v; new_cp = true; } |
1da177e4c Linux-2.6.12-rc2 |
1425 1426 1427 1428 |
verdict = NF_DROP; /* Ensure the checksum is correct */ |
604763722 [NET]: Treat CHEC... |
1429 |
if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) { |
1da177e4c Linux-2.6.12-rc2 |
1430 |
/* Failed checksum! */ |
14d5e834f net: replace NIPQ... |
1431 1432 1433 |
IP_VS_DBG(1, "Incoming ICMP: failed checksum from %pI4! ", &iph->saddr); |
1da177e4c Linux-2.6.12-rc2 |
1434 1435 |
goto out; } |
f2edb9f77 ipvs: implement p... |
1436 1437 |
if (ipip) { __be32 info = ic->un.gateway; |
f44a5f45f ipvs: Fix panic d... |
1438 1439 |
__u8 type = ic->type; __u8 code = ic->code; |
f2edb9f77 ipvs: implement p... |
1440 1441 1442 1443 1444 1445 |
/* Update the MTU */ if (ic->type == ICMP_DEST_UNREACH && ic->code == ICMP_FRAG_NEEDED) { struct ip_vs_dest *dest = cp->dest; u32 mtu = ntohs(ic->un.frag.mtu); |
f44a5f45f ipvs: Fix panic d... |
1446 |
__be16 frag_off = cih->frag_off; |
f2edb9f77 ipvs: implement p... |
1447 1448 |
/* Strip outer IP and ICMP, go to IPIP header */ |
f44a5f45f ipvs: Fix panic d... |
1449 1450 |
if (pskb_pull(skb, ihl + sizeof(_icmph)) == NULL) goto ignore_ipip; |
f2edb9f77 ipvs: implement p... |
1451 1452 1453 1454 1455 |
offset2 -= ihl + sizeof(_icmph); skb_reset_network_header(skb); IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u ", &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, mtu); |
6f2bcea99 ipvs: Pass ipvs i... |
1456 |
ipv4_update_pmtu(skb, ipvs->net, |
f2edb9f77 ipvs: implement p... |
1457 |
mtu, 0, 0, 0, 0); |
f2edb9f77 ipvs: implement p... |
1458 |
/* Client uses PMTUD? */ |
f44a5f45f ipvs: Fix panic d... |
1459 |
if (!(frag_off & htons(IP_DF))) |
f2edb9f77 ipvs: implement p... |
1460 1461 1462 |
goto ignore_ipip; /* Prefer the resulting PMTU */ if (dest) { |
026ace060 ipvs: optimize ds... |
1463 1464 1465 1466 1467 1468 1469 |
struct ip_vs_dest_dst *dest_dst; rcu_read_lock(); dest_dst = rcu_dereference(dest->dest_dst); if (dest_dst) mtu = dst_mtu(dest_dst->dst_cache); rcu_read_unlock(); |
f2edb9f77 ipvs: implement p... |
1470 1471 1472 1473 1474 1475 1476 1477 |
} if (mtu > 68 + sizeof(struct iphdr)) mtu -= sizeof(struct iphdr); info = htonl(mtu); } /* Strip outer IP, ICMP and IPIP, go to IP header of * original request. */ |
f44a5f45f ipvs: Fix panic d... |
1478 1479 |
if (pskb_pull(skb, offset2) == NULL) goto ignore_ipip; |
f2edb9f77 ipvs: implement p... |
1480 1481 1482 1483 |
skb_reset_network_header(skb); IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u ", &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, |
f44a5f45f ipvs: Fix panic d... |
1484 1485 |
type, code, ntohl(info)); icmp_send(skb, type, code, info); |
f2edb9f77 ipvs: implement p... |
1486 1487 1488 1489 1490 1491 1492 1493 |
/* ICMP can be shorter but anyways, account it */ ip_vs_out_stats(cp, skb); ignore_ipip: consume_skb(skb); verdict = NF_STOLEN; goto out; } |
1da177e4c Linux-2.6.12-rc2 |
1494 1495 |
/* do the statistics and put it back */ ip_vs_in_stats(cp, skb); |
06f3d7f97 ipvs: SCTP ports ... |
1496 1497 |
if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol || IPPROTO_SCTP == cih->protocol) |
1da177e4c Linux-2.6.12-rc2 |
1498 |
offset += 2 * sizeof(__u16); |
d4383f04d ipvs: API change ... |
1499 |
verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum, &ciph); |
1da177e4c Linux-2.6.12-rc2 |
1500 |
|
552ad65aa IPVS: labels at p... |
1501 |
out: |
6044eeffa ipvs: attempt to ... |
1502 1503 1504 1505 |
if (likely(!new_cp)) __ip_vs_conn_put(cp); else ip_vs_conn_put(cp); |
1da177e4c Linux-2.6.12-rc2 |
1506 1507 1508 |
return verdict; } |
2a3b791e6 IPVS: Add/adjust ... |
1509 |
#ifdef CONFIG_IP_VS_IPV6 |
6f2bcea99 ipvs: Pass ipvs i... |
1510 1511 1512 |
static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, unsigned int hooknum, struct ip_vs_iphdr *iph) |
2a3b791e6 IPVS: Add/adjust ... |
1513 |
{ |
2a3b791e6 IPVS: Add/adjust ... |
1514 |
struct icmp6hdr _icmph, *ic; |
63dca2c0b ipvs: Fix faulty ... |
1515 |
struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */ |
2a3b791e6 IPVS: Add/adjust ... |
1516 1517 |
struct ip_vs_conn *cp; struct ip_vs_protocol *pp; |
9330419d9 IPVS: netns, use ... |
1518 |
struct ip_vs_proto_data *pd; |
b0e010c52 ipvs: replace ip_... |
1519 |
unsigned int offset, verdict; |
6044eeffa ipvs: attempt to ... |
1520 |
bool new_cp = false; |
2a3b791e6 IPVS: Add/adjust ... |
1521 |
|
63dca2c0b ipvs: Fix faulty ... |
1522 |
*related = 1; |
2a3b791e6 IPVS: Add/adjust ... |
1523 |
|
2f74713d1 ipvs: Complete IP... |
1524 |
ic = frag_safe_skb_hp(skb, iph->len, sizeof(_icmph), &_icmph, iph); |
2a3b791e6 IPVS: Add/adjust ... |
1525 1526 |
if (ic == NULL) return NF_DROP; |
2a3b791e6 IPVS: Add/adjust ... |
1527 1528 1529 1530 1531 1532 1533 |
/* * Work through seeing if this is for us. * These checks are supposed to be in an order that means easy * things are checked first to speed up processing.... however * this means that some packets will manage to get a long way * down this stack and then be rejected, but that's life. */ |
2fab8917f ipvs: IPv6 extend... |
1534 |
if (ic->icmp6_type & ICMPV6_INFOMSG_MASK) { |
2a3b791e6 IPVS: Add/adjust ... |
1535 1536 1537 |
*related = 0; return NF_ACCEPT; } |
2f74713d1 ipvs: Complete IP... |
1538 1539 1540 |
/* Fragment header that is before ICMP header tells us that: * it's not an error message since they can't be fragmented. */ |
e7165030d Merge branch 'mas... |
1541 |
if (iph->flags & IP6_FH_F_FRAG) |
2f74713d1 ipvs: Complete IP... |
1542 |
return NF_DROP; |
2a3b791e6 IPVS: Add/adjust ... |
1543 |
|
63dca2c0b ipvs: Fix faulty ... |
1544 1545 1546 1547 |
IP_VS_DBG(8, "Incoming ICMPv6 (%d,%d) %pI6c->%pI6c ", ic->icmp6_type, ntohs(icmpv6_id(ic)), &iph->saddr, &iph->daddr); |
b0e010c52 ipvs: replace ip_... |
1548 |
offset = iph->len + sizeof(_icmph); |
4fd9beef3 ipvs: Add hdr_fla... |
1549 |
if (!ip_vs_fill_iph_skb_icmp(AF_INET6, skb, offset, true, &ciph)) |
b0e010c52 ipvs: replace ip_... |
1550 |
return NF_ACCEPT; |
2a3b791e6 IPVS: Add/adjust ... |
1551 |
|
18d6ade63 ipvs: Pass ipvs n... |
1552 |
pd = ip_vs_proto_data_get(ipvs, ciph.protocol); |
9330419d9 IPVS: netns, use ... |
1553 |
if (!pd) |
2a3b791e6 IPVS: Add/adjust ... |
1554 |
return NF_ACCEPT; |
9330419d9 IPVS: netns, use ... |
1555 |
pp = pd->pp; |
2a3b791e6 IPVS: Add/adjust ... |
1556 |
|
63dca2c0b ipvs: Fix faulty ... |
1557 1558 |
/* Cannot handle fragmented embedded protocol */ if (ciph.fragoffs) |
2a3b791e6 IPVS: Add/adjust ... |
1559 |
return NF_ACCEPT; |
b0e010c52 ipvs: replace ip_... |
1560 |
IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset, |
0d79641a9 ipvs: provide add... |
1561 |
"Checking incoming ICMPv6 for"); |
2a3b791e6 IPVS: Add/adjust ... |
1562 |
|
2f74713d1 ipvs: Complete IP... |
1563 1564 1565 |
/* The embedded headers contain source and dest in reverse order * if not from localhost */ |
ab1619764 ipvs: Pass ipvs i... |
1566 |
cp = pp->conn_in_get(ipvs, AF_INET6, skb, &ciph); |
2f74713d1 ipvs: Complete IP... |
1567 |
|
6044eeffa ipvs: attempt to ... |
1568 1569 |
if (!cp) { int v; |
a47b43008 ipvs: Cache ipvs ... |
1570 |
if (!sysctl_schedule_icmp(ipvs)) |
6044eeffa ipvs: attempt to ... |
1571 |
return NF_ACCEPT; |
d8f44c335 ipvs: Pass ipvs i... |
1572 |
if (!ip_vs_try_to_schedule(ipvs, AF_INET6, skb, pd, &v, &cp, &ciph)) |
6044eeffa ipvs: attempt to ... |
1573 1574 1575 1576 |
return v; new_cp = true; } |
2f74713d1 ipvs: Complete IP... |
1577 1578 1579 |
/* VS/TUN, VS/DR and LOCALNODE just let it go */ if ((hooknum == NF_INET_LOCAL_OUT) && (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)) { |
6044eeffa ipvs: attempt to ... |
1580 1581 |
verdict = NF_ACCEPT; goto out; |
2f74713d1 ipvs: Complete IP... |
1582 |
} |
2a3b791e6 IPVS: Add/adjust ... |
1583 |
|
2a3b791e6 IPVS: Add/adjust ... |
1584 1585 |
/* do the statistics and put it back */ ip_vs_in_stats(cp, skb); |
63dca2c0b ipvs: Fix faulty ... |
1586 1587 |
/* Need to mangle contained IPv6 header in ICMPv6 packet */ |
b0e010c52 ipvs: replace ip_... |
1588 |
offset = ciph.len; |
63dca2c0b ipvs: Fix faulty ... |
1589 1590 |
if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol || IPPROTO_SCTP == ciph.protocol) |
b0e010c52 ipvs: replace ip_... |
1591 |
offset += 2 * sizeof(__u16); /* Also mangle ports */ |
63dca2c0b ipvs: Fix faulty ... |
1592 |
|
b0e010c52 ipvs: replace ip_... |
1593 |
verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum, &ciph); |
2a3b791e6 IPVS: Add/adjust ... |
1594 |
|
6044eeffa ipvs: attempt to ... |
1595 1596 1597 1598 1599 |
out: if (likely(!new_cp)) __ip_vs_conn_put(cp); else ip_vs_conn_put(cp); |
2a3b791e6 IPVS: Add/adjust ... |
1600 1601 1602 1603 |
return verdict; } #endif |
1da177e4c Linux-2.6.12-rc2 |
1604 1605 1606 1607 1608 |
/* * Check if it's for virtual services, look it up, * and send it on its way... */ static unsigned int |
6e385bb3e ipvs: Pass ipvs i... |
1609 |
ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int af) |
1da177e4c Linux-2.6.12-rc2 |
1610 |
{ |
51ef348b1 IPVS: Add 'af' ar... |
1611 |
struct ip_vs_iphdr iph; |
1da177e4c Linux-2.6.12-rc2 |
1612 |
struct ip_vs_protocol *pp; |
9330419d9 IPVS: netns, use ... |
1613 |
struct ip_vs_proto_data *pd; |
1da177e4c Linux-2.6.12-rc2 |
1614 |
struct ip_vs_conn *cp; |
4a516f110 ipvs: Remove unus... |
1615 |
int ret, pkts; |
d752c3645 ipvs: allow resch... |
1616 |
int conn_reuse_mode; |
2a3b791e6 IPVS: Add/adjust ... |
1617 |
|
fc6047676 ipvs: changes for... |
1618 1619 1620 |
/* Already marked as IPVS request or reply? */ if (skb->ipvs_property) return NF_ACCEPT; |
1da177e4c Linux-2.6.12-rc2 |
1621 |
/* |
cb59155f2 ipvs: changes for... |
1622 1623 1624 |
* Big tappo: * - remote client: only PACKET_HOST * - route: used for struct net when skb->dev is unset |
1da177e4c Linux-2.6.12-rc2 |
1625 |
*/ |
cb59155f2 ipvs: changes for... |
1626 1627 1628 |
if (unlikely((skb->pkt_type != PACKET_HOST && hooknum != NF_INET_LOCAL_OUT) || !skb_dst(skb))) { |
4fd9beef3 ipvs: Add hdr_fla... |
1629 |
ip_vs_fill_iph_skb(af, skb, false, &iph); |
cb59155f2 ipvs: changes for... |
1630 1631 1632 1633 1634 |
IP_VS_DBG_BUF(12, "packet type=%d proto=%d daddr=%s" " ignored in hook %u ", skb->pkt_type, iph.protocol, IP_VS_DBG_ADDR(af, &iph.daddr), hooknum); |
1da177e4c Linux-2.6.12-rc2 |
1635 1636 |
return NF_ACCEPT; } |
7a4f0761f IPVS: init and cl... |
1637 |
/* ipvs enabled in this netns ? */ |
0c12582fb ipvs: add backup_... |
1638 |
if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable)) |
7a4f0761f IPVS: init and cl... |
1639 |
return NF_ACCEPT; |
4fd9beef3 ipvs: Add hdr_fla... |
1640 |
ip_vs_fill_iph_skb(af, skb, false, &iph); |
cb59155f2 ipvs: changes for... |
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 |
/* Bad... Do not break raw sockets */ if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT && af == AF_INET)) { struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(skb->sk); if (inet && sk->sk_family == PF_INET && inet->nodefrag) return NF_ACCEPT; } |
1da177e4c Linux-2.6.12-rc2 |
1651 |
|
94b265514 IPVS: Add handlin... |
1652 1653 1654 |
#ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { |
1ca5bb545 ipvs: create ip_v... |
1655 |
int related; |
6f2bcea99 ipvs: Pass ipvs i... |
1656 1657 |
int verdict = ip_vs_in_icmp_v6(ipvs, skb, &related, hooknum, &iph); |
1da177e4c Linux-2.6.12-rc2 |
1658 |
|
94b265514 IPVS: Add handlin... |
1659 1660 |
if (related) return verdict; |
94b265514 IPVS: Add handlin... |
1661 1662 1663 1664 |
} } else #endif if (unlikely(iph.protocol == IPPROTO_ICMP)) { |
1ca5bb545 ipvs: create ip_v... |
1665 |
int related; |
6f2bcea99 ipvs: Pass ipvs i... |
1666 1667 |
int verdict = ip_vs_in_icmp(ipvs, skb, &related, hooknum); |
94b265514 IPVS: Add handlin... |
1668 1669 1670 |
if (related) return verdict; |
94b265514 IPVS: Add handlin... |
1671 |
} |
1da177e4c Linux-2.6.12-rc2 |
1672 1673 |
/* Protocol supported? */ |
18d6ade63 ipvs: Pass ipvs n... |
1674 |
pd = ip_vs_proto_data_get(ipvs, iph.protocol); |
4e478098a ipvs: add sysctl ... |
1675 1676 1677 1678 1679 1680 1681 |
if (unlikely(!pd)) { /* The only way we'll see this packet again is if it's * encapsulated, so mark it with ipvs_property=1 so we * skip it if we're ignoring tunneled packets */ if (sysctl_ignore_tunneled(ipvs)) skb->ipvs_property = 1; |
1da177e4c Linux-2.6.12-rc2 |
1682 |
return NF_ACCEPT; |
4e478098a ipvs: add sysctl ... |
1683 |
} |
9330419d9 IPVS: netns, use ... |
1684 |
pp = pd->pp; |
1da177e4c Linux-2.6.12-rc2 |
1685 1686 1687 |
/* * Check if the packet belongs to an existing connection entry */ |
ab1619764 ipvs: Pass ipvs i... |
1688 |
cp = pp->conn_in_get(ipvs, af, skb, &iph); |
dc7b3eb90 ipvs: Fix reuse c... |
1689 |
|
d752c3645 ipvs: allow resch... |
1690 1691 1692 1693 1694 1695 1696 1697 |
conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp && ((unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && unlikely(!atomic_read(&cp->dest->weight))) || unlikely(is_new_conn_expected(cp, conn_reuse_mode)))) { if (!atomic_read(&cp->n_control)) ip_vs_conn_expire_now(cp); |
dc7b3eb90 ipvs: Fix reuse c... |
1698 1699 1700 |
__ip_vs_conn_put(cp); cp = NULL; } |
3b5ca6176 ipvs: pull out ip... |
1701 |
if (unlikely(!cp)) { |
1da177e4c Linux-2.6.12-rc2 |
1702 |
int v; |
d8f44c335 ipvs: Pass ipvs i... |
1703 |
if (!ip_vs_try_to_schedule(ipvs, af, skb, pd, &v, &cp, &iph)) |
1da177e4c Linux-2.6.12-rc2 |
1704 1705 |
return v; } |
b0e010c52 ipvs: replace ip_... |
1706 |
IP_VS_DBG_PKT(11, af, pp, skb, iph.off, "Incoming packet"); |
3b5ca6176 ipvs: pull out ip... |
1707 |
|
1da177e4c Linux-2.6.12-rc2 |
1708 1709 1710 |
/* Check the server status */ if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { /* the destination server is not available */ |
71a8ab6ca IPVS: Add sysctl_... |
1711 |
if (sysctl_expire_nodest_conn(ipvs)) { |
1da177e4c Linux-2.6.12-rc2 |
1712 1713 |
/* try to expire the connection immediately */ ip_vs_conn_expire_now(cp); |
1da177e4c Linux-2.6.12-rc2 |
1714 |
} |
dc8103f25 [IPVS]: fix conne... |
1715 1716 1717 |
/* don't restart its timer, and silently drop the packet. */ __ip_vs_conn_put(cp); |
1da177e4c Linux-2.6.12-rc2 |
1718 1719 1720 1721 |
return NF_DROP; } ip_vs_in_stats(cp, skb); |
4a516f110 ipvs: Remove unus... |
1722 |
ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd); |
1da177e4c Linux-2.6.12-rc2 |
1723 |
if (cp->packet_xmit) |
d4383f04d ipvs: API change ... |
1724 |
ret = cp->packet_xmit(skb, cp, pp, &iph); |
1da177e4c Linux-2.6.12-rc2 |
1725 1726 1727 1728 1729 |
/* do not touch skb anymore */ else { IP_VS_DBG_RL("warning: packet_xmit is null"); ret = NF_ACCEPT; } |
efac52762 [IPVS]: Synchroni... |
1730 1731 1732 1733 1734 |
/* Increase its packet counter and check if it is needed * to be synchronized * * Sync connection if it is about to close to * encorage the standby servers to update the connections timeout |
986a07579 IPVS: Backup, Cha... |
1735 1736 |
* * For ONE_PKT let ip_vs_sync_conn() do the filter work. |
efac52762 [IPVS]: Synchroni... |
1737 |
*/ |
f131315fa IPVS: netns aware... |
1738 |
|
986a07579 IPVS: Backup, Cha... |
1739 |
if (cp->flags & IP_VS_CONN_F_ONE_PACKET) |
59e0350ea IPVS: Add {sysctl... |
1740 |
pkts = sysctl_sync_threshold(ipvs); |
986a07579 IPVS: Backup, Cha... |
1741 1742 |
else pkts = atomic_add_return(1, &cp->in_pkts); |
749c42b62 ipvs: reduce sync... |
1743 |
if (ipvs->sync_state & IP_VS_STATE_MASTER) |
b61a8c1a4 ipvs: Pass ipvs n... |
1744 |
ip_vs_sync_conn(ipvs, cp, pkts); |
1da177e4c Linux-2.6.12-rc2 |
1745 1746 1747 1748 |
ip_vs_conn_put(cp); return ret; } |
cb59155f2 ipvs: changes for... |
1749 1750 1751 1752 1753 |
/* * AF_INET handler in NF_INET_LOCAL_IN chain * Schedule and forward packets from remote clients */ static unsigned int |
06198b34a netfilter: Pass p... |
1754 |
ip_vs_remote_request4(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1755 |
const struct nf_hook_state *state) |
cb59155f2 ipvs: changes for... |
1756 |
{ |
6e385bb3e ipvs: Pass ipvs i... |
1757 |
return ip_vs_in(net_ipvs(state->net), state->hook, skb, AF_INET); |
cb59155f2 ipvs: changes for... |
1758 1759 1760 1761 1762 1763 1764 |
} /* * AF_INET handler in NF_INET_LOCAL_OUT chain * Schedule and forward packets from local clients */ static unsigned int |
06198b34a netfilter: Pass p... |
1765 |
ip_vs_local_request4(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1766 |
const struct nf_hook_state *state) |
cb59155f2 ipvs: changes for... |
1767 |
{ |
6e385bb3e ipvs: Pass ipvs i... |
1768 |
return ip_vs_in(net_ipvs(state->net), state->hook, skb, AF_INET); |
cb59155f2 ipvs: changes for... |
1769 1770 1771 1772 1773 1774 1775 1776 1777 |
} #ifdef CONFIG_IP_VS_IPV6 /* * AF_INET6 handler in NF_INET_LOCAL_IN chain * Schedule and forward packets from remote clients */ static unsigned int |
06198b34a netfilter: Pass p... |
1778 |
ip_vs_remote_request6(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1779 |
const struct nf_hook_state *state) |
cb59155f2 ipvs: changes for... |
1780 |
{ |
6e385bb3e ipvs: Pass ipvs i... |
1781 |
return ip_vs_in(net_ipvs(state->net), state->hook, skb, AF_INET6); |
cb59155f2 ipvs: changes for... |
1782 1783 1784 1785 1786 1787 1788 |
} /* * AF_INET6 handler in NF_INET_LOCAL_OUT chain * Schedule and forward packets from local clients */ static unsigned int |
06198b34a netfilter: Pass p... |
1789 |
ip_vs_local_request6(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1790 |
const struct nf_hook_state *state) |
cb59155f2 ipvs: changes for... |
1791 |
{ |
6e385bb3e ipvs: Pass ipvs i... |
1792 |
return ip_vs_in(net_ipvs(state->net), state->hook, skb, AF_INET6); |
cb59155f2 ipvs: changes for... |
1793 1794 1795 |
} #endif |
1da177e4c Linux-2.6.12-rc2 |
1796 1797 |
/* |
6e23ae2a4 [NETFILTER]: Intr... |
1798 |
* It is hooked at the NF_INET_FORWARD chain, in order to catch ICMP |
1da177e4c Linux-2.6.12-rc2 |
1799 1800 1801 1802 |
* related packets destined for 0.0.0.0/0. * When fwmark-based virtual service is used, such as transparent * cache cluster, TCP packets can be marked and routed to ip_vs_in, * but ICMP destined for 0.0.0.0/0 cannot not be easily marked and |
6e23ae2a4 [NETFILTER]: Intr... |
1803 |
* sent to ip_vs_in_icmp. So, catch them at the NF_INET_FORWARD chain |
1da177e4c Linux-2.6.12-rc2 |
1804 1805 1806 |
* and send them to ip_vs_in_icmp. */ static unsigned int |
06198b34a netfilter: Pass p... |
1807 |
ip_vs_forward_icmp(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1808 |
const struct nf_hook_state *state) |
1da177e4c Linux-2.6.12-rc2 |
1809 1810 |
{ int r; |
6f2bcea99 ipvs: Pass ipvs i... |
1811 |
struct netns_ipvs *ipvs = net_ipvs(state->net); |
1da177e4c Linux-2.6.12-rc2 |
1812 |
|
3db05fea5 [NETFILTER]: Repl... |
1813 |
if (ip_hdr(skb)->protocol != IPPROTO_ICMP) |
1da177e4c Linux-2.6.12-rc2 |
1814 |
return NF_ACCEPT; |
7a4f0761f IPVS: init and cl... |
1815 |
/* ipvs enabled in this netns ? */ |
0c12582fb ipvs: add backup_... |
1816 |
if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable)) |
7a4f0761f IPVS: init and cl... |
1817 |
return NF_ACCEPT; |
6f2bcea99 ipvs: Pass ipvs i... |
1818 |
return ip_vs_in_icmp(ipvs, skb, &r, state->hook); |
1da177e4c Linux-2.6.12-rc2 |
1819 |
} |
2a3b791e6 IPVS: Add/adjust ... |
1820 1821 |
#ifdef CONFIG_IP_VS_IPV6 static unsigned int |
06198b34a netfilter: Pass p... |
1822 |
ip_vs_forward_icmp_v6(void *priv, struct sk_buff *skb, |
238e54c9c netfilter: Make n... |
1823 |
const struct nf_hook_state *state) |
2a3b791e6 IPVS: Add/adjust ... |
1824 1825 |
{ int r; |
6f2bcea99 ipvs: Pass ipvs i... |
1826 |
struct netns_ipvs *ipvs = net_ipvs(state->net); |
63dca2c0b ipvs: Fix faulty ... |
1827 |
struct ip_vs_iphdr iphdr; |
2a3b791e6 IPVS: Add/adjust ... |
1828 |
|
4fd9beef3 ipvs: Add hdr_fla... |
1829 |
ip_vs_fill_iph_skb(AF_INET6, skb, false, &iphdr); |
63dca2c0b ipvs: Fix faulty ... |
1830 |
if (iphdr.protocol != IPPROTO_ICMPV6) |
2a3b791e6 IPVS: Add/adjust ... |
1831 |
return NF_ACCEPT; |
7a4f0761f IPVS: init and cl... |
1832 |
/* ipvs enabled in this netns ? */ |
0c12582fb ipvs: add backup_... |
1833 |
if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable)) |
7a4f0761f IPVS: init and cl... |
1834 |
return NF_ACCEPT; |
6f2bcea99 ipvs: Pass ipvs i... |
1835 |
return ip_vs_in_icmp_v6(ipvs, skb, &r, state->hook, &iphdr); |
2a3b791e6 IPVS: Add/adjust ... |
1836 1837 |
} #endif |
1da177e4c Linux-2.6.12-rc2 |
1838 |
|
1999414a4 [NETFILTER]: Mark... |
1839 |
static struct nf_hook_ops ip_vs_ops[] __read_mostly = { |
cb59155f2 ipvs: changes for... |
1840 1841 1842 1843 |
/* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply4, .owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1844 |
.pf = NFPROTO_IPV4, |
cb59155f2 ipvs: changes for... |
1845 |
.hooknum = NF_INET_LOCAL_IN, |
afb523c54 ipvs: restore sup... |
1846 |
.priority = NF_IP_PRI_NAT_SRC - 2, |
cb59155f2 ipvs: changes for... |
1847 |
}, |
41c5b3170 [NETFILTER]: Use ... |
1848 1849 1850 1851 |
/* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be * applied to IPVS. */ { |
cb59155f2 ipvs: changes for... |
1852 |
.hook = ip_vs_remote_request4, |
41c5b3170 [NETFILTER]: Use ... |
1853 |
.owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1854 |
.pf = NFPROTO_IPV4, |
cb59155f2 ipvs: changes for... |
1855 |
.hooknum = NF_INET_LOCAL_IN, |
afb523c54 ipvs: restore sup... |
1856 |
.priority = NF_IP_PRI_NAT_SRC - 1, |
41c5b3170 [NETFILTER]: Use ... |
1857 |
}, |
fc6047676 ipvs: changes for... |
1858 |
/* Before ip_vs_in, change source only for VS/NAT */ |
41c5b3170 [NETFILTER]: Use ... |
1859 |
{ |
fc6047676 ipvs: changes for... |
1860 |
.hook = ip_vs_local_reply4, |
41c5b3170 [NETFILTER]: Use ... |
1861 |
.owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1862 |
.pf = NFPROTO_IPV4, |
fc6047676 ipvs: changes for... |
1863 |
.hooknum = NF_INET_LOCAL_OUT, |
afb523c54 ipvs: restore sup... |
1864 |
.priority = NF_IP_PRI_NAT_DST + 1, |
41c5b3170 [NETFILTER]: Use ... |
1865 |
}, |
cb59155f2 ipvs: changes for... |
1866 1867 1868 1869 |
/* After mangle, schedule and forward local requests */ { .hook = ip_vs_local_request4, .owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1870 |
.pf = NFPROTO_IPV4, |
cb59155f2 ipvs: changes for... |
1871 |
.hooknum = NF_INET_LOCAL_OUT, |
afb523c54 ipvs: restore sup... |
1872 |
.priority = NF_IP_PRI_NAT_DST + 2, |
cb59155f2 ipvs: changes for... |
1873 |
}, |
41c5b3170 [NETFILTER]: Use ... |
1874 1875 1876 1877 1878 |
/* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ { .hook = ip_vs_forward_icmp, .owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1879 |
.pf = NFPROTO_IPV4, |
cb59155f2 ipvs: changes for... |
1880 1881 |
.hooknum = NF_INET_FORWARD, .priority = 99, |
41c5b3170 [NETFILTER]: Use ... |
1882 |
}, |
fc6047676 ipvs: changes for... |
1883 1884 1885 1886 |
/* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply4, .owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1887 |
.pf = NFPROTO_IPV4, |
fc6047676 ipvs: changes for... |
1888 1889 1890 |
.hooknum = NF_INET_FORWARD, .priority = 100, }, |
473b23d37 IPVS: Activate IP... |
1891 |
#ifdef CONFIG_IP_VS_IPV6 |
cb59155f2 ipvs: changes for... |
1892 1893 1894 1895 |
/* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply6, .owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1896 |
.pf = NFPROTO_IPV6, |
cb59155f2 ipvs: changes for... |
1897 |
.hooknum = NF_INET_LOCAL_IN, |
afb523c54 ipvs: restore sup... |
1898 |
.priority = NF_IP6_PRI_NAT_SRC - 2, |
cb59155f2 ipvs: changes for... |
1899 |
}, |
473b23d37 IPVS: Activate IP... |
1900 1901 1902 1903 |
/* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be * applied to IPVS. */ { |
cb59155f2 ipvs: changes for... |
1904 |
.hook = ip_vs_remote_request6, |
473b23d37 IPVS: Activate IP... |
1905 |
.owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1906 |
.pf = NFPROTO_IPV6, |
cb59155f2 ipvs: changes for... |
1907 |
.hooknum = NF_INET_LOCAL_IN, |
afb523c54 ipvs: restore sup... |
1908 |
.priority = NF_IP6_PRI_NAT_SRC - 1, |
473b23d37 IPVS: Activate IP... |
1909 |
}, |
fc6047676 ipvs: changes for... |
1910 |
/* Before ip_vs_in, change source only for VS/NAT */ |
473b23d37 IPVS: Activate IP... |
1911 |
{ |
fc6047676 ipvs: changes for... |
1912 |
.hook = ip_vs_local_reply6, |
473b23d37 IPVS: Activate IP... |
1913 |
.owner = THIS_MODULE, |
eb90b0c73 ipvs: fix ipv6 ho... |
1914 |
.pf = NFPROTO_IPV6, |
fc6047676 ipvs: changes for... |
1915 |
.hooknum = NF_INET_LOCAL_OUT, |
afb523c54 ipvs: restore sup... |
1916 |
.priority = NF_IP6_PRI_NAT_DST + 1, |
473b23d37 IPVS: Activate IP... |
1917 |
}, |
cb59155f2 ipvs: changes for... |
1918 1919 1920 1921 |
/* After mangle, schedule and forward local requests */ { .hook = ip_vs_local_request6, .owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1922 |
.pf = NFPROTO_IPV6, |
cb59155f2 ipvs: changes for... |
1923 |
.hooknum = NF_INET_LOCAL_OUT, |
afb523c54 ipvs: restore sup... |
1924 |
.priority = NF_IP6_PRI_NAT_DST + 2, |
cb59155f2 ipvs: changes for... |
1925 |
}, |
473b23d37 IPVS: Activate IP... |
1926 1927 1928 1929 1930 |
/* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ { .hook = ip_vs_forward_icmp_v6, .owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1931 |
.pf = NFPROTO_IPV6, |
cb59155f2 ipvs: changes for... |
1932 1933 |
.hooknum = NF_INET_FORWARD, .priority = 99, |
473b23d37 IPVS: Activate IP... |
1934 |
}, |
fc6047676 ipvs: changes for... |
1935 1936 1937 1938 |
/* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply6, .owner = THIS_MODULE, |
4c809d630 netfilter: ipvs: ... |
1939 |
.pf = NFPROTO_IPV6, |
fc6047676 ipvs: changes for... |
1940 1941 1942 |
.hooknum = NF_INET_FORWARD, .priority = 100, }, |
473b23d37 IPVS: Activate IP... |
1943 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
1944 |
}; |
61b1ab458 IPVS: netns, add ... |
1945 1946 1947 1948 1949 1950 |
/* * Initialize IP Virtual Server netns mem. */ static int __net_init __ip_vs_init(struct net *net) { struct netns_ipvs *ipvs; |
61b1ab458 IPVS: netns, add ... |
1951 |
ipvs = net_generic(net, ip_vs_net_id); |
0a9ee8134 netfilter: Remove... |
1952 |
if (ipvs == NULL) |
61b1ab458 IPVS: netns, add ... |
1953 |
return -ENOMEM; |
0a9ee8134 netfilter: Remove... |
1954 |
|
7a4f0761f IPVS: init and cl... |
1955 1956 |
/* Hold the beast until a service is registerd */ ipvs->enable = 0; |
f6340ee0c IPVS: netns, defe... |
1957 |
ipvs->net = net; |
61b1ab458 IPVS: netns, add ... |
1958 1959 1960 1961 |
/* Counters used for creating unique names */ ipvs->gen = atomic_read(&ipvs_netns_cnt); atomic_inc(&ipvs_netns_cnt); net->ipvs = ipvs; |
7a4f0761f IPVS: init and cl... |
1962 |
|
a4dd0360c ipvs: Pass ipvs n... |
1963 |
if (ip_vs_estimator_net_init(ipvs) < 0) |
7a4f0761f IPVS: init and cl... |
1964 |
goto estimator_fail; |
3d9937668 ipvs: Pass ipvs n... |
1965 |
if (ip_vs_control_net_init(ipvs) < 0) |
7a4f0761f IPVS: init and cl... |
1966 |
goto control_fail; |
503cf15a5 IPVS: rename of n... |
1967 |
if (ip_vs_protocol_net_init(net) < 0) |
7a4f0761f IPVS: init and cl... |
1968 |
goto protocol_fail; |
b5dd212cc ipvs: Pass ipvs n... |
1969 |
if (ip_vs_app_net_init(ipvs) < 0) |
7a4f0761f IPVS: init and cl... |
1970 |
goto app_fail; |
2f3edc6a5 ipvs: Pass ipvs n... |
1971 |
if (ip_vs_conn_net_init(ipvs) < 0) |
7a4f0761f IPVS: init and cl... |
1972 |
goto conn_fail; |
802cb4370 ipvs: Pass ipvs n... |
1973 |
if (ip_vs_sync_net_init(ipvs) < 0) |
7a4f0761f IPVS: init and cl... |
1974 |
goto sync_fail; |
a870c8c5c IPVS: use z modif... |
1975 1976 |
printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d ", |
61b1ab458 IPVS: netns, add ... |
1977 1978 |
sizeof(struct netns_ipvs), ipvs->gen); return 0; |
7a4f0761f IPVS: init and cl... |
1979 1980 1981 1982 1983 |
/* * Error handling */ sync_fail: |
2f3edc6a5 ipvs: Pass ipvs n... |
1984 |
ip_vs_conn_net_cleanup(ipvs); |
7a4f0761f IPVS: init and cl... |
1985 |
conn_fail: |
b5dd212cc ipvs: Pass ipvs n... |
1986 |
ip_vs_app_net_cleanup(ipvs); |
7a4f0761f IPVS: init and cl... |
1987 |
app_fail: |
503cf15a5 IPVS: rename of n... |
1988 |
ip_vs_protocol_net_cleanup(net); |
7a4f0761f IPVS: init and cl... |
1989 |
protocol_fail: |
3d9937668 ipvs: Pass ipvs n... |
1990 |
ip_vs_control_net_cleanup(ipvs); |
7a4f0761f IPVS: init and cl... |
1991 |
control_fail: |
a4dd0360c ipvs: Pass ipvs n... |
1992 |
ip_vs_estimator_net_cleanup(ipvs); |
7a4f0761f IPVS: init and cl... |
1993 |
estimator_fail: |
39f618b4f ipvs: reset ipvs ... |
1994 |
net->ipvs = NULL; |
7a4f0761f IPVS: init and cl... |
1995 |
return -ENOMEM; |
61b1ab458 IPVS: netns, add ... |
1996 1997 1998 1999 |
} static void __net_exit __ip_vs_cleanup(struct net *net) { |
56d2169b7 ipvs: Pass ipvs n... |
2000 2001 2002 |
struct netns_ipvs *ipvs = net_ipvs(net); ip_vs_service_net_cleanup(ipvs); /* ip_vs_flush() with locks */ |
2f3edc6a5 ipvs: Pass ipvs n... |
2003 |
ip_vs_conn_net_cleanup(ipvs); |
b5dd212cc ipvs: Pass ipvs n... |
2004 |
ip_vs_app_net_cleanup(ipvs); |
503cf15a5 IPVS: rename of n... |
2005 |
ip_vs_protocol_net_cleanup(net); |
3d9937668 ipvs: Pass ipvs n... |
2006 |
ip_vs_control_net_cleanup(ipvs); |
a4dd0360c ipvs: Pass ipvs n... |
2007 |
ip_vs_estimator_net_cleanup(ipvs); |
56d2169b7 ipvs: Pass ipvs n... |
2008 2009 |
IP_VS_DBG(2, "ipvs netns %d released ", ipvs->gen); |
39f618b4f ipvs: reset ipvs ... |
2010 |
net->ipvs = NULL; |
61b1ab458 IPVS: netns, add ... |
2011 |
} |
7a4f0761f IPVS: init and cl... |
2012 2013 |
static void __net_exit __ip_vs_dev_cleanup(struct net *net) { |
ebea1f7c0 ipvs: Pass ipvs n... |
2014 |
struct netns_ipvs *ipvs = net_ipvs(net); |
7a4f0761f IPVS: init and cl... |
2015 |
EnterFunction(2); |
ebea1f7c0 ipvs: Pass ipvs n... |
2016 |
ipvs->enable = 0; /* Disable packet reception */ |
8f4e0a186 IPVS netns exit c... |
2017 |
smp_wmb(); |
ebea1f7c0 ipvs: Pass ipvs n... |
2018 |
ip_vs_sync_net_cleanup(ipvs); |
7a4f0761f IPVS: init and cl... |
2019 2020 |
LeaveFunction(2); } |
61b1ab458 IPVS: netns, add ... |
2021 2022 2023 2024 2025 2026 |
static struct pernet_operations ipvs_core_ops = { .init = __ip_vs_init, .exit = __ip_vs_cleanup, .id = &ip_vs_net_id, .size = sizeof(struct netns_ipvs), }; |
1da177e4c Linux-2.6.12-rc2 |
2027 |
|
7a4f0761f IPVS: init and cl... |
2028 2029 2030 |
static struct pernet_operations ipvs_core_dev_ops = { .exit = __ip_vs_dev_cleanup, }; |
1da177e4c Linux-2.6.12-rc2 |
2031 2032 2033 2034 2035 2036 2037 2038 2039 |
/* * Initialize IP Virtual Server */ static int __init ip_vs_init(void) { int ret; ret = ip_vs_control_init(); if (ret < 0) { |
1e3e238e9 IPVS: use pr_err ... |
2040 2041 |
pr_err("can't setup control. "); |
6c8f79499 IPVS: remove unus... |
2042 |
goto exit; |
1da177e4c Linux-2.6.12-rc2 |
2043 2044 2045 |
} ip_vs_protocol_init(); |
1da177e4c Linux-2.6.12-rc2 |
2046 2047 |
ret = ip_vs_conn_init(); if (ret < 0) { |
1e3e238e9 IPVS: use pr_err ... |
2048 2049 |
pr_err("can't setup connection table. "); |
6c8f79499 IPVS: remove unus... |
2050 |
goto cleanup_protocol; |
61b1ab458 IPVS: netns, add ... |
2051 |
} |
7a4f0761f IPVS: init and cl... |
2052 2053 |
ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ if (ret < 0) |
6c8f79499 IPVS: remove unus... |
2054 |
goto cleanup_conn; |
7a4f0761f IPVS: init and cl... |
2055 2056 2057 2058 |
ret = register_pernet_device(&ipvs_core_dev_ops); if (ret < 0) goto cleanup_sub; |
41c5b3170 [NETFILTER]: Use ... |
2059 |
ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
1da177e4c Linux-2.6.12-rc2 |
2060 |
if (ret < 0) { |
1e3e238e9 IPVS: use pr_err ... |
2061 2062 |
pr_err("can't register hooks. "); |
7a4f0761f IPVS: init and cl... |
2063 |
goto cleanup_dev; |
1da177e4c Linux-2.6.12-rc2 |
2064 |
} |
8537de8a7 ipvs: kernel oops... |
2065 2066 2067 2068 2069 2070 |
ret = ip_vs_register_nl_ioctl(); if (ret < 0) { pr_err("can't register netlink/ioctl. "); goto cleanup_hooks; } |
1e3e238e9 IPVS: use pr_err ... |
2071 2072 |
pr_info("ipvs loaded. "); |
7a4f0761f IPVS: init and cl... |
2073 |
|
1da177e4c Linux-2.6.12-rc2 |
2074 |
return ret; |
8537de8a7 ipvs: kernel oops... |
2075 2076 |
cleanup_hooks: nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
7a4f0761f IPVS: init and cl... |
2077 2078 2079 2080 |
cleanup_dev: unregister_pernet_device(&ipvs_core_dev_ops); cleanup_sub: unregister_pernet_subsys(&ipvs_core_ops); |
552ad65aa IPVS: labels at p... |
2081 |
cleanup_conn: |
1da177e4c Linux-2.6.12-rc2 |
2082 |
ip_vs_conn_cleanup(); |
552ad65aa IPVS: labels at p... |
2083 |
cleanup_protocol: |
1da177e4c Linux-2.6.12-rc2 |
2084 2085 |
ip_vs_protocol_cleanup(); ip_vs_control_cleanup(); |
6c8f79499 IPVS: remove unus... |
2086 |
exit: |
1da177e4c Linux-2.6.12-rc2 |
2087 2088 2089 2090 2091 |
return ret; } static void __exit ip_vs_cleanup(void) { |
8537de8a7 ipvs: kernel oops... |
2092 |
ip_vs_unregister_nl_ioctl(); |
41c5b3170 [NETFILTER]: Use ... |
2093 |
nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
7a4f0761f IPVS: init and cl... |
2094 2095 |
unregister_pernet_device(&ipvs_core_dev_ops); unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ |
1da177e4c Linux-2.6.12-rc2 |
2096 |
ip_vs_conn_cleanup(); |
1da177e4c Linux-2.6.12-rc2 |
2097 2098 |
ip_vs_protocol_cleanup(); ip_vs_control_cleanup(); |
1e3e238e9 IPVS: use pr_err ... |
2099 2100 |
pr_info("ipvs unloaded. "); |
1da177e4c Linux-2.6.12-rc2 |
2101 2102 2103 2104 2105 |
} module_init(ip_vs_init); module_exit(ip_vs_cleanup); MODULE_LICENSE("GPL"); |