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