1 /* $NetBSD: mpls_proto.c,v 1.29 2015/08/24 22:21:27 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Mihai Chelaru <kefren@NetBSD.org>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: mpls_proto.c,v 1.29 2015/08/24 22:21:27 pooka Exp $");
34
35 #ifdef _KERNEL_OPT
36 #include "opt_inet.h"
37 #include "opt_mbuftrace.h"
38 #endif
39
40 #include <sys/param.h>
41 #include <sys/socket.h>
42 #include <sys/protosw.h>
43 #include <sys/domain.h>
44 #include <sys/socketvar.h>
45 #include <sys/sysctl.h>
46
47 #include <net/route.h>
48
49 #include <netmpls/mpls.h>
50 #include <netmpls/mpls_var.h>
51
52 struct ifqueue mplsintrq;
53
54 static int mpls_attach(struct socket *, int);
55 static void sysctl_net_mpls_setup(struct sysctllog **);
56
57 #ifdef MBUFTRACE
58 struct mowner mpls_owner = MOWNER_INIT("MPLS", "");
59 #endif
60
61 int mpls_defttl = 255;
62 int mpls_mapttl_inet = 1;
63 int mpls_mapttl_inet6 = 1;
64 int mpls_icmp_respond = 0;
65 int mpls_forwarding = 0;
66 int mpls_frame_accept = 0;
67 int mpls_mapprec_inet = 1;
68 int mpls_mapclass_inet6 = 1;
69 int mpls_rfc4182 = 1;
70
mpls_init(void)71 void mpls_init(void)
72 {
73 #ifdef MBUFTRACE
74 MOWNER_ATTACH(&mpls_owner);
75 #endif
76 memset(&mplsintrq, 0, sizeof(mplsintrq));
77 mplsintrq.ifq_maxlen = 256;
78
79 sysctl_net_mpls_setup(NULL);
80 }
81
82 static int
mpls_attach(struct socket * so,int proto)83 mpls_attach(struct socket *so, int proto)
84 {
85 int error = EOPNOTSUPP;
86
87 sosetlock(so);
88 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
89 error = soreserve(so, 8192, 8192);
90 }
91 return error;
92 }
93
94 static void
mpls_detach(struct socket * so)95 mpls_detach(struct socket *so)
96 {
97 }
98
99 static int
mpls_accept(struct socket * so,struct sockaddr * nam)100 mpls_accept(struct socket *so, struct sockaddr *nam)
101 {
102 KASSERT(solocked(so));
103
104 return EOPNOTSUPP;
105 }
106
107 static int
mpls_bind(struct socket * so,struct sockaddr * nam,struct lwp * l)108 mpls_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
109 {
110 KASSERT(solocked(so));
111
112 return EOPNOTSUPP;
113 }
114
115 static int
mpls_listen(struct socket * so,struct lwp * l)116 mpls_listen(struct socket *so, struct lwp *l)
117 {
118 KASSERT(solocked(so));
119
120 return EOPNOTSUPP;
121 }
122
123 static int
mpls_connect(struct socket * so,struct sockaddr * nam,struct lwp * l)124 mpls_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
125 {
126 KASSERT(solocked(so));
127
128 return EOPNOTSUPP;
129 }
130
131 static int
mpls_connect2(struct socket * so,struct socket * so2)132 mpls_connect2(struct socket *so, struct socket *so2)
133 {
134 KASSERT(solocked(so));
135
136 return EOPNOTSUPP;
137 }
138
139 static int
mpls_disconnect(struct socket * so)140 mpls_disconnect(struct socket *so)
141 {
142 KASSERT(solocked(so));
143
144 return EOPNOTSUPP;
145 }
146
147 static int
mpls_shutdown(struct socket * so)148 mpls_shutdown(struct socket *so)
149 {
150 KASSERT(solocked(so));
151
152 return EOPNOTSUPP;
153 }
154
155 static int
mpls_abort(struct socket * so)156 mpls_abort(struct socket *so)
157 {
158 KASSERT(solocked(so));
159
160 return EOPNOTSUPP;
161 }
162
163 static int
mpls_ioctl(struct socket * so,u_long cmd,void * nam,struct ifnet * ifp)164 mpls_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
165 {
166 return EOPNOTSUPP;
167 }
168
169 static int
mpls_stat(struct socket * so,struct stat * ub)170 mpls_stat(struct socket *so, struct stat *ub)
171 {
172 KASSERT(solocked(so));
173
174 return EOPNOTSUPP;
175 }
176
177 static int
mpls_peeraddr(struct socket * so,struct sockaddr * nam)178 mpls_peeraddr(struct socket *so, struct sockaddr *nam)
179 {
180 KASSERT(solocked(so));
181
182 return EOPNOTSUPP;
183 }
184
185 static int
mpls_sockaddr(struct socket * so,struct sockaddr * nam)186 mpls_sockaddr(struct socket *so, struct sockaddr *nam)
187 {
188 KASSERT(solocked(so));
189
190 return EOPNOTSUPP;
191 }
192
193 static int
mpls_rcvd(struct socket * so,int flags,struct lwp * l)194 mpls_rcvd(struct socket *so, int flags, struct lwp *l)
195 {
196 KASSERT(solocked(so));
197
198 return EOPNOTSUPP;
199 }
200
201 static int
mpls_recvoob(struct socket * so,struct mbuf * m,int flags)202 mpls_recvoob(struct socket *so, struct mbuf *m, int flags)
203 {
204 KASSERT(solocked(so));
205
206 return EOPNOTSUPP;
207 }
208
209 static int
mpls_send(struct socket * so,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,struct lwp * l)210 mpls_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
211 struct mbuf *control, struct lwp *l)
212 {
213 KASSERT(solocked(so));
214
215 return EOPNOTSUPP;
216 }
217
218 static int
mpls_sendoob(struct socket * so,struct mbuf * m,struct mbuf * control)219 mpls_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
220 {
221 KASSERT(solocked(so));
222
223 return EOPNOTSUPP;
224 }
225
226 static int
mpls_purgeif(struct socket * so,struct ifnet * ifp)227 mpls_purgeif(struct socket *so, struct ifnet *ifp)
228 {
229
230 return EOPNOTSUPP;
231 }
232
233 /*
234 * Sysctl for MPLS variables.
235 */
236 static void
sysctl_net_mpls_setup(struct sysctllog ** clog)237 sysctl_net_mpls_setup(struct sysctllog **clog)
238 {
239
240 sysctl_createv(clog, 0, NULL, NULL,
241 CTLFLAG_PERMANENT,
242 CTLTYPE_NODE, "mpls", NULL,
243 NULL, 0, NULL, 0,
244 CTL_NET, PF_MPLS, CTL_EOL);
245
246 sysctl_createv(clog, 0, NULL, NULL,
247 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
248 CTLTYPE_INT, "ttl",
249 SYSCTL_DESCR("Default TTL"),
250 NULL, 0, &mpls_defttl, 0,
251 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
252 sysctl_createv(clog, 0, NULL, NULL,
253 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
254 CTLTYPE_INT, "forwarding",
255 SYSCTL_DESCR("MPLS forwarding"),
256 NULL, 0, &mpls_forwarding, 0,
257 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
258 sysctl_createv(clog, 0, NULL, NULL,
259 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
260 CTLTYPE_INT, "accept",
261 SYSCTL_DESCR("Accept MPLS Frames"),
262 NULL, 0, &mpls_frame_accept, 0,
263 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
264 sysctl_createv(clog, 0, NULL, NULL,
265 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
266 CTLTYPE_INT, "ifq_len",
267 SYSCTL_DESCR("MPLS queue length"),
268 NULL, 0, &mplsintrq.ifq_maxlen, 0,
269 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
270 sysctl_createv(clog, 0, NULL, NULL,
271 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
272 CTLTYPE_INT, "rfc4182",
273 SYSCTL_DESCR("RFC 4182 conformance"),
274 NULL, 0, &mpls_rfc4182, 0,
275 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
276 #ifdef INET
277 sysctl_createv(clog, 0, NULL, NULL,
278 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
279 CTLTYPE_INT, "inet_mapttl",
280 SYSCTL_DESCR("Map IP TTL"),
281 NULL, 0, &mpls_mapttl_inet, 0,
282 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
283 sysctl_createv(clog, 0, NULL, NULL,
284 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
285 CTLTYPE_INT, "inet_map_prec",
286 SYSCTL_DESCR("Map IP Prec"),
287 NULL, 0, &mpls_mapprec_inet, 0,
288 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
289 sysctl_createv(clog, 0, NULL, NULL,
290 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
291 CTLTYPE_INT, "icmp_respond",
292 SYSCTL_DESCR("Emit ICMP packets on errors"),
293 NULL, 0, &mpls_icmp_respond, 0,
294 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
295 #endif
296 #ifdef INET6
297 sysctl_createv(clog, 0, NULL, NULL,
298 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
299 CTLTYPE_INT, "inet6_mapttl",
300 SYSCTL_DESCR("Map IP6 TTL"),
301 NULL, 0, &mpls_mapttl_inet6, 0,
302 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
303 sysctl_createv(clog, 0, NULL, NULL,
304 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
305 CTLTYPE_INT, "inet6_map_prec",
306 SYSCTL_DESCR("Map IP6 class"),
307 NULL, 0, &mpls_mapclass_inet6, 0,
308 CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
309 #endif
310 }
311
312 DOMAIN_DEFINE(mplsdomain);
313
314 PR_WRAP_USRREQS(mpls)
315 #define mpls_attach mpls_attach_wrapper
316 #define mpls_detach mpls_detach_wrapper
317 #define mpls_accept mpls_accept_wrapper
318 #define mpls_bind mpls_bind_wrapper
319 #define mpls_listen mpls_listen_wrapper
320 #define mpls_connect mpls_connect_wrapper
321 #define mpls_connect2 mpls_connect2_wrapper
322 #define mpls_disconnect mpls_disconnect_wrapper
323 #define mpls_shutdown mpls_shutdown_wrapper
324 #define mpls_abort mpls_abort_wrapper
325 #define mpls_ioctl mpls_ioctl_wrapper
326 #define mpls_stat mpls_stat_wrapper
327 #define mpls_peeraddr mpls_peeraddr_wrapper
328 #define mpls_sockaddr mpls_sockaddr_wrapper
329 #define mpls_rcvd mpls_rcvd_wrapper
330 #define mpls_recvoob mpls_recvoob_wrapper
331 #define mpls_send mpls_send_wrapper
332 #define mpls_sendoob mpls_sendoob_wrapper
333 #define mpls_purgeif mpls_purgeif_wrapper
334
335 static const struct pr_usrreqs mpls_usrreqs = {
336 .pr_attach = mpls_attach,
337 .pr_detach = mpls_detach,
338 .pr_accept = mpls_accept,
339 .pr_bind = mpls_bind,
340 .pr_listen = mpls_listen,
341 .pr_connect = mpls_connect,
342 .pr_connect2 = mpls_connect2,
343 .pr_disconnect = mpls_disconnect,
344 .pr_shutdown = mpls_shutdown,
345 .pr_abort = mpls_abort,
346 .pr_ioctl = mpls_ioctl,
347 .pr_stat = mpls_stat,
348 .pr_peeraddr = mpls_peeraddr,
349 .pr_sockaddr = mpls_sockaddr,
350 .pr_rcvd = mpls_rcvd,
351 .pr_recvoob = mpls_recvoob,
352 .pr_send = mpls_send,
353 .pr_sendoob = mpls_sendoob,
354 .pr_purgeif = mpls_purgeif,
355 };
356
357 const struct protosw mplssw[] = {
358 { .pr_domain = &mplsdomain,
359 .pr_init = mpls_init,
360 },
361 {
362 .pr_type = SOCK_DGRAM,
363 .pr_domain = &mplsdomain,
364 .pr_flags = PR_ATOMIC | PR_ADDR,
365 .pr_usrreqs = &mpls_usrreqs,
366 },
367 {
368 .pr_type = SOCK_RAW,
369 .pr_domain = &mplsdomain,
370 .pr_flags = PR_ATOMIC | PR_ADDR,
371 .pr_usrreqs = &mpls_usrreqs,
372 },
373 };
374
375 struct domain mplsdomain = {
376 .dom_family = PF_MPLS,
377 .dom_name = "MPLS",
378 .dom_init = NULL,
379 .dom_externalize = NULL,
380 .dom_dispose = NULL,
381 .dom_protosw = mplssw,
382 .dom_protoswNPROTOSW = &mplssw[__arraycount(mplssw)],
383 .dom_rtattach = rt_inithead,
384 .dom_rtoffset = offsetof(struct sockaddr_mpls, smpls_addr) << 3,
385 .dom_maxrtkey = sizeof(union mpls_shim),
386 .dom_ifattach = NULL,
387 .dom_ifdetach = NULL,
388 .dom_ifqueues = { &mplsintrq, NULL },
389 .dom_link = { NULL },
390 .dom_mowner = MOWNER_INIT("MPLS", ""),
391 .dom_sa_cmpofs = offsetof(struct sockaddr_mpls, smpls_addr),
392 .dom_sa_cmplen = sizeof(union mpls_shim),
393 .dom_rtcache = LIST_HEAD_INITIALIZER(mplsdomain.dom_rtcache)
394 };
395