1 /* $NetBSD: raw_ip6.c,v 1.107 2010/07/08 01:22:28 dyoung 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.107 2010/07/08 01:22:28 dyoung Exp $"); 66 67 #include "opt_ipsec.h" 68 69 #include <sys/param.h> 70 #include <sys/sysctl.h> 71 #include <sys/malloc.h> 72 #include <sys/mbuf.h> 73 #include <sys/socket.h> 74 #include <sys/protosw.h> 75 #include <sys/socketvar.h> 76 #include <sys/errno.h> 77 #include <sys/systm.h> 78 #include <sys/proc.h> 79 #include <sys/kauth.h> 80 81 #include <net/if.h> 82 #include <net/route.h> 83 #include <net/if_types.h> 84 #include <net/net_stats.h> 85 86 #include <netinet/in.h> 87 #include <netinet/in_var.h> 88 #include <netinet/ip6.h> 89 #include <netinet6/ip6_var.h> 90 #include <netinet6/ip6_private.h> 91 #include <netinet6/ip6_mroute.h> 92 #include <netinet/icmp6.h> 93 #include <netinet6/icmp6_private.h> 94 #include <netinet6/in6_pcb.h> 95 #include <netinet6/nd6.h> 96 #include <netinet6/ip6protosw.h> 97 #include <netinet6/scope6_var.h> 98 #include <netinet6/raw_ip6.h> 99 100 #ifdef IPSEC 101 #include <netinet6/ipsec.h> 102 #include <netinet6/ipsec_private.h> 103 #endif /* IPSEC */ 104 105 #ifdef FAST_IPSEC 106 #include <netipsec/ipsec.h> 107 #include <netipsec/ipsec_var.h> 108 #include <netipsec/ipsec_private.h> 109 #include <netipsec/ipsec6.h> 110 #endif 111 112 #include "faith.h" 113 #if defined(NFAITH) && 0 < NFAITH 114 #include <net/if_faith.h> 115 #endif 116 117 extern struct inpcbtable rawcbtable; 118 struct inpcbtable raw6cbtable; 119 #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) 120 121 /* 122 * Raw interface to IP6 protocol. 123 */ 124 125 static percpu_t *rip6stat_percpu; 126 127 #define RIP6_STATINC(x) _NET_STATINC(rip6stat_percpu, x) 128 129 static void sysctl_net_inet6_raw6_setup(struct sysctllog **); 130 131 /* 132 * Initialize raw connection block queue. 133 */ 134 void 135 rip6_init(void) 136 { 137 138 sysctl_net_inet6_raw6_setup(NULL); 139 in6_pcbinit(&raw6cbtable, 1, 1); 140 141 rip6stat_percpu = percpu_alloc(sizeof(uint64_t) * RIP6_NSTATS); 142 } 143 144 /* 145 * Setup generic address and protocol structures 146 * for raw_input routine, then pass them along with 147 * mbuf chain. 148 */ 149 int 150 rip6_input(struct mbuf **mp, int *offp, int proto) 151 { 152 struct mbuf *m = *mp; 153 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 154 struct inpcb_hdr *inph; 155 struct in6pcb *in6p; 156 struct in6pcb *last = NULL; 157 struct sockaddr_in6 rip6src; 158 struct mbuf *opts = NULL; 159 160 RIP6_STATINC(RIP6_STAT_IPACKETS); 161 162 #if defined(NFAITH) && 0 < NFAITH 163 if (faithprefix(&ip6->ip6_dst)) { 164 /* send icmp6 host unreach? */ 165 m_freem(m); 166 return IPPROTO_DONE; 167 } 168 #endif 169 170 /* Be proactive about malicious use of IPv4 mapped address */ 171 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || 172 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { 173 /* XXX stat */ 174 m_freem(m); 175 return IPPROTO_DONE; 176 } 177 178 sockaddr_in6_init(&rip6src, &ip6->ip6_src, 0, 0, 0); 179 if (sa6_recoverscope(&rip6src) != 0) { 180 /* XXX: should be impossible. */ 181 m_freem(m); 182 return IPPROTO_DONE; 183 } 184 185 CIRCLEQ_FOREACH(inph, &raw6cbtable.inpt_queue, inph_queue) { 186 in6p = (struct in6pcb *)inph; 187 if (in6p->in6p_af != AF_INET6) 188 continue; 189 if (in6p->in6p_ip6.ip6_nxt && 190 in6p->in6p_ip6.ip6_nxt != proto) 191 continue; 192 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 193 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 194 continue; 195 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 196 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 197 continue; 198 if (in6p->in6p_cksum != -1) { 199 RIP6_STATINC(RIP6_STAT_ISUM); 200 if (in6_cksum(m, proto, *offp, 201 m->m_pkthdr.len - *offp)) { 202 RIP6_STATINC(RIP6_STAT_BADSUM); 203 continue; 204 } 205 } 206 if (last) { 207 struct mbuf *n; 208 209 #ifdef IPSEC 210 /* 211 * Check AH/ESP integrity. 212 */ 213 if (ipsec6_in_reject(m, last)) { 214 IPSEC6_STATINC(IPSEC_STAT_IN_INVAL); 215 /* do not inject data into pcb */ 216 } else 217 #endif /* IPSEC */ 218 #ifdef FAST_IPSEC 219 /* 220 * Check AH/ESP integrity 221 */ 222 if (!ipsec6_in_reject(m,last)) 223 #endif /* FAST_IPSEC */ 224 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 225 if (last->in6p_flags & IN6P_CONTROLOPTS) 226 ip6_savecontrol(last, &opts, ip6, n); 227 /* strip intermediate headers */ 228 m_adj(n, *offp); 229 if (sbappendaddr(&last->in6p_socket->so_rcv, 230 (struct sockaddr *)&rip6src, n, opts) == 0) { 231 /* should notify about lost packet */ 232 m_freem(n); 233 if (opts) 234 m_freem(opts); 235 RIP6_STATINC(RIP6_STAT_FULLSOCK); 236 } else 237 sorwakeup(last->in6p_socket); 238 opts = NULL; 239 } 240 } 241 last = in6p; 242 } 243 #ifdef IPSEC 244 /* 245 * Check AH/ESP integrity. 246 */ 247 if (last && ipsec6_in_reject(m, last)) { 248 m_freem(m); 249 IPSEC6_STATINC(IPSEC_STAT_IN_INVAL); 250 IP6_STATDEC(IP6_STAT_DELIVERED); 251 /* do not inject data into pcb */ 252 } else 253 #endif /* IPSEC */ 254 #ifdef FAST_IPSEC 255 if (last && ipsec6_in_reject(m, last)) { 256 m_freem(m); 257 /* 258 * XXX ipsec6_in_reject update stat if there is an error 259 * so we just need to update stats by hand in the case of last is 260 * NULL 261 */ 262 if (!last) 263 IPSEC6_STATINC(IPSEC_STAT_IN_POLVIO); 264 IP6_STATDEC(IP6_STAT_DELIVERED); 265 /* do not inject data into pcb */ 266 } else 267 #endif /* FAST_IPSEC */ 268 if (last) { 269 if (last->in6p_flags & IN6P_CONTROLOPTS) 270 ip6_savecontrol(last, &opts, ip6, m); 271 /* strip intermediate headers */ 272 m_adj(m, *offp); 273 if (sbappendaddr(&last->in6p_socket->so_rcv, 274 (struct sockaddr *)&rip6src, m, opts) == 0) { 275 m_freem(m); 276 if (opts) 277 m_freem(opts); 278 RIP6_STATINC(RIP6_STAT_FULLSOCK); 279 } else 280 sorwakeup(last->in6p_socket); 281 } else { 282 RIP6_STATINC(RIP6_STAT_NOSOCK); 283 if (m->m_flags & M_MCAST) 284 RIP6_STATINC(RIP6_STAT_NOSOCKMCAST); 285 if (proto == IPPROTO_NONE) 286 m_freem(m); 287 else { 288 u_int8_t *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ 289 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_protounknown); 290 icmp6_error(m, ICMP6_PARAM_PROB, 291 ICMP6_PARAMPROB_NEXTHEADER, 292 prvnxtp - mtod(m, u_int8_t *)); 293 } 294 IP6_STATDEC(IP6_STAT_DELIVERED); 295 } 296 return IPPROTO_DONE; 297 } 298 299 void * 300 rip6_ctlinput(int cmd, const struct sockaddr *sa, void *d) 301 { 302 struct ip6_hdr *ip6; 303 struct ip6ctlparam *ip6cp = NULL; 304 const struct sockaddr_in6 *sa6_src = NULL; 305 void *cmdarg; 306 void (*notify)(struct in6pcb *, int) = in6_rtchange; 307 int nxt; 308 309 if (sa->sa_family != AF_INET6 || 310 sa->sa_len != sizeof(struct sockaddr_in6)) 311 return NULL; 312 313 if ((unsigned)cmd >= PRC_NCMDS) 314 return NULL; 315 if (PRC_IS_REDIRECT(cmd)) 316 notify = in6_rtchange, d = NULL; 317 else if (cmd == PRC_HOSTDEAD) 318 d = NULL; 319 else if (cmd == PRC_MSGSIZE) 320 ; /* special code is present, see below */ 321 else if (inet6ctlerrmap[cmd] == 0) 322 return NULL; 323 324 /* if the parameter is from icmp6, decode it. */ 325 if (d != NULL) { 326 ip6cp = (struct ip6ctlparam *)d; 327 ip6 = ip6cp->ip6c_ip6; 328 cmdarg = ip6cp->ip6c_cmdarg; 329 sa6_src = ip6cp->ip6c_src; 330 nxt = ip6cp->ip6c_nxt; 331 } else { 332 ip6 = NULL; 333 cmdarg = NULL; 334 sa6_src = &sa6_any; 335 nxt = -1; 336 } 337 338 if (ip6 && cmd == PRC_MSGSIZE) { 339 const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *)sa; 340 int valid = 0; 341 struct in6pcb *in6p; 342 343 /* 344 * Check to see if we have a valid raw IPv6 socket 345 * corresponding to the address in the ICMPv6 message 346 * payload, and the protocol (ip6_nxt) meets the socket. 347 * XXX chase extension headers, or pass final nxt value 348 * from icmp6_notify_error() 349 */ 350 in6p = NULL; 351 in6p = in6_pcblookup_connect(&raw6cbtable, &sa6->sin6_addr, 0, 352 (const struct in6_addr *)&sa6_src->sin6_addr, 0, 0); 353 #if 0 354 if (!in6p) { 355 /* 356 * As the use of sendto(2) is fairly popular, 357 * we may want to allow non-connected pcb too. 358 * But it could be too weak against attacks... 359 * We should at least check if the local 360 * address (= s) is really ours. 361 */ 362 in6p = in6_pcblookup_bind(&raw6cbtable, 363 &sa6->sin6_addr, 0, 0); 364 } 365 #endif 366 367 if (in6p && in6p->in6p_ip6.ip6_nxt && 368 in6p->in6p_ip6.ip6_nxt == nxt) 369 valid++; 370 371 /* 372 * Depending on the value of "valid" and routing table 373 * size (mtudisc_{hi,lo}wat), we will: 374 * - recalculate the new MTU and create the 375 * corresponding routing entry, or 376 * - ignore the MTU change notification. 377 */ 378 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 379 380 /* 381 * regardless of if we called icmp6_mtudisc_update(), 382 * we need to call in6_pcbnotify(), to notify path MTU 383 * change to the userland (RFC3542), because some 384 * unconnected sockets may share the same destination 385 * and want to know the path MTU. 386 */ 387 } 388 389 (void) in6_pcbnotify(&raw6cbtable, sa, 0, 390 (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify); 391 return NULL; 392 } 393 394 /* 395 * Generate IPv6 header and pass packet to ip6_output. 396 * Tack on options user may have setup with control call. 397 */ 398 int 399 rip6_output(struct mbuf *m, struct socket * const so, 400 struct sockaddr_in6 * const dstsock, struct mbuf * const control) 401 { 402 struct in6_addr *dst; 403 struct ip6_hdr *ip6; 404 struct in6pcb *in6p; 405 u_int plen = m->m_pkthdr.len; 406 int error = 0; 407 struct ip6_pktopts opt, *optp = NULL; 408 struct ifnet *oifp = NULL; 409 int type, code; /* for ICMPv6 output statistics only */ 410 int scope_ambiguous = 0; 411 struct in6_addr *in6a; 412 413 in6p = sotoin6pcb(so); 414 415 dst = &dstsock->sin6_addr; 416 if (control) { 417 if ((error = ip6_setpktopts(control, &opt, 418 in6p->in6p_outputopts, 419 kauth_cred_get(), so->so_proto->pr_protocol)) != 0) { 420 goto bad; 421 } 422 optp = &opt; 423 } else 424 optp = in6p->in6p_outputopts; 425 426 /* 427 * Check and convert scope zone ID into internal form. 428 * XXX: we may still need to determine the zone later. 429 */ 430 if (!(so->so_state & SS_ISCONNECTED)) { 431 if (dstsock->sin6_scope_id == 0 && !ip6_use_defzone) 432 scope_ambiguous = 1; 433 if ((error = sa6_embedscope(dstsock, ip6_use_defzone)) != 0) 434 goto bad; 435 } 436 437 /* 438 * For an ICMPv6 packet, we should know its type and code 439 * to update statistics. 440 */ 441 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 442 struct icmp6_hdr *icmp6; 443 if (m->m_len < sizeof(struct icmp6_hdr) && 444 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) { 445 error = ENOBUFS; 446 goto bad; 447 } 448 icmp6 = mtod(m, struct icmp6_hdr *); 449 type = icmp6->icmp6_type; 450 code = icmp6->icmp6_code; 451 } else { 452 type = 0; 453 code = 0; 454 } 455 456 M_PREPEND(m, sizeof(*ip6), M_DONTWAIT); 457 if (!m) { 458 error = ENOBUFS; 459 goto bad; 460 } 461 ip6 = mtod(m, struct ip6_hdr *); 462 463 /* 464 * Next header might not be ICMP6 but use its pseudo header anyway. 465 */ 466 ip6->ip6_dst = *dst; 467 468 /* 469 * Source address selection. 470 */ 471 if ((in6a = in6_selectsrc(dstsock, optp, in6p->in6p_moptions, 472 &in6p->in6p_route, &in6p->in6p_laddr, &oifp, 473 &error)) == 0) { 474 if (error == 0) 475 error = EADDRNOTAVAIL; 476 goto bad; 477 } 478 ip6->ip6_src = *in6a; 479 480 if (oifp && scope_ambiguous) { 481 /* 482 * Application should provide a proper zone ID or the use of 483 * default zone IDs should be enabled. Unfortunately, some 484 * applications do not behave as it should, so we need a 485 * workaround. Even if an appropriate ID is not determined 486 * (when it's required), if we can determine the outgoing 487 * interface. determine the zone ID based on the interface. 488 */ 489 error = in6_setscope(&dstsock->sin6_addr, oifp, NULL); 490 if (error != 0) 491 goto bad; 492 } 493 ip6->ip6_dst = dstsock->sin6_addr; 494 495 /* fill in the rest of the IPv6 header fields */ 496 ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK; 497 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 498 ip6->ip6_vfc |= IPV6_VERSION; 499 /* ip6_plen will be filled in ip6_output, so not fill it here. */ 500 ip6->ip6_nxt = in6p->in6p_ip6.ip6_nxt; 501 ip6->ip6_hlim = in6_selecthlim(in6p, oifp); 502 503 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 || 504 in6p->in6p_cksum != -1) { 505 int off; 506 u_int16_t sum; 507 508 /* compute checksum */ 509 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) 510 off = offsetof(struct icmp6_hdr, icmp6_cksum); 511 else 512 off = in6p->in6p_cksum; 513 if (plen < off + 1) { 514 error = EINVAL; 515 goto bad; 516 } 517 off += sizeof(struct ip6_hdr); 518 519 sum = 0; 520 m = m_copyback_cow(m, off, sizeof(sum), (void *)&sum, 521 M_DONTWAIT); 522 if (m == NULL) { 523 error = ENOBUFS; 524 goto bad; 525 } 526 sum = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen); 527 m = m_copyback_cow(m, off, sizeof(sum), (void *)&sum, 528 M_DONTWAIT); 529 if (m == NULL) { 530 error = ENOBUFS; 531 goto bad; 532 } 533 } 534 535 error = ip6_output(m, optp, &in6p->in6p_route, 0, 536 in6p->in6p_moptions, so, &oifp); 537 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 538 if (oifp) 539 icmp6_ifoutstat_inc(oifp, type, code); 540 ICMP6_STATINC(ICMP6_STAT_OUTHIST + type); 541 } else 542 RIP6_STATINC(RIP6_STAT_OPACKETS); 543 544 goto freectl; 545 546 bad: 547 if (m) 548 m_freem(m); 549 550 freectl: 551 if (control) { 552 ip6_clearpktopts(&opt, -1); 553 m_freem(control); 554 } 555 return error; 556 } 557 558 /* 559 * Raw IPv6 socket option processing. 560 */ 561 int 562 rip6_ctloutput(int op, struct socket *so, struct sockopt *sopt) 563 { 564 int error = 0; 565 566 if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) { 567 int optval; 568 569 /* need to fiddle w/ opt(IPPROTO_IPV6, IPV6_CHECKSUM)? */ 570 if (op == PRCO_GETOPT) { 571 optval = 1; 572 error = sockopt_set(sopt, &optval, sizeof(optval)); 573 } else if (op == PRCO_SETOPT) { 574 error = sockopt_getint(sopt, &optval); 575 if (error) 576 goto out; 577 if (optval == 0) 578 error = EINVAL; 579 } 580 581 goto out; 582 } else if (sopt->sopt_level != IPPROTO_IPV6) 583 return ip6_ctloutput(op, so, sopt); 584 585 switch (sopt->sopt_name) { 586 case MRT6_INIT: 587 case MRT6_DONE: 588 case MRT6_ADD_MIF: 589 case MRT6_DEL_MIF: 590 case MRT6_ADD_MFC: 591 case MRT6_DEL_MFC: 592 case MRT6_PIM: 593 if (op == PRCO_SETOPT) 594 error = ip6_mrouter_set(so, sopt); 595 else if (op == PRCO_GETOPT) 596 error = ip6_mrouter_get(so, sopt); 597 else 598 error = EINVAL; 599 break; 600 case IPV6_CHECKSUM: 601 return ip6_raw_ctloutput(op, so, sopt); 602 default: 603 return ip6_ctloutput(op, so, sopt); 604 } 605 out: 606 return error; 607 } 608 609 extern u_long rip6_sendspace; 610 extern u_long rip6_recvspace; 611 612 int 613 rip6_usrreq(struct socket *so, int req, struct mbuf *m, 614 struct mbuf *nam, struct mbuf *control, struct lwp *l) 615 { 616 struct in6pcb *in6p = sotoin6pcb(so); 617 int s; 618 int error = 0; 619 620 if (req == PRU_CONTROL) 621 return in6_control(so, (u_long)m, (void *)nam, 622 (struct ifnet *)control, l); 623 624 if (req == PRU_PURGEIF) { 625 mutex_enter(softnet_lock); 626 in6_pcbpurgeif0(&raw6cbtable, (struct ifnet *)control); 627 in6_purgeif((struct ifnet *)control); 628 in6_pcbpurgeif(&raw6cbtable, (struct ifnet *)control); 629 mutex_exit(softnet_lock); 630 return 0; 631 } 632 633 switch (req) { 634 case PRU_ATTACH: 635 error = kauth_authorize_network(l->l_cred, 636 KAUTH_NETWORK_SOCKET, KAUTH_REQ_NETWORK_SOCKET_RAWSOCK, 637 NULL, NULL, NULL); 638 sosetlock(so); 639 if (in6p != NULL) 640 panic("rip6_attach"); 641 if (error) { 642 break; 643 } 644 s = splsoftnet(); 645 error = soreserve(so, rip6_sendspace, rip6_recvspace); 646 if (error != 0) { 647 splx(s); 648 break; 649 } 650 if ((error = in6_pcballoc(so, &raw6cbtable)) != 0) { 651 splx(s); 652 break; 653 } 654 splx(s); 655 in6p = sotoin6pcb(so); 656 in6p->in6p_ip6.ip6_nxt = (long)nam; 657 in6p->in6p_cksum = -1; 658 659 in6p->in6p_icmp6filt = malloc(sizeof(struct icmp6_filter), 660 M_PCB, M_NOWAIT); 661 if (in6p->in6p_icmp6filt == NULL) { 662 in6_pcbdetach(in6p); 663 error = ENOMEM; 664 break; 665 } 666 ICMP6_FILTER_SETPASSALL(in6p->in6p_icmp6filt); 667 break; 668 669 case PRU_DISCONNECT: 670 if ((so->so_state & SS_ISCONNECTED) == 0) { 671 error = ENOTCONN; 672 break; 673 } 674 in6p->in6p_faddr = in6addr_any; 675 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 676 break; 677 678 case PRU_ABORT: 679 soisdisconnected(so); 680 /* Fallthrough */ 681 case PRU_DETACH: 682 if (in6p == NULL) 683 panic("rip6_detach"); 684 if (so == ip6_mrouter) 685 ip6_mrouter_done(); 686 /* xxx: RSVP */ 687 if (in6p->in6p_icmp6filt != NULL) { 688 free(in6p->in6p_icmp6filt, M_PCB); 689 in6p->in6p_icmp6filt = NULL; 690 } 691 in6_pcbdetach(in6p); 692 break; 693 694 case PRU_BIND: 695 { 696 struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *); 697 struct ifaddr *ia = NULL; 698 699 if (nam->m_len != sizeof(*addr)) { 700 error = EINVAL; 701 break; 702 } 703 if (TAILQ_EMPTY(&ifnet) || addr->sin6_family != AF_INET6) { 704 error = EADDRNOTAVAIL; 705 break; 706 } 707 if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0) 708 break; 709 710 /* 711 * we don't support mapped address here, it would confuse 712 * users so reject it 713 */ 714 if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) { 715 error = EADDRNOTAVAIL; 716 break; 717 } 718 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && 719 (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) { 720 error = EADDRNOTAVAIL; 721 break; 722 } 723 if (ia && ((struct in6_ifaddr *)ia)->ia6_flags & 724 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| 725 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { 726 error = EADDRNOTAVAIL; 727 break; 728 } 729 in6p->in6p_laddr = addr->sin6_addr; 730 break; 731 } 732 733 case PRU_CONNECT: 734 { 735 struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *); 736 struct in6_addr *in6a = NULL; 737 struct ifnet *ifp = NULL; 738 int scope_ambiguous = 0; 739 740 if (nam->m_len != sizeof(*addr)) { 741 error = EINVAL; 742 break; 743 } 744 if (TAILQ_EMPTY(&ifnet)) { 745 error = EADDRNOTAVAIL; 746 break; 747 } 748 if (addr->sin6_family != AF_INET6) { 749 error = EAFNOSUPPORT; 750 break; 751 } 752 753 /* 754 * Application should provide a proper zone ID or the use of 755 * default zone IDs should be enabled. Unfortunately, some 756 * applications do not behave as it should, so we need a 757 * workaround. Even if an appropriate ID is not determined, 758 * we'll see if we can determine the outgoing interface. If we 759 * can, determine the zone ID based on the interface below. 760 */ 761 if (addr->sin6_scope_id == 0 && !ip6_use_defzone) 762 scope_ambiguous = 1; 763 if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0) 764 return error; 765 766 /* Source address selection. XXX: need pcblookup? */ 767 in6a = in6_selectsrc(addr, in6p->in6p_outputopts, 768 in6p->in6p_moptions, &in6p->in6p_route, 769 &in6p->in6p_laddr, &ifp, &error); 770 if (in6a == NULL) { 771 if (error == 0) 772 error = EADDRNOTAVAIL; 773 break; 774 } 775 /* XXX: see above */ 776 if (ifp && scope_ambiguous && 777 (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) { 778 break; 779 } 780 in6p->in6p_laddr = *in6a; 781 in6p->in6p_faddr = addr->sin6_addr; 782 soisconnected(so); 783 break; 784 } 785 786 case PRU_CONNECT2: 787 error = EOPNOTSUPP; 788 break; 789 790 /* 791 * Mark the connection as being incapable of futther input. 792 */ 793 case PRU_SHUTDOWN: 794 socantsendmore(so); 795 break; 796 /* 797 * Ship a packet out. The appropriate raw output 798 * routine handles any messaging necessary. 799 */ 800 case PRU_SEND: 801 { 802 struct sockaddr_in6 tmp; 803 struct sockaddr_in6 *dst; 804 805 /* always copy sockaddr to avoid overwrites */ 806 if (so->so_state & SS_ISCONNECTED) { 807 if (nam) { 808 error = EISCONN; 809 break; 810 } 811 /* XXX */ 812 sockaddr_in6_init(&tmp, &in6p->in6p_faddr, 0, 0, 0); 813 dst = &tmp; 814 } else { 815 if (nam == NULL) { 816 error = ENOTCONN; 817 break; 818 } 819 if (nam->m_len != sizeof(tmp)) { 820 error = EINVAL; 821 break; 822 } 823 824 tmp = *mtod(nam, struct sockaddr_in6 *); 825 dst = &tmp; 826 827 if (dst->sin6_family != AF_INET6) { 828 error = EAFNOSUPPORT; 829 break; 830 } 831 } 832 error = rip6_output(m, so, dst, control); 833 m = NULL; 834 break; 835 } 836 837 case PRU_SENSE: 838 /* 839 * stat: don't bother with a blocksize 840 */ 841 return 0; 842 /* 843 * Not supported. 844 */ 845 case PRU_RCVOOB: 846 case PRU_RCVD: 847 case PRU_LISTEN: 848 case PRU_ACCEPT: 849 case PRU_SENDOOB: 850 error = EOPNOTSUPP; 851 break; 852 853 case PRU_SOCKADDR: 854 in6_setsockaddr(in6p, nam); 855 break; 856 857 case PRU_PEERADDR: 858 in6_setpeeraddr(in6p, nam); 859 break; 860 861 default: 862 panic("rip6_usrreq"); 863 } 864 if (m != NULL) 865 m_freem(m); 866 return error; 867 } 868 869 static int 870 sysctl_net_inet6_raw6_stats(SYSCTLFN_ARGS) 871 { 872 873 return (NETSTAT_SYSCTL(rip6stat_percpu, RIP6_NSTATS)); 874 } 875 876 static void 877 sysctl_net_inet6_raw6_setup(struct sysctllog **clog) 878 { 879 880 sysctl_createv(clog, 0, NULL, NULL, 881 CTLFLAG_PERMANENT, 882 CTLTYPE_NODE, "net", NULL, 883 NULL, 0, NULL, 0, 884 CTL_NET, CTL_EOL); 885 sysctl_createv(clog, 0, NULL, NULL, 886 CTLFLAG_PERMANENT, 887 CTLTYPE_NODE, "inet6", NULL, 888 NULL, 0, NULL, 0, 889 CTL_NET, PF_INET6, CTL_EOL); 890 sysctl_createv(clog, 0, NULL, NULL, 891 CTLFLAG_PERMANENT, 892 CTLTYPE_NODE, "raw6", 893 SYSCTL_DESCR("Raw IPv6 settings"), 894 NULL, 0, NULL, 0, 895 CTL_NET, PF_INET6, IPPROTO_RAW, CTL_EOL); 896 897 sysctl_createv(clog, 0, NULL, NULL, 898 CTLFLAG_PERMANENT, 899 CTLTYPE_STRUCT, "pcblist", 900 SYSCTL_DESCR("Raw IPv6 control block list"), 901 sysctl_inpcblist, 0, &raw6cbtable, 0, 902 CTL_NET, PF_INET6, IPPROTO_RAW, 903 CTL_CREATE, CTL_EOL); 904 sysctl_createv(clog, 0, NULL, NULL, 905 CTLFLAG_PERMANENT, 906 CTLTYPE_STRUCT, "stats", 907 SYSCTL_DESCR("Raw IPv6 statistics"), 908 sysctl_net_inet6_raw6_stats, 0, NULL, 0, 909 CTL_NET, PF_INET6, IPPROTO_RAW, RAW6CTL_STATS, 910 CTL_EOL); 911 } 912