1 /* $NetBSD: udp_usrreq.c,v 1.85 2001/10/15 09:51:15 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_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 else { 782 if (IN6_IS_ADDR_V4MAPPED(&dst6) && 783 (in6p->in6p_flags & IN6P_IPV6_V6ONLY)) 784 continue; 785 } 786 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 787 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, 788 &src6) || in6p->in6p_fport != sport) 789 continue; 790 } 791 else { 792 if (IN6_IS_ADDR_V4MAPPED(&src6) && 793 (in6p->in6p_flags & IN6P_IPV6_V6ONLY)) 794 continue; 795 } 796 797 last = in6p; 798 udp6_sendup(m, off, (struct sockaddr *)src, 799 in6p->in6p_socket); 800 rcvcnt++; 801 802 /* 803 * Don't look for additional matches if this one does 804 * not have either the SO_REUSEPORT or SO_REUSEADDR 805 * socket options set. This heuristic avoids searching 806 * through all pcbs in the common case of a non-shared 807 * port. It assumes that an application will never 808 * clear these options after setting them. 809 */ 810 if ((in6p->in6p_socket->so_options & 811 (SO_REUSEPORT|SO_REUSEADDR)) == 0) 812 break; 813 } 814 } else { 815 /* 816 * Locate pcb for datagram. 817 */ 818 in6p = in6_pcblookup_connect(&udb6, &src6, sport, 819 &dst6, dport, 0); 820 if (in6p == 0) { 821 ++udpstat.udps_pcbhashmiss; 822 in6p = in6_pcblookup_bind(&udb6, &dst6, dport, 0); 823 if (in6p == 0) 824 return rcvcnt; 825 } 826 827 udp6_sendup(m, off, (struct sockaddr *)src, in6p->in6p_socket); 828 rcvcnt++; 829 } 830 831 bad: 832 return rcvcnt; 833 } 834 #endif 835 836 #else /*UDP6*/ 837 838 void 839 #if __STDC__ 840 udp_input(struct mbuf *m, ...) 841 #else 842 udp_input(m, va_alist) 843 struct mbuf *m; 844 va_dcl 845 #endif 846 { 847 int proto; 848 struct ip *ip; 849 struct udphdr *uh; 850 struct inpcb *inp; 851 struct mbuf *opts = 0; 852 int len; 853 struct ip save_ip; 854 int iphlen; 855 va_list ap; 856 struct sockaddr_in udpsrc; 857 struct sockaddr *sa; 858 859 va_start(ap, m); 860 iphlen = va_arg(ap, int); 861 proto = va_arg(ap, int); 862 va_end(ap); 863 864 udpstat.udps_ipackets++; 865 866 /* 867 * Strip IP options, if any; should skip this, 868 * make available to user, and use on returned packets, 869 * but we don't yet have a way to check the checksum 870 * with options still present. 871 */ 872 if (iphlen > sizeof (struct ip)) { 873 ip_stripoptions(m, (struct mbuf *)0); 874 iphlen = sizeof(struct ip); 875 } 876 877 /* 878 * Get IP and UDP header together in first mbuf. 879 */ 880 ip = mtod(m, struct ip *); 881 if (m->m_len < iphlen + sizeof(struct udphdr)) { 882 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) { 883 udpstat.udps_hdrops++; 884 return; 885 } 886 ip = mtod(m, struct ip *); 887 } 888 uh = (struct udphdr *)((caddr_t)ip + iphlen); 889 890 /* destination port of 0 is illegal, based on RFC768. */ 891 if (uh->uh_dport == 0) 892 goto bad; 893 894 /* 895 * Make mbuf data length reflect UDP length. 896 * If not enough data to reflect UDP length, drop. 897 */ 898 len = ntohs((u_int16_t)uh->uh_ulen); 899 if (ip->ip_len != iphlen + len) { 900 if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) { 901 udpstat.udps_badlen++; 902 goto bad; 903 } 904 m_adj(m, iphlen + len - ip->ip_len); 905 } 906 /* 907 * Save a copy of the IP header in case we want restore it 908 * for sending an ICMP error message in response. 909 */ 910 save_ip = *ip; 911 912 /* 913 * Checksum extended UDP header and data. 914 */ 915 if (uh->uh_sum) { 916 switch (m->m_pkthdr.csum_flags & 917 ((m->m_pkthdr.rcvif->if_csum_flags & M_CSUM_UDPv4) | 918 M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) { 919 case M_CSUM_UDPv4|M_CSUM_TCP_UDP_BAD: 920 UDP_CSUM_COUNTER_INCR(&udp_hwcsum_bad); 921 goto badcsum; 922 923 case M_CSUM_UDPv4|M_CSUM_DATA: 924 UDP_CSUM_COUNTER_INCR(&udp_hwcsum_data); 925 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) 926 goto badcsum; 927 break; 928 929 case M_CSUM_UDPv4: 930 /* Checksum was okay. */ 931 UDP_CSUM_COUNTER_INCR(&udp_hwcsum_ok); 932 break; 933 934 default: 935 /* Need to compute it ourselves. */ 936 UDP_CSUM_COUNTER_INCR(&udp_swcsum); 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 goto badcsum; 942 break; 943 } 944 } 945 946 /* 947 * Construct sockaddr format source address. 948 */ 949 udpsrc.sin_family = AF_INET; 950 udpsrc.sin_len = sizeof(struct sockaddr_in); 951 udpsrc.sin_addr = ip->ip_src; 952 udpsrc.sin_port = uh->uh_sport; 953 bzero((caddr_t)udpsrc.sin_zero, sizeof(udpsrc.sin_zero)); 954 955 if (IN_MULTICAST(ip->ip_dst.s_addr) || 956 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { 957 struct inpcb *last; 958 /* 959 * Deliver a multicast or broadcast datagram to *all* sockets 960 * for which the local and remote addresses and ports match 961 * those of the incoming datagram. This allows more than 962 * one process to receive multi/broadcasts on the same port. 963 * (This really ought to be done for unicast datagrams as 964 * well, but that would cause problems with existing 965 * applications that open both address-specific sockets and 966 * a wildcard socket listening to the same port -- they would 967 * end up receiving duplicates of every unicast datagram. 968 * Those applications open the multiple sockets to overcome an 969 * inadequacy of the UDP socket interface, but for backwards 970 * compatibility we avoid the problem here rather than 971 * fixing the interface. Maybe 4.5BSD will remedy this?) 972 */ 973 974 iphlen += sizeof(struct udphdr); 975 /* 976 * KAME note: usually we drop udpiphdr from mbuf here. 977 * we need udpiphdr for IPsec processing so we do that later. 978 */ 979 /* 980 * Locate pcb(s) for datagram. 981 * (Algorithm copied from raw_intr().) 982 */ 983 last = NULL; 984 for (inp = udbtable.inpt_queue.cqh_first; 985 inp != (struct inpcb *)&udbtable.inpt_queue; 986 inp = inp->inp_queue.cqe_next) { 987 if (inp->inp_lport != uh->uh_dport) 988 continue; 989 if (!in_nullhost(inp->inp_laddr)) { 990 if (!in_hosteq(inp->inp_laddr, ip->ip_dst)) 991 continue; 992 } 993 if (!in_nullhost(inp->inp_faddr)) { 994 if (!in_hosteq(inp->inp_faddr, ip->ip_src) || 995 inp->inp_fport != uh->uh_sport) 996 continue; 997 } 998 999 if (last != NULL) { 1000 struct mbuf *n; 1001 1002 #ifdef IPSEC 1003 /* check AH/ESP integrity. */ 1004 if (last != NULL && ipsec4_in_reject(m, last)) { 1005 ipsecstat.in_polvio++; 1006 /* do not inject data to pcb */ 1007 } else 1008 #endif /*IPSEC*/ 1009 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 1010 if (last->inp_flags & INP_CONTROLOPTS 1011 || last->inp_socket->so_options & 1012 SO_TIMESTAMP) { 1013 ip_savecontrol(last, &opts, 1014 ip, n); 1015 } 1016 m_adj(n, iphlen); 1017 sa = (struct sockaddr *)&udpsrc; 1018 if (sbappendaddr( 1019 &last->inp_socket->so_rcv, 1020 sa, n, opts) == 0) { 1021 m_freem(n); 1022 if (opts) 1023 m_freem(opts); 1024 udpstat.udps_fullsock++; 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_noportbcast++; 1051 goto bad; 1052 } 1053 #ifdef IPSEC 1054 /* check AH/ESP integrity. */ 1055 if (last != NULL && ipsec4_in_reject(m, last)) { 1056 ipsecstat.in_polvio++; 1057 goto bad; 1058 } 1059 #endif /*IPSEC*/ 1060 if (last->inp_flags & INP_CONTROLOPTS || 1061 last->inp_socket->so_options & SO_TIMESTAMP) 1062 ip_savecontrol(last, &opts, ip, m); 1063 m->m_len -= iphlen; 1064 m->m_pkthdr.len -= iphlen; 1065 m->m_data += iphlen; 1066 sa = (struct sockaddr *)&udpsrc; 1067 if (sbappendaddr(&last->inp_socket->so_rcv, sa, m, opts) == 0) { 1068 udpstat.udps_fullsock++; 1069 goto bad; 1070 } 1071 sorwakeup(last->inp_socket); 1072 return; 1073 } 1074 /* 1075 * Locate pcb for datagram. 1076 */ 1077 inp = in_pcblookup_connect(&udbtable, ip->ip_src, uh->uh_sport, 1078 ip->ip_dst, uh->uh_dport); 1079 if (inp == 0) { 1080 ++udpstat.udps_pcbhashmiss; 1081 inp = in_pcblookup_bind(&udbtable, ip->ip_dst, uh->uh_dport); 1082 if (inp == 0) { 1083 if (m->m_flags & (M_BCAST | M_MCAST)) { 1084 udpstat.udps_noportbcast++; 1085 goto bad; 1086 } 1087 udpstat.udps_noport++; 1088 *ip = save_ip; 1089 #ifdef IPKDB 1090 if (checkipkdb(&ip->ip_src, 1091 uh->uh_sport, 1092 uh->uh_dport, 1093 m, 1094 iphlen + sizeof(struct udphdr), 1095 len - sizeof(struct udphdr))) 1096 /* It was a debugger connect packet, just drop it now */ 1097 goto bad; 1098 #endif 1099 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); 1100 return; 1101 } 1102 } 1103 #ifdef IPSEC 1104 if (inp != NULL && ipsec4_in_reject(m, inp)) { 1105 ipsecstat.in_polvio++; 1106 goto bad; 1107 } 1108 #endif /*IPSEC*/ 1109 1110 /* 1111 * Stuff source address and datagram in user buffer. 1112 */ 1113 if (inp->inp_flags & INP_CONTROLOPTS || 1114 inp->inp_socket->so_options & SO_TIMESTAMP) 1115 ip_savecontrol(inp, &opts, ip, m); 1116 iphlen += sizeof(struct udphdr); 1117 m->m_len -= iphlen; 1118 m->m_pkthdr.len -= iphlen; 1119 m->m_data += iphlen; 1120 sa = (struct sockaddr *)&udpsrc; 1121 if (sbappendaddr(&inp->inp_socket->so_rcv, sa, m, opts) == 0) { 1122 udpstat.udps_fullsock++; 1123 goto bad; 1124 } 1125 sorwakeup(inp->inp_socket); 1126 return; 1127 bad: 1128 m_freem(m); 1129 if (opts) 1130 m_freem(opts); 1131 return; 1132 1133 badcsum: 1134 udpstat.udps_badsum++; 1135 m_freem(m); 1136 } 1137 #endif /*UDP6*/ 1138 1139 #ifdef INET 1140 /* 1141 * Notify a udp user of an asynchronous error; 1142 * just wake up so that he can collect error status. 1143 */ 1144 static void 1145 udp_notify(inp, errno) 1146 struct inpcb *inp; 1147 int errno; 1148 { 1149 1150 inp->inp_socket->so_error = errno; 1151 sorwakeup(inp->inp_socket); 1152 sowwakeup(inp->inp_socket); 1153 } 1154 1155 void * 1156 udp_ctlinput(cmd, sa, v) 1157 int cmd; 1158 struct sockaddr *sa; 1159 void *v; 1160 { 1161 struct ip *ip = v; 1162 struct udphdr *uh; 1163 void (*notify) __P((struct inpcb *, int)) = udp_notify; 1164 int errno; 1165 1166 if (sa->sa_family != AF_INET 1167 || sa->sa_len != sizeof(struct sockaddr_in)) 1168 return NULL; 1169 if ((unsigned)cmd >= PRC_NCMDS) 1170 return NULL; 1171 errno = inetctlerrmap[cmd]; 1172 if (PRC_IS_REDIRECT(cmd)) 1173 notify = in_rtchange, ip = 0; 1174 else if (cmd == PRC_HOSTDEAD) 1175 ip = 0; 1176 else if (errno == 0) 1177 return NULL; 1178 if (ip) { 1179 uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); 1180 in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport, 1181 ip->ip_src, uh->uh_sport, errno, notify); 1182 1183 /* XXX mapped address case */ 1184 } else 1185 in_pcbnotifyall(&udbtable, satosin(sa)->sin_addr, errno, 1186 notify); 1187 return NULL; 1188 } 1189 1190 int 1191 #if __STDC__ 1192 udp_output(struct mbuf *m, ...) 1193 #else 1194 udp_output(m, va_alist) 1195 struct mbuf *m; 1196 va_dcl 1197 #endif 1198 { 1199 struct inpcb *inp; 1200 struct udpiphdr *ui; 1201 int len = m->m_pkthdr.len; 1202 int error = 0; 1203 va_list ap; 1204 1205 va_start(ap, m); 1206 inp = va_arg(ap, struct inpcb *); 1207 va_end(ap); 1208 1209 /* 1210 * Calculate data length and get a mbuf 1211 * for UDP and IP headers. 1212 */ 1213 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); 1214 if (m == 0) { 1215 error = ENOBUFS; 1216 goto release; 1217 } 1218 1219 /* 1220 * Compute the packet length of the IP header, and 1221 * punt if the length looks bogus. 1222 */ 1223 if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { 1224 error = EMSGSIZE; 1225 goto release; 1226 } 1227 1228 /* 1229 * Fill in mbuf with extended UDP header 1230 * and addresses and length put into network format. 1231 */ 1232 ui = mtod(m, struct udpiphdr *); 1233 ui->ui_pr = IPPROTO_UDP; 1234 ui->ui_src = inp->inp_laddr; 1235 ui->ui_dst = inp->inp_faddr; 1236 ui->ui_sport = inp->inp_lport; 1237 ui->ui_dport = inp->inp_fport; 1238 ui->ui_ulen = htons((u_int16_t)len + sizeof(struct udphdr)); 1239 1240 /* 1241 * Set up checksum and output datagram. 1242 */ 1243 if (udpcksum) { 1244 /* 1245 * XXX Cache pseudo-header checksum part for 1246 * XXX "connected" UDP sockets. 1247 */ 1248 ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr, 1249 ui->ui_dst.s_addr, htons((u_int16_t)len + 1250 sizeof(struct udphdr) + IPPROTO_UDP)); 1251 m->m_pkthdr.csum_flags = M_CSUM_UDPv4; 1252 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); 1253 } else 1254 ui->ui_sum = 0; 1255 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 1256 ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ 1257 ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ 1258 udpstat.udps_opackets++; 1259 1260 #ifdef IPSEC 1261 if (ipsec_setsocket(m, inp->inp_socket) != 0) { 1262 error = ENOBUFS; 1263 goto release; 1264 } 1265 #endif /*IPSEC*/ 1266 1267 return (ip_output(m, inp->inp_options, &inp->inp_route, 1268 inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), 1269 inp->inp_moptions)); 1270 1271 release: 1272 m_freem(m); 1273 return (error); 1274 } 1275 1276 int udp_sendspace = 9216; /* really max datagram size */ 1277 int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); 1278 /* 40 1K datagrams */ 1279 1280 /*ARGSUSED*/ 1281 int 1282 udp_usrreq(so, req, m, nam, control, p) 1283 struct socket *so; 1284 int req; 1285 struct mbuf *m, *nam, *control; 1286 struct proc *p; 1287 { 1288 struct inpcb *inp; 1289 int s; 1290 int error = 0; 1291 1292 if (req == PRU_CONTROL) 1293 return (in_control(so, (long)m, (caddr_t)nam, 1294 (struct ifnet *)control, p)); 1295 1296 if (req == PRU_PURGEIF) { 1297 in_pcbpurgeif0(&udbtable, (struct ifnet *)control); 1298 in_purgeif((struct ifnet *)control); 1299 in_pcbpurgeif(&udbtable, (struct ifnet *)control); 1300 return (0); 1301 } 1302 1303 s = splsoftnet(); 1304 inp = sotoinpcb(so); 1305 #ifdef DIAGNOSTIC 1306 if (req != PRU_SEND && req != PRU_SENDOOB && control) 1307 panic("udp_usrreq: unexpected control mbuf"); 1308 #endif 1309 if (inp == 0 && req != PRU_ATTACH) { 1310 error = EINVAL; 1311 goto release; 1312 } 1313 1314 /* 1315 * Note: need to block udp_input while changing 1316 * the udp pcb queue and/or pcb addresses. 1317 */ 1318 switch (req) { 1319 1320 case PRU_ATTACH: 1321 if (inp != 0) { 1322 error = EISCONN; 1323 break; 1324 } 1325 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 1326 error = soreserve(so, udp_sendspace, udp_recvspace); 1327 if (error) 1328 break; 1329 } 1330 error = in_pcballoc(so, &udbtable); 1331 if (error) 1332 break; 1333 inp = sotoinpcb(so); 1334 inp->inp_ip.ip_ttl = ip_defttl; 1335 break; 1336 1337 case PRU_DETACH: 1338 in_pcbdetach(inp); 1339 break; 1340 1341 case PRU_BIND: 1342 error = in_pcbbind(inp, nam, p); 1343 break; 1344 1345 case PRU_LISTEN: 1346 error = EOPNOTSUPP; 1347 break; 1348 1349 case PRU_CONNECT: 1350 error = in_pcbconnect(inp, nam); 1351 if (error) 1352 break; 1353 soisconnected(so); 1354 break; 1355 1356 case PRU_CONNECT2: 1357 error = EOPNOTSUPP; 1358 break; 1359 1360 case PRU_DISCONNECT: 1361 /*soisdisconnected(so);*/ 1362 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 1363 in_pcbdisconnect(inp); 1364 inp->inp_laddr = zeroin_addr; /* XXX */ 1365 in_pcbstate(inp, INP_BOUND); /* XXX */ 1366 break; 1367 1368 case PRU_SHUTDOWN: 1369 socantsendmore(so); 1370 break; 1371 1372 case PRU_RCVD: 1373 error = EOPNOTSUPP; 1374 break; 1375 1376 case PRU_SEND: 1377 if (control && control->m_len) { 1378 m_freem(control); 1379 m_freem(m); 1380 error = EINVAL; 1381 break; 1382 } 1383 { 1384 struct in_addr laddr; /* XXX */ 1385 1386 if (nam) { 1387 laddr = inp->inp_laddr; /* XXX */ 1388 if ((so->so_state & SS_ISCONNECTED) != 0) { 1389 error = EISCONN; 1390 goto die; 1391 } 1392 error = in_pcbconnect(inp, nam); 1393 if (error) { 1394 die: 1395 m_freem(m); 1396 break; 1397 } 1398 } else { 1399 if ((so->so_state & SS_ISCONNECTED) == 0) { 1400 error = ENOTCONN; 1401 goto die; 1402 } 1403 } 1404 error = udp_output(m, inp); 1405 if (nam) { 1406 in_pcbdisconnect(inp); 1407 inp->inp_laddr = laddr; /* XXX */ 1408 in_pcbstate(inp, INP_BOUND); /* XXX */ 1409 } 1410 } 1411 break; 1412 1413 case PRU_SENSE: 1414 /* 1415 * stat: don't bother with a blocksize. 1416 */ 1417 splx(s); 1418 return (0); 1419 1420 case PRU_RCVOOB: 1421 error = EOPNOTSUPP; 1422 break; 1423 1424 case PRU_SENDOOB: 1425 m_freem(control); 1426 m_freem(m); 1427 error = EOPNOTSUPP; 1428 break; 1429 1430 case PRU_SOCKADDR: 1431 in_setsockaddr(inp, nam); 1432 break; 1433 1434 case PRU_PEERADDR: 1435 in_setpeeraddr(inp, nam); 1436 break; 1437 1438 default: 1439 panic("udp_usrreq"); 1440 } 1441 1442 release: 1443 splx(s); 1444 return (error); 1445 } 1446 1447 /* 1448 * Sysctl for udp variables. 1449 */ 1450 int 1451 udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 1452 int *name; 1453 u_int namelen; 1454 void *oldp; 1455 size_t *oldlenp; 1456 void *newp; 1457 size_t newlen; 1458 { 1459 /* All sysctl names at this level are terminal. */ 1460 if (namelen != 1) 1461 return (ENOTDIR); 1462 1463 switch (name[0]) { 1464 case UDPCTL_CHECKSUM: 1465 return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum)); 1466 case UDPCTL_SENDSPACE: 1467 return (sysctl_int(oldp, oldlenp, newp, newlen, 1468 &udp_sendspace)); 1469 case UDPCTL_RECVSPACE: 1470 return (sysctl_int(oldp, oldlenp, newp, newlen, 1471 &udp_recvspace)); 1472 default: 1473 return (ENOPROTOOPT); 1474 } 1475 /* NOTREACHED */ 1476 } 1477 #endif 1478