4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Original Author: James Chapman <jchapman@katalix.com>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <arpa/inet.h>
21 #include <sys/ioctl.h>
23 #include <linux/if_arp.h>
26 #include <linux/genetlink.h>
27 #include <linux/l2tp.h>
31 #include "ip_common.h"
42 uint32_t peer_tunnel_id
;
44 uint32_t peer_session_id
;
45 enum l2tp_encap_type encap
;
46 uint16_t local_udp_port
;
47 uint16_t peer_udp_port
;
51 uint8_t peer_cookie
[8];
57 unsigned int udp6_csum_tx
:1;
58 unsigned int udp6_csum_rx
:1;
59 unsigned int udp_csum
:1;
60 unsigned int recv_seq
:1;
61 unsigned int send_seq
:1;
62 unsigned int lns_mode
:1;
63 unsigned int data_seq
:2;
64 unsigned int tunnel
:1;
65 unsigned int session
:1;
73 uint64_t data_rx_packets
;
74 uint64_t data_rx_bytes
;
75 uint64_t data_rx_errors
;
76 uint64_t data_rx_oos_packets
;
77 uint64_t data_rx_oos_discards
;
78 uint64_t data_tx_packets
;
79 uint64_t data_tx_bytes
;
80 uint64_t data_tx_errors
;
84 struct l2tp_parm config
;
85 struct l2tp_stats stats
;
89 static struct rtnl_handle genl_rth
;
90 static int genl_family
= -1;
92 /*****************************************************************************
94 *****************************************************************************/
96 static int create_tunnel(struct l2tp_parm
*p
)
98 uint32_t local_attr
= L2TP_ATTR_IP_SADDR
;
99 uint32_t peer_attr
= L2TP_ATTR_IP_DADDR
;
101 GENL_REQUEST(req
, 1024, genl_family
, 0, L2TP_GENL_VERSION
,
102 L2TP_CMD_TUNNEL_CREATE
, NLM_F_REQUEST
| NLM_F_ACK
);
104 addattr32(&req
.n
, 1024, L2TP_ATTR_CONN_ID
, p
->tunnel_id
);
105 addattr32(&req
.n
, 1024, L2TP_ATTR_PEER_CONN_ID
, p
->peer_tunnel_id
);
106 addattr8(&req
.n
, 1024, L2TP_ATTR_PROTO_VERSION
, 3);
107 addattr16(&req
.n
, 1024, L2TP_ATTR_ENCAP_TYPE
, p
->encap
);
109 if (p
->local_ip
.family
== AF_INET6
)
110 local_attr
= L2TP_ATTR_IP6_SADDR
;
111 addattr_l(&req
.n
, 1024, local_attr
, &p
->local_ip
.data
,
112 p
->local_ip
.bytelen
);
114 if (p
->peer_ip
.family
== AF_INET6
)
115 peer_attr
= L2TP_ATTR_IP6_DADDR
;
116 addattr_l(&req
.n
, 1024, peer_attr
, &p
->peer_ip
.data
,
119 if (p
->encap
== L2TP_ENCAPTYPE_UDP
) {
120 addattr16(&req
.n
, 1024, L2TP_ATTR_UDP_SPORT
, p
->local_udp_port
);
121 addattr16(&req
.n
, 1024, L2TP_ATTR_UDP_DPORT
, p
->peer_udp_port
);
123 addattr8(&req
.n
, 1024, L2TP_ATTR_UDP_CSUM
, 1);
124 if (!p
->udp6_csum_tx
)
125 addattr(&req
.n
, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_TX
);
126 if (!p
->udp6_csum_rx
)
127 addattr(&req
.n
, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_RX
);
130 if (rtnl_talk(&genl_rth
, &req
.n
, NULL
) < 0)
136 static int delete_tunnel(struct l2tp_parm
*p
)
138 GENL_REQUEST(req
, 128, genl_family
, 0, L2TP_GENL_VERSION
,
139 L2TP_CMD_TUNNEL_DELETE
, NLM_F_REQUEST
| NLM_F_ACK
);
141 addattr32(&req
.n
, 128, L2TP_ATTR_CONN_ID
, p
->tunnel_id
);
143 if (rtnl_talk(&genl_rth
, &req
.n
, NULL
) < 0)
149 static int create_session(struct l2tp_parm
*p
)
151 GENL_REQUEST(req
, 1024, genl_family
, 0, L2TP_GENL_VERSION
,
152 L2TP_CMD_SESSION_CREATE
, NLM_F_REQUEST
| NLM_F_ACK
);
154 addattr32(&req
.n
, 1024, L2TP_ATTR_CONN_ID
, p
->tunnel_id
);
155 addattr32(&req
.n
, 1024, L2TP_ATTR_PEER_CONN_ID
, p
->peer_tunnel_id
);
156 addattr32(&req
.n
, 1024, L2TP_ATTR_SESSION_ID
, p
->session_id
);
157 addattr32(&req
.n
, 1024, L2TP_ATTR_PEER_SESSION_ID
, p
->peer_session_id
);
158 addattr16(&req
.n
, 1024, L2TP_ATTR_PW_TYPE
, p
->pw_type
);
159 addattr8(&req
.n
, 1024, L2TP_ATTR_L2SPEC_TYPE
, p
->l2spec_type
);
160 addattr8(&req
.n
, 1024, L2TP_ATTR_L2SPEC_LEN
, p
->l2spec_len
);
163 addattr16(&req
.n
, 1024, L2TP_ATTR_MTU
, p
->mtu
);
165 addattr8(&req
.n
, 1024, L2TP_ATTR_RECV_SEQ
, 1);
167 addattr8(&req
.n
, 1024, L2TP_ATTR_SEND_SEQ
, 1);
169 addattr(&req
.n
, 1024, L2TP_ATTR_LNS_MODE
);
171 addattr8(&req
.n
, 1024, L2TP_ATTR_DATA_SEQ
, p
->data_seq
);
172 if (p
->reorder_timeout
)
173 addattr64(&req
.n
, 1024, L2TP_ATTR_RECV_TIMEOUT
,
176 addattr_l(&req
.n
, 1024, L2TP_ATTR_COOKIE
,
177 p
->cookie
, p
->cookie_len
);
178 if (p
->peer_cookie_len
)
179 addattr_l(&req
.n
, 1024, L2TP_ATTR_PEER_COOKIE
,
180 p
->peer_cookie
, p
->peer_cookie_len
);
182 addattrstrz(&req
.n
, 1024, L2TP_ATTR_IFNAME
, p
->ifname
);
184 if (rtnl_talk(&genl_rth
, &req
.n
, NULL
) < 0)
190 static int delete_session(struct l2tp_parm
*p
)
192 GENL_REQUEST(req
, 1024, genl_family
, 0, L2TP_GENL_VERSION
,
193 L2TP_CMD_SESSION_DELETE
, NLM_F_REQUEST
| NLM_F_ACK
);
195 addattr32(&req
.n
, 1024, L2TP_ATTR_CONN_ID
, p
->tunnel_id
);
196 addattr32(&req
.n
, 1024, L2TP_ATTR_SESSION_ID
, p
->session_id
);
197 if (rtnl_talk(&genl_rth
, &req
.n
, NULL
) < 0)
203 static void print_cookie(const char *name
, const char *fmt
,
204 const uint8_t *cookie
, int len
)
209 n
= snprintf(abuf
, sizeof(abuf
),
211 cookie
[0], cookie
[1], cookie
[2], cookie
[3]);
213 snprintf(abuf
+ n
, sizeof(abuf
) - n
,
215 cookie
[4], cookie
[5],
216 cookie
[6], cookie
[7]);
218 print_string(PRINT_ANY
, name
, fmt
, abuf
);
221 static void print_tunnel(const struct l2tp_data
*data
)
223 const struct l2tp_parm
*p
= &data
->config
;
224 char buf
[INET6_ADDRSTRLEN
];
226 open_json_object(NULL
);
227 print_uint(PRINT_ANY
, "tunnel_id", "Tunnel %u,", p
->tunnel_id
);
228 print_string(PRINT_ANY
, "encap", " encap %s",
229 p
->encap
== L2TP_ENCAPTYPE_UDP
? "UDP" :
230 p
->encap
== L2TP_ENCAPTYPE_IP
? "IP" : "??");
231 print_string(PRINT_FP
, NULL
, "%s", _SL_
);
233 print_string(PRINT_ANY
, "local", " From %s ",
234 inet_ntop(p
->local_ip
.family
, p
->local_ip
.data
,
236 print_string(PRINT_ANY
, "peer", "to %s",
237 inet_ntop(p
->peer_ip
.family
, p
->peer_ip
.data
,
239 print_string(PRINT_FP
, NULL
, "%s", _SL_
);
241 print_uint(PRINT_ANY
, "peer_tunnel", " Peer tunnel %u",
243 print_string(PRINT_FP
, NULL
, "%s", _SL_
);
245 if (p
->encap
== L2TP_ENCAPTYPE_UDP
) {
246 print_string(PRINT_FP
, NULL
,
247 " UDP source / dest ports:", NULL
);
249 print_uint(PRINT_ANY
, "local_port", " %hu",
251 print_uint(PRINT_ANY
, "peer_port", "/%hu",
253 print_string(PRINT_FP
, NULL
, "%s", _SL_
);
255 switch (p
->local_ip
.family
) {
257 print_bool(PRINT_JSON
, "checksum",
259 print_string(PRINT_FP
, NULL
,
260 " UDP checksum: %s\n",
261 p
->udp_csum
? "enabled" : "disabled");
264 if (is_json_context()) {
265 print_bool(PRINT_JSON
, "checksum_tx",
266 NULL
, p
->udp6_csum_tx
);
268 print_bool(PRINT_JSON
, "checksum_rx",
269 NULL
, p
->udp6_csum_tx
);
271 printf(" UDP checksum: %s%s%s%s\n",
272 p
->udp6_csum_tx
&& p
->udp6_csum_rx
274 p
->udp6_csum_tx
&& !p
->udp6_csum_rx
276 !p
->udp6_csum_tx
&& p
->udp6_csum_rx
278 !p
->udp6_csum_tx
&& !p
->udp6_csum_rx
287 static void print_session(struct l2tp_data
*data
)
289 struct l2tp_parm
*p
= &data
->config
;
291 open_json_object(NULL
);
293 print_uint(PRINT_ANY
, "session_id", "Session %u", p
->session_id
);
294 print_uint(PRINT_ANY
, "tunnel_id", " in tunnel %u", p
->tunnel_id
);
295 print_string(PRINT_FP
, NULL
, "%s", _SL_
);
297 print_uint(PRINT_ANY
, "peer_session_id",
298 " Peer session %u,", p
->peer_session_id
);
299 print_uint(PRINT_ANY
, "peer_tunnel_id",
300 " tunnel %u", p
->peer_tunnel_id
);
301 print_string(PRINT_FP
, NULL
, "%s", _SL_
);
303 if (p
->ifname
!= NULL
) {
304 print_color_string(PRINT_ANY
, COLOR_IFNAME
,
305 "interface", " interface name: %s" , p
->ifname
);
306 print_string(PRINT_FP
, NULL
, "%s", _SL_
);
309 print_uint(PRINT_ANY
, "offset", " offset %u,", 0);
310 print_uint(PRINT_ANY
, "peer_offset", " peer offset %u\n", 0);
312 if (p
->cookie_len
> 0)
313 print_cookie("cookie", "cookie",
314 p
->cookie
, p
->cookie_len
);
315 if (p
->peer_cookie_len
> 0)
316 print_cookie("peer_cookie", "peer cookie",
317 p
->peer_cookie
, p
->peer_cookie_len
);
319 if (p
->reorder_timeout
!= 0)
320 print_uint(PRINT_ANY
, "reorder_timeout",
321 " reorder timeout: %u", p
->reorder_timeout
);
324 if (p
->send_seq
|| p
->recv_seq
) {
325 print_string(PRINT_FP
, NULL
, "%s sequence numbering:", _SL_
);
328 print_null(PRINT_ANY
, "send_seq", " send", NULL
);
330 print_null(PRINT_ANY
, "recv_seq", " recv", NULL
);
333 print_string(PRINT_FP
, NULL
, "\n", NULL
);
337 static int get_response(struct nlmsghdr
*n
, void *arg
)
339 struct genlmsghdr
*ghdr
;
340 struct l2tp_data
*data
= arg
;
341 struct l2tp_parm
*p
= &data
->config
;
342 struct rtattr
*attrs
[L2TP_ATTR_MAX
+ 1];
343 struct rtattr
*nla_stats
, *rta
;
346 /* Validate message and parse attributes */
347 if (n
->nlmsg_type
== NLMSG_ERROR
)
350 ghdr
= NLMSG_DATA(n
);
351 len
= n
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ghdr
));
355 parse_rtattr(attrs
, L2TP_ATTR_MAX
, (void *)ghdr
+ GENL_HDRLEN
, len
);
357 if (attrs
[L2TP_ATTR_PW_TYPE
])
358 p
->pw_type
= rta_getattr_u16(attrs
[L2TP_ATTR_PW_TYPE
]);
359 if (attrs
[L2TP_ATTR_ENCAP_TYPE
])
360 p
->encap
= rta_getattr_u16(attrs
[L2TP_ATTR_ENCAP_TYPE
]);
361 if (attrs
[L2TP_ATTR_DATA_SEQ
])
362 p
->data_seq
= rta_getattr_u16(attrs
[L2TP_ATTR_DATA_SEQ
]);
363 if (attrs
[L2TP_ATTR_CONN_ID
])
364 p
->tunnel_id
= rta_getattr_u32(attrs
[L2TP_ATTR_CONN_ID
]);
365 if (attrs
[L2TP_ATTR_PEER_CONN_ID
])
366 p
->peer_tunnel_id
= rta_getattr_u32(attrs
[L2TP_ATTR_PEER_CONN_ID
]);
367 if (attrs
[L2TP_ATTR_SESSION_ID
])
368 p
->session_id
= rta_getattr_u32(attrs
[L2TP_ATTR_SESSION_ID
]);
369 if (attrs
[L2TP_ATTR_PEER_SESSION_ID
])
370 p
->peer_session_id
= rta_getattr_u32(attrs
[L2TP_ATTR_PEER_SESSION_ID
]);
371 if (attrs
[L2TP_ATTR_L2SPEC_TYPE
])
372 p
->l2spec_type
= rta_getattr_u8(attrs
[L2TP_ATTR_L2SPEC_TYPE
]);
373 if (attrs
[L2TP_ATTR_L2SPEC_LEN
])
374 p
->l2spec_len
= rta_getattr_u8(attrs
[L2TP_ATTR_L2SPEC_LEN
]);
376 if (attrs
[L2TP_ATTR_UDP_CSUM
])
377 p
->udp_csum
= !!rta_getattr_u8(attrs
[L2TP_ATTR_UDP_CSUM
]);
379 p
->udp6_csum_tx
= !attrs
[L2TP_ATTR_UDP_ZERO_CSUM6_TX
];
380 p
->udp6_csum_rx
= !attrs
[L2TP_ATTR_UDP_ZERO_CSUM6_RX
];
382 if (attrs
[L2TP_ATTR_COOKIE
])
383 memcpy(p
->cookie
, RTA_DATA(attrs
[L2TP_ATTR_COOKIE
]),
384 p
->cookie_len
= RTA_PAYLOAD(attrs
[L2TP_ATTR_COOKIE
]));
386 if (attrs
[L2TP_ATTR_PEER_COOKIE
])
387 memcpy(p
->peer_cookie
, RTA_DATA(attrs
[L2TP_ATTR_PEER_COOKIE
]),
388 p
->peer_cookie_len
= RTA_PAYLOAD(attrs
[L2TP_ATTR_PEER_COOKIE
]));
390 if (attrs
[L2TP_ATTR_RECV_SEQ
])
391 p
->recv_seq
= !!rta_getattr_u8(attrs
[L2TP_ATTR_RECV_SEQ
]);
392 if (attrs
[L2TP_ATTR_SEND_SEQ
])
393 p
->send_seq
= !!rta_getattr_u8(attrs
[L2TP_ATTR_SEND_SEQ
]);
395 if (attrs
[L2TP_ATTR_RECV_TIMEOUT
])
396 p
->reorder_timeout
= rta_getattr_u64(attrs
[L2TP_ATTR_RECV_TIMEOUT
]);
398 rta
= attrs
[L2TP_ATTR_IP_SADDR
];
399 p
->local_ip
.family
= AF_INET
;
401 rta
= attrs
[L2TP_ATTR_IP6_SADDR
];
402 p
->local_ip
.family
= AF_INET6
;
404 if (rta
&& get_addr_rta(&p
->local_ip
, rta
, p
->local_ip
.family
))
407 rta
= attrs
[L2TP_ATTR_IP_DADDR
];
408 p
->peer_ip
.family
= AF_INET
;
410 rta
= attrs
[L2TP_ATTR_IP6_DADDR
];
411 p
->peer_ip
.family
= AF_INET6
;
413 if (rta
&& get_addr_rta(&p
->peer_ip
, rta
, p
->peer_ip
.family
))
416 if (attrs
[L2TP_ATTR_UDP_SPORT
])
417 p
->local_udp_port
= rta_getattr_u16(attrs
[L2TP_ATTR_UDP_SPORT
]);
418 if (attrs
[L2TP_ATTR_UDP_DPORT
])
419 p
->peer_udp_port
= rta_getattr_u16(attrs
[L2TP_ATTR_UDP_DPORT
]);
420 if (attrs
[L2TP_ATTR_MTU
])
421 p
->mtu
= rta_getattr_u16(attrs
[L2TP_ATTR_MTU
]);
422 if (attrs
[L2TP_ATTR_IFNAME
])
423 p
->ifname
= rta_getattr_str(attrs
[L2TP_ATTR_IFNAME
]);
425 nla_stats
= attrs
[L2TP_ATTR_STATS
];
427 struct rtattr
*tb
[L2TP_ATTR_STATS_MAX
+ 1];
429 parse_rtattr_nested(tb
, L2TP_ATTR_STATS_MAX
, nla_stats
);
431 if (tb
[L2TP_ATTR_TX_PACKETS
])
432 data
->stats
.data_tx_packets
= rta_getattr_u64(tb
[L2TP_ATTR_TX_PACKETS
]);
433 if (tb
[L2TP_ATTR_TX_BYTES
])
434 data
->stats
.data_tx_bytes
= rta_getattr_u64(tb
[L2TP_ATTR_TX_BYTES
]);
435 if (tb
[L2TP_ATTR_TX_ERRORS
])
436 data
->stats
.data_tx_errors
= rta_getattr_u64(tb
[L2TP_ATTR_TX_ERRORS
]);
437 if (tb
[L2TP_ATTR_RX_PACKETS
])
438 data
->stats
.data_rx_packets
= rta_getattr_u64(tb
[L2TP_ATTR_RX_PACKETS
]);
439 if (tb
[L2TP_ATTR_RX_BYTES
])
440 data
->stats
.data_rx_bytes
= rta_getattr_u64(tb
[L2TP_ATTR_RX_BYTES
]);
441 if (tb
[L2TP_ATTR_RX_ERRORS
])
442 data
->stats
.data_rx_errors
= rta_getattr_u64(tb
[L2TP_ATTR_RX_ERRORS
]);
443 if (tb
[L2TP_ATTR_RX_SEQ_DISCARDS
])
444 data
->stats
.data_rx_oos_discards
= rta_getattr_u64(tb
[L2TP_ATTR_RX_SEQ_DISCARDS
]);
445 if (tb
[L2TP_ATTR_RX_OOS_PACKETS
])
446 data
->stats
.data_rx_oos_packets
= rta_getattr_u64(tb
[L2TP_ATTR_RX_OOS_PACKETS
]);
452 static int session_nlmsg(const struct sockaddr_nl
*who
,
453 struct nlmsghdr
*n
, void *arg
)
455 int ret
= get_response(n
, arg
);
463 static int get_session(struct l2tp_data
*p
)
465 GENL_REQUEST(req
, 128, genl_family
, 0, L2TP_GENL_VERSION
,
466 L2TP_CMD_SESSION_GET
,
467 NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
);
469 req
.n
.nlmsg_seq
= genl_rth
.dump
= ++genl_rth
.seq
;
471 if (p
->config
.tunnel_id
&& p
->config
.session_id
) {
472 addattr32(&req
.n
, 128, L2TP_ATTR_CONN_ID
, p
->config
.tunnel_id
);
473 addattr32(&req
.n
, 128, L2TP_ATTR_SESSION_ID
,
474 p
->config
.session_id
);
477 if (rtnl_send(&genl_rth
, &req
, req
.n
.nlmsg_len
) < 0)
481 if (rtnl_dump_filter(&genl_rth
, session_nlmsg
, p
) < 0) {
482 fprintf(stderr
, "Dump terminated\n");
491 static int tunnel_nlmsg(const struct sockaddr_nl
*who
,
492 struct nlmsghdr
*n
, void *arg
)
494 int ret
= get_response(n
, arg
);
502 static int get_tunnel(struct l2tp_data
*p
)
504 GENL_REQUEST(req
, 1024, genl_family
, 0, L2TP_GENL_VERSION
,
506 NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
);
508 req
.n
.nlmsg_seq
= genl_rth
.dump
= ++genl_rth
.seq
;
510 if (p
->config
.tunnel_id
)
511 addattr32(&req
.n
, 1024, L2TP_ATTR_CONN_ID
, p
->config
.tunnel_id
);
513 if (rtnl_send(&genl_rth
, &req
, req
.n
.nlmsg_len
) < 0)
517 if (rtnl_dump_filter(&genl_rth
, tunnel_nlmsg
, p
) < 0) {
518 fprintf(stderr
, "Dump terminated\n");
527 /*****************************************************************************
529 *****************************************************************************/
531 static void usage(void) __attribute__((noreturn
));
533 static void usage(void)
535 fprintf(stderr
, "Usage: ip l2tp add tunnel\n"
536 " remote ADDR local ADDR\n"
537 " tunnel_id ID peer_tunnel_id ID\n"
538 " [ encap { ip | udp } ]\n"
539 " [ udp_sport PORT ] [ udp_dport PORT ]\n"
540 " [ udp_csum { on | off } ]\n"
541 " [ udp6_csum_tx { on | off } ]\n"
542 " [ udp6_csum_rx { on | off } ]\n"
543 "Usage: ip l2tp add session [ name NAME ]\n"
545 " session_id ID peer_session_id ID\n"
546 " [ cookie HEXSTR ] [ peer_cookie HEXSTR ]\n"
547 " [ seq { none | send | recv | both } ]\n"
548 " [ l2spec_type L2SPEC ]\n"
549 " ip l2tp del tunnel tunnel_id ID\n"
550 " ip l2tp del session tunnel_id ID session_id ID\n"
551 " ip l2tp show tunnel [ tunnel_id ID ]\n"
552 " ip l2tp show session [ tunnel_id ID ] [ session_id ID ]\n"
554 "Where: NAME := STRING\n"
555 " ADDR := { IP_ADDRESS | any }\n"
556 " PORT := { 0..65535 }\n"
557 " ID := { 1..4294967295 }\n"
558 " HEXSTR := { 8 or 16 hex digits (4 / 8 bytes) }\n"
559 " L2SPEC := { none | default }\n");
564 static int parse_args(int argc
, char **argv
, int cmd
, struct l2tp_parm
*p
)
566 memset(p
, 0, sizeof(*p
));
572 p
->l2spec_type
= L2TP_L2SPECTYPE_DEFAULT
;
578 if (strcmp(*argv
, "encap") == 0) {
580 if (strcmp(*argv
, "ip") == 0) {
581 p
->encap
= L2TP_ENCAPTYPE_IP
;
582 } else if (strcmp(*argv
, "udp") == 0) {
583 p
->encap
= L2TP_ENCAPTYPE_UDP
;
585 fprintf(stderr
, "Unknown tunnel encapsulation \"%s\"\n", *argv
);
588 } else if (strcmp(*argv
, "name") == 0) {
590 if (check_ifname(*argv
))
591 invarg("\"name\" not a valid ifname", *argv
);
593 } else if (strcmp(*argv
, "remote") == 0) {
595 if (get_addr(&p
->peer_ip
, *argv
, AF_UNSPEC
))
596 invarg("invalid remote address\n", *argv
);
597 } else if (strcmp(*argv
, "local") == 0) {
599 if (get_addr(&p
->local_ip
, *argv
, AF_UNSPEC
))
600 invarg("invalid local address\n", *argv
);
601 } else if ((strcmp(*argv
, "tunnel_id") == 0) ||
602 (strcmp(*argv
, "tid") == 0)) {
606 if (get_u32(&uval
, *argv
, 0))
607 invarg("invalid ID\n", *argv
);
609 } else if ((strcmp(*argv
, "peer_tunnel_id") == 0) ||
610 (strcmp(*argv
, "ptid") == 0)) {
614 if (get_u32(&uval
, *argv
, 0))
615 invarg("invalid ID\n", *argv
);
616 p
->peer_tunnel_id
= uval
;
617 } else if ((strcmp(*argv
, "session_id") == 0) ||
618 (strcmp(*argv
, "sid") == 0)) {
622 if (get_u32(&uval
, *argv
, 0))
623 invarg("invalid ID\n", *argv
);
624 p
->session_id
= uval
;
625 } else if ((strcmp(*argv
, "peer_session_id") == 0) ||
626 (strcmp(*argv
, "psid") == 0)) {
630 if (get_u32(&uval
, *argv
, 0))
631 invarg("invalid ID\n", *argv
);
632 p
->peer_session_id
= uval
;
633 } else if (strcmp(*argv
, "udp_sport") == 0) {
637 if (get_u16(&uval
, *argv
, 0))
638 invarg("invalid port\n", *argv
);
639 p
->local_udp_port
= uval
;
640 } else if (strcmp(*argv
, "udp_dport") == 0) {
644 if (get_u16(&uval
, *argv
, 0))
645 invarg("invalid port\n", *argv
);
646 p
->peer_udp_port
= uval
;
647 } else if (strcmp(*argv
, "udp_csum") == 0) {
649 if (strcmp(*argv
, "on") == 0)
651 else if (strcmp(*argv
, "off") == 0)
654 invarg("invalid option for udp_csum\n", *argv
);
655 } else if (strcmp(*argv
, "udp6_csum_rx") == 0) {
657 if (strcmp(*argv
, "on") == 0)
659 else if (strcmp(*argv
, "off") == 0)
662 invarg("invalid option for udp6_csum_rx\n"
664 } else if (strcmp(*argv
, "udp6_csum_tx") == 0) {
666 if (strcmp(*argv
, "on") == 0)
668 else if (strcmp(*argv
, "off") == 0)
671 invarg("invalid option for udp6_csum_tx\n"
673 } else if (strcmp(*argv
, "offset") == 0) {
674 fprintf(stderr
, "Ignoring option \"offset\"\n");
676 } else if (strcmp(*argv
, "peer_offset") == 0) {
677 fprintf(stderr
, "Ignoring option \"peer_offset\"\n");
679 } else if (strcmp(*argv
, "cookie") == 0) {
683 slen
= strlen(*argv
);
684 if ((slen
!= 8) && (slen
!= 16))
685 invarg("cookie must be either 8 or 16 hex digits\n", *argv
);
687 p
->cookie_len
= slen
/ 2;
688 if (hex2mem(*argv
, p
->cookie
, p
->cookie_len
) < 0)
689 invarg("cookie must be a hex string\n", *argv
);
690 } else if (strcmp(*argv
, "peer_cookie") == 0) {
694 slen
= strlen(*argv
);
695 if ((slen
!= 8) && (slen
!= 16))
696 invarg("cookie must be either 8 or 16 hex digits\n", *argv
);
698 p
->peer_cookie_len
= slen
/ 2;
699 if (hex2mem(*argv
, p
->peer_cookie
, p
->peer_cookie_len
) < 0)
700 invarg("cookie must be a hex string\n", *argv
);
701 } else if (strcmp(*argv
, "l2spec_type") == 0) {
703 if (strcasecmp(*argv
, "default") == 0) {
704 p
->l2spec_type
= L2TP_L2SPECTYPE_DEFAULT
;
706 } else if (strcasecmp(*argv
, "none") == 0) {
707 p
->l2spec_type
= L2TP_L2SPECTYPE_NONE
;
711 "Unknown layer2specific header type \"%s\"\n",
715 } else if (strcmp(*argv
, "seq") == 0) {
717 if (strcasecmp(*argv
, "both") == 0) {
720 } else if (strcasecmp(*argv
, "recv") == 0) {
722 } else if (strcasecmp(*argv
, "send") == 0) {
724 } else if (strcasecmp(*argv
, "none") == 0) {
729 "Unknown seq value \"%s\"\n", *argv
);
732 } else if (strcmp(*argv
, "tunnel") == 0) {
734 } else if (strcmp(*argv
, "session") == 0) {
736 } else if (matches(*argv
, "help") == 0) {
739 fprintf(stderr
, "Unknown command: %s\n", *argv
);
750 static int do_add(int argc
, char **argv
)
755 if (parse_args(argc
, argv
, L2TP_ADD
, &p
) < 0)
758 if (!p
.tunnel
&& !p
.session
)
759 missarg("tunnel or session");
761 if (p
.tunnel_id
== 0)
762 missarg("tunnel_id");
764 /* session_id and peer_session_id must be provided for sessions */
765 if ((p
.session
) && (p
.peer_session_id
== 0))
766 missarg("peer_session_id");
767 if ((p
.session
) && (p
.session_id
== 0))
768 missarg("session_id");
770 /* peer_tunnel_id is needed for tunnels */
771 if ((p
.tunnel
) && (p
.peer_tunnel_id
== 0))
772 missarg("peer_tunnel_id");
775 if (p
.local_ip
.family
== AF_UNSPEC
)
778 if (p
.peer_ip
.family
== AF_UNSPEC
)
781 if (p
.encap
== L2TP_ENCAPTYPE_UDP
) {
782 if (p
.local_udp_port
== 0)
783 missarg("udp_sport");
784 if (p
.peer_udp_port
== 0)
785 missarg("udp_dport");
788 ret
= create_tunnel(&p
);
792 /* Only ethernet pseudowires supported */
793 p
.pw_type
= L2TP_PWTYPE_ETH
;
795 ret
= create_session(&p
);
801 static int do_del(int argc
, char **argv
)
805 if (parse_args(argc
, argv
, L2TP_DEL
, &p
) < 0)
808 if (!p
.tunnel
&& !p
.session
)
809 missarg("tunnel or session");
811 if ((p
.tunnel
) && (p
.tunnel_id
== 0))
812 missarg("tunnel_id");
813 if ((p
.session
) && (p
.session_id
== 0))
814 missarg("session_id");
817 return delete_session(&p
);
819 return delete_tunnel(&p
);
824 static int do_show(int argc
, char **argv
)
826 struct l2tp_data data
;
827 struct l2tp_parm
*p
= &data
.config
;
829 if (parse_args(argc
, argv
, L2TP_GET
, p
) < 0)
832 if (!p
->tunnel
&& !p
->session
)
833 missarg("tunnel or session");
843 int do_ipl2tp(int argc
, char **argv
)
845 if (argc
< 1 || !matches(*argv
, "help"))
848 if (genl_init_handle(&genl_rth
, L2TP_GENL_NAME
, &genl_family
))
851 if (matches(*argv
, "add") == 0)
852 return do_add(argc
-1, argv
+1);
853 if (matches(*argv
, "delete") == 0)
854 return do_del(argc
-1, argv
+1);
855 if (matches(*argv
, "show") == 0 ||
856 matches(*argv
, "lst") == 0 ||
857 matches(*argv
, "list") == 0)
858 return do_show(argc
-1, argv
+1);
861 "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv
);