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