1 /* $OpenBSD: udp_usrreq.c,v 1.74 2001/06/25 02:06:40 angelos Exp $ */ 2 /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1988, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 37 * 38 * NRL grants permission for redistribution and use in source and binary 39 * forms, with or without modification, of the software and documentation 40 * created at NRL provided that the following conditions are met: 41 * 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgements: 49 * This product includes software developed by the University of 50 * California, Berkeley and its contributors. 51 * This product includes software developed at the Information 52 * Technology Division, US Naval Research Laboratory. 53 * 4. Neither the name of the NRL nor the names of its contributors 54 * may be used to endorse or promote products derived from this software 55 * without specific prior written permission. 56 * 57 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS 58 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 59 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 60 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR 61 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 62 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 63 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 64 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 65 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 66 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 67 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 68 * 69 * The views and conclusions contained in the software and documentation 70 * are those of the authors and should not be interpreted as representing 71 * official policies, either expressed or implied, of the US Naval 72 * Research Laboratory (NRL). 73 */ 74 75 #include <sys/param.h> 76 #include <sys/systm.h> 77 #include <sys/mbuf.h> 78 #include <sys/protosw.h> 79 #include <sys/socket.h> 80 #include <sys/socketvar.h> 81 #include <sys/sysctl.h> 82 83 #include <net/if.h> 84 #include <net/route.h> 85 86 #include <netinet/in.h> 87 #include <netinet/in_systm.h> 88 #include <netinet/in_var.h> 89 #include <netinet/ip.h> 90 #include <netinet/in_pcb.h> 91 #include <netinet/ip_var.h> 92 #include <netinet/ip_icmp.h> 93 #include <netinet/udp.h> 94 #include <netinet/udp_var.h> 95 96 #ifdef INET6 97 #ifndef INET 98 #include <netinet/in.h> 99 #endif 100 #include <netinet6/ip6protosw.h> 101 102 extern int ip6_defhlim; 103 #endif /* INET6 */ 104 105 /* 106 * UDP protocol implementation. 107 * Per RFC 768, August, 1980. 108 */ 109 int udpcksum = 1; 110 111 112 static void udp_detach __P((struct inpcb *)); 113 static void udp_notify __P((struct inpcb *, int)); 114 static struct mbuf *udp_saveopt __P((caddr_t, int, int)); 115 116 #ifndef UDBHASHSIZE 117 #define UDBHASHSIZE 128 118 #endif 119 int udbhashsize = UDBHASHSIZE; 120 121 /* from in_pcb.c */ 122 extern struct baddynamicports baddynamicports; 123 124 void 125 udp_init() 126 { 127 in_pcbinit(&udbtable, udbhashsize); 128 } 129 130 #ifdef INET6 131 int 132 udp6_input(mp, offp, proto) 133 struct mbuf **mp; 134 int *offp, proto; 135 { 136 struct mbuf *m = *mp; 137 138 #if defined(NFAITH) && 0 < NFAITH 139 if (m->m_pkthdr.rcvif) { 140 if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { 141 /* XXX send icmp6 host/port unreach? */ 142 m_freem(m); 143 return IPPROTO_DONE; 144 } 145 } 146 #endif 147 148 udp_input(m, *offp, proto); 149 return IPPROTO_DONE; 150 } 151 #endif 152 153 void 154 #if __STDC__ 155 udp_input(struct mbuf *m, ...) 156 #else 157 udp_input(m, va_alist) 158 struct mbuf *m; 159 va_dcl 160 #endif 161 { 162 register struct ip *ip; 163 register struct udphdr *uh; 164 register struct inpcb *inp; 165 struct mbuf *opts = 0; 166 int len; 167 struct ip save_ip; 168 int iphlen; 169 va_list ap; 170 u_int16_t savesum; 171 union { 172 struct sockaddr sa; 173 struct sockaddr_in sin; 174 #ifdef INET6 175 struct sockaddr_in6 sin6; 176 #endif /* INET6 */ 177 } srcsa, dstsa; 178 #ifdef INET6 179 struct ip6_hdr *ipv6; 180 #endif /* INET6 */ 181 #ifdef IPSEC 182 struct m_tag *mtag; 183 struct tdb_ident *tdbi; 184 struct tdb *tdb; 185 int error, s; 186 #endif /* IPSEC */ 187 188 va_start(ap, m); 189 iphlen = va_arg(ap, int); 190 va_end(ap); 191 192 udpstat.udps_ipackets++; 193 194 switch (mtod(m, struct ip *)->ip_v) { 195 case 4: 196 ip = mtod(m, struct ip *); 197 #ifdef INET6 198 ipv6 = NULL; 199 #endif /* INET6 */ 200 srcsa.sa.sa_family = AF_INET; 201 break; 202 #ifdef INET6 203 case 6: 204 ip = NULL; 205 ipv6 = mtod(m, struct ip6_hdr *); 206 srcsa.sa.sa_family = AF_INET6; 207 break; 208 #endif /* INET6 */ 209 default: 210 goto bad; 211 } 212 213 /* 214 * Strip IP options, if any; should skip this, 215 * make available to user, and use on returned packets, 216 * but we don't yet have a way to check the checksum 217 * with options still present. 218 */ 219 /* 220 * (contd. from above...) Furthermore, we may want to strip options 221 * for such things as ICMP errors, where options just get in the way. 222 */ 223 if (ip && iphlen > sizeof (struct ip)) { 224 ip_stripoptions(m, (struct mbuf *)0); 225 iphlen = sizeof(struct ip); 226 } 227 228 /* 229 * Get IP and UDP header together in first mbuf. 230 */ 231 if (m->m_len < iphlen + sizeof(struct udphdr)) { 232 if ((m = m_pullup2(m, iphlen + sizeof(struct udphdr))) == 233 NULL) { 234 udpstat.udps_hdrops++; 235 return; 236 } 237 #ifdef INET6 238 if (ipv6) 239 ipv6 = mtod(m, struct ip6_hdr *); 240 else 241 #endif /* INET6 */ 242 ip = mtod(m, struct ip *); 243 } 244 uh = (struct udphdr *)(mtod(m, caddr_t) + iphlen); 245 246 /* Check for illegal destination port 0 */ 247 if (uh->uh_dport == 0) { 248 udpstat.udps_noport++; 249 goto bad; 250 } 251 252 /* 253 * Make mbuf data length reflect UDP length. 254 * If not enough data to reflect UDP length, drop. 255 */ 256 len = ntohs((u_int16_t)uh->uh_ulen); 257 if (m->m_pkthdr.len - iphlen != len) { 258 if (len > (m->m_pkthdr.len - iphlen) || 259 len < sizeof(struct udphdr)) { 260 udpstat.udps_badlen++; 261 goto bad; 262 } 263 m_adj(m, len - (m->m_pkthdr.len - iphlen)); 264 } 265 /* 266 * Save a copy of the IP header in case we want restore it 267 * for sending an ICMP error message in response. 268 */ 269 if (ip) 270 save_ip = *ip; 271 272 /* 273 * Checksum extended UDP header and data. 274 * from W.R.Stevens: check incoming udp cksums even if 275 * udpcksum is not set. 276 */ 277 savesum = uh->uh_sum; 278 #ifdef INET6 279 if (ipv6) { 280 /* Be proactive about malicious use of IPv4 mapped address */ 281 if (IN6_IS_ADDR_V4MAPPED(&ipv6->ip6_src) || 282 IN6_IS_ADDR_V4MAPPED(&ipv6->ip6_dst)) { 283 /* XXX stat */ 284 goto bad; 285 } 286 287 /* 288 * In IPv6, the UDP checksum is ALWAYS used. 289 */ 290 if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, iphlen, len))) { 291 udpstat.udps_badsum++; 292 goto bad; 293 } 294 } else 295 #endif /* INET6 */ 296 if (uh->uh_sum) { 297 if ((m->m_pkthdr.csum & M_UDP_CSUM_IN_OK) == 0) { 298 if (m->m_pkthdr.csum & M_UDP_CSUM_IN_BAD) { 299 udpstat.udps_badsum++; 300 udpstat.udps_inhwcsum++; 301 m_freem(m); 302 return; 303 } 304 305 bzero(((struct ipovly *)ip)->ih_x1, 306 sizeof ((struct ipovly *)ip)->ih_x1); 307 ((struct ipovly *)ip)->ih_len = uh->uh_ulen; 308 309 if ((uh->uh_sum = in_cksum(m, len + 310 sizeof (struct ip))) != 0) { 311 udpstat.udps_badsum++; 312 m_freem(m); 313 return; 314 } 315 } else { 316 m->m_pkthdr.csum &= ~M_UDP_CSUM_IN_OK; 317 udpstat.udps_inhwcsum++; 318 } 319 } else 320 udpstat.udps_nosum++; 321 322 switch (srcsa.sa.sa_family) { 323 case AF_INET: 324 bzero(&srcsa, sizeof(struct sockaddr_in)); 325 srcsa.sin.sin_len = sizeof(struct sockaddr_in); 326 srcsa.sin.sin_family = AF_INET; 327 srcsa.sin.sin_port = uh->uh_sport; 328 srcsa.sin.sin_addr = ip->ip_src; 329 330 bzero(&dstsa, sizeof(struct sockaddr_in)); 331 dstsa.sin.sin_len = sizeof(struct sockaddr_in); 332 dstsa.sin.sin_family = AF_INET; 333 dstsa.sin.sin_port = uh->uh_dport; 334 dstsa.sin.sin_addr = ip->ip_dst; 335 break; 336 #ifdef INET6 337 case AF_INET6: 338 bzero(&srcsa, sizeof(struct sockaddr_in6)); 339 srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6); 340 srcsa.sin6.sin6_family = AF_INET6; 341 srcsa.sin6.sin6_port = uh->uh_sport; 342 #if 0 /*XXX inbound flowinfo */ 343 srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ipv6->ip6_flow; 344 #endif 345 /* KAME hack: recover scopeid */ 346 (void)in6_recoverscope(&srcsa.sin6, &ipv6->ip6_src, 347 m->m_pkthdr.rcvif); 348 349 bzero(&dstsa, sizeof(struct sockaddr_in6)); 350 dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6); 351 dstsa.sin6.sin6_family = AF_INET6; 352 dstsa.sin6.sin6_port = uh->uh_dport; 353 /* KAME hack: recover scopeid */ 354 (void)in6_recoverscope(&dstsa.sin6, &ipv6->ip6_dst, 355 m->m_pkthdr.rcvif); 356 break; 357 #endif /* INET6 */ 358 } 359 360 #ifdef INET6 361 if ((ipv6 && IN6_IS_ADDR_MULTICAST(&ipv6->ip6_dst)) || 362 (ip && IN_MULTICAST(ip->ip_dst.s_addr)) || 363 (ip && in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) 364 #else /* INET6 */ 365 if (IN_MULTICAST(ip->ip_dst.s_addr) || 366 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) 367 #endif /* INET6 */ 368 { 369 struct socket *last; 370 /* 371 * Deliver a multicast or broadcast datagram to *all* sockets 372 * for which the local and remote addresses and ports match 373 * those of the incoming datagram. This allows more than 374 * one process to receive multi/broadcasts on the same port. 375 * (This really ought to be done for unicast datagrams as 376 * well, but that would cause problems with existing 377 * applications that open both address-specific sockets and 378 * a wildcard socket listening to the same port -- they would 379 * end up receiving duplicates of every unicast datagram. 380 * Those applications open the multiple sockets to overcome an 381 * inadequacy of the UDP socket interface, but for backwards 382 * compatibility we avoid the problem here rather than 383 * fixing the interface. Maybe 4.5BSD will remedy this?) 384 */ 385 386 iphlen += sizeof(struct udphdr); 387 388 /* 389 * Locate pcb(s) for datagram. 390 * (Algorithm copied from raw_intr().) 391 */ 392 last = NULL; 393 for (inp = udbtable.inpt_queue.cqh_first; 394 inp != (struct inpcb *)&udbtable.inpt_queue; 395 inp = inp->inp_queue.cqe_next) { 396 #ifdef INET6 397 /* don't accept it if AF does not match */ 398 if (ipv6 && !(inp->inp_flags & INP_IPV6)) 399 continue; 400 if (!ipv6 && (inp->inp_flags & INP_IPV6)) 401 continue; 402 #endif 403 if (inp->inp_lport != uh->uh_dport) 404 continue; 405 #ifdef INET6 406 if (ipv6) { 407 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) 408 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, 409 &ipv6->ip6_dst)) 410 continue; 411 } else 412 #endif /* INET6 */ 413 if (inp->inp_laddr.s_addr != INADDR_ANY) { 414 if (inp->inp_laddr.s_addr != 415 ip->ip_dst.s_addr) 416 continue; 417 } 418 #ifdef INET6 419 if (ipv6) { 420 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) 421 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, 422 &ipv6->ip6_src) || 423 inp->inp_fport != uh->uh_sport) 424 continue; 425 } else 426 #endif /* INET6 */ 427 if (inp->inp_faddr.s_addr != INADDR_ANY) { 428 if (inp->inp_faddr.s_addr != 429 ip->ip_src.s_addr || 430 inp->inp_fport != uh->uh_sport) 431 continue; 432 } 433 434 if (last != NULL) { 435 struct mbuf *n; 436 437 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 438 opts = NULL; 439 #ifdef INET6 440 if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) 441 ip6_savecontrol(inp, &opts, ipv6, n); 442 #endif /* INET6 */ 443 m_adj(n, iphlen); 444 if (sbappendaddr(&last->so_rcv, 445 &srcsa.sa, n, opts) == 0) { 446 m_freem(n); 447 if (opts) 448 m_freem(opts); 449 udpstat.udps_fullsock++; 450 } else 451 sorwakeup(last); 452 opts = NULL; 453 } 454 } 455 last = inp->inp_socket; 456 /* 457 * Don't look for additional matches if this one does 458 * not have either the SO_REUSEPORT or SO_REUSEADDR 459 * socket options set. This heuristic avoids searching 460 * through all pcbs in the common case of a non-shared 461 * port. It * assumes that an application will never 462 * clear these options after setting them. 463 */ 464 if ((last->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0) 465 break; 466 } 467 468 if (last == NULL) { 469 /* 470 * No matching pcb found; discard datagram. 471 * (No need to send an ICMP Port Unreachable 472 * for a broadcast or multicast datgram.) 473 */ 474 udpstat.udps_noportbcast++; 475 goto bad; 476 } 477 478 opts = NULL; 479 #ifdef INET6 480 if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) 481 ip6_savecontrol(inp, &opts, ipv6, m); 482 #endif /* INET6 */ 483 m_adj(m, iphlen); 484 if (sbappendaddr(&last->so_rcv, 485 &srcsa.sa, m, opts) == 0) { 486 udpstat.udps_fullsock++; 487 goto bad; 488 } 489 sorwakeup(last); 490 return; 491 } 492 /* 493 * Locate pcb for datagram. 494 */ 495 #ifdef INET6 496 if (ipv6) 497 inp = in6_pcbhashlookup(&udbtable, &ipv6->ip6_src, uh->uh_sport, 498 &ipv6->ip6_dst, uh->uh_dport); 499 else 500 #endif /* INET6 */ 501 inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport, 502 ip->ip_dst, uh->uh_dport); 503 if (inp == 0) { 504 ++udpstat.udps_pcbhashmiss; 505 #ifdef INET6 506 if (ipv6) { 507 inp = in_pcblookup(&udbtable, 508 (struct in_addr *)&(ipv6->ip6_src), 509 uh->uh_sport, (struct in_addr *)&(ipv6->ip6_dst), 510 uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); 511 } else 512 #endif /* INET6 */ 513 inp = in_pcblookup(&udbtable, &ip->ip_src, uh->uh_sport, 514 &ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD); 515 if (inp == 0) { 516 udpstat.udps_noport++; 517 if (m->m_flags & (M_BCAST | M_MCAST)) { 518 udpstat.udps_noportbcast++; 519 goto bad; 520 } 521 #ifdef INET6 522 if (ipv6) { 523 icmp6_error(m, ICMP6_DST_UNREACH, 524 ICMP6_DST_UNREACH_NOPORT,0); 525 } else 526 #endif /* INET6 */ 527 { 528 *ip = save_ip; 529 uh->uh_sum = savesum; 530 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 531 0, 0); 532 } 533 return; 534 } 535 } 536 537 #ifdef IPSEC 538 mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); 539 s = splnet(); 540 if (mtag != NULL) { 541 tdbi = (struct tdb_ident *)(mtag + 1); 542 tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); 543 } else 544 tdb = NULL; 545 ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error, 546 IPSP_DIRECTION_IN, tdb, inp); 547 548 /* Latch SA only if the socket is connected */ 549 if (inp->inp_tdb_in != tdb && 550 (inp->inp_socket->so_state & SS_ISCONNECTED)) { 551 if (tdb) { 552 tdb_add_inp(tdb, inp, 1); 553 if (inp->inp_ipsec_remoteid == NULL && 554 tdb->tdb_srcid != NULL) { 555 inp->inp_ipsec_remoteid = tdb->tdb_srcid; 556 tdb->tdb_srcid->ref_count++; 557 } 558 if (inp->inp_ipsec_remotecred == NULL && 559 tdb->tdb_remote_cred != NULL) { 560 inp->inp_ipsec_remotecred = 561 tdb->tdb_remote_cred; 562 tdb->tdb_remote_cred->ref_count++; 563 } 564 if (inp->inp_ipsec_remoteauth == NULL && 565 tdb->tdb_remote_auth != NULL) { 566 inp->inp_ipsec_remoteauth = 567 tdb->tdb_remote_auth; 568 tdb->tdb_remote_auth->ref_count++; 569 } 570 } else { /* Just reset */ 571 TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in, inp, 572 inp_tdb_in_next); 573 inp->inp_tdb_in = NULL; 574 } 575 } 576 splx(s); 577 578 /* Error or otherwise drop-packet indication. */ 579 if (error) 580 goto bad; 581 #endif /*IPSEC */ 582 583 opts = NULL; 584 #ifdef INET6 585 if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) 586 ip6_savecontrol(inp, &opts, ipv6, m); 587 #endif /* INET6 */ 588 if (ip && (inp->inp_flags & INP_CONTROLOPTS)) { 589 struct mbuf **mp = &opts; 590 591 if (inp->inp_flags & INP_RECVDSTADDR) { 592 *mp = udp_saveopt((caddr_t) &ip->ip_dst, 593 sizeof(struct in_addr), IP_RECVDSTADDR); 594 if (*mp) 595 mp = &(*mp)->m_next; 596 } 597 #ifdef notyet 598 /* options were tossed above */ 599 if (inp->inp_flags & INP_RECVOPTS) { 600 *mp = udp_saveopt((caddr_t) opts_deleted_above, 601 sizeof(struct in_addr), IP_RECVOPTS); 602 if (*mp) 603 mp = &(*mp)->m_next; 604 } 605 /* ip_srcroute doesn't do what we want here, need to fix */ 606 if (inp->inp_flags & INP_RECVRETOPTS) { 607 *mp = udp_saveopt((caddr_t) ip_srcroute(), 608 sizeof(struct in_addr), IP_RECVRETOPTS); 609 if (*mp) 610 mp = &(*mp)->m_next; 611 } 612 #endif 613 } 614 iphlen += sizeof(struct udphdr); 615 m_adj(m, iphlen); 616 if (sbappendaddr(&inp->inp_socket->so_rcv, 617 &srcsa.sa, m, opts) == 0) { 618 udpstat.udps_fullsock++; 619 goto bad; 620 } 621 sorwakeup(inp->inp_socket); 622 return; 623 bad: 624 m_freem(m); 625 if (opts) 626 m_freem(opts); 627 } 628 629 /* 630 * Create a "control" mbuf containing the specified data 631 * with the specified type for presentation with a datagram. 632 */ 633 struct mbuf * 634 udp_saveopt(p, size, type) 635 caddr_t p; 636 register int size; 637 int type; 638 { 639 register struct cmsghdr *cp; 640 struct mbuf *m; 641 642 if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL) 643 return ((struct mbuf *) NULL); 644 cp = (struct cmsghdr *) mtod(m, struct cmsghdr *); 645 bcopy(p, CMSG_DATA(cp), size); 646 size = CMSG_LEN(size); 647 m->m_len = size; 648 cp->cmsg_len = size; 649 cp->cmsg_level = IPPROTO_IP; 650 cp->cmsg_type = type; 651 return (m); 652 } 653 654 /* 655 * Notify a udp user of an asynchronous error; 656 * just wake up so that he can collect error status. 657 */ 658 static void 659 udp_notify(inp, errno) 660 register struct inpcb *inp; 661 int errno; 662 { 663 inp->inp_socket->so_error = errno; 664 sorwakeup(inp->inp_socket); 665 sowwakeup(inp->inp_socket); 666 } 667 668 #ifdef INET6 669 void 670 udp6_ctlinput(cmd, sa, d) 671 int cmd; 672 struct sockaddr *sa; 673 void *d; 674 { 675 struct udphdr uh; 676 struct sockaddr_in6 sa6; 677 register struct ip6_hdr *ip6; 678 struct mbuf *m; 679 int off; 680 void *cmdarg; 681 struct ip6ctlparam *ip6cp = NULL; 682 struct in6_addr finaldst; 683 struct udp_portonly { 684 u_int16_t uh_sport; 685 u_int16_t uh_dport; 686 } *uhp; 687 void (*notify) __P((struct inpcb *, int)) = udp_notify; 688 689 if (sa == NULL) 690 return; 691 if (sa->sa_family != AF_INET6 || 692 sa->sa_len != sizeof(struct sockaddr_in6)) 693 return; 694 695 if ((unsigned)cmd >= PRC_NCMDS) 696 return; 697 if (PRC_IS_REDIRECT(cmd)) 698 notify = in_rtchange, d = NULL; 699 else if (cmd == PRC_HOSTDEAD) 700 d = NULL; 701 else if (cmd == PRC_MSGSIZE) 702 ; /* special code is present, see below */ 703 else if (inet6ctlerrmap[cmd] == 0) 704 return; 705 706 /* if the parameter is from icmp6, decode it. */ 707 if (d != NULL) { 708 ip6cp = (struct ip6ctlparam *)d; 709 m = ip6cp->ip6c_m; 710 ip6 = ip6cp->ip6c_ip6; 711 off = ip6cp->ip6c_off; 712 cmdarg = ip6cp->ip6c_cmdarg; 713 } else { 714 m = NULL; 715 ip6 = NULL; 716 cmdarg = NULL; 717 /* XXX: translate addresses into internal form */ 718 sa6 = *(struct sockaddr_in6 *)sa; 719 #ifndef SCOPEDROUTING 720 if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) { 721 /* should be impossible */ 722 return; 723 } 724 #endif 725 } 726 727 if (ip6cp && ip6cp->ip6c_finaldst) { 728 bzero(&sa6, sizeof(sa6)); 729 sa6.sin6_family = AF_INET6; 730 sa6.sin6_len = sizeof(sa6); 731 sa6.sin6_addr = *ip6cp->ip6c_finaldst; 732 /* XXX: assuming M is valid in this case */ 733 sa6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif, 734 ip6cp->ip6c_finaldst); 735 #ifndef SCOPEDROUTING 736 if (in6_embedscope(ip6cp->ip6c_finaldst, &sa6, NULL, NULL)) { 737 /* should be impossible */ 738 return; 739 } 740 #endif 741 } else { 742 /* XXX: translate addresses into internal form */ 743 sa6 = *(struct sockaddr_in6 *)sa; 744 #ifndef SCOPEDROUTING 745 if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) { 746 /* should be impossible */ 747 return; 748 } 749 #endif 750 } 751 752 if (ip6) { 753 /* 754 * XXX: We assume that when IPV6 is non NULL, 755 * M and OFF are valid. 756 */ 757 struct sockaddr_in6 sa6_src; 758 759 /* check if we can safely examine src and dst ports */ 760 if (m->m_pkthdr.len < off + sizeof(*uhp)) 761 return; 762 763 bzero(&uh, sizeof(uh)); 764 m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh); 765 766 bzero(&sa6_src, sizeof(sa6_src)); 767 sa6_src.sin6_family = AF_INET6; 768 sa6_src.sin6_len = sizeof(sa6_src); 769 sa6_src.sin6_addr = ip6->ip6_src; 770 sa6_src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif, 771 &ip6->ip6_src); 772 #ifndef SCOPEDROUTING 773 if (in6_embedscope(&sa6_src.sin6_addr, &sa6_src, NULL, NULL)) { 774 /* should be impossible */ 775 return; 776 } 777 #endif 778 779 if (cmd == PRC_MSGSIZE) { 780 int valid = 0; 781 782 /* 783 * Check to see if we have a valid UDP socket 784 * corresponding to the address in the ICMPv6 message 785 * payload. 786 */ 787 if (in6_pcbhashlookup(&udbtable, &finaldst, 788 uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport)) 789 valid = 1; 790 else if (in_pcblookup(&udbtable, &sa6.sin6_addr, 791 uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport, 792 INPLOOKUP_IPV6)) 793 valid = 1; 794 #if 0 795 /* 796 * As the use of sendto(2) is fairly popular, 797 * we may want to allow non-connected pcb too. 798 * But it could be too weak against attacks... 799 * We should at least check if the local address (= s) 800 * is really ours. 801 */ 802 else if (in_pcblookup(&udbtable, &sa6.sin6_addr, 803 uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport, 804 INPLOOKUP_WILDCARD | INPLOOKUP_IPV6)) 805 valid = 1; 806 #endif 807 808 /* 809 * Depending on the value of "valid" and routing table 810 * size (mtudisc_{hi,lo}wat), we will: 811 * - recalcurate the new MTU and create the 812 * corresponding routing entry, or 813 * - ignore the MTU change notification. 814 */ 815 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 816 817 /* 818 * regardless of if we called icmp6_mtudisc_update(), 819 * we need to call in6_pcbnotify(), to notify path 820 * MTU change to the userland (2292bis-02), because 821 * some unconnected sockets may share the same 822 * destination and want to know the path MTU. 823 */ 824 } 825 826 (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6, 827 uh.uh_dport, (struct sockaddr *)&sa6_src, 828 uh.uh_sport, cmd, cmdarg, notify); 829 } else { 830 (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6, 0, 831 (struct sockaddr *)&sa6_any, 0, cmd, cmdarg, notify); 832 } 833 } 834 #endif 835 836 void * 837 udp_ctlinput(cmd, sa, v) 838 int cmd; 839 struct sockaddr *sa; 840 void *v; 841 { 842 register struct ip *ip = v; 843 register struct udphdr *uhp; 844 extern int inetctlerrmap[]; 845 void (*notify) __P((struct inpcb *, int)) = udp_notify; 846 int errno; 847 848 if (sa == NULL) 849 return NULL; 850 if (sa->sa_family != AF_INET || 851 sa->sa_len != sizeof(struct sockaddr_in)) 852 return NULL; 853 854 if ((unsigned)cmd >= PRC_NCMDS) 855 return NULL; 856 errno = inetctlerrmap[cmd]; 857 if (PRC_IS_REDIRECT(cmd)) 858 notify = in_rtchange, ip = 0; 859 else if (cmd == PRC_HOSTDEAD) 860 ip = 0; 861 else if (errno == 0) 862 return NULL; 863 if (ip) { 864 uhp = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); 865 in_pcbnotify(&udbtable, sa, uhp->uh_dport, ip->ip_src, 866 uhp->uh_sport, errno, notify); 867 } else 868 in_pcbnotifyall(&udbtable, sa, errno, notify); 869 return NULL; 870 } 871 872 int 873 #if __STDC__ 874 udp_output(struct mbuf *m, ...) 875 #else 876 udp_output(m, va_alist) 877 struct mbuf *m; 878 va_dcl 879 #endif 880 { 881 register struct inpcb *inp; 882 struct mbuf *addr, *control; 883 register struct udpiphdr *ui; 884 register int len = m->m_pkthdr.len; 885 struct in_addr laddr; 886 int s = 0, error = 0; 887 va_list ap; 888 int pcbflags = 0; 889 890 va_start(ap, m); 891 inp = va_arg(ap, struct inpcb *); 892 addr = va_arg(ap, struct mbuf *); 893 control = va_arg(ap, struct mbuf *); 894 va_end(ap); 895 896 #ifdef DIAGNOSTIC 897 if ((inp->inp_flags & INP_IPV6) != 0) 898 panic("IPv6 inpcb to udp_output"); 899 #endif 900 901 /* 902 * Compute the packet length of the IP header, and 903 * punt if the length looks bogus. 904 */ 905 if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { 906 error = EMSGSIZE; 907 goto release; 908 } 909 910 if (addr) { 911 /* 912 * Save current PCB flags because they may change during 913 * temporary connection. 914 */ 915 pcbflags = inp->inp_flags; 916 917 laddr = inp->inp_laddr; 918 if (inp->inp_faddr.s_addr != INADDR_ANY) { 919 error = EISCONN; 920 goto release; 921 } 922 /* 923 * Must block input while temporarily connected. 924 */ 925 s = splsoftnet(); 926 error = in_pcbconnect(inp, addr); 927 if (error) { 928 splx(s); 929 goto release; 930 } 931 } else { 932 if (inp->inp_faddr.s_addr == INADDR_ANY) { 933 error = ENOTCONN; 934 goto release; 935 } 936 } 937 /* 938 * Calculate data length and get a mbuf 939 * for UDP and IP headers. 940 */ 941 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); 942 if (m == 0) { 943 error = ENOBUFS; 944 goto bail; 945 } 946 947 /* 948 * Fill in mbuf with extended UDP header 949 * and addresses and length put into network format. 950 */ 951 ui = mtod(m, struct udpiphdr *); 952 bzero(ui->ui_x1, sizeof ui->ui_x1); 953 ui->ui_pr = IPPROTO_UDP; 954 ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr)); 955 ui->ui_src = inp->inp_laddr; 956 ui->ui_dst = inp->inp_faddr; 957 ui->ui_sport = inp->inp_lport; 958 ui->ui_dport = inp->inp_fport; 959 ui->ui_ulen = ui->ui_len; 960 961 /* 962 * Compute the pseudo-header checksum; defer further checksumming 963 * until ip_output() or hardware (if it exists). 964 */ 965 if (udpcksum) { 966 m->m_pkthdr.csum |= M_UDPV4_CSUM_OUT; 967 ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr, 968 ui->ui_dst.s_addr, htons((u_int16_t)len + 969 sizeof (struct udphdr) + IPPROTO_UDP)); 970 } else 971 ui->ui_sum = 0; 972 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 973 ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; 974 ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; 975 976 udpstat.udps_opackets++; 977 error = ip_output(m, inp->inp_options, &inp->inp_route, 978 inp->inp_socket->so_options & 979 (SO_DONTROUTE | SO_BROADCAST), 980 inp->inp_moptions, inp, NULL); 981 982 bail: 983 if (addr) { 984 in_pcbdisconnect(inp); 985 inp->inp_flags = pcbflags; 986 inp->inp_laddr = laddr; 987 splx(s); 988 } 989 if (control) 990 m_freem(control); 991 return (error); 992 993 release: 994 m_freem(m); 995 if (control) 996 m_freem(control); 997 return (error); 998 } 999 1000 u_int udp_sendspace = 9216; /* really max datagram size */ 1001 u_int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); 1002 /* 40 1K datagrams */ 1003 1004 #ifdef INET6 1005 /*ARGSUSED*/ 1006 int 1007 udp6_usrreq(so, req, m, addr, control, p) 1008 struct socket *so; 1009 int req; 1010 struct mbuf *m, *addr, *control; 1011 struct proc *p; 1012 { 1013 1014 return udp_usrreq(so, req, m, addr, control); 1015 } 1016 #endif 1017 1018 /*ARGSUSED*/ 1019 int 1020 udp_usrreq(so, req, m, addr, control) 1021 struct socket *so; 1022 int req; 1023 struct mbuf *m, *addr, *control; 1024 { 1025 struct inpcb *inp = sotoinpcb(so); 1026 int error = 0; 1027 int s; 1028 1029 if (req == PRU_CONTROL) { 1030 #ifdef INET6 1031 if (inp->inp_flags & INP_IPV6) 1032 return (in6_control(so, (u_long)m, (caddr_t)addr, 1033 (struct ifnet *)control, 0)); 1034 else 1035 #endif /* INET6 */ 1036 return (in_control(so, (u_long)m, (caddr_t)addr, 1037 (struct ifnet *)control)); 1038 } 1039 if (inp == NULL && req != PRU_ATTACH) { 1040 error = EINVAL; 1041 goto release; 1042 } 1043 /* 1044 * Note: need to block udp_input while changing 1045 * the udp pcb queue and/or pcb addresses. 1046 */ 1047 switch (req) { 1048 1049 case PRU_ATTACH: 1050 if (inp != NULL) { 1051 error = EINVAL; 1052 break; 1053 } 1054 s = splsoftnet(); 1055 error = in_pcballoc(so, &udbtable); 1056 splx(s); 1057 if (error) 1058 break; 1059 error = soreserve(so, udp_sendspace, udp_recvspace); 1060 if (error) 1061 break; 1062 #ifdef INET6 1063 if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6) 1064 ((struct inpcb *) so->so_pcb)->inp_ipv6.ip6_hlim = 1065 ip6_defhlim; 1066 else 1067 #endif /* INET6 */ 1068 ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl; 1069 break; 1070 1071 case PRU_DETACH: 1072 udp_detach(inp); 1073 break; 1074 1075 case PRU_BIND: 1076 s = splsoftnet(); 1077 #ifdef INET6 1078 if (inp->inp_flags & INP_IPV6) 1079 error = in6_pcbbind(inp, addr); 1080 else 1081 #endif 1082 error = in_pcbbind(inp, addr); 1083 splx(s); 1084 break; 1085 1086 case PRU_LISTEN: 1087 error = EOPNOTSUPP; 1088 break; 1089 1090 case PRU_CONNECT: 1091 #ifdef INET6 1092 if (inp->inp_flags & INP_IPV6) { 1093 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { 1094 error = EISCONN; 1095 break; 1096 } 1097 s = splsoftnet(); 1098 error = in6_pcbconnect(inp, addr); 1099 splx(s); 1100 } else 1101 #endif /* INET6 */ 1102 { 1103 if (inp->inp_faddr.s_addr != INADDR_ANY) { 1104 error = EISCONN; 1105 break; 1106 } 1107 s = splsoftnet(); 1108 error = in_pcbconnect(inp, addr); 1109 splx(s); 1110 } 1111 1112 if (error == 0) 1113 soisconnected(so); 1114 break; 1115 1116 case PRU_CONNECT2: 1117 error = EOPNOTSUPP; 1118 break; 1119 1120 case PRU_ACCEPT: 1121 error = EOPNOTSUPP; 1122 break; 1123 1124 case PRU_DISCONNECT: 1125 #ifdef INET6 1126 if (inp->inp_flags & INP_IPV6) { 1127 if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { 1128 error = ENOTCONN; 1129 break; 1130 } 1131 } else 1132 #endif /* INET6 */ 1133 { 1134 if (inp->inp_faddr.s_addr == INADDR_ANY) { 1135 error = ENOTCONN; 1136 break; 1137 } 1138 } 1139 1140 s = splsoftnet(); 1141 in_pcbdisconnect(inp); 1142 #ifdef INET6 1143 if (inp->inp_flags & INP_IPV6) 1144 inp->inp_laddr6 = in6addr_any; 1145 else 1146 #endif /* INET6 */ 1147 inp->inp_laddr.s_addr = INADDR_ANY; 1148 1149 splx(s); 1150 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 1151 break; 1152 1153 case PRU_SHUTDOWN: 1154 socantsendmore(so); 1155 break; 1156 1157 case PRU_SEND: 1158 #ifdef INET6 1159 if (inp->inp_flags & INP_IPV6) 1160 return (udp6_output(inp, m, addr, control)); 1161 else 1162 return (udp_output(m, inp, addr, control)); 1163 #else 1164 return (udp_output(m, inp, addr, control)); 1165 #endif 1166 1167 case PRU_ABORT: 1168 soisdisconnected(so); 1169 udp_detach(inp); 1170 break; 1171 1172 case PRU_SOCKADDR: 1173 #ifdef INET6 1174 if (inp->inp_flags & INP_IPV6) 1175 in6_setsockaddr(inp, addr); 1176 else 1177 #endif /* INET6 */ 1178 in_setsockaddr(inp, addr); 1179 break; 1180 1181 case PRU_PEERADDR: 1182 #ifdef INET6 1183 if (inp->inp_flags & INP_IPV6) 1184 in6_setpeeraddr(inp, addr); 1185 else 1186 #endif /* INET6 */ 1187 in_setpeeraddr(inp, addr); 1188 break; 1189 1190 case PRU_SENSE: 1191 /* 1192 * stat: don't bother with a blocksize. 1193 */ 1194 /* 1195 * Perhaps Path MTU might be returned for a connected 1196 * UDP socket in this case. 1197 */ 1198 return (0); 1199 1200 case PRU_SENDOOB: 1201 case PRU_FASTTIMO: 1202 case PRU_SLOWTIMO: 1203 case PRU_PROTORCV: 1204 case PRU_PROTOSEND: 1205 error = EOPNOTSUPP; 1206 break; 1207 1208 case PRU_RCVD: 1209 case PRU_RCVOOB: 1210 return (EOPNOTSUPP); /* do not free mbuf's */ 1211 1212 default: 1213 panic("udp_usrreq"); 1214 } 1215 1216 release: 1217 if (control) { 1218 m_freem(control); 1219 } 1220 if (m) 1221 m_freem(m); 1222 return (error); 1223 } 1224 1225 static void 1226 udp_detach(inp) 1227 struct inpcb *inp; 1228 { 1229 int s = splsoftnet(); 1230 1231 in_pcbdetach(inp); 1232 splx(s); 1233 } 1234 1235 /* 1236 * Sysctl for udp variables. 1237 */ 1238 int 1239 udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 1240 int *name; 1241 u_int namelen; 1242 void *oldp; 1243 size_t *oldlenp; 1244 void *newp; 1245 size_t newlen; 1246 { 1247 /* All sysctl names at this level are terminal. */ 1248 if (namelen != 1) 1249 return (ENOTDIR); 1250 1251 switch (name[0]) { 1252 case UDPCTL_CHECKSUM: 1253 return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum)); 1254 case UDPCTL_BADDYNAMIC: 1255 return (sysctl_struct(oldp, oldlenp, newp, newlen, 1256 baddynamicports.udp, sizeof(baddynamicports.udp))); 1257 case UDPCTL_RECVSPACE: 1258 return (sysctl_int(oldp, oldlenp, newp, newlen,&udp_recvspace)); 1259 case UDPCTL_SENDSPACE: 1260 return (sysctl_int(oldp, oldlenp, newp, newlen,&udp_sendspace)); 1261 default: 1262 return (ENOPROTOOPT); 1263 } 1264 /* NOTREACHED */ 1265 } 1266