• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
33 enum {
34 	L2TP_ADD,
35 	L2TP_CHG,
36 	L2TP_DEL,
37 	L2TP_GET
38 };
39 
40 struct 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 
72 struct 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 
83 struct l2tp_data {
84 	struct l2tp_parm config;
85 	struct l2tp_stats stats;
86 };
87 
88 /* netlink socket */
89 static struct rtnl_handle genl_rth;
90 static int genl_family = -1;
91 
92 /*****************************************************************************
93  * Netlink actions
94  *****************************************************************************/
95 
create_tunnel(struct l2tp_parm * p)96 static 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 
delete_tunnel(struct l2tp_parm * p)128 static 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 
create_session(struct l2tp_parm * p)141 static 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 
delete_session(struct l2tp_parm * p)175 static 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 
print_cookie(char * name,const uint8_t * cookie,int len)188 static 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 
print_tunnel(const struct l2tp_data * data)199 static 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 
print_session(struct l2tp_data * data)218 static 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 
get_response(struct nlmsghdr * n,void * arg)243 static 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 
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 	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 
tunnel_nlmsg(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)392 static 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 
get_tunnel(struct l2tp_data * p)402 static 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 
hex(char ch)428 static 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 
hex2mem(const char * buf,uint8_t * mem,int count)439 static 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 
460 err:
461 	return -1;
462 }
463 
464 static void usage(void) __attribute__((noreturn));
465 
usage(void)466 static 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 
parse_args(int argc,char ** argv,int cmd,struct l2tp_parm * p)493 static 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 
do_add(int argc,char ** argv)628 static 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 
do_del(int argc,char ** argv)679 static 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 
do_show(int argc,char ** argv)702 static 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 
do_ipl2tp(int argc,char ** argv)721 int 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