@@ -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,9 @@ 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);
+ addattr8 (&req.n, 1024, L2TP_ATTR_UDP_CSUM, p->udp_csum);
+ addattr8 (&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_TX, p->udp6_csum_tx);
+ addattr8 (&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_RX, p->udp6_csum_rx);
}
if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
@@ -282,6 +287,14 @@ 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];
+ if (attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX])
+ p->udp6_csum_tx = rta_getattr_u8(attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX]);
+ else
+ p->udp6_csum_tx = 1;
+ if (attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX])
+ p->udp6_csum_rx = rta_getattr_u8(attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX]);
+ else
+ 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]));
@@ -470,6 +483,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");
@@ -500,6 +516,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) {
@@ -569,6 +587,33 @@ 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;