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