The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/udp_usrreq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: udp_usrreq.c,v 1.264 2022/11/04 09:00:58 ozaki-r Exp $ */
    2 
    3 /*
    4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the project nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
   34  *      The Regents of the University of California.  All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. Neither the name of the University nor the names of its contributors
   45  *    may be used to endorse or promote products derived from this software
   46  *    without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)udp_usrreq.c        8.6 (Berkeley) 5/23/95
   61  */
   62 
   63 /*
   64  * UDP protocol implementation.
   65  * Per RFC 768, August, 1980.
   66  */
   67 
   68 #include <sys/cdefs.h>
   69 __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.264 2022/11/04 09:00:58 ozaki-r Exp $");
   70 
   71 #ifdef _KERNEL_OPT
   72 #include "opt_inet.h"
   73 #include "opt_ipsec.h"
   74 #include "opt_inet_csum.h"
   75 #include "opt_mbuftrace.h"
   76 #include "opt_net_mpsafe.h"
   77 #endif
   78 
   79 #include <sys/param.h>
   80 #include <sys/mbuf.h>
   81 #include <sys/once.h>
   82 #include <sys/protosw.h>
   83 #include <sys/socket.h>
   84 #include <sys/socketvar.h>
   85 #include <sys/systm.h>
   86 #include <sys/proc.h>
   87 #include <sys/domain.h>
   88 #include <sys/sysctl.h>
   89 
   90 #include <net/if.h>
   91 
   92 #include <netinet/in.h>
   93 #include <netinet/in_systm.h>
   94 #include <netinet/in_var.h>
   95 #include <netinet/ip.h>
   96 #include <netinet/in_pcb.h>
   97 #include <netinet/ip_var.h>
   98 #include <netinet/ip_icmp.h>
   99 #include <netinet/udp.h>
  100 #include <netinet/udp_var.h>
  101 #include <netinet/udp_private.h>
  102 
  103 #ifdef INET6
  104 #include <netinet/ip6.h>
  105 #include <netinet6/ip6_var.h>
  106 #include <netinet6/ip6_private.h>
  107 #include <netinet6/in6_pcb.h>
  108 #include <netinet6/udp6_var.h>
  109 #include <netinet6/udp6_private.h>
  110 #endif
  111 
  112 #ifndef INET6
  113 #include <netinet/ip6.h>
  114 #endif
  115 
  116 #ifdef IPSEC
  117 #include <netipsec/ipsec.h>
  118 #include <netipsec/esp.h>
  119 #endif
  120 
  121 int udpcksum = 1;
  122 int udp_do_loopback_cksum = 0;
  123 
  124 struct inpcbtable udbtable;
  125 
  126 percpu_t *udpstat_percpu;
  127 
  128 #ifdef INET
  129 #ifdef IPSEC
  130 static int udp4_espinudp(struct mbuf **, int);
  131 #endif
  132 static void udp4_sendup(struct mbuf *, int, struct sockaddr *,
  133     struct socket *);
  134 static int udp4_realinput(struct sockaddr_in *, struct sockaddr_in *,
  135     struct mbuf **, int);
  136 static int udp4_input_checksum(struct mbuf *, const struct udphdr *, int, int);
  137 #endif
  138 #ifdef INET
  139 static void udp_notify (struct inpcb *, int);
  140 #endif
  141 
  142 #ifndef UDBHASHSIZE
  143 #define UDBHASHSIZE     128
  144 #endif
  145 int udbhashsize = UDBHASHSIZE;
  146 
  147 /*
  148  * For send - really max datagram size; for receive - 40 1K datagrams.
  149  */
  150 static int udp_sendspace = 9216;
  151 static int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
  152 
  153 #ifdef MBUFTRACE
  154 struct mowner udp_mowner = MOWNER_INIT("udp", "");
  155 struct mowner udp_rx_mowner = MOWNER_INIT("udp", "rx");
  156 struct mowner udp_tx_mowner = MOWNER_INIT("udp", "tx");
  157 #endif
  158 
  159 #ifdef UDP_CSUM_COUNTERS
  160 #include <sys/device.h>
  161 
  162 #if defined(INET)
  163 struct evcnt udp_hwcsum_bad = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  164     NULL, "udp", "hwcsum bad");
  165 struct evcnt udp_hwcsum_ok = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  166     NULL, "udp", "hwcsum ok");
  167 struct evcnt udp_hwcsum_data = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  168     NULL, "udp", "hwcsum data");
  169 struct evcnt udp_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  170     NULL, "udp", "swcsum");
  171 
  172 EVCNT_ATTACH_STATIC(udp_hwcsum_bad);
  173 EVCNT_ATTACH_STATIC(udp_hwcsum_ok);
  174 EVCNT_ATTACH_STATIC(udp_hwcsum_data);
  175 EVCNT_ATTACH_STATIC(udp_swcsum);
  176 #endif /* defined(INET) */
  177 
  178 #define UDP_CSUM_COUNTER_INCR(ev)       (ev)->ev_count++
  179 #else
  180 #define UDP_CSUM_COUNTER_INCR(ev)       /* nothing */
  181 #endif /* UDP_CSUM_COUNTERS */
  182 
  183 static void sysctl_net_inet_udp_setup(struct sysctllog **);
  184 
  185 static int
  186 do_udpinit(void)
  187 {
  188 
  189         inpcb_init(&udbtable, udbhashsize, udbhashsize);
  190         udpstat_percpu = percpu_alloc(sizeof(uint64_t) * UDP_NSTATS);
  191 
  192         MOWNER_ATTACH(&udp_tx_mowner);
  193         MOWNER_ATTACH(&udp_rx_mowner);
  194         MOWNER_ATTACH(&udp_mowner);
  195 
  196         return 0;
  197 }
  198 
  199 void
  200 udp_init_common(void)
  201 {
  202         static ONCE_DECL(doudpinit);
  203 
  204         RUN_ONCE(&doudpinit, do_udpinit);
  205 }
  206 
  207 void
  208 udp_init(void)
  209 {
  210 
  211         sysctl_net_inet_udp_setup(NULL);
  212 
  213         udp_init_common();
  214 }
  215 
  216 /*
  217  * Checksum extended UDP header and data.
  218  */
  219 int
  220 udp_input_checksum(int af, struct mbuf *m, const struct udphdr *uh,
  221     int iphlen, int len)
  222 {
  223 
  224         switch (af) {
  225 #ifdef INET
  226         case AF_INET:
  227                 return udp4_input_checksum(m, uh, iphlen, len);
  228 #endif
  229 #ifdef INET6
  230         case AF_INET6:
  231                 return udp6_input_checksum(m, uh, iphlen, len);
  232 #endif
  233         }
  234 #ifdef DIAGNOSTIC
  235         panic("udp_input_checksum: unknown af %d", af);
  236 #endif
  237         /* NOTREACHED */
  238         return -1;
  239 }
  240 
  241 #ifdef INET
  242 
  243 /*
  244  * Checksum extended UDP header and data.
  245  */
  246 static int
  247 udp4_input_checksum(struct mbuf *m, const struct udphdr *uh,
  248     int iphlen, int len)
  249 {
  250 
  251         /*
  252          * XXX it's better to record and check if this mbuf is
  253          * already checked.
  254          */
  255 
  256         if (uh->uh_sum == 0)
  257                 return 0;
  258 
  259         switch (m->m_pkthdr.csum_flags &
  260             ((m_get_rcvif_NOMPSAFE(m)->if_csum_flags_rx & M_CSUM_UDPv4) |
  261             M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
  262         case M_CSUM_UDPv4|M_CSUM_TCP_UDP_BAD:
  263                 UDP_CSUM_COUNTER_INCR(&udp_hwcsum_bad);
  264                 goto badcsum;
  265 
  266         case M_CSUM_UDPv4|M_CSUM_DATA: {
  267                 u_int32_t hw_csum = m->m_pkthdr.csum_data;
  268 
  269                 UDP_CSUM_COUNTER_INCR(&udp_hwcsum_data);
  270                 if (m->m_pkthdr.csum_flags & M_CSUM_NO_PSEUDOHDR) {
  271                         const struct ip *ip =
  272                             mtod(m, const struct ip *);
  273 
  274                         hw_csum = in_cksum_phdr(ip->ip_src.s_addr,
  275                             ip->ip_dst.s_addr,
  276                             htons(hw_csum + len + IPPROTO_UDP));
  277                 }
  278                 if ((hw_csum ^ 0xffff) != 0)
  279                         goto badcsum;
  280                 break;
  281         }
  282 
  283         case M_CSUM_UDPv4:
  284                 /* Checksum was okay. */
  285                 UDP_CSUM_COUNTER_INCR(&udp_hwcsum_ok);
  286                 break;
  287 
  288         default:
  289                 /*
  290                  * Need to compute it ourselves.  Maybe skip checksum
  291                  * on loopback interfaces.
  292                  */
  293                 if (__predict_true(!(m_get_rcvif_NOMPSAFE(m)->if_flags &
  294                                      IFF_LOOPBACK) ||
  295                                    udp_do_loopback_cksum)) {
  296                         UDP_CSUM_COUNTER_INCR(&udp_swcsum);
  297                         if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0)
  298                                 goto badcsum;
  299                 }
  300                 break;
  301         }
  302 
  303         return 0;
  304 
  305 badcsum:
  306         UDP_STATINC(UDP_STAT_BADSUM);
  307         return -1;
  308 }
  309 
  310 void
  311 udp_input(struct mbuf *m, int off, int proto)
  312 {
  313         struct sockaddr_in src, dst;
  314         struct ip *ip;
  315         struct udphdr *uh;
  316         int iphlen = off;
  317         int len;
  318         int n;
  319         u_int16_t ip_len;
  320 
  321         MCLAIM(m, &udp_rx_mowner);
  322         UDP_STATINC(UDP_STAT_IPACKETS);
  323 
  324         /*
  325          * Get IP and UDP header together in first mbuf.
  326          */
  327         ip = mtod(m, struct ip *);
  328         M_REGION_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
  329         if (uh == NULL) {
  330                 UDP_STATINC(UDP_STAT_HDROPS);
  331                 return;
  332         }
  333 
  334         /*
  335          * Enforce alignment requirements that are violated in
  336          * some cases, see kern/50766 for details.
  337          */
  338         if (ACCESSIBLE_POINTER(uh, struct udphdr) == 0) {
  339                 m = m_copyup(m, iphlen + sizeof(struct udphdr), 0);
  340                 if (m == NULL) {
  341                         UDP_STATINC(UDP_STAT_HDROPS);
  342                         return;
  343                 }
  344                 ip = mtod(m, struct ip *);
  345                 uh = (struct udphdr *)(mtod(m, char *) + iphlen);
  346         }
  347         KASSERT(ACCESSIBLE_POINTER(uh, struct udphdr));
  348 
  349         /* destination port of 0 is illegal, based on RFC768. */
  350         if (uh->uh_dport == 0)
  351                 goto bad;
  352 
  353         /*
  354          * Make mbuf data length reflect UDP length.
  355          * If not enough data to reflect UDP length, drop.
  356          */
  357         ip_len = ntohs(ip->ip_len);
  358         len = ntohs((u_int16_t)uh->uh_ulen);
  359         if (len < sizeof(struct udphdr)) {
  360                 UDP_STATINC(UDP_STAT_BADLEN);
  361                 goto bad;
  362         }
  363         if (ip_len != iphlen + len) {
  364                 if (ip_len < iphlen + len) {
  365                         UDP_STATINC(UDP_STAT_BADLEN);
  366                         goto bad;
  367                 }
  368                 m_adj(m, iphlen + len - ip_len);
  369         }
  370 
  371         /*
  372          * Checksum extended UDP header and data.
  373          */
  374         if (udp4_input_checksum(m, uh, iphlen, len))
  375                 goto badcsum;
  376 
  377         /* construct source and dst sockaddrs. */
  378         sockaddr_in_init(&src, &ip->ip_src, uh->uh_sport);
  379         sockaddr_in_init(&dst, &ip->ip_dst, uh->uh_dport);
  380 
  381         if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) {
  382                 UDP_STATINC(UDP_STAT_HDROPS);
  383                 return;
  384         }
  385         if (m == NULL) {
  386                 /*
  387                  * packet has been processed by ESP stuff -
  388                  * e.g. dropped NAT-T-keep-alive-packet ...
  389                  */
  390                 return;
  391         }
  392 
  393         ip = mtod(m, struct ip *);
  394         M_REGION_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
  395         if (uh == NULL) {
  396                 UDP_STATINC(UDP_STAT_HDROPS);
  397                 return;
  398         }
  399         /* XXX Re-enforce alignment? */
  400 
  401 #ifdef INET6
  402         if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) {
  403                 struct sockaddr_in6 src6, dst6;
  404 
  405                 memset(&src6, 0, sizeof(src6));
  406                 src6.sin6_family = AF_INET6;
  407                 src6.sin6_len = sizeof(struct sockaddr_in6);
  408                 in6_in_2_v4mapin6(&ip->ip_src, &src6.sin6_addr);
  409                 src6.sin6_port = uh->uh_sport;
  410                 memset(&dst6, 0, sizeof(dst6));
  411                 dst6.sin6_family = AF_INET6;
  412                 dst6.sin6_len = sizeof(struct sockaddr_in6);
  413                 in6_in_2_v4mapin6(&ip->ip_dst, &dst6.sin6_addr);
  414                 dst6.sin6_port = uh->uh_dport;
  415 
  416                 n += udp6_realinput(AF_INET, &src6, &dst6, &m, iphlen);
  417         }
  418 #endif
  419 
  420         if (n == 0) {
  421                 if (m->m_flags & (M_BCAST | M_MCAST)) {
  422                         UDP_STATINC(UDP_STAT_NOPORTBCAST);
  423                         goto bad;
  424                 }
  425                 UDP_STATINC(UDP_STAT_NOPORT);
  426                 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
  427                 m = NULL;
  428         }
  429 
  430 bad:
  431         if (m)
  432                 m_freem(m);
  433         return;
  434 
  435 badcsum:
  436         m_freem(m);
  437 }
  438 #endif
  439 
  440 #ifdef INET
  441 static void
  442 udp4_sendup(struct mbuf *m, int off /* offset of data portion */,
  443     struct sockaddr *src, struct socket *so)
  444 {
  445         struct mbuf *opts = NULL;
  446         struct mbuf *n;
  447         struct inpcb *inp;
  448 
  449         KASSERT(so != NULL);
  450         KASSERT(so->so_proto->pr_domain->dom_family == AF_INET);
  451         inp = sotoinpcb(so);
  452         KASSERT(inp != NULL);
  453 
  454 #if defined(IPSEC)
  455         if (ipsec_used && ipsec_in_reject(m, inp)) {
  456                 if ((n = m_copypacket(m, M_DONTWAIT)) != NULL)
  457                         icmp_error(n, ICMP_UNREACH, ICMP_UNREACH_ADMIN_PROHIBIT,
  458                             0, 0);
  459                 return;
  460         }
  461 #endif
  462 
  463         if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) {
  464                 if (inp->inp_flags & INP_CONTROLOPTS ||
  465                     SOOPT_TIMESTAMP(so->so_options)) {
  466                         struct ip *ip = mtod(n, struct ip *);
  467                         ip_savecontrol(inp, &opts, ip, n);
  468                 }
  469 
  470                 m_adj(n, off);
  471                 if (sbappendaddr(&so->so_rcv, src, n, opts) == 0) {
  472                         m_freem(n);
  473                         if (opts)
  474                                 m_freem(opts);
  475                         UDP_STATINC(UDP_STAT_FULLSOCK);
  476                         soroverflow(so);
  477                 } else
  478                         sorwakeup(so);
  479         }
  480 }
  481 #endif
  482 
  483 #ifdef INET
  484 static int
  485 udp4_realinput(struct sockaddr_in *src, struct sockaddr_in *dst,
  486     struct mbuf **mp, int off /* offset of udphdr */)
  487 {
  488         u_int16_t *sport, *dport;
  489         int rcvcnt;
  490         struct in_addr *src4, *dst4;
  491         struct inpcb *inp;
  492         struct mbuf *m = *mp;
  493 
  494         rcvcnt = 0;
  495         off += sizeof(struct udphdr);   /* now, offset of payload */
  496 
  497         if (src->sin_family != AF_INET || dst->sin_family != AF_INET)
  498                 goto bad;
  499 
  500         src4 = &src->sin_addr;
  501         sport = &src->sin_port;
  502         dst4 = &dst->sin_addr;
  503         dport = &dst->sin_port;
  504 
  505         if (IN_MULTICAST(dst4->s_addr) ||
  506             in_broadcast(*dst4, m_get_rcvif_NOMPSAFE(m))) {
  507                 /*
  508                  * Deliver a multicast or broadcast datagram to *all* sockets
  509                  * for which the local and remote addresses and ports match
  510                  * those of the incoming datagram.  This allows more than
  511                  * one process to receive multi/broadcasts on the same port.
  512                  * (This really ought to be done for unicast datagrams as
  513                  * well, but that would cause problems with existing
  514                  * applications that open both address-specific sockets and
  515                  * a wildcard socket listening to the same port -- they would
  516                  * end up receiving duplicates of every unicast datagram.
  517                  * Those applications open the multiple sockets to overcome an
  518                  * inadequacy of the UDP socket interface, but for backwards
  519                  * compatibility we avoid the problem here rather than
  520                  * fixing the interface.  Maybe 4.5BSD will remedy this?)
  521                  */
  522 
  523                 /*
  524                  * KAME note: traditionally we dropped udpiphdr from mbuf here.
  525                  * we need udpiphdr for IPsec processing so we do that later.
  526                  */
  527                 /*
  528                  * Locate pcb(s) for datagram.
  529                  */
  530                 TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) {
  531                         if (inp->inp_af != AF_INET)
  532                                 continue;
  533 
  534                         if (inp->inp_lport != *dport)
  535                                 continue;
  536                         if (!in_nullhost(in4p_laddr(inp))) {
  537                                 if (!in_hosteq(in4p_laddr(inp), *dst4))
  538                                         continue;
  539                         }
  540                         if (!in_nullhost(in4p_faddr(inp))) {
  541                                 if (!in_hosteq(in4p_faddr(inp), *src4) ||
  542                                     inp->inp_fport != *sport)
  543                                         continue;
  544                         }
  545 
  546                         udp4_sendup(m, off, (struct sockaddr *)src,
  547                             inp->inp_socket);
  548                         rcvcnt++;
  549 
  550                         /*
  551                          * Don't look for additional matches if this one does
  552                          * not have either the SO_REUSEPORT or SO_REUSEADDR
  553                          * socket options set.  This heuristic avoids searching
  554                          * through all pcbs in the common case of a non-shared
  555                          * port.  It assumes that an application will never
  556                          * clear these options after setting them.
  557                          */
  558                         if ((inp->inp_socket->so_options &
  559                             (SO_REUSEPORT|SO_REUSEADDR)) == 0)
  560                                 break;
  561                 }
  562         } else {
  563                 /*
  564                  * Locate pcb for datagram.
  565                  */
  566                 inp = inpcb_lookup(&udbtable, *src4, *sport, *dst4,
  567                     *dport, 0);
  568                 if (inp == 0) {
  569                         UDP_STATINC(UDP_STAT_PCBHASHMISS);
  570                         inp = inpcb_lookup_bound(&udbtable, *dst4, *dport);
  571                         if (inp == 0)
  572                                 return rcvcnt;
  573                 }
  574 
  575 #ifdef IPSEC
  576                 /* Handle ESP over UDP */
  577                 if (inp->inp_flags & INP_ESPINUDP) {
  578                         switch (udp4_espinudp(mp, off)) {
  579                         case -1: /* Error, m was freed */
  580                                 rcvcnt = -1;
  581                                 goto bad;
  582 
  583                         case 1: /* ESP over UDP */
  584                                 rcvcnt++;
  585                                 goto bad;
  586 
  587                         case 0: /* plain UDP */
  588                         default: /* Unexpected */
  589                                 /*
  590                                  * Normal UDP processing will take place,
  591                                  * m may have changed.
  592                                  */
  593                                 m = *mp;
  594                                 break;
  595                         }
  596                 }
  597 #endif
  598                 if (inp->inp_overudp_cb != NULL) {
  599                         int ret;
  600                         ret = inp->inp_overudp_cb(mp, off, inp->inp_socket,
  601                             sintosa(src), inp->inp_overudp_arg);
  602                         switch (ret) {
  603                         case -1: /* Error, m was freed */
  604                                 rcvcnt = -1;
  605                                 goto bad;
  606 
  607                         case 1: /* Foo over UDP */
  608                                 KASSERT(*mp == NULL);
  609                                 rcvcnt++;
  610                                 goto bad;
  611 
  612                         case 0: /* plain UDP */
  613                         default: /* Unexpected */
  614                                 /*
  615                                  * Normal UDP processing will take place,
  616                                  * m may have changed.
  617                                  */
  618                                 m = *mp;
  619                                 break;
  620                         }
  621                 }
  622 
  623                 /*
  624                  * Check the minimum TTL for socket.
  625                  */
  626                 if (mtod(m, struct ip *)->ip_ttl < in4p_ip_minttl(inp))
  627                         goto bad;
  628 
  629                 udp4_sendup(m, off, (struct sockaddr *)src, inp->inp_socket);
  630                 rcvcnt++;
  631         }
  632 
  633 bad:
  634         return rcvcnt;
  635 }
  636 #endif
  637 
  638 #ifdef INET
  639 /*
  640  * Notify a udp user of an asynchronous error;
  641  * just wake up so that he can collect error status.
  642  */
  643 static void
  644 udp_notify(struct inpcb *inp, int errno)
  645 {
  646         inp->inp_socket->so_error = errno;
  647         sorwakeup(inp->inp_socket);
  648         sowwakeup(inp->inp_socket);
  649 }
  650 
  651 void *
  652 udp_ctlinput(int cmd, const struct sockaddr *sa, void *v)
  653 {
  654         struct ip *ip = v;
  655         struct udphdr *uh;
  656         void (*notify)(struct inpcb *, int) = udp_notify;
  657         int errno;
  658 
  659         if (sa->sa_family != AF_INET ||
  660             sa->sa_len != sizeof(struct sockaddr_in))
  661                 return NULL;
  662         if ((unsigned)cmd >= PRC_NCMDS)
  663                 return NULL;
  664 
  665         errno = inetctlerrmap[cmd];
  666         if (PRC_IS_REDIRECT(cmd)) {
  667                 notify = inpcb_rtchange;
  668                 ip = NULL;
  669         } else if (cmd == PRC_HOSTDEAD) {
  670                 ip = NULL;
  671         } else if (errno == 0) {
  672                 return NULL;
  673         }
  674 
  675         if (ip) {
  676                 uh = (struct udphdr *)((char *)ip + (ip->ip_hl << 2));
  677                 inpcb_notify(&udbtable, satocsin(sa)->sin_addr, uh->uh_dport,
  678                     ip->ip_src, uh->uh_sport, errno, notify);
  679                 /* XXX mapped address case */
  680         } else {
  681                 inpcb_notifyall(&udbtable, satocsin(sa)->sin_addr, errno,
  682                     notify);
  683         }
  684 
  685         return NULL;
  686 }
  687 
  688 int
  689 udp_ctloutput(int op, struct socket *so, struct sockopt *sopt)
  690 {
  691         int s;
  692         int error = 0;
  693         struct inpcb *inp;
  694         int family;
  695         int optval;
  696 
  697         family = so->so_proto->pr_domain->dom_family;
  698 
  699         s = splsoftnet();
  700         switch (family) {
  701 #ifdef INET
  702         case PF_INET:
  703                 if (sopt->sopt_level != IPPROTO_UDP) {
  704                         error = ip_ctloutput(op, so, sopt);
  705                         goto end;
  706                 }
  707                 break;
  708 #endif
  709 #ifdef INET6
  710         case PF_INET6:
  711                 if (sopt->sopt_level != IPPROTO_UDP) {
  712                         error = ip6_ctloutput(op, so, sopt);
  713                         goto end;
  714                 }
  715                 break;
  716 #endif
  717         default:
  718                 error = EAFNOSUPPORT;
  719                 goto end;
  720         }
  721 
  722 
  723         switch (op) {
  724         case PRCO_SETOPT:
  725                 inp = sotoinpcb(so);
  726 
  727                 switch (sopt->sopt_name) {
  728                 case UDP_ENCAP:
  729                         error = sockopt_getint(sopt, &optval);
  730                         if (error)
  731                                 break;
  732 
  733                         switch(optval) {
  734                         case 0:
  735                                 inp->inp_flags &= ~INP_ESPINUDP;
  736                                 break;
  737 
  738                         case UDP_ENCAP_ESPINUDP:
  739                                 inp->inp_flags |= INP_ESPINUDP;
  740                                 break;
  741 
  742                         default:
  743                                 error = EINVAL;
  744                                 break;
  745                         }
  746                         break;
  747 
  748                 default:
  749                         error = ENOPROTOOPT;
  750                         break;
  751                 }
  752                 break;
  753 
  754         default:
  755                 error = EINVAL;
  756                 break;
  757         }
  758 
  759 end:
  760         splx(s);
  761         return error;
  762 }
  763 
  764 int
  765 udp_output(struct mbuf *m, struct inpcb *inp, struct mbuf *control,
  766     struct lwp *l)
  767 {
  768         struct udpiphdr *ui;
  769         struct route *ro;
  770         struct ip_pktopts pktopts;
  771         kauth_cred_t cred;
  772         int len = m->m_pkthdr.len;
  773         int error, flags = 0;
  774 
  775         MCLAIM(m, &udp_tx_mowner);
  776 
  777         /*
  778          * Calculate data length and get a mbuf
  779          * for UDP and IP headers.
  780          */
  781         M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
  782         if (m == NULL) {
  783                 error = ENOBUFS;
  784                 goto release;
  785         }
  786 
  787         /*
  788          * Compute the packet length of the IP header, and
  789          * punt if the length looks bogus.
  790          */
  791         if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
  792                 error = EMSGSIZE;
  793                 goto release;
  794         }
  795 
  796         if (l == NULL)
  797                 cred = NULL;
  798         else
  799                 cred = l->l_cred;
  800 
  801         /* Setup IP outgoing packet options */
  802         memset(&pktopts, 0, sizeof(pktopts));
  803         error = ip_setpktopts(control, &pktopts, &flags, inp, cred);
  804         if (error != 0)
  805                 goto release;
  806 
  807         if (control != NULL) {
  808                 m_freem(control);
  809                 control = NULL;
  810         }
  811 
  812         /*
  813          * Fill in mbuf with extended UDP header
  814          * and addresses and length put into network format.
  815          */
  816         ui = mtod(m, struct udpiphdr *);
  817         ui->ui_pr = IPPROTO_UDP;
  818         ui->ui_src = pktopts.ippo_laddr.sin_addr;
  819         ui->ui_dst = in4p_faddr(inp);
  820         ui->ui_sport = inp->inp_lport;
  821         ui->ui_dport = inp->inp_fport;
  822         ui->ui_ulen = htons((u_int16_t)len + sizeof(struct udphdr));
  823 
  824         ro = &inp->inp_route;
  825 
  826         /*
  827          * Set up checksum and output datagram.
  828          */
  829         if (udpcksum) {
  830                 /*
  831                  * XXX Cache pseudo-header checksum part for
  832                  * XXX "connected" UDP sockets.
  833                  */
  834                 ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
  835                     ui->ui_dst.s_addr, htons((u_int16_t)len +
  836                     sizeof(struct udphdr) + IPPROTO_UDP));
  837                 m->m_pkthdr.csum_flags = M_CSUM_UDPv4;
  838                 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
  839         } else
  840                 ui->ui_sum = 0;
  841 
  842         ((struct ip *)ui)->ip_len = htons(sizeof(struct udpiphdr) + len);
  843         ((struct ip *)ui)->ip_ttl = in4p_ip(inp).ip_ttl;        /* XXX */
  844         ((struct ip *)ui)->ip_tos = in4p_ip(inp).ip_tos;        /* XXX */
  845         UDP_STATINC(UDP_STAT_OPACKETS);
  846 
  847         flags |= inp->inp_socket->so_options & (SO_DONTROUTE|SO_BROADCAST);
  848         return ip_output(m, inp->inp_options, ro, flags, pktopts.ippo_imo, inp);
  849 
  850  release:
  851         if (control != NULL)
  852                 m_freem(control);
  853         m_freem(m);
  854         return error;
  855 }
  856 
  857 static int
  858 udp_attach(struct socket *so, int proto)
  859 {
  860         struct inpcb *inp;
  861         int error;
  862 
  863         KASSERT(sotoinpcb(so) == NULL);
  864 
  865         /* Assign the lock (must happen even if we will error out). */
  866         sosetlock(so);
  867 
  868 #ifdef MBUFTRACE
  869         so->so_mowner = &udp_mowner;
  870         so->so_rcv.sb_mowner = &udp_rx_mowner;
  871         so->so_snd.sb_mowner = &udp_tx_mowner;
  872 #endif
  873         if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  874                 error = soreserve(so, udp_sendspace, udp_recvspace);
  875                 if (error) {
  876                         return error;
  877                 }
  878         }
  879 
  880         error = inpcb_create(so, &udbtable);
  881         if (error) {
  882                 return error;
  883         }
  884         inp = sotoinpcb(so);
  885         in4p_ip(inp).ip_ttl = ip_defttl;
  886         KASSERT(solocked(so));
  887 
  888         return error;
  889 }
  890 
  891 static void
  892 udp_detach(struct socket *so)
  893 {
  894         struct inpcb *inp;
  895 
  896         KASSERT(solocked(so));
  897         inp = sotoinpcb(so);
  898         KASSERT(inp != NULL);
  899         inpcb_destroy(inp);
  900 }
  901 
  902 static int
  903 udp_accept(struct socket *so, struct sockaddr *nam)
  904 {
  905         KASSERT(solocked(so));
  906 
  907         panic("udp_accept");
  908 
  909         return EOPNOTSUPP;
  910 }
  911 
  912 static int
  913 udp_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
  914 {
  915         struct inpcb *inp = sotoinpcb(so);
  916         struct sockaddr_in *sin = (struct sockaddr_in *)nam;
  917         int error = 0;
  918         int s;
  919 
  920         KASSERT(solocked(so));
  921         KASSERT(inp != NULL);
  922         KASSERT(nam != NULL);
  923 
  924         s = splsoftnet();
  925         error = inpcb_bind(inp, sin, l);
  926         splx(s);
  927 
  928         return error;
  929 }
  930 
  931 static int
  932 udp_listen(struct socket *so, struct lwp *l)
  933 {
  934         KASSERT(solocked(so));
  935 
  936         return EOPNOTSUPP;
  937 }
  938 
  939 static int
  940 udp_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
  941 {
  942         struct inpcb *inp = sotoinpcb(so);
  943         int error = 0;
  944         int s;
  945 
  946         KASSERT(solocked(so));
  947         KASSERT(inp != NULL);
  948         KASSERT(nam != NULL);
  949 
  950         s = splsoftnet();
  951         error = inpcb_connect(inp, (struct sockaddr_in *)nam, l);
  952         if (! error)
  953                 soisconnected(so);
  954         splx(s);
  955         return error;
  956 }
  957 
  958 static int
  959 udp_connect2(struct socket *so, struct socket *so2)
  960 {
  961         KASSERT(solocked(so));
  962 
  963         return EOPNOTSUPP;
  964 }
  965 
  966 static int
  967 udp_disconnect(struct socket *so)
  968 {
  969         struct inpcb *inp = sotoinpcb(so);
  970         int s;
  971 
  972         KASSERT(solocked(so));
  973         KASSERT(inp != NULL);
  974 
  975         s = splsoftnet();
  976         /*soisdisconnected(so);*/
  977         so->so_state &= ~SS_ISCONNECTED;        /* XXX */
  978         inpcb_disconnect(inp);
  979         in4p_laddr(inp) = zeroin_addr;          /* XXX */
  980         inpcb_set_state(inp, INP_BOUND);                /* XXX */
  981         splx(s);
  982 
  983         return 0;
  984 }
  985 
  986 static int
  987 udp_shutdown(struct socket *so)
  988 {
  989         int s;
  990 
  991         KASSERT(solocked(so));
  992 
  993         s = splsoftnet();
  994         socantsendmore(so);
  995         splx(s);
  996 
  997         return 0;
  998 }
  999 
 1000 static int
 1001 udp_abort(struct socket *so)
 1002 {
 1003         KASSERT(solocked(so));
 1004 
 1005         panic("udp_abort");
 1006 
 1007         return EOPNOTSUPP;
 1008 }
 1009 
 1010 static int
 1011 udp_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
 1012 {
 1013         return in_control(so, cmd, nam, ifp);
 1014 }
 1015 
 1016 static int
 1017 udp_stat(struct socket *so, struct stat *ub)
 1018 {
 1019         KASSERT(solocked(so));
 1020 
 1021         /* stat: don't bother with a blocksize. */
 1022         return 0;
 1023 }
 1024 
 1025 static int
 1026 udp_peeraddr(struct socket *so, struct sockaddr *nam)
 1027 {
 1028         int s;
 1029 
 1030         KASSERT(solocked(so));
 1031         KASSERT(sotoinpcb(so) != NULL);
 1032         KASSERT(nam != NULL);
 1033 
 1034         s = splsoftnet();
 1035         inpcb_fetch_peeraddr(sotoinpcb(so), (struct sockaddr_in *)nam);
 1036         splx(s);
 1037 
 1038         return 0;
 1039 }
 1040 
 1041 static int
 1042 udp_sockaddr(struct socket *so, struct sockaddr *nam)
 1043 {
 1044         int s;
 1045 
 1046         KASSERT(solocked(so));
 1047         KASSERT(sotoinpcb(so) != NULL);
 1048         KASSERT(nam != NULL);
 1049 
 1050         s = splsoftnet();
 1051         inpcb_fetch_sockaddr(sotoinpcb(so), (struct sockaddr_in *)nam);
 1052         splx(s);
 1053 
 1054         return 0;
 1055 }
 1056 
 1057 static int
 1058 udp_rcvd(struct socket *so, int flags, struct lwp *l)
 1059 {
 1060         KASSERT(solocked(so));
 1061 
 1062         return EOPNOTSUPP;
 1063 }
 1064 
 1065 static int
 1066 udp_recvoob(struct socket *so, struct mbuf *m, int flags)
 1067 {
 1068         KASSERT(solocked(so));
 1069 
 1070         return EOPNOTSUPP;
 1071 }
 1072 
 1073 int
 1074 udp_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
 1075     struct mbuf *control, struct lwp *l)
 1076 {
 1077         struct inpcb *inp = sotoinpcb(so);
 1078         int error = 0;
 1079         struct in_addr laddr;                   /* XXX */
 1080         int s;
 1081 
 1082         KASSERT(solocked(so));
 1083         KASSERT(inp != NULL);
 1084         KASSERT(m != NULL);
 1085 
 1086         memset(&laddr, 0, sizeof laddr);
 1087 
 1088         s = splsoftnet();
 1089         if (nam) {
 1090                 laddr = in4p_laddr(inp);                /* XXX */
 1091                 if ((so->so_state & SS_ISCONNECTED) != 0) {
 1092                         error = EISCONN;
 1093                         goto die;
 1094                 }
 1095                 error = inpcb_connect(inp, (struct sockaddr_in *)nam, l);
 1096                 if (error)
 1097                         goto die;
 1098         } else {
 1099                 if ((so->so_state & SS_ISCONNECTED) == 0) {
 1100                         error = ENOTCONN;
 1101                         goto die;
 1102                 }
 1103         }
 1104         error = udp_output(m, inp, control, l);
 1105         m = NULL;
 1106         control = NULL;
 1107         if (nam) {
 1108                 inpcb_disconnect(inp);
 1109                 in4p_laddr(inp) = laddr;                /* XXX */
 1110                 inpcb_set_state(inp, INP_BOUND);        /* XXX */
 1111         }
 1112   die:
 1113         if (m != NULL)
 1114                 m_freem(m);
 1115         if (control != NULL)
 1116                 m_freem(control);
 1117 
 1118         splx(s);
 1119         return error;
 1120 }
 1121 
 1122 static int
 1123 udp_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
 1124 {
 1125         KASSERT(solocked(so));
 1126 
 1127         m_freem(m);
 1128         m_freem(control);
 1129 
 1130         return EOPNOTSUPP;
 1131 }
 1132 
 1133 static int
 1134 udp_purgeif(struct socket *so, struct ifnet *ifp)
 1135 {
 1136         int s;
 1137 
 1138         s = splsoftnet();
 1139         mutex_enter(softnet_lock);
 1140         inpcb_purgeif0(&udbtable, ifp);
 1141 #ifdef NET_MPSAFE
 1142         mutex_exit(softnet_lock);
 1143 #endif
 1144         in_purgeif(ifp);
 1145 #ifdef NET_MPSAFE
 1146         mutex_enter(softnet_lock);
 1147 #endif
 1148         inpcb_purgeif(&udbtable, ifp);
 1149         mutex_exit(softnet_lock);
 1150         splx(s);
 1151 
 1152         return 0;
 1153 }
 1154 
 1155 static int
 1156 sysctl_net_inet_udp_stats(SYSCTLFN_ARGS)
 1157 {
 1158 
 1159         return (NETSTAT_SYSCTL(udpstat_percpu, UDP_NSTATS));
 1160 }
 1161 
 1162 /*
 1163  * Sysctl for udp variables.
 1164  */
 1165 static void
 1166 sysctl_net_inet_udp_setup(struct sysctllog **clog)
 1167 {
 1168 
 1169         sysctl_createv(clog, 0, NULL, NULL,
 1170                        CTLFLAG_PERMANENT,
 1171                        CTLTYPE_NODE, "inet", NULL,
 1172                        NULL, 0, NULL, 0,
 1173                        CTL_NET, PF_INET, CTL_EOL);
 1174         sysctl_createv(clog, 0, NULL, NULL,
 1175                        CTLFLAG_PERMANENT,
 1176                        CTLTYPE_NODE, "udp",
 1177                        SYSCTL_DESCR("UDPv4 related settings"),
 1178                        NULL, 0, NULL, 0,
 1179                        CTL_NET, PF_INET, IPPROTO_UDP, CTL_EOL);
 1180 
 1181         sysctl_createv(clog, 0, NULL, NULL,
 1182                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1183                        CTLTYPE_INT, "checksum",
 1184                        SYSCTL_DESCR("Compute UDP checksums"),
 1185                        NULL, 0, &udpcksum, 0,
 1186                        CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_CHECKSUM,
 1187                        CTL_EOL);
 1188         sysctl_createv(clog, 0, NULL, NULL,
 1189                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1190                        CTLTYPE_INT, "sendspace",
 1191                        SYSCTL_DESCR("Default UDP send buffer size"),
 1192                        NULL, 0, &udp_sendspace, 0,
 1193                        CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_SENDSPACE,
 1194                        CTL_EOL);
 1195         sysctl_createv(clog, 0, NULL, NULL,
 1196                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1197                        CTLTYPE_INT, "recvspace",
 1198                        SYSCTL_DESCR("Default UDP receive buffer size"),
 1199                        NULL, 0, &udp_recvspace, 0,
 1200                        CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_RECVSPACE,
 1201                        CTL_EOL);
 1202         sysctl_createv(clog, 0, NULL, NULL,
 1203                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1204                        CTLTYPE_INT, "do_loopback_cksum",
 1205                        SYSCTL_DESCR("Perform UDP checksum on loopback"),
 1206                        NULL, 0, &udp_do_loopback_cksum, 0,
 1207                        CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_LOOPBACKCKSUM,
 1208                        CTL_EOL);
 1209         sysctl_createv(clog, 0, NULL, NULL,
 1210                        CTLFLAG_PERMANENT,
 1211                        CTLTYPE_STRUCT, "pcblist",
 1212                        SYSCTL_DESCR("UDP protocol control block list"),
 1213                        sysctl_inpcblist, 0, &udbtable, 0,
 1214                        CTL_NET, PF_INET, IPPROTO_UDP, CTL_CREATE,
 1215                        CTL_EOL);
 1216         sysctl_createv(clog, 0, NULL, NULL,
 1217                        CTLFLAG_PERMANENT,
 1218                        CTLTYPE_STRUCT, "stats",
 1219                        SYSCTL_DESCR("UDP statistics"),
 1220                        sysctl_net_inet_udp_stats, 0, NULL, 0,
 1221                        CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_STATS,
 1222                        CTL_EOL);
 1223 }
 1224 #endif
 1225 
 1226 void
 1227 udp_statinc(u_int stat)
 1228 {
 1229 
 1230         KASSERT(stat < UDP_NSTATS);
 1231         UDP_STATINC(stat);
 1232 }
 1233 
 1234 #if defined(INET) && defined(IPSEC)
 1235 /*
 1236  * Handle ESP-in-UDP packets (RFC3948).
 1237  *
 1238  * We need to distinguish between ESP packets and IKE packets. We do so by
 1239  * looking at the Non-ESP marker. If IKE, we process the UDP packet as usual.
 1240  * Otherwise, ESP, we invoke IPsec.
 1241  *
 1242  * Returns:
 1243  *     1 if the packet was processed
 1244  *     0 if normal UDP processing should take place
 1245  *    -1 if an error occurred and m was freed
 1246  */
 1247 static int
 1248 udp4_espinudp(struct mbuf **mp, int off)
 1249 {
 1250         const size_t skip = sizeof(struct udphdr);
 1251         size_t len;
 1252         uint8_t *data;
 1253         size_t minlen;
 1254         size_t iphdrlen;
 1255         struct ip *ip;
 1256         struct m_tag *tag;
 1257         struct udphdr *udphdr;
 1258         u_int16_t sport, dport;
 1259         struct mbuf *m = *mp;
 1260         uint32_t *marker;
 1261 
 1262         minlen = off + sizeof(struct esp);
 1263         if (minlen > m->m_pkthdr.len)
 1264                 minlen = m->m_pkthdr.len;
 1265 
 1266         if (m->m_len < minlen) {
 1267                 if ((*mp = m_pullup(m, minlen)) == NULL) {
 1268                         return -1;
 1269                 }
 1270                 m = *mp;
 1271         }
 1272 
 1273         len = m->m_len - off;
 1274         data = mtod(m, uint8_t *) + off;
 1275 
 1276         /* Ignore keepalive packets. */
 1277         if ((len == 1) && (*data == 0xff)) {
 1278                 m_freem(m);
 1279                 *mp = NULL; /* avoid any further processing by caller */
 1280                 return 1;
 1281         }
 1282 
 1283         /* Handle Non-ESP marker (32bit). If zero, then IKE. */
 1284         marker = (uint32_t *)data;
 1285         if (len <= sizeof(uint32_t))
 1286                 return 0;
 1287         if (marker[0] == 0)
 1288                 return 0;
 1289 
 1290         /*
 1291          * Get the UDP ports. They are handled in network order
 1292          * everywhere in the IPSEC_NAT_T code.
 1293          */
 1294         udphdr = (struct udphdr *)((char *)data - skip);
 1295         sport = udphdr->uh_sport;
 1296         dport = udphdr->uh_dport;
 1297 
 1298         /*
 1299          * Remove the UDP header, plus a possible marker. IP header
 1300          * length is iphdrlen.
 1301          *
 1302          * Before:
 1303          *   <--- off --->
 1304          *   +----+------+-----+
 1305          *   | IP |  UDP | ESP |
 1306          *   +----+------+-----+
 1307          *        <-skip->
 1308          * After:
 1309          *          +----+-----+
 1310          *          | IP | ESP |
 1311          *          +----+-----+
 1312          *   <-skip->
 1313          */
 1314         iphdrlen = off - sizeof(struct udphdr);
 1315         memmove(mtod(m, char *) + skip, mtod(m, void *), iphdrlen);
 1316         m_adj(m, skip);
 1317 
 1318         ip = mtod(m, struct ip *);
 1319         ip->ip_len = htons(ntohs(ip->ip_len) - skip);
 1320         ip->ip_p = IPPROTO_ESP;
 1321 
 1322         /*
 1323          * We have modified the packet - it is now ESP, so we should not
 1324          * return to UDP processing.
 1325          *
 1326          * Add a PACKET_TAG_IPSEC_NAT_T_PORTS tag to remember the source
 1327          * UDP port. This is required if we want to select the right SPD
 1328          * for multiple hosts behind same NAT.
 1329          */
 1330         if ((tag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS,
 1331             sizeof(sport) + sizeof(dport), M_DONTWAIT)) == NULL) {
 1332                 m_freem(m);
 1333                 return -1;
 1334         }
 1335         ((u_int16_t *)(tag + 1))[0] = sport;
 1336         ((u_int16_t *)(tag + 1))[1] = dport;
 1337         m_tag_prepend(m, tag);
 1338 
 1339         if (ipsec_used)
 1340                 ipsec4_common_input(m, iphdrlen, IPPROTO_ESP);
 1341         else
 1342                 m_freem(m);
 1343 
 1344         /* We handled it, it shouldn't be handled by UDP */
 1345         *mp = NULL; /* avoid free by caller ... */
 1346         return 1;
 1347 }
 1348 #endif
 1349 
 1350 PR_WRAP_USRREQS(udp)
 1351 #define udp_attach      udp_attach_wrapper
 1352 #define udp_detach      udp_detach_wrapper
 1353 #define udp_accept      udp_accept_wrapper
 1354 #define udp_bind        udp_bind_wrapper
 1355 #define udp_listen      udp_listen_wrapper
 1356 #define udp_connect     udp_connect_wrapper
 1357 #define udp_connect2    udp_connect2_wrapper
 1358 #define udp_disconnect  udp_disconnect_wrapper
 1359 #define udp_shutdown    udp_shutdown_wrapper
 1360 #define udp_abort       udp_abort_wrapper
 1361 #define udp_ioctl       udp_ioctl_wrapper
 1362 #define udp_stat        udp_stat_wrapper
 1363 #define udp_peeraddr    udp_peeraddr_wrapper
 1364 #define udp_sockaddr    udp_sockaddr_wrapper
 1365 #define udp_rcvd        udp_rcvd_wrapper
 1366 #define udp_recvoob     udp_recvoob_wrapper
 1367 #define udp_send        udp_send_wrapper
 1368 #define udp_sendoob     udp_sendoob_wrapper
 1369 #define udp_purgeif     udp_purgeif_wrapper
 1370 
 1371 const struct pr_usrreqs udp_usrreqs = {
 1372         .pr_attach      = udp_attach,
 1373         .pr_detach      = udp_detach,
 1374         .pr_accept      = udp_accept,
 1375         .pr_bind        = udp_bind,
 1376         .pr_listen      = udp_listen,
 1377         .pr_connect     = udp_connect,
 1378         .pr_connect2    = udp_connect2,
 1379         .pr_disconnect  = udp_disconnect,
 1380         .pr_shutdown    = udp_shutdown,
 1381         .pr_abort       = udp_abort,
 1382         .pr_ioctl       = udp_ioctl,
 1383         .pr_stat        = udp_stat,
 1384         .pr_peeraddr    = udp_peeraddr,
 1385         .pr_sockaddr    = udp_sockaddr,
 1386         .pr_rcvd        = udp_rcvd,
 1387         .pr_recvoob     = udp_recvoob,
 1388         .pr_send        = udp_send,
 1389         .pr_sendoob     = udp_sendoob,
 1390         .pr_purgeif     = udp_purgeif,
 1391 };

Cache object: c61afb0ef56c5f4fc31e2c9a9783a3ac


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.