xref: /netbsd/sys/netmpls/mpls_proto.c (revision 7258b55e)
1 /*	$NetBSD: mpls_proto.c,v 1.33 2022/09/03 02:24:59 thorpej 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.33 2022/09/03 02:24:59 thorpej 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 #define	MPLS_MAXQLEN	256
53 pktqueue_t *		mpls_pktq		__read_mostly;
54 
55 static int mpls_attach(struct socket *, int);
56 static void sysctl_net_mpls_setup(struct sysctllog **);
57 
58 #ifdef MBUFTRACE
59 struct mowner mpls_owner = MOWNER_INIT("MPLS", "");
60 #endif
61 
62 int mpls_defttl = 255;
63 int mpls_mapttl_inet = 1;
64 int mpls_mapttl_inet6 = 1;
65 int mpls_icmp_respond = 0;
66 int mpls_forwarding = 0;
67 int mpls_frame_accept = 0;
68 int mpls_mapprec_inet = 1;
69 int mpls_mapclass_inet6 = 1;
70 int mpls_rfc4182 = 1;
71 
mpls_init(void)72 void mpls_init(void)
73 {
74 #ifdef MBUFTRACE
75 	MOWNER_ATTACH(&mpls_owner);
76 #endif
77 	mpls_pktq = pktq_create(MPLS_MAXQLEN, mplsintr, NULL);
78 	KASSERT(mpls_pktq != NULL);
79 
80 	sysctl_net_mpls_setup(NULL);
81 }
82 
83 static int
mpls_attach(struct socket * so,int proto)84 mpls_attach(struct socket *so, int proto)
85 {
86 	int error = EOPNOTSUPP;
87 
88 	sosetlock(so);
89 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
90 		error = soreserve(so, 8192, 8192);
91 	}
92 	return error;
93 }
94 
95 static void
mpls_detach(struct socket * so)96 mpls_detach(struct socket *so)
97 {
98 }
99 
100 static int
mpls_accept(struct socket * so,struct sockaddr * nam)101 mpls_accept(struct socket *so, struct sockaddr *nam)
102 {
103 	KASSERT(solocked(so));
104 
105 	return EOPNOTSUPP;
106 }
107 
108 static int
mpls_bind(struct socket * so,struct sockaddr * nam,struct lwp * l)109 mpls_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
110 {
111 	KASSERT(solocked(so));
112 
113 	return EOPNOTSUPP;
114 }
115 
116 static int
mpls_listen(struct socket * so,struct lwp * l)117 mpls_listen(struct socket *so, struct lwp *l)
118 {
119 	KASSERT(solocked(so));
120 
121 	return EOPNOTSUPP;
122 }
123 
124 static int
mpls_connect(struct socket * so,struct sockaddr * nam,struct lwp * l)125 mpls_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
126 {
127 	KASSERT(solocked(so));
128 
129 	return EOPNOTSUPP;
130 }
131 
132 static int
mpls_connect2(struct socket * so,struct socket * so2)133 mpls_connect2(struct socket *so, struct socket *so2)
134 {
135 	KASSERT(solocked(so));
136 
137 	return EOPNOTSUPP;
138 }
139 
140 static int
mpls_disconnect(struct socket * so)141 mpls_disconnect(struct socket *so)
142 {
143 	KASSERT(solocked(so));
144 
145 	return EOPNOTSUPP;
146 }
147 
148 static int
mpls_shutdown(struct socket * so)149 mpls_shutdown(struct socket *so)
150 {
151 	KASSERT(solocked(so));
152 
153 	return EOPNOTSUPP;
154 }
155 
156 static int
mpls_abort(struct socket * so)157 mpls_abort(struct socket *so)
158 {
159 	KASSERT(solocked(so));
160 
161 	return EOPNOTSUPP;
162 }
163 
164 static int
mpls_ioctl(struct socket * so,u_long cmd,void * nam,struct ifnet * ifp)165 mpls_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
166 {
167 	return EOPNOTSUPP;
168 }
169 
170 static int
mpls_stat(struct socket * so,struct stat * ub)171 mpls_stat(struct socket *so, struct stat *ub)
172 {
173 	KASSERT(solocked(so));
174 
175 	return EOPNOTSUPP;
176 }
177 
178 static int
mpls_peeraddr(struct socket * so,struct sockaddr * nam)179 mpls_peeraddr(struct socket *so, struct sockaddr *nam)
180 {
181 	KASSERT(solocked(so));
182 
183 	return EOPNOTSUPP;
184 }
185 
186 static int
mpls_sockaddr(struct socket * so,struct sockaddr * nam)187 mpls_sockaddr(struct socket *so, struct sockaddr *nam)
188 {
189 	KASSERT(solocked(so));
190 
191 	return EOPNOTSUPP;
192 }
193 
194 static int
mpls_rcvd(struct socket * so,int flags,struct lwp * l)195 mpls_rcvd(struct socket *so, int flags, struct lwp *l)
196 {
197 	KASSERT(solocked(so));
198 
199 	return EOPNOTSUPP;
200 }
201 
202 static int
mpls_recvoob(struct socket * so,struct mbuf * m,int flags)203 mpls_recvoob(struct socket *so, struct mbuf *m, int flags)
204 {
205 	KASSERT(solocked(so));
206 
207 	return EOPNOTSUPP;
208 }
209 
210 static int
mpls_send(struct socket * so,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,struct lwp * l)211 mpls_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
212     struct mbuf *control, struct lwp *l)
213 {
214 	KASSERT(solocked(so));
215 
216 	return EOPNOTSUPP;
217 }
218 
219 static int
mpls_sendoob(struct socket * so,struct mbuf * m,struct mbuf * control)220 mpls_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
221 {
222 	KASSERT(solocked(so));
223 
224 	m_freem(m);
225 	m_freem(control);
226 
227 	return EOPNOTSUPP;
228 }
229 
230 static int
mpls_purgeif(struct socket * so,struct ifnet * ifp)231 mpls_purgeif(struct socket *so, struct ifnet *ifp)
232 {
233 
234 	return EOPNOTSUPP;
235 }
236 
237 /*
238  * Sysctl for MPLS variables.
239  */
240 static void
sysctl_net_mpls_setup(struct sysctllog ** clog)241 sysctl_net_mpls_setup(struct sysctllog **clog)
242 {
243 	const struct sysctlnode *mpls_node;
244 
245         sysctl_createv(clog, 0, NULL, &mpls_node,
246                        CTLFLAG_PERMANENT,
247                        CTLTYPE_NODE, "mpls", NULL,
248                        NULL, 0, NULL, 0,
249                        CTL_NET, PF_MPLS, CTL_EOL);
250 
251         sysctl_createv(clog, 0, NULL, NULL,
252                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
253                        CTLTYPE_INT, "ttl",
254                        SYSCTL_DESCR("Default TTL"),
255                        NULL, 0, &mpls_defttl, 0,
256                        CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
257 	sysctl_createv(clog, 0, NULL, NULL,
258 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
259 		       CTLTYPE_INT, "forwarding",
260 		       SYSCTL_DESCR("MPLS forwarding"),
261 		       NULL, 0, &mpls_forwarding, 0,
262 		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
263 	sysctl_createv(clog, 0, NULL, NULL,
264 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
265 		       CTLTYPE_INT, "accept",
266 		       SYSCTL_DESCR("Accept MPLS Frames"),
267 		       NULL, 0, &mpls_frame_accept, 0,
268 		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
269 
270 	pktq_sysctl_setup(mpls_pktq, clog, mpls_node, CTL_CREATE);
271 
272 	sysctl_createv(clog, 0, NULL, NULL,
273 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
274 		       CTLTYPE_INT, "rfc4182",
275 		       SYSCTL_DESCR("RFC 4182 conformance"),
276 		       NULL, 0, &mpls_rfc4182, 0,
277 		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
278 #ifdef INET
279 	sysctl_createv(clog, 0, NULL, NULL,
280 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
281 		       CTLTYPE_INT, "inet_mapttl",
282 		       SYSCTL_DESCR("Map IP TTL"),
283 		       NULL, 0, &mpls_mapttl_inet, 0,
284 		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
285 	sysctl_createv(clog, 0, NULL, NULL,
286 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
287 		       CTLTYPE_INT, "inet_map_prec",
288 		       SYSCTL_DESCR("Map IP Prec"),
289 		       NULL, 0, &mpls_mapprec_inet, 0,
290 		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
291 	sysctl_createv(clog, 0, NULL, NULL,
292 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
293 		       CTLTYPE_INT, "icmp_respond",
294 		       SYSCTL_DESCR("Emit ICMP packets on errors"),
295 		       NULL, 0, &mpls_icmp_respond, 0,
296 		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
297 #endif
298 #ifdef INET6
299 	sysctl_createv(clog, 0, NULL, NULL,
300 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
301 		       CTLTYPE_INT, "inet6_mapttl",
302 		       SYSCTL_DESCR("Map IP6 TTL"),
303 		       NULL, 0, &mpls_mapttl_inet6, 0,
304 		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
305 	sysctl_createv(clog, 0, NULL, NULL,
306 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
307 		       CTLTYPE_INT, "inet6_map_prec",
308 		       SYSCTL_DESCR("Map IP6 class"),
309 		       NULL, 0, &mpls_mapclass_inet6, 0,
310 		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
311 #endif
312 }
313 
314 DOMAIN_DEFINE(mplsdomain);
315 
316 PR_WRAP_USRREQS(mpls)
317 #define	mpls_attach	mpls_attach_wrapper
318 #define	mpls_detach	mpls_detach_wrapper
319 #define	mpls_accept	mpls_accept_wrapper
320 #define	mpls_bind	mpls_bind_wrapper
321 #define	mpls_listen	mpls_listen_wrapper
322 #define	mpls_connect	mpls_connect_wrapper
323 #define	mpls_connect2	mpls_connect2_wrapper
324 #define	mpls_disconnect	mpls_disconnect_wrapper
325 #define	mpls_shutdown	mpls_shutdown_wrapper
326 #define	mpls_abort	mpls_abort_wrapper
327 #define	mpls_ioctl	mpls_ioctl_wrapper
328 #define	mpls_stat	mpls_stat_wrapper
329 #define	mpls_peeraddr	mpls_peeraddr_wrapper
330 #define	mpls_sockaddr	mpls_sockaddr_wrapper
331 #define	mpls_rcvd	mpls_rcvd_wrapper
332 #define	mpls_recvoob	mpls_recvoob_wrapper
333 #define	mpls_send	mpls_send_wrapper
334 #define	mpls_sendoob	mpls_sendoob_wrapper
335 #define	mpls_purgeif	mpls_purgeif_wrapper
336 
337 static const struct pr_usrreqs mpls_usrreqs = {
338 	.pr_attach	= mpls_attach,
339 	.pr_detach	= mpls_detach,
340 	.pr_accept	= mpls_accept,
341 	.pr_bind	= mpls_bind,
342 	.pr_listen	= mpls_listen,
343 	.pr_connect	= mpls_connect,
344 	.pr_connect2	= mpls_connect2,
345 	.pr_disconnect	= mpls_disconnect,
346 	.pr_shutdown	= mpls_shutdown,
347 	.pr_abort	= mpls_abort,
348 	.pr_ioctl	= mpls_ioctl,
349 	.pr_stat	= mpls_stat,
350 	.pr_peeraddr	= mpls_peeraddr,
351 	.pr_sockaddr	= mpls_sockaddr,
352 	.pr_rcvd	= mpls_rcvd,
353 	.pr_recvoob	= mpls_recvoob,
354 	.pr_send	= mpls_send,
355 	.pr_sendoob	= mpls_sendoob,
356 	.pr_purgeif	= mpls_purgeif,
357 };
358 
359 const struct protosw mplssw[] = {
360 	{	.pr_domain = &mplsdomain,
361 		.pr_init = mpls_init,
362 	},
363 	{
364 		.pr_type = SOCK_DGRAM,
365 		.pr_domain = &mplsdomain,
366 		.pr_flags = PR_ATOMIC | PR_ADDR,
367 		.pr_usrreqs = &mpls_usrreqs,
368 	},
369 	{
370 		.pr_type = SOCK_RAW,
371 		.pr_domain = &mplsdomain,
372 		.pr_flags = PR_ATOMIC | PR_ADDR,
373 		.pr_usrreqs = &mpls_usrreqs,
374 	},
375 };
376 
377 struct domain mplsdomain = {
378 	.dom_family = PF_MPLS,
379 	.dom_name = "MPLS",
380 	.dom_init = NULL,
381 	.dom_externalize = NULL,
382 	.dom_dispose = NULL,
383 	.dom_protosw = mplssw,
384 	.dom_protoswNPROTOSW = &mplssw[__arraycount(mplssw)],
385 	.dom_rtattach = rt_inithead,
386 	.dom_rtoffset = offsetof(struct sockaddr_mpls, smpls_addr) << 3,
387 	.dom_maxrtkey = sizeof(union mpls_shim),
388 	.dom_ifattach = NULL,
389 	.dom_ifdetach = NULL,
390 	.dom_link = { NULL },
391 	.dom_mowner = MOWNER_INIT("MPLS", ""),
392 	.dom_sa_cmpofs = offsetof(struct sockaddr_mpls, smpls_addr),
393 	.dom_sa_cmplen = sizeof(union mpls_shim),
394 };
395