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