1 /* $OpenBSD: udp_usrreq.c,v 1.25 1999/03/27 21:04:20 provos 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 * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94 37 */ 38 39 /* 40 %%% portions-copyright-nrl-95 41 Portions of this software are Copyright 1995-1998 by Randall Atkinson, 42 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights 43 Reserved. All rights under this copyright have been assigned to the US 44 Naval Research Laboratory (NRL). The NRL Copyright Notice and License 45 Agreement Version 1.1 (January 17, 1995) applies to these portions of the 46 software. 47 You should have received a copy of the license with this software. If you 48 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. 49 */ 50 51 #include <sys/param.h> 52 #include <sys/malloc.h> 53 #include <sys/mbuf.h> 54 #include <sys/protosw.h> 55 #include <sys/socket.h> 56 #include <sys/socketvar.h> 57 #include <sys/errno.h> 58 #include <sys/stat.h> 59 #include <sys/systm.h> 60 #include <sys/proc.h> 61 62 #include <vm/vm.h> 63 #include <sys/sysctl.h> 64 65 #include <net/if.h> 66 #include <net/route.h> 67 68 #include <netinet/in.h> 69 #include <netinet/in_systm.h> 70 #include <netinet/in_var.h> 71 #include <netinet/ip.h> 72 #include <netinet/in_pcb.h> 73 #include <netinet/ip_var.h> 74 #include <netinet/ip_icmp.h> 75 #include <netinet/udp.h> 76 #include <netinet/udp_var.h> 77 78 #ifdef IPSEC 79 #include <netinet/ip_ipsp.h> 80 81 extern int check_ipsec_policy __P((struct inpcb *, u_int32_t)); 82 #endif 83 84 #include <machine/stdarg.h> 85 86 #ifdef INET6 87 #include <netinet6/in6.h> 88 #include <netinet6/ipv6.h> 89 #include <netinet6/in6_var.h> 90 #include <netinet6/ipv6_var.h> 91 #include <netinet6/ipv6_icmp.h> 92 93 extern int ipv6_defhoplmt; 94 95 #endif /* INET6 */ 96 97 /* 98 * UDP protocol implementation. 99 * Per RFC 768, August, 1980. 100 */ 101 int udpcksum = 1; 102 103 104 static void udp_detach __P((struct inpcb *)); 105 static void udp_notify __P((struct inpcb *, int)); 106 static struct mbuf *udp_saveopt __P((caddr_t, int, int)); 107 108 #ifndef UDBHASHSIZE 109 #define UDBHASHSIZE 128 110 #endif 111 int udbhashsize = UDBHASHSIZE; 112 113 /* from in_pcb.c */ 114 extern struct baddynamicports baddynamicports; 115 116 void 117 udp_init() 118 { 119 120 in_pcbinit(&udbtable, udbhashsize); 121 } 122 123 void 124 #if __STDC__ 125 udp_input(struct mbuf *m, ...) 126 #else 127 udp_input(m, va_alist) 128 struct mbuf *m; 129 va_dcl 130 #endif 131 { 132 register struct ip *ip; 133 register struct udphdr *uh; 134 register struct inpcb *inp; 135 struct mbuf *opts = 0; 136 int len; 137 struct ip save_ip; 138 int iphlen; 139 va_list ap; 140 u_int16_t savesum; 141 union { 142 struct sockaddr sa; 143 struct sockaddr_in sin; 144 #ifdef INET6 145 struct sockaddr_in6 sin6; 146 #endif /* INET6 */ 147 } srcsa, dstsa; 148 #ifdef INET6 149 struct ipv6 *ipv6; 150 struct sockaddr_in6 src_v4mapped; 151 #endif /* INET6 */ 152 #ifdef IPSEC 153 struct tdb *tdb = NULL; 154 #endif /* IPSEC */ 155 156 va_start(ap, m); 157 iphlen = va_arg(ap, int); 158 va_end(ap); 159 160 udpstat.udps_ipackets++; 161 162 #ifdef IPSEC 163 /* Save the last SA which was used to process the mbuf */ 164 if ((m->m_flags & (M_CONF|M_AUTH)) && m->m_pkthdr.tdbi) { 165 struct tdb_ident *tdbi = m->m_pkthdr.tdbi; 166 tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); 167 free(m->m_pkthdr.tdbi, M_TEMP); 168 m->m_pkthdr.tdbi = NULL; 169 } 170 #endif /* IPSEC */ 171 172 switch (mtod(m, struct ip *)->ip_v) { 173 case 4: 174 ip = mtod(m, struct ip *); 175 #ifdef INET6 176 ipv6 = NULL; 177 #endif /* INET6 */ 178 srcsa.sa.sa_family = AF_INET; 179 break; 180 #ifdef INET6 181 case 6: 182 ip = NULL; 183 ipv6 = mtod(m, struct ipv6 *); 184 srcsa.sa.sa_family = AF_INET6; 185 break; 186 #endif /* INET6 */ 187 default: 188 printf("udp_input: received unknown IP version %d", 189 mtod(m, struct ip *)->ip_v); 190 goto bad; 191 } 192 193 /* 194 * Strip IP options, if any; should skip this, 195 * make available to user, and use on returned packets, 196 * but we don't yet have a way to check the checksum 197 * with options still present. 198 */ 199 /* 200 * (contd. from above...) Furthermore, we may want to strip options 201 * for such things as ICMP errors, where options just get in the way. 202 */ 203 #ifdef INET6 204 if (ip) 205 #endif /* INET6 */ 206 if (iphlen > sizeof (struct ip)) { 207 ip_stripoptions(m, (struct mbuf *)0); 208 iphlen = sizeof(struct ip); 209 } 210 211 /* 212 * Get IP and UDP header together in first mbuf. 213 */ 214 if (m->m_len < iphlen + sizeof(struct udphdr)) { 215 if ((m = m_pullup2(m, iphlen + sizeof(struct udphdr))) == 0) { 216 udpstat.udps_hdrops++; 217 return; 218 } 219 #ifdef INET6 220 if (ipv6) 221 ipv6 = mtod(m, struct ipv6 *); 222 else 223 #endif /* INET6 */ 224 ip = mtod(m, struct ip *); 225 } 226 uh = (struct udphdr *)(mtod(m, caddr_t) + iphlen); 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 (m->m_pkthdr.len - iphlen != len) { 234 if (len > (m->m_pkthdr.len - iphlen) || 235 len < sizeof(struct udphdr)) { 236 udpstat.udps_badlen++; 237 goto bad; 238 } 239 m_adj(m, len - (m->m_pkthdr.len - iphlen)); 240 } 241 /* 242 * Save a copy of the IP header in case we want restore it 243 * for sending an ICMP error message in response. 244 */ 245 if (ip) 246 save_ip = *ip; 247 248 /* 249 * Checksum extended UDP header and data. 250 * from W.R.Stevens: check incoming udp cksums even if 251 * udpcksum is not set. 252 */ 253 savesum = uh->uh_sum; 254 #ifdef INET6 255 if (ipv6) { 256 /* 257 * In IPv6, the UDP checksum is ALWAYS used. 258 */ 259 if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, len, iphlen))) { 260 udpstat.udps_badsum++; 261 goto bad; 262 } 263 } else 264 #endif /* INET6 */ 265 if (uh->uh_sum) { 266 bzero(((struct ipovly *)ip)->ih_x1, 267 sizeof ((struct ipovly *)ip)->ih_x1); 268 ((struct ipovly *)ip)->ih_len = uh->uh_ulen; 269 if ((uh->uh_sum = in_cksum(m, len + sizeof (struct ip))) != 0) { 270 udpstat.udps_badsum++; 271 m_freem(m); 272 return; 273 } 274 } else 275 udpstat.udps_nosum++; 276 277 switch (srcsa.sa.sa_family) { 278 case AF_INET: 279 bzero(&srcsa, sizeof(struct sockaddr_in)); 280 srcsa.sin.sin_len = sizeof(struct sockaddr_in); 281 srcsa.sin.sin_family = AF_INET; 282 srcsa.sin.sin_port = uh->uh_sport; 283 srcsa.sin.sin_addr = ip->ip_src; 284 285 #ifdef INET6 286 bzero(&src_v4mapped, sizeof(struct sockaddr_in6)); 287 src_v4mapped.sin6_len = sizeof(struct sockaddr_in6); 288 src_v4mapped.sin6_family = AF_INET6; 289 src_v4mapped.sin6_port = uh->uh_sport; 290 CREATE_IPV6_MAPPED(src_v4mapped.sin6_addr, ip->ip_src.s_addr); 291 #endif /* INET6 */ 292 293 bzero(&dstsa, sizeof(struct sockaddr_in)); 294 dstsa.sin.sin_len = sizeof(struct sockaddr_in); 295 dstsa.sin.sin_family = AF_INET; 296 dstsa.sin.sin_port = uh->uh_dport; 297 dstsa.sin.sin_addr = ip->ip_dst; 298 break; 299 #ifdef INET6 300 case AF_INET6: 301 bzero(&srcsa, sizeof(struct sockaddr_in6)); 302 srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6); 303 srcsa.sin6.sin6_family = AF_INET6; 304 srcsa.sin6.sin6_port = uh->uh_sport; 305 srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ipv6->ipv6_versfl; 306 srcsa.sin6.sin6_addr = ipv6->ipv6_src; 307 308 bzero(&dstsa, sizeof(struct sockaddr_in6)); 309 dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6); 310 dstsa.sin6.sin6_family = AF_INET6; 311 dstsa.sin6.sin6_port = uh->uh_dport; 312 dstsa.sin6.sin6_addr = ipv6->ipv6_dst; 313 break; 314 #endif /* INET6 */ 315 } 316 317 #ifdef INET6 318 if ((ipv6 && IN6_IS_ADDR_MULTICAST(&ipv6->ipv6_dst)) || 319 (ip && IN_MULTICAST(ip->ip_dst.s_addr)) || 320 (ip && in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) { 321 #else /* INET6 */ 322 if (IN_MULTICAST(ip->ip_dst.s_addr) || 323 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { 324 #endif /* INET6 */ 325 struct socket *last; 326 /* 327 * Deliver a multicast or broadcast datagram to *all* sockets 328 * for which the local and remote addresses and ports match 329 * those of the incoming datagram. This allows more than 330 * one process to receive multi/broadcasts on the same port. 331 * (This really ought to be done for unicast datagrams as 332 * well, but that would cause problems with existing 333 * applications that open both address-specific sockets and 334 * a wildcard socket listening to the same port -- they would 335 * end up receiving duplicates of every unicast datagram. 336 * Those applications open the multiple sockets to overcome an 337 * inadequacy of the UDP socket interface, but for backwards 338 * compatibility we avoid the problem here rather than 339 * fixing the interface. Maybe 4.5BSD will remedy this?) 340 */ 341 342 iphlen += sizeof(struct udphdr); 343 m->m_len -= iphlen; 344 m->m_pkthdr.len -= iphlen; 345 m->m_data += iphlen; 346 /* 347 * Locate pcb(s) for datagram. 348 * (Algorithm copied from raw_intr().) 349 */ 350 last = NULL; 351 for (inp = udbtable.inpt_queue.cqh_first; 352 inp != (struct inpcb *)&udbtable.inpt_queue; 353 inp = inp->inp_queue.cqe_next) { 354 if (inp->inp_lport != uh->uh_dport) 355 continue; 356 #ifdef INET6 357 if (ipv6) { 358 if (!(inp->inp_flags & INP_IPV6)) 359 continue; 360 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) 361 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, 362 &ipv6->ipv6_dst)) 363 continue; 364 } else 365 #endif /* INET6 */ 366 if (inp->inp_laddr.s_addr != INADDR_ANY) { 367 if (inp->inp_laddr.s_addr != 368 ip->ip_dst.s_addr) 369 continue; 370 } 371 #ifdef INET6 372 if (ipv6) { 373 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) 374 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, 375 &ipv6->ipv6_src) || 376 inp->inp_fport != uh->uh_sport) 377 continue; 378 } else 379 #endif /* INET6 */ 380 if (inp->inp_faddr.s_addr != INADDR_ANY) { 381 if (inp->inp_faddr.s_addr != 382 ip->ip_src.s_addr || 383 inp->inp_fport != uh->uh_sport) 384 continue; 385 } 386 387 if (last != NULL) { 388 struct mbuf *n; 389 390 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 391 #ifdef INET6 392 if (ipv6) 393 opts = ipv6_headertocontrol(m, iphlen, ((struct inpcb *)last->so_pcb)->inp_flags); 394 #endif /* INET6 */ 395 if (sbappendaddr(&last->so_rcv, 396 #ifdef INET6 397 /* 398 * This cruft is needed in (the rare) 399 * case I deliver a {multi,broad}cast 400 * IPv4 packet to an AF_INET6 socket. 401 */ 402 ((((struct inpcb *)last->so_pcb)->inp_flags 403 & INP_IPV6) && ip) ? 404 (struct sockaddr *)&src_v4mapped : 405 #endif /* INET6 */ 406 &srcsa.sa, n, (struct mbuf *)0) == 0) { 407 m_freem(n); 408 udpstat.udps_fullsock++; 409 } else 410 sorwakeup(last); 411 } 412 } 413 last = inp->inp_socket; 414 /* 415 * Don't look for additional matches if this one does 416 * not have either the SO_REUSEPORT or SO_REUSEADDR 417 * socket options set. This heuristic avoids searching 418 * through all pcbs in the common case of a non-shared 419 * port. It * assumes that an application will never 420 * clear these options after setting them. 421 */ 422 if ((last->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0) 423 break; 424 } 425 426 if (last == NULL) { 427 /* 428 * No matching pcb found; discard datagram. 429 * (No need to send an ICMP Port Unreachable 430 * for a broadcast or multicast datgram.) 431 */ 432 udpstat.udps_noportbcast++; 433 goto bad; 434 } 435 436 #ifdef INET6 437 if (ipv6) 438 opts = ipv6_headertocontrol(m, iphlen, 439 ((struct inpcb *)last->so_pcb)->inp_flags); 440 #endif /* INET6 */ 441 if (sbappendaddr(&last->so_rcv, 442 #ifdef INET6 443 /* 444 * This cruft is needed in (the rare) case I 445 * deliver a {multi,broad}cast IPv4 packet to 446 * an AF_INET6 socket. 447 */ 448 ((((struct inpcb *)last->so_pcb)->inp_flags & INP_IPV6) && ip) ? 449 (struct sockaddr *)&src_v4mapped : 450 #endif /* INET6 */ 451 &srcsa.sa, m, (struct mbuf *)0) == 0) { 452 udpstat.udps_fullsock++; 453 goto bad; 454 } 455 sorwakeup(last); 456 return; 457 } 458 /* 459 * Locate pcb for datagram. 460 */ 461 #ifdef INET6 462 if (ipv6) 463 inp = in6_pcbhashlookup(&udbtable, &ipv6->ipv6_src, uh->uh_sport, 464 &ipv6->ipv6_dst, uh->uh_dport); 465 else 466 #endif /* INET6 */ 467 inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport, 468 ip->ip_dst, uh->uh_dport); 469 if (inp == 0) { 470 ++udpstat.udps_pcbhashmiss; 471 #ifdef INET6 472 if (ipv6) { 473 inp = in_pcblookup(&udbtable, 474 (struct in_addr *)&(ipv6->ipv6_src), 475 uh->uh_sport, (struct in_addr *)&(ipv6->ipv6_dst), 476 uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); 477 } else 478 #endif /* INET6 */ 479 inp = in_pcblookup(&udbtable, &ip->ip_src, uh->uh_sport, 480 &ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD); 481 if (inp == 0) { 482 udpstat.udps_noport++; 483 if (m->m_flags & (M_BCAST | M_MCAST)) { 484 udpstat.udps_noportbcast++; 485 goto bad; 486 } 487 *ip = save_ip; 488 HTONS(ip->ip_len); 489 HTONS(ip->ip_id); 490 HTONS(ip->ip_off); 491 uh->uh_sum = savesum; 492 #ifdef INET6 493 if (ipv6) 494 ipv6_icmp_error(m, ICMPV6_UNREACH, 495 ICMPV6_UNREACH_PORT,0); 496 else 497 #endif /* INET6 */ 498 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); 499 return; 500 } 501 } 502 503 #ifdef IPSEC 504 /* Check if this socket requires security for incoming packets */ 505 if ((inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_REQUIRE && 506 !(m->m_flags & M_AUTH)) || 507 (inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE && 508 !(m->m_flags & M_CONF))) { 509 #ifdef notyet 510 #ifdef INET6 511 if (ipv6) 512 ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0); 513 else 514 #endif /* INET6 */ 515 icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0); 516 #endif /* notyet */ 517 udpstat.udps_nosec++; 518 goto bad; 519 } 520 /* Use tdb_bind_out for this inp's outbound communication */ 521 if (tdb) 522 tdb_add_inp(tdb, inp); 523 #endif /*IPSEC */ 524 525 if (inp->inp_flags & INP_CONTROLOPTS) { 526 struct mbuf **mp = &opts; 527 528 #ifdef INET6 529 if (ipv6) { 530 if (inp->inp_flags & INP_IPV6) 531 opts = ipv6_headertocontrol(m, iphlen, 532 inp->inp_flags); 533 } else 534 if (ip) 535 #endif /* INET6 */ 536 if (inp->inp_flags & INP_RECVDSTADDR) { 537 *mp = udp_saveopt((caddr_t) &ip->ip_dst, 538 sizeof(struct in_addr), IP_RECVDSTADDR); 539 if (*mp) 540 mp = &(*mp)->m_next; 541 } 542 #ifdef notyet 543 /* options were tossed above */ 544 if (inp->inp_flags & INP_RECVOPTS) { 545 *mp = udp_saveopt((caddr_t) opts_deleted_above, 546 sizeof(struct in_addr), IP_RECVOPTS); 547 if (*mp) 548 mp = &(*mp)->m_next; 549 } 550 /* ip_srcroute doesn't do what we want here, need to fix */ 551 if (inp->inp_flags & INP_RECVRETOPTS) { 552 *mp = udp_saveopt((caddr_t) ip_srcroute(), 553 sizeof(struct in_addr), IP_RECVRETOPTS); 554 if (*mp) 555 mp = &(*mp)->m_next; 556 } 557 #endif 558 } 559 iphlen += sizeof(struct udphdr); 560 m->m_len -= iphlen; 561 m->m_pkthdr.len -= iphlen; 562 m->m_data += iphlen; 563 564 if (sbappendaddr(&inp->inp_socket->so_rcv, 565 #ifdef INET6 566 /* 567 * This cruft is needed to deliver a IPv4 packet to 568 * an AF_INET6 socket. 569 */ 570 ((((struct inpcb *)inp->inp_socket->so_pcb)->inp_flags & INP_IPV6) 571 && ip) ? (struct sockaddr *)&src_v4mapped : 572 #endif /* INET6 */ 573 &srcsa.sa, m, opts) == 0) { 574 udpstat.udps_fullsock++; 575 goto bad; 576 } 577 sorwakeup(inp->inp_socket); 578 return; 579 bad: 580 m_freem(m); 581 if (opts) 582 m_freem(opts); 583 } 584 585 /* 586 * Create a "control" mbuf containing the specified data 587 * with the specified type for presentation with a datagram. 588 */ 589 struct mbuf * 590 udp_saveopt(p, size, type) 591 caddr_t p; 592 register int size; 593 int type; 594 { 595 register struct cmsghdr *cp; 596 struct mbuf *m; 597 598 if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL) 599 return ((struct mbuf *) NULL); 600 cp = (struct cmsghdr *) mtod(m, struct cmsghdr *); 601 bcopy(p, CMSG_DATA(cp), size); 602 size += sizeof(*cp); 603 m->m_len = size; 604 cp->cmsg_len = size; 605 cp->cmsg_level = IPPROTO_IP; 606 cp->cmsg_type = type; 607 return (m); 608 } 609 610 /* 611 * Notify a udp user of an asynchronous error; 612 * just wake up so that he can collect error status. 613 */ 614 static void 615 udp_notify(inp, errno) 616 register struct inpcb *inp; 617 int errno; 618 { 619 inp->inp_socket->so_error = errno; 620 sorwakeup(inp->inp_socket); 621 sowwakeup(inp->inp_socket); 622 } 623 624 void * 625 udp_ctlinput(cmd, sa, v) 626 int cmd; 627 struct sockaddr *sa; 628 void *v; 629 { 630 register struct ip *ip = v; 631 register struct udphdr *uh; 632 extern int inetctlerrmap[]; 633 void (*notify) __P((struct inpcb *, int)) = udp_notify; 634 int errno; 635 636 if ((unsigned)cmd >= PRC_NCMDS) 637 return NULL; 638 errno = inetctlerrmap[cmd]; 639 if (PRC_IS_REDIRECT(cmd)) 640 notify = in_rtchange, ip = 0; 641 else if (cmd == PRC_HOSTDEAD) 642 ip = 0; 643 else if (errno == 0) 644 return NULL; 645 #ifdef INET6 646 if (sa->sa_family == AF_INET6) { 647 if (ip) { 648 struct ipv6 *ipv6 = (struct ipv6 *)ip; 649 650 uh = (struct udphdr *)((caddr_t)ipv6 + sizeof(struct ipv6)); 651 in6_pcbnotify(&udbtable, sa, uh->uh_dport, 652 &(ipv6->ipv6_src), uh->uh_sport, cmd, udp_notify); 653 } else 654 in6_pcbnotify(&udbtable, sa, 0, 655 (struct in6_addr *)&in6addr_any, 0, cmd, udp_notify); 656 } else 657 #endif /* INET6 */ 658 if (ip) { 659 uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); 660 in_pcbnotify(&udbtable, sa, uh->uh_dport, ip->ip_src, 661 uh->uh_sport, errno, notify); 662 } else 663 in_pcbnotifyall(&udbtable, sa, errno, notify); 664 return NULL; 665 } 666 667 int 668 #if __STDC__ 669 udp_output(struct mbuf *m, ...) 670 #else 671 udp_output(m, va_alist) 672 struct mbuf *m; 673 va_dcl 674 #endif 675 { 676 register struct inpcb *inp; 677 struct mbuf *addr, *control; 678 register struct udpiphdr *ui; 679 register int len = m->m_pkthdr.len; 680 struct in_addr laddr; 681 int s = 0, error = 0; 682 va_list ap; 683 #ifdef INET6 684 register struct in6_addr laddr6; 685 int v6packet = 0; 686 struct ifnet *forceif = NULL; 687 #endif /* INET6 */ 688 int pcbflags = 0; 689 690 va_start(ap, m); 691 inp = va_arg(ap, struct inpcb *); 692 addr = va_arg(ap, struct mbuf *); 693 control = va_arg(ap, struct mbuf *); 694 va_end(ap); 695 696 #ifndef INET6 697 if (control) 698 m_freem(control); /* XXX */ 699 #endif /* INET6 */ 700 701 if (addr) { 702 /* 703 * Save current PCB flags because they may change during 704 * temporary connection, particularly the INP_IPV6_UNDEC 705 * flag. 706 */ 707 pcbflags = inp->inp_flags; 708 709 #ifdef INET6 710 if (inp->inp_flags & INP_IPV6) 711 laddr6 = inp->inp_laddr6; 712 else 713 #endif /* INET6 */ 714 laddr = inp->inp_laddr; 715 #ifdef INET6 716 if (((inp->inp_flags & INP_IPV6) && 717 !IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) || 718 (inp->inp_faddr.s_addr != INADDR_ANY)) { 719 #else /* INET6 */ 720 if (inp->inp_faddr.s_addr != INADDR_ANY) { 721 #endif /* INET6 */ 722 error = EISCONN; 723 goto release; 724 } 725 /* 726 * Must block input while temporarily connected. 727 */ 728 s = splsoftnet(); 729 error = in_pcbconnect(inp, addr); 730 if (error) { 731 splx(s); 732 goto release; 733 } 734 } else { 735 #ifdef INET6 736 if (((inp->inp_flags & INP_IPV6) && 737 IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) || 738 (inp->inp_faddr.s_addr == INADDR_ANY)) { 739 #else /* INET6 */ 740 if (inp->inp_faddr.s_addr == INADDR_ANY) { 741 #endif /* INET6 */ 742 error = ENOTCONN; 743 goto release; 744 } 745 } 746 /* 747 * Calculate data length and get a mbuf 748 * for UDP and IP headers. 749 */ 750 #ifdef INET6 751 /* 752 * Handles IPv4-mapped IPv6 address because temporary connect sets 753 * the right flag. 754 */ 755 v6packet = ((inp->inp_flags & INP_IPV6) && 756 !(inp->inp_flags & INP_IPV6_MAPPED)); 757 758 if (!v6packet && control) 759 m_freem(control); 760 761 M_PREPEND(m, v6packet ? (sizeof(struct udphdr) + 762 sizeof(struct ipv6)) : sizeof(struct udpiphdr), M_DONTWAIT); 763 #else /* INET6 */ 764 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); 765 #endif /* INET6 */ 766 if (m == 0) { 767 error = ENOBUFS; 768 goto bail; 769 } 770 771 /* 772 * Compute the packet length of the IP header, and 773 * punt if the length looks bogus. 774 */ 775 if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { 776 error = EMSGSIZE; 777 goto release; 778 } 779 780 /* 781 * Fill in mbuf with extended UDP header 782 * and addresses and length put into network format. 783 */ 784 #ifdef INET6 785 if (v6packet) { 786 struct ipv6 *ipv6 = mtod(m, struct ipv6 *); 787 struct udphdr *uh = (struct udphdr *)(mtod(m, caddr_t) + 788 sizeof(struct ipv6)); 789 int payload = sizeof(struct ipv6); 790 791 ipv6->ipv6_versfl = htonl(0x60000000) | 792 (inp->inp_ipv6.ipv6_versfl & htonl(0x0fffffff)); 793 794 ipv6->ipv6_hoplimit = inp->inp_ipv6.ipv6_hoplimit; 795 ipv6->ipv6_nexthdr = IPPROTO_UDP; 796 ipv6->ipv6_src = inp->inp_laddr6; 797 ipv6->ipv6_dst = inp->inp_faddr6; 798 ipv6->ipv6_length = (u_short)len + sizeof(struct udphdr); 799 800 uh->uh_sport = inp->inp_lport; 801 uh->uh_dport = inp->inp_fport; 802 uh->uh_ulen = htons(ipv6->ipv6_length); 803 uh->uh_sum = 0; 804 805 if (control) 806 if ((error = ipv6_controltoheader(&m, control, 807 &forceif, &payload))) 808 goto release; 809 810 /* 811 * Always calculate udp checksum for IPv6 datagrams 812 */ 813 if (!(uh->uh_sum = in6_cksum(m, IPPROTO_UDP, len + 814 sizeof(struct udphdr), payload))) 815 uh->uh_sum = 0xffff; 816 817 error = ipv6_output(m, &inp->inp_route6, 818 inp->inp_socket->so_options & SO_DONTROUTE, 819 (inp->inp_flags & INP_IPV6_MCAST)?inp->inp_moptions6:NULL, 820 forceif, inp->inp_socket); 821 } else 822 #endif /* INET6 */ 823 { 824 ui = mtod(m, struct udpiphdr *); 825 bzero(ui->ui_x1, sizeof ui->ui_x1); 826 ui->ui_pr = IPPROTO_UDP; 827 ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr)); 828 ui->ui_src = inp->inp_laddr; 829 ui->ui_dst = inp->inp_faddr; 830 ui->ui_sport = inp->inp_lport; 831 ui->ui_dport = inp->inp_fport; 832 ui->ui_ulen = ui->ui_len; 833 834 /* 835 * Stuff checksum and output datagram. 836 */ 837 838 ui->ui_sum = 0; 839 if (udpcksum) { 840 if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + 841 len)) == 0) 842 ui->ui_sum = 0xffff; 843 } 844 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 845 #ifdef INET6 846 /* 847 * For now, we use the default values for ttl and tos for 848 * v4 packets sent using a v6 pcb. We probably want to 849 * later allow v4 setsockopt operations on a v6 socket to 850 * modify the ttl and tos for v4 packets sent using 851 * the mapped address format. We really ought to 852 * save the v4 ttl and v6 hoplimit in separate places 853 * instead of craming both in the inp_hu union. 854 */ 855 if (inp->inp_flags & INP_IPV6) { 856 ((struct ip *)ui)->ip_ttl = ip_defttl; 857 ((struct ip *)ui)->ip_tos = 0; 858 } else 859 #endif /* INET6 */ 860 { 861 ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; 862 ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; 863 } 864 865 udpstat.udps_opackets++; 866 #ifdef INET6 867 if (inp->inp_flags & INP_IPV6_MCAST) 868 error = ip_output(m, inp->inp_options, &inp->inp_route, 869 inp->inp_socket->so_options & 870 (SO_DONTROUTE | SO_BROADCAST), 871 NULL, NULL, inp->inp_socket); 872 else 873 #endif /* INET6 */ 874 error = ip_output(m, inp->inp_options, &inp->inp_route, 875 inp->inp_socket->so_options & 876 (SO_DONTROUTE | SO_BROADCAST), 877 inp->inp_moptions, inp, NULL); 878 } 879 880 bail: 881 if (addr) { 882 in_pcbdisconnect(inp); 883 inp->inp_flags = pcbflags; 884 #ifdef INET6 885 if (inp->inp_flags & INP_IPV6) 886 inp->inp_laddr6 = laddr6; 887 else 888 #endif /* INET6 */ 889 inp->inp_laddr = laddr; 890 splx(s); 891 } 892 return (error); 893 894 release: 895 m_freem(m); 896 return (error); 897 } 898 899 u_int udp_sendspace = 9216; /* really max datagram size */ 900 u_int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); 901 /* 40 1K datagrams */ 902 903 /*ARGSUSED*/ 904 int 905 udp_usrreq(so, req, m, addr, control) 906 struct socket *so; 907 int req; 908 struct mbuf *m, *addr, *control; 909 { 910 struct inpcb *inp = sotoinpcb(so); 911 int error = 0; 912 int s; 913 914 if (req == PRU_CONTROL) { 915 #ifdef INET6 916 if (inp->inp_flags & INP_IPV6) 917 return (in6_control(so, (u_long)m, (caddr_t)addr, 918 (struct ifnet *)control, 0)); 919 else 920 #endif /* INET6 */ 921 return (in_control(so, (u_long)m, (caddr_t)addr, 922 (struct ifnet *)control)); 923 } 924 if (inp == NULL && req != PRU_ATTACH) { 925 error = EINVAL; 926 goto release; 927 } 928 /* 929 * Note: need to block udp_input while changing 930 * the udp pcb queue and/or pcb addresses. 931 */ 932 switch (req) { 933 934 case PRU_ATTACH: 935 if (inp != NULL) { 936 error = EINVAL; 937 break; 938 } 939 s = splsoftnet(); 940 error = in_pcballoc(so, &udbtable); 941 splx(s); 942 if (error) 943 break; 944 error = soreserve(so, udp_sendspace, udp_recvspace); 945 if (error) 946 break; 947 #ifdef INET6 948 if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6) 949 ((struct inpcb *) so->so_pcb)->inp_ipv6.ipv6_hoplimit = 950 ipv6_defhoplmt; 951 else 952 #endif /* INET6 */ 953 ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl; 954 break; 955 956 case PRU_DETACH: 957 udp_detach(inp); 958 break; 959 960 case PRU_BIND: 961 s = splsoftnet(); 962 error = in_pcbbind(inp, addr); 963 splx(s); 964 break; 965 966 case PRU_LISTEN: 967 error = EOPNOTSUPP; 968 break; 969 970 case PRU_CONNECT: 971 #ifdef INET6 972 if (inp->inp_flags & INP_IPV6) { 973 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { 974 error = EISCONN; 975 break; 976 } 977 } else 978 #endif /* INET6 */ 979 if (inp->inp_faddr.s_addr != INADDR_ANY) { 980 error = EISCONN; 981 break; 982 } 983 984 s = splsoftnet(); 985 error = in_pcbconnect(inp, addr); 986 splx(s); 987 if (error == 0) 988 soisconnected(so); 989 break; 990 991 case PRU_CONNECT2: 992 error = EOPNOTSUPP; 993 break; 994 995 case PRU_ACCEPT: 996 error = EOPNOTSUPP; 997 break; 998 999 case PRU_DISCONNECT: 1000 #ifdef INET6 1001 if (inp->inp_flags & INP_IPV6) { 1002 if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { 1003 error = ENOTCONN; 1004 break; 1005 } 1006 } else 1007 #endif /* INET6 */ 1008 if (inp->inp_faddr.s_addr == INADDR_ANY) { 1009 error = ENOTCONN; 1010 break; 1011 } 1012 1013 s = splsoftnet(); 1014 in_pcbdisconnect(inp); 1015 #ifdef INET6 1016 if (inp->inp_flags & INP_IPV6) 1017 inp->inp_laddr6 = in6addr_any; 1018 else 1019 #endif /* INET6 */ 1020 inp->inp_laddr.s_addr = INADDR_ANY; 1021 1022 splx(s); 1023 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 1024 break; 1025 1026 case PRU_SHUTDOWN: 1027 socantsendmore(so); 1028 break; 1029 1030 case PRU_SEND: 1031 #ifdef IPSEC 1032 error = check_ipsec_policy(inp,0); 1033 if (error) 1034 return (error); 1035 #endif 1036 return (udp_output(m, inp, addr, control)); 1037 1038 case PRU_ABORT: 1039 soisdisconnected(so); 1040 udp_detach(inp); 1041 break; 1042 1043 case PRU_SOCKADDR: 1044 in_setsockaddr(inp, addr); 1045 break; 1046 1047 case PRU_PEERADDR: 1048 in_setpeeraddr(inp, addr); 1049 break; 1050 1051 case PRU_SENSE: 1052 /* 1053 * stat: don't bother with a blocksize. 1054 */ 1055 /* 1056 * Perhaps Path MTU might be returned for a connected 1057 * UDP socket in this case. 1058 */ 1059 return (0); 1060 1061 case PRU_SENDOOB: 1062 case PRU_FASTTIMO: 1063 case PRU_SLOWTIMO: 1064 case PRU_PROTORCV: 1065 case PRU_PROTOSEND: 1066 error = EOPNOTSUPP; 1067 break; 1068 1069 case PRU_RCVD: 1070 case PRU_RCVOOB: 1071 return (EOPNOTSUPP); /* do not free mbuf's */ 1072 1073 default: 1074 panic("udp_usrreq"); 1075 } 1076 1077 release: 1078 if (control) { 1079 printf("udp control data unexpectedly retained\n"); 1080 m_freem(control); 1081 } 1082 if (m) 1083 m_freem(m); 1084 return (error); 1085 } 1086 1087 static void 1088 udp_detach(inp) 1089 struct inpcb *inp; 1090 { 1091 int s = splsoftnet(); 1092 1093 in_pcbdetach(inp); 1094 splx(s); 1095 } 1096 1097 /* 1098 * Sysctl for udp variables. 1099 */ 1100 int 1101 udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 1102 int *name; 1103 u_int namelen; 1104 void *oldp; 1105 size_t *oldlenp; 1106 void *newp; 1107 size_t newlen; 1108 { 1109 /* All sysctl names at this level are terminal. */ 1110 if (namelen != 1) 1111 return (ENOTDIR); 1112 1113 switch (name[0]) { 1114 case UDPCTL_CHECKSUM: 1115 return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum)); 1116 case UDPCTL_BADDYNAMIC: 1117 return (sysctl_struct(oldp, oldlenp, newp, newlen, 1118 baddynamicports.udp, sizeof(baddynamicports.udp))); 1119 case UDPCTL_RECVSPACE: 1120 return (sysctl_int(oldp, oldlenp, newp, newlen,&udp_recvspace)); 1121 case UDPCTL_SENDSPACE: 1122 return (sysctl_int(oldp, oldlenp, newp, newlen,&udp_sendspace)); 1123 default: 1124 return (ENOPROTOOPT); 1125 } 1126 /* NOTREACHED */ 1127 } 1128