1 /* $OpenBSD: udp_usrreq.c,v 1.86 2002/08/28 15:43:03 pefo 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(struct inpcb *); 113 static void udp_notify(struct inpcb *, int); 114 static struct mbuf *udp_saveopt(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 udp_input(struct mbuf *m, ...) 155 { 156 register struct ip *ip; 157 register struct udphdr *uh; 158 register struct inpcb *inp; 159 struct mbuf *opts = 0; 160 struct ip save_ip; 161 int iphlen, len; 162 va_list ap; 163 u_int16_t savesum; 164 union { 165 struct sockaddr sa; 166 struct sockaddr_in sin; 167 #ifdef INET6 168 struct sockaddr_in6 sin6; 169 #endif /* INET6 */ 170 } srcsa, dstsa; 171 #ifdef INET6 172 struct ip6_hdr *ip6; 173 #endif /* INET6 */ 174 #ifdef IPSEC 175 struct m_tag *mtag; 176 struct tdb_ident *tdbi; 177 struct tdb *tdb; 178 int error, s; 179 #endif /* IPSEC */ 180 181 va_start(ap, m); 182 iphlen = va_arg(ap, int); 183 va_end(ap); 184 185 udpstat.udps_ipackets++; 186 187 switch (mtod(m, struct ip *)->ip_v) { 188 case 4: 189 ip = mtod(m, struct ip *); 190 #ifdef INET6 191 ip6 = NULL; 192 #endif /* INET6 */ 193 srcsa.sa.sa_family = AF_INET; 194 break; 195 #ifdef INET6 196 case 6: 197 ip = NULL; 198 ip6 = mtod(m, struct ip6_hdr *); 199 srcsa.sa.sa_family = AF_INET6; 200 break; 201 #endif /* INET6 */ 202 default: 203 goto bad; 204 } 205 206 /* 207 * Strip IP options, if any; should skip this, 208 * make available to user, and use on returned packets, 209 * but we don't yet have a way to check the checksum 210 * with options still present. 211 */ 212 /* 213 * (contd. from above...) Furthermore, we may want to strip options 214 * for such things as ICMP errors, where options just get in the way. 215 */ 216 if (ip && iphlen > sizeof (struct ip)) { 217 ip_stripoptions(m, (struct mbuf *)0); 218 iphlen = sizeof(struct ip); 219 } 220 221 /* 222 * Get IP and UDP header together in first mbuf. 223 */ 224 if (m->m_len < iphlen + sizeof(struct udphdr)) { 225 if ((m = m_pullup2(m, iphlen + sizeof(struct udphdr))) == 226 NULL) { 227 udpstat.udps_hdrops++; 228 return; 229 } 230 #ifdef INET6 231 if (ip6) 232 ip6 = mtod(m, struct ip6_hdr *); 233 else 234 #endif /* INET6 */ 235 ip = mtod(m, struct ip *); 236 } 237 uh = (struct udphdr *)(mtod(m, caddr_t) + iphlen); 238 239 /* Check for illegal destination port 0 */ 240 if (uh->uh_dport == 0) { 241 udpstat.udps_noport++; 242 goto bad; 243 } 244 245 /* 246 * Make mbuf data length reflect UDP length. 247 * If not enough data to reflect UDP length, drop. 248 */ 249 len = ntohs((u_int16_t)uh->uh_ulen); 250 if (m->m_pkthdr.len - iphlen != len) { 251 if (len > (m->m_pkthdr.len - iphlen) || 252 len < sizeof(struct udphdr)) { 253 udpstat.udps_badlen++; 254 goto bad; 255 } 256 m_adj(m, len - (m->m_pkthdr.len - iphlen)); 257 } 258 /* 259 * Save a copy of the IP header in case we want restore it 260 * for sending an ICMP error message in response. 261 */ 262 if (ip) 263 save_ip = *ip; 264 265 /* 266 * Checksum extended UDP header and data. 267 * from W.R.Stevens: check incoming udp cksums even if 268 * udpcksum is not set. 269 */ 270 savesum = uh->uh_sum; 271 #ifdef INET6 272 if (ip6) { 273 /* Be proactive about malicious use of IPv4 mapped address */ 274 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || 275 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { 276 /* XXX stat */ 277 goto bad; 278 } 279 280 /* 281 * In IPv6, the UDP checksum is ALWAYS used. 282 */ 283 if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, iphlen, len))) { 284 udpstat.udps_badsum++; 285 goto bad; 286 } 287 } else 288 #endif /* INET6 */ 289 if (uh->uh_sum) { 290 if ((m->m_pkthdr.csum & M_UDP_CSUM_IN_OK) == 0) { 291 if (m->m_pkthdr.csum & M_UDP_CSUM_IN_BAD) { 292 udpstat.udps_badsum++; 293 udpstat.udps_inhwcsum++; 294 m_freem(m); 295 return; 296 } 297 298 bzero(((struct ipovly *)ip)->ih_x1, 299 sizeof ((struct ipovly *)ip)->ih_x1); 300 ((struct ipovly *)ip)->ih_len = uh->uh_ulen; 301 302 if ((uh->uh_sum = in_cksum(m, len + 303 sizeof (struct ip))) != 0) { 304 udpstat.udps_badsum++; 305 m_freem(m); 306 return; 307 } 308 } else { 309 m->m_pkthdr.csum &= ~M_UDP_CSUM_IN_OK; 310 udpstat.udps_inhwcsum++; 311 } 312 } else 313 udpstat.udps_nosum++; 314 315 switch (srcsa.sa.sa_family) { 316 case AF_INET: 317 bzero(&srcsa, sizeof(struct sockaddr_in)); 318 srcsa.sin.sin_len = sizeof(struct sockaddr_in); 319 srcsa.sin.sin_family = AF_INET; 320 srcsa.sin.sin_port = uh->uh_sport; 321 srcsa.sin.sin_addr = ip->ip_src; 322 323 bzero(&dstsa, sizeof(struct sockaddr_in)); 324 dstsa.sin.sin_len = sizeof(struct sockaddr_in); 325 dstsa.sin.sin_family = AF_INET; 326 dstsa.sin.sin_port = uh->uh_dport; 327 dstsa.sin.sin_addr = ip->ip_dst; 328 break; 329 #ifdef INET6 330 case AF_INET6: 331 bzero(&srcsa, sizeof(struct sockaddr_in6)); 332 srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6); 333 srcsa.sin6.sin6_family = AF_INET6; 334 srcsa.sin6.sin6_port = uh->uh_sport; 335 #if 0 /*XXX inbound flowinfo */ 336 srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow; 337 #endif 338 /* KAME hack: recover scopeid */ 339 (void)in6_recoverscope(&srcsa.sin6, &ip6->ip6_src, 340 m->m_pkthdr.rcvif); 341 342 bzero(&dstsa, sizeof(struct sockaddr_in6)); 343 dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6); 344 dstsa.sin6.sin6_family = AF_INET6; 345 dstsa.sin6.sin6_port = uh->uh_dport; 346 /* KAME hack: recover scopeid */ 347 (void)in6_recoverscope(&dstsa.sin6, &ip6->ip6_dst, 348 m->m_pkthdr.rcvif); 349 break; 350 #endif /* INET6 */ 351 } 352 353 #ifdef INET6 354 if ((ip6 && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) || 355 (ip && IN_MULTICAST(ip->ip_dst.s_addr)) || 356 (ip && in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) { 357 #else /* INET6 */ 358 if (IN_MULTICAST(ip->ip_dst.s_addr) || 359 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { 360 #endif /* INET6 */ 361 struct socket *last; 362 /* 363 * Deliver a multicast or broadcast datagram to *all* sockets 364 * for which the local and remote addresses and ports match 365 * those of the incoming datagram. This allows more than 366 * one process to receive multi/broadcasts on the same port. 367 * (This really ought to be done for unicast datagrams as 368 * well, but that would cause problems with existing 369 * applications that open both address-specific sockets and 370 * a wildcard socket listening to the same port -- they would 371 * end up receiving duplicates of every unicast datagram. 372 * Those applications open the multiple sockets to overcome an 373 * inadequacy of the UDP socket interface, but for backwards 374 * compatibility we avoid the problem here rather than 375 * fixing the interface. Maybe 4.5BSD will remedy this?) 376 */ 377 378 iphlen += sizeof(struct udphdr); 379 380 /* 381 * Locate pcb(s) for datagram. 382 * (Algorithm copied from raw_intr().) 383 */ 384 last = NULL; 385 for (inp = udbtable.inpt_queue.cqh_first; 386 inp != (struct inpcb *)&udbtable.inpt_queue; 387 inp = inp->inp_queue.cqe_next) { 388 #ifdef INET6 389 /* don't accept it if AF does not match */ 390 if (ip6 && !(inp->inp_flags & INP_IPV6)) 391 continue; 392 if (!ip6 && (inp->inp_flags & INP_IPV6)) 393 continue; 394 #endif 395 if (inp->inp_lport != uh->uh_dport) 396 continue; 397 #ifdef INET6 398 if (ip6) { 399 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) 400 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, 401 &ip6->ip6_dst)) 402 continue; 403 } else 404 #endif /* INET6 */ 405 if (inp->inp_laddr.s_addr != INADDR_ANY) { 406 if (inp->inp_laddr.s_addr != 407 ip->ip_dst.s_addr) 408 continue; 409 } 410 #ifdef INET6 411 if (ip6) { 412 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) 413 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, 414 &ip6->ip6_src) || 415 inp->inp_fport != uh->uh_sport) 416 continue; 417 } else 418 #endif /* INET6 */ 419 if (inp->inp_faddr.s_addr != INADDR_ANY) { 420 if (inp->inp_faddr.s_addr != 421 ip->ip_src.s_addr || 422 inp->inp_fport != uh->uh_sport) 423 continue; 424 } 425 426 if (last != NULL) { 427 struct mbuf *n; 428 429 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 430 opts = NULL; 431 #ifdef INET6 432 if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS)) 433 ip6_savecontrol(inp, &opts, ip6, n); 434 #endif /* INET6 */ 435 m_adj(n, iphlen); 436 if (sbappendaddr(&last->so_rcv, 437 &srcsa.sa, n, opts) == 0) { 438 m_freem(n); 439 if (opts) 440 m_freem(opts); 441 udpstat.udps_fullsock++; 442 } else 443 sorwakeup(last); 444 opts = NULL; 445 } 446 } 447 last = inp->inp_socket; 448 /* 449 * Don't look for additional matches if this one does 450 * not have either the SO_REUSEPORT or SO_REUSEADDR 451 * socket options set. This heuristic avoids searching 452 * through all pcbs in the common case of a non-shared 453 * port. It * assumes that an application will never 454 * clear these options after setting them. 455 */ 456 if ((last->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0) 457 break; 458 } 459 460 if (last == NULL) { 461 /* 462 * No matching pcb found; discard datagram. 463 * (No need to send an ICMP Port Unreachable 464 * for a broadcast or multicast datgram.) 465 */ 466 udpstat.udps_noportbcast++; 467 goto bad; 468 } 469 470 opts = NULL; 471 #ifdef INET6 472 if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS)) 473 ip6_savecontrol(inp, &opts, ip6, m); 474 #endif /* INET6 */ 475 m_adj(m, iphlen); 476 if (sbappendaddr(&last->so_rcv, 477 &srcsa.sa, m, opts) == 0) { 478 udpstat.udps_fullsock++; 479 goto bad; 480 } 481 sorwakeup(last); 482 return; 483 } 484 /* 485 * Locate pcb for datagram. 486 */ 487 #ifdef INET6 488 if (ip6) 489 inp = in6_pcbhashlookup(&udbtable, &ip6->ip6_src, uh->uh_sport, 490 &ip6->ip6_dst, uh->uh_dport); 491 else 492 #endif /* INET6 */ 493 inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport, 494 ip->ip_dst, uh->uh_dport); 495 if (inp == 0) { 496 ++udpstat.udps_pcbhashmiss; 497 #ifdef INET6 498 if (ip6) { 499 inp = in_pcblookup(&udbtable, 500 (struct in_addr *)&(ip6->ip6_src), 501 uh->uh_sport, (struct in_addr *)&(ip6->ip6_dst), 502 uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); 503 } else 504 #endif /* INET6 */ 505 inp = in_pcblookup(&udbtable, &ip->ip_src, uh->uh_sport, 506 &ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD); 507 if (inp == 0) { 508 udpstat.udps_noport++; 509 if (m->m_flags & (M_BCAST | M_MCAST)) { 510 udpstat.udps_noportbcast++; 511 goto bad; 512 } 513 #ifdef INET6 514 if (ip6) { 515 icmp6_error(m, ICMP6_DST_UNREACH, 516 ICMP6_DST_UNREACH_NOPORT,0); 517 } else 518 #endif /* INET6 */ 519 { 520 *ip = save_ip; 521 uh->uh_sum = savesum; 522 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 523 0, 0); 524 } 525 return; 526 } 527 } 528 529 #ifdef IPSEC 530 mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); 531 s = splnet(); 532 if (mtag != NULL) { 533 tdbi = (struct tdb_ident *)(mtag + 1); 534 tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); 535 } else 536 tdb = NULL; 537 ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error, 538 IPSP_DIRECTION_IN, tdb, inp); 539 if (error) { 540 splx(s); 541 goto bad; 542 } 543 544 /* Latch SA only if the socket is connected */ 545 if (inp->inp_tdb_in != tdb && 546 (inp->inp_socket->so_state & SS_ISCONNECTED)) { 547 if (tdb) { 548 tdb_add_inp(tdb, inp, 1); 549 if (inp->inp_ipo == NULL) { 550 inp->inp_ipo = ipsec_add_policy(inp, 551 srcsa.sa.sa_family, IPSP_DIRECTION_OUT); 552 if (inp->inp_ipo == NULL) { 553 splx(s); 554 goto bad; 555 } 556 } 557 if (inp->inp_ipo->ipo_dstid == NULL && 558 tdb->tdb_srcid != NULL) { 559 inp->inp_ipo->ipo_dstid = tdb->tdb_srcid; 560 tdb->tdb_srcid->ref_count++; 561 } 562 if (inp->inp_ipsec_remotecred == NULL && 563 tdb->tdb_remote_cred != NULL) { 564 inp->inp_ipsec_remotecred = 565 tdb->tdb_remote_cred; 566 tdb->tdb_remote_cred->ref_count++; 567 } 568 if (inp->inp_ipsec_remoteauth == NULL && 569 tdb->tdb_remote_auth != NULL) { 570 inp->inp_ipsec_remoteauth = 571 tdb->tdb_remote_auth; 572 tdb->tdb_remote_auth->ref_count++; 573 } 574 } else { /* Just reset */ 575 TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in, inp, 576 inp_tdb_in_next); 577 inp->inp_tdb_in = NULL; 578 } 579 } 580 splx(s); 581 #endif /*IPSEC */ 582 583 opts = NULL; 584 #ifdef INET6 585 if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS)) 586 ip6_savecontrol(inp, &opts, ip6, 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)(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)(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 udp_output(struct mbuf *m, ...) 874 { 875 register struct inpcb *inp; 876 struct mbuf *addr, *control; 877 register struct udpiphdr *ui; 878 register int len = m->m_pkthdr.len; 879 struct in_addr laddr; 880 int s = 0, error = 0; 881 va_list ap; 882 int pcbflags = 0; 883 884 va_start(ap, m); 885 inp = va_arg(ap, struct inpcb *); 886 addr = va_arg(ap, struct mbuf *); 887 control = va_arg(ap, struct mbuf *); 888 va_end(ap); 889 890 #ifdef DIAGNOSTIC 891 if ((inp->inp_flags & INP_IPV6) != 0) 892 panic("IPv6 inpcb to udp_output"); 893 #endif 894 895 /* 896 * Compute the packet length of the IP header, and 897 * punt if the length looks bogus. 898 */ 899 if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { 900 error = EMSGSIZE; 901 goto release; 902 } 903 904 if (addr) { 905 /* 906 * Save current PCB flags because they may change during 907 * temporary connection. 908 */ 909 pcbflags = inp->inp_flags; 910 911 laddr = inp->inp_laddr; 912 if (inp->inp_faddr.s_addr != INADDR_ANY) { 913 error = EISCONN; 914 goto release; 915 } 916 /* 917 * Must block input while temporarily connected. 918 */ 919 s = splsoftnet(); 920 error = in_pcbconnect(inp, addr); 921 if (error) { 922 splx(s); 923 goto release; 924 } 925 } else { 926 if (inp->inp_faddr.s_addr == INADDR_ANY) { 927 error = ENOTCONN; 928 goto release; 929 } 930 } 931 /* 932 * Calculate data length and get a mbuf 933 * for UDP and IP headers. 934 */ 935 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); 936 if (m == 0) { 937 error = ENOBUFS; 938 goto bail; 939 } 940 941 /* 942 * Fill in mbuf with extended UDP header 943 * and addresses and length put into network format. 944 */ 945 ui = mtod(m, struct udpiphdr *); 946 bzero(ui->ui_x1, sizeof ui->ui_x1); 947 ui->ui_pr = IPPROTO_UDP; 948 ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr)); 949 ui->ui_src = inp->inp_laddr; 950 ui->ui_dst = inp->inp_faddr; 951 ui->ui_sport = inp->inp_lport; 952 ui->ui_dport = inp->inp_fport; 953 ui->ui_ulen = ui->ui_len; 954 955 /* 956 * Compute the pseudo-header checksum; defer further checksumming 957 * until ip_output() or hardware (if it exists). 958 */ 959 if (udpcksum) { 960 m->m_pkthdr.csum |= M_UDPV4_CSUM_OUT; 961 ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr, 962 ui->ui_dst.s_addr, htons((u_int16_t)len + 963 sizeof (struct udphdr) + IPPROTO_UDP)); 964 } else 965 ui->ui_sum = 0; 966 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 967 ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; 968 ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; 969 970 udpstat.udps_opackets++; 971 error = ip_output(m, inp->inp_options, &inp->inp_route, 972 inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), 973 inp->inp_moptions, inp, (void *)NULL); 974 975 bail: 976 if (addr) { 977 in_pcbdisconnect(inp); 978 inp->inp_flags = pcbflags; 979 inp->inp_laddr = laddr; 980 splx(s); 981 } 982 if (control) 983 m_freem(control); 984 return (error); 985 986 release: 987 m_freem(m); 988 if (control) 989 m_freem(control); 990 return (error); 991 } 992 993 u_int udp_sendspace = 9216; /* really max datagram size */ 994 u_int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); 995 /* 40 1K datagrams */ 996 997 #ifdef INET6 998 /*ARGSUSED*/ 999 int 1000 udp6_usrreq(so, req, m, addr, control, p) 1001 struct socket *so; 1002 int req; 1003 struct mbuf *m, *addr, *control; 1004 struct proc *p; 1005 { 1006 1007 return udp_usrreq(so, req, m, addr, control); 1008 } 1009 #endif 1010 1011 /*ARGSUSED*/ 1012 int 1013 udp_usrreq(so, req, m, addr, control) 1014 struct socket *so; 1015 int req; 1016 struct mbuf *m, *addr, *control; 1017 { 1018 struct inpcb *inp = sotoinpcb(so); 1019 int error = 0; 1020 int s; 1021 1022 if (req == PRU_CONTROL) { 1023 #ifdef INET6 1024 if (inp->inp_flags & INP_IPV6) 1025 return (in6_control(so, (u_long)m, (caddr_t)addr, 1026 (struct ifnet *)control, 0)); 1027 else 1028 #endif /* INET6 */ 1029 return (in_control(so, (u_long)m, (caddr_t)addr, 1030 (struct ifnet *)control)); 1031 } 1032 if (inp == NULL && req != PRU_ATTACH) { 1033 error = EINVAL; 1034 goto release; 1035 } 1036 /* 1037 * Note: need to block udp_input while changing 1038 * the udp pcb queue and/or pcb addresses. 1039 */ 1040 switch (req) { 1041 1042 case PRU_ATTACH: 1043 if (inp != NULL) { 1044 error = EINVAL; 1045 break; 1046 } 1047 s = splsoftnet(); 1048 error = in_pcballoc(so, &udbtable); 1049 splx(s); 1050 if (error) 1051 break; 1052 error = soreserve(so, udp_sendspace, udp_recvspace); 1053 if (error) 1054 break; 1055 #ifdef INET6 1056 if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6) 1057 ((struct inpcb *) so->so_pcb)->inp_ipv6.ip6_hlim = 1058 ip6_defhlim; 1059 else 1060 #endif /* INET6 */ 1061 ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl; 1062 break; 1063 1064 case PRU_DETACH: 1065 udp_detach(inp); 1066 break; 1067 1068 case PRU_BIND: 1069 s = splsoftnet(); 1070 #ifdef INET6 1071 if (inp->inp_flags & INP_IPV6) 1072 error = in6_pcbbind(inp, addr); 1073 else 1074 #endif 1075 error = in_pcbbind(inp, addr); 1076 splx(s); 1077 break; 1078 1079 case PRU_LISTEN: 1080 error = EOPNOTSUPP; 1081 break; 1082 1083 case PRU_CONNECT: 1084 #ifdef INET6 1085 if (inp->inp_flags & INP_IPV6) { 1086 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { 1087 error = EISCONN; 1088 break; 1089 } 1090 s = splsoftnet(); 1091 error = in6_pcbconnect(inp, addr); 1092 splx(s); 1093 } else 1094 #endif /* INET6 */ 1095 { 1096 if (inp->inp_faddr.s_addr != INADDR_ANY) { 1097 error = EISCONN; 1098 break; 1099 } 1100 s = splsoftnet(); 1101 error = in_pcbconnect(inp, addr); 1102 splx(s); 1103 } 1104 1105 if (error == 0) 1106 soisconnected(so); 1107 break; 1108 1109 case PRU_CONNECT2: 1110 error = EOPNOTSUPP; 1111 break; 1112 1113 case PRU_ACCEPT: 1114 error = EOPNOTSUPP; 1115 break; 1116 1117 case PRU_DISCONNECT: 1118 #ifdef INET6 1119 if (inp->inp_flags & INP_IPV6) { 1120 if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { 1121 error = ENOTCONN; 1122 break; 1123 } 1124 } else 1125 #endif /* INET6 */ 1126 { 1127 if (inp->inp_faddr.s_addr == INADDR_ANY) { 1128 error = ENOTCONN; 1129 break; 1130 } 1131 } 1132 1133 s = splsoftnet(); 1134 in_pcbdisconnect(inp); 1135 #ifdef INET6 1136 if (inp->inp_flags & INP_IPV6) 1137 inp->inp_laddr6 = in6addr_any; 1138 else 1139 #endif /* INET6 */ 1140 inp->inp_laddr.s_addr = INADDR_ANY; 1141 1142 splx(s); 1143 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 1144 break; 1145 1146 case PRU_SHUTDOWN: 1147 socantsendmore(so); 1148 break; 1149 1150 case PRU_SEND: 1151 #ifdef INET6 1152 if (inp->inp_flags & INP_IPV6) 1153 return (udp6_output(inp, m, addr, control)); 1154 else 1155 return (udp_output(m, inp, addr, control)); 1156 #else 1157 return (udp_output(m, inp, addr, control)); 1158 #endif 1159 1160 case PRU_ABORT: 1161 soisdisconnected(so); 1162 udp_detach(inp); 1163 break; 1164 1165 case PRU_SOCKADDR: 1166 #ifdef INET6 1167 if (inp->inp_flags & INP_IPV6) 1168 in6_setsockaddr(inp, addr); 1169 else 1170 #endif /* INET6 */ 1171 in_setsockaddr(inp, addr); 1172 break; 1173 1174 case PRU_PEERADDR: 1175 #ifdef INET6 1176 if (inp->inp_flags & INP_IPV6) 1177 in6_setpeeraddr(inp, addr); 1178 else 1179 #endif /* INET6 */ 1180 in_setpeeraddr(inp, addr); 1181 break; 1182 1183 case PRU_SENSE: 1184 /* 1185 * stat: don't bother with a blocksize. 1186 */ 1187 /* 1188 * Perhaps Path MTU might be returned for a connected 1189 * UDP socket in this case. 1190 */ 1191 return (0); 1192 1193 case PRU_SENDOOB: 1194 case PRU_FASTTIMO: 1195 case PRU_SLOWTIMO: 1196 case PRU_PROTORCV: 1197 case PRU_PROTOSEND: 1198 error = EOPNOTSUPP; 1199 break; 1200 1201 case PRU_RCVD: 1202 case PRU_RCVOOB: 1203 return (EOPNOTSUPP); /* do not free mbuf's */ 1204 1205 default: 1206 panic("udp_usrreq"); 1207 } 1208 1209 release: 1210 if (control) { 1211 m_freem(control); 1212 } 1213 if (m) 1214 m_freem(m); 1215 return (error); 1216 } 1217 1218 static void 1219 udp_detach(inp) 1220 struct inpcb *inp; 1221 { 1222 int s = splsoftnet(); 1223 1224 in_pcbdetach(inp); 1225 splx(s); 1226 } 1227 1228 /* 1229 * Sysctl for udp variables. 1230 */ 1231 int 1232 udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 1233 int *name; 1234 u_int namelen; 1235 void *oldp; 1236 size_t *oldlenp; 1237 void *newp; 1238 size_t newlen; 1239 { 1240 /* All sysctl names at this level are terminal. */ 1241 if (namelen != 1) 1242 return (ENOTDIR); 1243 1244 switch (name[0]) { 1245 case UDPCTL_CHECKSUM: 1246 return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum)); 1247 case UDPCTL_BADDYNAMIC: 1248 return (sysctl_struct(oldp, oldlenp, newp, newlen, 1249 baddynamicports.udp, sizeof(baddynamicports.udp))); 1250 case UDPCTL_RECVSPACE: 1251 return (sysctl_int(oldp, oldlenp, newp, newlen,&udp_recvspace)); 1252 case UDPCTL_SENDSPACE: 1253 return (sysctl_int(oldp, oldlenp, newp, newlen,&udp_sendspace)); 1254 default: 1255 return (ENOPROTOOPT); 1256 } 1257 /* NOTREACHED */ 1258 } 1259