1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include <linux/module.h>
30#include <linux/kernel.h>
31#include <linux/ip.h>
32#include <linux/tcp.h>
33#include <linux/icmp.h>
34
35#include <net/ip.h>
36#include <net/tcp.h>
37#include <net/udp.h>
38#include <net/icmp.h>
39#include <net/route.h>
40
41#include <linux/netfilter.h>
42#include <linux/netfilter_ipv4.h>
43
44#include <net/ip_vs.h>
45
46
47EXPORT_SYMBOL(register_ip_vs_scheduler);
48EXPORT_SYMBOL(unregister_ip_vs_scheduler);
49EXPORT_SYMBOL(ip_vs_skb_replace);
50EXPORT_SYMBOL(ip_vs_proto_name);
51EXPORT_SYMBOL(ip_vs_conn_new);
52EXPORT_SYMBOL(ip_vs_conn_in_get);
53EXPORT_SYMBOL(ip_vs_conn_out_get);
54#ifdef CONFIG_IP_VS_PROTO_TCP
55EXPORT_SYMBOL(ip_vs_tcp_conn_listen);
56#endif
57EXPORT_SYMBOL(ip_vs_conn_put);
58#ifdef CONFIG_IP_VS_DEBUG
59EXPORT_SYMBOL(ip_vs_get_debug_level);
60#endif
61
62
63
64#define icmp_id(icmph) (((icmph)->un).echo.id)
65
66const char *ip_vs_proto_name(unsigned proto)
67{
68 static char buf[20];
69
70 switch (proto) {
71 case IPPROTO_IP:
72 return "IP";
73 case IPPROTO_UDP:
74 return "UDP";
75 case IPPROTO_TCP:
76 return "TCP";
77 case IPPROTO_ICMP:
78 return "ICMP";
79 default:
80 sprintf(buf, "IP_%d", proto);
81 return buf;
82 }
83}
84
85void ip_vs_init_hash_table(struct list_head *table, int rows)
86{
87 while (--rows >= 0)
88 INIT_LIST_HEAD(&table[rows]);
89}
90
91static inline void
92ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
93{
94 struct ip_vs_dest *dest = cp->dest;
95 if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
96 spin_lock(&dest->stats.lock);
97 dest->stats.inpkts++;
98 dest->stats.inbytes += skb->len;
99 spin_unlock(&dest->stats.lock);
100
101 spin_lock(&dest->svc->stats.lock);
102 dest->svc->stats.inpkts++;
103 dest->svc->stats.inbytes += skb->len;
104 spin_unlock(&dest->svc->stats.lock);
105
106 spin_lock(&ip_vs_stats.lock);
107 ip_vs_stats.inpkts++;
108 ip_vs_stats.inbytes += skb->len;
109 spin_unlock(&ip_vs_stats.lock);
110 }
111}
112
113
114static inline void
115ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
116{
117 struct ip_vs_dest *dest = cp->dest;
118 if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
119 spin_lock(&dest->stats.lock);
120 dest->stats.outpkts++;
121 dest->stats.outbytes += skb->len;
122 spin_unlock(&dest->stats.lock);
123
124 spin_lock(&dest->svc->stats.lock);
125 dest->svc->stats.outpkts++;
126 dest->svc->stats.outbytes += skb->len;
127 spin_unlock(&dest->svc->stats.lock);
128
129 spin_lock(&ip_vs_stats.lock);
130 ip_vs_stats.outpkts++;
131 ip_vs_stats.outbytes += skb->len;
132 spin_unlock(&ip_vs_stats.lock);
133 }
134}
135
136
137static inline void
138ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
139{
140 spin_lock(&cp->dest->stats.lock);
141 cp->dest->stats.conns++;
142 spin_unlock(&cp->dest->stats.lock);
143
144 spin_lock(&svc->stats.lock);
145 svc->stats.conns++;
146 spin_unlock(&svc->stats.lock);
147
148 spin_lock(&ip_vs_stats.lock);
149 ip_vs_stats.conns++;
150 spin_unlock(&ip_vs_stats.lock);
151}
152
153
154static inline int
155ip_vs_set_state(struct ip_vs_conn *cp, int direction,
156 const struct sk_buff *skb,
157 struct ip_vs_protocol *pp)
158{
159 if (unlikely(!pp->state_transition))
160 return 0;
161 return pp->state_transition(cp, direction, skb, pp);
162}
163
164
165
166
167
168
169
170
171
172static struct ip_vs_conn *
173ip_vs_sched_persist(struct ip_vs_service *svc,
174 const struct sk_buff *skb,
175 __be16 ports[2])
176{
177 struct ip_vs_conn *cp = NULL;
178 struct iphdr *iph = ip_hdr(skb);
179 struct ip_vs_dest *dest;
180 struct ip_vs_conn *ct;
181 __be16 dport;
182 __be32 snet;
183
184
185 snet = iph->saddr & svc->netmask;
186
187 IP_VS_DBG(6, "p-schedule: src %u.%u.%u.%u:%u dest %u.%u.%u.%u:%u "
188 "mnet %u.%u.%u.%u\n",
189 NIPQUAD(iph->saddr), ntohs(ports[0]),
190 NIPQUAD(iph->daddr), ntohs(ports[1]),
191 NIPQUAD(snet));
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206 if (ports[1] == svc->port) {
207
208 if (svc->port != FTPPORT)
209 ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
210 iph->daddr, ports[1]);
211 else
212 ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
213 iph->daddr, 0);
214
215 if (!ct || !ip_vs_check_template(ct)) {
216
217
218
219
220 dest = svc->scheduler->schedule(svc, skb);
221 if (dest == NULL) {
222 IP_VS_DBG(1, "p-schedule: no dest found.\n");
223 return NULL;
224 }
225
226
227
228
229
230
231
232 if (svc->port != FTPPORT)
233 ct = ip_vs_conn_new(iph->protocol,
234 snet, 0,
235 iph->daddr,
236 ports[1],
237 dest->addr, dest->port,
238 IP_VS_CONN_F_TEMPLATE,
239 dest);
240 else
241 ct = ip_vs_conn_new(iph->protocol,
242 snet, 0,
243 iph->daddr, 0,
244 dest->addr, 0,
245 IP_VS_CONN_F_TEMPLATE,
246 dest);
247 if (ct == NULL)
248 return NULL;
249
250 ct->timeout = svc->timeout;
251 } else {
252
253 dest = ct->dest;
254 }
255 dport = dest->port;
256 } else {
257
258
259
260
261
262
263 if (svc->fwmark)
264 ct = ip_vs_ct_in_get(IPPROTO_IP, snet, 0,
265 htonl(svc->fwmark), 0);
266 else
267 ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
268 iph->daddr, 0);
269
270 if (!ct || !ip_vs_check_template(ct)) {
271
272
273
274
275 if (svc->port)
276 return NULL;
277
278 dest = svc->scheduler->schedule(svc, skb);
279 if (dest == NULL) {
280 IP_VS_DBG(1, "p-schedule: no dest found.\n");
281 return NULL;
282 }
283
284
285
286
287 if (svc->fwmark)
288 ct = ip_vs_conn_new(IPPROTO_IP,
289 snet, 0,
290 htonl(svc->fwmark), 0,
291 dest->addr, 0,
292 IP_VS_CONN_F_TEMPLATE,
293 dest);
294 else
295 ct = ip_vs_conn_new(iph->protocol,
296 snet, 0,
297 iph->daddr, 0,
298 dest->addr, 0,
299 IP_VS_CONN_F_TEMPLATE,
300 dest);
301 if (ct == NULL)
302 return NULL;
303
304 ct->timeout = svc->timeout;
305 } else {
306
307 dest = ct->dest;
308 }
309 dport = ports[1];
310 }
311
312
313
314
315 cp = ip_vs_conn_new(iph->protocol,
316 iph->saddr, ports[0],
317 iph->daddr, ports[1],
318 dest->addr, dport,
319 0,
320 dest);
321 if (cp == NULL) {
322 ip_vs_conn_put(ct);
323 return NULL;
324 }
325
326
327
328
329 ip_vs_control_add(cp, ct);
330 ip_vs_conn_put(ct);
331
332 ip_vs_conn_stats(cp, svc);
333 return cp;
334}
335
336
337
338
339
340
341
342
343struct ip_vs_conn *
344ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
345{
346 struct ip_vs_conn *cp = NULL;
347 struct iphdr *iph = ip_hdr(skb);
348 struct ip_vs_dest *dest;
349 __be16 _ports[2], *pptr;
350
351 pptr = skb_header_pointer(skb, iph->ihl*4,
352 sizeof(_ports), _ports);
353 if (pptr == NULL)
354 return NULL;
355
356
357
358
359 if (svc->flags & IP_VS_SVC_F_PERSISTENT)
360 return ip_vs_sched_persist(svc, skb, pptr);
361
362
363
364
365 if (!svc->fwmark && pptr[1] != svc->port) {
366 if (!svc->port)
367 IP_VS_ERR("Schedule: port zero only supported "
368 "in persistent services, "
369 "check your ipvs configuration\n");
370 return NULL;
371 }
372
373 dest = svc->scheduler->schedule(svc, skb);
374 if (dest == NULL) {
375 IP_VS_DBG(1, "Schedule: no dest found.\n");
376 return NULL;
377 }
378
379
380
381
382 cp = ip_vs_conn_new(iph->protocol,
383 iph->saddr, pptr[0],
384 iph->daddr, pptr[1],
385 dest->addr, dest->port?dest->port:pptr[1],
386 0,
387 dest);
388 if (cp == NULL)
389 return NULL;
390
391 IP_VS_DBG(6, "Schedule fwd:%c c:%u.%u.%u.%u:%u v:%u.%u.%u.%u:%u "
392 "d:%u.%u.%u.%u:%u conn->flags:%X conn->refcnt:%d\n",
393 ip_vs_fwd_tag(cp),
394 NIPQUAD(cp->caddr), ntohs(cp->cport),
395 NIPQUAD(cp->vaddr), ntohs(cp->vport),
396 NIPQUAD(cp->daddr), ntohs(cp->dport),
397 cp->flags, atomic_read(&cp->refcnt));
398
399 ip_vs_conn_stats(cp, svc);
400 return cp;
401}
402
403
404
405
406
407
408
409int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
410 struct ip_vs_protocol *pp)
411{
412 __be16 _ports[2], *pptr;
413 struct iphdr *iph = ip_hdr(skb);
414
415 pptr = skb_header_pointer(skb, iph->ihl*4,
416 sizeof(_ports), _ports);
417 if (pptr == NULL) {
418 ip_vs_service_put(svc);
419 return NF_DROP;
420 }
421
422
423
424
425 if (sysctl_ip_vs_cache_bypass && svc->fwmark
426 && (inet_addr_type(&init_net, iph->daddr) == RTN_UNICAST)) {
427 int ret, cs;
428 struct ip_vs_conn *cp;
429
430 ip_vs_service_put(svc);
431
432
433 IP_VS_DBG(6, "ip_vs_leave: create a cache_bypass entry\n");
434 cp = ip_vs_conn_new(iph->protocol,
435 iph->saddr, pptr[0],
436 iph->daddr, pptr[1],
437 0, 0,
438 IP_VS_CONN_F_BYPASS,
439 NULL);
440 if (cp == NULL)
441 return NF_DROP;
442
443
444 ip_vs_in_stats(cp, skb);
445
446
447 cs = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp);
448
449
450 ret = cp->packet_xmit(skb, cp, pp);
451
452
453 atomic_inc(&cp->in_pkts);
454 ip_vs_conn_put(cp);
455 return ret;
456 }
457
458
459
460
461
462
463
464 if ((svc->port == FTPPORT) && (pptr[1] != FTPPORT)) {
465 ip_vs_service_put(svc);
466 return NF_ACCEPT;
467 }
468
469 ip_vs_service_put(svc);
470
471
472
473
474
475
476
477
478 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
479 return NF_DROP;
480}
481
482
483
484
485
486
487
488
489
490static unsigned int ip_vs_post_routing(unsigned int hooknum,
491 struct sk_buff *skb,
492 const struct net_device *in,
493 const struct net_device *out,
494 int (*okfn)(struct sk_buff *))
495{
496 if (!skb->ipvs_property)
497 return NF_ACCEPT;
498
499 return NF_STOP;
500}
501
502__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
503{
504 return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
505}
506
507static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
508{
509 int err = ip_defrag(skb, user);
510
511 if (!err)
512 ip_send_check(ip_hdr(skb));
513
514 return err;
515}
516
517
518
519
520
521void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
522 struct ip_vs_conn *cp, int inout)
523{
524 struct iphdr *iph = ip_hdr(skb);
525 unsigned int icmp_offset = iph->ihl*4;
526 struct icmphdr *icmph = (struct icmphdr *)(skb_network_header(skb) +
527 icmp_offset);
528 struct iphdr *ciph = (struct iphdr *)(icmph + 1);
529
530 if (inout) {
531 iph->saddr = cp->vaddr;
532 ip_send_check(iph);
533 ciph->daddr = cp->vaddr;
534 ip_send_check(ciph);
535 } else {
536 iph->daddr = cp->daddr;
537 ip_send_check(iph);
538 ciph->saddr = cp->daddr;
539 ip_send_check(ciph);
540 }
541
542
543 if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol) {
544 __be16 *ports = (void *)ciph + ciph->ihl*4;
545
546 if (inout)
547 ports[1] = cp->vport;
548 else
549 ports[0] = cp->dport;
550 }
551
552
553 icmph->checksum = 0;
554 icmph->checksum = ip_vs_checksum_complete(skb, icmp_offset);
555 skb->ip_summed = CHECKSUM_UNNECESSARY;
556
557 if (inout)
558 IP_VS_DBG_PKT(11, pp, skb, (void *)ciph - (void *)iph,
559 "Forwarding altered outgoing ICMP");
560 else
561 IP_VS_DBG_PKT(11, pp, skb, (void *)ciph - (void *)iph,
562 "Forwarding altered incoming ICMP");
563}
564
565
566
567
568
569
570
571
572static int ip_vs_out_icmp(struct sk_buff *skb, int *related)
573{
574 struct iphdr *iph;
575 struct icmphdr _icmph, *ic;
576 struct iphdr _ciph, *cih;
577 struct ip_vs_conn *cp;
578 struct ip_vs_protocol *pp;
579 unsigned int offset, ihl, verdict;
580
581 *related = 1;
582
583
584 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
585 if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
586 return NF_STOLEN;
587 }
588
589 iph = ip_hdr(skb);
590 offset = ihl = iph->ihl * 4;
591 ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
592 if (ic == NULL)
593 return NF_DROP;
594
595 IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
596 ic->type, ntohs(icmp_id(ic)),
597 NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
598
599
600
601
602
603
604
605
606 if ((ic->type != ICMP_DEST_UNREACH) &&
607 (ic->type != ICMP_SOURCE_QUENCH) &&
608 (ic->type != ICMP_TIME_EXCEEDED)) {
609 *related = 0;
610 return NF_ACCEPT;
611 }
612
613
614 offset += sizeof(_icmph);
615 cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
616 if (cih == NULL)
617 return NF_ACCEPT;
618
619 pp = ip_vs_proto_get(cih->protocol);
620 if (!pp)
621 return NF_ACCEPT;
622
623
624 if (unlikely(cih->frag_off & htons(IP_OFFSET) &&
625 pp->dont_defrag))
626 return NF_ACCEPT;
627
628 IP_VS_DBG_PKT(11, pp, skb, offset, "Checking outgoing ICMP for");
629
630 offset += cih->ihl * 4;
631
632
633 cp = pp->conn_out_get(skb, pp, cih, offset, 1);
634 if (!cp)
635 return NF_ACCEPT;
636
637 verdict = NF_DROP;
638
639 if (IP_VS_FWD_METHOD(cp) != 0) {
640 IP_VS_ERR("shouldn't reach here, because the box is on the "
641 "half connection in the tun/dr module.\n");
642 }
643
644
645 if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
646
647 IP_VS_DBG(1, "Forward ICMP: failed checksum from %d.%d.%d.%d!\n",
648 NIPQUAD(iph->saddr));
649 goto out;
650 }
651
652 if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
653 offset += 2 * sizeof(__u16);
654 if (!skb_make_writable(skb, offset))
655 goto out;
656
657 ip_vs_nat_icmp(skb, pp, cp, 1);
658
659
660 ip_vs_out_stats(cp, skb);
661
662 skb->ipvs_property = 1;
663 verdict = NF_ACCEPT;
664
665 out:
666 __ip_vs_conn_put(cp);
667
668 return verdict;
669}
670
671static inline int is_tcp_reset(const struct sk_buff *skb)
672{
673 struct tcphdr _tcph, *th;
674
675 th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
676 if (th == NULL)
677 return 0;
678 return th->rst;
679}
680
681
682
683
684
685
686static unsigned int
687ip_vs_out(unsigned int hooknum, struct sk_buff *skb,
688 const struct net_device *in, const struct net_device *out,
689 int (*okfn)(struct sk_buff *))
690{
691 struct iphdr *iph;
692 struct ip_vs_protocol *pp;
693 struct ip_vs_conn *cp;
694 int ihl;
695
696 EnterFunction(11);
697
698 if (skb->ipvs_property)
699 return NF_ACCEPT;
700
701 iph = ip_hdr(skb);
702 if (unlikely(iph->protocol == IPPROTO_ICMP)) {
703 int related, verdict = ip_vs_out_icmp(skb, &related);
704
705 if (related)
706 return verdict;
707 iph = ip_hdr(skb);
708 }
709
710 pp = ip_vs_proto_get(iph->protocol);
711 if (unlikely(!pp))
712 return NF_ACCEPT;
713
714
715 if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) &&
716 !pp->dont_defrag)) {
717 if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
718 return NF_STOLEN;
719 iph = ip_hdr(skb);
720 }
721
722 ihl = iph->ihl << 2;
723
724
725
726
727 cp = pp->conn_out_get(skb, pp, iph, ihl, 0);
728
729 if (unlikely(!cp)) {
730 if (sysctl_ip_vs_nat_icmp_send &&
731 (pp->protocol == IPPROTO_TCP ||
732 pp->protocol == IPPROTO_UDP)) {
733 __be16 _ports[2], *pptr;
734
735 pptr = skb_header_pointer(skb, ihl,
736 sizeof(_ports), _ports);
737 if (pptr == NULL)
738 return NF_ACCEPT;
739 if (ip_vs_lookup_real_service(iph->protocol,
740 iph->saddr, pptr[0])) {
741
742
743
744
745
746 if (iph->protocol != IPPROTO_TCP
747 || !is_tcp_reset(skb)) {
748 icmp_send(skb,ICMP_DEST_UNREACH,
749 ICMP_PORT_UNREACH, 0);
750 return NF_DROP;
751 }
752 }
753 }
754 IP_VS_DBG_PKT(12, pp, skb, 0,
755 "packet continues traversal as normal");
756 return NF_ACCEPT;
757 }
758
759 IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet");
760
761 if (!skb_make_writable(skb, ihl))
762 goto drop;
763
764
765 if (pp->snat_handler && !pp->snat_handler(skb, pp, cp))
766 goto drop;
767 ip_hdr(skb)->saddr = cp->vaddr;
768 ip_send_check(ip_hdr(skb));
769
770
771
772
773
774
775
776 if (ip_route_me_harder(skb, RTN_LOCAL) != 0)
777 goto drop;
778
779 IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
780
781 ip_vs_out_stats(cp, skb);
782 ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp);
783 ip_vs_conn_put(cp);
784
785 skb->ipvs_property = 1;
786
787 LeaveFunction(11);
788 return NF_ACCEPT;
789
790 drop:
791 ip_vs_conn_put(cp);
792 kfree_skb(skb);
793 return NF_STOLEN;
794}
795
796
797
798
799
800
801
802
803static int
804ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
805{
806 struct iphdr *iph;
807 struct icmphdr _icmph, *ic;
808 struct iphdr _ciph, *cih;
809 struct ip_vs_conn *cp;
810 struct ip_vs_protocol *pp;
811 unsigned int offset, ihl, verdict;
812
813 *related = 1;
814
815
816 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
817 if (ip_vs_gather_frags(skb, hooknum == NF_INET_LOCAL_IN ?
818 IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD))
819 return NF_STOLEN;
820 }
821
822 iph = ip_hdr(skb);
823 offset = ihl = iph->ihl * 4;
824 ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
825 if (ic == NULL)
826 return NF_DROP;
827
828 IP_VS_DBG(12, "Incoming ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
829 ic->type, ntohs(icmp_id(ic)),
830 NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
831
832
833
834
835
836
837
838
839 if ((ic->type != ICMP_DEST_UNREACH) &&
840 (ic->type != ICMP_SOURCE_QUENCH) &&
841 (ic->type != ICMP_TIME_EXCEEDED)) {
842 *related = 0;
843 return NF_ACCEPT;
844 }
845
846
847 offset += sizeof(_icmph);
848 cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
849 if (cih == NULL)
850 return NF_ACCEPT;
851
852 pp = ip_vs_proto_get(cih->protocol);
853 if (!pp)
854 return NF_ACCEPT;
855
856
857 if (unlikely(cih->frag_off & htons(IP_OFFSET) &&
858 pp->dont_defrag))
859 return NF_ACCEPT;
860
861 IP_VS_DBG_PKT(11, pp, skb, offset, "Checking incoming ICMP for");
862
863 offset += cih->ihl * 4;
864
865
866 cp = pp->conn_in_get(skb, pp, cih, offset, 1);
867 if (!cp)
868 return NF_ACCEPT;
869
870 verdict = NF_DROP;
871
872
873 if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
874
875 IP_VS_DBG(1, "Incoming ICMP: failed checksum from %d.%d.%d.%d!\n",
876 NIPQUAD(iph->saddr));
877 goto out;
878 }
879
880
881 ip_vs_in_stats(cp, skb);
882 if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
883 offset += 2 * sizeof(__u16);
884 verdict = ip_vs_icmp_xmit(skb, cp, pp, offset);
885
886
887 out:
888 __ip_vs_conn_put(cp);
889
890 return verdict;
891}
892
893
894
895
896
897static unsigned int
898ip_vs_in(unsigned int hooknum, struct sk_buff *skb,
899 const struct net_device *in, const struct net_device *out,
900 int (*okfn)(struct sk_buff *))
901{
902 struct iphdr *iph;
903 struct ip_vs_protocol *pp;
904 struct ip_vs_conn *cp;
905 int ret, restart;
906 int ihl;
907
908
909
910
911
912 if (unlikely(skb->pkt_type != PACKET_HOST
913 || skb->dev->flags & IFF_LOOPBACK || skb->sk)) {
914 IP_VS_DBG(12, "packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n",
915 skb->pkt_type,
916 ip_hdr(skb)->protocol,
917 NIPQUAD(ip_hdr(skb)->daddr));
918 return NF_ACCEPT;
919 }
920
921 iph = ip_hdr(skb);
922 if (unlikely(iph->protocol == IPPROTO_ICMP)) {
923 int related, verdict = ip_vs_in_icmp(skb, &related, hooknum);
924
925 if (related)
926 return verdict;
927 iph = ip_hdr(skb);
928 }
929
930
931 pp = ip_vs_proto_get(iph->protocol);
932 if (unlikely(!pp))
933 return NF_ACCEPT;
934
935 ihl = iph->ihl << 2;
936
937
938
939
940 cp = pp->conn_in_get(skb, pp, iph, ihl, 0);
941
942 if (unlikely(!cp)) {
943 int v;
944
945 if (!pp->conn_schedule(skb, pp, &v, &cp))
946 return v;
947 }
948
949 if (unlikely(!cp)) {
950
951 IP_VS_DBG_PKT(12, pp, skb, 0,
952 "packet continues traversal as normal");
953 return NF_ACCEPT;
954 }
955
956 IP_VS_DBG_PKT(11, pp, skb, 0, "Incoming packet");
957
958
959 if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
960
961
962 if (sysctl_ip_vs_expire_nodest_conn) {
963
964 ip_vs_conn_expire_now(cp);
965 }
966
967
968 __ip_vs_conn_put(cp);
969 return NF_DROP;
970 }
971
972 ip_vs_in_stats(cp, skb);
973 restart = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp);
974 if (cp->packet_xmit)
975 ret = cp->packet_xmit(skb, cp, pp);
976
977 else {
978 IP_VS_DBG_RL("warning: packet_xmit is null");
979 ret = NF_ACCEPT;
980 }
981
982
983
984
985
986
987
988 atomic_inc(&cp->in_pkts);
989 if ((ip_vs_sync_state & IP_VS_STATE_MASTER) &&
990 (((cp->protocol != IPPROTO_TCP ||
991 cp->state == IP_VS_TCP_S_ESTABLISHED) &&
992 (atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1]
993 == sysctl_ip_vs_sync_threshold[0])) ||
994 ((cp->protocol == IPPROTO_TCP) && (cp->old_state != cp->state) &&
995 ((cp->state == IP_VS_TCP_S_FIN_WAIT) ||
996 (cp->state == IP_VS_TCP_S_CLOSE)))))
997 ip_vs_sync_conn(cp);
998 cp->old_state = cp->state;
999
1000 ip_vs_conn_put(cp);
1001 return ret;
1002}
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014static unsigned int
1015ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,
1016 const struct net_device *in, const struct net_device *out,
1017 int (*okfn)(struct sk_buff *))
1018{
1019 int r;
1020
1021 if (ip_hdr(skb)->protocol != IPPROTO_ICMP)
1022 return NF_ACCEPT;
1023
1024 return ip_vs_in_icmp(skb, &r, hooknum);
1025}
1026
1027
1028static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
1029
1030
1031
1032 {
1033 .hook = ip_vs_in,
1034 .owner = THIS_MODULE,
1035 .pf = PF_INET,
1036 .hooknum = NF_INET_LOCAL_IN,
1037 .priority = 100,
1038 },
1039
1040 {
1041 .hook = ip_vs_out,
1042 .owner = THIS_MODULE,
1043 .pf = PF_INET,
1044 .hooknum = NF_INET_FORWARD,
1045 .priority = 100,
1046 },
1047
1048
1049 {
1050 .hook = ip_vs_forward_icmp,
1051 .owner = THIS_MODULE,
1052 .pf = PF_INET,
1053 .hooknum = NF_INET_FORWARD,
1054 .priority = 99,
1055 },
1056
1057 {
1058 .hook = ip_vs_post_routing,
1059 .owner = THIS_MODULE,
1060 .pf = PF_INET,
1061 .hooknum = NF_INET_POST_ROUTING,
1062 .priority = NF_IP_PRI_NAT_SRC-1,
1063 },
1064};
1065
1066
1067
1068
1069
1070static int __init ip_vs_init(void)
1071{
1072 int ret;
1073
1074 ret = ip_vs_control_init();
1075 if (ret < 0) {
1076 IP_VS_ERR("can't setup control.\n");
1077 goto cleanup_nothing;
1078 }
1079
1080 ip_vs_protocol_init();
1081
1082 ret = ip_vs_app_init();
1083 if (ret < 0) {
1084 IP_VS_ERR("can't setup application helper.\n");
1085 goto cleanup_protocol;
1086 }
1087
1088 ret = ip_vs_conn_init();
1089 if (ret < 0) {
1090 IP_VS_ERR("can't setup connection table.\n");
1091 goto cleanup_app;
1092 }
1093
1094 ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
1095 if (ret < 0) {
1096 IP_VS_ERR("can't register hooks.\n");
1097 goto cleanup_conn;
1098 }
1099
1100 IP_VS_INFO("ipvs loaded.\n");
1101 return ret;
1102
1103 cleanup_conn:
1104 ip_vs_conn_cleanup();
1105 cleanup_app:
1106 ip_vs_app_cleanup();
1107 cleanup_protocol:
1108 ip_vs_protocol_cleanup();
1109 ip_vs_control_cleanup();
1110 cleanup_nothing:
1111 return ret;
1112}
1113
1114static void __exit ip_vs_cleanup(void)
1115{
1116 nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
1117 ip_vs_conn_cleanup();
1118 ip_vs_app_cleanup();
1119 ip_vs_protocol_cleanup();
1120 ip_vs_control_cleanup();
1121 IP_VS_INFO("ipvs unloaded.\n");
1122}
1123
1124module_init(ip_vs_init);
1125module_exit(ip_vs_cleanup);
1126MODULE_LICENSE("GPL");
1127