1/*
2 * ipl2tp.c	       "ip l2tp"
3 *
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.
8 *
9 * Original Author:	James Chapman <jchapman@katalix.com>
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <unistd.h>
17#include <errno.h>
18#include <sys/types.h>
19#include <sys/socket.h>
20#include <arpa/inet.h>
21#include <sys/ioctl.h>
22#include <linux/if.h>
23#include <linux/if_arp.h>
24#include <linux/ip.h>
25
26#include <linux/genetlink.h>
27#include <linux/l2tp.h>
28#include "libgenl.h"
29
30#include "utils.h"
31#include "ip_common.h"
32
33enum {
34	L2TP_ADD,
35	L2TP_CHG,
36	L2TP_DEL,
37	L2TP_GET
38};
39
40struct l2tp_parm {
41	uint32_t tunnel_id;
42	uint32_t peer_tunnel_id;
43	uint32_t session_id;
44	uint32_t peer_session_id;
45	uint32_t offset;
46	uint32_t peer_offset;
47	enum l2tp_encap_type encap;
48	uint16_t local_udp_port;
49	uint16_t peer_udp_port;
50	int cookie_len;
51	uint8_t cookie[8];
52	int peer_cookie_len;
53	uint8_t peer_cookie[8];
54	inet_prefix local_ip;
55	inet_prefix peer_ip;
56
57	uint16_t pw_type;
58	uint16_t mtu;
59	int udp_csum:1;
60	int recv_seq:1;
61	int send_seq:1;
62	int lns_mode:1;
63	int data_seq:2;
64	int tunnel:1;
65	int session:1;
66	int reorder_timeout;
67	const char *ifname;
68	uint8_t l2spec_type;
69	uint8_t l2spec_len;
70};
71
72struct l2tp_stats {
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;
81};
82
83struct l2tp_data {
84	struct l2tp_parm config;
85	struct l2tp_stats stats;
86};
87
88/* netlink socket */
89static struct rtnl_handle genl_rth;
90static int genl_family = -1;
91
92/*****************************************************************************
93 * Netlink actions
94 *****************************************************************************/
95
96static int create_tunnel(struct l2tp_parm *p)
97{
98	uint32_t local_attr = L2TP_ATTR_IP_SADDR;
99	uint32_t peer_attr = L2TP_ATTR_IP_DADDR;
100
101	GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
102		     L2TP_CMD_TUNNEL_CREATE, NLM_F_REQUEST | NLM_F_ACK);
103
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);
108
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, p->local_ip.bytelen);
112
113	if (p->peer_ip.family == AF_INET6)
114		peer_attr = L2TP_ATTR_IP6_DADDR;
115	addattr_l(&req.n, 1024, peer_attr, &p->peer_ip.data, p->peer_ip.bytelen);
116
117	if (p->encap == L2TP_ENCAPTYPE_UDP) {
118		addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port);
119		addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port);
120	}
121
122	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
123		return -2;
124
125	return 0;
126}
127
128static int delete_tunnel(struct l2tp_parm *p)
129{
130	GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION,
131		     L2TP_CMD_TUNNEL_DELETE, NLM_F_REQUEST | NLM_F_ACK);
132
133	addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id);
134
135	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
136		return -2;
137
138	return 0;
139}
140
141static int create_session(struct l2tp_parm *p)
142{
143	GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
144		     L2TP_CMD_SESSION_CREATE, NLM_F_REQUEST | NLM_F_ACK);
145
146	addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
147	addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id);
148	addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
149	addattr32(&req.n, 1024, L2TP_ATTR_PEER_SESSION_ID, p->peer_session_id);
150	addattr16(&req.n, 1024, L2TP_ATTR_PW_TYPE, p->pw_type);
151	addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_TYPE, p->l2spec_type);
152	addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_LEN, p->l2spec_len);
153
154	if (p->mtu)		addattr16(&req.n, 1024, L2TP_ATTR_MTU, p->mtu);
155	if (p->recv_seq)	addattr(&req.n, 1024, L2TP_ATTR_RECV_SEQ);
156	if (p->send_seq)	addattr(&req.n, 1024, L2TP_ATTR_SEND_SEQ);
157	if (p->lns_mode)	addattr(&req.n, 1024, L2TP_ATTR_LNS_MODE);
158	if (p->data_seq)	addattr8(&req.n, 1024, L2TP_ATTR_DATA_SEQ, p->data_seq);
159	if (p->reorder_timeout) addattr64(&req.n, 1024, L2TP_ATTR_RECV_TIMEOUT,
160					  p->reorder_timeout);
161	if (p->offset)		addattr16(&req.n, 1024, L2TP_ATTR_OFFSET, p->offset);
162	if (p->cookie_len)	addattr_l(&req.n, 1024, L2TP_ATTR_COOKIE,
163					  p->cookie, p->cookie_len);
164	if (p->peer_cookie_len) addattr_l(&req.n, 1024, L2TP_ATTR_PEER_COOKIE,
165					  p->peer_cookie,  p->peer_cookie_len);
166	if (p->ifname && p->ifname[0])
167		addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname);
168
169	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
170		return -2;
171
172	return 0;
173}
174
175static int delete_session(struct l2tp_parm *p)
176{
177	GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
178		     L2TP_CMD_SESSION_DELETE, NLM_F_REQUEST | NLM_F_ACK);
179
180	addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
181	addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
182	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
183		return -2;
184
185	return 0;
186}
187
188static void print_cookie(char *name, const uint8_t *cookie, int len)
189{
190	printf("  %s %02x%02x%02x%02x", name,
191	       cookie[0], cookie[1],
192	       cookie[2], cookie[3]);
193	if (len == 8)
194		printf("%02x%02x%02x%02x",
195		       cookie[4], cookie[5],
196		       cookie[6], cookie[7]);
197}
198
199static void print_tunnel(const struct l2tp_data *data)
200{
201	const struct l2tp_parm *p = &data->config;
202	char buf[INET6_ADDRSTRLEN];
203
204	printf("Tunnel %u, encap %s\n",
205	       p->tunnel_id,
206	       p->encap == L2TP_ENCAPTYPE_UDP ? "UDP" :
207	       p->encap == L2TP_ENCAPTYPE_IP ? "IP" : "??");
208	printf("  From %s ", inet_ntop(p->local_ip.family, p->local_ip.data, buf, sizeof(buf)));
209	printf("to %s\n", inet_ntop(p->peer_ip.family, p->peer_ip.data, buf, sizeof(buf)));
210	printf("  Peer tunnel %u\n",
211	       p->peer_tunnel_id);
212
213	if (p->encap == L2TP_ENCAPTYPE_UDP)
214		printf("  UDP source / dest ports: %hu/%hu\n",
215		       p->local_udp_port, p->peer_udp_port);
216}
217
218static void print_session(struct l2tp_data *data)
219{
220	struct l2tp_parm *p = &data->config;
221
222	printf("Session %u in tunnel %u\n",
223	       p->session_id, p->tunnel_id);
224	printf("  Peer session %u, tunnel %u\n",
225	       p->peer_session_id, p->peer_tunnel_id);
226
227	if (p->ifname != NULL) {
228		printf("  interface name: %s\n", p->ifname);
229	}
230	printf("  offset %u, peer offset %u\n",
231	       p->offset, p->peer_offset);
232	if (p->cookie_len > 0)
233		print_cookie("cookie", p->cookie, p->cookie_len);
234	if (p->peer_cookie_len > 0)
235		print_cookie("peer cookie", p->peer_cookie, p->peer_cookie_len);
236
237	if (p->reorder_timeout != 0)
238		printf("  reorder timeout: %u\n", p->reorder_timeout);
239	else
240		printf("\n");
241}
242
243static int get_response(struct nlmsghdr *n, void *arg)
244{
245	struct genlmsghdr *ghdr;
246	struct l2tp_data *data = arg;
247	struct l2tp_parm *p = &data->config;
248	struct rtattr *attrs[L2TP_ATTR_MAX + 1];
249	struct rtattr *nla_stats;
250	int len;
251
252	/* Validate message and parse attributes */
253	if (n->nlmsg_type == NLMSG_ERROR)
254		return -EBADMSG;
255
256	ghdr = NLMSG_DATA(n);
257	len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ghdr));
258	if (len < 0)
259		return -1;
260
261	parse_rtattr(attrs, L2TP_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
262
263	if (attrs[L2TP_ATTR_PW_TYPE])
264		p->pw_type = rta_getattr_u16(attrs[L2TP_ATTR_PW_TYPE]);
265	if (attrs[L2TP_ATTR_ENCAP_TYPE])
266		p->encap = rta_getattr_u16(attrs[L2TP_ATTR_ENCAP_TYPE]);
267	if (attrs[L2TP_ATTR_OFFSET])
268		p->offset = rta_getattr_u16(attrs[L2TP_ATTR_OFFSET]);
269	if (attrs[L2TP_ATTR_DATA_SEQ])
270		p->data_seq = rta_getattr_u16(attrs[L2TP_ATTR_DATA_SEQ]);
271	if (attrs[L2TP_ATTR_CONN_ID])
272		p->tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_CONN_ID]);
273	if (attrs[L2TP_ATTR_PEER_CONN_ID])
274		p->peer_tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_CONN_ID]);
275	if (attrs[L2TP_ATTR_SESSION_ID])
276		p->session_id = rta_getattr_u32(attrs[L2TP_ATTR_SESSION_ID]);
277	if (attrs[L2TP_ATTR_PEER_SESSION_ID])
278		p->peer_session_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_SESSION_ID]);
279	if (attrs[L2TP_ATTR_L2SPEC_TYPE])
280		p->l2spec_type = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_TYPE]);
281	if (attrs[L2TP_ATTR_L2SPEC_LEN])
282		p->l2spec_len = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_LEN]);
283
284	p->udp_csum = !!attrs[L2TP_ATTR_UDP_CSUM];
285	if (attrs[L2TP_ATTR_COOKIE])
286		memcpy(p->cookie, RTA_DATA(attrs[L2TP_ATTR_COOKIE]),
287		       p->cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_COOKIE]));
288
289	if (attrs[L2TP_ATTR_PEER_COOKIE])
290		memcpy(p->peer_cookie, RTA_DATA(attrs[L2TP_ATTR_PEER_COOKIE]),
291		       p->peer_cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_PEER_COOKIE]));
292
293	p->recv_seq = !!attrs[L2TP_ATTR_RECV_SEQ];
294	p->send_seq = !!attrs[L2TP_ATTR_SEND_SEQ];
295
296	if (attrs[L2TP_ATTR_RECV_TIMEOUT])
297		p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]);
298	if (attrs[L2TP_ATTR_IP_SADDR]) {
299		p->local_ip.family = AF_INET;
300		p->local_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_SADDR]);
301		p->local_ip.bytelen = 4;
302		p->local_ip.bitlen = -1;
303	}
304	if (attrs[L2TP_ATTR_IP_DADDR]) {
305		p->peer_ip.family = AF_INET;
306		p->peer_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_DADDR]);
307		p->peer_ip.bytelen = 4;
308		p->peer_ip.bitlen = -1;
309	}
310	if (attrs[L2TP_ATTR_IP6_SADDR]) {
311		p->local_ip.family = AF_INET6;
312		memcpy(&p->local_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_SADDR]),
313			p->local_ip.bytelen = 16);
314		p->local_ip.bitlen = -1;
315	}
316	if (attrs[L2TP_ATTR_IP6_DADDR]) {
317		p->peer_ip.family = AF_INET6;
318		memcpy(&p->peer_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_DADDR]),
319			p->peer_ip.bytelen = 16);
320		p->peer_ip.bitlen = -1;
321	}
322	if (attrs[L2TP_ATTR_UDP_SPORT])
323		p->local_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_SPORT]);
324	if (attrs[L2TP_ATTR_UDP_DPORT])
325		p->peer_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_DPORT]);
326	if (attrs[L2TP_ATTR_MTU])
327		p->mtu = rta_getattr_u16(attrs[L2TP_ATTR_MTU]);
328	if (attrs[L2TP_ATTR_IFNAME])
329		p->ifname = rta_getattr_str(attrs[L2TP_ATTR_IFNAME]);
330
331	nla_stats = attrs[L2TP_ATTR_STATS];
332	if (nla_stats) {
333		struct rtattr *tb[L2TP_ATTR_STATS_MAX + 1];
334
335		parse_rtattr_nested(tb, L2TP_ATTR_STATS_MAX, nla_stats);
336
337		if (tb[L2TP_ATTR_TX_PACKETS])
338			data->stats.data_tx_packets = rta_getattr_u64(tb[L2TP_ATTR_TX_PACKETS]);
339		if (tb[L2TP_ATTR_TX_BYTES])
340			data->stats.data_tx_bytes = rta_getattr_u64(tb[L2TP_ATTR_TX_BYTES]);
341		if (tb[L2TP_ATTR_TX_ERRORS])
342			data->stats.data_tx_errors = rta_getattr_u64(tb[L2TP_ATTR_TX_ERRORS]);
343		if (tb[L2TP_ATTR_RX_PACKETS])
344			data->stats.data_rx_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_PACKETS]);
345		if (tb[L2TP_ATTR_RX_BYTES])
346			data->stats.data_rx_bytes = rta_getattr_u64(tb[L2TP_ATTR_RX_BYTES]);
347		if (tb[L2TP_ATTR_RX_ERRORS])
348			data->stats.data_rx_errors = rta_getattr_u64(tb[L2TP_ATTR_RX_ERRORS]);
349		if (tb[L2TP_ATTR_RX_SEQ_DISCARDS])
350			data->stats.data_rx_oos_discards = rta_getattr_u64(tb[L2TP_ATTR_RX_SEQ_DISCARDS]);
351		if (tb[L2TP_ATTR_RX_OOS_PACKETS])
352			data->stats.data_rx_oos_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_OOS_PACKETS]);
353	}
354
355	return 0;
356}
357
358static int session_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
359{
360	int ret = get_response(n, arg);
361
362	if (ret == 0)
363		print_session(arg);
364
365	return ret;
366}
367
368static int get_session(struct l2tp_data *p)
369{
370	GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION,
371		     L2TP_CMD_SESSION_GET,
372		     NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST);
373
374	req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
375
376	if (p->config.tunnel_id && p->config.session_id) {
377		addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
378		addattr32(&req.n, 128, L2TP_ATTR_SESSION_ID, p->config.session_id);
379	}
380
381	if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
382		return -2;
383
384	if (rtnl_dump_filter(&genl_rth, session_nlmsg, p) < 0) {
385		fprintf(stderr, "Dump terminated\n");
386		exit(1);
387	}
388
389	return 0;
390}
391
392static int tunnel_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
393{
394	int ret = get_response(n, arg);
395
396	if (ret == 0)
397		print_tunnel(arg);
398
399	return ret;
400}
401
402static int get_tunnel(struct l2tp_data *p)
403{
404	GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
405		     L2TP_CMD_TUNNEL_GET,
406		     NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST);
407
408	req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
409
410	if (p->config.tunnel_id)
411		addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
412
413	if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
414		return -2;
415
416	if (rtnl_dump_filter(&genl_rth, tunnel_nlmsg, p) < 0) {
417		fprintf(stderr, "Dump terminated\n");
418		exit(1);
419	}
420
421	return 0;
422}
423
424/*****************************************************************************
425 * Command parser
426 *****************************************************************************/
427
428static int hex(char ch)
429{
430	if ((ch >= 'a') && (ch <= 'f'))
431		return ch - 'a' + 10;
432	if ((ch >= '0') && (ch <= '9'))
433		return ch - '0';
434	if ((ch >= 'A') && (ch <= 'F'))
435		return ch - 'A' + 10;
436	return -1;
437}
438
439static int hex2mem(const char *buf, uint8_t *mem, int count)
440{
441	int i, j;
442	int c;
443
444	for (i = 0, j = 0; i < count; i++, j += 2) {
445		c = hex(buf[j]);
446		if (c < 0)
447			goto err;
448
449		mem[i] = c << 4;
450
451		c = hex(buf[j + 1]);
452		if (c < 0)
453			goto err;
454
455		mem[i] |= c;
456	}
457
458	return 0;
459
460err:
461	return -1;
462}
463
464static void usage(void) __attribute__((noreturn));
465
466static void usage(void)
467{
468	fprintf(stderr, "Usage: ip l2tp add tunnel\n");
469	fprintf(stderr, "          remote ADDR local ADDR\n");
470	fprintf(stderr, "          tunnel_id ID peer_tunnel_id ID\n");
471	fprintf(stderr, "          [ encap { ip | udp } ]\n");
472	fprintf(stderr, "          [ udp_sport PORT ] [ udp_dport PORT ]\n");
473	fprintf(stderr, "Usage: ip l2tp add session [ name NAME ]\n");
474	fprintf(stderr, "          tunnel_id ID\n");
475	fprintf(stderr, "          session_id ID peer_session_id ID\n");
476	fprintf(stderr, "          [ cookie HEXSTR ] [ peer_cookie HEXSTR ]\n");
477	fprintf(stderr, "          [ offset OFFSET ] [ peer_offset OFFSET ]\n");
478	fprintf(stderr, "          [ l2spec_type L2SPEC ]\n");
479	fprintf(stderr, "       ip l2tp del tunnel tunnel_id ID\n");
480	fprintf(stderr, "       ip l2tp del session tunnel_id ID session_id ID\n");
481	fprintf(stderr, "       ip l2tp show tunnel [ tunnel_id ID ]\n");
482	fprintf(stderr, "       ip l2tp show session [ tunnel_id ID ] [ session_id ID ]\n");
483	fprintf(stderr, "\n");
484	fprintf(stderr, "Where: NAME   := STRING\n");
485	fprintf(stderr, "       ADDR   := { IP_ADDRESS | any }\n");
486	fprintf(stderr, "       PORT   := { 0..65535 }\n");
487	fprintf(stderr, "       ID     := { 1..4294967295 }\n");
488	fprintf(stderr, "       HEXSTR := { 8 or 16 hex digits (4 / 8 bytes) }\n");
489	fprintf(stderr, "       L2SPEC := { none | default }\n");
490	exit(-1);
491}
492
493static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
494{
495	memset(p, 0, sizeof(*p));
496
497	if (argc == 0)
498		usage();
499
500	/* Defaults */
501	p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT;
502	p->l2spec_len = 4;
503
504	while (argc > 0) {
505		if (strcmp(*argv, "encap") == 0) {
506			NEXT_ARG();
507			if (strcmp(*argv, "ip") == 0) {
508				p->encap = L2TP_ENCAPTYPE_IP;
509			} else if (strcmp(*argv, "udp") == 0) {
510				p->encap = L2TP_ENCAPTYPE_UDP;
511			} else {
512				fprintf(stderr, "Unknown tunnel encapsulation \"%s\"\n", *argv);
513				exit(-1);
514			}
515		} else if (strcmp(*argv, "name") == 0) {
516			NEXT_ARG();
517			p->ifname = *argv;
518		} else if (strcmp(*argv, "remote") == 0) {
519			NEXT_ARG();
520			if (get_addr(&p->peer_ip, *argv, AF_UNSPEC))
521				invarg("invalid remote address\n", *argv);
522		} else if (strcmp(*argv, "local") == 0) {
523			NEXT_ARG();
524			if (get_addr(&p->local_ip, *argv, AF_UNSPEC))
525				invarg("invalid local address\n", *argv);
526		} else if ((strcmp(*argv, "tunnel_id") == 0) ||
527			   (strcmp(*argv, "tid") == 0)) {
528			__u32 uval;
529			NEXT_ARG();
530			if (get_u32(&uval, *argv, 0))
531				invarg("invalid ID\n", *argv);
532			p->tunnel_id = uval;
533		} else if ((strcmp(*argv, "peer_tunnel_id") == 0) ||
534			   (strcmp(*argv, "ptid") == 0)) {
535			__u32 uval;
536			NEXT_ARG();
537			if (get_u32(&uval, *argv, 0))
538				invarg("invalid ID\n", *argv);
539			p->peer_tunnel_id = uval;
540		} else if ((strcmp(*argv, "session_id") == 0) ||
541			   (strcmp(*argv, "sid") == 0)) {
542			__u32 uval;
543			NEXT_ARG();
544			if (get_u32(&uval, *argv, 0))
545				invarg("invalid ID\n", *argv);
546			p->session_id = uval;
547		} else if ((strcmp(*argv, "peer_session_id") == 0) ||
548			   (strcmp(*argv, "psid") == 0)) {
549			__u32 uval;
550			NEXT_ARG();
551			if (get_u32(&uval, *argv, 0))
552				invarg("invalid ID\n", *argv);
553			p->peer_session_id = uval;
554		} else if (strcmp(*argv, "udp_sport") == 0) {
555			__u16 uval;
556			NEXT_ARG();
557			if (get_u16(&uval, *argv, 0))
558				invarg("invalid port\n", *argv);
559			p->local_udp_port = uval;
560		} else if (strcmp(*argv, "udp_dport") == 0) {
561			__u16 uval;
562			NEXT_ARG();
563			if (get_u16(&uval, *argv, 0))
564				invarg("invalid port\n", *argv);
565			p->peer_udp_port = uval;
566		} else if (strcmp(*argv, "offset") == 0) {
567			__u8 uval;
568			NEXT_ARG();
569			if (get_u8(&uval, *argv, 0))
570				invarg("invalid offset\n", *argv);
571			p->offset = uval;
572		} else if (strcmp(*argv, "peer_offset") == 0) {
573			__u8 uval;
574			NEXT_ARG();
575			if (get_u8(&uval, *argv, 0))
576				invarg("invalid offset\n", *argv);
577			p->peer_offset = uval;
578		} else if (strcmp(*argv, "cookie") == 0) {
579			int slen;
580			NEXT_ARG();
581			slen = strlen(*argv);
582			if ((slen != 8) && (slen != 16))
583				invarg("cookie must be either 8 or 16 hex digits\n", *argv);
584
585			p->cookie_len = slen / 2;
586			if (hex2mem(*argv, p->cookie, p->cookie_len) < 0)
587				invarg("cookie must be a hex string\n", *argv);
588		} else if (strcmp(*argv, "peer_cookie") == 0) {
589			int slen;
590			NEXT_ARG();
591			slen = strlen(*argv);
592			if ((slen != 8) && (slen != 16))
593				invarg("cookie must be either 8 or 16 hex digits\n", *argv);
594
595			p->peer_cookie_len = slen / 2;
596			if (hex2mem(*argv, p->peer_cookie, p->peer_cookie_len) < 0)
597				invarg("cookie must be a hex string\n", *argv);
598		} else if (strcmp(*argv, "l2spec_type") == 0) {
599			NEXT_ARG();
600			if (strcasecmp(*argv, "default") == 0) {
601				p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT;
602				p->l2spec_len = 4;
603			} else if (strcasecmp(*argv, "none") == 0) {
604				p->l2spec_type = L2TP_L2SPECTYPE_NONE;
605				p->l2spec_len = 0;
606			} else {
607				fprintf(stderr, "Unknown layer2specific header type \"%s\"\n", *argv);
608				exit(-1);
609			}
610		} else if (strcmp(*argv, "tunnel") == 0) {
611			p->tunnel = 1;
612		} else if (strcmp(*argv, "session") == 0) {
613			p->session = 1;
614		} else if (matches(*argv, "help") == 0) {
615			usage();
616		} else {
617			fprintf(stderr, "Unknown command: %s\n", *argv);
618			usage();
619		}
620
621		argc--; argv++;
622	}
623
624	return 0;
625}
626
627
628static int do_add(int argc, char **argv)
629{
630	struct l2tp_parm p;
631	int ret = 0;
632
633	if (parse_args(argc, argv, L2TP_ADD, &p) < 0)
634		return -1;
635
636	if (!p.tunnel && !p.session)
637		missarg("tunnel or session");
638
639	if (p.tunnel_id == 0)
640		missarg("tunnel_id");
641
642	/* session_id and peer_session_id must be provided for sessions */
643	if ((p.session) && (p.peer_session_id == 0))
644		missarg("peer_session_id");
645	if ((p.session) && (p.session_id == 0))
646		missarg("session_id");
647
648	/* peer_tunnel_id is needed for tunnels */
649	if ((p.tunnel) && (p.peer_tunnel_id == 0))
650		missarg("peer_tunnel_id");
651
652	if (p.tunnel) {
653		if (p.local_ip.family == AF_UNSPEC)
654			missarg("local");
655
656		if (p.peer_ip.family == AF_UNSPEC)
657			missarg("remote");
658
659		if (p.encap == L2TP_ENCAPTYPE_UDP) {
660			if (p.local_udp_port == 0)
661				missarg("udp_sport");
662			if (p.peer_udp_port == 0)
663				missarg("udp_dport");
664		}
665
666		ret = create_tunnel(&p);
667	}
668
669	if (p.session) {
670		/* Only ethernet pseudowires supported */
671		p.pw_type = L2TP_PWTYPE_ETH;
672
673		ret = create_session(&p);
674	}
675
676	return ret;
677}
678
679static int do_del(int argc, char **argv)
680{
681	struct l2tp_parm p;
682
683	if (parse_args(argc, argv, L2TP_DEL, &p) < 0)
684		return -1;
685
686	if (!p.tunnel && !p.session)
687		missarg("tunnel or session");
688
689	if ((p.tunnel) && (p.tunnel_id == 0))
690		missarg("tunnel_id");
691	if ((p.session) && (p.session_id == 0))
692		missarg("session_id");
693
694	if (p.session_id)
695		return delete_session(&p);
696	else
697		return delete_tunnel(&p);
698
699	return -1;
700}
701
702static int do_show(int argc, char **argv)
703{
704	struct l2tp_data data;
705	struct l2tp_parm *p = &data.config;
706
707	if (parse_args(argc, argv, L2TP_GET, p) < 0)
708		return -1;
709
710	if (!p->tunnel && !p->session)
711		missarg("tunnel or session");
712
713	if (p->session)
714		get_session(&data);
715	else
716		get_tunnel(&data);
717
718	return 0;
719}
720
721int do_ipl2tp(int argc, char **argv)
722{
723	if (genl_family < 0) {
724		if (rtnl_open_byproto(&genl_rth, 0, NETLINK_GENERIC) < 0) {
725			fprintf(stderr, "Cannot open generic netlink socket\n");
726			exit(1);
727		}
728
729		genl_family = genl_resolve_family(&genl_rth, L2TP_GENL_NAME);
730		if (genl_family < 0)
731			exit(1);
732	}
733
734	if (argc < 1)
735		usage();
736
737	if (matches(*argv, "add") == 0)
738		return do_add(argc-1, argv+1);
739	if (matches(*argv, "delete") == 0)
740		return do_del(argc-1, argv+1);
741	if (matches(*argv, "show") == 0 ||
742	    matches(*argv, "lst") == 0 ||
743	    matches(*argv, "list") == 0)
744		return do_show(argc-1, argv+1);
745	if (matches(*argv, "help") == 0)
746		usage();
747
748	fprintf(stderr, "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv);
749	exit(-1);
750}
751