root/netinet/udp_usrreq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. udp_init
  2. udp6_input
  3. udp_input
  4. udp_notify
  5. udp6_ctlinput
  6. udp_ctlinput
  7. udp_output
  8. udp6_usrreq
  9. udp_usrreq
  10. udp_detach
  11. udp_sysctl

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

/* [<][>][^][v][top][bottom][index][help] */