]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/blob - ip/ipl2tp.c
c5683f567568fd2d131826231aeadfe573291f25
[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         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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }