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>
31 #include "ip_common.h"
42 uint32_t peer_tunnel_id
;
44 uint32_t peer_session_id
;
47 enum l2tp_encap_type encap
;
48 uint16_t local_udp_port
;
49 uint16_t peer_udp_port
;
53 uint8_t peer_cookie
[8];
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
;
84 struct l2tp_parm config
;
85 struct l2tp_stats stats
;
89 static struct rtnl_handle genl_rth
;
90 static int genl_family
= -1;
92 /*****************************************************************************
94 *****************************************************************************/
96 static int create_tunnel(struct l2tp_parm
*p
)
98 uint32_t local_attr
= L2TP_ATTR_IP_SADDR
;
99 uint32_t peer_attr
= L2TP_ATTR_IP_DADDR
;
101 GENL_REQUEST(req
, 1024, genl_family
, 0, L2TP_GENL_VERSION
,
102 L2TP_CMD_TUNNEL_CREATE
, NLM_F_REQUEST
| NLM_F_ACK
);
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
);
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
);
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
);
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
);
122 if (rtnl_talk(&genl_rth
, &req
.n
, NULL
, 0) < 0)
128 static int delete_tunnel(struct l2tp_parm
*p
)
130 GENL_REQUEST(req
, 128, genl_family
, 0, L2TP_GENL_VERSION
,
131 L2TP_CMD_TUNNEL_DELETE
, NLM_F_REQUEST
| NLM_F_ACK
);
133 addattr32(&req
.n
, 128, L2TP_ATTR_CONN_ID
, p
->tunnel_id
);
135 if (rtnl_talk(&genl_rth
, &req
.n
, NULL
, 0) < 0)
141 static int create_session(struct l2tp_parm
*p
)
143 GENL_REQUEST(req
, 1024, genl_family
, 0, L2TP_GENL_VERSION
,
144 L2TP_CMD_SESSION_CREATE
, NLM_F_REQUEST
| NLM_F_ACK
);
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
);
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
,
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
);
169 if (rtnl_talk(&genl_rth
, &req
.n
, NULL
, 0) < 0)
175 static int delete_session(struct l2tp_parm
*p
)
177 GENL_REQUEST(req
, 1024, genl_family
, 0, L2TP_GENL_VERSION
,
178 L2TP_CMD_SESSION_DELETE
, NLM_F_REQUEST
| NLM_F_ACK
);
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)
188 static void print_cookie(char *name
, const uint8_t *cookie
, int len
)
190 printf(" %s %02x%02x%02x%02x", name
,
191 cookie
[0], cookie
[1],
192 cookie
[2], cookie
[3]);
194 printf("%02x%02x%02x%02x",
195 cookie
[4], cookie
[5],
196 cookie
[6], cookie
[7]);
199 static void print_tunnel(const struct l2tp_data
*data
)
201 const struct l2tp_parm
*p
= &data
->config
;
202 char buf
[INET6_ADDRSTRLEN
];
204 printf("Tunnel %u, encap %s\n",
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",
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
);
218 static void print_session(struct l2tp_data
*data
)
220 struct l2tp_parm
*p
= &data
->config
;
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
);
227 if (p
->ifname
!= NULL
) {
228 printf(" interface name: %s\n", p
->ifname
);
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
);
237 if (p
->reorder_timeout
!= 0)
238 printf(" reorder timeout: %u\n", p
->reorder_timeout
);
243 static int get_response(struct nlmsghdr
*n
, void *arg
)
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
;
252 /* Validate message and parse attributes */
253 if (n
->nlmsg_type
== NLMSG_ERROR
)
256 ghdr
= NLMSG_DATA(n
);
257 len
= n
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ghdr
));
261 parse_rtattr(attrs
, L2TP_ATTR_MAX
, (void *)ghdr
+ GENL_HDRLEN
, len
);
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
]);
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
]));
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
]));
293 p
->recv_seq
= !!attrs
[L2TP_ATTR_RECV_SEQ
];
294 p
->send_seq
= !!attrs
[L2TP_ATTR_SEND_SEQ
];
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;
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;
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;
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;
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
]);
331 nla_stats
= attrs
[L2TP_ATTR_STATS
];
333 struct rtattr
*tb
[L2TP_ATTR_STATS_MAX
+ 1];
335 parse_rtattr_nested(tb
, L2TP_ATTR_STATS_MAX
, nla_stats
);
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
]);
358 static int session_nlmsg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
, void *arg
)
360 int ret
= get_response(n
, arg
);
368 static int get_session(struct l2tp_data
*p
)
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
);
374 req
.n
.nlmsg_seq
= genl_rth
.dump
= ++genl_rth
.seq
;
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
);
381 if (rtnl_send(&genl_rth
, &req
, req
.n
.nlmsg_len
) < 0)
384 if (rtnl_dump_filter(&genl_rth
, session_nlmsg
, p
) < 0) {
385 fprintf(stderr
, "Dump terminated\n");
392 static int tunnel_nlmsg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
, void *arg
)
394 int ret
= get_response(n
, arg
);
402 static int get_tunnel(struct l2tp_data
*p
)
404 GENL_REQUEST(req
, 1024, genl_family
, 0, L2TP_GENL_VERSION
,
406 NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
);
408 req
.n
.nlmsg_seq
= genl_rth
.dump
= ++genl_rth
.seq
;
410 if (p
->config
.tunnel_id
)
411 addattr32(&req
.n
, 1024, L2TP_ATTR_CONN_ID
, p
->config
.tunnel_id
);
413 if (rtnl_send(&genl_rth
, &req
, req
.n
.nlmsg_len
) < 0)
416 if (rtnl_dump_filter(&genl_rth
, tunnel_nlmsg
, p
) < 0) {
417 fprintf(stderr
, "Dump terminated\n");
424 /*****************************************************************************
426 *****************************************************************************/
428 static int hex(char ch
)
430 if ((ch
>= 'a') && (ch
<= 'f'))
431 return ch
- 'a' + 10;
432 if ((ch
>= '0') && (ch
<= '9'))
434 if ((ch
>= 'A') && (ch
<= 'F'))
435 return ch
- 'A' + 10;
439 static int hex2mem(const char *buf
, uint8_t *mem
, int count
)
444 for (i
= 0, j
= 0; i
< count
; i
++, j
+= 2) {
464 static void usage(void) __attribute__((noreturn
));
466 static void usage(void)
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");
493 static int parse_args(int argc
, char **argv
, int cmd
, struct l2tp_parm
*p
)
495 memset(p
, 0, sizeof(*p
));
501 p
->l2spec_type
= L2TP_L2SPECTYPE_DEFAULT
;
505 if (strcmp(*argv
, "encap") == 0) {
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
;
512 fprintf(stderr
, "Unknown tunnel encapsulation \"%s\"\n", *argv
);
515 } else if (strcmp(*argv
, "name") == 0) {
518 } else if (strcmp(*argv
, "remote") == 0) {
520 if (get_addr(&p
->peer_ip
, *argv
, AF_UNSPEC
))
521 invarg("invalid remote address\n", *argv
);
522 } else if (strcmp(*argv
, "local") == 0) {
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)) {
530 if (get_u32(&uval
, *argv
, 0))
531 invarg("invalid ID\n", *argv
);
533 } else if ((strcmp(*argv
, "peer_tunnel_id") == 0) ||
534 (strcmp(*argv
, "ptid") == 0)) {
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)) {
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)) {
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) {
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) {
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) {
569 if (get_u8(&uval
, *argv
, 0))
570 invarg("invalid offset\n", *argv
);
572 } else if (strcmp(*argv
, "peer_offset") == 0) {
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) {
581 slen
= strlen(*argv
);
582 if ((slen
!= 8) && (slen
!= 16))
583 invarg("cookie must be either 8 or 16 hex digits\n", *argv
);
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) {
591 slen
= strlen(*argv
);
592 if ((slen
!= 8) && (slen
!= 16))
593 invarg("cookie must be either 8 or 16 hex digits\n", *argv
);
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) {
600 if (strcasecmp(*argv
, "default") == 0) {
601 p
->l2spec_type
= L2TP_L2SPECTYPE_DEFAULT
;
603 } else if (strcasecmp(*argv
, "none") == 0) {
604 p
->l2spec_type
= L2TP_L2SPECTYPE_NONE
;
607 fprintf(stderr
, "Unknown layer2specific header type \"%s\"\n", *argv
);
610 } else if (strcmp(*argv
, "tunnel") == 0) {
612 } else if (strcmp(*argv
, "session") == 0) {
614 } else if (matches(*argv
, "help") == 0) {
617 fprintf(stderr
, "Unknown command: %s\n", *argv
);
628 static int do_add(int argc
, char **argv
)
633 if (parse_args(argc
, argv
, L2TP_ADD
, &p
) < 0)
636 if (!p
.tunnel
&& !p
.session
)
637 missarg("tunnel or session");
639 if (p
.tunnel_id
== 0)
640 missarg("tunnel_id");
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");
648 /* peer_tunnel_id is needed for tunnels */
649 if ((p
.tunnel
) && (p
.peer_tunnel_id
== 0))
650 missarg("peer_tunnel_id");
653 if (p
.local_ip
.family
== AF_UNSPEC
)
656 if (p
.peer_ip
.family
== AF_UNSPEC
)
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");
666 ret
= create_tunnel(&p
);
670 /* Only ethernet pseudowires supported */
671 p
.pw_type
= L2TP_PWTYPE_ETH
;
673 ret
= create_session(&p
);
679 static int do_del(int argc
, char **argv
)
683 if (parse_args(argc
, argv
, L2TP_DEL
, &p
) < 0)
686 if (!p
.tunnel
&& !p
.session
)
687 missarg("tunnel or session");
689 if ((p
.tunnel
) && (p
.tunnel_id
== 0))
690 missarg("tunnel_id");
691 if ((p
.session
) && (p
.session_id
== 0))
692 missarg("session_id");
695 return delete_session(&p
);
697 return delete_tunnel(&p
);
702 static int do_show(int argc
, char **argv
)
704 struct l2tp_data data
;
705 struct l2tp_parm
*p
= &data
.config
;
707 if (parse_args(argc
, argv
, L2TP_GET
, p
) < 0)
710 if (!p
->tunnel
&& !p
->session
)
711 missarg("tunnel or session");
721 int do_ipl2tp(int argc
, char **argv
)
723 if (argc
< 1 || !matches(*argv
, "help"))
726 if (genl_family
< 0) {
727 if (rtnl_open_byproto(&genl_rth
, 0, NETLINK_GENERIC
) < 0) {
728 fprintf(stderr
, "Cannot open generic netlink socket\n");
732 genl_family
= genl_resolve_family(&genl_rth
, L2TP_GENL_NAME
);
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);
746 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv
);