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