1 /* $NetBSD: raw_ip6.c,v 1.158 2017/11/05 07:03:37 ozaki-r Exp $ */ 2 /* $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1982, 1986, 1988, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 62 */ 63 64 #include <sys/cdefs.h> 65 __KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.158 2017/11/05 07:03:37 ozaki-r Exp $"); 66 67 #ifdef _KERNEL_OPT 68 #include "opt_ipsec.h" 69 #include "opt_net_mpsafe.h" 70 #endif 71 72 #include <sys/param.h> 73 #include <sys/sysctl.h> 74 #include <sys/mbuf.h> 75 #include <sys/socket.h> 76 #include <sys/protosw.h> 77 #include <sys/socketvar.h> 78 #include <sys/systm.h> 79 #include <sys/proc.h> 80 #include <sys/kauth.h> 81 #include <sys/kmem.h> 82 83 #include <net/if.h> 84 #include <net/if_types.h> 85 #include <net/net_stats.h> 86 87 #include <netinet/in.h> 88 #include <netinet/in_var.h> 89 #include <netinet/ip6.h> 90 #include <netinet6/ip6_var.h> 91 #include <netinet6/ip6_private.h> 92 #include <netinet6/ip6_mroute.h> 93 #include <netinet/icmp6.h> 94 #include <netinet6/icmp6_private.h> 95 #include <netinet6/in6_pcb.h> 96 #include <netinet6/ip6protosw.h> 97 #include <netinet6/scope6_var.h> 98 #include <netinet6/raw_ip6.h> 99 100 #ifdef IPSEC 101 #include <netipsec/ipsec.h> 102 #include <netipsec/ipsec_var.h> 103 #include <netipsec/ipsec_private.h> 104 #include <netipsec/ipsec6.h> 105 #endif 106 107 #include "faith.h" 108 #if defined(NFAITH) && 0 < NFAITH 109 #include <net/if_faith.h> 110 #endif 111 112 extern struct inpcbtable rawcbtable; 113 struct inpcbtable raw6cbtable; 114 #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) 115 116 /* 117 * Raw interface to IP6 protocol. 118 */ 119 120 static percpu_t *rip6stat_percpu; 121 122 #define RIP6_STATINC(x) _NET_STATINC(rip6stat_percpu, x) 123 124 static void sysctl_net_inet6_raw6_setup(struct sysctllog **); 125 126 /* 127 * Initialize raw connection block queue. 128 */ 129 void 130 rip6_init(void) 131 { 132 133 sysctl_net_inet6_raw6_setup(NULL); 134 in6_pcbinit(&raw6cbtable, 1, 1); 135 136 rip6stat_percpu = percpu_alloc(sizeof(uint64_t) * RIP6_NSTATS); 137 } 138 139 /* 140 * Setup generic address and protocol structures 141 * for raw_input routine, then pass them along with 142 * mbuf chain. 143 */ 144 int 145 rip6_input(struct mbuf **mp, int *offp, int proto) 146 { 147 struct mbuf *m = *mp; 148 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 149 struct inpcb_hdr *inph; 150 struct in6pcb *in6p; 151 struct in6pcb *last = NULL; 152 struct sockaddr_in6 rip6src; 153 struct mbuf *opts = NULL; 154 155 RIP6_STATINC(RIP6_STAT_IPACKETS); 156 157 #if defined(NFAITH) && 0 < NFAITH 158 if (faithprefix(&ip6->ip6_dst)) { 159 /* send icmp6 host unreach? */ 160 m_freem(m); 161 return IPPROTO_DONE; 162 } 163 #endif 164 165 /* Be proactive about malicious use of IPv4 mapped address */ 166 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || 167 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { 168 /* XXX stat */ 169 m_freem(m); 170 return IPPROTO_DONE; 171 } 172 173 sockaddr_in6_init(&rip6src, &ip6->ip6_src, 0, 0, 0); 174 if (sa6_recoverscope(&rip6src) != 0) { 175 /* XXX: should be impossible. */ 176 m_freem(m); 177 return IPPROTO_DONE; 178 } 179 180 TAILQ_FOREACH(inph, &raw6cbtable.inpt_queue, inph_queue) { 181 in6p = (struct in6pcb *)inph; 182 if (in6p->in6p_af != AF_INET6) 183 continue; 184 if (in6p->in6p_ip6.ip6_nxt && 185 in6p->in6p_ip6.ip6_nxt != proto) 186 continue; 187 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 188 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 189 continue; 190 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 191 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 192 continue; 193 if (in6p->in6p_cksum != -1) { 194 RIP6_STATINC(RIP6_STAT_ISUM); 195 if (in6_cksum(m, proto, *offp, 196 m->m_pkthdr.len - *offp)) { 197 RIP6_STATINC(RIP6_STAT_BADSUM); 198 continue; 199 } 200 } 201 if (last) { 202 struct mbuf *n; 203 204 #ifdef IPSEC 205 /* 206 * Check AH/ESP integrity 207 */ 208 if (!ipsec_used || 209 (ipsec_used && !ipsec6_in_reject(m, last))) 210 #endif /* IPSEC */ 211 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 212 if (last->in6p_flags & IN6P_CONTROLOPTS) 213 ip6_savecontrol(last, &opts, ip6, n); 214 /* strip intermediate headers */ 215 m_adj(n, *offp); 216 if (sbappendaddr(&last->in6p_socket->so_rcv, 217 sin6tosa(&rip6src), n, opts) == 0) { 218 /* should notify about lost packet */ 219 m_freem(n); 220 if (opts) 221 m_freem(opts); 222 RIP6_STATINC(RIP6_STAT_FULLSOCK); 223 } else 224 sorwakeup(last->in6p_socket); 225 opts = NULL; 226 } 227 } 228 last = in6p; 229 } 230 #ifdef IPSEC 231 if (ipsec_used && last && ipsec6_in_reject(m, last)) { 232 m_freem(m); 233 /* 234 * XXX ipsec6_in_reject update stat if there is an error 235 * so we just need to update stats by hand in the case of last is 236 * NULL 237 */ 238 if (!last) 239 IPSEC6_STATINC(IPSEC_STAT_IN_POLVIO); 240 IP6_STATDEC(IP6_STAT_DELIVERED); 241 /* do not inject data into pcb */ 242 } else 243 #endif /* IPSEC */ 244 if (last) { 245 if (last->in6p_flags & IN6P_CONTROLOPTS) 246 ip6_savecontrol(last, &opts, ip6, m); 247 /* strip intermediate headers */ 248 m_adj(m, *offp); 249 if (sbappendaddr(&last->in6p_socket->so_rcv, 250 sin6tosa(&rip6src), m, opts) == 0) { 251 m_freem(m); 252 if (opts) 253 m_freem(opts); 254 RIP6_STATINC(RIP6_STAT_FULLSOCK); 255 } else 256 sorwakeup(last->in6p_socket); 257 } else { 258 RIP6_STATINC(RIP6_STAT_NOSOCK); 259 if (m->m_flags & M_MCAST) 260 RIP6_STATINC(RIP6_STAT_NOSOCKMCAST); 261 if (proto == IPPROTO_NONE) 262 m_freem(m); 263 else { 264 int s; 265 struct ifnet *rcvif = m_get_rcvif(m, &s); 266 u_int8_t *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ 267 in6_ifstat_inc(rcvif, ifs6_in_protounknown); 268 m_put_rcvif(rcvif, &s); 269 icmp6_error(m, ICMP6_PARAM_PROB, 270 ICMP6_PARAMPROB_NEXTHEADER, 271 prvnxtp - mtod(m, u_int8_t *)); 272 } 273 IP6_STATDEC(IP6_STAT_DELIVERED); 274 } 275 return IPPROTO_DONE; 276 } 277 278 void * 279 rip6_ctlinput(int cmd, const struct sockaddr *sa, void *d) 280 { 281 struct ip6_hdr *ip6; 282 struct ip6ctlparam *ip6cp = NULL; 283 const struct sockaddr_in6 *sa6_src = NULL; 284 void *cmdarg; 285 void (*notify)(struct in6pcb *, int) = in6_rtchange; 286 int nxt; 287 288 if (sa->sa_family != AF_INET6 || 289 sa->sa_len != sizeof(struct sockaddr_in6)) 290 return NULL; 291 292 if ((unsigned)cmd >= PRC_NCMDS) 293 return NULL; 294 if (PRC_IS_REDIRECT(cmd)) 295 notify = in6_rtchange, d = NULL; 296 else if (cmd == PRC_HOSTDEAD) 297 d = NULL; 298 else if (cmd == PRC_MSGSIZE) 299 ; /* special code is present, see below */ 300 else if (inet6ctlerrmap[cmd] == 0) 301 return NULL; 302 303 /* if the parameter is from icmp6, decode it. */ 304 if (d != NULL) { 305 ip6cp = (struct ip6ctlparam *)d; 306 ip6 = ip6cp->ip6c_ip6; 307 cmdarg = ip6cp->ip6c_cmdarg; 308 sa6_src = ip6cp->ip6c_src; 309 nxt = ip6cp->ip6c_nxt; 310 } else { 311 ip6 = NULL; 312 cmdarg = NULL; 313 sa6_src = &sa6_any; 314 nxt = -1; 315 } 316 317 if (ip6 && cmd == PRC_MSGSIZE) { 318 const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *)sa; 319 int valid = 0; 320 struct in6pcb *in6p; 321 322 /* 323 * Check to see if we have a valid raw IPv6 socket 324 * corresponding to the address in the ICMPv6 message 325 * payload, and the protocol (ip6_nxt) meets the socket. 326 * XXX chase extension headers, or pass final nxt value 327 * from icmp6_notify_error() 328 */ 329 in6p = NULL; 330 in6p = in6_pcblookup_connect(&raw6cbtable, &sa6->sin6_addr, 0, 331 (const struct in6_addr *)&sa6_src->sin6_addr, 0, 0, 0); 332 #if 0 333 if (!in6p) { 334 /* 335 * As the use of sendto(2) is fairly popular, 336 * we may want to allow non-connected pcb too. 337 * But it could be too weak against attacks... 338 * We should at least check if the local 339 * address (= s) is really ours. 340 */ 341 in6p = in6_pcblookup_bind(&raw6cbtable, 342 &sa6->sin6_addr, 0, 0); 343 } 344 #endif 345 346 if (in6p && in6p->in6p_ip6.ip6_nxt && 347 in6p->in6p_ip6.ip6_nxt == nxt) 348 valid++; 349 350 /* 351 * Depending on the value of "valid" and routing table 352 * size (mtudisc_{hi,lo}wat), we will: 353 * - recalculate the new MTU and create the 354 * corresponding routing entry, or 355 * - ignore the MTU change notification. 356 */ 357 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 358 359 /* 360 * regardless of if we called icmp6_mtudisc_update(), 361 * we need to call in6_pcbnotify(), to notify path MTU 362 * change to the userland (RFC3542), because some 363 * unconnected sockets may share the same destination 364 * and want to know the path MTU. 365 */ 366 } 367 368 (void) in6_pcbnotify(&raw6cbtable, sa, 0, 369 sin6tocsa(sa6_src), 0, cmd, cmdarg, notify); 370 return NULL; 371 } 372 373 /* 374 * Generate IPv6 header and pass packet to ip6_output. 375 * Tack on options user may have setup with control call. 376 */ 377 int 378 rip6_output(struct mbuf *m, struct socket * const so, 379 struct sockaddr_in6 * const dstsock, struct mbuf * const control) 380 { 381 struct in6_addr *dst; 382 struct ip6_hdr *ip6; 383 struct in6pcb *in6p; 384 u_int plen = m->m_pkthdr.len; 385 int error = 0; 386 struct ip6_pktopts opt, *optp = NULL; 387 struct ifnet *oifp = NULL; 388 int type, code; /* for ICMPv6 output statistics only */ 389 int scope_ambiguous = 0; 390 int bound = curlwp_bind(); 391 struct psref psref; 392 393 in6p = sotoin6pcb(so); 394 395 dst = &dstsock->sin6_addr; 396 if (control) { 397 if ((error = ip6_setpktopts(control, &opt, 398 in6p->in6p_outputopts, 399 kauth_cred_get(), so->so_proto->pr_protocol)) != 0) { 400 goto bad; 401 } 402 optp = &opt; 403 } else 404 optp = in6p->in6p_outputopts; 405 406 /* 407 * Check and convert scope zone ID into internal form. 408 * XXX: we may still need to determine the zone later. 409 */ 410 if (!(so->so_state & SS_ISCONNECTED)) { 411 if (dstsock->sin6_scope_id == 0 && !ip6_use_defzone) 412 scope_ambiguous = 1; 413 if ((error = sa6_embedscope(dstsock, ip6_use_defzone)) != 0) 414 goto bad; 415 } 416 417 /* 418 * For an ICMPv6 packet, we should know its type and code 419 * to update statistics. 420 */ 421 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 422 struct icmp6_hdr *icmp6; 423 if (m->m_len < sizeof(struct icmp6_hdr) && 424 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) { 425 error = ENOBUFS; 426 goto bad; 427 } 428 icmp6 = mtod(m, struct icmp6_hdr *); 429 type = icmp6->icmp6_type; 430 code = icmp6->icmp6_code; 431 } else { 432 type = 0; 433 code = 0; 434 } 435 436 M_PREPEND(m, sizeof(*ip6), M_DONTWAIT); 437 if (!m) { 438 error = ENOBUFS; 439 goto bad; 440 } 441 ip6 = mtod(m, struct ip6_hdr *); 442 443 /* 444 * Next header might not be ICMP6 but use its pseudo header anyway. 445 */ 446 ip6->ip6_dst = *dst; 447 448 /* 449 * Source address selection. 450 */ 451 error = in6_selectsrc(dstsock, optp, in6p->in6p_moptions, 452 &in6p->in6p_route, &in6p->in6p_laddr, &oifp, &psref, &ip6->ip6_src); 453 if (error != 0) 454 goto bad; 455 456 if (oifp && scope_ambiguous) { 457 /* 458 * Application should provide a proper zone ID or the use of 459 * default zone IDs should be enabled. Unfortunately, some 460 * applications do not behave as it should, so we need a 461 * workaround. Even if an appropriate ID is not determined 462 * (when it's required), if we can determine the outgoing 463 * interface. determine the zone ID based on the interface. 464 */ 465 error = in6_setscope(&dstsock->sin6_addr, oifp, NULL); 466 if (error != 0) 467 goto bad; 468 } 469 ip6->ip6_dst = dstsock->sin6_addr; 470 471 /* fill in the rest of the IPv6 header fields */ 472 ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK; 473 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 474 ip6->ip6_vfc |= IPV6_VERSION; 475 /* ip6_plen will be filled in ip6_output, so not fill it here. */ 476 ip6->ip6_nxt = in6p->in6p_ip6.ip6_nxt; 477 ip6->ip6_hlim = in6_selecthlim(in6p, oifp); 478 479 if_put(oifp, &psref); 480 oifp = NULL; 481 482 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 || 483 in6p->in6p_cksum != -1) { 484 int off; 485 u_int16_t sum; 486 487 /* compute checksum */ 488 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) 489 off = offsetof(struct icmp6_hdr, icmp6_cksum); 490 else 491 off = in6p->in6p_cksum; 492 if (plen < off + 1) { 493 error = EINVAL; 494 goto bad; 495 } 496 off += sizeof(struct ip6_hdr); 497 498 sum = 0; 499 m = m_copyback_cow(m, off, sizeof(sum), (void *)&sum, 500 M_DONTWAIT); 501 if (m == NULL) { 502 error = ENOBUFS; 503 goto bad; 504 } 505 sum = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen); 506 m = m_copyback_cow(m, off, sizeof(sum), (void *)&sum, 507 M_DONTWAIT); 508 if (m == NULL) { 509 error = ENOBUFS; 510 goto bad; 511 } 512 } 513 514 { 515 struct ifnet *ret_oifp = NULL; 516 517 error = ip6_output(m, optp, &in6p->in6p_route, 0, 518 in6p->in6p_moptions, in6p, &ret_oifp); 519 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 520 if (ret_oifp) 521 icmp6_ifoutstat_inc(ret_oifp, type, code); 522 ICMP6_STATINC(ICMP6_STAT_OUTHIST + type); 523 } else 524 RIP6_STATINC(RIP6_STAT_OPACKETS); 525 } 526 527 goto freectl; 528 529 bad: 530 if (m) 531 m_freem(m); 532 533 freectl: 534 if (control) { 535 ip6_clearpktopts(&opt, -1); 536 m_freem(control); 537 } 538 if_put(oifp, &psref); 539 curlwp_bindx(bound); 540 return error; 541 } 542 543 /* 544 * Raw IPv6 socket option processing. 545 */ 546 int 547 rip6_ctloutput(int op, struct socket *so, struct sockopt *sopt) 548 { 549 int error = 0; 550 551 if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) { 552 int optval; 553 554 /* need to fiddle w/ opt(IPPROTO_IPV6, IPV6_CHECKSUM)? */ 555 if (op == PRCO_GETOPT) { 556 optval = 1; 557 error = sockopt_set(sopt, &optval, sizeof(optval)); 558 } else if (op == PRCO_SETOPT) { 559 error = sockopt_getint(sopt, &optval); 560 if (error) 561 goto out; 562 if (optval == 0) 563 error = EINVAL; 564 } 565 566 goto out; 567 } else if (sopt->sopt_level != IPPROTO_IPV6) 568 return ip6_ctloutput(op, so, sopt); 569 570 switch (sopt->sopt_name) { 571 case MRT6_INIT: 572 case MRT6_DONE: 573 case MRT6_ADD_MIF: 574 case MRT6_DEL_MIF: 575 case MRT6_ADD_MFC: 576 case MRT6_DEL_MFC: 577 case MRT6_PIM: 578 if (op == PRCO_SETOPT) 579 error = ip6_mrouter_set(so, sopt); 580 else if (op == PRCO_GETOPT) 581 error = ip6_mrouter_get(so, sopt); 582 else 583 error = EINVAL; 584 break; 585 case IPV6_CHECKSUM: 586 return ip6_raw_ctloutput(op, so, sopt); 587 default: 588 return ip6_ctloutput(op, so, sopt); 589 } 590 out: 591 return error; 592 } 593 594 extern u_long rip6_sendspace; 595 extern u_long rip6_recvspace; 596 597 int 598 rip6_attach(struct socket *so, int proto) 599 { 600 struct in6pcb *in6p; 601 int s, error; 602 603 KASSERT(sotoin6pcb(so) == NULL); 604 sosetlock(so); 605 606 error = kauth_authorize_network(curlwp->l_cred, 607 KAUTH_NETWORK_SOCKET, KAUTH_REQ_NETWORK_SOCKET_RAWSOCK, 608 KAUTH_ARG(AF_INET6), 609 KAUTH_ARG(SOCK_RAW), 610 KAUTH_ARG(so->so_proto->pr_protocol)); 611 if (error) { 612 return error; 613 } 614 s = splsoftnet(); 615 error = soreserve(so, rip6_sendspace, rip6_recvspace); 616 if (error) { 617 splx(s); 618 return error; 619 } 620 if ((error = in6_pcballoc(so, &raw6cbtable)) != 0) { 621 splx(s); 622 return error; 623 } 624 splx(s); 625 in6p = sotoin6pcb(so); 626 in6p->in6p_ip6.ip6_nxt = proto; 627 in6p->in6p_cksum = -1; 628 629 in6p->in6p_icmp6filt = kmem_alloc(sizeof(struct icmp6_filter), KM_SLEEP); 630 ICMP6_FILTER_SETPASSALL(in6p->in6p_icmp6filt); 631 KASSERT(solocked(so)); 632 return error; 633 } 634 635 static void 636 rip6_detach(struct socket *so) 637 { 638 struct in6pcb *in6p = sotoin6pcb(so); 639 640 KASSERT(solocked(so)); 641 KASSERT(in6p != NULL); 642 643 if (so == ip6_mrouter) { 644 ip6_mrouter_done(); 645 } 646 /* xxx: RSVP */ 647 if (in6p->in6p_icmp6filt != NULL) { 648 kmem_free(in6p->in6p_icmp6filt, sizeof(struct icmp6_filter)); 649 in6p->in6p_icmp6filt = NULL; 650 } 651 in6_pcbdetach(in6p); 652 } 653 654 static int 655 rip6_accept(struct socket *so, struct sockaddr *nam) 656 { 657 KASSERT(solocked(so)); 658 659 return EOPNOTSUPP; 660 } 661 662 static int 663 rip6_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) 664 { 665 struct in6pcb *in6p = sotoin6pcb(so); 666 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 667 struct ifaddr *ifa = NULL; 668 int error = 0; 669 int s; 670 671 KASSERT(solocked(so)); 672 KASSERT(in6p != NULL); 673 KASSERT(nam != NULL); 674 675 if (addr->sin6_len != sizeof(*addr)) 676 return EINVAL; 677 if (IFNET_READER_EMPTY() || addr->sin6_family != AF_INET6) 678 return EADDRNOTAVAIL; 679 680 if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0) 681 return error; 682 683 /* 684 * we don't support mapped address here, it would confuse 685 * users so reject it 686 */ 687 if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) 688 return EADDRNOTAVAIL; 689 s = pserialize_read_enter(); 690 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && 691 (ifa = ifa_ifwithaddr(sin6tosa(addr))) == NULL) { 692 error = EADDRNOTAVAIL; 693 goto out; 694 } 695 if (ifa && (ifatoia6(ifa))->ia6_flags & 696 (IN6_IFF_ANYCAST | IN6_IFF_DUPLICATED)) { 697 error = EADDRNOTAVAIL; 698 goto out; 699 } 700 701 in6p->in6p_laddr = addr->sin6_addr; 702 error = 0; 703 out: 704 pserialize_read_exit(s); 705 return error; 706 } 707 708 static int 709 rip6_listen(struct socket *so, struct lwp *l) 710 { 711 KASSERT(solocked(so)); 712 713 return EOPNOTSUPP; 714 } 715 716 static int 717 rip6_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) 718 { 719 struct in6pcb *in6p = sotoin6pcb(so); 720 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 721 struct in6_addr in6a; 722 struct ifnet *ifp = NULL; 723 int scope_ambiguous = 0; 724 int error = 0; 725 struct psref psref; 726 int bound; 727 728 KASSERT(solocked(so)); 729 KASSERT(in6p != NULL); 730 KASSERT(nam != NULL); 731 732 if (IFNET_READER_EMPTY()) 733 return EADDRNOTAVAIL; 734 if (addr->sin6_family != AF_INET6) 735 return EAFNOSUPPORT; 736 737 /* 738 * Application should provide a proper zone ID or the use of 739 * default zone IDs should be enabled. Unfortunately, some 740 * applications do not behave as it should, so we need a 741 * workaround. Even if an appropriate ID is not determined, 742 * we'll see if we can determine the outgoing interface. If we 743 * can, determine the zone ID based on the interface below. 744 */ 745 if (addr->sin6_scope_id == 0 && !ip6_use_defzone) 746 scope_ambiguous = 1; 747 if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0) 748 return error; 749 750 bound = curlwp_bind(); 751 /* Source address selection. XXX: need pcblookup? */ 752 error = in6_selectsrc(addr, in6p->in6p_outputopts, 753 in6p->in6p_moptions, &in6p->in6p_route, 754 &in6p->in6p_laddr, &ifp, &psref, &in6a); 755 if (error != 0) 756 goto out; 757 /* XXX: see above */ 758 if (ifp && scope_ambiguous && 759 (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) { 760 goto out; 761 } 762 in6p->in6p_laddr = in6a; 763 in6p->in6p_faddr = addr->sin6_addr; 764 soisconnected(so); 765 out: 766 if_put(ifp, &psref); 767 curlwp_bindx(bound); 768 return error; 769 } 770 771 static int 772 rip6_connect2(struct socket *so, struct socket *so2) 773 { 774 KASSERT(solocked(so)); 775 776 return EOPNOTSUPP; 777 } 778 779 static int 780 rip6_disconnect(struct socket *so) 781 { 782 struct in6pcb *in6p = sotoin6pcb(so); 783 784 KASSERT(solocked(so)); 785 KASSERT(in6p != NULL); 786 787 if ((so->so_state & SS_ISCONNECTED) == 0) 788 return ENOTCONN; 789 790 in6p->in6p_faddr = in6addr_any; 791 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 792 return 0; 793 } 794 795 static int 796 rip6_shutdown(struct socket *so) 797 { 798 KASSERT(solocked(so)); 799 800 /* 801 * Mark the connection as being incapable of futther input. 802 */ 803 socantsendmore(so); 804 return 0; 805 } 806 807 static int 808 rip6_abort(struct socket *so) 809 { 810 KASSERT(solocked(so)); 811 812 soisdisconnected(so); 813 rip6_detach(so); 814 return 0; 815 } 816 817 static int 818 rip6_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) 819 { 820 return in6_control(so, cmd, nam, ifp); 821 } 822 823 static int 824 rip6_stat(struct socket *so, struct stat *ub) 825 { 826 KASSERT(solocked(so)); 827 828 /* stat: don't bother with a blocksize */ 829 return 0; 830 } 831 832 static int 833 rip6_peeraddr(struct socket *so, struct sockaddr *nam) 834 { 835 KASSERT(solocked(so)); 836 KASSERT(sotoin6pcb(so) != NULL); 837 KASSERT(nam != NULL); 838 839 in6_setpeeraddr(sotoin6pcb(so), (struct sockaddr_in6 *)nam); 840 return 0; 841 } 842 843 static int 844 rip6_sockaddr(struct socket *so, struct sockaddr *nam) 845 { 846 KASSERT(solocked(so)); 847 KASSERT(sotoin6pcb(so) != NULL); 848 KASSERT(nam != NULL); 849 850 in6_setsockaddr(sotoin6pcb(so), (struct sockaddr_in6 *)nam); 851 return 0; 852 } 853 854 static int 855 rip6_rcvd(struct socket *so, int flags, struct lwp *l) 856 { 857 KASSERT(solocked(so)); 858 859 return EOPNOTSUPP; 860 } 861 862 static int 863 rip6_recvoob(struct socket *so, struct mbuf *m, int flags) 864 { 865 KASSERT(solocked(so)); 866 867 return EOPNOTSUPP; 868 } 869 870 static int 871 rip6_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, 872 struct mbuf *control, struct lwp *l) 873 { 874 struct in6pcb *in6p = sotoin6pcb(so); 875 struct sockaddr_in6 tmp; 876 struct sockaddr_in6 *dst; 877 int error = 0; 878 879 KASSERT(solocked(so)); 880 KASSERT(in6p != NULL); 881 KASSERT(m != NULL); 882 883 /* 884 * Ship a packet out. The appropriate raw output 885 * routine handles any messaging necessary. 886 */ 887 888 /* always copy sockaddr to avoid overwrites */ 889 if (so->so_state & SS_ISCONNECTED) { 890 if (nam) { 891 error = EISCONN; 892 goto release; 893 } 894 /* XXX */ 895 sockaddr_in6_init(&tmp, &in6p->in6p_faddr, 0, 0, 0); 896 dst = &tmp; 897 } else { 898 if (nam == NULL) { 899 error = ENOTCONN; 900 goto release; 901 } 902 tmp = *(struct sockaddr_in6 *)nam; 903 dst = &tmp; 904 905 if (dst->sin6_family != AF_INET6) { 906 error = EAFNOSUPPORT; 907 goto release; 908 } 909 } 910 error = rip6_output(m, so, dst, control); 911 m = NULL; 912 913 release: 914 if (m) 915 m_freem(m); 916 917 return error; 918 } 919 920 static int 921 rip6_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) 922 { 923 KASSERT(solocked(so)); 924 925 if (m) 926 m_freem(m); 927 928 return EOPNOTSUPP; 929 } 930 931 static int 932 rip6_purgeif(struct socket *so, struct ifnet *ifp) 933 { 934 935 mutex_enter(softnet_lock); 936 in6_pcbpurgeif0(&raw6cbtable, ifp); 937 #ifdef NET_MPSAFE 938 mutex_exit(softnet_lock); 939 #endif 940 in6_purgeif(ifp); 941 #ifdef NET_MPSAFE 942 mutex_enter(softnet_lock); 943 #endif 944 in6_pcbpurgeif(&raw6cbtable, ifp); 945 mutex_exit(softnet_lock); 946 947 return 0; 948 } 949 950 static int 951 sysctl_net_inet6_raw6_stats(SYSCTLFN_ARGS) 952 { 953 954 return (NETSTAT_SYSCTL(rip6stat_percpu, RIP6_NSTATS)); 955 } 956 957 static void 958 sysctl_net_inet6_raw6_setup(struct sysctllog **clog) 959 { 960 961 sysctl_createv(clog, 0, NULL, NULL, 962 CTLFLAG_PERMANENT, 963 CTLTYPE_NODE, "inet6", NULL, 964 NULL, 0, NULL, 0, 965 CTL_NET, PF_INET6, CTL_EOL); 966 sysctl_createv(clog, 0, NULL, NULL, 967 CTLFLAG_PERMANENT, 968 CTLTYPE_NODE, "raw6", 969 SYSCTL_DESCR("Raw IPv6 settings"), 970 NULL, 0, NULL, 0, 971 CTL_NET, PF_INET6, IPPROTO_RAW, CTL_EOL); 972 973 sysctl_createv(clog, 0, NULL, NULL, 974 CTLFLAG_PERMANENT, 975 CTLTYPE_STRUCT, "pcblist", 976 SYSCTL_DESCR("Raw IPv6 control block list"), 977 sysctl_inpcblist, 0, &raw6cbtable, 0, 978 CTL_NET, PF_INET6, IPPROTO_RAW, 979 CTL_CREATE, CTL_EOL); 980 sysctl_createv(clog, 0, NULL, NULL, 981 CTLFLAG_PERMANENT, 982 CTLTYPE_STRUCT, "stats", 983 SYSCTL_DESCR("Raw IPv6 statistics"), 984 sysctl_net_inet6_raw6_stats, 0, NULL, 0, 985 CTL_NET, PF_INET6, IPPROTO_RAW, RAW6CTL_STATS, 986 CTL_EOL); 987 } 988 989 PR_WRAP_USRREQS(rip6) 990 #define rip6_attach rip6_attach_wrapper 991 #define rip6_detach rip6_detach_wrapper 992 #define rip6_accept rip6_accept_wrapper 993 #define rip6_bind rip6_bind_wrapper 994 #define rip6_listen rip6_listen_wrapper 995 #define rip6_connect rip6_connect_wrapper 996 #define rip6_connect2 rip6_connect2_wrapper 997 #define rip6_disconnect rip6_disconnect_wrapper 998 #define rip6_shutdown rip6_shutdown_wrapper 999 #define rip6_abort rip6_abort_wrapper 1000 #define rip6_ioctl rip6_ioctl_wrapper 1001 #define rip6_stat rip6_stat_wrapper 1002 #define rip6_peeraddr rip6_peeraddr_wrapper 1003 #define rip6_sockaddr rip6_sockaddr_wrapper 1004 #define rip6_rcvd rip6_rcvd_wrapper 1005 #define rip6_recvoob rip6_recvoob_wrapper 1006 #define rip6_send rip6_send_wrapper 1007 #define rip6_sendoob rip6_sendoob_wrapper 1008 #define rip6_purgeif rip6_purgeif_wrapper 1009 1010 const struct pr_usrreqs rip6_usrreqs = { 1011 .pr_attach = rip6_attach, 1012 .pr_detach = rip6_detach, 1013 .pr_accept = rip6_accept, 1014 .pr_bind = rip6_bind, 1015 .pr_listen = rip6_listen, 1016 .pr_connect = rip6_connect, 1017 .pr_connect2 = rip6_connect2, 1018 .pr_disconnect = rip6_disconnect, 1019 .pr_shutdown = rip6_shutdown, 1020 .pr_abort = rip6_abort, 1021 .pr_ioctl = rip6_ioctl, 1022 .pr_stat = rip6_stat, 1023 .pr_peeraddr = rip6_peeraddr, 1024 .pr_sockaddr = rip6_sockaddr, 1025 .pr_rcvd = rip6_rcvd, 1026 .pr_recvoob = rip6_recvoob, 1027 .pr_send = rip6_send, 1028 .pr_sendoob = rip6_sendoob, 1029 .pr_purgeif = rip6_purgeif, 1030 }; 1031