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
29 #include "utils.h"
30 #include "ip_common.h"
31
32 enum {
33 L2TP_ADD,
34 L2TP_CHG,
35 L2TP_DEL,
36 L2TP_GET
37 };
38
39 struct l2tp_parm {
40 uint32_t tunnel_id;
41 uint32_t peer_tunnel_id;
42 uint32_t session_id;
43 uint32_t peer_session_id;
44 uint32_t offset;
45 uint32_t peer_offset;
46 enum l2tp_encap_type encap;
47 uint16_t local_udp_port;
48 uint16_t peer_udp_port;
49 int cookie_len;
50 uint8_t cookie[8];
51 int peer_cookie_len;
52 uint8_t peer_cookie[8];
53 struct in_addr local_ip;
54 struct in_addr peer_ip;
55
56 uint16_t pw_type;
57 uint16_t mtu;
58 int udp_csum:1;
59 int recv_seq:1;
60 int send_seq:1;
61 int lns_mode:1;
62 int data_seq:2;
63 int tunnel:1;
64 int session:1;
65 int reorder_timeout;
66 const char *ifname;
67 };
68
69 struct l2tp_stats {
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;
78 };
79
80 struct l2tp_data {
81 struct l2tp_parm config;
82 struct l2tp_stats stats;
83 };
84
85 /* netlink socket */
86 static struct rtnl_handle genl_rth;
87 static int genl_family = -1;
88
89 /*****************************************************************************
90 * Netlink actions
91 *****************************************************************************/
92
create_tunnel(struct l2tp_parm * p)93 static int create_tunnel(struct l2tp_parm *p)
94 {
95 struct {
96 struct nlmsghdr n;
97 struct genlmsghdr g;
98 char buf[1024];
99 } req;
100
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;
107
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);
112
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);
118 }
119
120 if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
121 return -2;
122
123 return 0;
124 }
125
delete_tunnel(struct l2tp_parm * p)126 static int delete_tunnel(struct l2tp_parm *p)
127 {
128 struct {
129 struct nlmsghdr n;
130 struct genlmsghdr g;
131 char buf[128];
132 } req;
133
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;
140
141 addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id);
142
143 if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
144 return -2;
145
146 return 0;
147 }
148
create_session(struct l2tp_parm * p)149 static int create_session(struct l2tp_parm *p)
150 {
151 struct {
152 struct nlmsghdr n;
153 struct genlmsghdr g;
154 char buf[1024];
155 } req;
156
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;
163
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);
169
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,
176 p->reorder_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);
184
185 if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
186 return -2;
187
188 return 0;
189 }
190
delete_session(struct l2tp_parm * p)191 static int delete_session(struct l2tp_parm *p)
192 {
193 struct {
194 struct nlmsghdr n;
195 struct genlmsghdr g;
196 char buf[128];
197 } req;
198
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;
205
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)
209 return -2;
210
211 return 0;
212 }
213
print_cookie(char * name,const uint8_t * cookie,int len)214 static void print_cookie(char *name, const uint8_t *cookie, int len)
215 {
216 printf(" %s %02x%02x%02x%02x", name,
217 cookie[0], cookie[1],
218 cookie[2], cookie[3]);
219 if (len == 8)
220 printf("%02x%02x%02x%02x",
221 cookie[4], cookie[5],
222 cookie[6], cookie[7]);
223 }
224
print_tunnel(const struct l2tp_data * data)225 static void print_tunnel(const struct l2tp_data *data)
226 {
227 const struct l2tp_parm *p = &data->config;
228
229 printf("Tunnel %u, encap %s\n",
230 p->tunnel_id,
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",
236 p->peer_tunnel_id);
237
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);
241 }
242
print_session(struct l2tp_data * data)243 static void print_session(struct l2tp_data *data)
244 {
245 struct l2tp_parm *p = &data->config;
246
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);
251
252 if (p->ifname != NULL) {
253 printf(" interface name: %s\n", p->ifname);
254 }
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);
261
262 if (p->reorder_timeout != 0) {
263 printf(" reorder timeout: %u\n", p->reorder_timeout);
264 }
265 }
266
get_response(struct nlmsghdr * n,void * arg)267 static int get_response(struct nlmsghdr *n, void *arg)
268 {
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;
274 int len;
275
276 /* Validate message and parse attributes */
277 if (n->nlmsg_type == NLMSG_ERROR)
278 return -EBADMSG;
279
280 ghdr = NLMSG_DATA(n);
281 len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ghdr));
282 if (len < 0)
283 return -1;
284
285 parse_rtattr(attrs, L2TP_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
286
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]);
303
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]));
308
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]));
312
313 p->recv_seq = !!attrs[L2TP_ATTR_RECV_SEQ];
314 p->send_seq = !!attrs[L2TP_ATTR_SEND_SEQ];
315
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]);
330
331 nla_stats = attrs[L2TP_ATTR_STATS];
332 if (nla_stats) {
333 struct rtattr *tb[L2TP_ATTR_STATS_MAX + 1];
334
335 parse_rtattr_nested(tb, L2TP_ATTR_STATS_MAX, nla_stats);
336
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]);
353 }
354
355 return 0;
356 }
357
session_nlmsg(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)358 static int session_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
359 {
360 int ret = get_response(n, arg);
361
362 if (ret == 0)
363 print_session(arg);
364
365 return ret;
366 }
367
get_session(struct l2tp_data * p)368 static int get_session(struct l2tp_data *p)
369 {
370 struct {
371 struct nlmsghdr n;
372 struct genlmsghdr g;
373 char buf[128];
374 } req;
375
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;
381
382 req.g.cmd = L2TP_CMD_SESSION_GET;
383 req.g.version = L2TP_GENL_VERSION;
384
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);
388 }
389
390 if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
391 return -2;
392
393 if (rtnl_dump_filter(&genl_rth, session_nlmsg, p) < 0) {
394 fprintf(stderr, "Dump terminated\n");
395 exit(1);
396 }
397
398 return 0;
399 }
400
tunnel_nlmsg(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)401 static int tunnel_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
402 {
403 int ret = get_response(n, arg);
404
405 if (ret == 0)
406 print_tunnel(arg);
407
408 return ret;
409 }
410
get_tunnel(struct l2tp_data * p)411 static int get_tunnel(struct l2tp_data *p)
412 {
413 struct {
414 struct nlmsghdr n;
415 struct genlmsghdr g;
416 char buf[1024];
417 } req;
418
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;
424
425 req.g.cmd = L2TP_CMD_TUNNEL_GET;
426 req.g.version = L2TP_GENL_VERSION;
427
428 if (p->config.tunnel_id)
429 addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
430
431 if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
432 return -2;
433
434 if (rtnl_dump_filter(&genl_rth, tunnel_nlmsg, p) < 0) {
435 fprintf(stderr, "Dump terminated\n");
436 exit(1);
437 }
438
439 return 0;
440 }
441
442 /*****************************************************************************
443 * Command parser
444 *****************************************************************************/
445
hex(char ch)446 static int hex(char ch)
447 {
448 if ((ch >= 'a') && (ch <= 'f'))
449 return ch - 'a' + 10;
450 if ((ch >= '0') && (ch <= '9'))
451 return ch - '0';
452 if ((ch >= 'A') && (ch <= 'F'))
453 return ch - 'A' + 10;
454 return -1;
455 }
456
hex2mem(const char * buf,uint8_t * mem,int count)457 static int hex2mem(const char *buf, uint8_t *mem, int count)
458 {
459 int i, j;
460 int c;
461
462 for (i = 0, j = 0; i < count; i++, j += 2) {
463 c = hex(buf[j]);
464 if (c < 0)
465 goto err;
466
467 mem[i] = c << 4;
468
469 c = hex(buf[j + 1]);
470 if (c < 0)
471 goto err;
472
473 mem[i] |= c;
474 }
475
476 return 0;
477
478 err:
479 return -1;
480 }
481
482 static void usage(void) __attribute__((noreturn));
483
usage(void)484 static void usage(void)
485 {
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");
506 exit(-1);
507 }
508
parse_args(int argc,char ** argv,int cmd,struct l2tp_parm * p)509 static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
510 {
511 memset(p, 0, sizeof(*p));
512
513 if (argc == 0)
514 usage();
515
516 while (argc > 0) {
517 if (strcmp(*argv, "encap") == 0) {
518 NEXT_ARG();
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;
523 } else {
524 fprintf(stderr, "Unknown tunnel encapsulation.\n");
525 exit(-1);
526 }
527 } else if (strcmp(*argv, "name") == 0) {
528 NEXT_ARG();
529 p->ifname = *argv;
530 } else if (strcmp(*argv, "remote") == 0) {
531 NEXT_ARG();
532 p->peer_ip.s_addr = get_addr32(*argv);
533 } else if (strcmp(*argv, "local") == 0) {
534 NEXT_ARG();
535 p->local_ip.s_addr = get_addr32(*argv);
536 } else if ((strcmp(*argv, "tunnel_id") == 0) ||
537 (strcmp(*argv, "tid") == 0)) {
538 __u32 uval;
539 NEXT_ARG();
540 if (get_u32(&uval, *argv, 0))
541 invarg("invalid ID\n", *argv);
542 p->tunnel_id = uval;
543 } else if ((strcmp(*argv, "peer_tunnel_id") == 0) ||
544 (strcmp(*argv, "ptid") == 0)) {
545 __u32 uval;
546 NEXT_ARG();
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)) {
552 __u32 uval;
553 NEXT_ARG();
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)) {
559 __u32 uval;
560 NEXT_ARG();
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) {
565 __u16 uval;
566 NEXT_ARG();
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) {
571 __u16 uval;
572 NEXT_ARG();
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) {
577 __u8 uval;
578 NEXT_ARG();
579 if (get_u8(&uval, *argv, 0))
580 invarg("invalid offset\n", *argv);
581 p->offset = uval;
582 } else if (strcmp(*argv, "peer_offset") == 0) {
583 __u8 uval;
584 NEXT_ARG();
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) {
589 int slen;
590 NEXT_ARG();
591 slen = strlen(*argv);
592 if ((slen != 8) && (slen != 16))
593 invarg("cookie must be either 8 or 16 hex digits\n", *argv);
594
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) {
599 int slen;
600 NEXT_ARG();
601 slen = strlen(*argv);
602 if ((slen != 8) && (slen != 16))
603 invarg("cookie must be either 8 or 16 hex digits\n", *argv);
604
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) {
609 p->tunnel = 1;
610 } else if (strcmp(*argv, "session") == 0) {
611 p->session = 1;
612 } else if (matches(*argv, "help") == 0) {
613 usage();
614 } else {
615 fprintf(stderr, "Unknown command: %s\n", *argv);
616 usage();
617 }
618
619 argc--; argv++;
620 }
621
622 return 0;
623 }
624
625
do_add(int argc,char ** argv)626 static int do_add(int argc, char **argv)
627 {
628 struct l2tp_parm p;
629 int ret = 0;
630
631 if (parse_args(argc, argv, L2TP_ADD, &p) < 0)
632 return -1;
633
634 if (!p.tunnel && !p.session)
635 missarg("tunnel or session");
636
637 if (p.tunnel_id == 0)
638 missarg("tunnel_id");
639
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");
645
646 /* peer_tunnel_id is needed for tunnels */
647 if ((p.tunnel) && (p.peer_tunnel_id == 0))
648 missarg("peer_tunnel_id");
649
650 if (p.tunnel) {
651 if (p.local_ip.s_addr == 0)
652 missarg("local");
653
654 if (p.peer_ip.s_addr == 0)
655 missarg("remote");
656
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");
662 }
663
664 ret = create_tunnel(&p);
665 }
666
667 if (p.session) {
668 /* Only ethernet pseudowires supported */
669 p.pw_type = L2TP_PWTYPE_ETH;
670
671 ret = create_session(&p);
672 }
673
674 return ret;
675 }
676
do_del(int argc,char ** argv)677 static int do_del(int argc, char **argv)
678 {
679 struct l2tp_parm p;
680
681 if (parse_args(argc, argv, L2TP_DEL, &p) < 0)
682 return -1;
683
684 if (!p.tunnel && !p.session)
685 missarg("tunnel or session");
686
687 if ((p.tunnel) && (p.tunnel_id == 0))
688 missarg("tunnel_id");
689 if ((p.session) && (p.session_id == 0))
690 missarg("session_id");
691
692 if (p.session_id)
693 return delete_session(&p);
694 else
695 return delete_tunnel(&p);
696
697 return -1;
698 }
699
do_show(int argc,char ** argv)700 static int do_show(int argc, char **argv)
701 {
702 struct l2tp_data data;
703 struct l2tp_parm *p = &data.config;
704
705 if (parse_args(argc, argv, L2TP_GET, p) < 0)
706 return -1;
707
708 if (!p->tunnel && !p->session)
709 missarg("tunnel or session");
710
711 if (p->session)
712 get_session(&data);
713 else
714 get_tunnel(&data);
715
716 return 0;
717 }
718
genl_parse_getfamily(struct nlmsghdr * nlh)719 static int genl_parse_getfamily(struct nlmsghdr *nlh)
720 {
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;
725
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);
729 return -1;
730 }
731
732 if (ghdr->cmd != CTRL_CMD_NEWFAMILY) {
733 fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd);
734 return -1;
735 }
736
737 len -= NLMSG_LENGTH(GENL_HDRLEN);
738
739 if (len < 0) {
740 fprintf(stderr, "wrong controller message len %d\n", len);
741 return -1;
742 }
743
744 attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
745 parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
746
747 if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
748 fprintf(stderr, "Missing family id TLV\n");
749 return -1;
750 }
751
752 return rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
753 }
754
genl_ctrl_resolve_family(const char * family)755 int genl_ctrl_resolve_family(const char *family)
756 {
757 struct {
758 struct nlmsghdr n;
759 struct genlmsghdr g;
760 char buf[1024];
761 } req;
762
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;
768
769 addattr_l(&req.n, 1024, CTRL_ATTR_FAMILY_NAME,
770 family, strlen(family) + 1);
771
772 if (rtnl_talk(&genl_rth, &req.n, 0, 0, &req.n) < 0) {
773 fprintf(stderr, "Error talking to the kernel\n");
774 return -2;
775 }
776
777 return genl_parse_getfamily(&req.n);
778 }
779
do_ipl2tp(int argc,char ** argv)780 int do_ipl2tp(int argc, char **argv)
781 {
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");
785 exit(1);
786 }
787
788 genl_family = genl_ctrl_resolve_family(L2TP_GENL_NAME);
789 if (genl_family < 0)
790 exit(1);
791 }
792
793 if (argc < 1)
794 usage();
795
796 if (matches(*argv, "add") == 0)
797 return do_add(argc-1, argv+1);
798 if (matches(*argv, "del") == 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)
805 usage();
806
807 fprintf(stderr, "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv);
808 exit(-1);
809 }
810