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 
32 enum {
33 	L2TP_ADD,
34 	L2TP_CHG,
35 	L2TP_DEL,
36 	L2TP_GET
37 };
38 
39 struct 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 
69 struct 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 
80 struct l2tp_data {
81 	struct l2tp_parm config;
82 	struct l2tp_stats stats;
83 };
84 
85 /* netlink socket */
86 static struct rtnl_handle genl_rth;
87 static int genl_family = -1;
88 
89 /*****************************************************************************
90  * Netlink actions
91  *****************************************************************************/
92 
create_tunnel(struct l2tp_parm * p)93 static 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 
delete_tunnel(struct l2tp_parm * p)126 static 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 
create_session(struct l2tp_parm * p)149 static 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 
delete_session(struct l2tp_parm * p)191 static 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 
print_cookie(char * name,const uint8_t * cookie,int len)214 static 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 
print_tunnel(const struct l2tp_data * data)225 static 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 
print_session(struct l2tp_data * data)243 static 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 
get_response(struct nlmsghdr * n,void * arg)267 static 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 
session_nlmsg(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)358 static 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 
get_session(struct l2tp_data * p)368 static 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 
tunnel_nlmsg(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)401 static 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 
get_tunnel(struct l2tp_data * p)411 static 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 
hex(char ch)446 static 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 
hex2mem(const char * buf,uint8_t * mem,int count)457 static 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 
478 err:
479 	return -1;
480 }
481 
482 static void usage(void) __attribute__((noreturn));
483 
usage(void)484 static 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 
parse_args(int argc,char ** argv,int cmd,struct l2tp_parm * p)509 static 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 
do_add(int argc,char ** argv)626 static 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 
do_del(int argc,char ** argv)677 static 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 
do_show(int argc,char ** argv)700 static 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 
genl_parse_getfamily(struct nlmsghdr * nlh)719 static 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 
genl_ctrl_resolve_family(const char * family)755 int 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 
do_ipl2tp(int argc,char ** argv)780 int 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