1 /* $NetBSD: l2tp.c,v 1.1 2017/02/16 08:28:03 knakahara Exp $ */
2
3 /*
4 * Copyright (c) 2017 Internet Initiative Japan Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: l2tp.c,v 1.1 2017/02/16 08:28:03 knakahara Exp $");
31
32 #include <sys/param.h>
33 #include <sys/ioctl.h>
34
35 #include <net/if.h>
36 #include <net/if_ether.h>
37 #include <net/if_l2tp.h>
38
39 #include <ctype.h>
40 #include <err.h>
41 #include <errno.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <util.h>
46
47 #include "env.h"
48 #include "extern.h"
49 #include "util.h"
50
51 static status_func_t status;
52 static usage_func_t usage;
53 static cmdloop_branch_t branch;
54
55 static void l2tp_constructor(void) __attribute__((constructor));
56 static void l2tp_status(prop_dictionary_t, prop_dictionary_t);
57
58 static int setl2tpsession(prop_dictionary_t, prop_dictionary_t);
59 static int deletel2tpsession(prop_dictionary_t, prop_dictionary_t);
60 static int setl2tpcookie(prop_dictionary_t, prop_dictionary_t);
61 static int deletel2tpcookie(prop_dictionary_t, prop_dictionary_t);
62
63 struct pinteger l2tpremotesession = PINTEGER_INITIALIZER1(&l2tpremotesession,
64 "remote session id", 0, UINT_MAX, 10, setl2tpsession, "l2tpremotesession",
65 &command_root.pb_parser);
66
67 struct pinteger l2tplocalsession = PINTEGER_INITIALIZER1(&l2tplocalsession,
68 "local session id", 0, UINT_MAX, 10, NULL, "l2tplocalsession",
69 &l2tpremotesession.pi_parser);
70
71 struct pinteger l2tpremotecookie = PINTEGER_INITIALIZER1(&l2tpremotecookie,
72 "remote cookie", INT64_MIN, INT64_MAX, 10, setl2tpcookie, "l2tpremotecookie",
73 &command_root.pb_parser);
74
75 struct pinteger l2tpremotecookielen = PINTEGER_INITIALIZER1(&l2tpremotecookielen,
76 "remote cookie length", 0, UINT16_MAX, 10, NULL, "l2tpremotecookielen",
77 &l2tpremotecookie.pi_parser);
78
79 struct pinteger l2tplocalcookie = PINTEGER_INITIALIZER1(&l2tplocalcookie,
80 "local cookie", INT64_MIN, INT64_MAX, 10, NULL, "l2tplocalcookie",
81 &l2tpremotecookielen.pi_parser);
82
83 struct pinteger l2tplocalcookielen = PINTEGER_INITIALIZER1(&l2tplocalcookielen,
84 "local cookie length", 0, UINT16_MAX, 10, NULL, "l2tplocalcookielen",
85 &l2tplocalcookie.pi_parser);
86
87 static const struct kwinst l2tpkw[] = {
88 {.k_word = "cookie", .k_nextparser = &l2tplocalcookielen.pi_parser}
89 ,{.k_word = "deletecookie", .k_exec = deletel2tpcookie,
90 .k_nextparser = &command_root.pb_parser}
91 ,{.k_word = "session", .k_nextparser = &l2tplocalsession.pi_parser}
92 ,{.k_word = "deletesession", .k_exec = deletel2tpsession,
93 .k_nextparser = &command_root.pb_parser}
94 };
95
96 struct pkw l2tp = PKW_INITIALIZER(&l2tp, "l2tp", NULL, NULL,
97 l2tpkw, __arraycount(l2tpkw), NULL);
98
99 #define L2TP_COOKIE_LOCAL 0
100 #define L2TP_COOKIE_REMOTE 1
101
102 static int
checkifname(prop_dictionary_t env)103 checkifname(prop_dictionary_t env)
104 {
105 const char *ifname;
106
107 if ((ifname = getifname(env)) == NULL)
108 return 1;
109
110 return strncmp(ifname, "l2tp", 4) != 0 ||
111 !isdigit((unsigned char)ifname[4]);
112 }
113
114 static int
getl2tp(prop_dictionary_t env,struct l2tp_req * l2tpr,bool quiet)115 getl2tp(prop_dictionary_t env, struct l2tp_req *l2tpr, bool quiet)
116 {
117 memset(l2tpr, 0, sizeof(*l2tpr));
118
119 if (checkifname(env)) {
120 if (quiet)
121 return -1;
122 errx(EXIT_FAILURE, "valid only with l2tp(4) interfaces");
123 }
124
125 if (indirect_ioctl(env, SIOCGL2TP, l2tpr) == -1)
126 return -1;
127
128 return 0;
129 }
130
131 int
deletel2tpsession(prop_dictionary_t env,prop_dictionary_t oenv)132 deletel2tpsession(prop_dictionary_t env, prop_dictionary_t oenv)
133 {
134 struct l2tp_req l2tpr;
135
136 memset(&l2tpr, 0, sizeof(l2tpr));
137
138 if (indirect_ioctl(env, SIOCDL2TPSESSION, &l2tpr) == -1)
139 return -1;
140
141 l2tpr.state = L2TP_STATE_DOWN;
142
143 if (indirect_ioctl(env, SIOCSL2TPSTATE, &l2tpr) == -1)
144 return -1;
145
146
147 return 0;
148 }
149
150 int
setl2tpsession(prop_dictionary_t env,prop_dictionary_t oenv)151 setl2tpsession(prop_dictionary_t env, prop_dictionary_t oenv)
152 {
153 struct l2tp_req l2tpr;
154 int64_t local_session;
155 int64_t remote_session;
156
157 memset(&l2tpr, 0, sizeof(l2tpr));
158
159 if (!prop_dictionary_get_int64(env, "l2tplocalsession",
160 &local_session)) {
161 errno = ENOENT;
162 return -1;
163 }
164
165 if (!prop_dictionary_get_int64(env, "l2tpremotesession",
166 &remote_session)) {
167 errno = ENOENT;
168 return -1;
169 }
170
171 l2tpr.my_sess_id = local_session;
172 l2tpr.peer_sess_id = remote_session;
173
174 if (indirect_ioctl(env, SIOCSL2TPSESSION, &l2tpr) == -1)
175 return -1;
176
177 l2tpr.state = L2TP_STATE_UP;
178
179 if (indirect_ioctl(env, SIOCSL2TPSTATE, &l2tpr) == -1)
180 return -1;
181
182 return 0;
183 }
184
185 int
deletel2tpcookie(prop_dictionary_t env,prop_dictionary_t oenv)186 deletel2tpcookie(prop_dictionary_t env, prop_dictionary_t oenv)
187 {
188 struct l2tp_req l2tpr;
189
190 memset(&l2tpr, 0, sizeof(l2tpr));
191
192 if (indirect_ioctl(env, SIOCDL2TPCOOKIE, &l2tpr) == -1)
193 return -1;
194
195 return 0;
196 }
197
198 int
setl2tpcookie(prop_dictionary_t env,prop_dictionary_t oenv)199 setl2tpcookie(prop_dictionary_t env, prop_dictionary_t oenv)
200 {
201 struct l2tp_req l2tpr;
202 uint16_t cookielen;
203 uint64_t cookie;
204
205 memset(&l2tpr, 0, sizeof(l2tpr));
206
207 if (!prop_dictionary_get_uint16(env, "l2tplocalcookielen", &cookielen)) {
208 errno = ENOENT;
209 return -1;
210 }
211 if (!prop_dictionary_get_uint64(env, "l2tplocalcookie", &cookie)) {
212 errno = ENOENT;
213 return -1;
214 }
215 l2tpr.my_cookie_len = cookielen;
216 l2tpr.my_cookie = cookie;
217
218 if (!prop_dictionary_get_uint16(env, "l2tpremotecookielen", &cookielen)) {
219 errno = ENOENT;
220 return -1;
221 }
222 if (!prop_dictionary_get_uint64(env, "l2tpremotecookie", &cookie)) {
223 errno = ENOENT;
224 return -1;
225 }
226 l2tpr.peer_cookie_len = cookielen;
227 l2tpr.peer_cookie = cookie;
228
229 if (indirect_ioctl(env, SIOCSL2TPCOOKIE, &l2tpr) == -1)
230 return -1;
231
232 return 0;
233 }
234
235 static void
l2tp_status(prop_dictionary_t env,prop_dictionary_t oenv)236 l2tp_status(prop_dictionary_t env, prop_dictionary_t oenv)
237 {
238 struct l2tp_req l2tpr;
239
240 if (getl2tp(env, &l2tpr, true) == -1)
241 return;
242
243 if (l2tpr.my_sess_id != 0 || l2tpr.peer_sess_id != 0) {
244 printf("\tlocal-session-id: %u\n", l2tpr.my_sess_id);
245 printf("\tremote-session-id: %u\n", l2tpr.peer_sess_id);
246 }
247
248 if (l2tpr.my_cookie != 0 || l2tpr.peer_cookie != 0) {
249 printf("\tlocal-cookie: %" PRIu64 "\n", l2tpr.my_cookie);
250 printf("\tremote-cookie: %" PRIu64 "\n", l2tpr.peer_cookie);
251 }
252 }
253
254 static void
l2tp_usage(prop_dictionary_t env)255 l2tp_usage(prop_dictionary_t env)
256 {
257 fprintf(stderr, "\t[ session local-session-id remote-session-id ]\n");
258 fprintf(stderr, "\t[ cookie local-cookie-length local-cookie remote-cookie-length remote-cookie ]\n");
259 }
260
261 static void
l2tp_constructor(void)262 l2tp_constructor(void)
263 {
264 cmdloop_branch_init(&branch, &l2tp.pk_parser);
265 register_cmdloop_branch(&branch);
266 status_func_init(&status, l2tp_status);
267 usage_func_init(&usage, l2tp_usage);
268 register_status(&status);
269 register_usage(&usage);
270 }
271