1 /* $OpenBSD: udp_usrreq.c,v 1.219 2016/09/03 13:46:57 reyk 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 udpstat udpstat; 134 135 int udp_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *); 136 void udp_notify(struct inpcb *, int); 137 138 #ifndef UDB_INITIAL_HASH_SIZE 139 #define UDB_INITIAL_HASH_SIZE 128 140 #endif 141 142 void 143 udp_init(void) 144 { 145 in_pcbinit(&udbtable, UDB_INITIAL_HASH_SIZE); 146 } 147 148 #ifdef INET6 149 int 150 udp6_input(struct mbuf **mp, int *offp, int proto) 151 { 152 struct mbuf *m = *mp; 153 154 udp_input(m, *offp, proto); 155 return IPPROTO_DONE; 156 } 157 #endif 158 159 void 160 udp_input(struct mbuf *m, ...) 161 { 162 struct ip *ip; 163 struct udphdr *uh; 164 struct inpcb *inp = NULL; 165 struct mbuf *opts = NULL; 166 struct ip save_ip; 167 int iphlen, len; 168 va_list ap; 169 u_int16_t savesum; 170 union { 171 struct sockaddr sa; 172 struct sockaddr_in sin; 173 #ifdef INET6 174 struct sockaddr_in6 sin6; 175 #endif /* INET6 */ 176 } srcsa, dstsa; 177 #ifdef INET6 178 struct ip6_hdr *ip6; 179 #endif /* INET6 */ 180 #ifdef IPSEC 181 struct m_tag *mtag; 182 struct tdb_ident *tdbi; 183 struct tdb *tdb; 184 int error; 185 u_int32_t ipsecflowinfo = 0; 186 #endif /* IPSEC */ 187 188 va_start(ap, m); 189 iphlen = va_arg(ap, int); 190 va_end(ap); 191 192 udpstat.udps_ipackets++; 193 194 switch (mtod(m, struct ip *)->ip_v) { 195 case 4: 196 ip = mtod(m, struct ip *); 197 #ifdef INET6 198 ip6 = NULL; 199 #endif /* INET6 */ 200 srcsa.sa.sa_family = AF_INET; 201 break; 202 #ifdef INET6 203 case 6: 204 ip = NULL; 205 ip6 = mtod(m, struct ip6_hdr *); 206 srcsa.sa.sa_family = AF_INET6; 207 break; 208 #endif /* INET6 */ 209 default: 210 goto bad; 211 } 212 213 IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr)); 214 if (!uh) { 215 udpstat.udps_hdrops++; 216 return; 217 } 218 219 /* Check for illegal destination port 0 */ 220 if (uh->uh_dport == 0) { 221 udpstat.udps_noport++; 222 goto bad; 223 } 224 225 /* 226 * Make mbuf data length reflect UDP length. 227 * If not enough data to reflect UDP length, drop. 228 */ 229 len = ntohs((u_int16_t)uh->uh_ulen); 230 if (ip) { 231 if (m->m_pkthdr.len - iphlen != len) { 232 if (len > (m->m_pkthdr.len - iphlen) || 233 len < sizeof(struct udphdr)) { 234 udpstat.udps_badlen++; 235 goto bad; 236 } 237 m_adj(m, len - (m->m_pkthdr.len - iphlen)); 238 } 239 } 240 #ifdef INET6 241 else if (ip6) { 242 /* jumbograms */ 243 if (len == 0 && m->m_pkthdr.len - iphlen > 0xffff) 244 len = m->m_pkthdr.len - iphlen; 245 if (len != m->m_pkthdr.len - iphlen) { 246 udpstat.udps_badlen++; 247 goto bad; 248 } 249 } 250 #endif 251 else /* shouldn't happen */ 252 goto bad; 253 254 /* 255 * Save a copy of the IP header in case we want restore it 256 * for sending an ICMP error message in response. 257 */ 258 if (ip) 259 save_ip = *ip; 260 261 #ifdef INET6 262 if (ip6) { 263 /* Be proactive about malicious use of IPv4 mapped address */ 264 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || 265 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { 266 /* XXX stat */ 267 goto bad; 268 } 269 } 270 #endif /* INET6 */ 271 272 /* 273 * Checksum extended UDP header and data. 274 * from W.R.Stevens: check incoming udp cksums even if 275 * udpcksum is not set. 276 */ 277 savesum = uh->uh_sum; 278 if (uh->uh_sum == 0) { 279 udpstat.udps_nosum++; 280 #ifdef INET6 281 /* 282 * In IPv6, the UDP checksum is ALWAYS used. 283 */ 284 if (ip6) 285 goto bad; 286 #endif /* INET6 */ 287 } else { 288 if ((m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_OK) == 0) { 289 if (m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_BAD) { 290 udpstat.udps_badsum++; 291 goto bad; 292 } 293 udpstat.udps_inswcsum++; 294 295 if (ip) 296 uh->uh_sum = in4_cksum(m, IPPROTO_UDP, 297 iphlen, len); 298 #ifdef INET6 299 else if (ip6) 300 uh->uh_sum = in6_cksum(m, IPPROTO_UDP, 301 iphlen, len); 302 #endif /* INET6 */ 303 if (uh->uh_sum != 0) { 304 udpstat.udps_badsum++; 305 goto bad; 306 } 307 } 308 } 309 310 #ifdef IPSEC 311 if (udpencap_enable && udpencap_port && 312 #if NPF > 0 313 !(m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) && 314 #endif 315 uh->uh_dport == htons(udpencap_port)) { 316 u_int32_t spi; 317 int skip = iphlen + sizeof(struct udphdr); 318 319 if (m->m_pkthdr.len - skip < sizeof(u_int32_t)) { 320 /* packet too short */ 321 m_freem(m); 322 return; 323 } 324 m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi); 325 /* 326 * decapsulate if the SPI is not zero, otherwise pass 327 * to userland 328 */ 329 if (spi != 0) { 330 if ((m = m_pullup(m, skip)) == NULL) { 331 udpstat.udps_hdrops++; 332 return; 333 } 334 335 /* remove the UDP header */ 336 bcopy(mtod(m, u_char *), 337 mtod(m, u_char *) + sizeof(struct udphdr), iphlen); 338 m_adj(m, sizeof(struct udphdr)); 339 skip -= sizeof(struct udphdr); 340 341 espstat.esps_udpencin++; 342 ipsec_common_input(m, skip, offsetof(struct ip, ip_p), 343 srcsa.sa.sa_family, IPPROTO_ESP, 1); 344 return; 345 } 346 } 347 #endif 348 349 switch (srcsa.sa.sa_family) { 350 case AF_INET: 351 bzero(&srcsa, sizeof(struct sockaddr_in)); 352 srcsa.sin.sin_len = sizeof(struct sockaddr_in); 353 srcsa.sin.sin_family = AF_INET; 354 srcsa.sin.sin_port = uh->uh_sport; 355 srcsa.sin.sin_addr = ip->ip_src; 356 357 bzero(&dstsa, sizeof(struct sockaddr_in)); 358 dstsa.sin.sin_len = sizeof(struct sockaddr_in); 359 dstsa.sin.sin_family = AF_INET; 360 dstsa.sin.sin_port = uh->uh_dport; 361 dstsa.sin.sin_addr = ip->ip_dst; 362 break; 363 #ifdef INET6 364 case AF_INET6: 365 bzero(&srcsa, sizeof(struct sockaddr_in6)); 366 srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6); 367 srcsa.sin6.sin6_family = AF_INET6; 368 srcsa.sin6.sin6_port = uh->uh_sport; 369 #if 0 /*XXX inbound flowinfo */ 370 srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow; 371 #endif 372 /* KAME hack: recover scopeid */ 373 in6_recoverscope(&srcsa.sin6, &ip6->ip6_src); 374 375 bzero(&dstsa, sizeof(struct sockaddr_in6)); 376 dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6); 377 dstsa.sin6.sin6_family = AF_INET6; 378 dstsa.sin6.sin6_port = uh->uh_dport; 379 #if 0 /*XXX inbound flowinfo */ 380 dstsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow; 381 #endif 382 /* KAME hack: recover scopeid */ 383 in6_recoverscope(&dstsa.sin6, &ip6->ip6_dst); 384 break; 385 #endif /* INET6 */ 386 } 387 388 #if NVXLAN > 0 389 if (vxlan_enable > 0 && 390 #if NPF > 0 391 !(m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) && 392 #endif 393 (error = vxlan_lookup(m, uh, iphlen, &srcsa.sa, &dstsa.sa)) != 0) { 394 if (error == -1) { 395 udpstat.udps_hdrops++; 396 m_freem(m); 397 } 398 return; 399 } 400 #endif 401 402 if (m->m_flags & (M_BCAST|M_MCAST)) { 403 struct inpcb *last; 404 /* 405 * Deliver a multicast or broadcast datagram to *all* sockets 406 * for which the local and remote addresses and ports match 407 * those of the incoming datagram. This allows more than 408 * one process to receive multi/broadcasts on the same port. 409 * (This really ought to be done for unicast datagrams as 410 * well, but that would cause problems with existing 411 * applications that open both address-specific sockets and 412 * a wildcard socket listening to the same port -- they would 413 * end up receiving duplicates of every unicast datagram. 414 * Those applications open the multiple sockets to overcome an 415 * inadequacy of the UDP socket interface, but for backwards 416 * compatibility we avoid the problem here rather than 417 * fixing the interface. Maybe 4.5BSD will remedy this?) 418 */ 419 420 iphlen += sizeof(struct udphdr); 421 422 /* 423 * Locate pcb(s) for datagram. 424 * (Algorithm copied from raw_intr().) 425 */ 426 last = NULL; 427 TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) { 428 if (inp->inp_socket->so_state & SS_CANTRCVMORE) 429 continue; 430 #ifdef INET6 431 /* don't accept it if AF does not match */ 432 if (ip6 && !(inp->inp_flags & INP_IPV6)) 433 continue; 434 if (!ip6 && (inp->inp_flags & INP_IPV6)) 435 continue; 436 #endif 437 if (rtable_l2(inp->inp_rtableid) != 438 rtable_l2(m->m_pkthdr.ph_rtableid)) 439 continue; 440 if (inp->inp_lport != uh->uh_dport) 441 continue; 442 #ifdef INET6 443 if (ip6) { 444 if (inp->inp_ip6_minhlim && 445 inp->inp_ip6_minhlim > ip6->ip6_hlim) 446 continue; 447 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) 448 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, 449 &ip6->ip6_dst)) 450 continue; 451 } else 452 #endif /* INET6 */ 453 { 454 if (inp->inp_ip_minttl && 455 inp->inp_ip_minttl > ip->ip_ttl) 456 continue; 457 458 if (inp->inp_laddr.s_addr != INADDR_ANY) { 459 if (inp->inp_laddr.s_addr != 460 ip->ip_dst.s_addr) 461 continue; 462 } 463 } 464 #ifdef INET6 465 if (ip6) { 466 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) 467 if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, 468 &ip6->ip6_src) || 469 inp->inp_fport != uh->uh_sport) 470 continue; 471 } else 472 #endif /* INET6 */ 473 if (inp->inp_faddr.s_addr != INADDR_ANY) { 474 if (inp->inp_faddr.s_addr != 475 ip->ip_src.s_addr || 476 inp->inp_fport != uh->uh_sport) 477 continue; 478 } 479 480 if (last != NULL) { 481 struct mbuf *n; 482 483 n = m_copym(m, 0, M_COPYALL, M_NOWAIT); 484 if (n != NULL) { 485 #ifdef INET6 486 if (ip6 && (last->inp_flags & 487 IN6P_CONTROLOPTS || 488 last->inp_socket->so_options & 489 SO_TIMESTAMP)) 490 ip6_savecontrol(last, n, &opts); 491 #endif /* INET6 */ 492 if (ip && (last->inp_flags & 493 INP_CONTROLOPTS || 494 last->inp_socket->so_options & 495 SO_TIMESTAMP)) 496 ip_savecontrol(last, &opts, 497 ip, n); 498 499 m_adj(n, iphlen); 500 if (sbappendaddr( 501 &last->inp_socket->so_rcv, 502 &srcsa.sa, n, opts) == 0) { 503 m_freem(n); 504 m_freem(opts); 505 udpstat.udps_fullsock++; 506 } else 507 sorwakeup(last->inp_socket); 508 opts = NULL; 509 } 510 } 511 last = inp; 512 /* 513 * Don't look for additional matches if this one does 514 * not have either the SO_REUSEPORT or SO_REUSEADDR 515 * socket options set. This heuristic avoids searching 516 * through all pcbs in the common case of a non-shared 517 * port. It assumes that an application will never 518 * clear these options after setting them. 519 */ 520 if ((last->inp_socket->so_options & (SO_REUSEPORT | 521 SO_REUSEADDR)) == 0) 522 break; 523 } 524 525 if (last == NULL) { 526 /* 527 * No matching pcb found; discard datagram. 528 * (No need to send an ICMP Port Unreachable 529 * for a broadcast or multicast datgram.) 530 */ 531 udpstat.udps_noportbcast++; 532 goto bad; 533 } 534 535 #ifdef INET6 536 if (ip6 && (last->inp_flags & IN6P_CONTROLOPTS || 537 last->inp_socket->so_options & SO_TIMESTAMP)) 538 ip6_savecontrol(last, m, &opts); 539 #endif /* INET6 */ 540 if (ip && (last->inp_flags & INP_CONTROLOPTS || 541 last->inp_socket->so_options & SO_TIMESTAMP)) 542 ip_savecontrol(last, &opts, ip, m); 543 544 m_adj(m, iphlen); 545 if (sbappendaddr(&last->inp_socket->so_rcv, 546 &srcsa.sa, m, opts) == 0) { 547 udpstat.udps_fullsock++; 548 goto bad; 549 } 550 sorwakeup(last->inp_socket); 551 return; 552 } 553 /* 554 * Locate pcb for datagram. 555 */ 556 #if NPF > 0 && 0 /* currently disabled */ 557 inp = pf_inp_lookup(m); 558 #endif 559 if (inp == NULL) { 560 #ifdef INET6 561 if (ip6) 562 inp = in6_pcbhashlookup(&udbtable, &ip6->ip6_src, 563 uh->uh_sport, &ip6->ip6_dst, uh->uh_dport, 564 m->m_pkthdr.ph_rtableid); 565 else 566 #endif /* INET6 */ 567 inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport, 568 ip->ip_dst, uh->uh_dport, m->m_pkthdr.ph_rtableid); 569 } 570 if (inp == 0) { 571 int inpl_reverse = 0; 572 if (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST) 573 inpl_reverse = 1; 574 ++udpstat.udps_pcbhashmiss; 575 #ifdef INET6 576 if (ip6) { 577 inp = in6_pcblookup_listen(&udbtable, 578 &ip6->ip6_dst, uh->uh_dport, inpl_reverse, m, 579 m->m_pkthdr.ph_rtableid); 580 } else 581 #endif /* INET6 */ 582 inp = in_pcblookup_listen(&udbtable, 583 ip->ip_dst, uh->uh_dport, inpl_reverse, m, 584 m->m_pkthdr.ph_rtableid); 585 if (inp == 0) { 586 udpstat.udps_noport++; 587 if (m->m_flags & (M_BCAST | M_MCAST)) { 588 udpstat.udps_noportbcast++; 589 goto bad; 590 } 591 #ifdef INET6 592 if (ip6) { 593 uh->uh_sum = savesum; 594 icmp6_error(m, ICMP6_DST_UNREACH, 595 ICMP6_DST_UNREACH_NOPORT,0); 596 } else 597 #endif /* INET6 */ 598 { 599 *ip = save_ip; 600 uh->uh_sum = savesum; 601 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 602 0, 0); 603 } 604 return; 605 } 606 } 607 KASSERT(sotoinpcb(inp->inp_socket) == inp); 608 609 #ifdef INET6 610 if (ip6 && inp->inp_ip6_minhlim && 611 inp->inp_ip6_minhlim > ip6->ip6_hlim) { 612 goto bad; 613 } else 614 #endif 615 if (ip && inp->inp_ip_minttl && 616 inp->inp_ip_minttl > ip->ip_ttl) { 617 goto bad; 618 } 619 620 #if NPF > 0 621 if (inp->inp_socket->so_state & SS_ISCONNECTED) 622 pf_inp_link(m, inp); 623 #endif 624 625 #ifdef IPSEC 626 mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); 627 if (mtag != NULL) { 628 tdbi = (struct tdb_ident *)(mtag + 1); 629 tdb = gettdb(tdbi->rdomain, tdbi->spi, 630 &tdbi->dst, tdbi->proto); 631 } else 632 tdb = NULL; 633 ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error, 634 IPSP_DIRECTION_IN, tdb, inp, 0); 635 if (error) { 636 udpstat.udps_nosec++; 637 goto bad; 638 } 639 /* create ipsec options while we know that tdb cannot be modified */ 640 if (tdb && tdb->tdb_ids) 641 ipsecflowinfo = tdb->tdb_ids->id_flow; 642 #endif /*IPSEC */ 643 644 opts = NULL; 645 #ifdef INET6 646 if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS || 647 inp->inp_socket->so_options & SO_TIMESTAMP)) 648 ip6_savecontrol(inp, m, &opts); 649 #endif /* INET6 */ 650 if (ip && (inp->inp_flags & INP_CONTROLOPTS || 651 inp->inp_socket->so_options & SO_TIMESTAMP)) 652 ip_savecontrol(inp, &opts, ip, m); 653 #ifdef INET6 654 if (ip6 && (inp->inp_flags & IN6P_RECVDSTPORT)) { 655 struct mbuf **mp = &opts; 656 657 while (*mp) 658 mp = &(*mp)->m_next; 659 *mp = sbcreatecontrol((caddr_t)&uh->uh_dport, sizeof(u_int16_t), 660 IPV6_RECVDSTPORT, IPPROTO_IPV6); 661 } 662 #endif /* INET6 */ 663 if (ip && (inp->inp_flags & INP_RECVDSTPORT)) { 664 struct mbuf **mp = &opts; 665 666 while (*mp) 667 mp = &(*mp)->m_next; 668 *mp = sbcreatecontrol((caddr_t)&uh->uh_dport, sizeof(u_int16_t), 669 IP_RECVDSTPORT, IPPROTO_IP); 670 } 671 #ifdef IPSEC 672 if (ipsecflowinfo && (inp->inp_flags & INP_IPSECFLOWINFO)) { 673 struct mbuf **mp = &opts; 674 675 while (*mp) 676 mp = &(*mp)->m_next; 677 *mp = sbcreatecontrol((caddr_t)&ipsecflowinfo, 678 sizeof(u_int32_t), IP_IPSECFLOWINFO, IPPROTO_IP); 679 } 680 #endif 681 #ifdef PIPEX 682 if (pipex_enable && inp->inp_pipex) { 683 struct pipex_session *session; 684 int off = iphlen + sizeof(struct udphdr); 685 if ((session = pipex_l2tp_lookup_session(m, off)) != NULL) { 686 if ((m = pipex_l2tp_input(m, off, session, 687 ipsecflowinfo)) == NULL) { 688 m_freem(opts); 689 return; /* the packet is handled by PIPEX */ 690 } 691 } 692 } 693 #endif 694 695 iphlen += sizeof(struct udphdr); 696 m_adj(m, iphlen); 697 if (sbappendaddr(&inp->inp_socket->so_rcv, &srcsa.sa, m, opts) == 0) { 698 udpstat.udps_fullsock++; 699 goto bad; 700 } 701 sorwakeup(inp->inp_socket); 702 return; 703 bad: 704 m_freem(m); 705 m_freem(opts); 706 } 707 708 /* 709 * Notify a udp user of an asynchronous error; 710 * just wake up so that he can collect error status. 711 */ 712 void 713 udp_notify(struct inpcb *inp, int errno) 714 { 715 inp->inp_socket->so_error = errno; 716 sorwakeup(inp->inp_socket); 717 sowwakeup(inp->inp_socket); 718 } 719 720 #ifdef INET6 721 void 722 udp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d) 723 { 724 struct udphdr uh; 725 struct sockaddr_in6 sa6; 726 struct ip6_hdr *ip6; 727 struct mbuf *m; 728 int off; 729 void *cmdarg; 730 struct ip6ctlparam *ip6cp = NULL; 731 struct udp_portonly { 732 u_int16_t uh_sport; 733 u_int16_t uh_dport; 734 } *uhp; 735 void (*notify)(struct inpcb *, int) = udp_notify; 736 737 if (sa == NULL) 738 return; 739 if (sa->sa_family != AF_INET6 || 740 sa->sa_len != sizeof(struct sockaddr_in6)) 741 return; 742 743 if ((unsigned)cmd >= PRC_NCMDS) 744 return; 745 if (PRC_IS_REDIRECT(cmd)) 746 notify = in_rtchange, d = NULL; 747 else if (cmd == PRC_HOSTDEAD) 748 d = NULL; 749 else if (cmd == PRC_MSGSIZE) 750 ; /* special code is present, see below */ 751 else if (inet6ctlerrmap[cmd] == 0) 752 return; 753 754 /* if the parameter is from icmp6, decode it. */ 755 if (d != NULL) { 756 ip6cp = (struct ip6ctlparam *)d; 757 m = ip6cp->ip6c_m; 758 ip6 = ip6cp->ip6c_ip6; 759 off = ip6cp->ip6c_off; 760 cmdarg = ip6cp->ip6c_cmdarg; 761 } else { 762 m = NULL; 763 ip6 = NULL; 764 cmdarg = NULL; 765 /* XXX: translate addresses into internal form */ 766 sa6 = *satosin6(sa); 767 if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL)) { 768 /* should be impossible */ 769 return; 770 } 771 } 772 773 if (ip6cp && ip6cp->ip6c_finaldst) { 774 bzero(&sa6, sizeof(sa6)); 775 sa6.sin6_family = AF_INET6; 776 sa6.sin6_len = sizeof(sa6); 777 sa6.sin6_addr = *ip6cp->ip6c_finaldst; 778 /* XXX: assuming M is valid in this case */ 779 sa6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, 780 ip6cp->ip6c_finaldst); 781 if (in6_embedscope(ip6cp->ip6c_finaldst, &sa6, NULL)) { 782 /* should be impossible */ 783 return; 784 } 785 } else { 786 /* XXX: translate addresses into internal form */ 787 sa6 = *satosin6(sa); 788 if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL)) { 789 /* should be impossible */ 790 return; 791 } 792 } 793 794 if (ip6) { 795 /* 796 * XXX: We assume that when IPV6 is non NULL, 797 * M and OFF are valid. 798 */ 799 struct sockaddr_in6 sa6_src; 800 801 /* check if we can safely examine src and dst ports */ 802 if (m->m_pkthdr.len < off + sizeof(*uhp)) 803 return; 804 805 bzero(&uh, sizeof(uh)); 806 m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh); 807 808 bzero(&sa6_src, sizeof(sa6_src)); 809 sa6_src.sin6_family = AF_INET6; 810 sa6_src.sin6_len = sizeof(sa6_src); 811 sa6_src.sin6_addr = ip6->ip6_src; 812 sa6_src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, 813 &ip6->ip6_src); 814 if (in6_embedscope(&sa6_src.sin6_addr, &sa6_src, NULL)) { 815 /* should be impossible */ 816 return; 817 } 818 819 if (cmd == PRC_MSGSIZE) { 820 int valid = 0; 821 822 /* 823 * Check to see if we have a valid UDP socket 824 * corresponding to the address in the ICMPv6 message 825 * payload. 826 */ 827 if (in6_pcbhashlookup(&udbtable, &sa6.sin6_addr, 828 uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport, 829 rdomain)) 830 valid = 1; 831 #if 0 832 /* 833 * As the use of sendto(2) is fairly popular, 834 * we may want to allow non-connected pcb too. 835 * But it could be too weak against attacks... 836 * We should at least check if the local address (= s) 837 * is really ours. 838 */ 839 else if (in6_pcblookup_listen(&udbtable, 840 &sa6_src.sin6_addr, uh.uh_sport, 0, 841 rdomain)) 842 valid = 1; 843 #endif 844 845 /* 846 * Depending on the value of "valid" and routing table 847 * size (mtudisc_{hi,lo}wat), we will: 848 * - recalculate the new MTU and create the 849 * corresponding routing entry, or 850 * - ignore the MTU change notification. 851 */ 852 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 853 854 /* 855 * regardless of if we called icmp6_mtudisc_update(), 856 * we need to call in6_pcbnotify(), to notify path 857 * MTU change to the userland (2292bis-02), because 858 * some unconnected sockets may share the same 859 * destination and want to know the path MTU. 860 */ 861 } 862 863 (void) in6_pcbnotify(&udbtable, &sa6, uh.uh_dport, 864 &sa6_src, uh.uh_sport, rdomain, cmd, cmdarg, notify); 865 } else { 866 (void) in6_pcbnotify(&udbtable, &sa6, 0, 867 &sa6_any, 0, rdomain, cmd, cmdarg, notify); 868 } 869 } 870 #endif 871 872 void * 873 udp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) 874 { 875 struct ip *ip = v; 876 struct udphdr *uhp; 877 struct in_addr faddr; 878 struct inpcb *inp; 879 void (*notify)(struct inpcb *, int) = udp_notify; 880 int errno; 881 882 if (sa == NULL) 883 return NULL; 884 if (sa->sa_family != AF_INET || 885 sa->sa_len != sizeof(struct sockaddr_in)) 886 return NULL; 887 faddr = satosin(sa)->sin_addr; 888 if (faddr.s_addr == INADDR_ANY) 889 return NULL; 890 891 if ((unsigned)cmd >= PRC_NCMDS) 892 return NULL; 893 errno = inetctlerrmap[cmd]; 894 if (PRC_IS_REDIRECT(cmd)) 895 notify = in_rtchange, ip = 0; 896 else if (cmd == PRC_HOSTDEAD) 897 ip = 0; 898 else if (errno == 0) 899 return NULL; 900 if (ip) { 901 uhp = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); 902 903 #ifdef IPSEC 904 /* PMTU discovery for udpencap */ 905 if (cmd == PRC_MSGSIZE && ip_mtudisc && udpencap_enable && 906 udpencap_port && uhp->uh_sport == htons(udpencap_port)) { 907 udpencap_ctlinput(cmd, sa, rdomain, v); 908 return (NULL); 909 } 910 #endif 911 inp = in_pcbhashlookup(&udbtable, 912 ip->ip_dst, uhp->uh_dport, ip->ip_src, uhp->uh_sport, 913 rdomain); 914 if (inp && inp->inp_socket != NULL) 915 notify(inp, errno); 916 } else 917 in_pcbnotifyall(&udbtable, sa, rdomain, errno, notify); 918 return (NULL); 919 } 920 921 int 922 udp_output(struct inpcb *inp, struct mbuf *m, struct mbuf *addr, 923 struct mbuf *control) 924 { 925 struct sockaddr_in *sin = NULL; 926 struct udpiphdr *ui; 927 u_int32_t ipsecflowinfo = 0; 928 struct sockaddr_in src_sin; 929 int len = m->m_pkthdr.len; 930 struct in_addr *laddr; 931 int error = 0; 932 933 #ifdef DIAGNOSTIC 934 if ((inp->inp_flags & INP_IPV6) != 0) 935 panic("IPv6 inpcb to %s", __func__); 936 #endif 937 938 /* 939 * Compute the packet length of the IP header, and 940 * punt if the length looks bogus. 941 */ 942 if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { 943 error = EMSGSIZE; 944 goto release; 945 } 946 947 memset(&src_sin, 0, sizeof(src_sin)); 948 949 if (control) { 950 u_int clen; 951 struct cmsghdr *cm; 952 caddr_t cmsgs; 953 954 /* 955 * XXX: Currently, we assume all the optional information is 956 * stored in a single mbuf. 957 */ 958 if (control->m_next) { 959 error = EINVAL; 960 goto release; 961 } 962 963 clen = control->m_len; 964 cmsgs = mtod(control, caddr_t); 965 do { 966 if (clen < CMSG_LEN(0)) { 967 error = EINVAL; 968 goto release; 969 } 970 cm = (struct cmsghdr *)cmsgs; 971 if (cm->cmsg_len < CMSG_LEN(0) || 972 CMSG_ALIGN(cm->cmsg_len) > clen) { 973 error = EINVAL; 974 goto release; 975 } 976 #ifdef IPSEC 977 if ((inp->inp_flags & INP_IPSECFLOWINFO) != 0 && 978 cm->cmsg_len == CMSG_LEN(sizeof(ipsecflowinfo)) && 979 cm->cmsg_level == IPPROTO_IP && 980 cm->cmsg_type == IP_IPSECFLOWINFO) { 981 ipsecflowinfo = *(u_int32_t *)CMSG_DATA(cm); 982 } else 983 #endif 984 if (cm->cmsg_len == CMSG_LEN(sizeof(struct in_addr)) && 985 cm->cmsg_level == IPPROTO_IP && 986 cm->cmsg_type == IP_SENDSRCADDR) { 987 memcpy(&src_sin.sin_addr, CMSG_DATA(cm), 988 sizeof(struct in_addr)); 989 src_sin.sin_family = AF_INET; 990 src_sin.sin_len = sizeof(src_sin); 991 /* no check on reuse when sin->sin_port == 0 */ 992 if ((error = in_pcbaddrisavail(inp, &src_sin, 993 0, curproc))) 994 goto release; 995 } 996 clen -= CMSG_ALIGN(cm->cmsg_len); 997 cmsgs += CMSG_ALIGN(cm->cmsg_len); 998 } while (clen); 999 } 1000 1001 if (addr) { 1002 sin = mtod(addr, struct sockaddr_in *); 1003 1004 if (addr->m_len != sizeof(*sin)) { 1005 error = EINVAL; 1006 goto release; 1007 } 1008 if (sin->sin_family != AF_INET) { 1009 error = EAFNOSUPPORT; 1010 goto release; 1011 } 1012 if (sin->sin_port == 0) { 1013 error = EADDRNOTAVAIL; 1014 goto release; 1015 } 1016 1017 if (inp->inp_faddr.s_addr != INADDR_ANY) { 1018 error = EISCONN; 1019 goto release; 1020 } 1021 1022 error = in_pcbselsrc(&laddr, sin, inp); 1023 if (error) 1024 goto release; 1025 1026 if (inp->inp_lport == 0) { 1027 int s = splsoftnet(); 1028 error = in_pcbbind(inp, NULL, curproc); 1029 splx(s); 1030 if (error) 1031 goto release; 1032 } 1033 1034 if (src_sin.sin_len > 0 && 1035 src_sin.sin_addr.s_addr != INADDR_ANY && 1036 src_sin.sin_addr.s_addr != inp->inp_laddr.s_addr) { 1037 src_sin.sin_port = inp->inp_lport; 1038 if (inp->inp_laddr.s_addr != INADDR_ANY && 1039 (error = 1040 in_pcbaddrisavail(inp, &src_sin, 0, curproc))) 1041 goto release; 1042 laddr = &src_sin.sin_addr; 1043 } 1044 } else { 1045 if (inp->inp_faddr.s_addr == INADDR_ANY) { 1046 error = ENOTCONN; 1047 goto release; 1048 } 1049 laddr = &inp->inp_laddr; 1050 } 1051 1052 /* 1053 * Calculate data length and get a mbuf 1054 * for UDP and IP headers. 1055 */ 1056 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); 1057 if (m == NULL) { 1058 error = ENOBUFS; 1059 goto bail; 1060 } 1061 1062 /* 1063 * Fill in mbuf with extended UDP header 1064 * and addresses and length put into network format. 1065 */ 1066 ui = mtod(m, struct udpiphdr *); 1067 bzero(ui->ui_x1, sizeof ui->ui_x1); 1068 ui->ui_pr = IPPROTO_UDP; 1069 ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr)); 1070 ui->ui_src = *laddr; 1071 ui->ui_dst = sin ? sin->sin_addr : inp->inp_faddr; 1072 ui->ui_sport = inp->inp_lport; 1073 ui->ui_dport = sin ? sin->sin_port : inp->inp_fport; 1074 ui->ui_ulen = ui->ui_len; 1075 ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len); 1076 ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; 1077 ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; 1078 if (udpcksum) 1079 m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; 1080 1081 udpstat.udps_opackets++; 1082 1083 /* force routing table */ 1084 m->m_pkthdr.ph_rtableid = inp->inp_rtableid; 1085 1086 #if NPF > 0 1087 if (inp->inp_socket->so_state & SS_ISCONNECTED) 1088 m->m_pkthdr.pf.inp = inp; 1089 #endif 1090 1091 error = ip_output(m, inp->inp_options, &inp->inp_route, 1092 (inp->inp_socket->so_options & SO_BROADCAST), inp->inp_moptions, 1093 inp, ipsecflowinfo); 1094 if (error == EACCES) /* translate pf(4) error for userland */ 1095 error = EHOSTUNREACH; 1096 1097 bail: 1098 m_freem(control); 1099 return (error); 1100 1101 release: 1102 m_freem(m); 1103 goto bail; 1104 } 1105 1106 /*ARGSUSED*/ 1107 int 1108 udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, 1109 struct mbuf *control, struct proc *p) 1110 { 1111 struct inpcb *inp; 1112 int error = 0; 1113 int s; 1114 1115 if (req == PRU_CONTROL) { 1116 #ifdef INET6 1117 if (sotopf(so) == PF_INET6) 1118 return (in6_control(so, (u_long)m, (caddr_t)addr, 1119 (struct ifnet *)control)); 1120 else 1121 #endif /* INET6 */ 1122 return (in_control(so, (u_long)m, (caddr_t)addr, 1123 (struct ifnet *)control)); 1124 } 1125 1126 s = splsoftnet(); 1127 inp = sotoinpcb(so); 1128 if (inp == NULL && req != PRU_ATTACH) { 1129 error = EINVAL; 1130 goto release; 1131 } 1132 1133 /* 1134 * Note: need to block udp_input while changing 1135 * the udp pcb queue and/or pcb addresses. 1136 */ 1137 switch (req) { 1138 1139 case PRU_ATTACH: 1140 if (inp != NULL) { 1141 error = EINVAL; 1142 break; 1143 } 1144 if ((error = soreserve(so, udp_sendspace, udp_recvspace)) || 1145 (error = in_pcballoc(so, &udbtable))) 1146 break; 1147 #ifdef INET6 1148 if (sotoinpcb(so)->inp_flags & INP_IPV6) 1149 sotoinpcb(so)->inp_ipv6.ip6_hlim = ip6_defhlim; 1150 else 1151 #endif /* INET6 */ 1152 sotoinpcb(so)->inp_ip.ip_ttl = ip_defttl; 1153 break; 1154 1155 case PRU_DETACH: 1156 in_pcbdetach(inp); 1157 break; 1158 1159 case PRU_BIND: 1160 error = in_pcbbind(inp, addr, p); 1161 break; 1162 1163 case PRU_LISTEN: 1164 error = EOPNOTSUPP; 1165 break; 1166 1167 case PRU_CONNECT: 1168 #ifdef INET6 1169 if (inp->inp_flags & INP_IPV6) { 1170 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { 1171 error = EISCONN; 1172 break; 1173 } 1174 error = in6_pcbconnect(inp, addr); 1175 } else 1176 #endif /* INET6 */ 1177 { 1178 if (inp->inp_faddr.s_addr != INADDR_ANY) { 1179 error = EISCONN; 1180 break; 1181 } 1182 error = in_pcbconnect(inp, addr); 1183 } 1184 1185 if (error == 0) 1186 soisconnected(so); 1187 break; 1188 1189 case PRU_CONNECT2: 1190 error = EOPNOTSUPP; 1191 break; 1192 1193 case PRU_ACCEPT: 1194 error = EOPNOTSUPP; 1195 break; 1196 1197 case PRU_DISCONNECT: 1198 #ifdef INET6 1199 if (inp->inp_flags & INP_IPV6) { 1200 if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { 1201 error = ENOTCONN; 1202 break; 1203 } 1204 } else 1205 #endif /* INET6 */ 1206 { 1207 if (inp->inp_faddr.s_addr == INADDR_ANY) { 1208 error = ENOTCONN; 1209 break; 1210 } 1211 } 1212 1213 #ifdef INET6 1214 if (inp->inp_flags & INP_IPV6) 1215 inp->inp_laddr6 = in6addr_any; 1216 else 1217 #endif /* INET6 */ 1218 inp->inp_laddr.s_addr = INADDR_ANY; 1219 in_pcbdisconnect(inp); 1220 1221 so->so_state &= ~SS_ISCONNECTED; /* XXX */ 1222 break; 1223 1224 case PRU_SHUTDOWN: 1225 socantsendmore(so); 1226 break; 1227 1228 case PRU_SEND: 1229 #ifdef PIPEX 1230 if (inp->inp_pipex) { 1231 struct pipex_session *session; 1232 1233 if (addr != NULL) 1234 session = 1235 pipex_l2tp_userland_lookup_session(m, 1236 mtod(addr, struct sockaddr *)); 1237 else 1238 #ifdef INET6 1239 if (inp->inp_flags & INP_IPV6) 1240 session = 1241 pipex_l2tp_userland_lookup_session_ipv6( 1242 m, inp->inp_faddr6); 1243 else 1244 #endif 1245 session = 1246 pipex_l2tp_userland_lookup_session_ipv4( 1247 m, inp->inp_faddr); 1248 if (session != NULL) 1249 if ((m = pipex_l2tp_userland_output( 1250 m, session)) == NULL) { 1251 error = ENOMEM; 1252 goto release; 1253 } 1254 } 1255 #endif 1256 1257 #ifdef INET6 1258 if (inp->inp_flags & INP_IPV6) 1259 error = udp6_output(inp, m, addr, control); 1260 else 1261 #endif 1262 error = udp_output(inp, m, addr, control); 1263 splx(s); 1264 return (error); 1265 1266 case PRU_ABORT: 1267 soisdisconnected(so); 1268 in_pcbdetach(inp); 1269 break; 1270 1271 case PRU_SOCKADDR: 1272 #ifdef INET6 1273 if (inp->inp_flags & INP_IPV6) 1274 in6_setsockaddr(inp, addr); 1275 else 1276 #endif /* INET6 */ 1277 in_setsockaddr(inp, addr); 1278 break; 1279 1280 case PRU_PEERADDR: 1281 #ifdef INET6 1282 if (inp->inp_flags & INP_IPV6) 1283 in6_setpeeraddr(inp, addr); 1284 else 1285 #endif /* INET6 */ 1286 in_setpeeraddr(inp, addr); 1287 break; 1288 1289 case PRU_SENSE: 1290 /* 1291 * stat: don't bother with a blocksize. 1292 */ 1293 /* 1294 * Perhaps Path MTU might be returned for a connected 1295 * UDP socket in this case. 1296 */ 1297 splx(s); 1298 return (0); 1299 1300 case PRU_SENDOOB: 1301 case PRU_FASTTIMO: 1302 case PRU_SLOWTIMO: 1303 case PRU_PROTORCV: 1304 case PRU_PROTOSEND: 1305 error = EOPNOTSUPP; 1306 break; 1307 1308 case PRU_RCVD: 1309 case PRU_RCVOOB: 1310 splx(s); 1311 return (EOPNOTSUPP); /* do not free mbuf's */ 1312 1313 default: 1314 panic("udp_usrreq"); 1315 } 1316 1317 release: 1318 splx(s); 1319 m_freem(control); 1320 m_freem(m); 1321 return (error); 1322 } 1323 1324 /* 1325 * Sysctl for udp variables. 1326 */ 1327 int 1328 udp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 1329 size_t newlen) 1330 { 1331 /* All sysctl names at this level are terminal. */ 1332 if (namelen != 1) 1333 return (ENOTDIR); 1334 1335 switch (name[0]) { 1336 case UDPCTL_BADDYNAMIC: 1337 return (sysctl_struct(oldp, oldlenp, newp, newlen, 1338 baddynamicports.udp, sizeof(baddynamicports.udp))); 1339 1340 case UDPCTL_ROOTONLY: 1341 if (newp && securelevel > 0) 1342 return (EPERM); 1343 return (sysctl_struct(oldp, oldlenp, newp, newlen, 1344 rootonlyports.udp, sizeof(rootonlyports.udp))); 1345 1346 case UDPCTL_STATS: 1347 if (newp != NULL) 1348 return (EPERM); 1349 return (sysctl_struct(oldp, oldlenp, newp, newlen, 1350 &udpstat, sizeof(udpstat))); 1351 1352 default: 1353 if (name[0] < UDPCTL_MAXID) 1354 return (sysctl_int_arr(udpctl_vars, name, namelen, 1355 oldp, oldlenp, newp, newlen)); 1356 return (ENOPROTOOPT); 1357 } 1358 /* NOTREACHED */ 1359 } 1360