aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipvs/ip_vs_ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ipvs/ip_vs_ctl.c')
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c523
1 files changed, 355 insertions, 168 deletions
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index ede101eeec17..993a83fb0d56 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -35,6 +35,10 @@
35 35
36#include <net/net_namespace.h> 36#include <net/net_namespace.h>
37#include <net/ip.h> 37#include <net/ip.h>
38#ifdef CONFIG_IP_VS_IPV6
39#include <net/ipv6.h>
40#include <net/ip6_route.h>
41#endif
38#include <net/route.h> 42#include <net/route.h>
39#include <net/sock.h> 43#include <net/sock.h>
40#include <net/genetlink.h> 44#include <net/genetlink.h>
@@ -91,6 +95,26 @@ int ip_vs_get_debug_level(void)
91} 95}
92#endif 96#endif
93 97
98#ifdef CONFIG_IP_VS_IPV6
99/* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */
100static int __ip_vs_addr_is_local_v6(const struct in6_addr *addr)
101{
102 struct rt6_info *rt;
103 struct flowi fl = {
104 .oif = 0,
105 .nl_u = {
106 .ip6_u = {
107 .daddr = *addr,
108 .saddr = { .s6_addr32 = {0, 0, 0, 0} }, } },
109 };
110
111 rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
112 if (rt && rt->rt6i_dev && (rt->rt6i_dev->flags & IFF_LOOPBACK))
113 return 1;
114
115 return 0;
116}
117#endif
94/* 118/*
95 * update_defense_level is called from keventd and from sysctl, 119 * update_defense_level is called from keventd and from sysctl,
96 * so it needs to protect itself from softirqs 120 * so it needs to protect itself from softirqs
@@ -282,11 +306,19 @@ static atomic_t ip_vs_nullsvc_counter = ATOMIC_INIT(0);
282 * Returns hash value for virtual service 306 * Returns hash value for virtual service
283 */ 307 */
284static __inline__ unsigned 308static __inline__ unsigned
285ip_vs_svc_hashkey(unsigned proto, __be32 addr, __be16 port) 309ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr,
310 __be16 port)
286{ 311{
287 register unsigned porth = ntohs(port); 312 register unsigned porth = ntohs(port);
313 __be32 addr_fold = addr->ip;
314
315#ifdef CONFIG_IP_VS_IPV6
316 if (af == AF_INET6)
317 addr_fold = addr->ip6[0]^addr->ip6[1]^
318 addr->ip6[2]^addr->ip6[3];
319#endif
288 320
289 return (proto^ntohl(addr)^(porth>>IP_VS_SVC_TAB_BITS)^porth) 321 return (proto^ntohl(addr_fold)^(porth>>IP_VS_SVC_TAB_BITS)^porth)
290 & IP_VS_SVC_TAB_MASK; 322 & IP_VS_SVC_TAB_MASK;
291} 323}
292 324
@@ -317,7 +349,8 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
317 /* 349 /*
318 * Hash it by <protocol,addr,port> in ip_vs_svc_table 350 * Hash it by <protocol,addr,port> in ip_vs_svc_table
319 */ 351 */
320 hash = ip_vs_svc_hashkey(svc->protocol, svc->addr, svc->port); 352 hash = ip_vs_svc_hashkey(svc->af, svc->protocol, &svc->addr,
353 svc->port);
321 list_add(&svc->s_list, &ip_vs_svc_table[hash]); 354 list_add(&svc->s_list, &ip_vs_svc_table[hash]);
322 } else { 355 } else {
323 /* 356 /*
@@ -363,17 +396,19 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
363/* 396/*
364 * Get service by {proto,addr,port} in the service table. 397 * Get service by {proto,addr,port} in the service table.
365 */ 398 */
366static __inline__ struct ip_vs_service * 399static inline struct ip_vs_service *
367__ip_vs_service_get(__u16 protocol, __be32 vaddr, __be16 vport) 400__ip_vs_service_get(int af, __u16 protocol, const union nf_inet_addr *vaddr,
401 __be16 vport)
368{ 402{
369 unsigned hash; 403 unsigned hash;
370 struct ip_vs_service *svc; 404 struct ip_vs_service *svc;
371 405
372 /* Check for "full" addressed entries */ 406 /* Check for "full" addressed entries */
373 hash = ip_vs_svc_hashkey(protocol, vaddr, vport); 407 hash = ip_vs_svc_hashkey(af, protocol, vaddr, vport);
374 408
375 list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){ 409 list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){
376 if ((svc->addr == vaddr) 410 if ((svc->af == af)
411 && ip_vs_addr_equal(af, &svc->addr, vaddr)
377 && (svc->port == vport) 412 && (svc->port == vport)
378 && (svc->protocol == protocol)) { 413 && (svc->protocol == protocol)) {
379 /* HIT */ 414 /* HIT */
@@ -389,7 +424,8 @@ __ip_vs_service_get(__u16 protocol, __be32 vaddr, __be16 vport)
389/* 424/*
390 * Get service by {fwmark} in the service table. 425 * Get service by {fwmark} in the service table.
391 */ 426 */
392static __inline__ struct ip_vs_service *__ip_vs_svc_fwm_get(__u32 fwmark) 427static inline struct ip_vs_service *
428__ip_vs_svc_fwm_get(int af, __u32 fwmark)
393{ 429{
394 unsigned hash; 430 unsigned hash;
395 struct ip_vs_service *svc; 431 struct ip_vs_service *svc;
@@ -398,7 +434,7 @@ static __inline__ struct ip_vs_service *__ip_vs_svc_fwm_get(__u32 fwmark)
398 hash = ip_vs_svc_fwm_hashkey(fwmark); 434 hash = ip_vs_svc_fwm_hashkey(fwmark);
399 435
400 list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) { 436 list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) {
401 if (svc->fwmark == fwmark) { 437 if (svc->fwmark == fwmark && svc->af == af) {
402 /* HIT */ 438 /* HIT */
403 atomic_inc(&svc->usecnt); 439 atomic_inc(&svc->usecnt);
404 return svc; 440 return svc;
@@ -409,7 +445,8 @@ static __inline__ struct ip_vs_service *__ip_vs_svc_fwm_get(__u32 fwmark)
409} 445}
410 446
411struct ip_vs_service * 447struct ip_vs_service *
412ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport) 448ip_vs_service_get(int af, __u32 fwmark, __u16 protocol,
449 const union nf_inet_addr *vaddr, __be16 vport)
413{ 450{
414 struct ip_vs_service *svc; 451 struct ip_vs_service *svc;
415 452
@@ -418,14 +455,14 @@ ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport)
418 /* 455 /*
419 * Check the table hashed by fwmark first 456 * Check the table hashed by fwmark first
420 */ 457 */
421 if (fwmark && (svc = __ip_vs_svc_fwm_get(fwmark))) 458 if (fwmark && (svc = __ip_vs_svc_fwm_get(af, fwmark)))
422 goto out; 459 goto out;
423 460
424 /* 461 /*
425 * Check the table hashed by <protocol,addr,port> 462 * Check the table hashed by <protocol,addr,port>
426 * for "full" addressed entries 463 * for "full" addressed entries
427 */ 464 */
428 svc = __ip_vs_service_get(protocol, vaddr, vport); 465 svc = __ip_vs_service_get(af, protocol, vaddr, vport);
429 466
430 if (svc == NULL 467 if (svc == NULL
431 && protocol == IPPROTO_TCP 468 && protocol == IPPROTO_TCP
@@ -435,7 +472,7 @@ ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport)
435 * Check if ftp service entry exists, the packet 472 * Check if ftp service entry exists, the packet
436 * might belong to FTP data connections. 473 * might belong to FTP data connections.
437 */ 474 */
438 svc = __ip_vs_service_get(protocol, vaddr, FTPPORT); 475 svc = __ip_vs_service_get(af, protocol, vaddr, FTPPORT);
439 } 476 }
440 477
441 if (svc == NULL 478 if (svc == NULL
@@ -443,16 +480,16 @@ ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport)
443 /* 480 /*
444 * Check if the catch-all port (port zero) exists 481 * Check if the catch-all port (port zero) exists
445 */ 482 */
446 svc = __ip_vs_service_get(protocol, vaddr, 0); 483 svc = __ip_vs_service_get(af, protocol, vaddr, 0);
447 } 484 }
448 485
449 out: 486 out:
450 read_unlock(&__ip_vs_svc_lock); 487 read_unlock(&__ip_vs_svc_lock);
451 488
452 IP_VS_DBG(9, "lookup service: fwm %u %s %u.%u.%u.%u:%u %s\n", 489 IP_VS_DBG_BUF(9, "lookup service: fwm %u %s %s:%u %s\n",
453 fwmark, ip_vs_proto_name(protocol), 490 fwmark, ip_vs_proto_name(protocol),
454 NIPQUAD(vaddr), ntohs(vport), 491 IP_VS_DBG_ADDR(af, vaddr), ntohs(vport),
455 svc?"hit":"not hit"); 492 svc ? "hit" : "not hit");
456 493
457 return svc; 494 return svc;
458} 495}
@@ -479,11 +516,20 @@ __ip_vs_unbind_svc(struct ip_vs_dest *dest)
479/* 516/*
480 * Returns hash value for real service 517 * Returns hash value for real service
481 */ 518 */
482static __inline__ unsigned ip_vs_rs_hashkey(__be32 addr, __be16 port) 519static inline unsigned ip_vs_rs_hashkey(int af,
520 const union nf_inet_addr *addr,
521 __be16 port)
483{ 522{
484 register unsigned porth = ntohs(port); 523 register unsigned porth = ntohs(port);
524 __be32 addr_fold = addr->ip;
525
526#ifdef CONFIG_IP_VS_IPV6
527 if (af == AF_INET6)
528 addr_fold = addr->ip6[0]^addr->ip6[1]^
529 addr->ip6[2]^addr->ip6[3];
530#endif
485 531
486 return (ntohl(addr)^(porth>>IP_VS_RTAB_BITS)^porth) 532 return (ntohl(addr_fold)^(porth>>IP_VS_RTAB_BITS)^porth)
487 & IP_VS_RTAB_MASK; 533 & IP_VS_RTAB_MASK;
488} 534}
489 535
@@ -503,7 +549,8 @@ static int ip_vs_rs_hash(struct ip_vs_dest *dest)
503 * Hash by proto,addr,port, 549 * Hash by proto,addr,port,
504 * which are the parameters of the real service. 550 * which are the parameters of the real service.
505 */ 551 */
506 hash = ip_vs_rs_hashkey(dest->addr, dest->port); 552 hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port);
553
507 list_add(&dest->d_list, &ip_vs_rtable[hash]); 554 list_add(&dest->d_list, &ip_vs_rtable[hash]);
508 555
509 return 1; 556 return 1;
@@ -530,7 +577,9 @@ static int ip_vs_rs_unhash(struct ip_vs_dest *dest)
530 * Lookup real service by <proto,addr,port> in the real service table. 577 * Lookup real service by <proto,addr,port> in the real service table.
531 */ 578 */
532struct ip_vs_dest * 579struct ip_vs_dest *
533ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) 580ip_vs_lookup_real_service(int af, __u16 protocol,
581 const union nf_inet_addr *daddr,
582 __be16 dport)
534{ 583{
535 unsigned hash; 584 unsigned hash;
536 struct ip_vs_dest *dest; 585 struct ip_vs_dest *dest;
@@ -539,11 +588,12 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport)
539 * Check for "full" addressed entries 588 * Check for "full" addressed entries
540 * Return the first found entry 589 * Return the first found entry
541 */ 590 */
542 hash = ip_vs_rs_hashkey(daddr, dport); 591 hash = ip_vs_rs_hashkey(af, daddr, dport);
543 592
544 read_lock(&__ip_vs_rs_lock); 593 read_lock(&__ip_vs_rs_lock);
545 list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) { 594 list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) {
546 if ((dest->addr == daddr) 595 if ((dest->af == af)
596 && ip_vs_addr_equal(af, &dest->addr, daddr)
547 && (dest->port == dport) 597 && (dest->port == dport)
548 && ((dest->protocol == protocol) || 598 && ((dest->protocol == protocol) ||
549 dest->vfwmark)) { 599 dest->vfwmark)) {
@@ -561,7 +611,8 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport)
561 * Lookup destination by {addr,port} in the given service 611 * Lookup destination by {addr,port} in the given service
562 */ 612 */
563static struct ip_vs_dest * 613static struct ip_vs_dest *
564ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) 614ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
615 __be16 dport)
565{ 616{
566 struct ip_vs_dest *dest; 617 struct ip_vs_dest *dest;
567 618
@@ -569,7 +620,9 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
569 * Find the destination for the given service 620 * Find the destination for the given service
570 */ 621 */
571 list_for_each_entry(dest, &svc->destinations, n_list) { 622 list_for_each_entry(dest, &svc->destinations, n_list) {
572 if ((dest->addr == daddr) && (dest->port == dport)) { 623 if ((dest->af == svc->af)
624 && ip_vs_addr_equal(svc->af, &dest->addr, daddr)
625 && (dest->port == dport)) {
573 /* HIT */ 626 /* HIT */
574 return dest; 627 return dest;
575 } 628 }
@@ -588,13 +641,15 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
588 * ip_vs_lookup_real_service() looked promissing, but 641 * ip_vs_lookup_real_service() looked promissing, but
589 * seems not working as expected. 642 * seems not working as expected.
590 */ 643 */
591struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, 644struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr,
592 __be32 vaddr, __be16 vport, __u16 protocol) 645 __be16 dport,
646 const union nf_inet_addr *vaddr,
647 __be16 vport, __u16 protocol)
593{ 648{
594 struct ip_vs_dest *dest; 649 struct ip_vs_dest *dest;
595 struct ip_vs_service *svc; 650 struct ip_vs_service *svc;
596 651
597 svc = ip_vs_service_get(0, protocol, vaddr, vport); 652 svc = ip_vs_service_get(af, 0, protocol, vaddr, vport);
598 if (!svc) 653 if (!svc)
599 return NULL; 654 return NULL;
600 dest = ip_vs_lookup_dest(svc, daddr, dport); 655 dest = ip_vs_lookup_dest(svc, daddr, dport);
@@ -615,7 +670,8 @@ struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport,
615 * scheduling. 670 * scheduling.
616 */ 671 */
617static struct ip_vs_dest * 672static struct ip_vs_dest *
618ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) 673ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
674 __be16 dport)
619{ 675{
620 struct ip_vs_dest *dest, *nxt; 676 struct ip_vs_dest *dest, *nxt;
621 677
@@ -623,17 +679,19 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
623 * Find the destination in trash 679 * Find the destination in trash
624 */ 680 */
625 list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) { 681 list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) {
626 IP_VS_DBG(3, "Destination %u/%u.%u.%u.%u:%u still in trash, " 682 IP_VS_DBG_BUF(3, "Destination %u/%s:%u still in trash, "
627 "dest->refcnt=%d\n", 683 "dest->refcnt=%d\n",
628 dest->vfwmark, 684 dest->vfwmark,
629 NIPQUAD(dest->addr), ntohs(dest->port), 685 IP_VS_DBG_ADDR(svc->af, &dest->addr),
630 atomic_read(&dest->refcnt)); 686 ntohs(dest->port),
631 if (dest->addr == daddr && 687 atomic_read(&dest->refcnt));
688 if (dest->af == svc->af &&
689 ip_vs_addr_equal(svc->af, &dest->addr, daddr) &&
632 dest->port == dport && 690 dest->port == dport &&
633 dest->vfwmark == svc->fwmark && 691 dest->vfwmark == svc->fwmark &&
634 dest->protocol == svc->protocol && 692 dest->protocol == svc->protocol &&
635 (svc->fwmark || 693 (svc->fwmark ||
636 (dest->vaddr == svc->addr && 694 (ip_vs_addr_equal(svc->af, &dest->vaddr, &svc->addr) &&
637 dest->vport == svc->port))) { 695 dest->vport == svc->port))) {
638 /* HIT */ 696 /* HIT */
639 return dest; 697 return dest;
@@ -643,10 +701,11 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
643 * Try to purge the destination from trash if not referenced 701 * Try to purge the destination from trash if not referenced
644 */ 702 */
645 if (atomic_read(&dest->refcnt) == 1) { 703 if (atomic_read(&dest->refcnt) == 1) {
646 IP_VS_DBG(3, "Removing destination %u/%u.%u.%u.%u:%u " 704 IP_VS_DBG_BUF(3, "Removing destination %u/%s:%u "
647 "from trash\n", 705 "from trash\n",
648 dest->vfwmark, 706 dest->vfwmark,
649 NIPQUAD(dest->addr), ntohs(dest->port)); 707 IP_VS_DBG_ADDR(svc->af, &dest->addr),
708 ntohs(dest->port));
650 list_del(&dest->n_list); 709 list_del(&dest->n_list);
651 ip_vs_dst_reset(dest); 710 ip_vs_dst_reset(dest);
652 __ip_vs_unbind_svc(dest); 711 __ip_vs_unbind_svc(dest);
@@ -685,18 +744,7 @@ ip_vs_zero_stats(struct ip_vs_stats *stats)
685{ 744{
686 spin_lock_bh(&stats->lock); 745 spin_lock_bh(&stats->lock);
687 746
688 stats->conns = 0; 747 memset(&stats->ustats, 0, sizeof(stats->ustats));
689 stats->inpkts = 0;
690 stats->outpkts = 0;
691 stats->inbytes = 0;
692 stats->outbytes = 0;
693
694 stats->cps = 0;
695 stats->inpps = 0;
696 stats->outpps = 0;
697 stats->inbps = 0;
698 stats->outbps = 0;
699
700 ip_vs_zero_estimator(stats); 748 ip_vs_zero_estimator(stats);
701 749
702 spin_unlock_bh(&stats->lock); 750 spin_unlock_bh(&stats->lock);
@@ -707,7 +755,7 @@ ip_vs_zero_stats(struct ip_vs_stats *stats)
707 */ 755 */
708static void 756static void
709__ip_vs_update_dest(struct ip_vs_service *svc, 757__ip_vs_update_dest(struct ip_vs_service *svc,
710 struct ip_vs_dest *dest, struct ip_vs_dest_user *udest) 758 struct ip_vs_dest *dest, struct ip_vs_dest_user_kern *udest)
711{ 759{
712 int conn_flags; 760 int conn_flags;
713 761
@@ -716,10 +764,18 @@ __ip_vs_update_dest(struct ip_vs_service *svc,
716 conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE; 764 conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE;
717 765
718 /* check if local node and update the flags */ 766 /* check if local node and update the flags */
719 if (inet_addr_type(&init_net, udest->addr) == RTN_LOCAL) { 767#ifdef CONFIG_IP_VS_IPV6
720 conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK) 768 if (svc->af == AF_INET6) {
721 | IP_VS_CONN_F_LOCALNODE; 769 if (__ip_vs_addr_is_local_v6(&udest->addr.in6)) {
722 } 770 conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK)
771 | IP_VS_CONN_F_LOCALNODE;
772 }
773 } else
774#endif
775 if (inet_addr_type(&init_net, udest->addr.ip) == RTN_LOCAL) {
776 conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK)
777 | IP_VS_CONN_F_LOCALNODE;
778 }
723 779
724 /* set the IP_VS_CONN_F_NOOUTPUT flag if not masquerading/NAT */ 780 /* set the IP_VS_CONN_F_NOOUTPUT flag if not masquerading/NAT */
725 if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != 0) { 781 if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != 0) {
@@ -760,7 +816,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc,
760 * Create a destination for the given service 816 * Create a destination for the given service
761 */ 817 */
762static int 818static int
763ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest, 819ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
764 struct ip_vs_dest **dest_p) 820 struct ip_vs_dest **dest_p)
765{ 821{
766 struct ip_vs_dest *dest; 822 struct ip_vs_dest *dest;
@@ -768,9 +824,20 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest,
768 824
769 EnterFunction(2); 825 EnterFunction(2);
770 826
771 atype = inet_addr_type(&init_net, udest->addr); 827#ifdef CONFIG_IP_VS_IPV6
772 if (atype != RTN_LOCAL && atype != RTN_UNICAST) 828 if (svc->af == AF_INET6) {
773 return -EINVAL; 829 atype = ipv6_addr_type(&udest->addr.in6);
830 if ((!(atype & IPV6_ADDR_UNICAST) ||
831 atype & IPV6_ADDR_LINKLOCAL) &&
832 !__ip_vs_addr_is_local_v6(&udest->addr.in6))
833 return -EINVAL;
834 } else
835#endif
836 {
837 atype = inet_addr_type(&init_net, udest->addr.ip);
838 if (atype != RTN_LOCAL && atype != RTN_UNICAST)
839 return -EINVAL;
840 }
774 841
775 dest = kzalloc(sizeof(struct ip_vs_dest), GFP_ATOMIC); 842 dest = kzalloc(sizeof(struct ip_vs_dest), GFP_ATOMIC);
776 if (dest == NULL) { 843 if (dest == NULL) {
@@ -778,11 +845,12 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest,
778 return -ENOMEM; 845 return -ENOMEM;
779 } 846 }
780 847
848 dest->af = svc->af;
781 dest->protocol = svc->protocol; 849 dest->protocol = svc->protocol;
782 dest->vaddr = svc->addr; 850 dest->vaddr = svc->addr;
783 dest->vport = svc->port; 851 dest->vport = svc->port;
784 dest->vfwmark = svc->fwmark; 852 dest->vfwmark = svc->fwmark;
785 dest->addr = udest->addr; 853 ip_vs_addr_copy(svc->af, &dest->addr, &udest->addr);
786 dest->port = udest->port; 854 dest->port = udest->port;
787 855
788 atomic_set(&dest->activeconns, 0); 856 atomic_set(&dest->activeconns, 0);
@@ -807,10 +875,10 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest,
807 * Add a destination into an existing service 875 * Add a destination into an existing service
808 */ 876 */
809static int 877static int
810ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) 878ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
811{ 879{
812 struct ip_vs_dest *dest; 880 struct ip_vs_dest *dest;
813 __be32 daddr = udest->addr; 881 union nf_inet_addr daddr;
814 __be16 dport = udest->port; 882 __be16 dport = udest->port;
815 int ret; 883 int ret;
816 884
@@ -827,10 +895,13 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
827 return -ERANGE; 895 return -ERANGE;
828 } 896 }
829 897
898 ip_vs_addr_copy(svc->af, &daddr, &udest->addr);
899
830 /* 900 /*
831 * Check if the dest already exists in the list 901 * Check if the dest already exists in the list
832 */ 902 */
833 dest = ip_vs_lookup_dest(svc, daddr, dport); 903 dest = ip_vs_lookup_dest(svc, &daddr, dport);
904
834 if (dest != NULL) { 905 if (dest != NULL) {
835 IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n"); 906 IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n");
836 return -EEXIST; 907 return -EEXIST;
@@ -840,15 +911,17 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
840 * Check if the dest already exists in the trash and 911 * Check if the dest already exists in the trash and
841 * is from the same service 912 * is from the same service
842 */ 913 */
843 dest = ip_vs_trash_get_dest(svc, daddr, dport); 914 dest = ip_vs_trash_get_dest(svc, &daddr, dport);
915
844 if (dest != NULL) { 916 if (dest != NULL) {
845 IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, " 917 IP_VS_DBG_BUF(3, "Get destination %s:%u from trash, "
846 "dest->refcnt=%d, service %u/%u.%u.%u.%u:%u\n", 918 "dest->refcnt=%d, service %u/%s:%u\n",
847 NIPQUAD(daddr), ntohs(dport), 919 IP_VS_DBG_ADDR(svc->af, &daddr), ntohs(dport),
848 atomic_read(&dest->refcnt), 920 atomic_read(&dest->refcnt),
849 dest->vfwmark, 921 dest->vfwmark,
850 NIPQUAD(dest->vaddr), 922 IP_VS_DBG_ADDR(svc->af, &dest->vaddr),
851 ntohs(dest->vport)); 923 ntohs(dest->vport));
924
852 __ip_vs_update_dest(svc, dest, udest); 925 __ip_vs_update_dest(svc, dest, udest);
853 926
854 /* 927 /*
@@ -915,10 +988,10 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
915 * Edit a destination in the given service 988 * Edit a destination in the given service
916 */ 989 */
917static int 990static int
918ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) 991ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
919{ 992{
920 struct ip_vs_dest *dest; 993 struct ip_vs_dest *dest;
921 __be32 daddr = udest->addr; 994 union nf_inet_addr daddr;
922 __be16 dport = udest->port; 995 __be16 dport = udest->port;
923 996
924 EnterFunction(2); 997 EnterFunction(2);
@@ -934,10 +1007,13 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
934 return -ERANGE; 1007 return -ERANGE;
935 } 1008 }
936 1009
1010 ip_vs_addr_copy(svc->af, &daddr, &udest->addr);
1011
937 /* 1012 /*
938 * Lookup the destination list 1013 * Lookup the destination list
939 */ 1014 */
940 dest = ip_vs_lookup_dest(svc, daddr, dport); 1015 dest = ip_vs_lookup_dest(svc, &daddr, dport);
1016
941 if (dest == NULL) { 1017 if (dest == NULL) {
942 IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n"); 1018 IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n");
943 return -ENOENT; 1019 return -ENOENT;
@@ -991,10 +1067,11 @@ static void __ip_vs_del_dest(struct ip_vs_dest *dest)
991 atomic_dec(&dest->svc->refcnt); 1067 atomic_dec(&dest->svc->refcnt);
992 kfree(dest); 1068 kfree(dest);
993 } else { 1069 } else {
994 IP_VS_DBG(3, "Moving dest %u.%u.%u.%u:%u into trash, " 1070 IP_VS_DBG_BUF(3, "Moving dest %s:%u into trash, "
995 "dest->refcnt=%d\n", 1071 "dest->refcnt=%d\n",
996 NIPQUAD(dest->addr), ntohs(dest->port), 1072 IP_VS_DBG_ADDR(dest->af, &dest->addr),
997 atomic_read(&dest->refcnt)); 1073 ntohs(dest->port),
1074 atomic_read(&dest->refcnt));
998 list_add(&dest->n_list, &ip_vs_dest_trash); 1075 list_add(&dest->n_list, &ip_vs_dest_trash);
999 atomic_inc(&dest->refcnt); 1076 atomic_inc(&dest->refcnt);
1000 } 1077 }
@@ -1028,15 +1105,15 @@ static void __ip_vs_unlink_dest(struct ip_vs_service *svc,
1028 * Delete a destination server in the given service 1105 * Delete a destination server in the given service
1029 */ 1106 */
1030static int 1107static int
1031ip_vs_del_dest(struct ip_vs_service *svc,struct ip_vs_dest_user *udest) 1108ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
1032{ 1109{
1033 struct ip_vs_dest *dest; 1110 struct ip_vs_dest *dest;
1034 __be32 daddr = udest->addr;
1035 __be16 dport = udest->port; 1111 __be16 dport = udest->port;
1036 1112
1037 EnterFunction(2); 1113 EnterFunction(2);
1038 1114
1039 dest = ip_vs_lookup_dest(svc, daddr, dport); 1115 dest = ip_vs_lookup_dest(svc, &udest->addr, dport);
1116
1040 if (dest == NULL) { 1117 if (dest == NULL) {
1041 IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n"); 1118 IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n");
1042 return -ENOENT; 1119 return -ENOENT;
@@ -1071,7 +1148,8 @@ ip_vs_del_dest(struct ip_vs_service *svc,struct ip_vs_dest_user *udest)
1071 * Add a service into the service hash table 1148 * Add a service into the service hash table
1072 */ 1149 */
1073static int 1150static int
1074ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p) 1151ip_vs_add_service(struct ip_vs_service_user_kern *u,
1152 struct ip_vs_service **svc_p)
1075{ 1153{
1076 int ret = 0; 1154 int ret = 0;
1077 struct ip_vs_scheduler *sched = NULL; 1155 struct ip_vs_scheduler *sched = NULL;
@@ -1089,6 +1167,19 @@ ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p)
1089 goto out_mod_dec; 1167 goto out_mod_dec;
1090 } 1168 }
1091 1169
1170#ifdef CONFIG_IP_VS_IPV6
1171 if (u->af == AF_INET6) {
1172 if (!sched->supports_ipv6) {
1173 ret = -EAFNOSUPPORT;
1174 goto out_err;
1175 }
1176 if ((u->netmask < 1) || (u->netmask > 128)) {
1177 ret = -EINVAL;
1178 goto out_err;
1179 }
1180 }
1181#endif
1182
1092 svc = kzalloc(sizeof(struct ip_vs_service), GFP_ATOMIC); 1183 svc = kzalloc(sizeof(struct ip_vs_service), GFP_ATOMIC);
1093 if (svc == NULL) { 1184 if (svc == NULL) {
1094 IP_VS_DBG(1, "ip_vs_add_service: kmalloc failed.\n"); 1185 IP_VS_DBG(1, "ip_vs_add_service: kmalloc failed.\n");
@@ -1100,8 +1191,9 @@ ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p)
1100 atomic_set(&svc->usecnt, 1); 1191 atomic_set(&svc->usecnt, 1);
1101 atomic_set(&svc->refcnt, 0); 1192 atomic_set(&svc->refcnt, 0);
1102 1193
1194 svc->af = u->af;
1103 svc->protocol = u->protocol; 1195 svc->protocol = u->protocol;
1104 svc->addr = u->addr; 1196 ip_vs_addr_copy(svc->af, &svc->addr, &u->addr);
1105 svc->port = u->port; 1197 svc->port = u->port;
1106 svc->fwmark = u->fwmark; 1198 svc->fwmark = u->fwmark;
1107 svc->flags = u->flags; 1199 svc->flags = u->flags;
@@ -1125,7 +1217,10 @@ ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p)
1125 atomic_inc(&ip_vs_nullsvc_counter); 1217 atomic_inc(&ip_vs_nullsvc_counter);
1126 1218
1127 ip_vs_new_estimator(&svc->stats); 1219 ip_vs_new_estimator(&svc->stats);
1128 ip_vs_num_services++; 1220
1221 /* Count only IPv4 services for old get/setsockopt interface */
1222 if (svc->af == AF_INET)
1223 ip_vs_num_services++;
1129 1224
1130 /* Hash the service into the service table */ 1225 /* Hash the service into the service table */
1131 write_lock_bh(&__ip_vs_svc_lock); 1226 write_lock_bh(&__ip_vs_svc_lock);
@@ -1160,7 +1255,7 @@ ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p)
1160 * Edit a service and bind it with a new scheduler 1255 * Edit a service and bind it with a new scheduler
1161 */ 1256 */
1162static int 1257static int
1163ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user *u) 1258ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
1164{ 1259{
1165 struct ip_vs_scheduler *sched, *old_sched; 1260 struct ip_vs_scheduler *sched, *old_sched;
1166 int ret = 0; 1261 int ret = 0;
@@ -1176,6 +1271,19 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user *u)
1176 } 1271 }
1177 old_sched = sched; 1272 old_sched = sched;
1178 1273
1274#ifdef CONFIG_IP_VS_IPV6
1275 if (u->af == AF_INET6) {
1276 if (!sched->supports_ipv6) {
1277 ret = -EAFNOSUPPORT;
1278 goto out;
1279 }
1280 if ((u->netmask < 1) || (u->netmask > 128)) {
1281 ret = -EINVAL;
1282 goto out;
1283 }
1284 }
1285#endif
1286
1179 write_lock_bh(&__ip_vs_svc_lock); 1287 write_lock_bh(&__ip_vs_svc_lock);
1180 1288
1181 /* 1289 /*
@@ -1240,7 +1348,10 @@ static void __ip_vs_del_service(struct ip_vs_service *svc)
1240 struct ip_vs_dest *dest, *nxt; 1348 struct ip_vs_dest *dest, *nxt;
1241 struct ip_vs_scheduler *old_sched; 1349 struct ip_vs_scheduler *old_sched;
1242 1350
1243 ip_vs_num_services--; 1351 /* Count only IPv4 services for old get/setsockopt interface */
1352 if (svc->af == AF_INET)
1353 ip_vs_num_services--;
1354
1244 ip_vs_kill_estimator(&svc->stats); 1355 ip_vs_kill_estimator(&svc->stats);
1245 1356
1246 /* Unbind scheduler */ 1357 /* Unbind scheduler */
@@ -1748,15 +1859,25 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
1748 const struct ip_vs_iter *iter = seq->private; 1859 const struct ip_vs_iter *iter = seq->private;
1749 const struct ip_vs_dest *dest; 1860 const struct ip_vs_dest *dest;
1750 1861
1751 if (iter->table == ip_vs_svc_table) 1862 if (iter->table == ip_vs_svc_table) {
1752 seq_printf(seq, "%s %08X:%04X %s ", 1863#ifdef CONFIG_IP_VS_IPV6
1753 ip_vs_proto_name(svc->protocol), 1864 if (svc->af == AF_INET6)
1754 ntohl(svc->addr), 1865 seq_printf(seq, "%s [" NIP6_FMT "]:%04X %s ",
1755 ntohs(svc->port), 1866 ip_vs_proto_name(svc->protocol),
1756 svc->scheduler->name); 1867 NIP6(svc->addr.in6),
1757 else 1868 ntohs(svc->port),
1869 svc->scheduler->name);
1870 else
1871#endif
1872 seq_printf(seq, "%s %08X:%04X %s ",
1873 ip_vs_proto_name(svc->protocol),
1874 ntohl(svc->addr.ip),
1875 ntohs(svc->port),
1876 svc->scheduler->name);
1877 } else {
1758 seq_printf(seq, "FWM %08X %s ", 1878 seq_printf(seq, "FWM %08X %s ",
1759 svc->fwmark, svc->scheduler->name); 1879 svc->fwmark, svc->scheduler->name);
1880 }
1760 1881
1761 if (svc->flags & IP_VS_SVC_F_PERSISTENT) 1882 if (svc->flags & IP_VS_SVC_F_PERSISTENT)
1762 seq_printf(seq, "persistent %d %08X\n", 1883 seq_printf(seq, "persistent %d %08X\n",
@@ -1766,13 +1887,29 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
1766 seq_putc(seq, '\n'); 1887 seq_putc(seq, '\n');
1767 1888
1768 list_for_each_entry(dest, &svc->destinations, n_list) { 1889 list_for_each_entry(dest, &svc->destinations, n_list) {
1769 seq_printf(seq, 1890#ifdef CONFIG_IP_VS_IPV6
1770 " -> %08X:%04X %-7s %-6d %-10d %-10d\n", 1891 if (dest->af == AF_INET6)
1771 ntohl(dest->addr), ntohs(dest->port), 1892 seq_printf(seq,
1772 ip_vs_fwd_name(atomic_read(&dest->conn_flags)), 1893 " -> [" NIP6_FMT "]:%04X"
1773 atomic_read(&dest->weight), 1894 " %-7s %-6d %-10d %-10d\n",
1774 atomic_read(&dest->activeconns), 1895 NIP6(dest->addr.in6),
1775 atomic_read(&dest->inactconns)); 1896 ntohs(dest->port),
1897 ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
1898 atomic_read(&dest->weight),
1899 atomic_read(&dest->activeconns),
1900 atomic_read(&dest->inactconns));
1901 else
1902#endif
1903 seq_printf(seq,
1904 " -> %08X:%04X "
1905 "%-7s %-6d %-10d %-10d\n",
1906 ntohl(dest->addr.ip),
1907 ntohs(dest->port),
1908 ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
1909 atomic_read(&dest->weight),
1910 atomic_read(&dest->activeconns),
1911 atomic_read(&dest->inactconns));
1912
1776 } 1913 }
1777 } 1914 }
1778 return 0; 1915 return 0;
@@ -1816,20 +1953,20 @@ static int ip_vs_stats_show(struct seq_file *seq, void *v)
1816 " Conns Packets Packets Bytes Bytes\n"); 1953 " Conns Packets Packets Bytes Bytes\n");
1817 1954
1818 spin_lock_bh(&ip_vs_stats.lock); 1955 spin_lock_bh(&ip_vs_stats.lock);
1819 seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", ip_vs_stats.conns, 1956 seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", ip_vs_stats.ustats.conns,
1820 ip_vs_stats.inpkts, ip_vs_stats.outpkts, 1957 ip_vs_stats.ustats.inpkts, ip_vs_stats.ustats.outpkts,
1821 (unsigned long long) ip_vs_stats.inbytes, 1958 (unsigned long long) ip_vs_stats.ustats.inbytes,
1822 (unsigned long long) ip_vs_stats.outbytes); 1959 (unsigned long long) ip_vs_stats.ustats.outbytes);
1823 1960
1824/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */ 1961/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
1825 seq_puts(seq, 1962 seq_puts(seq,
1826 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n"); 1963 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
1827 seq_printf(seq,"%8X %8X %8X %16X %16X\n", 1964 seq_printf(seq,"%8X %8X %8X %16X %16X\n",
1828 ip_vs_stats.cps, 1965 ip_vs_stats.ustats.cps,
1829 ip_vs_stats.inpps, 1966 ip_vs_stats.ustats.inpps,
1830 ip_vs_stats.outpps, 1967 ip_vs_stats.ustats.outpps,
1831 ip_vs_stats.inbps, 1968 ip_vs_stats.ustats.inbps,
1832 ip_vs_stats.outbps); 1969 ip_vs_stats.ustats.outbps);
1833 spin_unlock_bh(&ip_vs_stats.lock); 1970 spin_unlock_bh(&ip_vs_stats.lock);
1834 1971
1835 return 0; 1972 return 0;
@@ -1904,14 +2041,44 @@ static const unsigned char set_arglen[SET_CMDID(IP_VS_SO_SET_MAX)+1] = {
1904 [SET_CMDID(IP_VS_SO_SET_ZERO)] = SERVICE_ARG_LEN, 2041 [SET_CMDID(IP_VS_SO_SET_ZERO)] = SERVICE_ARG_LEN,
1905}; 2042};
1906 2043
2044static void ip_vs_copy_usvc_compat(struct ip_vs_service_user_kern *usvc,
2045 struct ip_vs_service_user *usvc_compat)
2046{
2047 usvc->af = AF_INET;
2048 usvc->protocol = usvc_compat->protocol;
2049 usvc->addr.ip = usvc_compat->addr;
2050 usvc->port = usvc_compat->port;
2051 usvc->fwmark = usvc_compat->fwmark;
2052
2053 /* Deep copy of sched_name is not needed here */
2054 usvc->sched_name = usvc_compat->sched_name;
2055
2056 usvc->flags = usvc_compat->flags;
2057 usvc->timeout = usvc_compat->timeout;
2058 usvc->netmask = usvc_compat->netmask;
2059}
2060
2061static void ip_vs_copy_udest_compat(struct ip_vs_dest_user_kern *udest,
2062 struct ip_vs_dest_user *udest_compat)
2063{
2064 udest->addr.ip = udest_compat->addr;
2065 udest->port = udest_compat->port;
2066 udest->conn_flags = udest_compat->conn_flags;
2067 udest->weight = udest_compat->weight;
2068 udest->u_threshold = udest_compat->u_threshold;
2069 udest->l_threshold = udest_compat->l_threshold;
2070}
2071
1907static int 2072static int
1908do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) 2073do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1909{ 2074{
1910 int ret; 2075 int ret;
1911 unsigned char arg[MAX_ARG_LEN]; 2076 unsigned char arg[MAX_ARG_LEN];
1912 struct ip_vs_service_user *usvc; 2077 struct ip_vs_service_user *usvc_compat;
2078 struct ip_vs_service_user_kern usvc;
1913 struct ip_vs_service *svc; 2079 struct ip_vs_service *svc;
1914 struct ip_vs_dest_user *udest; 2080 struct ip_vs_dest_user *udest_compat;
2081 struct ip_vs_dest_user_kern udest;
1915 2082
1916 if (!capable(CAP_NET_ADMIN)) 2083 if (!capable(CAP_NET_ADMIN))
1917 return -EPERM; 2084 return -EPERM;
@@ -1951,35 +2118,40 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1951 goto out_unlock; 2118 goto out_unlock;
1952 } 2119 }
1953 2120
1954 usvc = (struct ip_vs_service_user *)arg; 2121 usvc_compat = (struct ip_vs_service_user *)arg;
1955 udest = (struct ip_vs_dest_user *)(usvc + 1); 2122 udest_compat = (struct ip_vs_dest_user *)(usvc_compat + 1);
2123
2124 /* We only use the new structs internally, so copy userspace compat
2125 * structs to extended internal versions */
2126 ip_vs_copy_usvc_compat(&usvc, usvc_compat);
2127 ip_vs_copy_udest_compat(&udest, udest_compat);
1956 2128
1957 if (cmd == IP_VS_SO_SET_ZERO) { 2129 if (cmd == IP_VS_SO_SET_ZERO) {
1958 /* if no service address is set, zero counters in all */ 2130 /* if no service address is set, zero counters in all */
1959 if (!usvc->fwmark && !usvc->addr && !usvc->port) { 2131 if (!usvc.fwmark && !usvc.addr.ip && !usvc.port) {
1960 ret = ip_vs_zero_all(); 2132 ret = ip_vs_zero_all();
1961 goto out_unlock; 2133 goto out_unlock;
1962 } 2134 }
1963 } 2135 }
1964 2136
1965 /* Check for valid protocol: TCP or UDP, even for fwmark!=0 */ 2137 /* Check for valid protocol: TCP or UDP, even for fwmark!=0 */
1966 if (usvc->protocol!=IPPROTO_TCP && usvc->protocol!=IPPROTO_UDP) { 2138 if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP) {
1967 IP_VS_ERR("set_ctl: invalid protocol: %d %d.%d.%d.%d:%d %s\n", 2139 IP_VS_ERR("set_ctl: invalid protocol: %d %d.%d.%d.%d:%d %s\n",
1968 usvc->protocol, NIPQUAD(usvc->addr), 2140 usvc.protocol, NIPQUAD(usvc.addr.ip),
1969 ntohs(usvc->port), usvc->sched_name); 2141 ntohs(usvc.port), usvc.sched_name);
1970 ret = -EFAULT; 2142 ret = -EFAULT;
1971 goto out_unlock; 2143 goto out_unlock;
1972 } 2144 }
1973 2145
1974 /* Lookup the exact service by <protocol, addr, port> or fwmark */ 2146 /* Lookup the exact service by <protocol, addr, port> or fwmark */
1975 if (usvc->fwmark == 0) 2147 if (usvc.fwmark == 0)
1976 svc = __ip_vs_service_get(usvc->protocol, 2148 svc = __ip_vs_service_get(usvc.af, usvc.protocol,
1977 usvc->addr, usvc->port); 2149 &usvc.addr, usvc.port);
1978 else 2150 else
1979 svc = __ip_vs_svc_fwm_get(usvc->fwmark); 2151 svc = __ip_vs_svc_fwm_get(usvc.af, usvc.fwmark);
1980 2152
1981 if (cmd != IP_VS_SO_SET_ADD 2153 if (cmd != IP_VS_SO_SET_ADD
1982 && (svc == NULL || svc->protocol != usvc->protocol)) { 2154 && (svc == NULL || svc->protocol != usvc.protocol)) {
1983 ret = -ESRCH; 2155 ret = -ESRCH;
1984 goto out_unlock; 2156 goto out_unlock;
1985 } 2157 }
@@ -1989,10 +2161,10 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1989 if (svc != NULL) 2161 if (svc != NULL)
1990 ret = -EEXIST; 2162 ret = -EEXIST;
1991 else 2163 else
1992 ret = ip_vs_add_service(usvc, &svc); 2164 ret = ip_vs_add_service(&usvc, &svc);
1993 break; 2165 break;
1994 case IP_VS_SO_SET_EDIT: 2166 case IP_VS_SO_SET_EDIT:
1995 ret = ip_vs_edit_service(svc, usvc); 2167 ret = ip_vs_edit_service(svc, &usvc);
1996 break; 2168 break;
1997 case IP_VS_SO_SET_DEL: 2169 case IP_VS_SO_SET_DEL:
1998 ret = ip_vs_del_service(svc); 2170 ret = ip_vs_del_service(svc);
@@ -2003,13 +2175,13 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2003 ret = ip_vs_zero_service(svc); 2175 ret = ip_vs_zero_service(svc);
2004 break; 2176 break;
2005 case IP_VS_SO_SET_ADDDEST: 2177 case IP_VS_SO_SET_ADDDEST:
2006 ret = ip_vs_add_dest(svc, udest); 2178 ret = ip_vs_add_dest(svc, &udest);
2007 break; 2179 break;
2008 case IP_VS_SO_SET_EDITDEST: 2180 case IP_VS_SO_SET_EDITDEST:
2009 ret = ip_vs_edit_dest(svc, udest); 2181 ret = ip_vs_edit_dest(svc, &udest);
2010 break; 2182 break;
2011 case IP_VS_SO_SET_DELDEST: 2183 case IP_VS_SO_SET_DELDEST:
2012 ret = ip_vs_del_dest(svc, udest); 2184 ret = ip_vs_del_dest(svc, &udest);
2013 break; 2185 break;
2014 default: 2186 default:
2015 ret = -EINVAL; 2187 ret = -EINVAL;
@@ -2032,7 +2204,7 @@ static void
2032ip_vs_copy_stats(struct ip_vs_stats_user *dst, struct ip_vs_stats *src) 2204ip_vs_copy_stats(struct ip_vs_stats_user *dst, struct ip_vs_stats *src)
2033{ 2205{
2034 spin_lock_bh(&src->lock); 2206 spin_lock_bh(&src->lock);
2035 memcpy(dst, src, (char*)&src->lock - (char*)src); 2207 memcpy(dst, &src->ustats, sizeof(*dst));
2036 spin_unlock_bh(&src->lock); 2208 spin_unlock_bh(&src->lock);
2037} 2209}
2038 2210
@@ -2040,7 +2212,7 @@ static void
2040ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src) 2212ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
2041{ 2213{
2042 dst->protocol = src->protocol; 2214 dst->protocol = src->protocol;
2043 dst->addr = src->addr; 2215 dst->addr = src->addr.ip;
2044 dst->port = src->port; 2216 dst->port = src->port;
2045 dst->fwmark = src->fwmark; 2217 dst->fwmark = src->fwmark;
2046 strlcpy(dst->sched_name, src->scheduler->name, sizeof(dst->sched_name)); 2218 strlcpy(dst->sched_name, src->scheduler->name, sizeof(dst->sched_name));
@@ -2062,6 +2234,10 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
2062 2234
2063 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 2235 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
2064 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { 2236 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
2237 /* Only expose IPv4 entries to old interface */
2238 if (svc->af != AF_INET)
2239 continue;
2240
2065 if (count >= get->num_services) 2241 if (count >= get->num_services)
2066 goto out; 2242 goto out;
2067 memset(&entry, 0, sizeof(entry)); 2243 memset(&entry, 0, sizeof(entry));
@@ -2077,6 +2253,10 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
2077 2253
2078 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { 2254 for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
2079 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { 2255 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
2256 /* Only expose IPv4 entries to old interface */
2257 if (svc->af != AF_INET)
2258 continue;
2259
2080 if (count >= get->num_services) 2260 if (count >= get->num_services)
2081 goto out; 2261 goto out;
2082 memset(&entry, 0, sizeof(entry)); 2262 memset(&entry, 0, sizeof(entry));
@@ -2098,13 +2278,15 @@ __ip_vs_get_dest_entries(const struct ip_vs_get_dests *get,
2098 struct ip_vs_get_dests __user *uptr) 2278 struct ip_vs_get_dests __user *uptr)
2099{ 2279{
2100 struct ip_vs_service *svc; 2280 struct ip_vs_service *svc;
2281 union nf_inet_addr addr = { .ip = get->addr };
2101 int ret = 0; 2282 int ret = 0;
2102 2283
2103 if (get->fwmark) 2284 if (get->fwmark)
2104 svc = __ip_vs_svc_fwm_get(get->fwmark); 2285 svc = __ip_vs_svc_fwm_get(AF_INET, get->fwmark);
2105 else 2286 else
2106 svc = __ip_vs_service_get(get->protocol, 2287 svc = __ip_vs_service_get(AF_INET, get->protocol, &addr,
2107 get->addr, get->port); 2288 get->port);
2289
2108 if (svc) { 2290 if (svc) {
2109 int count = 0; 2291 int count = 0;
2110 struct ip_vs_dest *dest; 2292 struct ip_vs_dest *dest;
@@ -2114,7 +2296,7 @@ __ip_vs_get_dest_entries(const struct ip_vs_get_dests *get,
2114 if (count >= get->num_dests) 2296 if (count >= get->num_dests)
2115 break; 2297 break;
2116 2298
2117 entry.addr = dest->addr; 2299 entry.addr = dest->addr.ip;
2118 entry.port = dest->port; 2300 entry.port = dest->port;
2119 entry.conn_flags = atomic_read(&dest->conn_flags); 2301 entry.conn_flags = atomic_read(&dest->conn_flags);
2120 entry.weight = atomic_read(&dest->weight); 2302 entry.weight = atomic_read(&dest->weight);
@@ -2239,13 +2421,15 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2239 { 2421 {
2240 struct ip_vs_service_entry *entry; 2422 struct ip_vs_service_entry *entry;
2241 struct ip_vs_service *svc; 2423 struct ip_vs_service *svc;
2424 union nf_inet_addr addr;
2242 2425
2243 entry = (struct ip_vs_service_entry *)arg; 2426 entry = (struct ip_vs_service_entry *)arg;
2427 addr.ip = entry->addr;
2244 if (entry->fwmark) 2428 if (entry->fwmark)
2245 svc = __ip_vs_svc_fwm_get(entry->fwmark); 2429 svc = __ip_vs_svc_fwm_get(AF_INET, entry->fwmark);
2246 else 2430 else
2247 svc = __ip_vs_service_get(entry->protocol, 2431 svc = __ip_vs_service_get(AF_INET, entry->protocol,
2248 entry->addr, entry->port); 2432 &addr, entry->port);
2249 if (svc) { 2433 if (svc) {
2250 ip_vs_copy_service(entry, svc); 2434 ip_vs_copy_service(entry, svc);
2251 if (copy_to_user(user, entry, sizeof(*entry)) != 0) 2435 if (copy_to_user(user, entry, sizeof(*entry)) != 0)
@@ -2396,16 +2580,16 @@ static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type,
2396 2580
2397 spin_lock_bh(&stats->lock); 2581 spin_lock_bh(&stats->lock);
2398 2582
2399 NLA_PUT_U32(skb, IPVS_STATS_ATTR_CONNS, stats->conns); 2583 NLA_PUT_U32(skb, IPVS_STATS_ATTR_CONNS, stats->ustats.conns);
2400 NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPKTS, stats->inpkts); 2584 NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPKTS, stats->ustats.inpkts);
2401 NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPKTS, stats->outpkts); 2585 NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPKTS, stats->ustats.outpkts);
2402 NLA_PUT_U64(skb, IPVS_STATS_ATTR_INBYTES, stats->inbytes); 2586 NLA_PUT_U64(skb, IPVS_STATS_ATTR_INBYTES, stats->ustats.inbytes);
2403 NLA_PUT_U64(skb, IPVS_STATS_ATTR_OUTBYTES, stats->outbytes); 2587 NLA_PUT_U64(skb, IPVS_STATS_ATTR_OUTBYTES, stats->ustats.outbytes);
2404 NLA_PUT_U32(skb, IPVS_STATS_ATTR_CPS, stats->cps); 2588 NLA_PUT_U32(skb, IPVS_STATS_ATTR_CPS, stats->ustats.cps);
2405 NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPPS, stats->inpps); 2589 NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPPS, stats->ustats.inpps);
2406 NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPPS, stats->outpps); 2590 NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPPS, stats->ustats.outpps);
2407 NLA_PUT_U32(skb, IPVS_STATS_ATTR_INBPS, stats->inbps); 2591 NLA_PUT_U32(skb, IPVS_STATS_ATTR_INBPS, stats->ustats.inbps);
2408 NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTBPS, stats->outbps); 2592 NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTBPS, stats->ustats.outbps);
2409 2593
2410 spin_unlock_bh(&stats->lock); 2594 spin_unlock_bh(&stats->lock);
2411 2595
@@ -2430,7 +2614,7 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb,
2430 if (!nl_service) 2614 if (!nl_service)
2431 return -EMSGSIZE; 2615 return -EMSGSIZE;
2432 2616
2433 NLA_PUT_U16(skb, IPVS_SVC_ATTR_AF, AF_INET); 2617 NLA_PUT_U16(skb, IPVS_SVC_ATTR_AF, svc->af);
2434 2618
2435 if (svc->fwmark) { 2619 if (svc->fwmark) {
2436 NLA_PUT_U32(skb, IPVS_SVC_ATTR_FWMARK, svc->fwmark); 2620 NLA_PUT_U32(skb, IPVS_SVC_ATTR_FWMARK, svc->fwmark);
@@ -2516,7 +2700,7 @@ nla_put_failure:
2516 return skb->len; 2700 return skb->len;
2517} 2701}
2518 2702
2519static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc, 2703static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc,
2520 struct nlattr *nla, int full_entry) 2704 struct nlattr *nla, int full_entry)
2521{ 2705{
2522 struct nlattr *attrs[IPVS_SVC_ATTR_MAX + 1]; 2706 struct nlattr *attrs[IPVS_SVC_ATTR_MAX + 1];
@@ -2536,8 +2720,12 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc,
2536 if (!(nla_af && (nla_fwmark || (nla_port && nla_protocol && nla_addr)))) 2720 if (!(nla_af && (nla_fwmark || (nla_port && nla_protocol && nla_addr))))
2537 return -EINVAL; 2721 return -EINVAL;
2538 2722
2539 /* For now, only support IPv4 */ 2723 usvc->af = nla_get_u16(nla_af);
2540 if (nla_get_u16(nla_af) != AF_INET) 2724#ifdef CONFIG_IP_VS_IPV6
2725 if (usvc->af != AF_INET && usvc->af != AF_INET6)
2726#else
2727 if (usvc->af != AF_INET)
2728#endif
2541 return -EAFNOSUPPORT; 2729 return -EAFNOSUPPORT;
2542 2730
2543 if (nla_fwmark) { 2731 if (nla_fwmark) {
@@ -2569,10 +2757,10 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc,
2569 2757
2570 /* prefill flags from service if it already exists */ 2758 /* prefill flags from service if it already exists */
2571 if (usvc->fwmark) 2759 if (usvc->fwmark)
2572 svc = __ip_vs_svc_fwm_get(usvc->fwmark); 2760 svc = __ip_vs_svc_fwm_get(usvc->af, usvc->fwmark);
2573 else 2761 else
2574 svc = __ip_vs_service_get(usvc->protocol, usvc->addr, 2762 svc = __ip_vs_service_get(usvc->af, usvc->protocol,
2575 usvc->port); 2763 &usvc->addr, usvc->port);
2576 if (svc) { 2764 if (svc) {
2577 usvc->flags = svc->flags; 2765 usvc->flags = svc->flags;
2578 ip_vs_service_put(svc); 2766 ip_vs_service_put(svc);
@@ -2582,9 +2770,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc,
2582 /* set new flags from userland */ 2770 /* set new flags from userland */
2583 usvc->flags = (usvc->flags & ~flags.mask) | 2771 usvc->flags = (usvc->flags & ~flags.mask) |
2584 (flags.flags & flags.mask); 2772 (flags.flags & flags.mask);
2585 2773 usvc->sched_name = nla_data(nla_sched);
2586 strlcpy(usvc->sched_name, nla_data(nla_sched),
2587 sizeof(usvc->sched_name));
2588 usvc->timeout = nla_get_u32(nla_timeout); 2774 usvc->timeout = nla_get_u32(nla_timeout);
2589 usvc->netmask = nla_get_u32(nla_netmask); 2775 usvc->netmask = nla_get_u32(nla_netmask);
2590 } 2776 }
@@ -2594,7 +2780,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc,
2594 2780
2595static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla) 2781static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla)
2596{ 2782{
2597 struct ip_vs_service_user usvc; 2783 struct ip_vs_service_user_kern usvc;
2598 int ret; 2784 int ret;
2599 2785
2600 ret = ip_vs_genl_parse_service(&usvc, nla, 0); 2786 ret = ip_vs_genl_parse_service(&usvc, nla, 0);
@@ -2602,10 +2788,10 @@ static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla)
2602 return ERR_PTR(ret); 2788 return ERR_PTR(ret);
2603 2789
2604 if (usvc.fwmark) 2790 if (usvc.fwmark)
2605 return __ip_vs_svc_fwm_get(usvc.fwmark); 2791 return __ip_vs_svc_fwm_get(usvc.af, usvc.fwmark);
2606 else 2792 else
2607 return __ip_vs_service_get(usvc.protocol, usvc.addr, 2793 return __ip_vs_service_get(usvc.af, usvc.protocol,
2608 usvc.port); 2794 &usvc.addr, usvc.port);
2609} 2795}
2610 2796
2611static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) 2797static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
@@ -2704,7 +2890,7 @@ out_err:
2704 return skb->len; 2890 return skb->len;
2705} 2891}
2706 2892
2707static int ip_vs_genl_parse_dest(struct ip_vs_dest_user *udest, 2893static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
2708 struct nlattr *nla, int full_entry) 2894 struct nlattr *nla, int full_entry)
2709{ 2895{
2710 struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1]; 2896 struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1];
@@ -2860,8 +3046,8 @@ static int ip_vs_genl_set_config(struct nlattr **attrs)
2860static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) 3046static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
2861{ 3047{
2862 struct ip_vs_service *svc = NULL; 3048 struct ip_vs_service *svc = NULL;
2863 struct ip_vs_service_user usvc; 3049 struct ip_vs_service_user_kern usvc;
2864 struct ip_vs_dest_user udest; 3050 struct ip_vs_dest_user_kern udest;
2865 int ret = 0, cmd; 3051 int ret = 0, cmd;
2866 int need_full_svc = 0, need_full_dest = 0; 3052 int need_full_svc = 0, need_full_dest = 0;
2867 3053
@@ -2913,9 +3099,10 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
2913 3099
2914 /* Lookup the exact service by <protocol, addr, port> or fwmark */ 3100 /* Lookup the exact service by <protocol, addr, port> or fwmark */
2915 if (usvc.fwmark == 0) 3101 if (usvc.fwmark == 0)
2916 svc = __ip_vs_service_get(usvc.protocol, usvc.addr, usvc.port); 3102 svc = __ip_vs_service_get(usvc.af, usvc.protocol,
3103 &usvc.addr, usvc.port);
2917 else 3104 else
2918 svc = __ip_vs_svc_fwm_get(usvc.fwmark); 3105 svc = __ip_vs_svc_fwm_get(usvc.af, usvc.fwmark);
2919 3106
2920 /* Unless we're adding a new service, the service must already exist */ 3107 /* Unless we're adding a new service, the service must already exist */
2921 if ((cmd != IPVS_CMD_NEW_SERVICE) && (svc == NULL)) { 3108 if ((cmd != IPVS_CMD_NEW_SERVICE) && (svc == NULL)) {