1 /* $NetBSD: udp_usrreq.c,v 1.74 2000/12/04 11:24:20 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, 1988, 1990, 1993, 1995 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_usrreq.c 8.6 (Berkeley) 5/23/95 65 */ 66 67 #include "opt_ipsec.h" 68 #include "opt_ipkdb.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/domain.h> 81 82 #include <uvm/uvm_extern.h> 83 #include <sys/sysctl.h> 84 85 #include <net/if.h> 86 #include <net/route.h> 87 88 #include <netinet/in.h> 89 #include <netinet/in_systm.h> 90 #include <netinet/in_var.h> 91 #include <netinet/ip.h> 92 #include <netinet/in_pcb.h> 93 #include <netinet/ip_var.h> 94 #include <netinet/ip_icmp.h> 95 #include <netinet/udp.h> 96 #include <netinet/udp_var.h> 97 98 #ifdef INET6 99 #include <netinet/ip6.h> 100 #include <netinet/icmp6.h> 101 #include <netinet6/ip6_var.h> 102 #include <netinet6/in6_pcb.h> 103 #include <netinet6/udp6_var.h> 104 #endif 105 106 #ifdef PULLDOWN_TEST 107 #ifndef INET6 108 /* always need ip6.h for IP6_EXTHDR_GET */ 109 #include <netinet/ip6.h> 110 #endif 111 #endif 112 113 #include <machine/stdarg.h> 114 115 #ifdef IPSEC 116 #include <netinet6/ipsec.h> 117 #include <netkey/key.h> 118 #endif /*IPSEC*/ 119 120 #ifdef IPKDB 121 #include <ipkdb/ipkdb.h> 122 #endif 123 124 /* 125 * UDP protocol implementation. 126 * Per RFC 768, August, 1980. 127 */ 128 #ifndef COMPAT_42 129 int udpcksum = 1; 130 #else 131 int udpcksum = 0; /* XXX */ 132 #endif 133 134 #ifdef INET 135 static void udp4_sendup __P((struct mbuf *, int, struct sockaddr *, 136 struct socket *)); 137 static int udp4_realinput __P((struct sockaddr_in *, struct sockaddr_in *, 138 struct mbuf *, int)); 139 #endif 140 #ifdef INET6 141 static void udp6_sendup __P((struct mbuf *, int, struct sockaddr *, 142 struct socket *)); 143 static int in6_mcmatch __P((struct in6pcb *, struct in6_addr *, 144 struct ifnet *)); 145 static int udp6_realinput __P((int, struct sockaddr_in6 *, 146 struct sockaddr_in6 *, struct mbuf *, int)); 147 #endif 148 #ifdef INET 149 static void udp_notify __P((struct inpcb *, int)); 150 #endif 151 152 #ifndef UDBHASHSIZE 153 #define UDBHASHSIZE 128 154 #endif 155 int udbhashsize = UDBHASHSIZE; 156 157 void 158 udp_init() 159 { 160 161 #ifdef INET 162 in_pcbinit(&udbtable, udbhashsize, udbhashsize); 163 #endif 164 } 165 166 #ifndef UDP6 167 #ifdef INET 168 void 169 #if __STDC__ 170 udp_input(struct mbuf *m, ...) 171 #else 172 udp_input(m, va_alist) 173 struct mbuf *m; 174 va_dcl 175 #endif 176 { 177 va_list ap; 178 struct sockaddr_in src, dst; 179 struct ip *ip; 180 struct udphdr *uh; 181 int iphlen, proto; 182 int len; 183 int n; 184 185 va_start(ap, m); 186 iphlen = va_arg(ap, int); 187 proto = va_arg(ap, int); 188 va_end(ap); 189 190 udpstat.udps_ipackets++; 191 192 #ifndef PULLDOWN_TEST 193 /* 194 * Strip IP options, if any; should skip this, 195 * make available to user, and use on returned packets, 196 * but we don't yet have a way to check the checksum 197 * with options still present. 198 */ 199 if (iphlen > sizeof (struct ip)) { 200 ip_stripoptions(m, (struct mbuf *)0); 201 iphlen = sizeof(struct ip); 202 } 203 #else 204 /* 205 * we may enable the above code if we save and pass IPv4 options 206 * to the userland. 207 */ 208 #endif 209 210 /* 211 * Get IP and UDP header together in first mbuf. 212 */ 213 ip = mtod(m, struct ip *); 214 #ifndef PULLDOWN_TEST 215 if (m->m_len < iphlen + sizeof(struct udphdr)) { 216 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) { 217 udpstat.udps_hdrops++; 218 return; 219 } 220 ip = mtod(m, struct ip *); 221 } 222 uh = (struct udphdr *)((caddr_t)ip + iphlen); 223 #else 224 IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr)); 225 if (uh == NULL) { 226 udpstat.udps_hdrops++; 227 return; 228 } 229 #endif 230 231 /* destination port of 0 is illegal, based on RFC768. */ 232 if (uh->uh_dport == 0) 233 goto bad; 234 235 /* 236 * Make mbuf data length reflect UDP length. 237 * If not enough data to reflect UDP length, drop. 238 */ 239 len = ntohs((u_int16_t)uh->uh_ulen); 240 if (ip->ip_len != iphlen + len) { 241 if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) { 242 udpstat.udps_badlen++; 243 goto bad; 244 } 245 m_adj(m, iphlen + len - ip->ip_len); 246 } 247 248 /* 249 * Checksum extended UDP header and data. 250 */ 251 if (uh->uh_sum) { 252 if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0) { 253 udpstat.udps_badsum++; 254 m_freem(m); 255 return; 256 } 257 } 258 259 /* construct source and dst sockaddrs. */ 260 bzero(&src, sizeof(src)); 261 src.sin_family = AF_INET; 262 src.sin_len = sizeof(struct sockaddr_in); 263 bcopy(&ip->ip_src, &src.sin_addr, sizeof(src.sin_addr)); 264 src.sin_port = uh->uh_sport; 265 bzero(&dst, sizeof(dst)); 266 dst.sin_family = AF_INET; 267 dst.sin_len = sizeof(struct sockaddr_in); 268 bcopy(&ip->ip_dst, &dst.sin_addr, sizeof(dst.sin_addr)); 269 dst.sin_port = uh->uh_dport; 270 271 n = udp4_realinput(&src, &dst, m, iphlen); 272 #ifdef INET6 273 if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) { 274 struct sockaddr_in6 src6, dst6; 275 276 bzero(&src6, sizeof(src6)); 277 src6.sin6_family = AF_INET6; 278 src6.sin6_len = sizeof(struct sockaddr_in6); 279 src6.sin6_addr.s6_addr[10] = src6.sin6_addr.s6_addr[11] = 0xff; 280 bcopy(&ip->ip_src, &src6.sin6_addr.s6_addr[12], 281 sizeof(ip->ip_src)); 282 src6.sin6_port = uh->uh_sport; 283 bzero(&dst6, sizeof(dst6)); 284 dst6.sin6_family = AF_INET6; 285 dst6.sin6_len = sizeof(struct sockaddr_in6); 286 dst6.sin6_addr.s6_addr[10] = dst6.sin6_addr.s6_addr[11] = 0xff; 287 bcopy(&ip->ip_dst, &dst6.sin6_addr.s6_addr[12], 288 sizeof(ip->ip_dst)); 289 dst6.sin6_port = uh->uh_dport; 290 291 n += udp6_realinput(AF_INET, &src6, &dst6, m, iphlen); 292 } 293 #endif 294 295 if (n == 0) { 296 if (m->m_flags & (M_BCAST | M_MCAST)) { 297 udpstat.udps_noportbcast++; 298 goto bad; 299 } 300 udpstat.udps_noport++; 301 #ifdef IPKDB 302 if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport, 303 m, iphlen + sizeof(struct udphdr), 304 m->m_pkthdr.len - iphlen - sizeof(struct udphdr))) { 305 /* 306 * It was a debugger connect packet, 307 * just drop it now 308 */ 309 goto bad; 310 } 311 #endif 312 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); 313 m = NULL; 314 } 315 316 bad: 317 if (m) 318 m_freem(m); 319 } 320 #endif 321 322 #ifdef INET6 323 int 324 udp6_input(mp, offp, proto) 325 struct mbuf **mp; 326 int *offp, proto; 327 { 328 struct mbuf *m = *mp; 329 int off = *offp; 330 struct sockaddr_in6 src, dst; 331 struct ip6_hdr *ip6; 332 struct udphdr *uh; 333 u_int32_t plen, ulen; 334 335 #if defined(NFAITH) && 0 < NFAITH 336 if (m->m_pkthdr.rcvif) { 337 if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { 338 /* send icmp6 host unreach? */ 339 m_freem(m); 340 return IPPROTO_DONE; 341 } 342 } 343 #endif 344 345 udp6stat.udp6s_ipackets++; 346 347 #ifndef PULLDOWN_TEST 348 IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); 349 #endif 350 351 ip6 = mtod(m, struct ip6_hdr *); 352 /* check for jumbogram is done in ip6_input. we can trust pkthdr.len */ 353 plen = m->m_pkthdr.len - off; 354 #ifndef PULLDOWN_TEST 355 uh = (struct udphdr *)((caddr_t)ip6 + off); 356 #else 357 IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr)); 358 if (uh == NULL) { 359 ip6stat.ip6s_tooshort++; 360 return IPPROTO_DONE; 361 } 362 #endif 363 ulen = ntohs((u_short)uh->uh_ulen); 364 /* 365 * RFC2675 section 4: jumbograms will have 0 in the UDP header field, 366 * iff payload length > 0xffff. 367 */ 368 if (ulen == 0 && plen > 0xffff) 369 ulen = plen; 370 371 if (plen != ulen) { 372 udp6stat.udp6s_badlen++; 373 goto bad; 374 } 375 376 /* destination port of 0 is illegal, based on RFC768. */ 377 if (uh->uh_dport == 0) 378 goto bad; 379 380 /* Be proactive about malicious use of IPv4 mapped address */ 381 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || 382 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { 383 /* XXX stat */ 384 goto bad; 385 } 386 387 /* 388 * Checksum extended UDP header and data. 389 */ 390 if (uh->uh_sum == 0) 391 udp6stat.udp6s_nosum++; 392 else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) { 393 udp6stat.udp6s_badsum++; 394 goto bad; 395 } 396 397 /* 398 * Construct source and dst sockaddrs. 399 * Note that ifindex (s6_addr16[1]) is already filled. 400 */ 401 bzero(&src, sizeof(src)); 402 src.sin6_family = AF_INET6; 403 src.sin6_len = sizeof(struct sockaddr_in6); 404 /* KAME hack: recover scopeid */ 405 (void)in6_recoverscope(&src, &ip6->ip6_src, m->m_pkthdr.rcvif); 406 src.sin6_port = uh->uh_sport; 407 bzero(&dst, sizeof(dst)); 408 dst.sin6_family = AF_INET6; 409 dst.sin6_len = sizeof(struct sockaddr_in6); 410 /* KAME hack: recover scopeid */ 411 (void)in6_recoverscope(&dst, &ip6->ip6_dst, m->m_pkthdr.rcvif); 412 dst.sin6_port = uh->uh_dport; 413 414 if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) { 415 if (m->m_flags & M_MCAST) { 416 udp6stat.udp6s_noportmcast++; 417 goto bad; 418 } 419 udp6stat.udp6s_noport++; 420 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); 421 m = NULL; 422 } 423 424 bad: 425 if (m) 426 m_freem(m); 427 return IPPROTO_DONE; 428 } 429 #endif 430 431 #ifdef INET 432 static void 433 udp4_sendup(m, off, src, so) 434 struct mbuf *m; 435 int off; /* offset of data portion */ 436 struct sockaddr *src; 437 struct socket *so; 438 { 439 struct mbuf *opts = NULL; 440 struct mbuf *n; 441 struct inpcb *inp = NULL; 442 #ifdef INET6 443 struct in6pcb *in6p = NULL; 444 #endif 445 446 if (!so) 447 return; 448 switch (so->so_proto->pr_domain->dom_family) { 449 case AF_INET: 450 inp = sotoinpcb(so); 451 break; 452 #ifdef INET6 453 case AF_INET6: 454 in6p = sotoin6pcb(so); 455 break; 456 #endif 457 default: 458 return; 459 } 460 461 #ifdef IPSEC 462 /* check AH/ESP integrity. */ 463 if (so != NULL && ipsec4_in_reject_so(m, so)) { 464 ipsecstat.in_polvio++; 465 return; 466 } 467 #endif /*IPSEC*/ 468 469 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 470 if (inp && (inp->inp_flags & INP_CONTROLOPTS 471 || so->so_options & SO_TIMESTAMP)) { 472 struct ip *ip = mtod(n, struct ip *); 473 ip_savecontrol(inp, &opts, ip, n); 474 } 475 476 m_adj(n, off); 477 if (sbappendaddr(&so->so_rcv, src, n, 478 opts) == 0) { 479 m_freem(n); 480 if (opts) 481 m_freem(opts); 482 } else 483 sorwakeup(so); 484 } 485 } 486 #endif 487 488 #ifdef INET6 489 static void 490 udp6_sendup(m, off, src, so) 491 struct mbuf *m; 492 int off; /* offset of data portion */ 493 struct sockaddr *src; 494 struct socket *so; 495 { 496 struct mbuf *opts = NULL; 497 struct mbuf *n; 498 struct in6pcb *in6p = NULL; 499 500 if (!so) 501 return; 502 if (so->so_proto->pr_domain->dom_family != AF_INET6) 503 return; 504 in6p = sotoin6pcb(so); 505 506 #ifdef IPSEC 507 /* check AH/ESP integrity. */ 508 if (so != NULL && ipsec6_in_reject_so(m, so)) { 509 ipsec6stat.in_polvio++; 510 return; 511 } 512 #endif /*IPSEC*/ 513 514 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 515 if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS 516 || in6p->in6p_socket->so_options & SO_TIMESTAMP)) { 517 struct ip6_hdr *ip6 = mtod(n, struct ip6_hdr *); 518 ip6_savecontrol(in6p, &opts, ip6, n); 519 } 520 521 m_adj(n, off); 522 if (sbappendaddr(&so->so_rcv, src, n, opts) == 0) { 523 m_freem(n); 524 if (opts) 525 m_freem(opts); 526 udp6stat.udp6s_fullsock++; 527 } else 528 sorwakeup(so); 529 } 530 } 531 #endif 532 533 #ifdef INET 534 static int 535 udp4_realinput(src, dst, m, off) 536 struct sockaddr_in *src; 537 struct sockaddr_in *dst; 538 struct mbuf *m; 539 int off; /* offset of udphdr */ 540 { 541 u_int16_t *sport, *dport; 542 int rcvcnt; 543 struct in_addr *src4, *dst4; 544 struct inpcb *inp; 545 546 rcvcnt = 0; 547 off += sizeof(struct udphdr); /* now, offset of payload */ 548 549 if (src->sin_family != AF_INET || dst->sin_family != AF_INET) 550 goto bad; 551 552 src4 = &src->sin_addr; 553 sport = &src->sin_port; 554 dst4 = &dst->sin_addr; 555 dport = &dst->sin_port; 556 557 if (IN_MULTICAST(dst4->s_addr) || 558 in_broadcast(*dst4, m->m_pkthdr.rcvif)) { 559 struct inpcb *last; 560 /* 561 * Deliver a multicast or broadcast datagram to *all* sockets 562 * for which the local and remote addresses and ports match 563 * those of the incoming datagram. This allows more than 564 * one process to receive multi/broadcasts on the same port. 565 * (This really ought to be done for unicast datagrams as 566 * well, but that would cause problems with existing 567 * applications that open both address-specific sockets and 568 * a wildcard socket listening to the same port -- they would 569 * end up receiving duplicates of every unicast datagram. 570 * Those applications open the multiple sockets to overcome an 571 * inadequacy of the UDP socket interface, but for backwards 572 * compatibility we avoid the problem here rather than 573 * fixing the interface. Maybe 4.5BSD will remedy this?) 574 */ 575 576 /* 577 * KAME note: usually we drop udpiphdr from mbuf here. 578 * we need udpiphdr for IPsec processing so we do that later. 579 */ 580 /* 581 * Locate pcb(s) for datagram. 582 */ 583 for (inp = udbtable.inpt_queue.cqh_first; 584 inp != (struct inpcb *)&udbtable.inpt_queue; 585 inp = inp->inp_queue.cqe_next) { 586 if (inp->inp_lport != *dport) 587 continue; 588 if (!in_nullhost(inp->inp_laddr)) { 589 if (!in_hosteq(inp->inp_laddr, *dst4)) 590 continue; 591 } 592 if (!in_nullhost(inp->inp_faddr)) { 593 if (!in_hosteq(inp->inp_faddr, *src4) || 594 inp->inp_fport != *sport) 595 continue; 596 } 597 598 last = inp; 599 udp4_sendup(m, off, (struct sockaddr *)src, 600 inp->inp_socket); 601 rcvcnt++; 602 603 /* 604 * Don't look for additional matches if this one does 605 * not have either the SO_REUSEPORT or SO_REUSEADDR 606 * socket options set. This heuristic avoids searching 607 * through all pcbs in the common case of a non-shared 608 * port. It assumes that an application will never 609 * clear these options after setting them. 610 */ 611 if ((inp->inp_socket->so_options & 612 (SO_REUSEPORT|SO_REUSEADDR)) == 0) 613 break; 614 } 615 616 #if 0 617 if (last == NULL) { 618 /* 619 * No matching pcb found; discard datagram. 620 * (No need to send an ICMP Port Unreachable 621 * for a broadcast or multicast datgram.) 622 */ 623 udpstat.udps_noportbcast++; 624 goto bad; 625 } 626 #endif 627 } else { 628 /* 629 * Locate pcb for datagram. 630 */ 631 inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4, *dport); 632 if (inp == 0) { 633 ++udpstat.udps_pcbhashmiss; 634 inp = in_pcblookup_bind(&udbtable, *dst4, *dport); 635 if (inp == 0) { 636 #if 0 637 struct mbuf *n; 638 639 if (m->m_flags & (M_BCAST | M_MCAST)) { 640 udpstat.udps_noportbcast++; 641 goto bad; 642 } 643 udpstat.udps_noport++; 644 #ifdef IPKDB 645 if (checkipkdb(src4, *sport, *dport, m, off, 646 m->m_pkthdr.len - off)) { 647 /* 648 * It was a debugger connect packet, 649 * just drop it now 650 */ 651 goto bad; 652 } 653 #endif 654 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 655 icmp_error(n, ICMP_UNREACH, 656 ICMP_UNREACH_PORT, 0, 0); 657 } 658 #endif 659 return rcvcnt; 660 } 661 } 662 663 udp4_sendup(m, off, (struct sockaddr *)src, inp->inp_socket); 664 rcvcnt++; 665 } 666 667 bad: 668 return rcvcnt; 669 } 670 #endif 671 672 #ifdef INET6 673 static int 674 in6_mcmatch(in6p, ia6, ifp) 675 struct in6pcb *in6p; 676 struct in6_addr *ia6; 677 struct ifnet *ifp; 678 { 679 struct ip6_moptions *im6o = in6p->in6p_moptions; 680 struct in6_multi_mship *imm; 681 682 if (im6o == NULL) 683 return 0; 684 685 for (imm = im6o->im6o_memberships.lh_first; imm != NULL; 686 imm = imm->i6mm_chain.le_next) { 687 if ((ifp == NULL || 688 imm->i6mm_maddr->in6m_ifp == ifp) && 689 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, 690 ia6)) 691 return 1; 692 } 693 return 0; 694 } 695 696 static int 697 udp6_realinput(af, src, dst, m, off) 698 int af; /* af on packet */ 699 struct sockaddr_in6 *src; 700 struct sockaddr_in6 *dst; 701 struct mbuf *m; 702 int off; /* offset of udphdr */ 703 { 704 u_int16_t *sport, *dport; 705 int rcvcnt; 706 struct in6_addr *src6, *dst6; 707 struct in_addr *dst4; 708 struct in6pcb *in6p; 709 710 rcvcnt = 0; 711 off += sizeof(struct udphdr); /* now, offset of payload */ 712 713 if (af != AF_INET && af != AF_INET6) 714 goto bad; 715 if (src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6) 716 goto bad; 717 718 src6 = &src->sin6_addr; 719 sport = &src->sin6_port; 720 dst6 = &dst->sin6_addr; 721 dport = &dst->sin6_port; 722 dst4 = (struct in_addr *)&dst->sin6_addr.s6_addr32[12]; 723 724 if (IN6_IS_ADDR_MULTICAST(dst6) 725 || (af == AF_INET && IN_MULTICAST(dst4->s_addr))) { 726 struct in6pcb *last; 727 /* 728 * Deliver a multicast or broadcast datagram to *all* sockets 729 * for which the local and remote addresses and ports match 730 * those of the incoming datagram. This allows more than 731 * one process to receive multi/broadcasts on the same port. 732 * (This really ought to be done for unicast datagrams as 733 * well, but that would cause problems with existing 734 * applications that open both address-specific sockets and 735 * a wildcard socket listening to the same port -- they would 736 * end up receiving duplicates of every unicast datagram. 737 * Those applications open the multiple sockets to overcome an 738 * inadequacy of the UDP socket interface, but for backwards 739 * compatibility we avoid the problem here rather than 740 * fixing the interface. Maybe 4.5BSD will remedy this?) 741 */ 742 743 /* 744 * KAME note: usually we drop udpiphdr from mbuf here. 745 * we need udpiphdr for IPsec processing so we do that later. 746 */ 747 /* 748 * Locate pcb(s) for datagram. 749 */ 750 for (in6p = udb6.in6p_next; in6p != &udb6; 751 in6p = in6p->in6p_next) { 752 if (in6p->in6p_lport != *dport) 753 continue; 754 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) { 755 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, dst6) 756 && !in6_mcmatch(in6p, dst6, m->m_pkthdr.rcvif)) 757 continue; 758 } 759 #ifndef INET6_BINDV6ONLY 760 else { 761 if (IN6_IS_ADDR_V4MAPPED(dst6) 762 && (in6p->in6p_flags & IN6P_BINDV6ONLY)) 763 continue; 764 } 765 #endif 766 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 767 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, src6) 768 || in6p->in6p_fport != *sport) 769 continue; 770 } 771 #ifndef INET6_BINDV6ONLY 772 else { 773 if (IN6_IS_ADDR_V4MAPPED(src6) 774 && (in6p->in6p_flags & IN6P_BINDV6ONLY)) 775 continue; 776 } 777 #endif 778 779 last = in6p; 780 udp6_sendup(m, off, (struct sockaddr *)src, 781 in6p->in6p_socket); 782 rcvcnt++; 783 784 /* 785 * Don't look for additional matches if this one does 786 * not have either the SO_REUSEPORT or SO_REUSEADDR 787 * socket options set. This heuristic avoids searching 788 * through all pcbs in the common case of a non-shared 789 * port. It assumes that an application will never 790 * clear these options after setting them. 791 */ 792 if ((in6p->in6p_socket->so_options & 793 (SO_REUSEPORT|SO_REUSEADDR)) == 0) 794 break; 795 } 796 797 #if 0 798 if (last == NULL) { 799 /* 800 * No matching pcb found; discard datagram. 801 * (No need to send an ICMP Port Unreachable 802 * for a broadcast or multicast datgram.) 803 */ 804 switch (af) { 805 case AF_INET: 806 udpstat.udps_noportbcast++; 807 break; 808 case AF_INET6: 809 udp6stat.udp6s_noportmcast++; 810 break; 811 } 812 goto bad; 813 } 814 #endif 815 } else { 816 /* 817 * Locate pcb for datagram. 818 */ 819 in6p = in6_pcblookup_connect(&udb6, src6, *sport, 820 dst6, *dport, 0); 821 if (in6p == 0) { 822 ++udpstat.udps_pcbhashmiss; 823 in6p = in6_pcblookup_bind(&udb6, dst6, *dport, 0); 824 if (in6p == 0) { 825 #if 0 826 struct mbuf *n; 827 n = m_copy(m, 0, M_COPYALL); 828 switch (af) { 829 case AF_INET: 830 if (m->m_flags & (M_BCAST | M_MCAST)) { 831 udpstat.udps_noportbcast++; 832 goto bad; 833 } 834 udpstat.udps_noport++; 835 if (n != NULL) 836 icmp_error(n, ICMP_UNREACH, 837 ICMP_UNREACH_PORT, 0, 0); 838 break; 839 case AF_INET6: 840 if (m->m_flags & M_MCAST) { 841 udp6stat.udp6s_noportmcast++; 842 goto bad; 843 } 844 udp6stat.udp6s_noport++; 845 if (n != NULL) 846 icmp6_error(n, ICMP6_DST_UNREACH, 847 ICMP6_DST_UNREACH_NOPORT, 0); 848 break; 849 } 850 #endif 851 852 return rcvcnt; 853 } 854 } 855 856 udp6_sendup(m, off, (struct sockaddr *)src, in6p->in6p_socket); 857 rcvcnt++; 858 } 859 860 bad: 861 return rcvcnt; 862 } 863 #endif 864 865 #else /*UDP6*/ 866 867 void 868 #if __STDC__ 869 udp_input(struct mbuf *m, ...) 870 #else 871 udp_input(m, va_alist) 872 struct mbuf *m; 873 va_dcl 874 #endif 875 { 876 int proto; 877 struct ip *ip; 878 struct udphdr *uh; 879 struct inpcb *inp; 880 struct mbuf *opts = 0; 881 int len; 882 struct ip save_ip; 883 int iphlen; 884 va_list ap; 885 struct sockaddr_in udpsrc; 886 struct sockaddr *sa; 887 888 va_start(ap, m); 889 iphlen = va_arg(ap, int); 890 proto = va_arg(ap, int); 891 va_end(ap); 892 893 udpstat.udps_ipackets++; 894 895 /* 896 * Strip IP options, if any; should skip this, 897 * make available to user, and use on returned packets, 898 * but we don't yet have a way to check the checksum 899 * with options still present. 900 */ 901 if (iphlen > sizeof (struct ip)) { 902 ip_stripoptions(m, (struct mbuf *)0); 903 iphlen = sizeof(struct ip); 904 } 905 906 /* 907 * Get IP and UDP header together in first mbuf. 908 */ 909 ip = mtod(m, struct ip *); 910 if (m->m_len < iphlen + sizeof(struct udphdr)) { 911 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) { 912 udpstat.udps_hdrops++; 913 return; 914 } 915 ip = mtod(m, struct ip *); 916 } 917 uh = (struct udphdr *)((caddr_t)ip + iphlen); 918 919 /* destination port of 0 is illegal, based on RFC768. */ 920 if (uh->uh_dport == 0) 921 goto bad; 922 923 /* 924 * Make mbuf data length reflect UDP length. 925 * If not enough data to reflect UDP length, drop. 926 */ 927 len = ntohs((u_int16_t)uh->uh_ulen); 928 if (ip->ip_len != iphlen + len) { 929 if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) { 930 udpstat.udps_badlen++; 931 goto bad; 932 } 933 m_adj(m, iphlen + len - ip->ip_len); 934 } 935 /* 936 * Save a copy of the IP header in case we want restore it 937 * for sending an ICMP error message in response. 938 */ 939 save_ip = *ip; 940 941 /* 942 * Checksum extended UDP header and data. 943 */ 944 if (uh->uh_sum) { 945 bzero(((struct ipovly *)ip)->ih_x1, 946 sizeof ((struct ipovly *)ip)->ih_x1); 947 ((struct ipovly *)ip)->ih_len = uh->uh_ulen; 948 if (in_cksum(m, len + sizeof (struct ip)) != 0) { 949 udpstat.udps_badsum++; 950 m_freem(m); 951 return; 952 } 953 } 954 955 /* 956 * Construct sockaddr format source address. 957 */ 958 udpsrc.sin_family = AF_INET; 959 udpsrc.sin_len = sizeof(struct sockaddr_in); 960 udpsrc.sin_addr = ip->ip_src; 961 udpsrc.sin_port = uh->uh_sport; 962 bzero((caddr_t)udpsrc.sin_zero, sizeof(udpsrc.sin_zero)); 963 964 if (IN_MULTICAST(ip->ip_dst.s_addr) || 965 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { 966 struct inpcb *last; 967 /* 968 * Deliver a multicast or broadcast datagram to *all* sockets 969 * for which the local and remote addresses and ports match 970 * those of the incoming datagram. This allows more than 971 * one process to receive multi/broadcasts on the same port. 972 * (This really ought to be done for unicast datagrams as 973 * well, but that would cause problems with existing 974 * applications that open both address-specific sockets and 975 * a wildcard socket listening to the same port -- they would 976 * end up receiving duplicates of every unicast datagram. 977 * Those applications open the multiple sockets to overcome an 978 * inadequacy of the UDP socket interface, but for backwards 979 * compatibility we avoid the problem here rather than 980 * fixing the interface. Maybe 4.5BSD will remedy this?) 981 */ 982 983 iphlen += sizeof(struct udphdr); 984 /* 985 * KAME note: usually we drop udpiphdr from mbuf here. 986 * we need udpiphdr for IPsec processing so we do that later. 987 */ 988 /* 989 * Locate pcb(s) for datagram. 990 * (Algorithm copied from raw_intr().) 991 */ 992 last = NULL; 993 for (inp = udbtable.inpt_queue.cqh_first; 994 inp != (struct inpcb *)&udbtable.inpt_queue; 995 inp = inp->inp_queue.cqe_next) { 996 if (inp->inp_lport != uh->uh_dport) 997 continue; 998 if (!in_nullhost(inp->inp_laddr)) { 999 if (!in_hosteq(inp->inp_laddr, ip->ip_dst)) 1000 continue; 1001 } 1002 if (!in_nullhost(inp->inp_faddr)) { 1003 if (!in_hosteq(inp->inp_faddr, ip->ip_src) || 1004 inp->inp_fport != uh->uh_sport) 1005 continue; 1006 } 1007 1008 if (last != NULL) { 1009 struct mbuf *n; 1010 1011 #ifdef IPSEC 1012 /* check AH/ESP integrity. */ 1013 if (last != NULL && ipsec4_in_reject(m, last)) { 1014 ipsecstat.in_polvio++; 1015 /* do not inject data to pcb */ 1016 } else 1017 #endif /*IPSEC*/ 1018 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 1019 if (last->inp_flags & INP_CONTROLOPTS 1020 || last->inp_socket->so_options & 1021 SO_TIMESTAMP) { 1022 ip_savecontrol(last, &opts, 1023 ip, n); 1024 } 1025 m_adj(n, iphlen); 1026 sa = (struct sockaddr *)&udpsrc; 1027 if (sbappendaddr( 1028 &last->inp_socket->so_rcv, 1029 sa, n, opts) == 0) { 1030 m_freem(n); 1031 if (opts) 1032 m_freem(opts); 1033 } else 1034 sorwakeup(last->inp_socket); 1035 opts = 0; 1036 } 1037 } 1038 last = inp; 1039 /* 1040 * Don't look for additional matches if this one does 1041 * not have either the SO_REUSEPORT or SO_REUSEADDR 1042 * socket options set. This heuristic avoids searching 1043 * through all pcbs in the common case of a non-shared 1044 * port. It * assumes that an application will never 1045 * clear these options after setting them. 1046 */ 1047 if ((last->inp_socket->so_options & 1048 (SO_REUSEPORT|SO_REUSEADDR)) == 0) 1049 break; 1050 } 1051 1052 if (last == NULL) { 1053 /* 1054 * No matching pcb found; discard datagram. 1055 * (No need to send an ICMP Port Unreachable 1056 * for a broadcast or multicast datgram.) 1057 */ 1058 udpstat.udps_noportbcast++; 1059 goto bad; 1060 } 1061 #ifdef IPSEC 1062 /* check AH/ESP integrity. */ 1063 if (last != NULL && ipsec4_in_reject(m, last)) { 1064 ipsecstat.in_polvio++; 1065 goto bad; 1066 } 1067 #endif /*IPSEC*/ 1068 if (last->inp_flags & INP_CONTROLOPTS || 1069 last->inp_socket->so_options & SO_TIMESTAMP) 1070 ip_savecontrol(last, &opts, ip, m); 1071 m->m_len -= iphlen; 1072 m->m_pkthdr.len -= iphlen; 1073 m->m_data += iphlen; 1074 sa = (struct sockaddr *)&udpsrc; 1075 if (sbappendaddr(&last->inp_socket->so_rcv, sa, m, opts) == 0) { 1076 udpstat.udps_fullsock++; 1077 goto bad; 1078 } 1079 sorwakeup(last->inp_socket); 1080 return; 1081 } 1082 /* 1083 * Locate pcb for datagram. 1084 */ 1085 inp = in_pcblookup_connect(&udbtable, ip->ip_src, uh->uh_sport, 1086 ip->ip_dst, uh->uh_dport); 1087 if (inp == 0) { 1088 ++udpstat.udps_pcbhashmiss; 1089 inp = in_pcblookup_bind(&udbtable, ip->ip_dst, uh->uh_dport); 1090 if (inp == 0) { 1091 if (m->m_flags & (M_BCAST | M_MCAST)) { 1092 udpstat.udps_noportbcast++; 1093 goto bad; 1094 } 1095 udpstat.udps_noport++; 1096 *ip = save_ip; 1097 #ifdef IPKDB 1098 if (checkipkdb(&ip->ip_src, 1099 uh->uh_sport, 1100 uh->uh_dport, 1101 m, 1102 iphlen + sizeof(struct udphdr), 1103 len - sizeof(struct udphdr))) 1104 /* It was a debugger connect packet, just drop it now */ 1105 goto bad; 1106 #endif 1107 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); 1108 return; 1109 } 1110 } 1111 #ifdef IPSEC 1112 if (inp != NULL && ipsec4_in_reject(m, inp)) { 1113 ipsecstat.in_polvio++; 1114 goto bad; 1115 } 1116 #endif /*IPSEC*/ 1117 1118 /* 1119 * Stuff source address and datagram in user buffer. 1120 */ 1121 if (inp->inp_flags & INP_CONTROLOPTS || 1122 inp->inp_socket->so_options & SO_TIMESTAMP) 1123 ip_savecontrol(inp, &opts, ip, m); 1124 iphlen += sizeof(struct udphdr); 1125 m->m_len -= iphlen; 1126 m->m_pkthdr.len -= iphlen; 1127 m->m_data += iphlen; 1128 sa = (struct sockaddr *)&udpsrc; 1129 if (sbappendaddr(&inp->inp_socket->so_rcv, sa, m, opts) == 0) { 1130 udpstat.udps_fullsock++; 1131 goto bad; 1132 } 1133 sorwakeup(inp->inp_socket); 1134 return; 1135 bad: 1136 m_freem(m); 1137 if (opts) 1138 m_freem(opts); 1139 } 1140 #endif /*UDP6*/ 1141 1142 #ifdef INET 1143 /* 1144 * Notify a udp user of an asynchronous error; 1145 * just wake up so that he can collect error status. 1146 */ 1147 static void 1148 udp_notify(inp, errno) 1149 struct inpcb *inp; 1150 int errno; 1151 { 1152 1153 inp->inp_socket->so_error = errno; 1154 sorwakeup(inp->inp_socket); 1155 sowwakeup(inp->inp_socket); 1156 } 1157 1158 void * 1159 udp_ctlinput(cmd, sa, v) 1160 int cmd; 1161 struct sockaddr *sa; 1162 void *v; 1163 { 1164 struct ip *ip = v; 1165 struct udphdr *uh; 1166 void (*notify) __P((struct inpcb *, int)) = udp_notify; 1167 int errno; 1168 1169 if (sa->sa_family != AF_INET 1170 || sa->sa_len != sizeof(struct sockaddr_in)) 1171 return NULL; 1172 if ((unsigned)cmd >= PRC_NCMDS) 1173 return NULL; 1174 errno = inetctlerrmap[cmd]; 1175 if (PRC_IS_REDIRECT(cmd)) 1176 notify = in_rtchange, ip = 0; 1177 else if (cmd == PRC_HOSTDEAD) 1178 ip = 0; 1179 else if (errno == 0) 1180 return NULL; 1181 if (ip) { 1182 uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); 1183 in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport, 1184 ip->ip_src, uh->uh_sport, errno, notify); 1185 1186 /* XXX mapped address case */ 1187 } else 1188 in_pcbnotifyall(&udbtable, satosin(sa)->sin_addr, errno, 1189 notify); 1190 return NULL; 1191 } 1192 1193 int 1194 #if __STDC__ 1195 udp_output(struct mbuf *m, ...) 1196 #else 1197 udp_output(m, va_alist) 1198 struct mbuf *m; 1199 va_dcl 1200 #endif 1201 { 1202 struct inpcb *inp; 1203 struct udpiphdr *ui; 1204 int len = m->m_pkthdr.len; 1205 int error = 0; 1206 va_list ap; 1207 1208 va_start(ap, m); 1209 inp = va_arg(ap, struct inpcb *); 1210 va_end(ap); 1211 1212 /* 1213 * Calculate data length and get a mbuf 1214 * for UDP and IP headers. 1215 */ 1216 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); 1217 if (m == 0) { 1218 error = ENOBUFS; 1219 goto release; 1220 } 1221 1222 /* 1223 * Compute the packet length of the IP header, and 1224 * punt if the length looks bogus. 1225 */ 1226 if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { 1227 error = EMSGSIZE; 1228 goto release; 1229 } 1230 1231 /* 1232 * Fill in mbuf with extended UDP header 1233 * and addresses and length put into network format. 1234 */ 1235 ui = mtod(m, struct udpiphdr *); 1236 bzero(ui->ui_x1, sizeof ui->ui_x1); 1237 ui->ui_pr = IPPROTO_UDP; 1238 ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr)); 1239 ui->ui_src = inp->inp_laddr; 1240 ui->ui_dst = inp->inp_faddr; 1241 ui->ui_sport = inp->inp_lport; 1242 ui->ui_dport = inp->inp_fport; 1243 ui->ui_ulen = ui->ui_len; 1244 1245 /* 1246 * Stuff checksum and output datagram. 1247 */ 1248 ui->ui_sum = 0; 1249 if (udpcksum) { 1250 if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) 1251 ui->ui_sum = 0xffff; 1252 } 1253 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 1254 ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ 1255 ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ 1256 udpstat.udps_opackets++; 1257 1258 #ifdef IPSEC 1259 ipsec_setsocket(m, inp->inp_socket); 1260 #endif /*IPSEC*/ 1261 1262 return (ip_output(m, inp->inp_options, &inp->inp_route, 1263 inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), 1264 inp->inp_moptions)); 1265 1266 release: 1267 m_freem(m); 1268 return (error); 1269 } 1270 1271 int udp_sendspace = 9216; /* really max datagram size */ 1272 int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); 1273 /* 40 1K datagrams */ 1274 1275 /*ARGSUSED*/ 1276 int 1277 udp_usrreq(so, req, m, nam, control, p) 1278 struct socket *so; 1279 int req; 1280 struct mbuf *m, *nam, *control; 1281 struct proc *p; 1282 { 1283 struct inpcb *inp; 1284 int s; 1285 int error = 0; 1286 1287 if (req == PRU_CONTROL) 1288 return (in_control(so, (long)m, (caddr_t)nam, 1289 (struct ifnet *)control, p)); 1290 1291 if (req == PRU_PURGEIF) { 1292 in_purgeif((struct ifnet *)control); 1293 in_pcbpurgeif(&udbtable, (struct ifnet *)control); 1294 return (0); 1295 } 1296 1297 s = splsoftnet(); 1298 inp = sotoinpcb(so); 1299 #ifdef DIAGNOSTIC 1300 if (req != PRU_SEND && req != PRU_SENDOOB && control) 1301 panic("udp_usrreq: unexpected control mbuf"); 1302 #endif 1303 if (inp == 0 && req != PRU_ATTACH) { 1304 error = EINVAL; 1305 goto release; 1306 } 1307 1308 /* 1309 * Note: need to block udp_input while changing 1310 * the udp pcb queue and/or pcb addresses. 1311 */ 1312 switch (req) { 1313 1314 case PRU_ATTACH: 1315 if (inp != 0) { 1316 error = EISCONN; 1317 break; 1318 } 1319 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 1320 error = soreserve(so, udp_sendspace, udp_recvspace); 1321 if (error) 1322 break; 1323 } 1324 error = in_pcballoc(so, &udbtable); 1325 if (error) 1326 break; 1327 inp = sotoinpcb(so); 1328 inp->inp_ip.ip_ttl = ip_defttl; 1329 #ifdef IPSEC 1330 error = ipsec_init_policy(so, &inp->inp_sp); 1331 if (error != 0) { 1332 in_pcbdetach(inp); 1333 break; 1334 } 1335 #endif /*IPSEC*/ 1336 break; 1337 1338 case PRU_DETACH: 1339 in_pcbdetach(inp); 1340 break; 1341 1342 case PRU_BIND: 1343 error = in_pcbbind(inp, nam, p); 1344 break; 1345 1346 case PRU_LISTEN: 1347 error = EOPNOTSUPP; 1348 break; 1349 1350 case PRU_CONNECT: 1351 error = in_pcbconnect(inp, nam); 1352 if (error) 1353 break; 1354 soisconnected(so); 1355 break; 1356 1357 case PRU_CONNECT2: 1358 error = EOPNOTSUPP; 1359 break; 1360 1361 case PRU_DISCONNECT: 1362 /*soisdisconnected(so);*/ 1363 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 1364 in_pcbdisconnect(inp); 1365 inp->inp_laddr = zeroin_addr; /* XXX */ 1366 in_pcbstate(inp, INP_BOUND); /* XXX */ 1367 break; 1368 1369 case PRU_SHUTDOWN: 1370 socantsendmore(so); 1371 break; 1372 1373 case PRU_RCVD: 1374 error = EOPNOTSUPP; 1375 break; 1376 1377 case PRU_SEND: 1378 if (control && control->m_len) { 1379 m_freem(control); 1380 m_freem(m); 1381 error = EINVAL; 1382 break; 1383 } 1384 { 1385 struct in_addr laddr; /* XXX */ 1386 1387 if (nam) { 1388 laddr = inp->inp_laddr; /* XXX */ 1389 if ((so->so_state & SS_ISCONNECTED) != 0) { 1390 error = EISCONN; 1391 goto die; 1392 } 1393 error = in_pcbconnect(inp, nam); 1394 if (error) { 1395 die: 1396 m_freem(m); 1397 break; 1398 } 1399 } else { 1400 if ((so->so_state & SS_ISCONNECTED) == 0) { 1401 error = ENOTCONN; 1402 goto die; 1403 } 1404 } 1405 error = udp_output(m, inp); 1406 if (nam) { 1407 in_pcbdisconnect(inp); 1408 inp->inp_laddr = laddr; /* XXX */ 1409 in_pcbstate(inp, INP_BOUND); /* XXX */ 1410 } 1411 } 1412 break; 1413 1414 case PRU_SENSE: 1415 /* 1416 * stat: don't bother with a blocksize. 1417 */ 1418 splx(s); 1419 return (0); 1420 1421 case PRU_RCVOOB: 1422 error = EOPNOTSUPP; 1423 break; 1424 1425 case PRU_SENDOOB: 1426 m_freem(control); 1427 m_freem(m); 1428 error = EOPNOTSUPP; 1429 break; 1430 1431 case PRU_SOCKADDR: 1432 in_setsockaddr(inp, nam); 1433 break; 1434 1435 case PRU_PEERADDR: 1436 in_setpeeraddr(inp, nam); 1437 break; 1438 1439 default: 1440 panic("udp_usrreq"); 1441 } 1442 1443 release: 1444 splx(s); 1445 return (error); 1446 } 1447 1448 /* 1449 * Sysctl for udp variables. 1450 */ 1451 int 1452 udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 1453 int *name; 1454 u_int namelen; 1455 void *oldp; 1456 size_t *oldlenp; 1457 void *newp; 1458 size_t newlen; 1459 { 1460 /* All sysctl names at this level are terminal. */ 1461 if (namelen != 1) 1462 return (ENOTDIR); 1463 1464 switch (name[0]) { 1465 case UDPCTL_CHECKSUM: 1466 return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum)); 1467 case UDPCTL_SENDSPACE: 1468 return (sysctl_int(oldp, oldlenp, newp, newlen, 1469 &udp_sendspace)); 1470 case UDPCTL_RECVSPACE: 1471 return (sysctl_int(oldp, oldlenp, newp, newlen, 1472 &udp_recvspace)); 1473 default: 1474 return (ENOPROTOOPT); 1475 } 1476 /* NOTREACHED */ 1477 } 1478 #endif 1479