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