udp6_usrreq.c revision 1.20
1/* $NetBSD: udp6_usrreq.c,v 1.20 2000/02/01 22:52:12 thorpej 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#include "opt_ipsec.h" 68 69#include <sys/param.h> 70#include <sys/malloc.h> 71#include <sys/mbuf.h> 72#include <sys/protosw.h> 73#include <sys/socket.h> 74#include <sys/socketvar.h> 75#include <sys/errno.h> 76#include <sys/stat.h> 77#include <sys/systm.h> 78#include <sys/proc.h> 79#include <sys/syslog.h> 80 81#include <net/if.h> 82#include <net/route.h> 83#include <net/if_types.h> 84 85#include <netinet/in.h> 86#include <netinet/in_var.h> 87#include <netinet/in_systm.h> 88#include <netinet/ip.h> 89#include <netinet/ip_var.h> 90#include <netinet/in_pcb.h> 91#include <netinet/udp.h> 92#include <netinet/udp_var.h> 93#include <netinet6/ip6.h> 94#include <netinet6/in6_pcb.h> 95#include <netinet6/ip6_var.h> 96#include <netinet6/icmp6.h> 97#include <netinet6/udp6_var.h> 98#include <netinet6/ip6protosw.h> 99 100#ifdef IPSEC 101#include <netinet6/ipsec.h> 102#endif /*IPSEC*/ 103 104#include "faith.h" 105 106/* 107 * UDP protocol inplementation. 108 * Per RFC 768, August, 1980. 109 */ 110 111struct in6pcb *udp6_last_in6pcb = &udb6; 112 113#ifdef UDP6 114static int in6_mcmatch __P((struct in6pcb *, struct in6_addr *, struct ifnet *)); 115#endif 116static void udp6_detach __P((struct in6pcb *)); 117static void udp6_notify __P((struct in6pcb *, int)); 118 119void 120udp6_init() 121{ 122 udb6.in6p_next = udb6.in6p_prev = &udb6; 123} 124 125#ifdef UDP6 126static int 127in6_mcmatch(in6p, ia6, ifp) 128 struct in6pcb *in6p; 129 register struct in6_addr *ia6; 130 struct ifnet *ifp; 131{ 132 struct ip6_moptions *im6o = in6p->in6p_moptions; 133 struct in6_multi_mship *imm; 134 135 if (im6o == NULL) 136 return 0; 137 138 for (imm = im6o->im6o_memberships.lh_first; imm != NULL; 139 imm = imm->i6mm_chain.le_next) { 140 if ((ifp == NULL || 141 imm->i6mm_maddr->in6m_ifp == ifp) && 142 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, 143 ia6)) 144 return 1; 145 } 146 return 0; 147} 148 149int 150udp6_input(mp, offp, proto) 151 struct mbuf **mp; 152 int *offp, proto; 153{ 154 struct mbuf *m = *mp; 155 register struct ip6_hdr *ip6; 156 register struct udphdr *uh; 157 register struct in6pcb *in6p; 158 struct mbuf *opts = 0; 159 int off = *offp; 160 u_int32_t plen, ulen; 161 struct sockaddr_in6 udp_in6; 162 163#if defined(NFAITH) && 0 < NFAITH 164 if (m->m_pkthdr.rcvif) { 165 if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { 166 /* send icmp6 host unreach? */ 167 m_freem(m); 168 return IPPROTO_DONE; 169 } 170 } 171#endif 172 udp6stat.udp6s_ipackets++; 173 174 ip6 = mtod(m, struct ip6_hdr *); 175 /* check for jumbogram is done in ip6_input. we can trust pkthdr.len */ 176 plen = m->m_pkthdr.len - off; 177#ifndef PULLDOWN_TEST 178 IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); 179 uh = (struct udphdr *)((caddr_t)ip6 + off); 180#else 181 IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udhpdr)); 182 if (uh == NULL) { 183 udp6stat.udp6s_hdrops++; 184 return IPPROTO_DONE; 185 } 186#endif 187 ulen = ntohs((u_short)uh->uh_ulen); 188 if (ulen == 0 && plen > 0xffff) /* jumbogram */ 189 ulen = plen; 190 191 if (plen != ulen) { 192 udp6stat.udp6s_badlen++; 193 goto bad; 194 } 195 196 /* destination port of 0 is illegal, based on RFC768. */ 197 if (uh->uh_dport == 0) 198 goto bad; 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; 448bad: 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 */ 461static void 462udp6_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 471void 472udp6_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 543int 544udp6_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 762release: 763 m_freem(m); 764 765releaseopt: 766 if (control) { 767 in6p->in6p_outputopts = stickyopt; 768 m_freem(control); 769 } 770 return(error); 771} 772 773extern int udp6_sendspace; 774extern int udp6_recvspace; 775 776int 777udp6_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 (req == PRU_PURGEADDR) { 802 in6_purgeaddr((struct ifaddr *)addr6, (struct ifnet *)control); 803 return (0); 804 } 805 806 if (in6p == NULL && req != PRU_ATTACH) { 807 error = EINVAL; 808 goto release; 809 } 810 811 switch (req) { 812 case PRU_ATTACH: 813 /* 814 * MAPPED_ADDR implementation spec: 815 * Always attach for IPv6, 816 * and only when necessary for IPv4. 817 */ 818 if (in6p != NULL) { 819 error = EINVAL; 820 break; 821 } 822 s = splsoftnet(); 823 error = in6_pcballoc(so, &udb6); 824 splx(s); 825 if (error) 826 break; 827 error = soreserve(so, udp6_sendspace, udp6_recvspace); 828 if (error) 829 break; 830 in6p = sotoin6pcb(so); 831 in6p->in6p_cksum = -1; /* just to be sure */ 832#ifdef IPSEC 833 error = ipsec_init_policy(so, &in6p->in6p_sp); 834 if (error != 0) { 835 in6_pcbdetach(in6p); 836 break; 837 } 838#endif /*IPSEC*/ 839 break; 840 841 case PRU_DETACH: 842 udp6_detach(in6p); 843 break; 844 845 case PRU_BIND: 846 s = splsoftnet(); 847 error = in6_pcbbind(in6p, addr6); 848 splx(s); 849 break; 850 851 case PRU_LISTEN: 852 error = EOPNOTSUPP; 853 break; 854 855 case PRU_CONNECT: 856 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 857 error = EISCONN; 858 break; 859 } 860 s = splsoftnet(); 861 error = in6_pcbconnect(in6p, addr6); 862 if (ip6_auto_flowlabel) { 863 in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 864 in6p->in6p_flowinfo |= 865 (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK); 866 } 867 splx(s); 868 if (error == 0) 869 soisconnected(so); 870 break; 871 872 case PRU_CONNECT2: 873 error = EOPNOTSUPP; 874 break; 875 876 case PRU_ACCEPT: 877 error = EOPNOTSUPP; 878 break; 879 880 case PRU_DISCONNECT: 881 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 882 error = ENOTCONN; 883 break; 884 } 885 s = splsoftnet(); 886 in6_pcbdisconnect(in6p); 887 bzero((caddr_t)&in6p->in6p_laddr, sizeof(in6p->in6p_laddr)); 888 splx(s); 889 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 890 break; 891 892 case PRU_SHUTDOWN: 893 socantsendmore(so); 894 break; 895 896 case PRU_SEND: 897 return(udp6_output(in6p, m, addr6, control)); 898 899 case PRU_ABORT: 900 soisdisconnected(so); 901 udp6_detach(in6p); 902 break; 903 904 case PRU_SOCKADDR: 905 in6_setsockaddr(in6p, addr6); 906 break; 907 908 case PRU_PEERADDR: 909 in6_setpeeraddr(in6p, addr6); 910 break; 911 912 case PRU_SENSE: 913 /* 914 * stat: don't bother with a blocksize 915 */ 916 return(0); 917 918 case PRU_SENDOOB: 919 case PRU_FASTTIMO: 920 case PRU_SLOWTIMO: 921 case PRU_PROTORCV: 922 case PRU_PROTOSEND: 923 error = EOPNOTSUPP; 924 break; 925 926 case PRU_RCVD: 927 case PRU_RCVOOB: 928 return(EOPNOTSUPP); /* do not free mbuf's */ 929 930 default: 931 panic("udp6_usrreq"); 932 } 933 934release: 935 if (control) { 936 printf("udp control data unexpectedly retained\n"); 937 m_freem(control); 938 } 939 if (m) 940 m_freem(m); 941 return(error); 942} 943 944static void 945udp6_detach(in6p) 946 struct in6pcb *in6p; 947{ 948 int s = splsoftnet(); 949 950 if (in6p == udp6_last_in6pcb) 951 udp6_last_in6pcb = &udb6; 952 in6_pcbdetach(in6p); 953 splx(s); 954} 955 956#include <vm/vm.h> 957#include <sys/sysctl.h> 958 959int 960udp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 961 int *name; 962 u_int namelen; 963 void *oldp; 964 size_t *oldlenp; 965 void *newp; 966 size_t newlen; 967{ 968 /* All sysctl names at this level are terminal. */ 969 if (namelen != 1) 970 return ENOTDIR; 971 972 switch (name[0]) { 973 974 case UDP6CTL_SENDMAX: 975 return sysctl_int(oldp, oldlenp, newp, newlen, 976 &udp6_sendspace); 977 case UDP6CTL_RECVSPACE: 978 return sysctl_int(oldp, oldlenp, newp, newlen, 979 &udp6_recvspace); 980 default: 981 return ENOPROTOOPT; 982 } 983 /* NOTREACHED */ 984} 985