Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ipvsadm for openSUSE:Factory checked 
in at 2022-05-17 17:23:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ipvsadm (Old)
 and      /work/SRC/openSUSE:Factory/.ipvsadm.new.1538 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ipvsadm"

Tue May 17 17:23:44 2022 rev:26 rq:977477 version:1.31

Changes:
--------
--- /work/SRC/openSUSE:Factory/ipvsadm/ipvsadm.changes  2021-05-10 
15:39:18.281582744 +0200
+++ /work/SRC/openSUSE:Factory/.ipvsadm.new.1538/ipvsadm.changes        
2022-05-17 17:23:53.255141239 +0200
@@ -1,0 +2,14 @@
+Sat Apr 23 23:38:34 UTC 2022 - Ferdinand Thiessen <r...@fthiessen.de>
+
+- Update to version 1.31
+  * This release add support for configuring tunneling with
+    GRE or GUE encapsulation. See manpage ipvsadm(8) for --tun-type
+    and --tun-info, plus more specific --tun-xxxx options for adjustments.
+  * Some manpage adjustments.
+- Update to version 1.30
+  * Adding the missing userspace side for the schedulers MH, FO and OVF.
+- Replaced and rebased ipvsadm-1.26.diff and ipvsadm-PIE.patch with
+  ipvsadm-makefile.patch
+- Rebased ipvsadm-print_largenum.diff as ipvsadm-print_largenum.patch
+
+-------------------------------------------------------------------

Old:
----
  ipvsadm-1.26.diff
  ipvsadm-1.29.tar.xz
  ipvsadm-PIE.patch
  ipvsadm-print_largenum.diff

New:
----
  ipvsadm-1.31.tar.xz
  ipvsadm-makefile.patch
  ipvsadm-print_largenum.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ipvsadm.spec ++++++
--- /var/tmp/diff_new_pack.phyr3k/_old  2022-05-17 17:23:53.859141789 +0200
+++ /var/tmp/diff_new_pack.phyr3k/_new  2022-05-17 17:23:53.863141792 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package ipvsadm
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -31,14 +31,13 @@
 Summary:        A Utility for Administering the Linux Virtual Server
 License:        GPL-2.0-or-later
 Group:          Productivity/Networking/System
-Version:        1.29
+Version:        1.31
 Release:        0
 URL:            http://www.linuxvirtualserver.org/
 Source0:        
https://www.kernel.org/pub/linux/utils/kernel/ipvsadm/%{name}-%{version}.tar.xz
 Source1:        ipvsadm.service
-Patch1:         ipvsadm-1.26.diff
-Patch2:         ipvsadm-print_largenum.diff
-Patch3:         ipvsadm-PIE.patch
+Patch0:         ipvsadm-makefile.patch
+Patch1:         ipvsadm-print_largenum.patch
 Provides:       %{name}-%{version}
 Requires:       grep
 Requires(pre):  %fillup_prereq
@@ -49,7 +48,7 @@
 offered by the Linux kernel with Linux Virtual Server support.
 
 %prep
-%setup -q
+%autosetup
 # This files are embedded here instead of being another source in order
 # to the prefix directory
 cat >sysconfig.ipvsadm <<EOFF
@@ -68,9 +67,6 @@
 # Please insert your ipvs-rules here
 #
 EOFF
-%patch1
-%patch2
-%patch3 -p1
 
 %build
 make POPT_LIB="-lpopt" CFLAGS="%{optflags} -fPIC -DHAVE_POPT -DLIBIPVS_USE_NL 
-I%{_includedir}/libnl3"

++++++ ipvsadm-1.29.tar.xz -> ipvsadm-1.31.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipvsadm-1.29/SCHEDULERS new/ipvsadm-1.31/SCHEDULERS
--- old/ipvsadm-1.29/SCHEDULERS 2016-12-23 11:38:16.000000000 +0100
+++ new/ipvsadm-1.31/SCHEDULERS 2019-12-24 14:20:30.000000000 +0100
@@ -1 +1 @@
-rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq
+rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq|fo|ovf|mh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipvsadm-1.29/VERSION new/ipvsadm-1.31/VERSION
--- old/ipvsadm-1.29/VERSION    2016-12-23 11:38:16.000000000 +0100
+++ new/ipvsadm-1.31/VERSION    2019-12-24 14:20:30.000000000 +0100
@@ -1 +1 @@
-1.29
+1.31
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipvsadm-1.29/ipvsadm.8 new/ipvsadm-1.31/ipvsadm.8
--- old/ipvsadm-1.29/ipvsadm.8  2016-12-23 11:38:16.000000000 +0100
+++ new/ipvsadm-1.31/ipvsadm.8  2019-12-24 14:20:30.000000000 +0100
@@ -94,11 +94,11 @@
 The first format manipulates a virtual service and the algorithm for
 assigning service requests to real servers. Optionally, a persistent
 timeout and network mask for the granularity of a persistent service
-may be specified. The second format manipulates a real server that is
-associated with an existing virtual service. When specifying a real
-server, the packet-forwarding method and the weight of the real
-server, relative to other real servers for the virtual service, may be
-specified, otherwise defaults will be used.
+and a persistence engine may be specified. The second format manipulates
+a real server that is associated with an existing virtual service.
+When specifying a real server, the packet-forwarding method and the
+weight of the real server, relative to other real servers for the
+virtual service, may be specified, otherwise defaults will be used.
 .SS COMMANDS
 \fBipvsadm\fR(8) recognises the commands described below. Upper-case
 commands maintain virtual services. Lower-case commands maintain real
@@ -196,9 +196,10 @@
 .TP
 .B -f, --fwmark-service \fIinteger\fP
 Use a firewall-mark, an integer value greater than zero, to denote a
-virtual service instead of an address, port and protocol (UDP or
-TCP). The marking of packets with a firewall-mark is configured using
-the -m|--mark option to \fBiptables\fR(8). It can be used to build a
+virtual service instead of an address, port and protocol (UDP, TCP or
+SCTP). The marking of packets with a firewall-mark is configured using
+the -m|--mark option to \fBiptables\fR(8), the meta mark set \fIvalue\fR
+option to \fBnft\fR(8) or via an eBPF program. It can be used to build a
 virtual service associated with the same real servers, covering
 multiple IP address, port and protocol triplets. If IPv6 addresses
 are used, the -6 option must be used.
@@ -267,6 +268,24 @@
 \fBnq\fR - Never Queue: assigns an incoming job to an idle server if
 there is, instead of waiting for a fast one; if all the servers are
 busy, it adopts the Shortest Expected Delay policy to assign the job.
+.sp
+\fBfo\fR - Weighted Failover: assigns an incoming job to the server
+with the highest weight that is currently available.
+.sp
+\fBovf\fR - Weighted Overflow: assigns an incoming job to the server
+with the highest weight that is currently available and overflows
+to the next when active connections exceed the node's weight. Note
+that this scheduler might not be suitable for UDP because it only uses
+active connections.
+.sp
+\fBmh\fR - Maglev Hashing: assigns incoming jobs based on Google's
+Maglev hashing algorithm, providing an almost equal share of jobs to
+each real server and provides minimal disruption. When the set of real
+servers changes, a connection will likely be sent to the same real
+server as it was before.
+This scheduler has two flags: mh-fallback, which enables fallback to a
+different server if the selected server was unavailable, and mh-port,
+which adds the source port number to the hash computation.
 .TP
 .B -p, --persistent [\fItimeout\fP]
 Specify that a virtual service is persistent. If this option is
@@ -295,6 +314,10 @@
 IPv6 netmasks should be specified as a prefix length between 1 and 128.
 The default prefix length is 128.
 .TP
+.B --pe \fIpersistence-engine\fP
+Specify an alternative persistence engine to be used. Currently the
+only alternative persistence engine available is sip.
+.TP
 .B -b, --sched-flags \fIsched-flags\fP
 Set scheduler flags for this virtual server.  \fIsched-flags\fP is a
 comma-separated list of flags.  See the scheduler descriptions for
@@ -321,6 +344,36 @@
 .sp
 \fB-i, --ipip\fR  Use ipip encapsulation (tunneling).
 .sp
+.ti +8
+.B --tun-type \fItun-type\fP
+.ti +16
+\fItun-type\fP is one of \fIipip\fP|\fIgue\fP|\fIgre\fP.
+The default value of \fItun-type\fP is \fIipip\fP.
+.sp
+.ti +8
+.B --tun-port \fItun-port\fP
+.ti +16
+\fItun-port\fP is an integer specifying the destination port.
+Only valid for \fItun-type\fP \fIgue\fP.
+.sp
+.ti +8
+.B --tun-nocsum
+.ti +16
+Specify that tunnel checksums are disabled. This is the default.
+Only valid for \fItun-type\fP \fIgue\fP and \fIgre\fP.
+.sp
+.ti +8
+.B --tun-csum
+.ti +16
+Specify that tunnel checksums are enabled.
+Only valid for \fItun-type\fP \fIgue\fP and \fIgre\fP.
+.sp
+.ti +8
+.B --tun-remcsum
+.ti +16
+Specify that Remote Checksum Offload is enabled.
+Only valid for \fItun-type\fP \fIgue\fP.
+.sp
 \fB-m, --masquerading\fR  Use masquerading (network access translation, or 
NAT).
 .sp
 \fBNote:\fR  Regardless of the packet-forwarding mechanism specified,
@@ -398,6 +451,11 @@
 will include persistence engine data, if any is present, when listing
 connections.
 .TP
+.B --tun-info
+Output of tunneling information. The \fIlist\fP command with this
+option will display the tunneling information of services and their
+servers.
+.TP
 .B --sort
 Sort the list of virtual services and real servers. The virtual
 service entries are sorted in ascending order by <protocol, address,
@@ -535,6 +593,50 @@
 iptables  -A PREROUTING -t mangle -d 207.175.44.110/31 -j MARK --set-mark 1
 modprobe ip_vs_ftp
 .fi
+.SH EXAMPLE 3 - Virtual Service with GUE Tunneling
+The following commands configure a Linux Director to distribute
+incoming requests addressed to port 80 on 207.175.44.110 equally to
+port 80 on five real servers. The forwarding method used in this
+example is tunneling with gue encapsulation.
+.PP
+.nf
+ipvsadm -A -t 207.175.44.110:80 -s rr
+ipvsadm -a -t 207.175.44.110:80 -r 192.168.10.1:80 -i --tun-type gue \
+--tun-port 6080 --tun-nocsum
+ipvsadm -a -t 207.175.44.110:80 -r 192.168.10.2:80 -i --tun-type gue \
+--tun-port 6080 --tun-csum
+ipvsadm -a -t 207.175.44.110:80 -r 192.168.10.3:80 -i --tun-type gue \
+--tun-port 6080 --tun-remcsum
+ipvsadm -a -t 207.175.44.110:80 -r 192.168.10.4:80 -i --tun-type gue \
+--tun-port 6078
+ipvsadm -a -t 207.175.44.110:80 -r 192.168.10.5:80 -i --tun-type gue \
+--tun-port 6079
+.fi
+.PP
+Alternatively, this could be achieved in a single ipvsadm command.
+.PP
+.nf
+echo "
+-A -t 207.175.44.110:80 -s rr
+-a -t 207.175.44.110:80 -r 192.168.10.1:80 -i --tun-type gue --tun-port 6080 \
+--tun-nocsum
+-a -t 207.175.44.110:80 -r 192.168.10.2:80 -i --tun-type gue --tun-port 6080 \
+--tun-csum
+-a -t 207.175.44.110:80 -r 192.168.10.3:80 -i --tun-type gue --tun-port 6080 \
+--tun-remcsum
+-a -t 207.175.44.110:80 -r 192.168.10.4:80 -i --tun-type gue --tun-port 6078
+-a -t 207.175.44.110:80 -r 192.168.10.5:80 -i --tun-type gue --tun-port 6079
+" | ipvsadm -R
+.fi
+.SH EXAMPLE 4 - Virtual Service with GRE Tunneling
+The following commands configure a Linux Director to use GRE
+encapsulation.
+.PP
+.nf
+ipvsadm -A -t 10.0.0.1:80 -s rr
+ipvsadm -a -t 10.0.0.1:80 -r 192.168.11.1:80 -i --tun-type gre \
+--tun-csum
+.fi
 .SH IPv6
 IPv6 addresses should be surrounded by square brackets ([ and ]).
 .PP
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipvsadm-1.29/ipvsadm.c new/ipvsadm-1.31/ipvsadm.c
--- old/ipvsadm-1.29/ipvsadm.c  2016-12-23 11:38:16.000000000 +0100
+++ new/ipvsadm-1.31/ipvsadm.c  2019-12-24 14:20:30.000000000 +0100
@@ -118,7 +118,7 @@
 #include "libipvs/libipvs.h"
 
 #define IPVSADM_VERSION_NO     "v" VERSION
-#define IPVSADM_VERSION_DATE   "2016/12/23"
+#define IPVSADM_VERSION_DATE   "2019/12/24"
 #define IPVSADM_VERSION                IPVSADM_VERSION_NO " " 
IPVSADM_VERSION_DATE
 
 #define MAX_TIMEOUT            (86400*31)      /* 31 days */
@@ -187,7 +187,48 @@
 #define OPT_MCAST_PORT         0x02000000
 #define OPT_MCAST_TTL          0x04000000
 #define OPT_SYNC_MAXLEN        0x08000000
-#define NUMBER_OF_OPT          28
+#define OPT_TUN_INFO           0x10000000
+#define OPT_TUN_TYPE           0x20000000
+#define OPT_TUN_PORT           0x40000000
+#define OPT_TUN_NOCSUM         0x80000000
+#define OPT_TUN_CSUM           0x100000000
+#define OPT_TUN_REMCSUM                0x200000000
+#define NUMBER_OF_OPT          34
+
+#define OPTC_NUMERIC           0
+#define OPTC_CONNECTION                1
+#define OPTC_SERVICE           2
+#define OPTC_SCHEDULER         3
+#define OPTC_PERSISTENT                4
+#define OPTC_NETMASK           5
+#define OPTC_SERVER            6
+#define OPTC_FORWARD           7
+#define OPTC_WEIGHT            8
+#define OPTC_UTHRESHOLD                9
+#define OPTC_LTHRESHOLD                10
+#define OPTC_MCAST             11
+#define OPTC_TIMEOUT           12
+#define OPTC_DAEMON            13
+#define OPTC_STATS             14
+#define OPTC_RATE              15
+#define OPTC_THRESHOLDS                16
+#define OPTC_PERSISTENTCONN    17
+#define OPTC_NOSORT            18
+#define OPTC_SYNCID            19
+#define OPTC_EXACT             20
+#define OPTC_ONEPACKET         21
+#define OPTC_PERSISTENCE_ENGINE        22
+#define OPTC_SCHED_FLAGS       23
+#define OPTC_MCAST_GROUP       24
+#define OPTC_MCAST_PORT                25
+#define OPTC_MCAST_TTL         26
+#define OPTC_SYNC_MAXLEN       27
+#define OPTC_TUN_INFO          28
+#define OPTC_TUN_TYPE          29
+#define OPTC_TUN_PORT          30
+#define OPTC_TUN_NOCSUM                31
+#define OPTC_TUN_CSUM          32
+#define OPTC_TUN_REMCSUM       33
 
 static const char* optnames[] = {
        "numeric",
@@ -218,6 +259,12 @@
        "mcast-port",
        "mcast-ttl",
        "sync-maxlen",
+       "tun-info",
+       "tun-type",
+       "tun-port",
+       "tun-nocsum",
+       "tun-csum",
+       "tun-remcsum",
 };
 
 /*
@@ -230,21 +277,65 @@
  */
 static const char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
 {
-       /*   -n   -c   svc  -s   -p   -M   -r   fwd  -w   -x   -y   -mc  tot  
dmn  -st  -rt  thr  -pc  srt  sid  -ex  ops  -pe  -b   grp  port ttl  size */
-/*ADD*/     {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', ' ', ' ', 'x', 'x', 'x', 'x'},
-/*EDIT*/    {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', ' ', ' ', 'x', 'x', 'x', 'x'},
-/*DEL*/     {'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*FLUSH*/   {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*LIST*/    {' ', '1', '1', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', '1', 
'1', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*ADDSRV*/  {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*DELSRV*/  {'x', 'x', '+', 'x', 'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*EDITSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*TIMEOUT*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*STARTD*/  {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x', ' ', ' ', ' ', ' '},
-/*STOPD*/   {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*RESTORE*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*SAVE*/    {' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
-/*ZERO*/    {'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},
+       /*   -n   -c   svc  -s   -p   -M   -r   fwd  -w   -x   -y   -mc  tot  
dmn  -st  -rt  thr  -pc  srt  sid  -ex  ops  -pe  -b   grp  port ttl  size tinf 
type tprt nocs csum remc */
+/*ADD*/     {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*EDIT*/    {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*DEL*/     {'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*FLUSH*/   {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*LIST*/    {' ', '1', '1', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', '1', 
'1', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 
'x', 'x', 'x', 'x', 'x'},
+/*ADDSRV*/  {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
' ', ' ', ' ', ' ', ' '},
+/*DELSRV*/  {'x', 'x', '+', 'x', 'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*EDITSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
' ', ' ', ' ', ' ', ' '},
+/*TIMEOUT*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*STARTD*/  {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x', ' ', ' ', ' ', ' ', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*STOPD*/   {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*RESTORE*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*SAVE*/    {' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+/*ZERO*/    {'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 
'x', 'x', 'x', 'x', 'x'},
+};
+
+static const char * const tunnames[] = {
+       "ipip",
+       "gue",
+       "gre",
+};
+
+static const char * const tunflags[] = {
+       "-c",           /* without checksum */
+       "+c",           /* with checksum */
+       "r+c",          /* with remote checksum */
+};
+
+static const char * const tun_flags_opts[] = {
+       "--tun-nocsum",
+       "--tun-csum",
+       "--tun-remcsum",
+};
+
+static const int tunopts[] = {
+       OPTC_TUN_PORT,
+       OPTC_TUN_NOCSUM,
+       OPTC_TUN_CSUM,
+       OPTC_TUN_REMCSUM,
+};
+
+#define NUMBER_OF_TUN_OPT              4
+#define NA                             "n/a"
+
+/*
+ * Table of legal combinations of tunnel types and options.
+ * Key:
+ *  '+'  compulsory
+ *  'x'  illegal
+ *  '1'  exclusive (only one '1' option can be supplied)
+ *  ' '  optional
+ */
+static const char
+tunnel_types_v_options[IP_VS_CONN_F_TUNNEL_TYPE_MAX][NUMBER_OF_TUN_OPT] = {
+       /*  tprt nocs csum remc */
+/* ipip */ {'x', 'x', 'x', 'x'},
+/* gue */  {'+', '1', '1', '1'},
+/* gre */  {'x', '1', '1', 'x'},
 };
 
 /* printing format flags */
@@ -257,6 +348,7 @@
 #define FMT_PERSISTENTCONN     0x0020
 #define FMT_NOSORT             0x0040
 #define FMT_EXACT              0x0080
+#define FMT_TUN_INFO           0x0100
 
 #define SERVICE_NONE           0x0000
 #define SERVICE_ADDR           0x0001
@@ -265,6 +357,9 @@
 /* default scheduler */
 #define DEF_SCHED              "wlc"
 
+/* default tunnel type */
+#define DEF_TUNNEL_TYPE        "ipip"
+
 /* default multicast interface name */
 #define DEF_MCAST_IFN          "eth0"
 
@@ -300,6 +395,12 @@
        TAG_MCAST_PORT,
        TAG_MCAST_TTL,
        TAG_SYNC_MAXLEN,
+       TAG_TUN_INFO,
+       TAG_TUN_TYPE,
+       TAG_TUN_PORT,
+       TAG_TUN_NOCSUM,
+       TAG_TUN_CSUM,
+       TAG_TUN_REMCSUM,
 };
 
 /* various parsing helpers & parsing functions */
@@ -318,11 +419,15 @@
 static int parse_timeout(char *buf, int min, int max);
 static unsigned int parse_fwmark(char *buf);
 static unsigned int parse_sched_flags(const char *sched, char *optarg);
+static int parse_tun_type(const char *name);
 
 /* check the options based on the commands_v_options table */
-static void generic_opt_check(int command, int options);
+static void generic_opt_check(int command, unsigned long long options);
 static void set_command(int *cmd, const int newcmd);
-static void set_option(unsigned int *options, unsigned int option);
+static void set_option(unsigned long long *options, int optc);
+
+/* check the options based on the tunnel_types_v_options table */
+static void tunnel_opt_check(int tun_type, unsigned long long options);
 
 static void tryhelp_exit(const char *program, const int exit_status);
 static void usage_exit(const char *program, const int exit_status);
@@ -416,7 +521,7 @@
 
 static int
 parse_options(int argc, char **argv, struct ipvs_command_entry *ce,
-             unsigned int *options, unsigned int *format)
+             unsigned long long *options, unsigned int *format)
 {
        int c, parse;
        poptContext context;
@@ -495,6 +600,18 @@
                  TAG_MCAST_TTL, NULL, NULL },
                { "sync-maxlen", '\0', POPT_ARG_STRING, &optarg,
                  TAG_SYNC_MAXLEN, NULL, NULL },
+               { "tun-info", '\0', POPT_ARG_NONE, NULL, TAG_TUN_INFO,
+                 NULL, NULL },
+               { "tun-type", '\0', POPT_ARG_STRING, &optarg, TAG_TUN_TYPE,
+                 NULL, NULL },
+               { "tun-port", '\0', POPT_ARG_STRING, &optarg, TAG_TUN_PORT,
+                 NULL, NULL },
+               { "tun-nocsum", '\0', POPT_ARG_NONE, NULL, TAG_TUN_NOCSUM,
+                 NULL, NULL },
+               { "tun-csum", '\0', POPT_ARG_NONE, NULL, TAG_TUN_CSUM,
+                 NULL, NULL },
+               { "tun-remcsum", '\0', POPT_ARG_NONE, NULL, TAG_TUN_REMCSUM,
+                 NULL, NULL },
                { NULL, 0, 0, NULL, 0, NULL, NULL }
        };
 
@@ -575,7 +692,7 @@
                case 't':
                case 'u':
                case TAG_SCTP_SERVICE:
-                       set_option(options, OPT_SERVICE);
+                       set_option(options, OPTC_SERVICE);
                        ce->svc.protocol = option_to_protocol(c);
                        parse = parse_service(optarg, &ce->svc);
                        if (!(parse & SERVICE_ADDR))
@@ -583,7 +700,7 @@
                                     "address[:port] specified");
                        break;
                case 'f':
-                       set_option(options, OPT_SERVICE);
+                       set_option(options, OPTC_SERVICE);
                        /*
                         * Set protocol to a sane values, even
                         * though it is not used
@@ -593,18 +710,18 @@
                        ce->svc.fwmark = parse_fwmark(optarg);
                        break;
                case 's':
-                       set_option(options, OPT_SCHEDULER);
+                       set_option(options, OPTC_SCHEDULER);
                        strncpy(ce->svc.sched_name,
-                               optarg, IP_VS_SCHEDNAME_MAXLEN);
+                               optarg, IP_VS_SCHEDNAME_MAXLEN - 1);
                        break;
                case 'p':
-                       set_option(options, OPT_PERSISTENT);
+                       set_option(options, OPTC_PERSISTENT);
                        ce->svc.flags |= IP_VS_SVC_F_PERSISTENT;
                        ce->svc.timeout =
                                parse_timeout(optarg, 1, MAX_TIMEOUT);
                        break;
                case 'M':
-                       set_option(options, OPT_NETMASK);
+                       set_option(options, OPTC_NETMASK);
                        if (ce->svc.af != AF_INET6) {
                                parse = parse_netmask(optarg, &ce->svc.netmask);
                                if (parse != 1)
@@ -617,7 +734,7 @@
                        }
                        break;
                case 'r':
-                       set_option(options, OPT_SERVER);
+                       set_option(options, OPTC_SERVER);
                        ipvs_service_t t_dest = ce->svc;
                        parse = parse_service(optarg, &t_dest);
                        ce->dest.af = t_dest.af;
@@ -631,84 +748,84 @@
                                ce->dest.port = ce->svc.port;
                        break;
                case 'i':
-                       set_option(options, OPT_FORWARD);
+                       set_option(options, OPTC_FORWARD);
                        ce->dest.conn_flags = IP_VS_CONN_F_TUNNEL;
                        break;
                case 'g':
-                       set_option(options, OPT_FORWARD);
+                       set_option(options, OPTC_FORWARD);
                        ce->dest.conn_flags = IP_VS_CONN_F_DROUTE;
                        break;
                case 'm':
-                       set_option(options, OPT_FORWARD);
+                       set_option(options, OPTC_FORWARD);
                        ce->dest.conn_flags = IP_VS_CONN_F_MASQ;
                        break;
                case 'w':
-                       set_option(options, OPT_WEIGHT);
+                       set_option(options, OPTC_WEIGHT);
                        if ((ce->dest.weight =
                             string_to_number(optarg, 0, 65535)) == -1)
                                fail(2, "illegal weight specified");
                        break;
                case 'x':
-                       set_option(options, OPT_UTHRESHOLD);
+                       set_option(options, OPTC_UTHRESHOLD);
                        if ((ce->dest.u_threshold =
                             string_to_number(optarg, 0, INT_MAX)) == -1)
                                fail(2, "illegal u_threshold specified");
                        break;
                case 'y':
-                       set_option(options, OPT_LTHRESHOLD);
+                       set_option(options, OPTC_LTHRESHOLD);
                        if ((ce->dest.l_threshold =
                             string_to_number(optarg, 0, INT_MAX)) == -1)
                                fail(2, "illegal l_threshold specified");
                        break;
                case 'c':
-                       set_option(options, OPT_CONNECTION);
+                       set_option(options, OPTC_CONNECTION);
                        break;
                case 'n':
-                       set_option(options, OPT_NUMERIC);
+                       set_option(options, OPTC_NUMERIC);
                        *format |= FMT_NUMERIC;
                        break;
                case TAG_MCAST_INTERFACE:
-                       set_option(options, OPT_MCAST);
+                       set_option(options, OPTC_MCAST);
                        strncpy(ce->daemon.mcast_ifn,
-                               optarg, IP_VS_IFNAME_MAXLEN);
+                               optarg, IP_VS_IFNAME_MAXLEN - 1);
                        break;
                case 'I':
-                       set_option(options, OPT_SYNCID);
+                       set_option(options, OPTC_SYNCID);
                        if ((ce->daemon.syncid =
                             string_to_number(optarg, 0, 255)) == -1)
                                fail(2, "illegal syncid specified");
                        break;
                case TAG_TIMEOUT:
-                       set_option(options, OPT_TIMEOUT);
+                       set_option(options, OPTC_TIMEOUT);
                        break;
                case TAG_DAEMON:
-                       set_option(options, OPT_DAEMON);
+                       set_option(options, OPTC_DAEMON);
                        break;
                case TAG_STATS:
-                       set_option(options, OPT_STATS);
+                       set_option(options, OPTC_STATS);
                        *format |= FMT_STATS;
                        break;
                case TAG_RATE:
-                       set_option(options, OPT_RATE);
+                       set_option(options, OPTC_RATE);
                        *format |= FMT_RATE;
                        break;
                case TAG_THRESHOLDS:
-                       set_option(options, OPT_THRESHOLDS);
+                       set_option(options, OPTC_THRESHOLDS);
                        *format |= FMT_THRESHOLDS;
                        break;
                case TAG_PERSISTENTCONN:
-                       set_option(options, OPT_PERSISTENTCONN);
+                       set_option(options, OPTC_PERSISTENTCONN);
                        *format |= FMT_PERSISTENTCONN;
                        break;
                case TAG_NO_SORT:
-                       set_option(options, OPT_NOSORT  );
+                       set_option(options, OPTC_NOSORT);
                        *format |= FMT_NOSORT;
                        break;
                case TAG_SORT:
                        /* Sort is the default, this is a no-op for 
compatibility */
                        break;
                case 'X':
-                       set_option(options, OPT_EXACT);
+                       set_option(options, OPTC_EXACT);
                        *format |= FMT_EXACT;
                        break;
                case '6':
@@ -720,20 +837,20 @@
                        }
                        break;
                case 'o':
-                       set_option(options, OPT_ONEPACKET);
+                       set_option(options, OPTC_ONEPACKET);
                        ce->svc.flags |= IP_VS_SVC_F_ONEPACKET;
                        break;
                case TAG_PERSISTENCE_ENGINE:
-                       set_option(options, OPT_PERSISTENCE_ENGINE);
+                       set_option(options, OPTC_PERSISTENCE_ENGINE);
                        strncpy(ce->svc.pe_name, optarg, IP_VS_PENAME_MAXLEN);
                        break;
                case 'b':
-                       set_option(options, OPT_SCHED_FLAGS);
+                       set_option(options, OPTC_SCHED_FLAGS);
                        snprintf(sched_flags_arg, sizeof(sched_flags_arg),
                                "%s", optarg);
                        break;
                case TAG_MCAST_GROUP:
-                       set_option(options, OPT_MCAST_GROUP);
+                       set_option(options, OPTC_MCAST_GROUP);
                        if (strchr(optarg, ':')) {
                                if (inet_pton(AF_INET6, optarg,
                                              &ce->daemon.mcast_group) <= 0 ||
@@ -753,26 +870,56 @@
                        }
                        break;
                case TAG_MCAST_PORT:
-                       set_option(options, OPT_MCAST_PORT);
+                       set_option(options, OPTC_MCAST_PORT);
                        parse = string_to_number(optarg, 1, 65535);
                        if (parse == -1)
                                fail(2, "illegal mcast-port specified");
                        ce->daemon.mcast_port = parse;
                        break;
                case TAG_MCAST_TTL:
-                       set_option(options, OPT_MCAST_TTL);
+                       set_option(options, OPTC_MCAST_TTL);
                        parse = string_to_number(optarg, 1, 255);
                        if (parse == -1)
                                fail(2, "illegal mcast-ttl specified");
                        ce->daemon.mcast_ttl = parse;
                        break;
                case TAG_SYNC_MAXLEN:
-                       set_option(options, OPT_SYNC_MAXLEN);
+                       set_option(options, OPTC_SYNC_MAXLEN);
                        parse = string_to_number(optarg, 1, 65535 - 20 - 8);
                        if (parse == -1)
                                fail(2, "illegal sync-maxlen specified");
                        ce->daemon.sync_maxlen = parse;
                        break;
+               case TAG_TUN_INFO:
+                       set_option(options, OPTC_TUN_INFO);
+                       *format |= FMT_TUN_INFO;
+                       break;
+               case TAG_TUN_TYPE:
+                       set_option(options, OPTC_TUN_TYPE);
+                       parse = parse_tun_type(optarg);
+                       if (parse == -1)
+                               fail(2, "illegal tunnel type specified");
+                       ce->dest.tun_type = parse;
+                       break;
+               case TAG_TUN_PORT:
+                       set_option(options, OPTC_TUN_PORT);
+                       parse = string_to_number(optarg, 1, 65535);
+                       if (parse == -1)
+                               fail(2, "illegal tunnel port specified");
+                       ce->dest.tun_port = htons(parse);
+                       break;
+               case TAG_TUN_NOCSUM:
+                       set_option(options, OPTC_TUN_NOCSUM);
+                       ce->dest.tun_flags |= IP_VS_TUNNEL_ENCAP_FLAG_NOCSUM;
+                       break;
+               case TAG_TUN_CSUM:
+                       set_option(options, OPTC_TUN_CSUM);
+                       ce->dest.tun_flags |= IP_VS_TUNNEL_ENCAP_FLAG_CSUM;
+                       break;
+               case TAG_TUN_REMCSUM:
+                       set_option(options, OPTC_TUN_REMCSUM);
+                       ce->dest.tun_flags |= IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM;
+                       break;
                default:
                        fail(2, "invalid option `%s'",
                             poptBadOption(context, POPT_BADOPTION_NOALIAS));
@@ -845,14 +992,21 @@
 static int process_options(int argc, char **argv, int reading_stdin)
 {
        struct ipvs_command_entry ce;
-       unsigned int options = OPT_NONE;
+       unsigned long long options = OPT_NONE;
        unsigned int format = FMT_NONE;
+       unsigned int fwd_method;
        int result = 0;
 
        memset(&ce, 0, sizeof(struct ipvs_command_entry));
        ce.cmd = CMD_NONE;
        /* Set the default weight 1 */
        ce.dest.weight = 1;
+       /* Set the default tunnel type 0(ipip) */
+       ce.dest.tun_type = 0;
+       /* Set the default tunnel port 0(n/a) */
+       ce.dest.tun_port = 0;
+       /* Set the default tunnel flags 0(nocsum) */
+       ce.dest.tun_flags = 0;
        /* Set direct routing as default forwarding method */
        ce.dest.conn_flags = IP_VS_CONN_F_DROUTE;
        /* Set the default persistent granularity to /32 mask */
@@ -883,6 +1037,8 @@
        if (ce.cmd == CMD_STARTDAEMON && strlen(ce.daemon.mcast_ifn) == 0)
                strcpy(ce.daemon.mcast_ifn, DEF_MCAST_IFN);
 
+       fwd_method = ce.dest.conn_flags & IP_VS_CONN_F_FWD_MASK;
+
        if (ce.cmd == CMD_ADDDEST || ce.cmd == CMD_EDITDEST) {
                /*
                 * The destination port must be equal to the service port
@@ -890,15 +1046,25 @@
                 * Don't worry about this if fwmark is used.
                 */
                if (!ce.svc.fwmark &&
-                   (ce.dest.conn_flags == IP_VS_CONN_F_TUNNEL
-                    || ce.dest.conn_flags == IP_VS_CONN_F_DROUTE))
+                   (fwd_method == IP_VS_CONN_F_TUNNEL ||
+                    fwd_method == IP_VS_CONN_F_DROUTE))
                        ce.dest.port = ce.svc.port;
 
                /* Tunneling allows different address family */
                if (ce.dest.af != ce.svc.af &&
-                   ce.dest.conn_flags != IP_VS_CONN_F_TUNNEL)
+                   fwd_method != IP_VS_CONN_F_TUNNEL)
                        fail(2, "Different address family is allowed only "
                             "for tunneling servers");
+
+               /* Only tunneling allows tunnel options */
+               if (((options & (OPT_TUN_TYPE | OPT_TUN_PORT)) ||
+                    (options & (OPT_TUN_NOCSUM | OPT_TUN_CSUM)) ||
+                    (options & OPT_TUN_REMCSUM)) &&
+                   fwd_method != IP_VS_CONN_F_TUNNEL)
+                       fail(2,
+                            "Tunnel options conflict with forward method");
+
+               tunnel_opt_check(ce.dest.tun_type, options);
        }
 
        switch (ce.cmd) {
@@ -1145,6 +1311,16 @@
                        if (strcmp(sched, "sh"))
                                fail(2, "incompatible scheduler flag `%s'",
                                     flag);
+               } else if (!strcmp(flag, "mh-fallback")) {
+                       flags |= IP_VS_SVC_F_SCHED_MH_FALLBACK;
+                       if (strcmp(sched, "mh"))
+                               fail(2, "incompatible scheduler flag `%s'",
+                                    flag);
+               } else if (!strcmp(flag, "mh-port")) {
+                       flags |= IP_VS_SVC_F_SCHED_MH_PORT;
+                       if (strcmp(sched, "mh"))
+                               fail(2, "incompatible scheduler flag `%s'",
+                                    flag);
                } else {
                        fail(2, "invalid scheduler flag `%s'", flag);
                }
@@ -1153,8 +1329,24 @@
        return flags;
 }
 
+static int parse_tun_type(const char *tun_type)
+{
+       int type = -1;
+
+       if (!strcmp(tun_type, "ipip"))
+               type = IP_VS_CONN_F_TUNNEL_TYPE_IPIP;
+       else if (!strcmp(tun_type, "gue"))
+               type = IP_VS_CONN_F_TUNNEL_TYPE_GUE;
+       else if (!strcmp(tun_type, "gre"))
+               type = IP_VS_CONN_F_TUNNEL_TYPE_GRE;
+       else
+               type = -1;
+
+       return type;
+}
+
 static void
-generic_opt_check(int command, int options)
+generic_opt_check(int command, unsigned long long options)
 {
        int i, j;
        int last = 0, count = 0;
@@ -1163,7 +1355,7 @@
        i = command - CMD_NONE -1;
 
        for (j = 0; j < NUMBER_OF_OPT; j++) {
-               if (!(options & (1<<j))) {
+               if (!(options & (1ULL << j))) {
                        if (commands_v_options[i][j] == '+')
                                fail(2, "You need to supply the '%s' "
                                     "option for the '%s' command",
@@ -1187,13 +1379,39 @@
        }
 }
 
-static inline const char *
-opt2name(int option)
+static void
+tunnel_opt_check(int tun_type, unsigned long long options)
 {
-       const char **ptr;
-       for (ptr = optnames; option > 1; option >>= 1, ptr++);
+       int i, j, k;
+       int last = 0, count = 0;
 
-       return *ptr;
+       /* Check that tunnel types are valid with options. */
+       i = tun_type;
+
+       for (j = 0; j < NUMBER_OF_TUN_OPT; j++) {
+               k = tunopts[j];
+               if (!(options & (1ULL << k))) {
+                       if (tunnel_types_v_options[i][j] == '+')
+                               fail(2, "You need to supply the '%s' "
+                                    "option for the '%s' tunnel type",
+                                    optnames[k], tunnames[i]);
+               } else {
+                       if (tunnel_types_v_options[i][j] == 'x')
+                               fail(2, "Illegal '%s' option with "
+                                    "the '%s' tunnel type",
+                                    optnames[k], tunnames[i]);
+                       if (tunnel_types_v_options[i][j] == '1') {
+                               count++;
+                               if (count == 1) {
+                                       last = k;
+                                       continue;
+                               }
+                               fail(2, "The option '%s' conflicts with the "
+                                    "'%s' option in the '%s' tunnel type",
+                                    optnames[k], optnames[last], tunnames[i]);
+                       }
+               }
+       }
 }
 
 static void
@@ -1205,10 +1423,11 @@
 }
 
 static void
-set_option(unsigned int *options, unsigned int option)
+set_option(unsigned long long *options, int optc)
 {
+       unsigned long long option = 1ULL << optc;
        if (*options & option)
-               fail(2, "multiple '%s' options specified", opt2name(option));
+               fail(2, "multiple '%s' options specified", optnames[optc]);
        *options |= option;
 }
 
@@ -1291,6 +1510,12 @@
                "  --gatewaying   -g                   gatewaying (direct 
routing) (default)\n"
                "  --ipip         -i                   ipip encapsulation 
(tunneling)\n"
                "  --masquerading -m                   masquerading (NAT)\n"
+               "  --tun-type      type                one of ipip|gue|gre,\n"
+               "                                      the default tunnel type 
is %s.\n"
+               "  --tun-port      port                tunnel destination 
port\n"
+               "  --tun-nocsum                        tunnel encapsulation 
without checksum\n"
+               "  --tun-csum                          tunnel encapsulation 
with checksum\n"
+               "  --tun-remcsum                       tunnel encapsulation 
with remote checksum\n"
                "  --weight       -w weight            capacity of real 
server\n"
                "  --u-threshold  -x uthreshold        upper threshold of 
connections\n"
                "  --l-threshold  -y lthreshold        lower threshold of 
connections\n"
@@ -1302,12 +1527,13 @@
                "  --exact                             expand numbers (display 
exact values)\n"
                "  --thresholds                        output of thresholds 
information\n"
                "  --persistent-conn                   output of persistent 
connection info\n"
+               "  --tun-info                          output of tunnel 
information\n"
                "  --nosort                            disable sorting output 
of service/server entries\n"
                "  --sort                              does nothing, for 
backwards compatibility\n"
                "  --ops          -o                   one-packet scheduling\n"
                "  --numeric      -n                   numeric output of 
addresses and ports\n"
                "  --sched-flags  -b flags             scheduler flags 
(comma-separated)\n",
-               DEF_SCHED);
+               DEF_SCHED, DEF_TUNNEL_TYPE);
 
        fprintf(stream,
                "Daemon Options:\n"
@@ -1415,8 +1641,8 @@
        unsigned int    expires;
        unsigned short  af = AF_INET;
        unsigned short  daf = AF_INET;
-       char            pe_name[IP_VS_PENAME_MAXLEN];
-       char            pe_data[IP_VS_PEDATA_MAXLEN];
+       char            pe_name[IP_VS_PENAME_MAXLEN + 1];
+       char            pe_data[IP_VS_PEDATA_MAXLEN + 1];
 
        int n;
        char temp1[INET6_ADDRSTRLEN], temp2[INET6_ADDRSTRLEN], 
temp3[INET6_ADDRSTRLEN];
@@ -1555,6 +1781,41 @@
 }
 
 
+static inline char *fwd_tun_info(ipvs_dest_entry_t *e)
+{
+       char *info = malloc(16);
+
+       if (!info)
+               return NULL;
+
+       switch (e->conn_flags & IP_VS_CONN_F_FWD_MASK) {
+       case IP_VS_CONN_F_TUNNEL:
+               switch (e->tun_type) {
+               case IP_VS_CONN_F_TUNNEL_TYPE_IPIP:
+                       snprintf(info, 16, "%s", tunnames[e->tun_type]);
+                       break;
+               case IP_VS_CONN_F_TUNNEL_TYPE_GUE:
+                       snprintf(info, 16, "%s:%d:%s",
+                                tunnames[e->tun_type], ntohs(e->tun_port),
+                                tunflags[e->tun_flags]);
+                       break;
+               case IP_VS_CONN_F_TUNNEL_TYPE_GRE:
+                       snprintf(info, 16, "%s:%s",
+                                tunnames[e->tun_type],
+                                tunflags[e->tun_flags]);
+                       break;
+               default:
+                       free(info);
+                       return NULL;
+               }
+               break;
+       default:
+               free(info);
+               return NULL;
+       }
+       return info;
+}
+
 static void print_largenum(unsigned long long i, unsigned int format)
 {
        if (format & FMT_EXACT) {
@@ -1589,8 +1850,11 @@
                        strcat(flags, "sh-fallback,");
                if (se->flags & IP_VS_SVC_F_SCHED_SH_PORT)
                        strcat(flags, "sh-port,");
-               if (se->flags & IP_VS_SVC_F_SCHED3)
-                       strcat(flags, "flag-3,");
+       } else if (!strcmp(se->sched_name, "mh")) {
+               if (se->flags & IP_VS_SVC_F_SCHED_MH_FALLBACK)
+                       strcat(flags, "mh-fallback,");
+               if (se->flags & IP_VS_SVC_F_SCHED_MH_PORT)
+                       strcat(flags, "mh-port,");
        } else {
                if (se->flags & IP_VS_SVC_F_SCHED1)
                        strcat(flags, "flag-1,");
@@ -1628,12 +1892,56 @@
                       "  -> RemoteAddress:Port\n",
                       "Prot LocalAddress:Port",
                       "Weight", "PersistConn", "ActiveConn", "InActConn");
+       else if ((format & FMT_TUN_INFO))
+               printf("Prot LocalAddress:Port Scheduler Flags\n"
+                      "  -> RemoteAddress:Port           Forward TunnelInfo    
Weight ActiveConn InActConn\n");
        else if (!(format & FMT_RULE))
                printf("Prot LocalAddress:Port Scheduler Flags\n"
                       "  -> RemoteAddress:Port           Forward Weight 
ActiveConn InActConn\n");
 }
 
 
+static inline void
+print_tunnel_rule(char *svc_name, char *dname, ipvs_dest_entry_t *e)
+{
+       switch (e->tun_type) {
+       case IP_VS_CONN_F_TUNNEL_TYPE_GRE:
+               printf("-a %s -r %s %s -w %d --tun-type %s %s\n",
+                      svc_name,
+                      dname,
+                      fwd_switch(e->conn_flags),
+                      e->weight,
+                      tunnames[e->tun_type],
+                      tun_flags_opts[e->tun_flags]);
+               break;
+       case IP_VS_CONN_F_TUNNEL_TYPE_GUE:
+               printf("-a %s -r %s %s -w %d --tun-type %s --tun-port %d %s\n",
+                      svc_name,
+                      dname,
+                      fwd_switch(e->conn_flags),
+                      e->weight,
+                      tunnames[e->tun_type],
+                      ntohs(e->tun_port),
+                      tun_flags_opts[e->tun_flags]);
+               break;
+       case IP_VS_CONN_F_TUNNEL_TYPE_IPIP:
+               printf("-a %s -r %s %s -w %d --tun-type %s\n",
+                      svc_name,
+                      dname,
+                      fwd_switch(e->conn_flags),
+                      e->weight,
+                      tunnames[e->tun_type]);
+               break;
+       default:
+               printf("-a %s -r %s %s -w %d\n",
+                      svc_name,
+                      dname,
+                      fwd_switch(e->conn_flags),
+                      e->weight);
+               break;
+       }
+}
+
 static void
 print_service_entry(ipvs_service_entry_t *se, unsigned int format)
 {
@@ -1755,6 +2063,7 @@
        for (i = 0; i < d->num_dests; i++) {
                char *dname;
                ipvs_dest_entry_t *e = &d->entrytable[i];
+               unsigned int fwd_method = e->conn_flags & IP_VS_CONN_F_FWD_MASK;
 
                if (!(dname = addrport_to_anyname(e->af, &(e->addr), 
ntohs(e->port),
                                                  se->protocol, format))) {
@@ -1765,8 +2074,15 @@
                        dname[28] = '\0';
 
                if (format & FMT_RULE) {
-                       printf("-a %s -r %s %s -w %d\n", svc_name, dname,
-                              fwd_switch(e->conn_flags), e->weight);
+                       if (fwd_method == IP_VS_CONN_F_TUNNEL) {
+                               print_tunnel_rule(svc_name, dname, e);
+                       } else {
+                               printf("-a %s -r %s %s -w %d\n",
+                                      svc_name,
+                                      dname,
+                                      fwd_switch(e->conn_flags),
+                                      e->weight);
+                       }
                } else if (format & FMT_STATS) {
                        printf("  -> %-28s", dname);
                        print_largenum(e->stats64.conns, format);
@@ -1791,6 +2107,15 @@
                        printf("  -> %-28s %-9u %-11u %-10u %-10u\n", dname,
                               e->weight, e->persistconns,
                               e->activeconns, e->inactconns);
+               } else if (format & FMT_TUN_INFO) {
+                       char *ti = fwd_tun_info(e);
+
+                       printf("  -> %-28s %-7s %-13s %-6d %-10u %-10u\n",
+                              dname, fwd_name(e->conn_flags),
+                              ti ? : NA,
+                              e->weight, e->activeconns, e->inactconns);
+
+                       free(ti);
                } else
                        printf("  -> %-28s %-7s %-6d %-10u %-10u\n",
                               dname, fwd_name(e->conn_flags),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipvsadm-1.29/ipvsadm.spec 
new/ipvsadm-1.31/ipvsadm.spec
--- old/ipvsadm-1.29/ipvsadm.spec       2016-12-23 11:45:37.000000000 +0100
+++ new/ipvsadm-1.31/ipvsadm.spec       2019-12-24 14:27:30.000000000 +0100
@@ -2,7 +2,7 @@
 
 Summary: Utility to administer the Linux Virtual Server
 Name: ipvsadm
-Version: 1.29
+Version: 1.31
 Release: 1
 License: GPL
 URL: http://www.LinuxVirtualServer.org/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipvsadm-1.29/libipvs/ip_vs.h 
new/ipvsadm-1.31/libipvs/ip_vs.h
--- old/ipvsadm-1.29/libipvs/ip_vs.h    2016-12-23 11:38:16.000000000 +0100
+++ new/ipvsadm-1.31/libipvs/ip_vs.h    2019-12-24 14:20:30.000000000 +0100
@@ -36,6 +36,9 @@
 #define IP_VS_SVC_F_SCHED_SH_FALLBACK  IP_VS_SVC_F_SCHED1 /* SH fallback */
 #define IP_VS_SVC_F_SCHED_SH_PORT      IP_VS_SVC_F_SCHED2 /* SH use port */
 
+#define IP_VS_SVC_F_SCHED_MH_FALLBACK  IP_VS_SVC_F_SCHED1 /* MH fallback */
+#define IP_VS_SVC_F_SCHED_MH_PORT      IP_VS_SVC_F_SCHED2 /* MH use port */
+
 
 /*
  *      IPVS sync daemon states
@@ -104,6 +107,19 @@
 
 #define IP_VS_PEDATA_MAXLEN    255
 
+/* Tunnel types */
+enum {
+       IP_VS_CONN_F_TUNNEL_TYPE_IPIP = 0,      /* IPIP */
+       IP_VS_CONN_F_TUNNEL_TYPE_GUE,           /* GUE */
+       IP_VS_CONN_F_TUNNEL_TYPE_GRE,           /* GRE */
+       IP_VS_CONN_F_TUNNEL_TYPE_MAX,
+};
+
+/* Tunnel encapsulation flags */
+#define IP_VS_TUNNEL_ENCAP_FLAG_NOCSUM         (0)
+#define IP_VS_TUNNEL_ENCAP_FLAG_CSUM           (1 << 0)
+#define IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM                (1 << 1)
+
 union nf_inet_addr {
         __u32           all[4];
         __be32          ip;
@@ -144,7 +160,7 @@
        __be32                  netmask;        /* persistent netmask */
        u_int16_t               af;
        union nf_inet_addr      addr;
-       char                    pe_name[IP_VS_PENAME_MAXLEN];
+       char                    pe_name[IP_VS_PENAME_MAXLEN + 1];
 };
 
 struct ip_vs_dest_kern {
@@ -175,6 +191,11 @@
        u_int32_t               l_threshold;    /* lower threshold */
        u_int16_t               af;
        union nf_inet_addr      addr;
+
+       /* tunnel info */
+       u_int16_t               tun_type;       /* tunnel type */
+       __be16                  tun_port;       /* tunnel port */
+       u_int16_t               tun_flags;      /* tunnel flags */
 };
 
 /*
@@ -267,7 +288,7 @@
 
        u_int16_t               af;
        union nf_inet_addr      addr;
-       char                    pe_name[IP_VS_PENAME_MAXLEN];
+       char                    pe_name[IP_VS_PENAME_MAXLEN + 1];
 
        /* statistics, 64-bit */
        struct ip_vs_stats64    stats64;
@@ -310,6 +331,11 @@
 
        /* statistics, 64-bit */
        struct ip_vs_stats64    stats64;
+
+       /* tunnel info */
+       u_int16_t               tun_type;       /* tunnel type */
+       __be16                  tun_port;       /* tunnel port */
+       u_int16_t               tun_flags;      /* tunnel flags */
 };
 
 /* The argument to IP_VS_SO_GET_DESTS */
@@ -524,6 +550,12 @@
 
        IPVS_DEST_ATTR_STATS64,         /* nested attribute for dest stats */
 
+       IPVS_DEST_ATTR_TUN_TYPE,        /* tunnel type */
+
+       IPVS_DEST_ATTR_TUN_PORT,        /* tunnel port */
+
+       IPVS_DEST_ATTR_TUN_FLAGS,       /* tunnel flags */
+
        __IPVS_DEST_ATTR_MAX,
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipvsadm-1.29/libipvs/libipvs.c 
new/ipvsadm-1.31/libipvs/libipvs.c
--- old/ipvsadm-1.29/libipvs/libipvs.c  2016-12-23 11:38:16.000000000 +0100
+++ new/ipvsadm-1.31/libipvs/libipvs.c  2019-12-24 14:20:30.000000000 +0100
@@ -63,7 +63,7 @@
        if (!msg)
                return NULL;
 
-       genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, flags,
+       genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, family, 0, flags,
                    cmd, IPVS_GENL_VERSION);
 
        return msg;
@@ -74,9 +74,23 @@
        return NL_OK;
 }
 
+struct cb_err_data {
+       int     err;
+};
+
+static int ipvs_nl_err_cb(struct sockaddr_nl *nla, struct nlmsgerr *nlerr,
+                         void *arg)
+{
+       struct cb_err_data *data = arg;
+
+       data->err = nlerr->error;
+       return -nl_syserr2nlerr(nlerr->error);
+}
+
 int ipvs_nl_send_message(struct nl_msg *msg, nl_recvmsg_msg_cb_t func, void 
*arg)
 {
        int err = EINVAL;
+       struct cb_err_data err_data = { .err = 0 };
 
        sock = nl_socket_alloc();
        if (!sock) {
@@ -100,12 +114,18 @@
 
        if (nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, func, arg) != 
0)
                goto fail_genl;
+       if (nl_socket_modify_err_cb(sock, NL_CB_CUSTOM, ipvs_nl_err_cb,
+                                   &err_data) != 0)
+               goto fail_genl;
 
        if (nl_send_auto_complete(sock, msg) < 0)
                goto fail_genl;
 
-       if ((err = -nl_recvmsgs_default(sock)) > 0)
+       if (nl_recvmsgs_default(sock) < 0) {
+               if (err_data.err)
+                       err = -err_data.err;
                goto fail_genl;
+       }
 
        nlmsg_free(msg);
 
@@ -370,6 +390,9 @@
        NLA_PUT_U16(msg, IPVS_DEST_ATTR_PORT, dst->port);
        NLA_PUT_U32(msg, IPVS_DEST_ATTR_FWD_METHOD, dst->conn_flags & 
IP_VS_CONN_F_FWD_MASK);
        NLA_PUT_U32(msg, IPVS_DEST_ATTR_WEIGHT, dst->weight);
+       NLA_PUT_U8(msg, IPVS_DEST_ATTR_TUN_TYPE, dst->tun_type);
+       NLA_PUT_U16(msg, IPVS_DEST_ATTR_TUN_PORT, dst->tun_port);
+       NLA_PUT_U16(msg, IPVS_DEST_ATTR_TUN_FLAGS, dst->tun_flags);
        NLA_PUT_U32(msg, IPVS_DEST_ATTR_U_THRESH, dst->u_threshold);
        NLA_PUT_U32(msg, IPVS_DEST_ATTR_L_THRESH, dst->l_threshold);
 
@@ -699,7 +722,7 @@
 
        strncpy(get->entrytable[i].sched_name,
                nla_get_string(svc_attrs[IPVS_SVC_ATTR_SCHED_NAME]),
-               IP_VS_SCHEDNAME_MAXLEN);
+               IP_VS_SCHEDNAME_MAXLEN - 1);
 
        if (svc_attrs[IPVS_SVC_ATTR_PE_NAME])
                strncpy(get->entrytable[i].pe_name,
@@ -836,6 +859,9 @@
        struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
        struct nlattr *dest_attrs[IPVS_DEST_ATTR_MAX + 1];
        struct nlattr *attr_addr_family = NULL;
+       struct nlattr *attr_tun_type = NULL;
+       struct nlattr *attr_tun_port = NULL;
+       struct nlattr *attr_tun_flags = NULL;
        struct ip_vs_get_dests **dp = (struct ip_vs_get_dests **)arg;
        struct ip_vs_get_dests *d = (struct ip_vs_get_dests *)*dp;
        int i = d->num_dests;
@@ -868,6 +894,15 @@
        d->entrytable[i].port = nla_get_u16(dest_attrs[IPVS_DEST_ATTR_PORT]);
        d->entrytable[i].conn_flags = 
nla_get_u32(dest_attrs[IPVS_DEST_ATTR_FWD_METHOD]);
        d->entrytable[i].weight = 
nla_get_u32(dest_attrs[IPVS_DEST_ATTR_WEIGHT]);
+       attr_tun_type = dest_attrs[IPVS_DEST_ATTR_TUN_TYPE];
+       if (attr_tun_type)
+               d->entrytable[i].tun_type = nla_get_u8(attr_tun_type);
+       attr_tun_port = dest_attrs[IPVS_DEST_ATTR_TUN_PORT];
+       if (attr_tun_port)
+               d->entrytable[i].tun_port = nla_get_u16(attr_tun_port);
+       attr_tun_flags = dest_attrs[IPVS_DEST_ATTR_TUN_FLAGS];
+       if (attr_tun_flags)
+               d->entrytable[i].tun_flags = nla_get_u16(attr_tun_flags);
        d->entrytable[i].u_threshold = 
nla_get_u32(dest_attrs[IPVS_DEST_ATTR_U_THRESH]);
        d->entrytable[i].l_threshold = 
nla_get_u32(dest_attrs[IPVS_DEST_ATTR_L_THRESH]);
        d->entrytable[i].activeconns = 
nla_get_u32(dest_attrs[IPVS_DEST_ATTR_ACTIVE_CONNS]);
@@ -1179,7 +1214,7 @@
        u[i].state = nla_get_u32(daemon_attrs[IPVS_DAEMON_ATTR_STATE]);
        strncpy(u[i].mcast_ifn,
                nla_get_string(daemon_attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
-               IP_VS_IFNAME_MAXLEN);
+               IP_VS_IFNAME_MAXLEN - 1);
        u[i].syncid = nla_get_u32(daemon_attrs[IPVS_DAEMON_ATTR_SYNC_ID]);
 
        a = daemon_attrs[IPVS_DAEMON_ATTR_SYNC_MAXLEN];
@@ -1245,7 +1280,8 @@
        }
        for (i = 0; i < 2; i++) {
                u[i].state = dmk[i].state;
-               strncpy(u[i].mcast_ifn, dmk[i].mcast_ifn, IP_VS_IFNAME_MAXLEN);
+               strncpy(u[i].mcast_ifn, dmk[i].mcast_ifn,
+                       IP_VS_IFNAME_MAXLEN - 1);
                u[i].syncid = dmk[i].syncid;
        }
        return u;

++++++ ipvsadm-makefile.patch ++++++
diff -Nur ipvsadm-1.31/Makefile new/Makefile
--- ipvsadm-1.31/Makefile       2019-12-24 14:20:30.000000000 +0100
+++ new/Makefile        2022-04-24 01:42:51.839729180 +0200
@@ -38,9 +38,9 @@
 CC             = gcc
 INCLUDE                =
 SBIN           = $(BUILD_ROOT)/sbin
-MANDIR         = usr/man
+MANDIR         = usr/share/man
 MAN            = $(BUILD_ROOT)/$(MANDIR)/man8
-INIT           = $(BUILD_ROOT)/etc/rc.d/init.d
+INIT           = $(BUILD_ROOT)/etc/init.d
 MKDIR          = mkdir
 INSTALL                = install
 STATIC_LIBS    = libipvs/libipvs.a
@@ -87,7 +87,7 @@
                make -C libipvs
 
 ipvsadm:       $(OBJS) $(STATIC_LIBS)
-               $(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+               $(CC) $(CFLAGS) -pie -o $@ $^ $(LIBS)
 
 install:        all
                if [ ! -d $(SBIN) ]; then $(MKDIR) -p $(SBIN); fi
@@ -99,7 +99,7 @@
                $(INSTALL) -m 0644 ipvsadm-save.8 $(MAN)
                $(INSTALL) -m 0644 ipvsadm-restore.8 $(MAN)
                [ -d $(INIT) ] || $(MKDIR) -p $(INIT)
-               $(INSTALL) -m 0755 ipvsadm.sh $(INIT)/ipvsadm
+               $(INSTALL) -m 0754 ipvsadm.sh $(INIT)/ipvsadm
 
 clean:
                rm -f ipvsadm $(NAME).spec $(NAME)-$(VERSION).tar.gz

++++++ ipvsadm-print_largenum.patch ++++++

(No newline at EOF)

Reply via email to