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