1/* 2 * Copyright (c) 2000-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 30 * All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 3. Neither the name of the project nor the names of its contributors 41 * may be used to endorse or promote products derived from this software 42 * without specific prior written permission. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 * 56 * $FreeBSD: src/sys/netinet6/raw_ip6.c,v 1.7.2.4 2001/07/29 19:32:40 ume Exp $ 57 */ 58 59/* 60 * Copyright (c) 1982, 1986, 1988, 1993 61 * The Regents of the University of California. All rights reserved. 62 * 63 * Redistribution and use in source and binary forms, with or without 64 * modification, are permitted provided that the following conditions 65 * are met: 66 * 1. Redistributions of source code must retain the above copyright 67 * notice, this list of conditions and the following disclaimer. 68 * 2. Redistributions in binary form must reproduce the above copyright 69 * notice, this list of conditions and the following disclaimer in the 70 * documentation and/or other materials provided with the distribution. 71 * 3. All advertising materials mentioning features or use of this software 72 * must display the following acknowledgement: 73 * This product includes software developed by the University of 74 * California, Berkeley and its contributors. 75 * 4. Neither the name of the University nor the names of its contributors 76 * may be used to endorse or promote products derived from this software 77 * without specific prior written permission. 78 * 79 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 80 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 81 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 82 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 83 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 84 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 85 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 86 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 87 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 88 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 89 * SUCH DAMAGE. 90 * 91 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 92 */ 93#include <sys/param.h> 94#include <sys/malloc.h> 95#include <sys/proc.h> 96#include <sys/mcache.h> 97#include <sys/mbuf.h> 98#include <sys/socket.h> 99#include <sys/protosw.h> 100#include <sys/socketvar.h> 101#include <sys/errno.h> 102#include <sys/systm.h> 103 104#include <net/if.h> 105#include <net/route.h> 106#include <net/if_types.h> 107 108#include <netinet/in.h> 109#include <netinet/in_var.h> 110#include <netinet/in_systm.h> 111#include <netinet/ip6.h> 112#include <netinet6/ip6_var.h> 113#include <netinet/icmp6.h> 114#include <netinet/in_pcb.h> 115#include <netinet6/in6_pcb.h> 116#include <netinet6/nd6.h> 117#include <netinet6/ip6protosw.h> 118#include <netinet6/scope6_var.h> 119#include <netinet6/raw_ip6.h> 120#include <netinet6/ip6_fw.h> 121 122#if IPSEC 123#include <netinet6/ipsec.h> 124#include <netinet6/ipsec6.h> 125#endif /*IPSEC*/ 126 127#if NECP 128#include <net/necp.h> 129#endif 130 131/* 132 * Raw interface to IP6 protocol. 133 */ 134 135extern struct inpcbhead ripcb; 136extern struct inpcbinfo ripcbinfo; 137extern u_int32_t rip_sendspace; 138extern u_int32_t rip_recvspace; 139 140struct rip6stat rip6stat; 141 142/* 143 * Setup generic address and protocol structures 144 * for raw_input routine, then pass them along with 145 * mbuf chain. 146 */ 147int 148rip6_input( 149 struct mbuf **mp, 150 int *offp, 151 int proto) 152{ 153 struct mbuf *m = *mp; 154 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 155 struct inpcb *in6p; 156 struct inpcb *last = 0; 157 struct mbuf *opts = NULL; 158 struct sockaddr_in6 rip6src; 159 int ret; 160 struct ifnet *ifp = m->m_pkthdr.rcvif; 161 162 /* Expect 32-bit aligned data pointer on strict-align platforms */ 163 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); 164 165 rip6stat.rip6s_ipackets++; 166 167 init_sin6(&rip6src, m); /* general init */ 168 169 lck_rw_lock_shared(ripcbinfo.ipi_lock); 170 LIST_FOREACH(in6p, &ripcb, inp_list) { 171 if ((in6p->in6p_vflag & INP_IPV6) == 0) 172 continue; 173 if (in6p->in6p_ip6_nxt && 174 in6p->in6p_ip6_nxt != proto) 175 continue; 176 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 177 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 178 continue; 179 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 180 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 181 continue; 182 183 if (inp_restricted_recv(in6p, ifp)) 184 continue; 185 186 if (proto == IPPROTO_ICMPV6 || in6p->in6p_cksum != -1) { 187 rip6stat.rip6s_isum++; 188 if (in6_cksum(m, ip6->ip6_nxt, *offp, 189 m->m_pkthdr.len - *offp)) { 190 rip6stat.rip6s_badsum++; 191 continue; 192 } 193 } 194 if (last) { 195 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 196 197#if NECP 198 if (n && !necp_socket_is_allowed_to_send_recv_v6(in6p, 0, 0, &ip6->ip6_dst, &ip6->ip6_src, ifp, NULL)) { 199 m_freem(n); 200 /* do not inject data into pcb */ 201 } else 202#endif /* NECP */ 203 if (n) { 204 if ((last->in6p_flags & INP_CONTROLOPTS) != 0 || 205 (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 || 206 (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0) { 207 ret = ip6_savecontrol(last, n, &opts); 208 if (ret != 0) { 209 m_freem(n); 210 m_freem(opts); 211 last = in6p; 212 continue; 213 } 214 } 215 /* strip intermediate headers */ 216 m_adj(n, *offp); 217 so_recv_data_stat(last->in6p_socket, m, 0); 218 if (sbappendaddr(&last->in6p_socket->so_rcv, 219 (struct sockaddr *)&rip6src, 220 n, opts, NULL) == 0) { 221 rip6stat.rip6s_fullsock++; 222 } else 223 sorwakeup(last->in6p_socket); 224 opts = NULL; 225 } 226 } 227 last = in6p; 228 } 229 230#if NECP 231 if (last && !necp_socket_is_allowed_to_send_recv_v6(in6p, 0, 0, &ip6->ip6_dst, &ip6->ip6_src, ifp, NULL)) { 232 m_freem(m); 233 ip6stat.ip6s_delivered--; 234 /* do not inject data into pcb */ 235 } else 236#endif /* NECP */ 237 if (last) { 238 if ((last->in6p_flags & INP_CONTROLOPTS) != 0 || 239 (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 || 240 (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0) { 241 ret = ip6_savecontrol(last, m, &opts); 242 if (ret != 0) { 243 m_freem(m); 244 m_freem(opts); 245 ip6stat.ip6s_delivered--; 246 goto unlock; 247 } 248 249 } 250 /* strip intermediate headers */ 251 m_adj(m, *offp); 252 so_recv_data_stat(last->in6p_socket, m, 0); 253 if (sbappendaddr(&last->in6p_socket->so_rcv, 254 (struct sockaddr *)&rip6src, m, opts, NULL) == 0) { 255 rip6stat.rip6s_fullsock++; 256 } else 257 sorwakeup(last->in6p_socket); 258 } else { 259 rip6stat.rip6s_nosock++; 260 if (m->m_flags & M_MCAST) 261 rip6stat.rip6s_nosockmcast++; 262 if (proto == IPPROTO_NONE) 263 m_freem(m); 264 else { 265 char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ 266 icmp6_error(m, ICMP6_PARAM_PROB, 267 ICMP6_PARAMPROB_NEXTHEADER, 268 prvnxtp - mtod(m, char *)); 269 } 270 ip6stat.ip6s_delivered--; 271 } 272 273unlock: 274 lck_rw_done(ripcbinfo.ipi_lock); 275 276 return IPPROTO_DONE; 277} 278 279void 280rip6_ctlinput( 281 int cmd, 282 struct sockaddr *sa, 283 void *d) 284{ 285 struct ip6_hdr *ip6; 286 struct mbuf *m; 287 void *cmdarg = NULL; 288 int off = 0; 289 struct ip6ctlparam *ip6cp = NULL; 290 const struct sockaddr_in6 *sa6_src = NULL; 291 void (*notify)(struct inpcb *, int) = in6_rtchange; 292 293 if (sa->sa_family != AF_INET6 || 294 sa->sa_len != sizeof(struct sockaddr_in6)) 295 return; 296 297 if ((unsigned)cmd >= PRC_NCMDS) 298 return; 299 if (PRC_IS_REDIRECT(cmd)) 300 notify = in6_rtchange, d = NULL; 301 else if (cmd == PRC_HOSTDEAD) 302 d = NULL; 303 else if (inet6ctlerrmap[cmd] == 0) 304 return; 305 306 /* if the parameter is from icmp6, decode it. */ 307 if (d != NULL) { 308 ip6cp = (struct ip6ctlparam *)d; 309 m = ip6cp->ip6c_m; 310 ip6 = ip6cp->ip6c_ip6; 311 off = ip6cp->ip6c_off; 312 cmdarg = ip6cp->ip6c_cmdarg; 313 sa6_src = ip6cp->ip6c_src; 314 } else { 315 m = NULL; 316 ip6 = NULL; 317 sa6_src = &sa6_any; 318 } 319 320 (void) in6_pcbnotify(&ripcbinfo, sa, 0, (const struct sockaddr *)sa6_src, 321 0, cmd, cmdarg, notify); 322} 323 324/* 325 * Generate IPv6 header and pass packet to ip6_output. 326 * Tack on options user may have setup with control call. 327 */ 328int 329rip6_output( 330 struct mbuf *m, 331 struct socket *so, 332 struct sockaddr_in6 *dstsock, 333 struct mbuf *control, 334 int israw) 335{ 336 struct in6_addr *dst; 337 struct ip6_hdr *ip6; 338 struct inpcb *in6p; 339 u_int plen = m->m_pkthdr.len; 340 int error = 0; 341 struct ip6_pktopts opt, *optp = NULL; 342 struct ip6_moptions *im6o = NULL; 343 struct ifnet *oifp = NULL; 344 int type = 0, code = 0; /* for ICMPv6 output statistics only */ 345 mbuf_svc_class_t msc = MBUF_SC_UNSPEC; 346 struct ip6_out_args ip6oa = 347 { IFSCOPE_NONE, { 0 }, IP6OAF_SELECT_SRCIF, 0 }; 348 int flags = IPV6_OUTARGS; 349 350 in6p = sotoin6pcb(so); 351 352 if (in6p == NULL 353#if NECP 354 || (necp_socket_should_use_flow_divert(in6p)) 355#endif /* NECP */ 356 ) { 357 if (in6p == NULL) 358 error = EINVAL; 359 else 360 error = EPROTOTYPE; 361 goto bad; 362 } 363 if (dstsock != NULL && IN6_IS_ADDR_V4MAPPED(&dstsock->sin6_addr)) { 364 error = EINVAL; 365 goto bad; 366 } 367 368 if (in6p->inp_flags & INP_BOUND_IF) { 369 ip6oa.ip6oa_boundif = in6p->inp_boundifp->if_index; 370 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF; 371 } 372 if (INP_NO_CELLULAR(in6p)) 373 ip6oa.ip6oa_flags |= IP6OAF_NO_CELLULAR; 374 if (INP_NO_EXPENSIVE(in6p)) 375 ip6oa.ip6oa_flags |= IP6OAF_NO_EXPENSIVE; 376 if (INP_AWDL_UNRESTRICTED(in6p)) 377 ip6oa.ip6oa_flags |= IP6OAF_AWDL_UNRESTRICTED; 378 379 dst = &dstsock->sin6_addr; 380 if (control) { 381 msc = mbuf_service_class_from_control(control); 382 383 if ((error = ip6_setpktopts(control, &opt, NULL, 384 SOCK_PROTO(so))) != 0) 385 goto bad; 386 optp = &opt; 387 } else 388 optp = in6p->in6p_outputopts; 389 390 /* 391 * For an ICMPv6 packet, we should know its type and code 392 * to update statistics. 393 */ 394 if (SOCK_PROTO(so) == IPPROTO_ICMPV6) { 395 struct icmp6_hdr *icmp6; 396 if (m->m_len < sizeof(struct icmp6_hdr) && 397 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) { 398 error = ENOBUFS; 399 goto bad; 400 } 401 icmp6 = mtod(m, struct icmp6_hdr *); 402 type = icmp6->icmp6_type; 403 code = icmp6->icmp6_code; 404 } 405 406 if (in6p->inp_flowhash == 0) 407 in6p->inp_flowhash = inp_calc_flowhash(in6p); 408 /* update flowinfo - RFC 6437 */ 409 if (in6p->inp_flow == 0 && in6p->in6p_flags & IN6P_AUTOFLOWLABEL) { 410 in6p->inp_flow &= ~IPV6_FLOWLABEL_MASK; 411 in6p->inp_flow |= 412 (htonl(in6p->inp_flowhash) & IPV6_FLOWLABEL_MASK); 413 } 414 415 M_PREPEND(m, sizeof(*ip6), M_WAIT); 416 if (m == NULL) { 417 error = ENOBUFS; 418 goto bad; 419 } 420 ip6 = mtod(m, struct ip6_hdr *); 421 422 /* 423 * Next header might not be ICMP6 but use its pseudo header anyway. 424 */ 425 ip6->ip6_dst = *dst; 426 427 im6o = in6p->in6p_moptions; 428 429 /* 430 * If the scope of the destination is link-local, embed the interface 431 * index in the address. 432 * 433 * XXX advanced-api value overrides sin6_scope_id 434 */ 435 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 436 struct in6_pktinfo *pi; 437 struct ifnet *im6o_multicast_ifp = NULL; 438 439 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && im6o != NULL) { 440 IM6O_LOCK(im6o); 441 im6o_multicast_ifp = im6o->im6o_multicast_ifp; 442 IM6O_UNLOCK(im6o); 443 } 444 /* 445 * XXX Boundary check is assumed to be already done in 446 * ip6_setpktoptions(). 447 */ 448 ifnet_head_lock_shared(); 449 if (optp && (pi = optp->ip6po_pktinfo) && pi->ipi6_ifindex) { 450 ip6->ip6_dst.s6_addr16[1] = htons(pi->ipi6_ifindex); 451 oifp = ifindex2ifnet[pi->ipi6_ifindex]; 452 if (oifp != NULL) 453 ifnet_reference(oifp); 454 } else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && 455 im6o != NULL && im6o_multicast_ifp != NULL) { 456 oifp = im6o_multicast_ifp; 457 ifnet_reference(oifp); 458 ip6->ip6_dst.s6_addr16[1] = htons(oifp->if_index); 459 } else if (dstsock->sin6_scope_id) { 460 /* 461 * boundary check 462 * 463 * Sinced stsock->sin6_scope_id is unsigned, we don't 464 * need to check if it's < 0 465 */ 466 if (if_index < dstsock->sin6_scope_id) { 467 error = ENXIO; /* XXX EINVAL? */ 468 ifnet_head_done(); 469 goto bad; 470 } 471 ip6->ip6_dst.s6_addr16[1] 472 = htons(dstsock->sin6_scope_id & 0xffff);/*XXX*/ 473 } 474 ifnet_head_done(); 475 } 476 477 /* 478 * Source address selection. 479 */ 480 { 481 struct in6_addr *in6a; 482 struct in6_addr storage; 483 u_short index = 0; 484 485 if (israw != 0 && optp && optp->ip6po_pktinfo && !IN6_IS_ADDR_UNSPECIFIED(&optp->ip6po_pktinfo->ipi6_addr)) { 486 in6a = &optp->ip6po_pktinfo->ipi6_addr; 487 flags |= IPV6_FLAG_NOSRCIFSEL; 488 } else if ((in6a = in6_selectsrc(dstsock, optp, in6p, 489 &in6p->in6p_route, NULL, &storage, ip6oa.ip6oa_boundif, 490 &error)) == 0) { 491 if (error == 0) 492 error = EADDRNOTAVAIL; 493 goto bad; 494 } else { 495 ip6oa.ip6oa_flags |= IP6OAF_BOUND_SRCADDR; 496 } 497 ip6->ip6_src = *in6a; 498 if (in6p->in6p_route.ro_rt != NULL) { 499 RT_LOCK(in6p->in6p_route.ro_rt); 500 if (in6p->in6p_route.ro_rt->rt_ifp != NULL) 501 index = in6p->in6p_route.ro_rt->rt_ifp->if_index; 502 RT_UNLOCK(in6p->in6p_route.ro_rt); 503 if (oifp != NULL) 504 ifnet_release(oifp); 505 ifnet_head_lock_shared(); 506 if (index == 0 || if_index < index) { 507 panic("bad if_index on interface from route"); 508 } 509 oifp = ifindex2ifnet[index]; 510 if (oifp != NULL) 511 ifnet_reference(oifp); 512 ifnet_head_done(); 513 } 514 } 515 ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) | 516 (in6p->inp_flow & IPV6_FLOWINFO_MASK); 517 ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) | 518 (IPV6_VERSION & IPV6_VERSION_MASK); 519 /* ip6_plen will be filled in ip6_output, so not fill it here. */ 520 ip6->ip6_nxt = in6p->in6p_ip6_nxt; 521 ip6->ip6_hlim = in6_selecthlim(in6p, oifp); 522 523 if (SOCK_PROTO(so) == IPPROTO_ICMPV6 || in6p->in6p_cksum != -1) { 524 struct mbuf *n; 525 int off; 526 u_int16_t *p; 527 528 /* compute checksum */ 529 if (SOCK_PROTO(so) == IPPROTO_ICMPV6) 530 off = offsetof(struct icmp6_hdr, icmp6_cksum); 531 else 532 off = in6p->in6p_cksum; 533 if (plen < (unsigned int)(off + 1)) { 534 error = EINVAL; 535 goto bad; 536 } 537 off += sizeof(struct ip6_hdr); 538 539 n = m; 540 while (n && n->m_len <= off) { 541 off -= n->m_len; 542 n = n->m_next; 543 } 544 if (!n) 545 goto bad; 546 p = (u_int16_t *)(void *)(mtod(n, caddr_t) + off); 547 *p = 0; 548 *p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen); 549 } 550 551#if NECP 552 { 553 necp_kernel_policy_id policy_id; 554 if (!necp_socket_is_allowed_to_send_recv_v6(in6p, 0, 0, &ip6->ip6_src, &ip6->ip6_dst, NULL, &policy_id)) { 555 error = EHOSTUNREACH; 556 goto bad; 557 } 558 559 necp_mark_packet_from_socket(m, in6p, policy_id); 560 } 561#endif /* NECP */ 562 563#if IPSEC 564 if (in6p->in6p_sp != NULL && ipsec_setsocket(m, so) != 0) { 565 error = ENOBUFS; 566 goto bad; 567 } 568#endif /*IPSEC*/ 569 570 if (ROUTE_UNUSABLE(&in6p->in6p_route)) 571 ROUTE_RELEASE(&in6p->in6p_route); 572 573 if (oifp != NULL) { 574 ifnet_release(oifp); 575 oifp = NULL; 576 } 577 578 set_packet_service_class(m, so, msc, PKT_SCF_IPV6); 579 m->m_pkthdr.pkt_flowsrc = FLOWSRC_INPCB; 580 m->m_pkthdr.pkt_flowid = in6p->inp_flowhash; 581 m->m_pkthdr.pkt_flags |= (PKTF_FLOW_ID | PKTF_FLOW_LOCALSRC | 582 PKTF_FLOW_RAWSOCK); 583 m->m_pkthdr.pkt_proto = in6p->in6p_ip6_nxt; 584 585 if (im6o != NULL) 586 IM6O_ADDREF(im6o); 587 588 error = ip6_output(m, optp, &in6p->in6p_route, flags, im6o, 589 &oifp, &ip6oa); 590 591 if (im6o != NULL) 592 IM6O_REMREF(im6o); 593 594 if (in6p->in6p_route.ro_rt != NULL) { 595 struct rtentry *rt = in6p->in6p_route.ro_rt; 596 struct ifnet *outif; 597 598 if ((rt->rt_flags & RTF_MULTICAST) || 599 in6p->in6p_socket == NULL || 600 !(in6p->in6p_socket->so_state & SS_ISCONNECTED)) { 601 rt = NULL; /* unusable */ 602 } 603 /* 604 * Always discard the cached route for unconnected 605 * socket or if it is a multicast route. 606 */ 607 if (rt == NULL) 608 ROUTE_RELEASE(&in6p->in6p_route); 609 610 /* 611 * If this is a connected socket and the destination 612 * route is not multicast, update outif with that of 613 * the route interface index used by IP. 614 */ 615 if (rt != NULL && 616 (outif = rt->rt_ifp) != in6p->in6p_last_outifp) 617 in6p->in6p_last_outifp = outif; 618 } else { 619 ROUTE_RELEASE(&in6p->in6p_route); 620 } 621 622 /* 623 * If output interface was cellular/expensive, and this socket is 624 * denied access to it, generate an event. 625 */ 626 if (error != 0 && (ip6oa.ip6oa_retflags & IP6OARF_IFDENIED) && 627 (INP_NO_CELLULAR(in6p) || INP_NO_EXPENSIVE(in6p))) 628 soevent(in6p->inp_socket, (SO_FILT_HINT_LOCKED| 629 SO_FILT_HINT_IFDENIED)); 630 631 if (SOCK_PROTO(so) == IPPROTO_ICMPV6) { 632 if (oifp) 633 icmp6_ifoutstat_inc(oifp, type, code); 634 icmp6stat.icp6s_outhist[type]++; 635 } else 636 rip6stat.rip6s_opackets++; 637 638 goto freectl; 639 640bad: 641 if (m != NULL) 642 m_freem(m); 643 644freectl: 645 if (optp == &opt && optp->ip6po_rthdr) 646 ROUTE_RELEASE(&optp->ip6po_route); 647 648 if (control != NULL) { 649 if (optp == &opt) 650 ip6_clearpktopts(optp, -1); 651 m_freem(control); 652 } 653 if (oifp != NULL) 654 ifnet_release(oifp); 655 return(error); 656} 657 658#if IPFW2 659__private_extern__ void 660load_ip6fw(void) 661{ 662 ip6_fw_init(); 663} 664#endif 665 666/* 667 * Raw IPv6 socket option processing. 668 */ 669int 670rip6_ctloutput( 671 struct socket *so, 672 struct sockopt *sopt) 673{ 674 int error, optval; 675 676 /* Allow <SOL_SOCKET,SO_FLUSH> at this level */ 677 if (sopt->sopt_level == IPPROTO_ICMPV6) 678 /* 679 * XXX: is it better to call icmp6_ctloutput() directly 680 * from protosw? 681 */ 682 return(icmp6_ctloutput(so, sopt)); 683 else if (sopt->sopt_level != IPPROTO_IPV6 && 684 !(sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_FLUSH)) 685 return (EINVAL); 686 687 error = 0; 688 689 switch (sopt->sopt_dir) { 690 case SOPT_GET: 691 switch (sopt->sopt_name) { 692#if IPFW2 693 case IPV6_FW_ADD: 694 case IPV6_FW_GET: 695 if (ip6_fw_ctl_ptr == 0) 696 load_ip6fw(); 697 if (ip6_fw_ctl_ptr) 698 error = ip6_fw_ctl_ptr(sopt); 699 else 700 error = ENOPROTOOPT; 701 break; 702#endif 703 case IPV6_CHECKSUM: 704 error = ip6_raw_ctloutput(so, sopt); 705 break; 706 default: 707 error = ip6_ctloutput(so, sopt); 708 break; 709 } 710 break; 711 712 case SOPT_SET: 713 switch (sopt->sopt_name) { 714#if IPFW2 715 case IPV6_FW_ADD: 716 case IPV6_FW_DEL: 717 case IPV6_FW_FLUSH: 718 case IPV6_FW_ZERO: 719 if (ip6_fw_ctl_ptr == 0) 720 load_ip6fw(); 721 if (ip6_fw_ctl_ptr) 722 error = ip6_fw_ctl_ptr(sopt); 723 else 724 error = ENOPROTOOPT; 725 break; 726#endif 727 728 case IPV6_CHECKSUM: 729 error = ip6_raw_ctloutput(so, sopt); 730 break; 731 732 case SO_FLUSH: 733 if ((error = sooptcopyin(sopt, &optval, sizeof (optval), 734 sizeof (optval))) != 0) 735 break; 736 737 error = inp_flush(sotoinpcb(so), optval); 738 break; 739 740 default: 741 error = ip6_ctloutput(so, sopt); 742 break; 743 } 744 break; 745 } 746 747 return (error); 748} 749 750static int 751rip6_attach(struct socket *so, int proto, struct proc *p) 752{ 753 struct inpcb *inp; 754 int error; 755 756 inp = sotoinpcb(so); 757 if (inp) 758 panic("rip6_attach"); 759 if ((error = proc_suser(p)) != 0) 760 return error; 761 762 error = soreserve(so, rip_sendspace, rip_recvspace); 763 if (error) 764 return error; 765 error = in_pcballoc(so, &ripcbinfo, p); 766 if (error) 767 return error; 768 inp = (struct inpcb *)so->so_pcb; 769 inp->inp_vflag |= INP_IPV6; 770 inp->in6p_ip6_nxt = (char)proto; 771 inp->in6p_hops = -1; /* use kernel default */ 772 inp->in6p_cksum = -1; 773 MALLOC(inp->in6p_icmp6filt, struct icmp6_filter *, 774 sizeof(struct icmp6_filter), M_PCB, M_WAITOK); 775 if (inp->in6p_icmp6filt == NULL) 776 return (ENOMEM); 777 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt); 778 return 0; 779} 780 781static int 782rip6_detach(struct socket *so) 783{ 784 struct inpcb *inp; 785 786 inp = sotoinpcb(so); 787 if (inp == 0) 788 panic("rip6_detach"); 789 /* xxx: RSVP */ 790 if (inp->in6p_icmp6filt) { 791 FREE(inp->in6p_icmp6filt, M_PCB); 792 inp->in6p_icmp6filt = NULL; 793 } 794 in6_pcbdetach(inp); 795 return 0; 796} 797 798static int 799rip6_abort(struct socket *so) 800{ 801 soisdisconnected(so); 802 return rip6_detach(so); 803} 804 805static int 806rip6_disconnect(struct socket *so) 807{ 808 struct inpcb *inp = sotoinpcb(so); 809 810 if ((so->so_state & SS_ISCONNECTED) == 0) 811 return ENOTCONN; 812 inp->in6p_faddr = in6addr_any; 813 return rip6_abort(so); 814} 815 816static int 817rip6_bind(struct socket *so, struct sockaddr *nam, struct proc *p) 818{ 819#pragma unused(p) 820 struct inpcb *inp = sotoinpcb(so); 821 struct sockaddr_in6 sin6; 822 struct ifaddr *ifa = NULL; 823 struct ifnet *outif = NULL; 824 int error; 825 826 if (inp == NULL 827#if NECP 828 || (necp_socket_should_use_flow_divert(inp)) 829#endif /* NECP */ 830 ) 831 return (inp == NULL ? EINVAL : EPROTOTYPE); 832 833 if (nam->sa_len != sizeof (struct sockaddr_in6)) 834 return (EINVAL); 835 836 if (TAILQ_EMPTY(&ifnet_head) || SIN6(nam)->sin6_family != AF_INET6) 837 return (EADDRNOTAVAIL); 838 839 bzero(&sin6, sizeof (sin6)); 840 *(&sin6) = *SIN6(nam); 841 842 if ((error = sa6_embedscope(&sin6, ip6_use_defzone)) != 0) 843 return (error); 844 845 /* Sanitize local copy for address searches */ 846 sin6.sin6_flowinfo = 0; 847 sin6.sin6_scope_id = 0; 848 sin6.sin6_port = 0; 849 850 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr) && 851 (ifa = ifa_ifwithaddr(SA(&sin6))) == 0) 852 return (EADDRNOTAVAIL); 853 if (ifa != NULL) { 854 IFA_LOCK(ifa); 855 if (((struct in6_ifaddr *)ifa)->ia6_flags & 856 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| 857 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { 858 IFA_UNLOCK(ifa); 859 IFA_REMREF(ifa); 860 return (EADDRNOTAVAIL); 861 } 862 outif = ifa->ifa_ifp; 863 IFA_UNLOCK(ifa); 864 IFA_REMREF(ifa); 865 } 866 inp->in6p_laddr = sin6.sin6_addr; 867 inp->in6p_last_outifp = outif; 868 return (0); 869} 870 871static int 872rip6_connect(struct socket *so, struct sockaddr *nam, __unused struct proc *p) 873{ 874 struct inpcb *inp = sotoinpcb(so); 875 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)nam; 876 struct in6_addr *in6a = NULL; 877 struct in6_addr storage; 878 int error = 0; 879#if ENABLE_DEFAULT_SCOPE 880 struct sockaddr_in6 tmp; 881#endif 882 unsigned int ifscope; 883 struct ifnet *outif = NULL; 884 885 if (inp == NULL 886#if NECP 887 || (necp_socket_should_use_flow_divert(inp)) 888#endif /* NECP */ 889 ) 890 return (inp == NULL ? EINVAL : EPROTOTYPE); 891 if (nam->sa_len != sizeof(*addr)) 892 return EINVAL; 893 if (TAILQ_EMPTY(&ifnet_head)) 894 return EADDRNOTAVAIL; 895 if (addr->sin6_family != AF_INET6) 896 return EAFNOSUPPORT; 897#if ENABLE_DEFAULT_SCOPE 898 if (addr->sin6_scope_id == 0) { /* not change if specified */ 899 /* avoid overwrites */ 900 tmp = *addr; 901 addr = &tmp; 902 addr->sin6_scope_id = scope6_addr2default(&addr->sin6_addr); 903 } 904#endif 905 906 ifscope = (inp->inp_flags & INP_BOUND_IF) ? 907 inp->inp_boundifp->if_index : IFSCOPE_NONE; 908 909 /* Source address selection. XXX: need pcblookup? */ 910 in6a = in6_selectsrc(addr, inp->in6p_outputopts, inp, &inp->in6p_route, 911 NULL, &storage, ifscope, &error); 912 if (in6a == NULL) 913 return (error ? error : EADDRNOTAVAIL); 914 inp->in6p_laddr = *in6a; 915 inp->in6p_faddr = addr->sin6_addr; 916 if (inp->in6p_route.ro_rt != NULL) 917 outif = inp->in6p_route.ro_rt->rt_ifp; 918 inp->in6p_last_outifp = outif; 919 soisconnected(so); 920 return 0; 921} 922 923static int 924rip6_shutdown(struct socket *so) 925{ 926 socantsendmore(so); 927 return 0; 928} 929 930static int 931rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 932 struct mbuf *control, struct proc *p) 933{ 934#pragma unused(flags, p) 935 struct inpcb *inp = sotoinpcb(so); 936 struct sockaddr_in6 tmp; 937 struct sockaddr_in6 *dst = (struct sockaddr_in6 *)(void *)nam; 938 int error = 0; 939 940 if (inp == NULL 941#if NECP 942 || (necp_socket_should_use_flow_divert(inp)) 943#endif /* NECP */ 944 ) { 945 if (inp == NULL) 946 error = EINVAL; 947 else 948 error = EPROTOTYPE; 949 goto bad; 950 } 951 952 /* always copy sockaddr to avoid overwrites */ 953 if (so->so_state & SS_ISCONNECTED) { 954 if (nam != NULL) { 955 error = EISCONN; 956 goto bad; 957 } 958 /* XXX */ 959 bzero(&tmp, sizeof(tmp)); 960 tmp.sin6_family = AF_INET6; 961 tmp.sin6_len = sizeof(struct sockaddr_in6); 962 bcopy(&inp->in6p_faddr, &tmp.sin6_addr, 963 sizeof(struct in6_addr)); 964 dst = &tmp; 965 } else { 966 if (nam == NULL) { 967 error = ENOTCONN; 968 goto bad; 969 } 970 tmp = *(struct sockaddr_in6 *)(void *)nam; 971 dst = &tmp; 972 } 973#if ENABLE_DEFAULT_SCOPE 974 if (dst->sin6_scope_id == 0) { /* not change if specified */ 975 dst->sin6_scope_id = scope6_addr2default(&dst->sin6_addr); 976 } 977#endif 978 return (rip6_output(m, so, dst, control, 1)); 979 980bad: 981 VERIFY(error != 0); 982 983 if (m != NULL) 984 m_freem(m); 985 if (control != NULL) 986 m_freem(control); 987 988 return (error); 989} 990 991struct pr_usrreqs rip6_usrreqs = { 992 .pru_abort = rip6_abort, 993 .pru_attach = rip6_attach, 994 .pru_bind = rip6_bind, 995 .pru_connect = rip6_connect, 996 .pru_control = in6_control, 997 .pru_detach = rip6_detach, 998 .pru_disconnect = rip6_disconnect, 999 .pru_peeraddr = in6_getpeeraddr, 1000 .pru_send = rip6_send, 1001 .pru_shutdown = rip6_shutdown, 1002 .pru_sockaddr = in6_getsockaddr, 1003 .pru_sosend = sosend, 1004 .pru_soreceive = soreceive, 1005}; 1006 1007__private_extern__ struct pr_usrreqs icmp6_dgram_usrreqs = { 1008 .pru_abort = rip6_abort, 1009 .pru_attach = icmp6_dgram_attach, 1010 .pru_bind = rip6_bind, 1011 .pru_connect = rip6_connect, 1012 .pru_control = in6_control, 1013 .pru_detach = rip6_detach, 1014 .pru_disconnect = rip6_disconnect, 1015 .pru_peeraddr = in6_getpeeraddr, 1016 .pru_send = icmp6_dgram_send, 1017 .pru_shutdown = rip6_shutdown, 1018 .pru_sockaddr = in6_getsockaddr, 1019 .pru_sosend = sosend, 1020 .pru_soreceive = soreceive, 1021}; 1022