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