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