]> git.proxmox.com Git - mirror_iproute2.git/blob - ip/ipl2tp.c
ip/l2tp: remove offset and peer-offset options
[mirror_iproute2.git] / ip / ipl2tp.c
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 enum l2tp_encap_type encap;
46 uint16_t local_udp_port;
47 uint16_t peer_udp_port;
48 int cookie_len;
49 uint8_t cookie[8];
50 int peer_cookie_len;
51 uint8_t peer_cookie[8];
52 inet_prefix local_ip;
53 inet_prefix peer_ip;
54
55 uint16_t pw_type;
56 uint16_t mtu;
57 unsigned int udp6_csum_tx:1;
58 unsigned int udp6_csum_rx:1;
59 unsigned int udp_csum:1;
60 unsigned int recv_seq:1;
61 unsigned int send_seq:1;
62 unsigned int lns_mode:1;
63 unsigned int data_seq:2;
64 unsigned int tunnel:1;
65 unsigned int session:1;
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
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,
112 p->local_ip.bytelen);
113
114 if (p->peer_ip.family == AF_INET6)
115 peer_attr = L2TP_ATTR_IP6_DADDR;
116 addattr_l(&req.n, 1024, peer_attr, &p->peer_ip.data,
117 p->peer_ip.bytelen);
118
119 if (p->encap == L2TP_ENCAPTYPE_UDP) {
120 addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port);
121 addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port);
122 if (p->udp_csum)
123 addattr8(&req.n, 1024, L2TP_ATTR_UDP_CSUM, 1);
124 if (!p->udp6_csum_tx)
125 addattr(&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_TX);
126 if (!p->udp6_csum_rx)
127 addattr(&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_RX);
128 }
129
130 if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
131 return -2;
132
133 return 0;
134 }
135
136 static int delete_tunnel(struct l2tp_parm *p)
137 {
138 GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION,
139 L2TP_CMD_TUNNEL_DELETE, NLM_F_REQUEST | NLM_F_ACK);
140
141 addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id);
142
143 if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
144 return -2;
145
146 return 0;
147 }
148
149 static int create_session(struct l2tp_parm *p)
150 {
151 GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
152 L2TP_CMD_SESSION_CREATE, NLM_F_REQUEST | NLM_F_ACK);
153
154 addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
155 addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id);
156 addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
157 addattr32(&req.n, 1024, L2TP_ATTR_PEER_SESSION_ID, p->peer_session_id);
158 addattr16(&req.n, 1024, L2TP_ATTR_PW_TYPE, p->pw_type);
159 addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_TYPE, p->l2spec_type);
160 addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_LEN, p->l2spec_len);
161
162 if (p->mtu)
163 addattr16(&req.n, 1024, L2TP_ATTR_MTU, p->mtu);
164 if (p->recv_seq)
165 addattr8(&req.n, 1024, L2TP_ATTR_RECV_SEQ, 1);
166 if (p->send_seq)
167 addattr8(&req.n, 1024, L2TP_ATTR_SEND_SEQ, 1);
168 if (p->lns_mode)
169 addattr(&req.n, 1024, L2TP_ATTR_LNS_MODE);
170 if (p->data_seq)
171 addattr8(&req.n, 1024, L2TP_ATTR_DATA_SEQ, p->data_seq);
172 if (p->reorder_timeout)
173 addattr64(&req.n, 1024, L2TP_ATTR_RECV_TIMEOUT,
174 p->reorder_timeout);
175 if (p->cookie_len)
176 addattr_l(&req.n, 1024, L2TP_ATTR_COOKIE,
177 p->cookie, p->cookie_len);
178 if (p->peer_cookie_len)
179 addattr_l(&req.n, 1024, L2TP_ATTR_PEER_COOKIE,
180 p->peer_cookie, p->peer_cookie_len);
181 if (p->ifname)
182 addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname);
183
184 if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
185 return -2;
186
187 return 0;
188 }
189
190 static int delete_session(struct l2tp_parm *p)
191 {
192 GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
193 L2TP_CMD_SESSION_DELETE, NLM_F_REQUEST | NLM_F_ACK);
194
195 addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
196 addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
197 if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
198 return -2;
199
200 return 0;
201 }
202
203 static void print_cookie(const char *name, const char *fmt,
204 const uint8_t *cookie, int len)
205 {
206 char abuf[32];
207 size_t n;
208
209 n = snprintf(abuf, sizeof(abuf),
210 "%02x%02x%02x%02x",
211 cookie[0], cookie[1], cookie[2], cookie[3]);
212 if (len == 8)
213 snprintf(abuf + n, sizeof(abuf) - n,
214 "%02x%02x%02x%02x",
215 cookie[4], cookie[5],
216 cookie[6], cookie[7]);
217
218 print_string(PRINT_ANY, name, fmt, abuf);
219 }
220
221 static void print_tunnel(const struct l2tp_data *data)
222 {
223 const struct l2tp_parm *p = &data->config;
224 char buf[INET6_ADDRSTRLEN];
225
226 open_json_object(NULL);
227 print_uint(PRINT_ANY, "tunnel_id", "Tunnel %u,", p->tunnel_id);
228 print_string(PRINT_ANY, "encap", " encap %s",
229 p->encap == L2TP_ENCAPTYPE_UDP ? "UDP" :
230 p->encap == L2TP_ENCAPTYPE_IP ? "IP" : "??");
231 print_string(PRINT_FP, NULL, "%s", _SL_);
232
233 print_string(PRINT_ANY, "local", " From %s ",
234 inet_ntop(p->local_ip.family, p->local_ip.data,
235 buf, sizeof(buf)));
236 print_string(PRINT_ANY, "peer", "to %s",
237 inet_ntop(p->peer_ip.family, p->peer_ip.data,
238 buf, sizeof(buf)));
239 print_string(PRINT_FP, NULL, "%s", _SL_);
240
241 print_uint(PRINT_ANY, "peer_tunnel", " Peer tunnel %u",
242 p->peer_tunnel_id);
243 print_string(PRINT_FP, NULL, "%s", _SL_);
244
245 if (p->encap == L2TP_ENCAPTYPE_UDP) {
246 print_string(PRINT_FP, NULL,
247 " UDP source / dest ports:", NULL);
248
249 print_uint(PRINT_ANY, "local_port", " %hu",
250 p->local_udp_port);
251 print_uint(PRINT_ANY, "peer_port", "/%hu",
252 p->peer_udp_port);
253 print_string(PRINT_FP, NULL, "%s", _SL_);
254
255 switch (p->local_ip.family) {
256 case AF_INET:
257 print_bool(PRINT_JSON, "checksum",
258 NULL, p->udp_csum);
259 print_string(PRINT_FP, NULL,
260 " UDP checksum: %s\n",
261 p->udp_csum ? "enabled" : "disabled");
262 break;
263 case AF_INET6:
264 if (is_json_context()) {
265 print_bool(PRINT_JSON, "checksum_tx",
266 NULL, p->udp6_csum_tx);
267
268 print_bool(PRINT_JSON, "checksum_rx",
269 NULL, p->udp6_csum_tx);
270 } else {
271 printf(" UDP checksum: %s%s%s%s\n",
272 p->udp6_csum_tx && p->udp6_csum_rx
273 ? "enabled" : "",
274 p->udp6_csum_tx && !p->udp6_csum_rx
275 ? "tx" : "",
276 !p->udp6_csum_tx && p->udp6_csum_rx
277 ? "rx" : "",
278 !p->udp6_csum_tx && !p->udp6_csum_rx
279 ? "disabled" : "");
280 }
281 break;
282 }
283 }
284 close_json_object();
285 }
286
287 static void print_session(struct l2tp_data *data)
288 {
289 struct l2tp_parm *p = &data->config;
290
291 open_json_object(NULL);
292
293 print_uint(PRINT_ANY, "session_id", "Session %u", p->session_id);
294 print_uint(PRINT_ANY, "tunnel_id", " in tunnel %u", p->tunnel_id);
295 print_string(PRINT_FP, NULL, "%s", _SL_);
296
297 print_uint(PRINT_ANY, "peer_session_id",
298 " Peer session %u,", p->peer_session_id);
299 print_uint(PRINT_ANY, "peer_tunnel_id",
300 " tunnel %u", p->peer_tunnel_id);
301 print_string(PRINT_FP, NULL, "%s", _SL_);
302
303 if (p->ifname != NULL) {
304 print_color_string(PRINT_ANY, COLOR_IFNAME,
305 "interface", " interface name: %s" , p->ifname);
306 print_string(PRINT_FP, NULL, "%s", _SL_);
307 }
308
309 print_uint(PRINT_ANY, "offset", " offset %u,", 0);
310 print_uint(PRINT_ANY, "peer_offset", " peer offset %u\n", 0);
311
312 if (p->cookie_len > 0)
313 print_cookie("cookie", "cookie",
314 p->cookie, p->cookie_len);
315 if (p->peer_cookie_len > 0)
316 print_cookie("peer_cookie", "peer cookie",
317 p->peer_cookie, p->peer_cookie_len);
318
319 if (p->reorder_timeout != 0)
320 print_uint(PRINT_ANY, "reorder_timeout",
321 " reorder timeout: %u", p->reorder_timeout);
322
323
324 if (p->send_seq || p->recv_seq) {
325 print_string(PRINT_FP, NULL, "%s sequence numbering:", _SL_);
326
327 if (p->send_seq)
328 print_null(PRINT_ANY, "send_seq", " send", NULL);
329 if (p->recv_seq)
330 print_null(PRINT_ANY, "recv_seq", " recv", NULL);
331
332 }
333 print_string(PRINT_FP, NULL, "\n", NULL);
334 close_json_object();
335 }
336
337 static int get_response(struct nlmsghdr *n, void *arg)
338 {
339 struct genlmsghdr *ghdr;
340 struct l2tp_data *data = arg;
341 struct l2tp_parm *p = &data->config;
342 struct rtattr *attrs[L2TP_ATTR_MAX + 1];
343 struct rtattr *nla_stats, *rta;
344 int len;
345
346 /* Validate message and parse attributes */
347 if (n->nlmsg_type == NLMSG_ERROR)
348 return -EBADMSG;
349
350 ghdr = NLMSG_DATA(n);
351 len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ghdr));
352 if (len < 0)
353 return -1;
354
355 parse_rtattr(attrs, L2TP_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
356
357 if (attrs[L2TP_ATTR_PW_TYPE])
358 p->pw_type = rta_getattr_u16(attrs[L2TP_ATTR_PW_TYPE]);
359 if (attrs[L2TP_ATTR_ENCAP_TYPE])
360 p->encap = rta_getattr_u16(attrs[L2TP_ATTR_ENCAP_TYPE]);
361 if (attrs[L2TP_ATTR_DATA_SEQ])
362 p->data_seq = rta_getattr_u16(attrs[L2TP_ATTR_DATA_SEQ]);
363 if (attrs[L2TP_ATTR_CONN_ID])
364 p->tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_CONN_ID]);
365 if (attrs[L2TP_ATTR_PEER_CONN_ID])
366 p->peer_tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_CONN_ID]);
367 if (attrs[L2TP_ATTR_SESSION_ID])
368 p->session_id = rta_getattr_u32(attrs[L2TP_ATTR_SESSION_ID]);
369 if (attrs[L2TP_ATTR_PEER_SESSION_ID])
370 p->peer_session_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_SESSION_ID]);
371 if (attrs[L2TP_ATTR_L2SPEC_TYPE])
372 p->l2spec_type = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_TYPE]);
373 if (attrs[L2TP_ATTR_L2SPEC_LEN])
374 p->l2spec_len = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_LEN]);
375
376 if (attrs[L2TP_ATTR_UDP_CSUM])
377 p->udp_csum = !!rta_getattr_u8(attrs[L2TP_ATTR_UDP_CSUM]);
378
379 p->udp6_csum_tx = !attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX];
380 p->udp6_csum_rx = !attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX];
381
382 if (attrs[L2TP_ATTR_COOKIE])
383 memcpy(p->cookie, RTA_DATA(attrs[L2TP_ATTR_COOKIE]),
384 p->cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_COOKIE]));
385
386 if (attrs[L2TP_ATTR_PEER_COOKIE])
387 memcpy(p->peer_cookie, RTA_DATA(attrs[L2TP_ATTR_PEER_COOKIE]),
388 p->peer_cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_PEER_COOKIE]));
389
390 if (attrs[L2TP_ATTR_RECV_SEQ])
391 p->recv_seq = !!rta_getattr_u8(attrs[L2TP_ATTR_RECV_SEQ]);
392 if (attrs[L2TP_ATTR_SEND_SEQ])
393 p->send_seq = !!rta_getattr_u8(attrs[L2TP_ATTR_SEND_SEQ]);
394
395 if (attrs[L2TP_ATTR_RECV_TIMEOUT])
396 p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]);
397
398 rta = attrs[L2TP_ATTR_IP_SADDR];
399 p->local_ip.family = AF_INET;
400 if (!rta) {
401 rta = attrs[L2TP_ATTR_IP6_SADDR];
402 p->local_ip.family = AF_INET6;
403 }
404 if (rta && get_addr_rta(&p->local_ip, rta, p->local_ip.family))
405 return -1;
406
407 rta = attrs[L2TP_ATTR_IP_DADDR];
408 p->peer_ip.family = AF_INET;
409 if (!rta) {
410 rta = attrs[L2TP_ATTR_IP6_DADDR];
411 p->peer_ip.family = AF_INET6;
412 }
413 if (rta && get_addr_rta(&p->peer_ip, rta, p->peer_ip.family))
414 return -1;
415
416 if (attrs[L2TP_ATTR_UDP_SPORT])
417 p->local_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_SPORT]);
418 if (attrs[L2TP_ATTR_UDP_DPORT])
419 p->peer_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_DPORT]);
420 if (attrs[L2TP_ATTR_MTU])
421 p->mtu = rta_getattr_u16(attrs[L2TP_ATTR_MTU]);
422 if (attrs[L2TP_ATTR_IFNAME])
423 p->ifname = rta_getattr_str(attrs[L2TP_ATTR_IFNAME]);
424
425 nla_stats = attrs[L2TP_ATTR_STATS];
426 if (nla_stats) {
427 struct rtattr *tb[L2TP_ATTR_STATS_MAX + 1];
428
429 parse_rtattr_nested(tb, L2TP_ATTR_STATS_MAX, nla_stats);
430
431 if (tb[L2TP_ATTR_TX_PACKETS])
432 data->stats.data_tx_packets = rta_getattr_u64(tb[L2TP_ATTR_TX_PACKETS]);
433 if (tb[L2TP_ATTR_TX_BYTES])
434 data->stats.data_tx_bytes = rta_getattr_u64(tb[L2TP_ATTR_TX_BYTES]);
435 if (tb[L2TP_ATTR_TX_ERRORS])
436 data->stats.data_tx_errors = rta_getattr_u64(tb[L2TP_ATTR_TX_ERRORS]);
437 if (tb[L2TP_ATTR_RX_PACKETS])
438 data->stats.data_rx_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_PACKETS]);
439 if (tb[L2TP_ATTR_RX_BYTES])
440 data->stats.data_rx_bytes = rta_getattr_u64(tb[L2TP_ATTR_RX_BYTES]);
441 if (tb[L2TP_ATTR_RX_ERRORS])
442 data->stats.data_rx_errors = rta_getattr_u64(tb[L2TP_ATTR_RX_ERRORS]);
443 if (tb[L2TP_ATTR_RX_SEQ_DISCARDS])
444 data->stats.data_rx_oos_discards = rta_getattr_u64(tb[L2TP_ATTR_RX_SEQ_DISCARDS]);
445 if (tb[L2TP_ATTR_RX_OOS_PACKETS])
446 data->stats.data_rx_oos_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_OOS_PACKETS]);
447 }
448
449 return 0;
450 }
451
452 static int session_nlmsg(const struct sockaddr_nl *who,
453 struct nlmsghdr *n, void *arg)
454 {
455 int ret = get_response(n, arg);
456
457 if (ret == 0)
458 print_session(arg);
459
460 return ret;
461 }
462
463 static int get_session(struct l2tp_data *p)
464 {
465 GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION,
466 L2TP_CMD_SESSION_GET,
467 NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST);
468
469 req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
470
471 if (p->config.tunnel_id && p->config.session_id) {
472 addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
473 addattr32(&req.n, 128, L2TP_ATTR_SESSION_ID,
474 p->config.session_id);
475 }
476
477 if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
478 return -2;
479
480 new_json_obj(json);
481 if (rtnl_dump_filter(&genl_rth, session_nlmsg, p) < 0) {
482 fprintf(stderr, "Dump terminated\n");
483 exit(1);
484 }
485 delete_json_obj();
486 fflush(stdout);
487
488 return 0;
489 }
490
491 static int tunnel_nlmsg(const struct sockaddr_nl *who,
492 struct nlmsghdr *n, void *arg)
493 {
494 int ret = get_response(n, arg);
495
496 if (ret == 0)
497 print_tunnel(arg);
498
499 return ret;
500 }
501
502 static int get_tunnel(struct l2tp_data *p)
503 {
504 GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
505 L2TP_CMD_TUNNEL_GET,
506 NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST);
507
508 req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
509
510 if (p->config.tunnel_id)
511 addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
512
513 if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
514 return -2;
515
516 new_json_obj(json);
517 if (rtnl_dump_filter(&genl_rth, tunnel_nlmsg, p) < 0) {
518 fprintf(stderr, "Dump terminated\n");
519 exit(1);
520 }
521 delete_json_obj();
522 fflush(stdout);
523
524 return 0;
525 }
526
527 /*****************************************************************************
528 * Command parser
529 *****************************************************************************/
530
531 static void usage(void) __attribute__((noreturn));
532
533 static void usage(void)
534 {
535 fprintf(stderr, "Usage: ip l2tp add tunnel\n"
536 " remote ADDR local ADDR\n"
537 " tunnel_id ID peer_tunnel_id ID\n"
538 " [ encap { ip | udp } ]\n"
539 " [ udp_sport PORT ] [ udp_dport PORT ]\n"
540 " [ udp_csum { on | off } ]\n"
541 " [ udp6_csum_tx { on | off } ]\n"
542 " [ udp6_csum_rx { on | off } ]\n"
543 "Usage: ip l2tp add session [ name NAME ]\n"
544 " tunnel_id ID\n"
545 " session_id ID peer_session_id ID\n"
546 " [ cookie HEXSTR ] [ peer_cookie HEXSTR ]\n"
547 " [ seq { none | send | recv | both } ]\n"
548 " [ l2spec_type L2SPEC ]\n"
549 " ip l2tp del tunnel tunnel_id ID\n"
550 " ip l2tp del session tunnel_id ID session_id ID\n"
551 " ip l2tp show tunnel [ tunnel_id ID ]\n"
552 " ip l2tp show session [ tunnel_id ID ] [ session_id ID ]\n"
553 "\n"
554 "Where: NAME := STRING\n"
555 " ADDR := { IP_ADDRESS | any }\n"
556 " PORT := { 0..65535 }\n"
557 " ID := { 1..4294967295 }\n"
558 " HEXSTR := { 8 or 16 hex digits (4 / 8 bytes) }\n"
559 " L2SPEC := { none | default }\n");
560
561 exit(-1);
562 }
563
564 static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
565 {
566 memset(p, 0, sizeof(*p));
567
568 if (argc == 0)
569 usage();
570
571 /* Defaults */
572 p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT;
573 p->l2spec_len = 4;
574 p->udp6_csum_rx = 1;
575 p->udp6_csum_tx = 1;
576
577 while (argc > 0) {
578 if (strcmp(*argv, "encap") == 0) {
579 NEXT_ARG();
580 if (strcmp(*argv, "ip") == 0) {
581 p->encap = L2TP_ENCAPTYPE_IP;
582 } else if (strcmp(*argv, "udp") == 0) {
583 p->encap = L2TP_ENCAPTYPE_UDP;
584 } else {
585 fprintf(stderr, "Unknown tunnel encapsulation \"%s\"\n", *argv);
586 exit(-1);
587 }
588 } else if (strcmp(*argv, "name") == 0) {
589 NEXT_ARG();
590 if (check_ifname(*argv))
591 invarg("\"name\" not a valid ifname", *argv);
592 p->ifname = *argv;
593 } else if (strcmp(*argv, "remote") == 0) {
594 NEXT_ARG();
595 if (get_addr(&p->peer_ip, *argv, AF_UNSPEC))
596 invarg("invalid remote address\n", *argv);
597 } else if (strcmp(*argv, "local") == 0) {
598 NEXT_ARG();
599 if (get_addr(&p->local_ip, *argv, AF_UNSPEC))
600 invarg("invalid local address\n", *argv);
601 } else if ((strcmp(*argv, "tunnel_id") == 0) ||
602 (strcmp(*argv, "tid") == 0)) {
603 __u32 uval;
604
605 NEXT_ARG();
606 if (get_u32(&uval, *argv, 0))
607 invarg("invalid ID\n", *argv);
608 p->tunnel_id = uval;
609 } else if ((strcmp(*argv, "peer_tunnel_id") == 0) ||
610 (strcmp(*argv, "ptid") == 0)) {
611 __u32 uval;
612
613 NEXT_ARG();
614 if (get_u32(&uval, *argv, 0))
615 invarg("invalid ID\n", *argv);
616 p->peer_tunnel_id = uval;
617 } else if ((strcmp(*argv, "session_id") == 0) ||
618 (strcmp(*argv, "sid") == 0)) {
619 __u32 uval;
620
621 NEXT_ARG();
622 if (get_u32(&uval, *argv, 0))
623 invarg("invalid ID\n", *argv);
624 p->session_id = uval;
625 } else if ((strcmp(*argv, "peer_session_id") == 0) ||
626 (strcmp(*argv, "psid") == 0)) {
627 __u32 uval;
628
629 NEXT_ARG();
630 if (get_u32(&uval, *argv, 0))
631 invarg("invalid ID\n", *argv);
632 p->peer_session_id = uval;
633 } else if (strcmp(*argv, "udp_sport") == 0) {
634 __u16 uval;
635
636 NEXT_ARG();
637 if (get_u16(&uval, *argv, 0))
638 invarg("invalid port\n", *argv);
639 p->local_udp_port = uval;
640 } else if (strcmp(*argv, "udp_dport") == 0) {
641 __u16 uval;
642
643 NEXT_ARG();
644 if (get_u16(&uval, *argv, 0))
645 invarg("invalid port\n", *argv);
646 p->peer_udp_port = uval;
647 } else if (strcmp(*argv, "udp_csum") == 0) {
648 NEXT_ARG();
649 if (strcmp(*argv, "on") == 0)
650 p->udp_csum = 1;
651 else if (strcmp(*argv, "off") == 0)
652 p->udp_csum = 0;
653 else
654 invarg("invalid option for udp_csum\n", *argv);
655 } else if (strcmp(*argv, "udp6_csum_rx") == 0) {
656 NEXT_ARG();
657 if (strcmp(*argv, "on") == 0)
658 p->udp6_csum_rx = 1;
659 else if (strcmp(*argv, "off") == 0)
660 p->udp6_csum_rx = 0;
661 else
662 invarg("invalid option for udp6_csum_rx\n"
663 , *argv);
664 } else if (strcmp(*argv, "udp6_csum_tx") == 0) {
665 NEXT_ARG();
666 if (strcmp(*argv, "on") == 0)
667 p->udp6_csum_tx = 1;
668 else if (strcmp(*argv, "off") == 0)
669 p->udp6_csum_tx = 0;
670 else
671 invarg("invalid option for udp6_csum_tx\n"
672 , *argv);
673 } else if (strcmp(*argv, "offset") == 0) {
674 fprintf(stderr, "Ignoring option \"offset\"\n");
675 NEXT_ARG();
676 } else if (strcmp(*argv, "peer_offset") == 0) {
677 fprintf(stderr, "Ignoring option \"peer_offset\"\n");
678 NEXT_ARG();
679 } else if (strcmp(*argv, "cookie") == 0) {
680 int slen;
681
682 NEXT_ARG();
683 slen = strlen(*argv);
684 if ((slen != 8) && (slen != 16))
685 invarg("cookie must be either 8 or 16 hex digits\n", *argv);
686
687 p->cookie_len = slen / 2;
688 if (hex2mem(*argv, p->cookie, p->cookie_len) < 0)
689 invarg("cookie must be a hex string\n", *argv);
690 } else if (strcmp(*argv, "peer_cookie") == 0) {
691 int slen;
692
693 NEXT_ARG();
694 slen = strlen(*argv);
695 if ((slen != 8) && (slen != 16))
696 invarg("cookie must be either 8 or 16 hex digits\n", *argv);
697
698 p->peer_cookie_len = slen / 2;
699 if (hex2mem(*argv, p->peer_cookie, p->peer_cookie_len) < 0)
700 invarg("cookie must be a hex string\n", *argv);
701 } else if (strcmp(*argv, "l2spec_type") == 0) {
702 NEXT_ARG();
703 if (strcasecmp(*argv, "default") == 0) {
704 p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT;
705 p->l2spec_len = 4;
706 } else if (strcasecmp(*argv, "none") == 0) {
707 p->l2spec_type = L2TP_L2SPECTYPE_NONE;
708 p->l2spec_len = 0;
709 } else {
710 fprintf(stderr,
711 "Unknown layer2specific header type \"%s\"\n",
712 *argv);
713 exit(-1);
714 }
715 } else if (strcmp(*argv, "seq") == 0) {
716 NEXT_ARG();
717 if (strcasecmp(*argv, "both") == 0) {
718 p->recv_seq = 1;
719 p->send_seq = 1;
720 } else if (strcasecmp(*argv, "recv") == 0) {
721 p->recv_seq = 1;
722 } else if (strcasecmp(*argv, "send") == 0) {
723 p->send_seq = 1;
724 } else if (strcasecmp(*argv, "none") == 0) {
725 p->recv_seq = 0;
726 p->send_seq = 0;
727 } else {
728 fprintf(stderr,
729 "Unknown seq value \"%s\"\n", *argv);
730 exit(-1);
731 }
732 } else if (strcmp(*argv, "tunnel") == 0) {
733 p->tunnel = 1;
734 } else if (strcmp(*argv, "session") == 0) {
735 p->session = 1;
736 } else if (matches(*argv, "help") == 0) {
737 usage();
738 } else {
739 fprintf(stderr, "Unknown command: %s\n", *argv);
740 usage();
741 }
742
743 argc--; argv++;
744 }
745
746 return 0;
747 }
748
749
750 static int do_add(int argc, char **argv)
751 {
752 struct l2tp_parm p;
753 int ret = 0;
754
755 if (parse_args(argc, argv, L2TP_ADD, &p) < 0)
756 return -1;
757
758 if (!p.tunnel && !p.session)
759 missarg("tunnel or session");
760
761 if (p.tunnel_id == 0)
762 missarg("tunnel_id");
763
764 /* session_id and peer_session_id must be provided for sessions */
765 if ((p.session) && (p.peer_session_id == 0))
766 missarg("peer_session_id");
767 if ((p.session) && (p.session_id == 0))
768 missarg("session_id");
769
770 /* peer_tunnel_id is needed for tunnels */
771 if ((p.tunnel) && (p.peer_tunnel_id == 0))
772 missarg("peer_tunnel_id");
773
774 if (p.tunnel) {
775 if (p.local_ip.family == AF_UNSPEC)
776 missarg("local");
777
778 if (p.peer_ip.family == AF_UNSPEC)
779 missarg("remote");
780
781 if (p.encap == L2TP_ENCAPTYPE_UDP) {
782 if (p.local_udp_port == 0)
783 missarg("udp_sport");
784 if (p.peer_udp_port == 0)
785 missarg("udp_dport");
786 }
787
788 ret = create_tunnel(&p);
789 }
790
791 if (p.session) {
792 /* Only ethernet pseudowires supported */
793 p.pw_type = L2TP_PWTYPE_ETH;
794
795 ret = create_session(&p);
796 }
797
798 return ret;
799 }
800
801 static int do_del(int argc, char **argv)
802 {
803 struct l2tp_parm p;
804
805 if (parse_args(argc, argv, L2TP_DEL, &p) < 0)
806 return -1;
807
808 if (!p.tunnel && !p.session)
809 missarg("tunnel or session");
810
811 if ((p.tunnel) && (p.tunnel_id == 0))
812 missarg("tunnel_id");
813 if ((p.session) && (p.session_id == 0))
814 missarg("session_id");
815
816 if (p.session_id)
817 return delete_session(&p);
818 else
819 return delete_tunnel(&p);
820
821 return -1;
822 }
823
824 static int do_show(int argc, char **argv)
825 {
826 struct l2tp_data data;
827 struct l2tp_parm *p = &data.config;
828
829 if (parse_args(argc, argv, L2TP_GET, p) < 0)
830 return -1;
831
832 if (!p->tunnel && !p->session)
833 missarg("tunnel or session");
834
835 if (p->session)
836 get_session(&data);
837 else
838 get_tunnel(&data);
839
840 return 0;
841 }
842
843 int do_ipl2tp(int argc, char **argv)
844 {
845 if (argc < 1 || !matches(*argv, "help"))
846 usage();
847
848 if (genl_init_handle(&genl_rth, L2TP_GENL_NAME, &genl_family))
849 exit(1);
850
851 if (matches(*argv, "add") == 0)
852 return do_add(argc-1, argv+1);
853 if (matches(*argv, "delete") == 0)
854 return do_del(argc-1, argv+1);
855 if (matches(*argv, "show") == 0 ||
856 matches(*argv, "lst") == 0 ||
857 matches(*argv, "list") == 0)
858 return do_show(argc-1, argv+1);
859
860 fprintf(stderr,
861 "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv);
862 exit(-1);
863 }