Three options are added for the user to control
whether the checksum is enabled

Signed-off-by: Miao Wang <miao.w...@tuna.tsinghua.edu.cn>
---
 ip/ipl2tp.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c
index 1f84c61..9ebda13 100644
--- a/ip/ipl2tp.c
+++ b/ip/ipl2tp.c
@@ -56,6 +56,8 @@ struct l2tp_parm {
 
        uint16_t pw_type;
        uint16_t mtu;
+       int udp6_csum_tx:1;
+       int udp6_csum_rx:1;
        int udp_csum:1;
        int recv_seq:1;
        int send_seq:1;
@@ -117,6 +119,12 @@ static int create_tunnel(struct l2tp_parm *p)
        if (p->encap == L2TP_ENCAPTYPE_UDP) {
                addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port);
                addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port);
+               if (p->udp_csum)
+                       addattr(&req.n, 1024, L2TP_ATTR_UDP_CSUM);
+               if (!p->udp6_csum_tx)
+                       addattr(&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_TX);
+               if (!p->udp6_csum_rx)
+                       addattr(&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_RX);
        }
 
        if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
@@ -282,6 +290,12 @@ static int get_response(struct nlmsghdr *n, void *arg)
                p->l2spec_len = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_LEN]);
 
        p->udp_csum = !!attrs[L2TP_ATTR_UDP_CSUM];
+       /*
+        * Not fetching from L2TP_ATTR_UDP_ZERO_CSUM6_{T,R}X because the
+        * kernel doesn't send it so just leave it as default value.
+        */
+       p->udp6_csum_tx = 1;
+       p->udp6_csum_rx = 1;
        if (attrs[L2TP_ATTR_COOKIE])
                memcpy(p->cookie, RTA_DATA(attrs[L2TP_ATTR_COOKIE]),
                       p->cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_COOKIE]));
@@ -459,6 +473,9 @@ static void usage(void)
        fprintf(stderr, "          tunnel_id ID peer_tunnel_id ID\n");
        fprintf(stderr, "          [ encap { ip | udp } ]\n");
        fprintf(stderr, "          [ udp_sport PORT ] [ udp_dport PORT ]\n");
+       fprintf(stderr, "          [ udp_csum { on | off } ]\n");
+       fprintf(stderr, "          [ udp6_csum_tx { on | off } ]\n");
+       fprintf(stderr, "          [ udp6_csum_rx { on | off } ]\n");
        fprintf(stderr, "Usage: ip l2tp add session [ name NAME ]\n");
        fprintf(stderr, "          tunnel_id ID\n");
        fprintf(stderr, "          session_id ID peer_session_id ID\n");
@@ -489,6 +506,8 @@ static int parse_args(int argc, char **argv, int cmd, 
struct l2tp_parm *p)
        /* Defaults */
        p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT;
        p->l2spec_len = 4;
+       p->udp6_csum_rx = 1;
+       p->udp6_csum_tx = 1;
 
        while (argc > 0) {
                if (strcmp(*argv, "encap") == 0) {
@@ -558,6 +577,32 @@ static int parse_args(int argc, char **argv, int cmd, 
struct l2tp_parm *p)
                        if (get_u16(&uval, *argv, 0))
                                invarg("invalid port\n", *argv);
                        p->peer_udp_port = uval;
+               } else if (strcmp(*argv, "udp_csum") == 0) {
+                       NEXT_ARG();
+                       if (strcmp(*argv, "on") == 0)
+                               p->udp_csum = 1;
+                       else if (strcmp(*argv, "off") == 0)
+                               p->udp_csum = 0;
+                       else
+                               invarg("invalid option for udp_csum\n", *argv);
+               } else if (strcmp(*argv, "udp6_csum_rx") == 0) {
+                       NEXT_ARG();
+                       if (strcmp(*argv, "on") == 0)
+                               p->udp6_csum_rx = 1;
+                       else if (strcmp(*argv, "off") == 0)
+                               p->udp6_csum_rx = 0;
+                       else
+                               invarg("invalid option for udp6_csum_rx\n"
+                                               , *argv);
+               } else if (strcmp(*argv, "udp6_csum_tx") == 0) {
+                       NEXT_ARG();
+                       if (strcmp(*argv, "on") == 0)
+                               p->udp6_csum_tx = 1;
+                       else if (strcmp(*argv, "off") == 0)
+                               p->udp6_csum_tx = 0;
+                       else
+                               invarg("invalid option for udp6_csum_tx\n"
+                                               , *argv);
                } else if (strcmp(*argv, "offset") == 0) {
                        __u8 uval;
 
-- 
2.5.2

Reply via email to