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.
9 * Original Author: James Chapman <jchapman@katalix.com>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <arpa/inet.h>
21 #include <sys/ioctl.h>
23 #include <linux/if_arp.h>
26 #include <linux/genetlink.h>
27 #include <linux/l2tp.h>
30 #include "ip_common.h"
41 uint32_t peer_tunnel_id;
43 uint32_t peer_session_id;
46 enum l2tp_encap_type encap;
47 uint16_t local_udp_port;
48 uint16_t peer_udp_port;
52 uint8_t peer_cookie[8];
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;
81 struct l2tp_parm config;
82 struct l2tp_stats stats;
86 static struct rtnl_handle genl_rth;
87 static int genl_family = -1;
89 /*****************************************************************************
91 *****************************************************************************/
93 static int create_tunnel(struct l2tp_parm *p)
100 uint32_t local_attr = L2TP_ATTR_IP_SADDR;
101 uint32_t peer_attr = L2TP_ATTR_IP_DADDR;
103 memset(&req, 0, sizeof(req));
104 req.n.nlmsg_type = genl_family;
105 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
106 req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
107 req.g.cmd = L2TP_CMD_TUNNEL_CREATE;
108 req.g.version = L2TP_GENL_VERSION;
110 addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
111 addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id);
112 addattr8(&req.n, 1024, L2TP_ATTR_PROTO_VERSION, 3);
113 addattr16(&req.n, 1024, L2TP_ATTR_ENCAP_TYPE, p->encap);
115 if (p->local_ip.family == AF_INET6)
116 local_attr = L2TP_ATTR_IP6_SADDR;
117 addattr_l(&req.n, 1024, local_attr, &p->local_ip.data, p->local_ip.bytelen);
119 if (p->peer_ip.family == AF_INET6)
120 peer_attr = L2TP_ATTR_IP6_DADDR;
121 addattr_l(&req.n, 1024, peer_attr, &p->peer_ip.data, p->peer_ip.bytelen);
123 if (p->encap == L2TP_ENCAPTYPE_UDP) {
124 addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port);
125 addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port);
128 if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
134 static int delete_tunnel(struct l2tp_parm *p)
142 memset(&req, 0, sizeof(req));
143 req.n.nlmsg_type = genl_family;
144 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
145 req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
146 req.g.cmd = L2TP_CMD_TUNNEL_DELETE;
147 req.g.version = L2TP_GENL_VERSION;
149 addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id);
151 if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
157 static int create_session(struct l2tp_parm *p)
165 memset(&req, 0, sizeof(req));
166 req.n.nlmsg_type = genl_family;
167 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
168 req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
169 req.g.cmd = L2TP_CMD_SESSION_CREATE;
170 req.g.version = L2TP_GENL_VERSION;
172 addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
173 addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id);
174 addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
175 addattr32(&req.n, 1024, L2TP_ATTR_PEER_SESSION_ID, p->peer_session_id);
176 addattr16(&req.n, 1024, L2TP_ATTR_PW_TYPE, p->pw_type);
178 if (p->mtu) addattr16(&req.n, 1024, L2TP_ATTR_MTU, p->mtu);
179 if (p->recv_seq) addattr(&req.n, 1024, L2TP_ATTR_RECV_SEQ);
180 if (p->send_seq) addattr(&req.n, 1024, L2TP_ATTR_SEND_SEQ);
181 if (p->lns_mode) addattr(&req.n, 1024, L2TP_ATTR_LNS_MODE);
182 if (p->data_seq) addattr8(&req.n, 1024, L2TP_ATTR_DATA_SEQ, p->data_seq);
183 if (p->reorder_timeout) addattr64(&req.n, 1024, L2TP_ATTR_RECV_TIMEOUT,
185 if (p->offset) addattr16(&req.n, 1024, L2TP_ATTR_OFFSET, p->offset);
186 if (p->cookie_len) addattr_l(&req.n, 1024, L2TP_ATTR_COOKIE,
187 p->cookie, p->cookie_len);
188 if (p->peer_cookie_len) addattr_l(&req.n, 1024, L2TP_ATTR_PEER_COOKIE,
189 p->peer_cookie, p->peer_cookie_len);
190 if (p->ifname && p->ifname[0])
191 addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname);
193 if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
199 static int delete_session(struct l2tp_parm *p)
207 memset(&req, 0, sizeof(req));
208 req.n.nlmsg_type = genl_family;
209 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
210 req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
211 req.g.cmd = L2TP_CMD_SESSION_DELETE;
212 req.g.version = L2TP_GENL_VERSION;
214 addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
215 addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
216 if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
222 static void print_cookie(char *name, const uint8_t *cookie, int len)
224 printf(" %s %02x%02x%02x%02x", name,
225 cookie[0], cookie[1],
226 cookie[2], cookie[3]);
228 printf("%02x%02x%02x%02x",
229 cookie[4], cookie[5],
230 cookie[6], cookie[7]);
233 static void print_tunnel(const struct l2tp_data *data)
235 const struct l2tp_parm *p = &data->config;
236 char buf[INET6_ADDRSTRLEN];
238 printf("Tunnel %u, encap %s\n",
240 p->encap == L2TP_ENCAPTYPE_UDP ? "UDP" :
241 p->encap == L2TP_ENCAPTYPE_IP ? "IP" : "??");
242 printf(" From %s ", inet_ntop(p->local_ip.family, p->local_ip.data, buf, sizeof(buf)));
243 printf("to %s\n", inet_ntop(p->peer_ip.family, p->peer_ip.data, buf, sizeof(buf)));
244 printf(" Peer tunnel %u\n",
247 if (p->encap == L2TP_ENCAPTYPE_UDP)
248 printf(" UDP source / dest ports: %hu/%hu\n",
249 p->local_udp_port, p->peer_udp_port);
252 static void print_session(struct l2tp_data *data)
254 struct l2tp_parm *p = &data->config;
256 printf("Session %u in tunnel %u\n",
257 p->session_id, p->tunnel_id);
258 printf(" Peer session %u, tunnel %u\n",
259 p->peer_session_id, p->peer_tunnel_id);
261 if (p->ifname != NULL) {
262 printf(" interface name: %s\n", p->ifname);
264 printf(" offset %u, peer offset %u\n",
265 p->offset, p->peer_offset);
266 if (p->cookie_len > 0)
267 print_cookie("cookie", p->cookie, p->cookie_len);
268 if (p->peer_cookie_len > 0)
269 print_cookie("peer cookie", p->peer_cookie, p->peer_cookie_len);
271 if (p->reorder_timeout != 0) {
272 printf(" reorder timeout: %u\n", p->reorder_timeout);
276 static int get_response(struct nlmsghdr *n, void *arg)
278 struct genlmsghdr *ghdr;
279 struct l2tp_data *data = arg;
280 struct l2tp_parm *p = &data->config;
281 struct rtattr *attrs[L2TP_ATTR_MAX + 1];
282 struct rtattr *nla_stats;
285 /* Validate message and parse attributes */
286 if (n->nlmsg_type == NLMSG_ERROR)
289 ghdr = NLMSG_DATA(n);
290 len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ghdr));
294 parse_rtattr(attrs, L2TP_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
296 if (attrs[L2TP_ATTR_PW_TYPE])
297 p->pw_type = rta_getattr_u16(attrs[L2TP_ATTR_PW_TYPE]);
298 if (attrs[L2TP_ATTR_ENCAP_TYPE])
299 p->encap = rta_getattr_u16(attrs[L2TP_ATTR_ENCAP_TYPE]);
300 if (attrs[L2TP_ATTR_OFFSET])
301 p->offset = rta_getattr_u16(attrs[L2TP_ATTR_OFFSET]);
302 if (attrs[L2TP_ATTR_DATA_SEQ])
303 p->data_seq = rta_getattr_u16(attrs[L2TP_ATTR_DATA_SEQ]);
304 if (attrs[L2TP_ATTR_CONN_ID])
305 p->tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_CONN_ID]);
306 if (attrs[L2TP_ATTR_PEER_CONN_ID])
307 p->peer_tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_CONN_ID]);
308 if (attrs[L2TP_ATTR_SESSION_ID])
309 p->session_id = rta_getattr_u32(attrs[L2TP_ATTR_SESSION_ID]);
310 if (attrs[L2TP_ATTR_PEER_SESSION_ID])
311 p->peer_session_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_SESSION_ID]);
313 p->udp_csum = !!attrs[L2TP_ATTR_UDP_CSUM];
314 if (attrs[L2TP_ATTR_COOKIE])
315 memcpy(p->cookie, RTA_DATA(attrs[L2TP_ATTR_COOKIE]),
316 p->cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_COOKIE]));
318 if (attrs[L2TP_ATTR_PEER_COOKIE])
319 memcpy(p->peer_cookie, RTA_DATA(attrs[L2TP_ATTR_PEER_COOKIE]),
320 p->peer_cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_PEER_COOKIE]));
322 p->recv_seq = !!attrs[L2TP_ATTR_RECV_SEQ];
323 p->send_seq = !!attrs[L2TP_ATTR_SEND_SEQ];
325 if (attrs[L2TP_ATTR_RECV_TIMEOUT])
326 p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]);
327 if (attrs[L2TP_ATTR_IP_SADDR]) {
328 p->local_ip.family = AF_INET;
329 p->local_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_SADDR]);
330 p->local_ip.bytelen = 4;
331 p->local_ip.bitlen = -1;
333 if (attrs[L2TP_ATTR_IP_DADDR]) {
334 p->peer_ip.family = AF_INET;
335 p->peer_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_DADDR]);
336 p->peer_ip.bytelen = 4;
337 p->peer_ip.bitlen = -1;
339 if (attrs[L2TP_ATTR_IP6_SADDR]) {
340 p->local_ip.family = AF_INET6;
341 memcpy(&p->local_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_SADDR]),
342 p->local_ip.bytelen = 16);
343 p->local_ip.bitlen = -1;
345 if (attrs[L2TP_ATTR_IP6_DADDR]) {
346 p->peer_ip.family = AF_INET6;
347 memcpy(&p->peer_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_DADDR]),
348 p->peer_ip.bytelen = 16);
349 p->peer_ip.bitlen = -1;
351 if (attrs[L2TP_ATTR_UDP_SPORT])
352 p->local_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_SPORT]);
353 if (attrs[L2TP_ATTR_UDP_DPORT])
354 p->peer_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_DPORT]);
355 if (attrs[L2TP_ATTR_MTU])
356 p->mtu = rta_getattr_u16(attrs[L2TP_ATTR_MTU]);
357 if (attrs[L2TP_ATTR_IFNAME])
358 p->ifname = rta_getattr_str(attrs[L2TP_ATTR_IFNAME]);
360 nla_stats = attrs[L2TP_ATTR_STATS];
362 struct rtattr *tb[L2TP_ATTR_STATS_MAX + 1];
364 parse_rtattr_nested(tb, L2TP_ATTR_STATS_MAX, nla_stats);
366 if (tb[L2TP_ATTR_TX_PACKETS])
367 data->stats.data_tx_packets = rta_getattr_u64(tb[L2TP_ATTR_TX_PACKETS]);
368 if (tb[L2TP_ATTR_TX_BYTES])
369 data->stats.data_tx_bytes = rta_getattr_u64(tb[L2TP_ATTR_TX_BYTES]);
370 if (tb[L2TP_ATTR_TX_ERRORS])
371 data->stats.data_tx_errors = rta_getattr_u64(tb[L2TP_ATTR_TX_ERRORS]);
372 if (tb[L2TP_ATTR_RX_PACKETS])
373 data->stats.data_rx_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_PACKETS]);
374 if (tb[L2TP_ATTR_RX_BYTES])
375 data->stats.data_rx_bytes = rta_getattr_u64(tb[L2TP_ATTR_RX_BYTES]);
376 if (tb[L2TP_ATTR_RX_ERRORS])
377 data->stats.data_rx_errors = rta_getattr_u64(tb[L2TP_ATTR_RX_ERRORS]);
378 if (tb[L2TP_ATTR_RX_SEQ_DISCARDS])
379 data->stats.data_rx_oos_discards = rta_getattr_u64(tb[L2TP_ATTR_RX_SEQ_DISCARDS]);
380 if (tb[L2TP_ATTR_RX_OOS_PACKETS])
381 data->stats.data_rx_oos_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_OOS_PACKETS]);
387 static int session_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
389 int ret = get_response(n, arg);
397 static int get_session(struct l2tp_data *p)
405 memset(&req, 0, sizeof(req));
406 req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
407 req.n.nlmsg_type = genl_family;
408 req.n.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
409 req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
411 req.g.cmd = L2TP_CMD_SESSION_GET;
412 req.g.version = L2TP_GENL_VERSION;
414 if (p->config.tunnel_id && p->config.session_id) {
415 addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
416 addattr32(&req.n, 128, L2TP_ATTR_SESSION_ID, p->config.session_id);
419 if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
422 if (rtnl_dump_filter(&genl_rth, session_nlmsg, p) < 0) {
423 fprintf(stderr, "Dump terminated\n");
430 static int tunnel_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
432 int ret = get_response(n, arg);
440 static int get_tunnel(struct l2tp_data *p)
448 memset(&req, 0, sizeof(req));
449 req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
450 req.n.nlmsg_type = genl_family;
451 req.n.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
452 req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
454 req.g.cmd = L2TP_CMD_TUNNEL_GET;
455 req.g.version = L2TP_GENL_VERSION;
457 if (p->config.tunnel_id)
458 addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
460 if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
463 if (rtnl_dump_filter(&genl_rth, tunnel_nlmsg, p) < 0) {
464 fprintf(stderr, "Dump terminated\n");
471 /*****************************************************************************
473 *****************************************************************************/
475 static int hex(char ch)
477 if ((ch >= 'a') && (ch <= 'f'))
478 return ch - 'a' + 10;
479 if ((ch >= '0') && (ch <= '9'))
481 if ((ch >= 'A') && (ch <= 'F'))
482 return ch - 'A' + 10;
486 static int hex2mem(const char *buf, uint8_t *mem, int count)
491 for (i = 0, j = 0; i < count; i++, j += 2) {
511 static void usage(void) __attribute__((noreturn));
513 static void usage(void)
515 fprintf(stderr, "Usage: ip l2tp add tunnel\n");
516 fprintf(stderr, " remote ADDR local ADDR\n");
517 fprintf(stderr, " tunnel_id ID peer_tunnel_id ID\n");
518 fprintf(stderr, " [ encap { ip | udp } ]\n");
519 fprintf(stderr, " [ udp_sport PORT ] [ udp_dport PORT ]\n");
520 fprintf(stderr, "Usage: ip l2tp add session [ name NAME ]\n");
521 fprintf(stderr, " tunnel_id ID\n");
522 fprintf(stderr, " session_id ID peer_session_id ID\n");
523 fprintf(stderr, " [ cookie HEXSTR ] [ peer_cookie HEXSTR ]\n");
524 fprintf(stderr, " [ offset OFFSET ] [ peer_offset OFFSET ]\n");
525 fprintf(stderr, " ip l2tp del tunnel tunnel_id ID\n");
526 fprintf(stderr, " ip l2tp del session tunnel_id ID session_id ID\n");
527 fprintf(stderr, " ip l2tp show tunnel [ tunnel_id ID ]\n");
528 fprintf(stderr, " ip l2tp show session [ tunnel_id ID ] [ session_id ID ]\n");
529 fprintf(stderr, "\n");
530 fprintf(stderr, "Where: NAME := STRING\n");
531 fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n");
532 fprintf(stderr, " PORT := { 0..65535 }\n");
533 fprintf(stderr, " ID := { 1..4294967295 }\n");
534 fprintf(stderr, " HEXSTR := { 8 or 16 hex digits (4 / 8 bytes) }\n");
538 static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
540 memset(p, 0, sizeof(*p));
546 if (strcmp(*argv, "encap") == 0) {
548 if (strcmp(*argv, "ip") == 0) {
549 p->encap = L2TP_ENCAPTYPE_IP;
550 } else if (strcmp(*argv, "udp") == 0) {
551 p->encap = L2TP_ENCAPTYPE_UDP;
553 fprintf(stderr, "Unknown tunnel encapsulation.\n");
556 } else if (strcmp(*argv, "name") == 0) {
559 } else if (strcmp(*argv, "remote") == 0) {
561 if (get_addr(&p->peer_ip, *argv, AF_UNSPEC))
562 invarg("invalid remote address\n", *argv);
563 } else if (strcmp(*argv, "local") == 0) {
565 if (get_addr(&p->local_ip, *argv, AF_UNSPEC))
566 invarg("invalid local address\n", *argv);
567 } else if ((strcmp(*argv, "tunnel_id") == 0) ||
568 (strcmp(*argv, "tid") == 0)) {
571 if (get_u32(&uval, *argv, 0))
572 invarg("invalid ID\n", *argv);
574 } else if ((strcmp(*argv, "peer_tunnel_id") == 0) ||
575 (strcmp(*argv, "ptid") == 0)) {
578 if (get_u32(&uval, *argv, 0))
579 invarg("invalid ID\n", *argv);
580 p->peer_tunnel_id = uval;
581 } else if ((strcmp(*argv, "session_id") == 0) ||
582 (strcmp(*argv, "sid") == 0)) {
585 if (get_u32(&uval, *argv, 0))
586 invarg("invalid ID\n", *argv);
587 p->session_id = uval;
588 } else if ((strcmp(*argv, "peer_session_id") == 0) ||
589 (strcmp(*argv, "psid") == 0)) {
592 if (get_u32(&uval, *argv, 0))
593 invarg("invalid ID\n", *argv);
594 p->peer_session_id = uval;
595 } else if (strcmp(*argv, "udp_sport") == 0) {
598 if (get_u16(&uval, *argv, 0))
599 invarg("invalid port\n", *argv);
600 p->local_udp_port = uval;
601 } else if (strcmp(*argv, "udp_dport") == 0) {
604 if (get_u16(&uval, *argv, 0))
605 invarg("invalid port\n", *argv);
606 p->peer_udp_port = uval;
607 } else if (strcmp(*argv, "offset") == 0) {
610 if (get_u8(&uval, *argv, 0))
611 invarg("invalid offset\n", *argv);
613 } else if (strcmp(*argv, "peer_offset") == 0) {
616 if (get_u8(&uval, *argv, 0))
617 invarg("invalid offset\n", *argv);
618 p->peer_offset = uval;
619 } else if (strcmp(*argv, "cookie") == 0) {
622 slen = strlen(*argv);
623 if ((slen != 8) && (slen != 16))
624 invarg("cookie must be either 8 or 16 hex digits\n", *argv);
626 p->cookie_len = slen / 2;
627 if (hex2mem(*argv, p->cookie, p->cookie_len) < 0)
628 invarg("cookie must be a hex string\n", *argv);
629 } else if (strcmp(*argv, "peer_cookie") == 0) {
632 slen = strlen(*argv);
633 if ((slen != 8) && (slen != 16))
634 invarg("cookie must be either 8 or 16 hex digits\n", *argv);
636 p->peer_cookie_len = slen / 2;
637 if (hex2mem(*argv, p->peer_cookie, p->peer_cookie_len) < 0)
638 invarg("cookie must be a hex string\n", *argv);
639 } else if (strcmp(*argv, "tunnel") == 0) {
641 } else if (strcmp(*argv, "session") == 0) {
643 } else if (matches(*argv, "help") == 0) {
646 fprintf(stderr, "Unknown command: %s\n", *argv);
657 static int do_add(int argc, char **argv)
662 if (parse_args(argc, argv, L2TP_ADD, &p) < 0)
665 if (!p.tunnel && !p.session)
666 missarg("tunnel or session");
668 if (p.tunnel_id == 0)
669 missarg("tunnel_id");
671 /* session_id and peer_session_id must be provided for sessions */
672 if ((p.session) && (p.peer_session_id == 0))
673 missarg("peer_session_id");
674 if ((p.session) && (p.session_id == 0))
675 missarg("session_id");
677 /* peer_tunnel_id is needed for tunnels */
678 if ((p.tunnel) && (p.peer_tunnel_id == 0))
679 missarg("peer_tunnel_id");
682 if (p.local_ip.family == AF_UNSPEC)
685 if (p.peer_ip.family == AF_UNSPEC)
688 if (p.encap == L2TP_ENCAPTYPE_UDP) {
689 if (p.local_udp_port == 0)
690 missarg("udp_sport");
691 if (p.peer_udp_port == 0)
692 missarg("udp_dport");
695 ret = create_tunnel(&p);
699 /* Only ethernet pseudowires supported */
700 p.pw_type = L2TP_PWTYPE_ETH;
702 ret = create_session(&p);
708 static int do_del(int argc, char **argv)
712 if (parse_args(argc, argv, L2TP_DEL, &p) < 0)
715 if (!p.tunnel && !p.session)
716 missarg("tunnel or session");
718 if ((p.tunnel) && (p.tunnel_id == 0))
719 missarg("tunnel_id");
720 if ((p.session) && (p.session_id == 0))
721 missarg("session_id");
724 return delete_session(&p);
726 return delete_tunnel(&p);
731 static int do_show(int argc, char **argv)
733 struct l2tp_data data;
734 struct l2tp_parm *p = &data.config;
736 if (parse_args(argc, argv, L2TP_GET, p) < 0)
739 if (!p->tunnel && !p->session)
740 missarg("tunnel or session");
750 static int genl_parse_getfamily(struct nlmsghdr *nlh)
752 struct rtattr *tb[CTRL_ATTR_MAX + 1];
753 struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
754 int len = nlh->nlmsg_len;
755 struct rtattr *attrs;
757 if (nlh->nlmsg_type != GENL_ID_CTRL) {
758 fprintf(stderr, "Not a controller message, nlmsg_len=%d "
759 "nlmsg_type=0x%x\n", nlh->nlmsg_len, nlh->nlmsg_type);
763 if (ghdr->cmd != CTRL_CMD_NEWFAMILY) {
764 fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd);
768 len -= NLMSG_LENGTH(GENL_HDRLEN);
771 fprintf(stderr, "wrong controller message len %d\n", len);
775 attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
776 parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
778 if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
779 fprintf(stderr, "Missing family id TLV\n");
783 return rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
786 int genl_ctrl_resolve_family(const char *family)
794 memset(&req, 0, sizeof(req));
795 req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
796 req.n.nlmsg_flags = NLM_F_REQUEST;
797 req.n.nlmsg_type = GENL_ID_CTRL;
798 req.g.cmd = CTRL_CMD_GETFAMILY;
800 addattr_l(&req.n, 1024, CTRL_ATTR_FAMILY_NAME,
801 family, strlen(family) + 1);
803 if (rtnl_talk(&genl_rth, &req.n, 0, 0, &req.n) < 0) {
804 fprintf(stderr, "Error talking to the kernel\n");
808 return genl_parse_getfamily(&req.n);
811 int do_ipl2tp(int argc, char **argv)
813 if (genl_family < 0) {
814 if (rtnl_open_byproto(&genl_rth, 0, NETLINK_GENERIC) < 0) {
815 fprintf(stderr, "Cannot open generic netlink socket\n");
819 genl_family = genl_ctrl_resolve_family(L2TP_GENL_NAME);
827 if (matches(*argv, "add") == 0)
828 return do_add(argc-1, argv+1);
829 if (matches(*argv, "delete") == 0)
830 return do_del(argc-1, argv+1);
831 if (matches(*argv, "show") == 0 ||
832 matches(*argv, "lst") == 0 ||
833 matches(*argv, "list") == 0)
834 return do_show(argc-1, argv+1);
835 if (matches(*argv, "help") == 0)
838 fprintf(stderr, "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv);