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