1 /* $NetBSD: in6_pcb.c,v 1.71 2006/05/14 21:19:34 elad Exp $ */ 2 /* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun 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, 1991, 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 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 62 */ 63 64 #include <sys/cdefs.h> 65 __KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.71 2006/05/14 21:19:34 elad Exp $"); 66 67 #include "opt_inet.h" 68 #include "opt_ipsec.h" 69 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/malloc.h> 73 #include <sys/mbuf.h> 74 #include <sys/protosw.h> 75 #include <sys/socket.h> 76 #include <sys/socketvar.h> 77 #include <sys/ioctl.h> 78 #include <sys/errno.h> 79 #include <sys/time.h> 80 #include <sys/proc.h> 81 #include <sys/kauth.h> 82 83 #include <net/if.h> 84 #include <net/route.h> 85 86 #include <netinet/in.h> 87 #include <netinet/in_var.h> 88 #include <netinet/in_systm.h> 89 #include <netinet/ip.h> 90 #include <netinet/in_pcb.h> 91 #include <netinet/ip6.h> 92 #include <netinet6/ip6_var.h> 93 #include <netinet6/in6_pcb.h> 94 #include <netinet6/scope6_var.h> 95 #include <netinet6/nd6.h> 96 97 #include "faith.h" 98 99 #ifdef IPSEC 100 #include <netinet6/ipsec.h> 101 #include <netkey/key.h> 102 #endif /* IPSEC */ 103 104 #ifdef FAST_IPSEC 105 #include <netipsec/ipsec.h> 106 #include <netipsec/ipsec6.h> 107 #include <netipsec/key.h> 108 #endif /* FAST_IPSEC */ 109 110 struct in6_addr zeroin6_addr; 111 112 #define IN6PCBHASH_PORT(table, lport) \ 113 &(table)->inpt_porthashtbl[ntohs(lport) & (table)->inpt_porthash] 114 #define IN6PCBHASH_BIND(table, laddr, lport) \ 115 &(table)->inpt_bindhashtbl[ \ 116 (((laddr)->s6_addr32[0] ^ (laddr)->s6_addr32[1] ^ \ 117 (laddr)->s6_addr32[2] ^ (laddr)->s6_addr32[3]) + ntohs(lport)) & \ 118 (table)->inpt_bindhash] 119 #define IN6PCBHASH_CONNECT(table, faddr, fport, laddr, lport) \ 120 &(table)->inpt_bindhashtbl[ \ 121 ((((faddr)->s6_addr32[0] ^ (faddr)->s6_addr32[1] ^ \ 122 (faddr)->s6_addr32[2] ^ (faddr)->s6_addr32[3]) + ntohs(fport)) + \ 123 (((laddr)->s6_addr32[0] ^ (laddr)->s6_addr32[1] ^ \ 124 (laddr)->s6_addr32[2] ^ (laddr)->s6_addr32[3]) + \ 125 ntohs(lport))) & (table)->inpt_bindhash] 126 127 int ip6_anonportmin = IPV6PORT_ANONMIN; 128 int ip6_anonportmax = IPV6PORT_ANONMAX; 129 int ip6_lowportmin = IPV6PORT_RESERVEDMIN; 130 int ip6_lowportmax = IPV6PORT_RESERVEDMAX; 131 132 POOL_INIT(in6pcb_pool, sizeof(struct in6pcb), 0, 0, 0, "in6pcbpl", NULL); 133 134 void 135 in6_pcbinit(table, bindhashsize, connecthashsize) 136 struct inpcbtable *table; 137 int bindhashsize, connecthashsize; 138 { 139 140 in_pcbinit(table, bindhashsize, connecthashsize); 141 table->inpt_lastport = (u_int16_t)ip6_anonportmax; 142 } 143 144 int 145 in6_pcballoc(so, v) 146 struct socket *so; 147 void *v; 148 { 149 struct inpcbtable *table = v; 150 struct in6pcb *in6p; 151 int s; 152 #if defined(IPSEC) || defined(FAST_IPSEC) 153 int error; 154 #endif 155 156 in6p = pool_get(&in6pcb_pool, PR_NOWAIT); 157 if (in6p == NULL) 158 return (ENOBUFS); 159 bzero((caddr_t)in6p, sizeof(*in6p)); 160 in6p->in6p_af = AF_INET6; 161 in6p->in6p_table = table; 162 in6p->in6p_socket = so; 163 in6p->in6p_hops = -1; /* use kernel default */ 164 in6p->in6p_icmp6filt = NULL; 165 #if defined(IPSEC) || defined(FAST_IPSEC) 166 error = ipsec_init_pcbpolicy(so, &in6p->in6p_sp); 167 if (error != 0) { 168 pool_put(&in6pcb_pool, in6p); 169 return error; 170 } 171 #endif /* IPSEC */ 172 s = splnet(); 173 CIRCLEQ_INSERT_HEAD(&table->inpt_queue, (struct inpcb_hdr*)in6p, 174 inph_queue); 175 LIST_INSERT_HEAD(IN6PCBHASH_PORT(table, in6p->in6p_lport), 176 &in6p->in6p_head, inph_lhash); 177 in6_pcbstate(in6p, IN6P_ATTACHED); 178 splx(s); 179 if (ip6_v6only) 180 in6p->in6p_flags |= IN6P_IPV6_V6ONLY; 181 so->so_pcb = (caddr_t)in6p; 182 return (0); 183 } 184 185 int 186 in6_pcbbind(v, nam, p) 187 void *v; 188 struct mbuf *nam; 189 struct proc *p; 190 { 191 struct in6pcb *in6p = v; 192 struct socket *so = in6p->in6p_socket; 193 struct inpcbtable *table = in6p->in6p_table; 194 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL; 195 u_int16_t lport = 0; 196 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); 197 198 if (in6p->in6p_af != AF_INET6) 199 return (EINVAL); 200 201 if (in6p->in6p_lport || !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) 202 return (EINVAL); 203 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && 204 ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || 205 (so->so_options & SO_ACCEPTCONN) == 0)) 206 wild = 1; 207 if (nam) { 208 int error; 209 210 sin6 = mtod(nam, struct sockaddr_in6 *); 211 if (nam->m_len != sizeof(*sin6)) 212 return (EINVAL); 213 /* 214 * We should check the family, but old programs 215 * incorrectly fail to intialize it. 216 */ 217 if (sin6->sin6_family != AF_INET6) 218 return (EAFNOSUPPORT); 219 220 #ifndef INET 221 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 222 return (EADDRNOTAVAIL); 223 #endif 224 225 if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0) 226 return (error); 227 228 lport = sin6->sin6_port; 229 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 230 /* 231 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 232 * allow compepte duplication of binding if 233 * SO_REUSEPORT is set, or if SO_REUSEADDR is set 234 * and a multicast address is bound on both 235 * new and duplicated sockets. 236 */ 237 if (so->so_options & SO_REUSEADDR) 238 reuseport = SO_REUSEADDR|SO_REUSEPORT; 239 } else if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 240 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 241 return (EINVAL); 242 if (sin6->sin6_addr.s6_addr32[3]) { 243 struct sockaddr_in sin; 244 245 bzero(&sin, sizeof(sin)); 246 sin.sin_len = sizeof(sin); 247 sin.sin_family = AF_INET; 248 bcopy(&sin6->sin6_addr.s6_addr32[3], 249 &sin.sin_addr, sizeof(sin.sin_addr)); 250 if (ifa_ifwithaddr((struct sockaddr *)&sin) == 0) 251 return EADDRNOTAVAIL; 252 } 253 } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 254 struct ifaddr *ia = NULL; 255 256 sin6->sin6_port = 0; /* yech... */ 257 if ((in6p->in6p_flags & IN6P_FAITH) == 0 && 258 (ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0) 259 return (EADDRNOTAVAIL); 260 261 /* 262 * bind to an anycast address might accidentally 263 * cause sending a packet with an anycast source 264 * address, so we forbid it. 265 * 266 * We should allow to bind to a deprecated address, 267 * since the application dare to use it. 268 * But, can we assume that they are careful enough 269 * to check if the address is deprecated or not? 270 * Maybe, as a safeguard, we should have a setsockopt 271 * flag to control the bind(2) behavior against 272 * deprecated addresses (default: forbid bind(2)). 273 */ 274 if (ia && 275 ((struct in6_ifaddr *)ia)->ia6_flags & 276 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) 277 return (EADDRNOTAVAIL); 278 } 279 if (lport) { 280 #ifndef IPNOPRIVPORTS 281 int priv; 282 283 /* 284 * NOTE: all operating systems use suser() for 285 * privilege check! do not rewrite it into SS_PRIV. 286 */ 287 priv = (p && !kauth_authorize_generic(p->p_cred, 288 KAUTH_GENERIC_ISSUSER, &p->p_acflag)) ? 1 : 0; 289 /* GROSS */ 290 if (ntohs(lport) < IPV6PORT_RESERVED && !priv) 291 return (EACCES); 292 #endif 293 294 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 295 #ifdef INET 296 struct inpcb *t; 297 298 t = in_pcblookup_port(table, 299 *(struct in_addr *)&sin6->sin6_addr.s6_addr32[3], 300 lport, wild); 301 if (t && (reuseport & t->inp_socket->so_options) == 0) 302 return (EADDRINUSE); 303 #else 304 return (EADDRNOTAVAIL); 305 #endif 306 } 307 308 { 309 struct in6pcb *t; 310 311 t = in6_pcblookup_port(table, &sin6->sin6_addr, 312 lport, wild); 313 if (t && (reuseport & t->in6p_socket->so_options) == 0) 314 return (EADDRINUSE); 315 } 316 } 317 in6p->in6p_laddr = sin6->sin6_addr; 318 } 319 320 if (lport == 0) { 321 int e; 322 e = in6_pcbsetport(&in6p->in6p_laddr, in6p, p); 323 if (e != 0) 324 return (e); 325 } else { 326 in6p->in6p_lport = lport; 327 in6_pcbstate(in6p, IN6P_BOUND); 328 } 329 330 LIST_REMOVE(&in6p->in6p_head, inph_lhash); 331 LIST_INSERT_HEAD(IN6PCBHASH_PORT(table, in6p->in6p_lport), 332 &in6p->in6p_head, inph_lhash); 333 334 #if 0 335 in6p->in6p_flowinfo = 0; /* XXX */ 336 #endif 337 return (0); 338 } 339 340 /* 341 * Connect from a socket to a specified address. 342 * Both address and port must be specified in argument sin6. 343 * If don't have a local address for this socket yet, 344 * then pick one. 345 */ 346 int 347 in6_pcbconnect(v, nam, p) 348 void *v; 349 struct mbuf *nam; 350 struct proc *p; 351 { 352 struct in6pcb *in6p = v; 353 struct in6_addr *in6a = NULL; 354 struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *); 355 struct ifnet *ifp = NULL; /* outgoing interface */ 356 int error = 0; 357 int scope_ambiguous = 0; 358 #ifdef INET 359 struct in6_addr mapped; 360 #endif 361 struct sockaddr_in6 tmp; 362 363 (void)&in6a; /* XXX fool gcc */ 364 365 if (in6p->in6p_af != AF_INET6) 366 return (EINVAL); 367 368 if (nam->m_len != sizeof(*sin6)) 369 return (EINVAL); 370 if (sin6->sin6_family != AF_INET6) 371 return (EAFNOSUPPORT); 372 if (sin6->sin6_port == 0) 373 return (EADDRNOTAVAIL); 374 375 if (sin6->sin6_scope_id == 0 && !ip6_use_defzone) 376 scope_ambiguous = 1; 377 if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0) 378 return(error); 379 380 /* sanity check for mapped address case */ 381 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 382 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 383 return EINVAL; 384 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) 385 in6p->in6p_laddr.s6_addr16[5] = htons(0xffff); 386 if (!IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)) 387 return EINVAL; 388 } else 389 { 390 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)) 391 return EINVAL; 392 } 393 394 /* protect *sin6 from overwrites */ 395 tmp = *sin6; 396 sin6 = &tmp; 397 398 /* Source address selection. */ 399 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr) && 400 in6p->in6p_laddr.s6_addr32[3] == 0) { 401 #ifdef INET 402 struct sockaddr_in sin, *sinp; 403 404 bzero(&sin, sizeof(sin)); 405 sin.sin_len = sizeof(sin); 406 sin.sin_family = AF_INET; 407 bcopy(&sin6->sin6_addr.s6_addr32[3], &sin.sin_addr, 408 sizeof(sin.sin_addr)); 409 sinp = in_selectsrc(&sin, (struct route *)&in6p->in6p_route, 410 in6p->in6p_socket->so_options, NULL, &error); 411 if (sinp == 0) { 412 if (error == 0) 413 error = EADDRNOTAVAIL; 414 return (error); 415 } 416 bzero(&mapped, sizeof(mapped)); 417 mapped.s6_addr16[5] = htons(0xffff); 418 bcopy(&sinp->sin_addr, &mapped.s6_addr32[3], sizeof(sinp->sin_addr)); 419 in6a = &mapped; 420 #else 421 return EADDRNOTAVAIL; 422 #endif 423 } else { 424 /* 425 * XXX: in6_selectsrc might replace the bound local address 426 * with the address specified by setsockopt(IPV6_PKTINFO). 427 * Is it the intended behavior? 428 */ 429 in6a = in6_selectsrc(sin6, in6p->in6p_outputopts, 430 in6p->in6p_moptions, 431 &in6p->in6p_route, 432 &in6p->in6p_laddr, &ifp, &error); 433 if (ifp && scope_ambiguous && 434 (error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) { 435 return(error); 436 } 437 438 if (in6a == 0) { 439 if (error == 0) 440 error = EADDRNOTAVAIL; 441 return (error); 442 } 443 } 444 if (ifp == NULL && in6p->in6p_route.ro_rt) 445 ifp = in6p->in6p_route.ro_rt->rt_ifp; 446 447 in6p->in6p_ip6.ip6_hlim = (u_int8_t)in6_selecthlim(in6p, ifp); 448 449 if (in6_pcblookup_connect(in6p->in6p_table, &sin6->sin6_addr, 450 sin6->sin6_port, 451 IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) ? in6a : &in6p->in6p_laddr, 452 in6p->in6p_lport, 0)) 453 return (EADDRINUSE); 454 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) || 455 (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr) && 456 in6p->in6p_laddr.s6_addr32[3] == 0)) 457 { 458 if (in6p->in6p_lport == 0) { 459 error = in6_pcbbind(in6p, (struct mbuf *)0, p); 460 if (error != 0) 461 return error; 462 } 463 in6p->in6p_laddr = *in6a; 464 } 465 in6p->in6p_faddr = sin6->sin6_addr; 466 in6p->in6p_fport = sin6->sin6_port; 467 in6_pcbstate(in6p, IN6P_CONNECTED); 468 in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 469 if (ip6_auto_flowlabel) 470 in6p->in6p_flowinfo |= 471 (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK); 472 #if defined(IPSEC) || defined(FAST_IPSEC) 473 if (in6p->in6p_socket->so_type == SOCK_STREAM) 474 ipsec_pcbconn(in6p->in6p_sp); 475 #endif 476 return (0); 477 } 478 479 void 480 in6_pcbdisconnect(in6p) 481 struct in6pcb *in6p; 482 { 483 bzero((caddr_t)&in6p->in6p_faddr, sizeof(in6p->in6p_faddr)); 484 in6p->in6p_fport = 0; 485 in6_pcbstate(in6p, IN6P_BOUND); 486 in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 487 #if defined(IPSEC) || defined(FAST_IPSEC) 488 ipsec_pcbdisconn(in6p->in6p_sp); 489 #endif 490 if (in6p->in6p_socket->so_state & SS_NOFDREF) 491 in6_pcbdetach(in6p); 492 } 493 494 void 495 in6_pcbdetach(in6p) 496 struct in6pcb *in6p; 497 { 498 struct socket *so = in6p->in6p_socket; 499 int s; 500 501 if (in6p->in6p_af != AF_INET6) 502 return; 503 504 #if defined(IPSEC) || defined(FAST_IPSEC) 505 ipsec6_delete_pcbpolicy(in6p); 506 #endif /* IPSEC */ 507 so->so_pcb = 0; 508 sofree(so); 509 if (in6p->in6p_options) 510 m_freem(in6p->in6p_options); 511 if (in6p->in6p_outputopts) { 512 if (in6p->in6p_outputopts->ip6po_rthdr && 513 in6p->in6p_outputopts->ip6po_route.ro_rt) 514 RTFREE(in6p->in6p_outputopts->ip6po_route.ro_rt); 515 if (in6p->in6p_outputopts->ip6po_m) 516 (void)m_free(in6p->in6p_outputopts->ip6po_m); 517 free(in6p->in6p_outputopts, M_IP6OPT); 518 } 519 if (in6p->in6p_route.ro_rt) 520 rtfree(in6p->in6p_route.ro_rt); 521 ip6_freemoptions(in6p->in6p_moptions); 522 s = splnet(); 523 in6_pcbstate(in6p, IN6P_ATTACHED); 524 LIST_REMOVE(&in6p->in6p_head, inph_lhash); 525 CIRCLEQ_REMOVE(&in6p->in6p_table->inpt_queue, &in6p->in6p_head, 526 inph_queue); 527 splx(s); 528 pool_put(&in6pcb_pool, in6p); 529 } 530 531 void 532 in6_setsockaddr(in6p, nam) 533 struct in6pcb *in6p; 534 struct mbuf *nam; 535 { 536 struct sockaddr_in6 *sin6; 537 538 if (in6p->in6p_af != AF_INET6) 539 return; 540 541 nam->m_len = sizeof(*sin6); 542 sin6 = mtod(nam, struct sockaddr_in6 *); 543 bzero((caddr_t)sin6, sizeof(*sin6)); 544 sin6->sin6_family = AF_INET6; 545 sin6->sin6_len = sizeof(struct sockaddr_in6); 546 sin6->sin6_port = in6p->in6p_lport; 547 sin6->sin6_addr = in6p->in6p_laddr; 548 (void)sa6_recoverscope(sin6); /* XXX: should catch errors */ 549 } 550 551 void 552 in6_setpeeraddr(in6p, nam) 553 struct in6pcb *in6p; 554 struct mbuf *nam; 555 { 556 struct sockaddr_in6 *sin6; 557 558 if (in6p->in6p_af != AF_INET6) 559 return; 560 561 nam->m_len = sizeof(*sin6); 562 sin6 = mtod(nam, struct sockaddr_in6 *); 563 bzero((caddr_t)sin6, sizeof(*sin6)); 564 sin6->sin6_family = AF_INET6; 565 sin6->sin6_len = sizeof(struct sockaddr_in6); 566 sin6->sin6_port = in6p->in6p_fport; 567 sin6->sin6_addr = in6p->in6p_faddr; 568 (void)sa6_recoverscope(sin6); /* XXX: should catch errors */ 569 } 570 571 /* 572 * Pass some notification to all connections of a protocol 573 * associated with address dst. The local address and/or port numbers 574 * may be specified to limit the search. The "usual action" will be 575 * taken, depending on the ctlinput cmd. The caller must filter any 576 * cmds that are uninteresting (e.g., no error in the map). 577 * Call the protocol specific routine (if any) to report 578 * any errors for each matching socket. 579 * 580 * Must be called at splsoftnet. 581 * 582 * Note: src (4th arg) carries the flowlabel value on the original IPv6 583 * header, in sin6_flowinfo member. 584 */ 585 int 586 in6_pcbnotify(table, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify) 587 struct inpcbtable *table; 588 struct sockaddr *dst; 589 const struct sockaddr *src; 590 u_int fport_arg, lport_arg; 591 int cmd; 592 void *cmdarg; 593 void (*notify) __P((struct in6pcb *, int)); 594 { 595 struct in6pcb *in6p, *nin6p; 596 struct sockaddr_in6 sa6_src, *sa6_dst; 597 u_int16_t fport = fport_arg, lport = lport_arg; 598 int errno; 599 int nmatch = 0; 600 u_int32_t flowinfo; 601 602 if ((unsigned)cmd >= PRC_NCMDS || dst->sa_family != AF_INET6) 603 return 0; 604 605 sa6_dst = (struct sockaddr_in6 *)dst; 606 if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr)) 607 return 0; 608 609 /* 610 * note that src can be NULL when we get notify by local fragmentation. 611 */ 612 sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src; 613 flowinfo = sa6_src.sin6_flowinfo; 614 615 /* 616 * Redirects go to all references to the destination, 617 * and use in6_rtchange to invalidate the route cache. 618 * Dead host indications: also use in6_rtchange to invalidate 619 * the cache, and deliver the error to all the sockets. 620 * Otherwise, if we have knowledge of the local port and address, 621 * deliver only to that socket. 622 */ 623 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { 624 fport = 0; 625 lport = 0; 626 bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr)); 627 628 if (cmd != PRC_HOSTDEAD) 629 notify = in6_rtchange; 630 } 631 632 errno = inet6ctlerrmap[cmd]; 633 for (in6p = (struct in6pcb *)CIRCLEQ_FIRST(&table->inpt_queue); 634 in6p != (void *)&table->inpt_queue; 635 in6p = nin6p) { 636 nin6p = (struct in6pcb *)CIRCLEQ_NEXT(in6p, in6p_queue); 637 638 if (in6p->in6p_af != AF_INET6) 639 continue; 640 641 /* 642 * Under the following condition, notify of redirects 643 * to the pcb, without making address matches against inpcb. 644 * - redirect notification is arrived. 645 * - the inpcb is unconnected. 646 * - the inpcb is caching !RTF_HOST routing entry. 647 * - the ICMPv6 notification is from the gateway cached in the 648 * inpcb. i.e. ICMPv6 notification is from nexthop gateway 649 * the inpcb used very recently. 650 * 651 * This is to improve interaction between netbsd/openbsd 652 * redirect handling code, and inpcb route cache code. 653 * without the clause, !RTF_HOST routing entry (which carries 654 * gateway used by inpcb right before the ICMPv6 redirect) 655 * will be cached forever in unconnected inpcb. 656 * 657 * There still is a question regarding to what is TRT: 658 * - On bsdi/freebsd, RTF_HOST (cloned) routing entry will be 659 * generated on packet output. inpcb will always cache 660 * RTF_HOST routing entry so there's no need for the clause 661 * (ICMPv6 redirect will update RTF_HOST routing entry, 662 * and inpcb is caching it already). 663 * However, bsdi/freebsd are vulnerable to local DoS attacks 664 * due to the cloned routing entries. 665 * - Specwise, "destination cache" is mentioned in RFC2461. 666 * Jinmei says that it implies bsdi/freebsd behavior, itojun 667 * is not really convinced. 668 * - Having hiwat/lowat on # of cloned host route (redirect/ 669 * pmtud) may be a good idea. netbsd/openbsd has it. see 670 * icmp6_mtudisc_update(). 671 */ 672 if ((PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) && 673 IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 674 in6p->in6p_route.ro_rt && 675 !(in6p->in6p_route.ro_rt->rt_flags & RTF_HOST)) { 676 struct sockaddr_in6 *dst6; 677 678 dst6 = (struct sockaddr_in6 *)&in6p->in6p_route.ro_dst; 679 if (IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, 680 &sa6_dst->sin6_addr)) 681 goto do_notify; 682 } 683 684 /* 685 * If the error designates a new path MTU for a destination 686 * and the application (associated with this socket) wanted to 687 * know the value, notify. Note that we notify for all 688 * disconnected sockets if the corresponding application 689 * wanted. This is because some UDP applications keep sending 690 * sockets disconnected. 691 * XXX: should we avoid to notify the value to TCP sockets? 692 */ 693 if (cmd == PRC_MSGSIZE && (in6p->in6p_flags & IN6P_MTU) != 0 && 694 (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) || 695 IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &sa6_dst->sin6_addr))) { 696 ip6_notify_pmtu(in6p, (struct sockaddr_in6 *)dst, 697 (u_int32_t *)cmdarg); 698 } 699 700 /* 701 * Detect if we should notify the error. If no source and 702 * destination ports are specified, but non-zero flowinfo and 703 * local address match, notify the error. This is the case 704 * when the error is delivered with an encrypted buffer 705 * by ESP. Otherwise, just compare addresses and ports 706 * as usual. 707 */ 708 if (lport == 0 && fport == 0 && flowinfo && 709 in6p->in6p_socket != NULL && 710 flowinfo == (in6p->in6p_flowinfo & IPV6_FLOWLABEL_MASK) && 711 IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &sa6_src.sin6_addr)) 712 goto do_notify; 713 else if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, 714 &sa6_dst->sin6_addr) || 715 in6p->in6p_socket == 0 || 716 (lport && in6p->in6p_lport != lport) || 717 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) && 718 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, 719 &sa6_src.sin6_addr)) || 720 (fport && in6p->in6p_fport != fport)) 721 continue; 722 723 do_notify: 724 if (notify) 725 (*notify)(in6p, errno); 726 nmatch++; 727 } 728 return nmatch; 729 } 730 731 void 732 in6_pcbpurgeif0(table, ifp) 733 struct inpcbtable *table; 734 struct ifnet *ifp; 735 { 736 struct in6pcb *in6p, *nin6p; 737 struct ip6_moptions *im6o; 738 struct in6_multi_mship *imm, *nimm; 739 740 for (in6p = (struct in6pcb *)CIRCLEQ_FIRST(&table->inpt_queue); 741 in6p != (void *)&table->inpt_queue; 742 in6p = nin6p) { 743 nin6p = (struct in6pcb *)CIRCLEQ_NEXT(in6p, in6p_queue); 744 if (in6p->in6p_af != AF_INET6) 745 continue; 746 747 im6o = in6p->in6p_moptions; 748 if (im6o) { 749 /* 750 * Unselect the outgoing interface if it is being 751 * detached. 752 */ 753 if (im6o->im6o_multicast_ifp == ifp) 754 im6o->im6o_multicast_ifp = NULL; 755 756 /* 757 * Drop multicast group membership if we joined 758 * through the interface being detached. 759 * XXX controversial - is it really legal for kernel 760 * to force this? 761 */ 762 for (imm = im6o->im6o_memberships.lh_first; 763 imm != NULL; imm = nimm) { 764 nimm = imm->i6mm_chain.le_next; 765 if (imm->i6mm_maddr->in6m_ifp == ifp) { 766 LIST_REMOVE(imm, i6mm_chain); 767 in6_leavegroup(imm); 768 } 769 } 770 } 771 } 772 } 773 774 void 775 in6_pcbpurgeif(table, ifp) 776 struct inpcbtable *table; 777 struct ifnet *ifp; 778 { 779 struct in6pcb *in6p, *nin6p; 780 781 for (in6p = (struct in6pcb *)CIRCLEQ_FIRST(&table->inpt_queue); 782 in6p != (void *)&table->inpt_queue; 783 in6p = nin6p) { 784 nin6p = (struct in6pcb *)CIRCLEQ_NEXT(in6p, in6p_queue); 785 if (in6p->in6p_af != AF_INET6) 786 continue; 787 if (in6p->in6p_route.ro_rt != NULL && 788 in6p->in6p_route.ro_rt->rt_ifp == ifp) 789 in6_rtchange(in6p, 0); 790 } 791 } 792 793 /* 794 * Check for alternatives when higher level complains 795 * about service problems. For now, invalidate cached 796 * routing information. If the route was created dynamically 797 * (by a redirect), time to try a default gateway again. 798 */ 799 void 800 in6_losing(in6p) 801 struct in6pcb *in6p; 802 { 803 struct rtentry *rt; 804 struct rt_addrinfo info; 805 806 if (in6p->in6p_af != AF_INET6) 807 return; 808 809 if ((rt = in6p->in6p_route.ro_rt) != NULL) { 810 in6p->in6p_route.ro_rt = 0; 811 bzero((caddr_t)&info, sizeof(info)); 812 info.rti_info[RTAX_DST] = 813 (struct sockaddr *)&in6p->in6p_route.ro_dst; 814 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 815 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 816 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); 817 if (rt->rt_flags & RTF_DYNAMIC) { 818 (void)rtrequest(RTM_DELETE, rt_key(rt), 819 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 820 (struct rtentry **)0); 821 } else { 822 /* 823 * A new route can be allocated 824 * the next time output is attempted. 825 */ 826 rtfree(rt); 827 } 828 } 829 } 830 831 /* 832 * After a routing change, flush old routing 833 * and allocate a (hopefully) better one. 834 */ 835 void 836 in6_rtchange(in6p, errno) 837 struct in6pcb *in6p; 838 int errno; 839 { 840 if (in6p->in6p_af != AF_INET6) 841 return; 842 843 if (in6p->in6p_route.ro_rt) { 844 rtfree(in6p->in6p_route.ro_rt); 845 in6p->in6p_route.ro_rt = 0; 846 /* 847 * A new route can be allocated the next time 848 * output is attempted. 849 */ 850 } 851 } 852 853 struct in6pcb * 854 in6_pcblookup_port(table, laddr6, lport_arg, lookup_wildcard) 855 struct inpcbtable *table; 856 struct in6_addr *laddr6; 857 u_int lport_arg; 858 int lookup_wildcard; 859 { 860 struct inpcbhead *head; 861 struct inpcb_hdr *inph; 862 struct in6pcb *in6p, *match = 0; 863 int matchwild = 3, wildcard; 864 u_int16_t lport = lport_arg; 865 866 head = IN6PCBHASH_PORT(table, lport); 867 LIST_FOREACH(inph, head, inph_lhash) { 868 in6p = (struct in6pcb *)inph; 869 if (in6p->in6p_af != AF_INET6) 870 continue; 871 872 if (in6p->in6p_lport != lport) 873 continue; 874 wildcard = 0; 875 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr)) { 876 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 877 continue; 878 } 879 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) 880 wildcard++; 881 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)) { 882 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 883 continue; 884 if (!IN6_IS_ADDR_V4MAPPED(laddr6)) 885 continue; 886 887 /* duplicate of IPv4 logic */ 888 wildcard = 0; 889 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr) && 890 in6p->in6p_faddr.s6_addr32[3]) 891 wildcard++; 892 if (!in6p->in6p_laddr.s6_addr32[3]) { 893 if (laddr6->s6_addr32[3]) 894 wildcard++; 895 } else { 896 if (!laddr6->s6_addr32[3]) 897 wildcard++; 898 else { 899 if (in6p->in6p_laddr.s6_addr32[3] != 900 laddr6->s6_addr32[3]) 901 continue; 902 } 903 } 904 } else if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) { 905 if (IN6_IS_ADDR_V4MAPPED(laddr6)) { 906 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 907 continue; 908 } 909 if (!IN6_IS_ADDR_UNSPECIFIED(laddr6)) 910 wildcard++; 911 } else { 912 if (IN6_IS_ADDR_V4MAPPED(laddr6)) { 913 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 914 continue; 915 } 916 if (IN6_IS_ADDR_UNSPECIFIED(laddr6)) 917 wildcard++; 918 else { 919 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, 920 laddr6)) 921 continue; 922 } 923 } 924 if (wildcard && !lookup_wildcard) 925 continue; 926 if (wildcard < matchwild) { 927 match = in6p; 928 matchwild = wildcard; 929 if (matchwild == 0) 930 break; 931 } 932 } 933 return (match); 934 } 935 #undef continue 936 937 /* 938 * WARNING: return value (rtentry) could be IPv4 one if in6pcb is connected to 939 * IPv4 mapped address. 940 */ 941 struct rtentry * 942 in6_pcbrtentry(in6p) 943 struct in6pcb *in6p; 944 { 945 struct route_in6 *ro; 946 struct sockaddr_in6 *dst6; 947 948 ro = &in6p->in6p_route; 949 dst6 = (struct sockaddr_in6 *)&ro->ro_dst; 950 951 if (in6p->in6p_af != AF_INET6) 952 return (NULL); 953 954 if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || 955 !IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &in6p->in6p_faddr))) { 956 RTFREE(ro->ro_rt); 957 ro->ro_rt = (struct rtentry *)NULL; 958 } 959 #ifdef INET 960 if (ro->ro_rt == (struct rtentry *)NULL && 961 IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr)) { 962 struct sockaddr_in *dst = (struct sockaddr_in *)&ro->ro_dst; 963 964 bzero(dst, sizeof(*dst)); 965 dst->sin_family = AF_INET; 966 dst->sin_len = sizeof(struct sockaddr_in); 967 bcopy(&in6p->in6p_faddr.s6_addr32[3], &dst->sin_addr, 968 sizeof(dst->sin_addr)); 969 rtalloc((struct route *)ro); 970 } else 971 #endif 972 if (ro->ro_rt == (struct rtentry *)NULL && 973 !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 974 bzero(dst6, sizeof(*dst6)); 975 dst6->sin6_family = AF_INET6; 976 dst6->sin6_len = sizeof(struct sockaddr_in6); 977 dst6->sin6_addr = in6p->in6p_faddr; 978 rtalloc((struct route *)ro); 979 } 980 return (ro->ro_rt); 981 } 982 983 struct in6pcb * 984 in6_pcblookup_connect(table, faddr6, fport_arg, laddr6, lport_arg, faith) 985 struct inpcbtable *table; 986 struct in6_addr *faddr6; 987 const struct in6_addr *laddr6; 988 u_int fport_arg, lport_arg; 989 int faith; 990 { 991 struct inpcbhead *head; 992 struct inpcb_hdr *inph; 993 struct in6pcb *in6p; 994 u_int16_t fport = fport_arg, lport = lport_arg; 995 996 head = IN6PCBHASH_CONNECT(table, faddr6, fport, laddr6, lport); 997 LIST_FOREACH(inph, head, inph_hash) { 998 in6p = (struct in6pcb *)inph; 999 if (in6p->in6p_af != AF_INET6) 1000 continue; 1001 1002 /* find exact match on both source and dest */ 1003 if (in6p->in6p_fport != fport) 1004 continue; 1005 if (in6p->in6p_lport != lport) 1006 continue; 1007 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) 1008 continue; 1009 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, faddr6)) 1010 continue; 1011 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) 1012 continue; 1013 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, laddr6)) 1014 continue; 1015 if ((IN6_IS_ADDR_V4MAPPED(laddr6) || 1016 IN6_IS_ADDR_V4MAPPED(faddr6)) && 1017 (in6p->in6p_flags & IN6P_IPV6_V6ONLY)) 1018 continue; 1019 return in6p; 1020 } 1021 return NULL; 1022 } 1023 1024 struct in6pcb * 1025 in6_pcblookup_bind(table, laddr6, lport_arg, faith) 1026 struct inpcbtable *table; 1027 struct in6_addr *laddr6; 1028 u_int lport_arg; 1029 int faith; 1030 { 1031 struct inpcbhead *head; 1032 struct inpcb_hdr *inph; 1033 struct in6pcb *in6p; 1034 u_int16_t lport = lport_arg; 1035 #ifdef INET 1036 struct in6_addr zero_mapped; 1037 #endif 1038 1039 head = IN6PCBHASH_BIND(table, laddr6, lport); 1040 LIST_FOREACH(inph, head, inph_hash) { 1041 in6p = (struct in6pcb *)inph; 1042 if (in6p->in6p_af != AF_INET6) 1043 continue; 1044 1045 if (faith && (in6p->in6p_flags & IN6P_FAITH) == 0) 1046 continue; 1047 if (in6p->in6p_fport != 0) 1048 continue; 1049 if (in6p->in6p_lport != lport) 1050 continue; 1051 if (IN6_IS_ADDR_V4MAPPED(laddr6) && 1052 (in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 1053 continue; 1054 if (IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, laddr6)) 1055 goto out; 1056 } 1057 #ifdef INET 1058 if (IN6_IS_ADDR_V4MAPPED(laddr6)) { 1059 memset(&zero_mapped, 0, sizeof(zero_mapped)); 1060 zero_mapped.s6_addr16[5] = 0xffff; 1061 head = IN6PCBHASH_BIND(table, &zero_mapped, lport); 1062 LIST_FOREACH(inph, head, inph_hash) { 1063 in6p = (struct in6pcb *)inph; 1064 if (in6p->in6p_af != AF_INET6) 1065 continue; 1066 1067 if (faith && (in6p->in6p_flags & IN6P_FAITH) == 0) 1068 continue; 1069 if (in6p->in6p_fport != 0) 1070 continue; 1071 if (in6p->in6p_lport != lport) 1072 continue; 1073 if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 1074 continue; 1075 if (IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &zero_mapped)) 1076 goto out; 1077 } 1078 } 1079 #endif 1080 head = IN6PCBHASH_BIND(table, &zeroin6_addr, lport); 1081 LIST_FOREACH(inph, head, inph_hash) { 1082 in6p = (struct in6pcb *)inph; 1083 if (in6p->in6p_af != AF_INET6) 1084 continue; 1085 1086 if (faith && (in6p->in6p_flags & IN6P_FAITH) == 0) 1087 continue; 1088 if (in6p->in6p_fport != 0) 1089 continue; 1090 if (in6p->in6p_lport != lport) 1091 continue; 1092 if (IN6_IS_ADDR_V4MAPPED(laddr6) && 1093 (in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) 1094 continue; 1095 if (IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &zeroin6_addr)) 1096 goto out; 1097 } 1098 return (NULL); 1099 1100 out: 1101 inph = &in6p->in6p_head; 1102 if (inph != LIST_FIRST(head)) { 1103 LIST_REMOVE(inph, inph_hash); 1104 LIST_INSERT_HEAD(head, inph, inph_hash); 1105 } 1106 return in6p; 1107 } 1108 1109 void 1110 in6_pcbstate(in6p, state) 1111 struct in6pcb *in6p; 1112 int state; 1113 { 1114 1115 if (in6p->in6p_af != AF_INET6) 1116 return; 1117 1118 if (in6p->in6p_state > IN6P_ATTACHED) 1119 LIST_REMOVE(&in6p->in6p_head, inph_hash); 1120 1121 switch (state) { 1122 case IN6P_BOUND: 1123 LIST_INSERT_HEAD(IN6PCBHASH_BIND(in6p->in6p_table, 1124 &in6p->in6p_laddr, in6p->in6p_lport), &in6p->in6p_head, 1125 inph_hash); 1126 break; 1127 case IN6P_CONNECTED: 1128 LIST_INSERT_HEAD(IN6PCBHASH_CONNECT(in6p->in6p_table, 1129 &in6p->in6p_faddr, in6p->in6p_fport, 1130 &in6p->in6p_laddr, in6p->in6p_lport), &in6p->in6p_head, 1131 inph_hash); 1132 break; 1133 } 1134 1135 in6p->in6p_state = state; 1136 } 1137