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