1 /*- 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /*- 31 * Copyright (c) 1982, 1986, 1988, 1993 32 * The Regents of the University of California. 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 4. Neither the name of the University nor the names of its contributors 44 * may be used to endorse or promote products derived from this software 45 * without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 * 59 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 60 */ 61 62 #include <sys/cdefs.h> 63 __FBSDID("$FreeBSD$"); 64 65 #include "opt_ipsec.h" 66 #include "opt_inet6.h" 67 68 #include <sys/param.h> 69 #include <sys/errno.h> 70 #include <sys/jail.h> 71 #include <sys/lock.h> 72 #include <sys/malloc.h> 73 #include <sys/mbuf.h> 74 #include <sys/priv.h> 75 #include <sys/proc.h> 76 #include <sys/protosw.h> 77 #include <sys/signalvar.h> 78 #include <sys/socket.h> 79 #include <sys/socketvar.h> 80 #include <sys/sx.h> 81 #include <sys/syslog.h> 82 83 #include <net/if.h> 84 #include <net/if_types.h> 85 #include <net/route.h> 86 #include <net/vnet.h> 87 88 #include <netinet/in.h> 89 #include <netinet/in_var.h> 90 #include <netinet/in_systm.h> 91 #include <netinet/in_pcb.h> 92 93 #include <netinet/icmp6.h> 94 #include <netinet/ip6.h> 95 #include <netinet6/ip6protosw.h> 96 #include <netinet6/ip6_mroute.h> 97 #include <netinet6/in6_pcb.h> 98 #include <netinet6/ip6_var.h> 99 #include <netinet6/nd6.h> 100 #include <netinet6/raw_ip6.h> 101 #include <netinet6/scope6_var.h> 102 103 #ifdef IPSEC 104 #include <netipsec/ipsec.h> 105 #include <netipsec/ipsec6.h> 106 #endif /* IPSEC */ 107 108 #include <machine/stdarg.h> 109 110 #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) 111 #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) 112 113 /* 114 * Raw interface to IP6 protocol. 115 */ 116 117 VNET_DECLARE(struct inpcbhead, ripcb); 118 VNET_DECLARE(struct inpcbinfo, ripcbinfo); 119 #define V_ripcb VNET(ripcb) 120 #define V_ripcbinfo VNET(ripcbinfo) 121 122 VNET_DEFINE(struct rip6stat, rip6stat); 123 124 extern u_long rip_sendspace; 125 extern u_long rip_recvspace; 126 127 /* 128 * Hooks for multicast routing. They all default to NULL, so leave them not 129 * initialized and rely on BSS being set to 0. 130 */ 131 132 /* 133 * The socket used to communicate with the multicast routing daemon. 134 */ 135 VNET_DEFINE(struct socket *, ip6_mrouter); 136 137 /* 138 * The various mrouter functions. 139 */ 140 int (*ip6_mrouter_set)(struct socket *, struct sockopt *); 141 int (*ip6_mrouter_get)(struct socket *, struct sockopt *); 142 int (*ip6_mrouter_done)(void); 143 int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *); 144 int (*mrt6_ioctl)(u_long, caddr_t); 145 146 /* 147 * Setup generic address and protocol structures for raw_input routine, then 148 * pass them along with mbuf chain. 149 */ 150 int 151 rip6_input(struct mbuf **mp, int *offp, int proto) 152 { 153 struct ifnet *ifp; 154 struct mbuf *m = *mp; 155 register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 156 register struct inpcb *in6p; 157 struct inpcb *last = 0; 158 struct mbuf *opts = NULL; 159 struct sockaddr_in6 fromsa; 160 161 V_rip6stat.rip6s_ipackets++; 162 163 if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { 164 /* XXX Send icmp6 host/port unreach? */ 165 m_freem(m); 166 return (IPPROTO_DONE); 167 } 168 169 init_sin6(&fromsa, m); /* general init */ 170 171 ifp = m->m_pkthdr.rcvif; 172 173 INP_INFO_RLOCK(&V_ripcbinfo); 174 LIST_FOREACH(in6p, &V_ripcb, inp_list) { 175 /* XXX inp locking */ 176 if ((in6p->inp_vflag & INP_IPV6) == 0) 177 continue; 178 if (in6p->inp_ip_p && 179 in6p->inp_ip_p != proto) 180 continue; 181 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 182 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 183 continue; 184 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 185 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 186 continue; 187 if (jailed(in6p->inp_cred)) { 188 /* 189 * Allow raw socket in jail to receive multicast; 190 * assume process had PRIV_NETINET_RAW at attach, 191 * and fall through into normal filter path if so. 192 */ 193 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && 194 prison_check_ip6(in6p->inp_cred, 195 &ip6->ip6_dst) != 0) 196 continue; 197 } 198 if (in6p->in6p_cksum != -1) { 199 V_rip6stat.rip6s_isum++; 200 if (in6_cksum(m, proto, *offp, 201 m->m_pkthdr.len - *offp)) { 202 INP_RUNLOCK(in6p); 203 V_rip6stat.rip6s_badsum++; 204 continue; 205 } 206 } 207 INP_RLOCK(in6p); 208 /* 209 * If this raw socket has multicast state, and we 210 * have received a multicast, check if this socket 211 * should receive it, as multicast filtering is now 212 * the responsibility of the transport layer. 213 */ 214 if (in6p->in6p_moptions && 215 IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 216 struct sockaddr_in6 mcaddr; 217 int blocked; 218 219 bzero(&mcaddr, sizeof(struct sockaddr_in6)); 220 mcaddr.sin6_len = sizeof(struct sockaddr_in6); 221 mcaddr.sin6_family = AF_INET6; 222 mcaddr.sin6_addr = ip6->ip6_dst; 223 224 blocked = im6o_mc_filter(in6p->in6p_moptions, ifp, 225 (struct sockaddr *)&mcaddr, 226 (struct sockaddr *)&fromsa); 227 if (blocked != MCAST_PASS) { 228 IP6STAT_INC(ip6s_notmember); 229 continue; 230 } 231 } 232 if (last != NULL) { 233 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 234 235 #ifdef IPSEC 236 /* 237 * Check AH/ESP integrity. 238 */ 239 if (n && ipsec6_in_reject(n, last)) { 240 m_freem(n); 241 V_ipsec6stat.in_polvio++; 242 /* Do not inject data into pcb. */ 243 } else 244 #endif /* IPSEC */ 245 if (n) { 246 if (last->inp_flags & INP_CONTROLOPTS || 247 last->inp_socket->so_options & SO_TIMESTAMP) 248 ip6_savecontrol(last, n, &opts); 249 /* strip intermediate headers */ 250 m_adj(n, *offp); 251 if (sbappendaddr(&last->inp_socket->so_rcv, 252 (struct sockaddr *)&fromsa, 253 n, opts) == 0) { 254 m_freem(n); 255 if (opts) 256 m_freem(opts); 257 V_rip6stat.rip6s_fullsock++; 258 } else 259 sorwakeup(last->inp_socket); 260 opts = NULL; 261 } 262 INP_RUNLOCK(last); 263 } 264 last = in6p; 265 } 266 INP_INFO_RUNLOCK(&V_ripcbinfo); 267 #ifdef IPSEC 268 /* 269 * Check AH/ESP integrity. 270 */ 271 if ((last != NULL) && ipsec6_in_reject(m, last)) { 272 m_freem(m); 273 V_ipsec6stat.in_polvio++; 274 V_ip6stat.ip6s_delivered--; 275 /* Do not inject data into pcb. */ 276 INP_RUNLOCK(last); 277 } else 278 #endif /* IPSEC */ 279 if (last != NULL) { 280 if (last->inp_flags & INP_CONTROLOPTS || 281 last->inp_socket->so_options & SO_TIMESTAMP) 282 ip6_savecontrol(last, m, &opts); 283 /* Strip intermediate headers. */ 284 m_adj(m, *offp); 285 if (sbappendaddr(&last->inp_socket->so_rcv, 286 (struct sockaddr *)&fromsa, m, opts) == 0) { 287 m_freem(m); 288 if (opts) 289 m_freem(opts); 290 V_rip6stat.rip6s_fullsock++; 291 } else 292 sorwakeup(last->inp_socket); 293 INP_RUNLOCK(last); 294 } else { 295 V_rip6stat.rip6s_nosock++; 296 if (m->m_flags & M_MCAST) 297 V_rip6stat.rip6s_nosockmcast++; 298 if (proto == IPPROTO_NONE) 299 m_freem(m); 300 else { 301 char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ 302 icmp6_error(m, ICMP6_PARAM_PROB, 303 ICMP6_PARAMPROB_NEXTHEADER, 304 prvnxtp - mtod(m, char *)); 305 } 306 V_ip6stat.ip6s_delivered--; 307 } 308 return (IPPROTO_DONE); 309 } 310 311 void 312 rip6_ctlinput(int cmd, struct sockaddr *sa, void *d) 313 { 314 struct ip6_hdr *ip6; 315 struct mbuf *m; 316 int off = 0; 317 struct ip6ctlparam *ip6cp = NULL; 318 const struct sockaddr_in6 *sa6_src = NULL; 319 void *cmdarg; 320 struct inpcb *(*notify)(struct inpcb *, int) = in6_rtchange; 321 322 if (sa->sa_family != AF_INET6 || 323 sa->sa_len != sizeof(struct sockaddr_in6)) 324 return; 325 326 if ((unsigned)cmd >= PRC_NCMDS) 327 return; 328 if (PRC_IS_REDIRECT(cmd)) 329 notify = in6_rtchange, d = NULL; 330 else if (cmd == PRC_HOSTDEAD) 331 d = NULL; 332 else if (inet6ctlerrmap[cmd] == 0) 333 return; 334 335 /* 336 * If the parameter is from icmp6, decode it. 337 */ 338 if (d != NULL) { 339 ip6cp = (struct ip6ctlparam *)d; 340 m = ip6cp->ip6c_m; 341 ip6 = ip6cp->ip6c_ip6; 342 off = ip6cp->ip6c_off; 343 cmdarg = ip6cp->ip6c_cmdarg; 344 sa6_src = ip6cp->ip6c_src; 345 } else { 346 m = NULL; 347 ip6 = NULL; 348 cmdarg = NULL; 349 sa6_src = &sa6_any; 350 } 351 352 (void) in6_pcbnotify(&V_ripcbinfo, sa, 0, 353 (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify); 354 } 355 356 /* 357 * Generate IPv6 header and pass packet to ip6_output. Tack on options user 358 * may have setup with control call. 359 */ 360 int 361 #if __STDC__ 362 rip6_output(struct mbuf *m, ...) 363 #else 364 rip6_output(m, va_alist) 365 struct mbuf *m; 366 va_dcl 367 #endif 368 { 369 struct mbuf *control; 370 struct socket *so; 371 struct sockaddr_in6 *dstsock; 372 struct in6_addr *dst; 373 struct ip6_hdr *ip6; 374 struct inpcb *in6p; 375 u_int plen = m->m_pkthdr.len; 376 int error = 0; 377 struct ip6_pktopts opt, *optp; 378 struct ifnet *oifp = NULL; 379 int type = 0, code = 0; /* for ICMPv6 output statistics only */ 380 int scope_ambiguous = 0; 381 struct in6_addr in6a; 382 va_list ap; 383 384 va_start(ap, m); 385 so = va_arg(ap, struct socket *); 386 dstsock = va_arg(ap, struct sockaddr_in6 *); 387 control = va_arg(ap, struct mbuf *); 388 va_end(ap); 389 390 in6p = sotoinpcb(so); 391 INP_WLOCK(in6p); 392 393 dst = &dstsock->sin6_addr; 394 if (control != NULL) { 395 if ((error = ip6_setpktopts(control, &opt, 396 in6p->in6p_outputopts, so->so_cred, 397 so->so_proto->pr_protocol)) != 0) { 398 goto bad; 399 } 400 optp = &opt; 401 } else 402 optp = in6p->in6p_outputopts; 403 404 /* 405 * Check and convert scope zone ID into internal form. 406 * 407 * XXX: we may still need to determine the zone later. 408 */ 409 if (!(so->so_state & SS_ISCONNECTED)) { 410 if (dstsock->sin6_scope_id == 0 && !V_ip6_use_defzone) 411 scope_ambiguous = 1; 412 if ((error = sa6_embedscope(dstsock, V_ip6_use_defzone)) != 0) 413 goto bad; 414 } 415 416 /* 417 * For an ICMPv6 packet, we should know its type and code to update 418 * statistics. 419 */ 420 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 421 struct icmp6_hdr *icmp6; 422 if (m->m_len < sizeof(struct icmp6_hdr) && 423 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) { 424 error = ENOBUFS; 425 goto bad; 426 } 427 icmp6 = mtod(m, struct icmp6_hdr *); 428 type = icmp6->icmp6_type; 429 code = icmp6->icmp6_code; 430 } 431 432 M_PREPEND(m, sizeof(*ip6), M_DONTWAIT); 433 if (m == NULL) { 434 error = ENOBUFS; 435 goto bad; 436 } 437 ip6 = mtod(m, struct ip6_hdr *); 438 439 /* 440 * Source address selection. 441 */ 442 error = in6_selectsrc(dstsock, optp, in6p, NULL, so->so_cred, 443 &oifp, &in6a); 444 if (error) 445 goto bad; 446 error = prison_get_ip6(in6p->inp_cred, &in6a); 447 if (error != 0) 448 goto bad; 449 ip6->ip6_src = in6a; 450 451 if (oifp && scope_ambiguous) { 452 /* 453 * Application should provide a proper zone ID or the use of 454 * default zone IDs should be enabled. Unfortunately, some 455 * applications do not behave as it should, so we need a 456 * workaround. Even if an appropriate ID is not determined 457 * (when it's required), if we can determine the outgoing 458 * interface. determine the zone ID based on the interface. 459 */ 460 error = in6_setscope(&dstsock->sin6_addr, oifp, NULL); 461 if (error != 0) 462 goto bad; 463 } 464 ip6->ip6_dst = dstsock->sin6_addr; 465 466 /* 467 * Fill in the rest of the IPv6 header fields. 468 */ 469 ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) | 470 (in6p->inp_flow & IPV6_FLOWINFO_MASK); 471 ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) | 472 (IPV6_VERSION & IPV6_VERSION_MASK); 473 474 /* 475 * ip6_plen will be filled in ip6_output, so not fill it here. 476 */ 477 ip6->ip6_nxt = in6p->inp_ip_p; 478 ip6->ip6_hlim = in6_selecthlim(in6p, oifp); 479 480 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 || 481 in6p->in6p_cksum != -1) { 482 struct mbuf *n; 483 int off; 484 u_int16_t *p; 485 486 /* Compute checksum. */ 487 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) 488 off = offsetof(struct icmp6_hdr, icmp6_cksum); 489 else 490 off = in6p->in6p_cksum; 491 if (plen < off + 1) { 492 error = EINVAL; 493 goto bad; 494 } 495 off += sizeof(struct ip6_hdr); 496 497 n = m; 498 while (n && n->m_len <= off) { 499 off -= n->m_len; 500 n = n->m_next; 501 } 502 if (!n) 503 goto bad; 504 p = (u_int16_t *)(mtod(n, caddr_t) + off); 505 *p = 0; 506 *p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen); 507 } 508 509 error = ip6_output(m, optp, NULL, 0, in6p->in6p_moptions, &oifp, in6p); 510 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 511 if (oifp) 512 icmp6_ifoutstat_inc(oifp, type, code); 513 ICMP6STAT_INC(icp6s_outhist[type]); 514 } else 515 V_rip6stat.rip6s_opackets++; 516 517 goto freectl; 518 519 bad: 520 if (m) 521 m_freem(m); 522 523 freectl: 524 if (control != NULL) { 525 ip6_clearpktopts(&opt, -1); 526 m_freem(control); 527 } 528 INP_WUNLOCK(in6p); 529 return (error); 530 } 531 532 /* 533 * Raw IPv6 socket option processing. 534 */ 535 int 536 rip6_ctloutput(struct socket *so, struct sockopt *sopt) 537 { 538 int error; 539 540 if (sopt->sopt_level == IPPROTO_ICMPV6) 541 /* 542 * XXX: is it better to call icmp6_ctloutput() directly 543 * from protosw? 544 */ 545 return (icmp6_ctloutput(so, sopt)); 546 else if (sopt->sopt_level != IPPROTO_IPV6) 547 return (EINVAL); 548 549 error = 0; 550 551 switch (sopt->sopt_dir) { 552 case SOPT_GET: 553 switch (sopt->sopt_name) { 554 case MRT6_INIT: 555 case MRT6_DONE: 556 case MRT6_ADD_MIF: 557 case MRT6_DEL_MIF: 558 case MRT6_ADD_MFC: 559 case MRT6_DEL_MFC: 560 case MRT6_PIM: 561 error = ip6_mrouter_get ? ip6_mrouter_get(so, sopt) : 562 EOPNOTSUPP; 563 break; 564 case IPV6_CHECKSUM: 565 error = ip6_raw_ctloutput(so, sopt); 566 break; 567 default: 568 error = ip6_ctloutput(so, sopt); 569 break; 570 } 571 break; 572 573 case SOPT_SET: 574 switch (sopt->sopt_name) { 575 case MRT6_INIT: 576 case MRT6_DONE: 577 case MRT6_ADD_MIF: 578 case MRT6_DEL_MIF: 579 case MRT6_ADD_MFC: 580 case MRT6_DEL_MFC: 581 case MRT6_PIM: 582 error = ip6_mrouter_set ? ip6_mrouter_set(so, sopt) : 583 EOPNOTSUPP; 584 break; 585 case IPV6_CHECKSUM: 586 error = ip6_raw_ctloutput(so, sopt); 587 break; 588 default: 589 error = ip6_ctloutput(so, sopt); 590 break; 591 } 592 break; 593 } 594 595 return (error); 596 } 597 598 static int 599 rip6_attach(struct socket *so, int proto, struct thread *td) 600 { 601 struct inpcb *inp; 602 struct icmp6_filter *filter; 603 int error; 604 605 inp = sotoinpcb(so); 606 KASSERT(inp == NULL, ("rip6_attach: inp != NULL")); 607 608 error = priv_check(td, PRIV_NETINET_RAW); 609 if (error) 610 return (error); 611 error = soreserve(so, rip_sendspace, rip_recvspace); 612 if (error) 613 return (error); 614 filter = malloc(sizeof(struct icmp6_filter), M_PCB, M_NOWAIT); 615 if (filter == NULL) 616 return (ENOMEM); 617 INP_INFO_WLOCK(&V_ripcbinfo); 618 error = in_pcballoc(so, &V_ripcbinfo); 619 if (error) { 620 INP_INFO_WUNLOCK(&V_ripcbinfo); 621 free(filter, M_PCB); 622 return (error); 623 } 624 inp = (struct inpcb *)so->so_pcb; 625 INP_INFO_WUNLOCK(&V_ripcbinfo); 626 inp->inp_vflag |= INP_IPV6; 627 inp->inp_ip_p = (long)proto; 628 inp->in6p_hops = -1; /* use kernel default */ 629 inp->in6p_cksum = -1; 630 inp->in6p_icmp6filt = filter; 631 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt); 632 INP_WUNLOCK(inp); 633 return (0); 634 } 635 636 static void 637 rip6_detach(struct socket *so) 638 { 639 struct inpcb *inp; 640 641 inp = sotoinpcb(so); 642 KASSERT(inp != NULL, ("rip6_detach: inp == NULL")); 643 644 if (so == V_ip6_mrouter && ip6_mrouter_done) 645 ip6_mrouter_done(); 646 /* xxx: RSVP */ 647 INP_INFO_WLOCK(&V_ripcbinfo); 648 INP_WLOCK(inp); 649 free(inp->in6p_icmp6filt, M_PCB); 650 in_pcbdetach(inp); 651 in_pcbfree(inp); 652 INP_INFO_WUNLOCK(&V_ripcbinfo); 653 } 654 655 /* XXXRW: This can't ever be called. */ 656 static void 657 rip6_abort(struct socket *so) 658 { 659 struct inpcb *inp; 660 661 inp = sotoinpcb(so); 662 KASSERT(inp != NULL, ("rip6_abort: inp == NULL")); 663 664 soisdisconnected(so); 665 } 666 667 static void 668 rip6_close(struct socket *so) 669 { 670 struct inpcb *inp; 671 672 inp = sotoinpcb(so); 673 KASSERT(inp != NULL, ("rip6_close: inp == NULL")); 674 675 soisdisconnected(so); 676 } 677 678 static int 679 rip6_disconnect(struct socket *so) 680 { 681 struct inpcb *inp; 682 683 inp = sotoinpcb(so); 684 KASSERT(inp != NULL, ("rip6_disconnect: inp == NULL")); 685 686 if ((so->so_state & SS_ISCONNECTED) == 0) 687 return (ENOTCONN); 688 inp->in6p_faddr = in6addr_any; 689 rip6_abort(so); 690 return (0); 691 } 692 693 static int 694 rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 695 { 696 struct inpcb *inp; 697 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 698 struct ifaddr *ifa = NULL; 699 int error = 0; 700 701 inp = sotoinpcb(so); 702 KASSERT(inp != NULL, ("rip6_bind: inp == NULL")); 703 704 if (nam->sa_len != sizeof(*addr)) 705 return (EINVAL); 706 if ((error = prison_check_ip6(td->td_ucred, &addr->sin6_addr)) != 0) 707 return (error); 708 if (TAILQ_EMPTY(&V_ifnet) || addr->sin6_family != AF_INET6) 709 return (EADDRNOTAVAIL); 710 if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0) 711 return (error); 712 713 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && 714 (ifa = ifa_ifwithaddr((struct sockaddr *)addr)) == NULL) 715 return (EADDRNOTAVAIL); 716 if (ifa != NULL && 717 ((struct in6_ifaddr *)ifa)->ia6_flags & 718 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| 719 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { 720 ifa_free(ifa); 721 return (EADDRNOTAVAIL); 722 } 723 if (ifa != NULL) 724 ifa_free(ifa); 725 INP_INFO_WLOCK(&V_ripcbinfo); 726 INP_WLOCK(inp); 727 inp->in6p_laddr = addr->sin6_addr; 728 INP_WUNLOCK(inp); 729 INP_INFO_WUNLOCK(&V_ripcbinfo); 730 return (0); 731 } 732 733 static int 734 rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 735 { 736 struct inpcb *inp; 737 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 738 struct in6_addr in6a; 739 struct ifnet *ifp = NULL; 740 int error = 0, scope_ambiguous = 0; 741 742 inp = sotoinpcb(so); 743 KASSERT(inp != NULL, ("rip6_connect: inp == NULL")); 744 745 if (nam->sa_len != sizeof(*addr)) 746 return (EINVAL); 747 if (TAILQ_EMPTY(&V_ifnet)) 748 return (EADDRNOTAVAIL); 749 if (addr->sin6_family != AF_INET6) 750 return (EAFNOSUPPORT); 751 752 /* 753 * Application should provide a proper zone ID or the use of default 754 * zone IDs should be enabled. Unfortunately, some applications do 755 * not behave as it should, so we need a workaround. Even if an 756 * appropriate ID is not determined, we'll see if we can determine 757 * the outgoing interface. If we can, determine the zone ID based on 758 * the interface below. 759 */ 760 if (addr->sin6_scope_id == 0 && !V_ip6_use_defzone) 761 scope_ambiguous = 1; 762 if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0) 763 return (error); 764 765 INP_INFO_WLOCK(&V_ripcbinfo); 766 INP_WLOCK(inp); 767 /* Source address selection. XXX: need pcblookup? */ 768 error = in6_selectsrc(addr, inp->in6p_outputopts, 769 inp, NULL, so->so_cred, &ifp, &in6a); 770 if (error) { 771 INP_WUNLOCK(inp); 772 INP_INFO_WUNLOCK(&V_ripcbinfo); 773 return (error); 774 } 775 776 /* XXX: see above */ 777 if (ifp && scope_ambiguous && 778 (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) { 779 INP_WUNLOCK(inp); 780 INP_INFO_WUNLOCK(&V_ripcbinfo); 781 return (error); 782 } 783 inp->in6p_faddr = addr->sin6_addr; 784 inp->in6p_laddr = in6a; 785 soisconnected(so); 786 INP_WUNLOCK(inp); 787 INP_INFO_WUNLOCK(&V_ripcbinfo); 788 return (0); 789 } 790 791 static int 792 rip6_shutdown(struct socket *so) 793 { 794 struct inpcb *inp; 795 796 inp = sotoinpcb(so); 797 KASSERT(inp != NULL, ("rip6_shutdown: inp == NULL")); 798 799 INP_WLOCK(inp); 800 socantsendmore(so); 801 INP_WUNLOCK(inp); 802 return (0); 803 } 804 805 static int 806 rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 807 struct mbuf *control, struct thread *td) 808 { 809 struct inpcb *inp; 810 struct sockaddr_in6 tmp; 811 struct sockaddr_in6 *dst; 812 int ret; 813 814 inp = sotoinpcb(so); 815 KASSERT(inp != NULL, ("rip6_send: inp == NULL")); 816 817 /* Always copy sockaddr to avoid overwrites. */ 818 /* Unlocked read. */ 819 if (so->so_state & SS_ISCONNECTED) { 820 if (nam) { 821 m_freem(m); 822 return (EISCONN); 823 } 824 /* XXX */ 825 bzero(&tmp, sizeof(tmp)); 826 tmp.sin6_family = AF_INET6; 827 tmp.sin6_len = sizeof(struct sockaddr_in6); 828 INP_RLOCK(inp); 829 bcopy(&inp->in6p_faddr, &tmp.sin6_addr, 830 sizeof(struct in6_addr)); 831 INP_RUNLOCK(inp); 832 dst = &tmp; 833 } else { 834 if (nam == NULL) { 835 m_freem(m); 836 return (ENOTCONN); 837 } 838 if (nam->sa_len != sizeof(struct sockaddr_in6)) { 839 m_freem(m); 840 return (EINVAL); 841 } 842 tmp = *(struct sockaddr_in6 *)nam; 843 dst = &tmp; 844 845 if (dst->sin6_family == AF_UNSPEC) { 846 /* 847 * XXX: we allow this case for backward 848 * compatibility to buggy applications that 849 * rely on old (and wrong) kernel behavior. 850 */ 851 log(LOG_INFO, "rip6 SEND: address family is " 852 "unspec. Assume AF_INET6\n"); 853 dst->sin6_family = AF_INET6; 854 } else if (dst->sin6_family != AF_INET6) { 855 m_freem(m); 856 return(EAFNOSUPPORT); 857 } 858 } 859 ret = rip6_output(m, so, dst, control); 860 return (ret); 861 } 862 863 struct pr_usrreqs rip6_usrreqs = { 864 .pru_abort = rip6_abort, 865 .pru_attach = rip6_attach, 866 .pru_bind = rip6_bind, 867 .pru_connect = rip6_connect, 868 .pru_control = in6_control, 869 .pru_detach = rip6_detach, 870 .pru_disconnect = rip6_disconnect, 871 .pru_peeraddr = in6_getpeeraddr, 872 .pru_send = rip6_send, 873 .pru_shutdown = rip6_shutdown, 874 .pru_sockaddr = in6_getsockaddr, 875 .pru_close = rip6_close, 876 }; 877