1 /* $NetBSD: udp6_usrreq.c,v 1.16 1999/12/22 04:03:03 itojun Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1982, 1986, 1989, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 65 */ 66 67 #ifdef __NetBSD__ /*XXX*/ 68 #include "opt_ipsec.h" 69 #endif 70 71 #include <sys/param.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/errno.h> 78 #include <sys/stat.h> 79 #include <sys/systm.h> 80 #ifdef __NetBSD__ 81 #include <sys/proc.h> 82 #endif 83 #include <sys/syslog.h> 84 85 #include <net/if.h> 86 #include <net/route.h> 87 #include <net/if_types.h> 88 89 #include <netinet/in.h> 90 #include <netinet/in_var.h> 91 #include <netinet/in_systm.h> 92 #include <netinet/ip.h> 93 #include <netinet/ip_var.h> 94 #include <netinet/in_pcb.h> 95 #include <netinet/udp.h> 96 #include <netinet/udp_var.h> 97 #include <netinet6/ip6.h> 98 #include <netinet6/in6_pcb.h> 99 #include <netinet6/ip6_var.h> 100 #include <netinet6/icmp6.h> 101 #include <netinet6/udp6_var.h> 102 #include <netinet6/ip6protosw.h> 103 104 #ifdef IPSEC 105 #include <netinet6/ipsec.h> 106 #endif /*IPSEC*/ 107 108 #include "faith.h" 109 110 /* 111 * UDP protocol inplementation. 112 * Per RFC 768, August, 1980. 113 */ 114 115 struct in6pcb *udp6_last_in6pcb = &udb6; 116 117 #ifndef __NetBSD__ 118 static int in6_mcmatch __P((struct in6pcb *, struct in6_addr *, struct ifnet *)); 119 #endif 120 static void udp6_detach __P((struct in6pcb *)); 121 static void udp6_notify __P((struct in6pcb *, int)); 122 123 void 124 udp6_init() 125 { 126 udb6.in6p_next = udb6.in6p_prev = &udb6; 127 } 128 129 #ifndef __NetBSD__ 130 static int 131 in6_mcmatch(in6p, ia6, ifp) 132 struct in6pcb *in6p; 133 register struct in6_addr *ia6; 134 struct ifnet *ifp; 135 { 136 struct ip6_moptions *im6o = in6p->in6p_moptions; 137 struct in6_multi_mship *imm; 138 139 if (im6o == NULL) 140 return 0; 141 142 for (imm = im6o->im6o_memberships.lh_first; imm != NULL; 143 imm = imm->i6mm_chain.le_next) { 144 if ((ifp == NULL || 145 imm->i6mm_maddr->in6m_ifp == ifp) && 146 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, 147 ia6)) 148 return 1; 149 } 150 return 0; 151 } 152 153 int 154 udp6_input(mp, offp, proto) 155 struct mbuf **mp; 156 int *offp, proto; 157 { 158 struct mbuf *m = *mp; 159 register struct ip6_hdr *ip6; 160 register struct udphdr *uh; 161 register struct in6pcb *in6p; 162 struct mbuf *opts = 0; 163 int off = *offp; 164 u_int32_t plen, ulen; 165 struct sockaddr_in6 udp_in6; 166 167 #if defined(NFAITH) && 0 < NFAITH 168 if (m->m_pkthdr.rcvif) { 169 if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { 170 /* send icmp6 host unreach? */ 171 m_freem(m); 172 return IPPROTO_DONE; 173 } 174 } 175 #endif 176 udp6stat.udp6s_ipackets++; 177 178 ip6 = mtod(m, struct ip6_hdr *); 179 /* check for jumbogram is done in ip6_input. we can trust pkthdr.len */ 180 plen = m->m_pkthdr.len - off; 181 #ifndef PULLDOWN_TEST 182 IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); 183 uh = (struct udphdr *)((caddr_t)ip6 + off); 184 #else 185 IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udhpdr)); 186 if (uh == NULL) { 187 udp6stat.udp6s_hdrops++; 188 return IPPROTO_DONE; 189 } 190 #endif 191 ulen = ntohs((u_short)uh->uh_ulen); 192 if (ulen == 0 && plen > 0xffff) /* jumbogram */ 193 ulen = plen; 194 195 if (plen != ulen) { 196 udp6stat.udp6s_badlen++; 197 goto bad; 198 } 199 200 /* Be proactive about malicious use of IPv4 mapped address */ 201 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || 202 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { 203 /* XXX stat */ 204 goto bad; 205 } 206 207 /* 208 * Checksum extended UDP header and data. 209 */ 210 if (uh->uh_sum == 0) 211 udp6stat.udp6s_nosum++; 212 else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) { 213 udp6stat.udp6s_badsum++; 214 goto bad; 215 } 216 217 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 218 struct in6pcb *last; 219 220 /* 221 * Deliver a multicast datagram to all sockets 222 * for which the local and remote addresses and ports match 223 * those of the incoming datagram. This allows more than 224 * one process to receive multicasts on the same port. 225 * (This really ought to be done for unicast datagrams as 226 * well, but that would cause problems with existing 227 * applications that open both address-specific sockets and 228 * a wildcard socket listening to the same port -- they would 229 * end up receiving duplicates of every unicast datagram. 230 * Those applications open the multiple sockets to overcome an 231 * inadequacy of the UDP socket interface, but for backwards 232 * compatibility we avoid the problem here rather than 233 * fixing the interface. Maybe 4.5BSD will remedy this?) 234 */ 235 236 /* 237 * In a case that laddr should be set to the link-local 238 * address (this happens in RIPng), the multicast address 239 * specified in the received packet does not match with 240 * laddr. To cure this situation, the matching is relaxed 241 * if the receiving interface is the same as one specified 242 * in the socket and if the destination multicast address 243 * matches one of the multicast groups specified in the socket. 244 */ 245 246 /* 247 * Construct sockaddr format source address. 248 */ 249 bzero(&udp_in6, sizeof(udp_in6)); 250 udp_in6.sin6_len = sizeof(struct sockaddr_in6); 251 udp_in6.sin6_family = AF_INET6; 252 udp_in6.sin6_port = uh->uh_sport; 253 udp_in6.sin6_addr = ip6->ip6_src; 254 if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr)) 255 udp_in6.sin6_addr.s6_addr16[1] = 0; 256 if (m->m_pkthdr.rcvif) { 257 if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr)) { 258 udp_in6.sin6_scope_id = 259 m->m_pkthdr.rcvif->if_index; 260 } else 261 udp_in6.sin6_scope_id = 0; 262 } else 263 udp_in6.sin6_scope_id = 0; 264 /* 265 * KAME note: usually we drop udphdr from mbuf here. 266 * We need udphdr for IPsec processing so we do that later. 267 */ 268 269 /* 270 * Locate pcb(s) for datagram. 271 * (Algorithm copied from raw_intr().) 272 */ 273 last = NULL; 274 for (in6p = udb6.in6p_next; 275 in6p != &udb6; 276 in6p = in6p->in6p_next) { 277 if (in6p->in6p_lport != uh->uh_dport) 278 continue; 279 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) { 280 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, 281 &ip6->ip6_dst) && 282 !in6_mcmatch(in6p, &ip6->ip6_dst, 283 m->m_pkthdr.rcvif)) 284 continue; 285 } 286 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 287 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, 288 &ip6->ip6_src) || 289 in6p->in6p_fport != uh->uh_sport) 290 continue; 291 } 292 293 if (last != NULL) { 294 struct mbuf *n; 295 296 #ifdef IPSEC 297 /* 298 * Check AH/ESP integrity. 299 */ 300 if (last != NULL && ipsec6_in_reject(m, last)) { 301 ipsec6stat.in_polvio++; 302 /* do not inject data into pcb */ 303 } else 304 #endif /*IPSEC*/ 305 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 306 /* 307 * KAME NOTE: do not 308 * m_copy(m, offset, ...) above. 309 * sbappendaddr() expects M_PKTHDR, 310 * and m_copy() will copy M_PKTHDR 311 * only if offset is 0. 312 */ 313 if (last->in6p_flags & IN6P_CONTROLOPTS 314 || last->in6p_socket->so_options & SO_TIMESTAMP) { 315 ip6_savecontrol(last, &opts, 316 ip6, n); 317 } 318 319 m_adj(n, off + sizeof(struct udphdr)); 320 if (sbappendaddr(&last->in6p_socket->so_rcv, 321 (struct sockaddr *)&udp_in6, 322 n, opts) == 0) { 323 m_freem(n); 324 if (opts) 325 m_freem(opts); 326 udp6stat.udp6s_fullsock++; 327 } else 328 sorwakeup(last->in6p_socket); 329 opts = 0; 330 } 331 } 332 last = in6p; 333 /* 334 * Don't look for additional matches if this one does 335 * not have either the SO_REUSEPORT or SO_REUSEADDR 336 * socket options set. This heuristic avoids searching 337 * through all pcbs in the common case of a non-shared 338 * port. It assumes that an application will never 339 * clear these options after setting them. 340 */ 341 if ((last->in6p_socket->so_options & 342 (SO_REUSEPORT|SO_REUSEADDR)) == 0) 343 break; 344 } 345 346 if (last == NULL) { 347 /* 348 * No matching pcb found; discard datagram. 349 * (No need to send an ICMP Port Unreachable 350 * for a broadcast or multicast datgram.) 351 */ 352 udp6stat.udp6s_noport++; 353 udp6stat.udp6s_noportmcast++; 354 goto bad; 355 } 356 #ifdef IPSEC 357 /* 358 * Check AH/ESP integrity. 359 */ 360 if (last != NULL && ipsec6_in_reject(m, last)) { 361 ipsec6stat.in_polvio++; 362 goto bad; 363 } 364 #endif /*IPSEC*/ 365 if (last->in6p_flags & IN6P_CONTROLOPTS 366 || last->in6p_socket->so_options & SO_TIMESTAMP) { 367 ip6_savecontrol(last, &opts, ip6, m); 368 } 369 370 m_adj(m, off + sizeof(struct udphdr)); 371 if (sbappendaddr(&last->in6p_socket->so_rcv, 372 (struct sockaddr *)&udp_in6, 373 m, opts) == 0) { 374 udp6stat.udp6s_fullsock++; 375 goto bad; 376 } 377 sorwakeup(last->in6p_socket); 378 return IPPROTO_DONE; 379 } 380 /* 381 * Locate pcb for datagram. 382 */ 383 in6p = udp6_last_in6pcb; 384 if (in6p->in6p_lport != uh->uh_dport || 385 in6p->in6p_fport != uh->uh_sport || 386 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src) || 387 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) { 388 in6p = in6_pcblookup(&udb6, 389 &ip6->ip6_src, uh->uh_sport, 390 &ip6->ip6_dst, uh->uh_dport, 391 IN6PLOOKUP_WILDCARD); 392 if (in6p) 393 udp6_last_in6pcb = in6p; 394 udp6stat.udp6ps_pcbcachemiss++; 395 } 396 if (in6p == 0) { 397 udp6stat.udp6s_noport++; 398 if (m->m_flags & M_MCAST) { 399 printf("UDP6: M_MCAST is set in a unicast packet.\n"); 400 udp6stat.udp6s_noportmcast++; 401 goto bad; 402 } 403 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); 404 return IPPROTO_DONE; 405 } 406 #ifdef IPSEC 407 /* 408 * Check AH/ESP integrity. 409 */ 410 if (in6p != NULL && ipsec6_in_reject(m, in6p)) { 411 ipsec6stat.in_polvio++; 412 goto bad; 413 } 414 #endif /*IPSEC*/ 415 416 /* 417 * Construct sockaddr format source address. 418 * Stuff source address and datagram in user buffer. 419 */ 420 bzero(&udp_in6, sizeof(udp_in6)); 421 udp_in6.sin6_len = sizeof(struct sockaddr_in6); 422 udp_in6.sin6_family = AF_INET6; 423 udp_in6.sin6_port = uh->uh_sport; 424 udp_in6.sin6_addr = ip6->ip6_src; 425 if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr)) 426 udp_in6.sin6_addr.s6_addr16[1] = 0; 427 if (m->m_pkthdr.rcvif) { 428 if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr)) 429 udp_in6.sin6_scope_id = m->m_pkthdr.rcvif->if_index; 430 else 431 udp_in6.sin6_scope_id = 0; 432 } else 433 udp_in6.sin6_scope_id = 0; 434 if (in6p->in6p_flags & IN6P_CONTROLOPTS 435 || in6p->in6p_socket->so_options & SO_TIMESTAMP) { 436 ip6_savecontrol(in6p, &opts, ip6, m); 437 } 438 439 m_adj(m, off + sizeof(struct udphdr)); 440 if (sbappendaddr(&in6p->in6p_socket->so_rcv, 441 (struct sockaddr *)&udp_in6, 442 m, opts) == 0) { 443 udp6stat.udp6s_fullsock++; 444 goto bad; 445 } 446 sorwakeup(in6p->in6p_socket); 447 return IPPROTO_DONE; 448 bad: 449 if (m) 450 m_freem(m); 451 if (opts) 452 m_freem(opts); 453 return IPPROTO_DONE; 454 } 455 #endif 456 457 /* 458 * Notify a udp user of an asynchronous error; 459 * just wake up so tat he can collect error status. 460 */ 461 static void 462 udp6_notify(in6p, errno) 463 register struct in6pcb *in6p; 464 int errno; 465 { 466 in6p->in6p_socket->so_error = errno; 467 sorwakeup(in6p->in6p_socket); 468 sowwakeup(in6p->in6p_socket); 469 } 470 471 void 472 udp6_ctlinput(cmd, sa, d) 473 int cmd; 474 struct sockaddr *sa; 475 void *d; 476 { 477 register struct udphdr *uhp; 478 struct udphdr uh; 479 struct sockaddr_in6 sa6; 480 register struct ip6_hdr *ip6; 481 struct mbuf *m; 482 int off; 483 484 if (sa->sa_family != AF_INET6 || 485 sa->sa_len != sizeof(struct sockaddr_in6)) 486 return; 487 488 #if 0 489 if (cmd == PRC_IFNEWADDR) 490 in6_mrejoin(&udb6); 491 else 492 #endif 493 if (!PRC_IS_REDIRECT(cmd) && 494 ((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0)) 495 return; 496 497 /* if the parameter is from icmp6, decode it. */ 498 if (d != NULL) { 499 struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d; 500 m = ip6cp->ip6c_m; 501 ip6 = ip6cp->ip6c_ip6; 502 off = ip6cp->ip6c_off; 503 } else { 504 m = NULL; 505 ip6 = NULL; 506 } 507 508 /* translate addresses into internal form */ 509 sa6 = *(struct sockaddr_in6 *)sa; 510 if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr)) 511 sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index); 512 513 if (ip6) { 514 /* 515 * XXX: We assume that when IPV6 is non NULL, 516 * M and OFF are valid. 517 */ 518 struct in6_addr s; 519 520 /* translate addresses into internal form */ 521 memcpy(&s, &ip6->ip6_src, sizeof(s)); 522 if (IN6_IS_ADDR_LINKLOCAL(&s)) 523 s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index); 524 525 if (m->m_len < off + sizeof(uh)) { 526 /* 527 * this should be rare case, 528 * so we compromise on this copy... 529 */ 530 m_copydata(m, off, sizeof(uh), (caddr_t)&uh); 531 uhp = &uh; 532 } else 533 uhp = (struct udphdr *)(mtod(m, caddr_t) + off); 534 (void) in6_pcbnotify(&udb6, (struct sockaddr *)&sa6, 535 uhp->uh_dport, &s, 536 uhp->uh_sport, cmd, udp6_notify); 537 } else { 538 (void) in6_pcbnotify(&udb6, (struct sockaddr *)&sa6, 0, 539 &zeroin6_addr, 0, cmd, udp6_notify); 540 } 541 } 542 543 int 544 udp6_output(in6p, m, addr6, control) 545 register struct in6pcb *in6p; 546 register struct mbuf *m; 547 struct mbuf *addr6, *control; 548 { 549 register u_int32_t ulen = m->m_pkthdr.len; 550 u_int32_t plen = sizeof(struct udphdr) + ulen; 551 struct ip6_hdr *ip6; 552 struct udphdr *udp6; 553 struct in6_addr *laddr, *faddr; 554 u_short fport; 555 int error = 0; 556 struct ip6_pktopts opt, *stickyopt = in6p->in6p_outputopts; 557 int priv; 558 struct proc *p = curproc; /* XXX */ 559 int af, hlen; 560 #ifdef INET 561 struct ip *ip; 562 #endif 563 564 priv = 0; 565 if (p && !suser(p->p_ucred, &p->p_acflag)) 566 priv = 1; 567 if (control) { 568 if ((error = ip6_setpktoptions(control, &opt, priv)) != 0) 569 goto release; 570 in6p->in6p_outputopts = &opt; 571 } 572 573 if (addr6) { 574 /* 575 * IPv4 version of udp_output calls in_pcbconnect in this case, 576 * which needs splnet and affects performance. 577 * Since we saw no essential reason for calling in_pcbconnect, 578 * we get rid of such kind of logic, and call in6_selectsrc 579 * and In6_pcbsetport in order to fill in the local address 580 * and the local port. 581 */ 582 struct sockaddr_in6 *sin6 = mtod(addr6, struct sockaddr_in6 *); 583 584 if (addr6->m_len != sizeof(*sin6)) { 585 error = EINVAL; 586 goto release; 587 } 588 if (sin6->sin6_family != AF_INET6) { 589 error = EAFNOSUPPORT; 590 goto release; 591 } 592 if (sin6->sin6_port == 0) { 593 error = EADDRNOTAVAIL; 594 goto release; 595 } 596 597 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 598 error = EISCONN; 599 goto release; 600 } 601 602 faddr = &sin6->sin6_addr; 603 fport = sin6->sin6_port; /* allow 0 port */ 604 /* 605 * If the scope of the destination is link-local, 606 * embed the interface 607 * index in the address. 608 * 609 * XXX advanced-api value overrides sin6_scope_id 610 */ 611 if (IN6_IS_ADDR_LINKLOCAL(faddr) || 612 IN6_IS_ADDR_MC_LINKLOCAL(faddr)) { 613 struct ip6_pktopts *optp = in6p->in6p_outputopts; 614 struct in6_pktinfo *pi = NULL; 615 struct ifnet *oifp = NULL; 616 struct ip6_moptions *mopt = NULL; 617 618 /* 619 * XXX Boundary check is assumed to be already done in 620 * ip6_setpktoptions(). 621 */ 622 if (optp && (pi = optp->ip6po_pktinfo) && 623 pi->ipi6_ifindex) { 624 faddr->s6_addr16[1] = htons(pi->ipi6_ifindex); 625 oifp = ifindex2ifnet[pi->ipi6_ifindex]; 626 } 627 else if (IN6_IS_ADDR_MULTICAST(faddr) && 628 (mopt = in6p->in6p_moptions) && 629 mopt->im6o_multicast_ifp) { 630 oifp = mopt->im6o_multicast_ifp; 631 faddr->s6_addr16[1] = oifp->if_index; 632 } else if (sin6->sin6_scope_id) { 633 /* boundary check */ 634 if (sin6->sin6_scope_id < 0 635 || if_index < sin6->sin6_scope_id) { 636 error = ENXIO; /* XXX EINVAL? */ 637 goto release; 638 } 639 /* XXX */ 640 faddr->s6_addr16[1] = 641 htons(sin6->sin6_scope_id & 0xffff); 642 } 643 } 644 645 if (!IN6_IS_ADDR_V4MAPPED(faddr)) { 646 laddr = in6_selectsrc(sin6, in6p->in6p_outputopts, 647 in6p->in6p_moptions, 648 &in6p->in6p_route, 649 &in6p->in6p_laddr, &error); 650 } else 651 laddr = &in6p->in6p_laddr; /*XXX*/ 652 if (laddr == NULL) { 653 if (error == 0) 654 error = EADDRNOTAVAIL; 655 goto release; 656 } 657 if (in6p->in6p_lport == 0 && 658 (error = in6_pcbsetport(laddr, in6p)) != 0) 659 goto release; 660 } else { 661 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 662 error = ENOTCONN; 663 goto release; 664 } 665 laddr = &in6p->in6p_laddr; 666 faddr = &in6p->in6p_faddr; 667 fport = in6p->in6p_fport; 668 } 669 670 if (!IN6_IS_ADDR_V4MAPPED(faddr)) { 671 af = AF_INET6; 672 hlen = sizeof(struct ip6_hdr); 673 } else { 674 af = AF_INET; 675 hlen = sizeof(struct ip); 676 } 677 678 /* 679 * Calculate data length and get a mbuf 680 * for UDP and IP6 headers. 681 */ 682 M_PREPEND(m, hlen + sizeof(struct udphdr), M_DONTWAIT); 683 if (m == 0) { 684 error = ENOBUFS; 685 goto release; 686 } 687 688 /* 689 * Stuff checksum and output datagram. 690 */ 691 udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen); 692 udp6->uh_sport = in6p->in6p_lport; /* lport is always set in the PCB */ 693 udp6->uh_dport = fport; 694 if (plen <= 0xffff) 695 udp6->uh_ulen = htons((u_short)plen); 696 else 697 udp6->uh_ulen = 0; 698 udp6->uh_sum = 0; 699 700 switch (af) { 701 case AF_INET6: 702 ip6 = mtod(m, struct ip6_hdr *); 703 ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK; 704 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 705 ip6->ip6_vfc |= IPV6_VERSION; 706 #if 0 /* ip6_plen will be filled in ip6_output. */ 707 ip6->ip6_plen = htons((u_short)plen); 708 #endif 709 ip6->ip6_nxt = IPPROTO_UDP; 710 ip6->ip6_hlim = in6_selecthlim(in6p, 711 in6p->in6p_route.ro_rt ? 712 in6p->in6p_route.ro_rt->rt_ifp : NULL); 713 ip6->ip6_src = *laddr; 714 ip6->ip6_dst = *faddr; 715 716 if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP, 717 sizeof(struct ip6_hdr), plen)) == 0) { 718 udp6->uh_sum = 0xffff; 719 } 720 721 udp6stat.udp6s_opackets++; 722 #ifdef IPSEC 723 m->m_pkthdr.rcvif = (struct ifnet *)in6p->in6p_socket; 724 #endif /*IPSEC*/ 725 error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route, 726 0, in6p->in6p_moptions, NULL); 727 break; 728 case AF_INET: 729 #ifdef INET 730 /* can't transmit jumbogram over IPv4 */ 731 if (plen > 0xffff) { 732 error = EMSGSIZE; 733 goto release; 734 } 735 736 ip = mtod(m, struct ip *); 737 738 ip->ip_len = plen; 739 ip->ip_p = IPPROTO_UDP; 740 ip->ip_ttl = in6p->in6p_hops; /*XXX*/ 741 ip->ip_tos = 0; /*XXX*/ 742 bcopy(&laddr->s6_addr[12], &ip->ip_src, sizeof(ip->ip_src)); 743 bcopy(&faddr->s6_addr[12], &ip->ip_dst, sizeof(ip->ip_dst)); 744 745 udp6->uh_sum = 0; 746 if ((udp6->uh_sum = in_cksum(m, ulen)) == 0) 747 udp6->uh_sum = 0xffff; 748 749 udpstat.udps_opackets++; 750 #ifdef IPSEC 751 m->m_pkthdr.rcvif = NULL; /*XXX*/ 752 #endif /*IPSEC*/ 753 error = ip_output(m, NULL, &in6p->in6p_route, 0 /*XXX*/); 754 break; 755 #else 756 error = EAFNOSUPPORT; 757 goto release; 758 #endif 759 } 760 goto releaseopt; 761 762 release: 763 m_freem(m); 764 765 releaseopt: 766 if (control) { 767 in6p->in6p_outputopts = stickyopt; 768 m_freem(control); 769 } 770 return(error); 771 } 772 773 extern int udp6_sendspace; 774 extern int udp6_recvspace; 775 776 int 777 udp6_usrreq(so, req, m, addr6, control, p) 778 struct socket *so; 779 int req; 780 struct mbuf *m, *addr6, *control; 781 struct proc *p; 782 { 783 struct in6pcb *in6p = sotoin6pcb(so); 784 int error = 0; 785 int s; 786 787 /* 788 * MAPPED_ADDR implementation info: 789 * Mapped addr support for PRU_CONTROL is not necessary. 790 * Because typical user of PRU_CONTROL is such as ifconfig, 791 * and they don't associate any addr to their socket. Then 792 * socket family is only hint about the PRU_CONTROL'ed address 793 * family, especially when getting addrs from kernel. 794 * So AF_INET socket need to be used to control AF_INET addrs, 795 * and AF_INET6 socket for AF_INET6 addrs. 796 */ 797 if (req == PRU_CONTROL) 798 return(in6_control(so, (u_long)m, (caddr_t)addr6, 799 (struct ifnet *)control, p)); 800 801 if (in6p == NULL && req != PRU_ATTACH) { 802 error = EINVAL; 803 goto release; 804 } 805 806 switch (req) { 807 case PRU_ATTACH: 808 /* 809 * MAPPED_ADDR implementation spec: 810 * Always attach for IPv6, 811 * and only when necessary for IPv4. 812 */ 813 if (in6p != NULL) { 814 error = EINVAL; 815 break; 816 } 817 s = splsoftnet(); 818 error = in6_pcballoc(so, &udb6); 819 splx(s); 820 if (error) 821 break; 822 error = soreserve(so, udp6_sendspace, udp6_recvspace); 823 if (error) 824 break; 825 in6p = sotoin6pcb(so); 826 in6p->in6p_cksum = -1; /* just to be sure */ 827 #ifdef IPSEC 828 error = ipsec_init_policy(&in6p->in6p_sp); 829 if (error != 0) { 830 in6_pcbdetach(in6p); 831 break; 832 } 833 #endif /*IPSEC*/ 834 break; 835 836 case PRU_DETACH: 837 udp6_detach(in6p); 838 break; 839 840 case PRU_BIND: 841 s = splsoftnet(); 842 error = in6_pcbbind(in6p, addr6); 843 splx(s); 844 break; 845 846 case PRU_LISTEN: 847 error = EOPNOTSUPP; 848 break; 849 850 case PRU_CONNECT: 851 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 852 error = EISCONN; 853 break; 854 } 855 s = splsoftnet(); 856 error = in6_pcbconnect(in6p, addr6); 857 if (ip6_auto_flowlabel) { 858 in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 859 in6p->in6p_flowinfo |= 860 (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK); 861 } 862 splx(s); 863 if (error == 0) 864 soisconnected(so); 865 break; 866 867 case PRU_CONNECT2: 868 error = EOPNOTSUPP; 869 break; 870 871 case PRU_ACCEPT: 872 error = EOPNOTSUPP; 873 break; 874 875 case PRU_DISCONNECT: 876 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 877 error = ENOTCONN; 878 break; 879 } 880 s = splsoftnet(); 881 in6_pcbdisconnect(in6p); 882 bzero((caddr_t)&in6p->in6p_laddr, sizeof(in6p->in6p_laddr)); 883 splx(s); 884 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 885 break; 886 887 case PRU_SHUTDOWN: 888 socantsendmore(so); 889 break; 890 891 case PRU_SEND: 892 return(udp6_output(in6p, m, addr6, control)); 893 894 case PRU_ABORT: 895 soisdisconnected(so); 896 udp6_detach(in6p); 897 break; 898 899 case PRU_SOCKADDR: 900 in6_setsockaddr(in6p, addr6); 901 break; 902 903 case PRU_PEERADDR: 904 in6_setpeeraddr(in6p, addr6); 905 break; 906 907 case PRU_SENSE: 908 /* 909 * stat: don't bother with a blocksize 910 */ 911 return(0); 912 913 case PRU_SENDOOB: 914 case PRU_FASTTIMO: 915 case PRU_SLOWTIMO: 916 case PRU_PROTORCV: 917 case PRU_PROTOSEND: 918 error = EOPNOTSUPP; 919 break; 920 921 case PRU_RCVD: 922 case PRU_RCVOOB: 923 return(EOPNOTSUPP); /* do not free mbuf's */ 924 925 default: 926 panic("udp6_usrreq"); 927 } 928 929 release: 930 if (control) { 931 printf("udp control data unexpectedly retained\n"); 932 m_freem(control); 933 } 934 if (m) 935 m_freem(m); 936 return(error); 937 } 938 939 static void 940 udp6_detach(in6p) 941 struct in6pcb *in6p; 942 { 943 int s = splsoftnet(); 944 945 if (in6p == udp6_last_in6pcb) 946 udp6_last_in6pcb = &udb6; 947 in6_pcbdetach(in6p); 948 splx(s); 949 } 950 951 #ifdef __bsdi__ 952 int *udp6_sysvars[] = UDP6CTL_VARS; 953 954 int 955 udp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 956 int *name; 957 u_int namelen; 958 void *oldp; 959 size_t *oldlenp; 960 void *newp; 961 size_t newlen; 962 { 963 if (name[0] >= UDP6CTL_MAXID) 964 return (EOPNOTSUPP); 965 switch (name[0]) { 966 case UDP6CTL_STATS: 967 return sysctl_rdtrunc(oldp, oldlenp, newp, &udp6stat, 968 sizeof(udp6stat)); 969 970 default: 971 return (sysctl_int_arr(udp6_sysvars, name, namelen, 972 oldp, oldlenp, newp, newlen)); 973 } 974 } 975 #endif /*__bsdi__*/ 976 977 #ifdef __NetBSD__ 978 #include <vm/vm.h> 979 #include <sys/sysctl.h> 980 981 int 982 udp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 983 int *name; 984 u_int namelen; 985 void *oldp; 986 size_t *oldlenp; 987 void *newp; 988 size_t newlen; 989 { 990 /* All sysctl names at this level are terminal. */ 991 if (namelen != 1) 992 return ENOTDIR; 993 994 switch (name[0]) { 995 996 case UDP6CTL_SENDMAX: 997 return sysctl_int(oldp, oldlenp, newp, newlen, 998 &udp6_sendspace); 999 case UDP6CTL_RECVSPACE: 1000 return sysctl_int(oldp, oldlenp, newp, newlen, 1001 &udp6_recvspace); 1002 default: 1003 return ENOPROTOOPT; 1004 } 1005 /* NOTREACHED */ 1006 } 1007 #endif 1008