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