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