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];
53 struct in_addr local_ip
;
54 struct in_addr peer_ip
;
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
)
101 memset(&req
, 0, sizeof(req
));
102 req
.n
.nlmsg_type
= genl_family
;
103 req
.n
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
104 req
.n
.nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
105 req
.g
.cmd
= L2TP_CMD_TUNNEL_CREATE
;
106 req
.g
.version
= L2TP_GENL_VERSION
;
108 addattr32(&req
.n
, 1024, L2TP_ATTR_CONN_ID
, p
->tunnel_id
);
109 addattr32(&req
.n
, 1024, L2TP_ATTR_PEER_CONN_ID
, p
->peer_tunnel_id
);
110 addattr8(&req
.n
, 1024, L2TP_ATTR_PROTO_VERSION
, 3);
111 addattr16(&req
.n
, 1024, L2TP_ATTR_ENCAP_TYPE
, p
->encap
);
113 addattr32(&req
.n
, 1024, L2TP_ATTR_IP_SADDR
, p
->local_ip
.s_addr
);
114 addattr32(&req
.n
, 1024, L2TP_ATTR_IP_DADDR
, p
->peer_ip
.s_addr
);
115 if (p
->encap
== L2TP_ENCAPTYPE_UDP
) {
116 addattr16(&req
.n
, 1024, L2TP_ATTR_UDP_SPORT
, p
->local_udp_port
);
117 addattr16(&req
.n
, 1024, L2TP_ATTR_UDP_DPORT
, p
->peer_udp_port
);
120 if (rtnl_talk(&genl_rth
, &req
.n
, 0, 0, NULL
) < 0)
126 static int delete_tunnel(struct l2tp_parm
*p
)
134 memset(&req
, 0, sizeof(req
));
135 req
.n
.nlmsg_type
= genl_family
;
136 req
.n
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
137 req
.n
.nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
138 req
.g
.cmd
= L2TP_CMD_TUNNEL_DELETE
;
139 req
.g
.version
= L2TP_GENL_VERSION
;
141 addattr32(&req
.n
, 128, L2TP_ATTR_CONN_ID
, p
->tunnel_id
);
143 if (rtnl_talk(&genl_rth
, &req
.n
, 0, 0, NULL
) < 0)
149 static int create_session(struct l2tp_parm
*p
)
157 memset(&req
, 0, sizeof(req
));
158 req
.n
.nlmsg_type
= genl_family
;
159 req
.n
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
160 req
.n
.nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
161 req
.g
.cmd
= L2TP_CMD_SESSION_CREATE
;
162 req
.g
.version
= L2TP_GENL_VERSION
;
164 addattr32(&req
.n
, 1024, L2TP_ATTR_CONN_ID
, p
->tunnel_id
);
165 addattr32(&req
.n
, 1024, L2TP_ATTR_PEER_CONN_ID
, p
->peer_tunnel_id
);
166 addattr32(&req
.n
, 1024, L2TP_ATTR_SESSION_ID
, p
->session_id
);
167 addattr32(&req
.n
, 1024, L2TP_ATTR_PEER_SESSION_ID
, p
->peer_session_id
);
168 addattr16(&req
.n
, 1024, L2TP_ATTR_PW_TYPE
, p
->pw_type
);
170 if (p
->mtu
) addattr16(&req
.n
, 1024, L2TP_ATTR_MTU
, p
->mtu
);
171 if (p
->recv_seq
) addattr(&req
.n
, 1024, L2TP_ATTR_RECV_SEQ
);
172 if (p
->send_seq
) addattr(&req
.n
, 1024, L2TP_ATTR_SEND_SEQ
);
173 if (p
->lns_mode
) addattr(&req
.n
, 1024, L2TP_ATTR_LNS_MODE
);
174 if (p
->data_seq
) addattr8(&req
.n
, 1024, L2TP_ATTR_DATA_SEQ
, p
->data_seq
);
175 if (p
->reorder_timeout
) addattr64(&req
.n
, 1024, L2TP_ATTR_RECV_TIMEOUT
,
177 if (p
->offset
) addattr16(&req
.n
, 1024, L2TP_ATTR_OFFSET
, p
->offset
);
178 if (p
->cookie_len
) addattr_l(&req
.n
, 1024, L2TP_ATTR_COOKIE
,
179 p
->cookie
, p
->cookie_len
);
180 if (p
->peer_cookie_len
) addattr_l(&req
.n
, 1024, L2TP_ATTR_PEER_COOKIE
,
181 p
->peer_cookie
, p
->peer_cookie_len
);
182 if (p
->ifname
&& p
->ifname
[0])
183 addattrstrz(&req
.n
, 1024, L2TP_ATTR_IFNAME
, p
->ifname
);
185 if (rtnl_talk(&genl_rth
, &req
.n
, 0, 0, NULL
) < 0)
191 static int delete_session(struct l2tp_parm
*p
)
199 memset(&req
, 0, sizeof(req
));
200 req
.n
.nlmsg_type
= genl_family
;
201 req
.n
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
202 req
.n
.nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
203 req
.g
.cmd
= L2TP_CMD_SESSION_DELETE
;
204 req
.g
.version
= L2TP_GENL_VERSION
;
206 addattr32(&req
.n
, 1024, L2TP_ATTR_CONN_ID
, p
->tunnel_id
);
207 addattr32(&req
.n
, 1024, L2TP_ATTR_SESSION_ID
, p
->session_id
);
208 if (rtnl_talk(&genl_rth
, &req
.n
, 0, 0, NULL
) < 0)
214 static void print_cookie(char *name
, const uint8_t *cookie
, int len
)
216 printf(" %s %02x%02x%02x%02x", name
,
217 cookie
[0], cookie
[1],
218 cookie
[2], cookie
[3]);
220 printf("%02x%02x%02x%02x",
221 cookie
[4], cookie
[5],
222 cookie
[6], cookie
[7]);
225 static void print_tunnel(const struct l2tp_data
*data
)
227 const struct l2tp_parm
*p
= &data
->config
;
229 printf("Tunnel %u, encap %s\n",
231 p
->encap
== L2TP_ENCAPTYPE_UDP
? "UDP" :
232 p
->encap
== L2TP_ENCAPTYPE_IP
? "IP" : "??");
233 printf(" From %s ", inet_ntoa(p
->local_ip
));
234 printf("to %s\n", inet_ntoa(p
->peer_ip
));
235 printf(" Peer tunnel %u\n",
238 if (p
->encap
== L2TP_ENCAPTYPE_UDP
)
239 printf(" UDP source / dest ports: %hu/%hu\n",
240 p
->local_udp_port
, p
->peer_udp_port
);
243 static void print_session(struct l2tp_data
*data
)
245 struct l2tp_parm
*p
= &data
->config
;
247 printf("Session %u in tunnel %u\n",
248 p
->session_id
, p
->tunnel_id
);
249 printf(" Peer session %u, tunnel %u\n",
250 p
->peer_session_id
, p
->peer_tunnel_id
);
252 if (p
->ifname
!= NULL
) {
253 printf(" interface name: %s\n", p
->ifname
);
255 printf(" offset %u, peer offset %u\n",
256 p
->offset
, p
->peer_offset
);
257 if (p
->cookie_len
> 0)
258 print_cookie("cookie", p
->cookie
, p
->cookie_len
);
259 if (p
->peer_cookie_len
> 0)
260 print_cookie("peer cookie", p
->peer_cookie
, p
->peer_cookie_len
);
262 if (p
->reorder_timeout
!= 0) {
263 printf(" reorder timeout: %u\n", p
->reorder_timeout
);
267 static int get_response(struct nlmsghdr
*n
, void *arg
)
269 struct genlmsghdr
*ghdr
;
270 struct l2tp_data
*data
= arg
;
271 struct l2tp_parm
*p
= &data
->config
;
272 struct rtattr
*attrs
[L2TP_ATTR_MAX
+ 1];
273 struct rtattr
*nla_stats
;
276 /* Validate message and parse attributes */
277 if (n
->nlmsg_type
== NLMSG_ERROR
)
280 ghdr
= NLMSG_DATA(n
);
281 len
= n
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ghdr
));
285 parse_rtattr(attrs
, L2TP_ATTR_MAX
, (void *)ghdr
+ GENL_HDRLEN
, len
);
287 if (attrs
[L2TP_ATTR_PW_TYPE
])
288 p
->pw_type
= rta_getattr_u16(attrs
[L2TP_ATTR_PW_TYPE
]);
289 if (attrs
[L2TP_ATTR_ENCAP_TYPE
])
290 p
->encap
= rta_getattr_u16(attrs
[L2TP_ATTR_ENCAP_TYPE
]);
291 if (attrs
[L2TP_ATTR_OFFSET
])
292 p
->offset
= rta_getattr_u16(attrs
[L2TP_ATTR_OFFSET
]);
293 if (attrs
[L2TP_ATTR_DATA_SEQ
])
294 p
->data_seq
= rta_getattr_u16(attrs
[L2TP_ATTR_DATA_SEQ
]);
295 if (attrs
[L2TP_ATTR_CONN_ID
])
296 p
->tunnel_id
= rta_getattr_u32(attrs
[L2TP_ATTR_CONN_ID
]);
297 if (attrs
[L2TP_ATTR_PEER_CONN_ID
])
298 p
->peer_tunnel_id
= rta_getattr_u32(attrs
[L2TP_ATTR_PEER_CONN_ID
]);
299 if (attrs
[L2TP_ATTR_SESSION_ID
])
300 p
->session_id
= rta_getattr_u32(attrs
[L2TP_ATTR_SESSION_ID
]);
301 if (attrs
[L2TP_ATTR_PEER_SESSION_ID
])
302 p
->peer_session_id
= rta_getattr_u32(attrs
[L2TP_ATTR_PEER_SESSION_ID
]);
304 p
->udp_csum
= !!attrs
[L2TP_ATTR_UDP_CSUM
];
305 if (attrs
[L2TP_ATTR_COOKIE
])
306 memcpy(p
->cookie
, RTA_DATA(attrs
[L2TP_ATTR_COOKIE
]),
307 p
->cookie_len
= RTA_PAYLOAD(attrs
[L2TP_ATTR_COOKIE
]));
309 if (attrs
[L2TP_ATTR_PEER_COOKIE
])
310 memcpy(p
->peer_cookie
, RTA_DATA(attrs
[L2TP_ATTR_PEER_COOKIE
]),
311 p
->peer_cookie_len
= RTA_PAYLOAD(attrs
[L2TP_ATTR_PEER_COOKIE
]));
313 p
->recv_seq
= !!attrs
[L2TP_ATTR_RECV_SEQ
];
314 p
->send_seq
= !!attrs
[L2TP_ATTR_SEND_SEQ
];
316 if (attrs
[L2TP_ATTR_RECV_TIMEOUT
])
317 p
->reorder_timeout
= rta_getattr_u64(attrs
[L2TP_ATTR_RECV_TIMEOUT
]);
318 if (attrs
[L2TP_ATTR_IP_SADDR
])
319 p
->local_ip
.s_addr
= rta_getattr_u32(attrs
[L2TP_ATTR_IP_SADDR
]);
320 if (attrs
[L2TP_ATTR_IP_DADDR
])
321 p
->peer_ip
.s_addr
= rta_getattr_u32(attrs
[L2TP_ATTR_IP_DADDR
]);
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
)
376 memset(&req
, 0, sizeof(req
));
377 req
.n
.nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
378 req
.n
.nlmsg_type
= genl_family
;
379 req
.n
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
380 req
.n
.nlmsg_seq
= genl_rth
.dump
= ++genl_rth
.seq
;
382 req
.g
.cmd
= L2TP_CMD_SESSION_GET
;
383 req
.g
.version
= L2TP_GENL_VERSION
;
385 if (p
->config
.tunnel_id
&& p
->config
.session_id
) {
386 addattr32(&req
.n
, 128, L2TP_ATTR_CONN_ID
, p
->config
.tunnel_id
);
387 addattr32(&req
.n
, 128, L2TP_ATTR_SESSION_ID
, p
->config
.session_id
);
390 if (rtnl_send(&genl_rth
, &req
, req
.n
.nlmsg_len
) < 0)
393 if (rtnl_dump_filter(&genl_rth
, session_nlmsg
, p
) < 0) {
394 fprintf(stderr
, "Dump terminated\n");
401 static int tunnel_nlmsg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
, void *arg
)
403 int ret
= get_response(n
, arg
);
411 static int get_tunnel(struct l2tp_data
*p
)
419 memset(&req
, 0, sizeof(req
));
420 req
.n
.nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
421 req
.n
.nlmsg_type
= genl_family
;
422 req
.n
.nlmsg_flags
= NLM_F_ROOT
|NLM_F_MATCH
|NLM_F_REQUEST
;
423 req
.n
.nlmsg_seq
= genl_rth
.dump
= ++genl_rth
.seq
;
425 req
.g
.cmd
= L2TP_CMD_TUNNEL_GET
;
426 req
.g
.version
= L2TP_GENL_VERSION
;
428 if (p
->config
.tunnel_id
)
429 addattr32(&req
.n
, 1024, L2TP_ATTR_CONN_ID
, p
->config
.tunnel_id
);
431 if (rtnl_send(&genl_rth
, &req
, req
.n
.nlmsg_len
) < 0)
434 if (rtnl_dump_filter(&genl_rth
, tunnel_nlmsg
, p
) < 0) {
435 fprintf(stderr
, "Dump terminated\n");
442 /*****************************************************************************
444 *****************************************************************************/
446 static int hex(char ch
)
448 if ((ch
>= 'a') && (ch
<= 'f'))
449 return ch
- 'a' + 10;
450 if ((ch
>= '0') && (ch
<= '9'))
452 if ((ch
>= 'A') && (ch
<= 'F'))
453 return ch
- 'A' + 10;
457 static int hex2mem(const char *buf
, uint8_t *mem
, int count
)
462 for (i
= 0, j
= 0; i
< count
; i
++, j
+= 2) {
482 static void usage(void) __attribute__((noreturn
));
484 static void usage(void)
486 fprintf(stderr
, "Usage: ip l2tp add tunnel\n");
487 fprintf(stderr
, " remote ADDR local ADDR\n");
488 fprintf(stderr
, " tunnel_id ID peer_tunnel_id ID\n");
489 fprintf(stderr
, " [ encap { ip | udp } ]\n");
490 fprintf(stderr
, " [ udp_sport PORT ] [ udp_dport PORT ]\n");
491 fprintf(stderr
, "Usage: ip l2tp add session [ name NAME ]\n");
492 fprintf(stderr
, " tunnel_id ID\n");
493 fprintf(stderr
, " session_id ID peer_session_id ID\n");
494 fprintf(stderr
, " [ cookie HEXSTR ] [ peer_cookie HEXSTR ]\n");
495 fprintf(stderr
, " [ offset OFFSET ] [ peer_offset OFFSET ]\n");
496 fprintf(stderr
, " ip l2tp del tunnel tunnel_id ID\n");
497 fprintf(stderr
, " ip l2tp del session tunnel_id ID session_id ID\n");
498 fprintf(stderr
, " ip l2tp show tunnel [ tunnel_id ID ]\n");
499 fprintf(stderr
, " ip l2tp show session [ tunnel_id ID ] [ session_id ID ]\n");
500 fprintf(stderr
, "\n");
501 fprintf(stderr
, "Where: NAME := STRING\n");
502 fprintf(stderr
, " ADDR := { IP_ADDRESS | any }\n");
503 fprintf(stderr
, " PORT := { 0..65535 }\n");
504 fprintf(stderr
, " ID := { 1..4294967295 }\n");
505 fprintf(stderr
, " HEXSTR := { 8 or 16 hex digits (4 / 8 bytes) }\n");
509 static int parse_args(int argc
, char **argv
, int cmd
, struct l2tp_parm
*p
)
511 memset(p
, 0, sizeof(*p
));
517 if (strcmp(*argv
, "encap") == 0) {
519 if (strcmp(*argv
, "ip") == 0) {
520 p
->encap
= L2TP_ENCAPTYPE_IP
;
521 } else if (strcmp(*argv
, "udp") == 0) {
522 p
->encap
= L2TP_ENCAPTYPE_UDP
;
524 fprintf(stderr
, "Unknown tunnel encapsulation.\n");
527 } else if (strcmp(*argv
, "name") == 0) {
530 } else if (strcmp(*argv
, "remote") == 0) {
532 p
->peer_ip
.s_addr
= get_addr32(*argv
);
533 } else if (strcmp(*argv
, "local") == 0) {
535 p
->local_ip
.s_addr
= get_addr32(*argv
);
536 } else if ((strcmp(*argv
, "tunnel_id") == 0) ||
537 (strcmp(*argv
, "tid") == 0)) {
540 if (get_u32(&uval
, *argv
, 0))
541 invarg("invalid ID\n", *argv
);
543 } else if ((strcmp(*argv
, "peer_tunnel_id") == 0) ||
544 (strcmp(*argv
, "ptid") == 0)) {
547 if (get_u32(&uval
, *argv
, 0))
548 invarg("invalid ID\n", *argv
);
549 p
->peer_tunnel_id
= uval
;
550 } else if ((strcmp(*argv
, "session_id") == 0) ||
551 (strcmp(*argv
, "sid") == 0)) {
554 if (get_u32(&uval
, *argv
, 0))
555 invarg("invalid ID\n", *argv
);
556 p
->session_id
= uval
;
557 } else if ((strcmp(*argv
, "peer_session_id") == 0) ||
558 (strcmp(*argv
, "psid") == 0)) {
561 if (get_u32(&uval
, *argv
, 0))
562 invarg("invalid ID\n", *argv
);
563 p
->peer_session_id
= uval
;
564 } else if (strcmp(*argv
, "udp_sport") == 0) {
567 if (get_u16(&uval
, *argv
, 0))
568 invarg("invalid port\n", *argv
);
569 p
->local_udp_port
= uval
;
570 } else if (strcmp(*argv
, "udp_dport") == 0) {
573 if (get_u16(&uval
, *argv
, 0))
574 invarg("invalid port\n", *argv
);
575 p
->peer_udp_port
= uval
;
576 } else if (strcmp(*argv
, "offset") == 0) {
579 if (get_u8(&uval
, *argv
, 0))
580 invarg("invalid offset\n", *argv
);
582 } else if (strcmp(*argv
, "peer_offset") == 0) {
585 if (get_u8(&uval
, *argv
, 0))
586 invarg("invalid offset\n", *argv
);
587 p
->peer_offset
= uval
;
588 } else if (strcmp(*argv
, "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
->cookie_len
= slen
/ 2;
596 if (hex2mem(*argv
, p
->cookie
, p
->cookie_len
) < 0)
597 invarg("cookie must be a hex string\n", *argv
);
598 } else if (strcmp(*argv
, "peer_cookie") == 0) {
601 slen
= strlen(*argv
);
602 if ((slen
!= 8) && (slen
!= 16))
603 invarg("cookie must be either 8 or 16 hex digits\n", *argv
);
605 p
->peer_cookie_len
= slen
/ 2;
606 if (hex2mem(*argv
, p
->peer_cookie
, p
->peer_cookie_len
) < 0)
607 invarg("cookie must be a hex string\n", *argv
);
608 } else if (strcmp(*argv
, "tunnel") == 0) {
610 } else if (strcmp(*argv
, "session") == 0) {
612 } else if (matches(*argv
, "help") == 0) {
615 fprintf(stderr
, "Unknown command: %s\n", *argv
);
626 static int do_add(int argc
, char **argv
)
631 if (parse_args(argc
, argv
, L2TP_ADD
, &p
) < 0)
634 if (!p
.tunnel
&& !p
.session
)
635 missarg("tunnel or session");
637 if (p
.tunnel_id
== 0)
638 missarg("tunnel_id");
640 /* session_id and peer_session_id must be provided for sessions */
641 if ((p
.session
) && (p
.peer_session_id
== 0))
642 missarg("peer_session_id");
643 if ((p
.session
) && (p
.session_id
== 0))
644 missarg("session_id");
646 /* peer_tunnel_id is needed for tunnels */
647 if ((p
.tunnel
) && (p
.peer_tunnel_id
== 0))
648 missarg("peer_tunnel_id");
651 if (p
.local_ip
.s_addr
== 0)
654 if (p
.peer_ip
.s_addr
== 0)
657 if (p
.encap
== L2TP_ENCAPTYPE_UDP
) {
658 if (p
.local_udp_port
== 0)
659 missarg("udp_sport");
660 if (p
.peer_udp_port
== 0)
661 missarg("udp_dport");
664 ret
= create_tunnel(&p
);
668 /* Only ethernet pseudowires supported */
669 p
.pw_type
= L2TP_PWTYPE_ETH
;
671 ret
= create_session(&p
);
677 static int do_del(int argc
, char **argv
)
681 if (parse_args(argc
, argv
, L2TP_DEL
, &p
) < 0)
684 if (!p
.tunnel
&& !p
.session
)
685 missarg("tunnel or session");
687 if ((p
.tunnel
) && (p
.tunnel_id
== 0))
688 missarg("tunnel_id");
689 if ((p
.session
) && (p
.session_id
== 0))
690 missarg("session_id");
693 return delete_session(&p
);
695 return delete_tunnel(&p
);
700 static int do_show(int argc
, char **argv
)
702 struct l2tp_data data
;
703 struct l2tp_parm
*p
= &data
.config
;
705 if (parse_args(argc
, argv
, L2TP_GET
, p
) < 0)
708 if (!p
->tunnel
&& !p
->session
)
709 missarg("tunnel or session");
719 static int genl_parse_getfamily(struct nlmsghdr
*nlh
)
721 struct rtattr
*tb
[CTRL_ATTR_MAX
+ 1];
722 struct genlmsghdr
*ghdr
= NLMSG_DATA(nlh
);
723 int len
= nlh
->nlmsg_len
;
724 struct rtattr
*attrs
;
726 if (nlh
->nlmsg_type
!= GENL_ID_CTRL
) {
727 fprintf(stderr
, "Not a controller message, nlmsg_len=%d "
728 "nlmsg_type=0x%x\n", nlh
->nlmsg_len
, nlh
->nlmsg_type
);
732 if (ghdr
->cmd
!= CTRL_CMD_NEWFAMILY
) {
733 fprintf(stderr
, "Unknown controller command %d\n", ghdr
->cmd
);
737 len
-= NLMSG_LENGTH(GENL_HDRLEN
);
740 fprintf(stderr
, "wrong controller message len %d\n", len
);
744 attrs
= (struct rtattr
*) ((char *) ghdr
+ GENL_HDRLEN
);
745 parse_rtattr(tb
, CTRL_ATTR_MAX
, attrs
, len
);
747 if (tb
[CTRL_ATTR_FAMILY_ID
] == NULL
) {
748 fprintf(stderr
, "Missing family id TLV\n");
752 return rta_getattr_u16(tb
[CTRL_ATTR_FAMILY_ID
]);
755 int genl_ctrl_resolve_family(const char *family
)
763 memset(&req
, 0, sizeof(req
));
764 req
.n
.nlmsg_len
= NLMSG_LENGTH(GENL_HDRLEN
);
765 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
766 req
.n
.nlmsg_type
= GENL_ID_CTRL
;
767 req
.g
.cmd
= CTRL_CMD_GETFAMILY
;
769 addattr_l(&req
.n
, 1024, CTRL_ATTR_FAMILY_NAME
,
770 family
, strlen(family
) + 1);
772 if (rtnl_talk(&genl_rth
, &req
.n
, 0, 0, &req
.n
) < 0) {
773 fprintf(stderr
, "Error talking to the kernel\n");
777 return genl_parse_getfamily(&req
.n
);
780 int do_ipl2tp(int argc
, char **argv
)
782 if (genl_family
< 0) {
783 if (rtnl_open_byproto(&genl_rth
, 0, NETLINK_GENERIC
) < 0) {
784 fprintf(stderr
, "Cannot open generic netlink socket\n");
788 genl_family
= genl_ctrl_resolve_family(L2TP_GENL_NAME
);
796 if (matches(*argv
, "add") == 0)
797 return do_add(argc
-1, argv
+1);
798 if (matches(*argv
, "delete") == 0)
799 return do_del(argc
-1, argv
+1);
800 if (matches(*argv
, "show") == 0 ||
801 matches(*argv
, "lst") == 0 ||
802 matches(*argv
, "list") == 0)
803 return do_show(argc
-1, argv
+1);
804 if (matches(*argv
, "help") == 0)
807 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv
);