]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/blob - ip/ipl2tp.c
iproute2: allow IPv6 addresses for l2tp local and remote parameters
[lisovros/iproute2_canprio.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
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         inet_prefix local_ip;
54         inet_prefix 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
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         uint32_t local_attr = L2TP_ATTR_IP_SADDR;
101         uint32_t peer_attr = L2TP_ATTR_IP_DADDR;
102
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;
109
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);
114
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);
118
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);
122
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);
126         }
127
128         if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
129                 return -2;
130
131         return 0;
132 }
133
134 static int delete_tunnel(struct l2tp_parm *p)
135 {
136         struct {
137                 struct nlmsghdr         n;
138                 struct genlmsghdr       g;
139                 char                    buf[128];
140         } req;
141
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;
148
149         addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id);
150
151         if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
152                 return -2;
153
154         return 0;
155 }
156
157 static int create_session(struct l2tp_parm *p)
158 {
159         struct {
160                 struct nlmsghdr         n;
161                 struct genlmsghdr       g;
162                 char                    buf[1024];
163         } req;
164
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;
171
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);
177
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,
184                                           p->reorder_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);
192
193         if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0)
194                 return -2;
195
196         return 0;
197 }
198
199 static int delete_session(struct l2tp_parm *p)
200 {
201         struct {
202                 struct nlmsghdr         n;
203                 struct genlmsghdr       g;
204                 char                    buf[128];
205         } req;
206
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;
213
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)
217                 return -2;
218
219         return 0;
220 }
221
222 static void print_cookie(char *name, const uint8_t *cookie, int len)
223 {
224         printf("  %s %02x%02x%02x%02x", name,
225                cookie[0], cookie[1],
226                cookie[2], cookie[3]);
227         if (len == 8)
228                 printf("%02x%02x%02x%02x",
229                        cookie[4], cookie[5],
230                        cookie[6], cookie[7]);
231 }
232
233 static void print_tunnel(const struct l2tp_data *data)
234 {
235         const struct l2tp_parm *p = &data->config;
236         char buf[INET6_ADDRSTRLEN];
237
238         printf("Tunnel %u, encap %s\n",
239                p->tunnel_id,
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",
245                p->peer_tunnel_id);
246
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);
250 }
251
252 static void print_session(struct l2tp_data *data)
253 {
254         struct l2tp_parm *p = &data->config;
255
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);
260
261         if (p->ifname != NULL) {
262                 printf("  interface name: %s\n", p->ifname);
263         }
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);
270
271         if (p->reorder_timeout != 0) {
272                 printf("  reorder timeout: %u\n", p->reorder_timeout);
273         }
274 }
275
276 static int get_response(struct nlmsghdr *n, void *arg)
277 {
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;
283         int len;
284
285         /* Validate message and parse attributes */
286         if (n->nlmsg_type == NLMSG_ERROR)
287                 return -EBADMSG;
288
289         ghdr = NLMSG_DATA(n);
290         len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ghdr));
291         if (len < 0)
292                 return -1;
293
294         parse_rtattr(attrs, L2TP_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
295
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]);
312
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]));
317
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]));
321
322         p->recv_seq = !!attrs[L2TP_ATTR_RECV_SEQ];
323         p->send_seq = !!attrs[L2TP_ATTR_SEND_SEQ];
324
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;
332         }
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;
338         }
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;
344         }
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;
350         }
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]);
359
360         nla_stats = attrs[L2TP_ATTR_STATS];
361         if (nla_stats) {
362                 struct rtattr *tb[L2TP_ATTR_STATS_MAX + 1];
363
364                 parse_rtattr_nested(tb, L2TP_ATTR_STATS_MAX, nla_stats);
365
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]);
382         }
383
384         return 0;
385 }
386
387 static int session_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
388 {
389         int ret = get_response(n, arg);
390
391         if (ret == 0)
392                 print_session(arg);
393
394         return ret;
395 }
396
397 static int get_session(struct l2tp_data *p)
398 {
399         struct {
400                 struct nlmsghdr         n;
401                 struct genlmsghdr       g;
402                 char buf[128];
403         } req;
404
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;
410
411         req.g.cmd = L2TP_CMD_SESSION_GET;
412         req.g.version = L2TP_GENL_VERSION;
413
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);
417         }
418
419         if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
420                 return -2;
421
422         if (rtnl_dump_filter(&genl_rth, session_nlmsg, p) < 0) {
423                 fprintf(stderr, "Dump terminated\n");
424                 exit(1);
425         }
426
427         return 0;
428 }
429
430 static int tunnel_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
431 {
432         int ret = get_response(n, arg);
433
434         if (ret == 0)
435                 print_tunnel(arg);
436
437         return ret;
438 }
439
440 static int get_tunnel(struct l2tp_data *p)
441 {
442         struct {
443                 struct nlmsghdr         n;
444                 struct genlmsghdr       g;
445                 char buf[1024];
446         } req;
447
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;
453
454         req.g.cmd = L2TP_CMD_TUNNEL_GET;
455         req.g.version = L2TP_GENL_VERSION;
456
457         if (p->config.tunnel_id)
458                 addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
459
460         if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
461                 return -2;
462
463         if (rtnl_dump_filter(&genl_rth, tunnel_nlmsg, p) < 0) {
464                 fprintf(stderr, "Dump terminated\n");
465                 exit(1);
466         }
467
468         return 0;
469 }
470
471 /*****************************************************************************
472  * Command parser
473  *****************************************************************************/
474
475 static int hex(char ch)
476 {
477         if ((ch >= 'a') && (ch <= 'f'))
478                 return ch - 'a' + 10;
479         if ((ch >= '0') && (ch <= '9'))
480                 return ch - '0';
481         if ((ch >= 'A') && (ch <= 'F'))
482                 return ch - 'A' + 10;
483         return -1;
484 }
485
486 static int hex2mem(const char *buf, uint8_t *mem, int count)
487 {
488         int i, j;
489         int c;
490
491         for (i = 0, j = 0; i < count; i++, j += 2) {
492                 c = hex(buf[j]);
493                 if (c < 0)
494                         goto err;
495
496                 mem[i] = c << 4;
497
498                 c = hex(buf[j + 1]);
499                 if (c < 0)
500                         goto err;
501
502                 mem[i] |= c;
503         }
504
505         return 0;
506
507 err:
508         return -1;
509 }
510
511 static void usage(void) __attribute__((noreturn));
512
513 static void usage(void)
514 {
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");
535         exit(-1);
536 }
537
538 static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
539 {
540         memset(p, 0, sizeof(*p));
541
542         if (argc == 0)
543                 usage();
544
545         while (argc > 0) {
546                 if (strcmp(*argv, "encap") == 0) {
547                         NEXT_ARG();
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;
552                         } else {
553                                 fprintf(stderr, "Unknown tunnel encapsulation.\n");
554                                 exit(-1);
555                         }
556                 } else if (strcmp(*argv, "name") == 0) {
557                         NEXT_ARG();
558                         p->ifname = *argv;
559                 } else if (strcmp(*argv, "remote") == 0) {
560                         NEXT_ARG();
561                         if (get_addr(&p->peer_ip, *argv, AF_UNSPEC))
562                                 invarg("invalid remote address\n", *argv);
563                 } else if (strcmp(*argv, "local") == 0) {
564                         NEXT_ARG();
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)) {
569                         __u32 uval;
570                         NEXT_ARG();
571                         if (get_u32(&uval, *argv, 0))
572                                 invarg("invalid ID\n", *argv);
573                         p->tunnel_id = uval;
574                 } else if ((strcmp(*argv, "peer_tunnel_id") == 0) ||
575                            (strcmp(*argv, "ptid") == 0)) {
576                         __u32 uval;
577                         NEXT_ARG();
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)) {
583                         __u32 uval;
584                         NEXT_ARG();
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)) {
590                         __u32 uval;
591                         NEXT_ARG();
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) {
596                         __u16 uval;
597                         NEXT_ARG();
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) {
602                         __u16 uval;
603                         NEXT_ARG();
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) {
608                         __u8 uval;
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                         NEXT_ARG();
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) {
620                         int slen;
621                         NEXT_ARG();
622                         slen = strlen(*argv);
623                         if ((slen != 8) && (slen != 16))
624                                 invarg("cookie must be either 8 or 16 hex digits\n", *argv);
625
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) {
630                         int slen;
631                         NEXT_ARG();
632                         slen = strlen(*argv);
633                         if ((slen != 8) && (slen != 16))
634                                 invarg("cookie must be either 8 or 16 hex digits\n", *argv);
635
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) {
640                         p->tunnel = 1;
641                 } else if (strcmp(*argv, "session") == 0) {
642                         p->session = 1;
643                 } else if (matches(*argv, "help") == 0) {
644                         usage();
645                 } else {
646                         fprintf(stderr, "Unknown command: %s\n", *argv);
647                         usage();
648                 }
649
650                 argc--; argv++;
651         }
652
653         return 0;
654 }
655
656
657 static int do_add(int argc, char **argv)
658 {
659         struct l2tp_parm p;
660         int ret = 0;
661
662         if (parse_args(argc, argv, L2TP_ADD, &p) < 0)
663                 return -1;
664
665         if (!p.tunnel && !p.session)
666                 missarg("tunnel or session");
667
668         if (p.tunnel_id == 0)
669                 missarg("tunnel_id");
670
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");
676
677         /* peer_tunnel_id is needed for tunnels */
678         if ((p.tunnel) && (p.peer_tunnel_id == 0))
679                 missarg("peer_tunnel_id");
680
681         if (p.tunnel) {
682                 if (p.local_ip.family == AF_UNSPEC)
683                         missarg("local");
684
685                 if (p.peer_ip.family == AF_UNSPEC)
686                         missarg("remote");
687
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");
693                 }
694
695                 ret = create_tunnel(&p);
696         }
697
698         if (p.session) {
699                 /* Only ethernet pseudowires supported */
700                 p.pw_type = L2TP_PWTYPE_ETH;
701
702                 ret = create_session(&p);
703         }
704
705         return ret;
706 }
707
708 static int do_del(int argc, char **argv)
709 {
710         struct l2tp_parm p;
711
712         if (parse_args(argc, argv, L2TP_DEL, &p) < 0)
713                 return -1;
714
715         if (!p.tunnel && !p.session)
716                 missarg("tunnel or session");
717
718         if ((p.tunnel) && (p.tunnel_id == 0))
719                 missarg("tunnel_id");
720         if ((p.session) && (p.session_id == 0))
721                 missarg("session_id");
722
723         if (p.session_id)
724                 return delete_session(&p);
725         else
726                 return delete_tunnel(&p);
727
728         return -1;
729 }
730
731 static int do_show(int argc, char **argv)
732 {
733         struct l2tp_data data;
734         struct l2tp_parm *p = &data.config;
735
736         if (parse_args(argc, argv, L2TP_GET, p) < 0)
737                 return -1;
738
739         if (!p->tunnel && !p->session)
740                 missarg("tunnel or session");
741
742         if (p->session)
743                 get_session(&data);
744         else
745                 get_tunnel(&data);
746
747         return 0;
748 }
749
750 static int genl_parse_getfamily(struct nlmsghdr *nlh)
751 {
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;
756
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);
760                 return -1;
761         }
762
763         if (ghdr->cmd != CTRL_CMD_NEWFAMILY) {
764                 fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd);
765                 return -1;
766         }
767
768         len -= NLMSG_LENGTH(GENL_HDRLEN);
769
770         if (len < 0) {
771                 fprintf(stderr, "wrong controller message len %d\n", len);
772                 return -1;
773         }
774
775         attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
776         parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
777
778         if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
779                 fprintf(stderr, "Missing family id TLV\n");
780                 return -1;
781         }
782
783         return rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
784 }
785
786 int genl_ctrl_resolve_family(const char *family)
787 {
788         struct {
789                 struct nlmsghdr         n;
790                 struct genlmsghdr       g;
791                 char                    buf[1024];
792         } req;
793
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;
799
800         addattr_l(&req.n, 1024, CTRL_ATTR_FAMILY_NAME,
801                   family, strlen(family) + 1);
802
803         if (rtnl_talk(&genl_rth, &req.n, 0, 0, &req.n) < 0) {
804                 fprintf(stderr, "Error talking to the kernel\n");
805                 return -2;
806         }
807
808         return genl_parse_getfamily(&req.n);
809 }
810
811 int do_ipl2tp(int argc, char **argv)
812 {
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");
816                         exit(1);
817                 }
818
819                 genl_family = genl_ctrl_resolve_family(L2TP_GENL_NAME);
820                 if (genl_family < 0)
821                         exit(1);
822         }
823
824         if (argc < 1)
825                 usage();
826
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)
836                 usage();
837
838         fprintf(stderr, "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv);
839         exit(-1);
840 }