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/netinet6/udp6_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 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    5  * Copyright (c) 2010-2011 Juniper Networks, Inc.
    6  * Copyright (c) 2014 Kevin Lo
    7  * All rights reserved.
    8  *
    9  * Portions of this software were developed by Robert N. M. Watson under
   10  * contract to Juniper Networks, Inc.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the project nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      $KAME: udp6_usrreq.c,v 1.27 2001/05/21 05:45:10 jinmei Exp $
   37  *      $KAME: udp6_output.c,v 1.31 2001/05/21 16:39:15 jinmei Exp $
   38  */
   39 
   40 /*-
   41  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
   42  *      The Regents of the University of California.
   43  * All rights reserved.
   44  *
   45  * Redistribution and use in source and binary forms, with or without
   46  * modification, are permitted provided that the following conditions
   47  * are met:
   48  * 1. Redistributions of source code must retain the above copyright
   49  *    notice, this list of conditions and the following disclaimer.
   50  * 2. Redistributions in binary form must reproduce the above copyright
   51  *    notice, this list of conditions and the following disclaimer in the
   52  *    documentation and/or other materials provided with the distribution.
   53  * 3. Neither the name of the University nor the names of its contributors
   54  *    may be used to endorse or promote products derived from this software
   55  *    without specific prior written permission.
   56  *
   57  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   58  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   59  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   60  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   61  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   62  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   63  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   64  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   65  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   66  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   67  * SUCH DAMAGE.
   68  *
   69  *      @(#)udp_usrreq.c        8.6 (Berkeley) 5/23/95
   70  */
   71 
   72 #include <sys/cdefs.h>
   73 __FBSDID("$FreeBSD$");
   74 
   75 #include "opt_inet.h"
   76 #include "opt_inet6.h"
   77 #include "opt_ipsec.h"
   78 #include "opt_route.h"
   79 #include "opt_rss.h"
   80 
   81 #include <sys/param.h>
   82 #include <sys/jail.h>
   83 #include <sys/kernel.h>
   84 #include <sys/lock.h>
   85 #include <sys/mbuf.h>
   86 #include <sys/priv.h>
   87 #include <sys/proc.h>
   88 #include <sys/protosw.h>
   89 #include <sys/sdt.h>
   90 #include <sys/signalvar.h>
   91 #include <sys/socket.h>
   92 #include <sys/socketvar.h>
   93 #include <sys/sx.h>
   94 #include <sys/sysctl.h>
   95 #include <sys/syslog.h>
   96 #include <sys/systm.h>
   97 
   98 #include <net/if.h>
   99 #include <net/if_var.h>
  100 #include <net/if_types.h>
  101 #include <net/route.h>
  102 #include <net/rss_config.h>
  103 
  104 #include <netinet/in.h>
  105 #include <netinet/in_kdtrace.h>
  106 #include <netinet/in_pcb.h>
  107 #include <netinet/in_systm.h>
  108 #include <netinet/in_var.h>
  109 #include <netinet/ip.h>
  110 #include <netinet/ip6.h>
  111 #include <netinet/icmp6.h>
  112 #include <netinet/ip_var.h>
  113 #include <netinet/udp.h>
  114 #include <netinet/udp_var.h>
  115 #include <netinet/udplite.h>
  116 
  117 #include <netinet6/ip6_var.h>
  118 #include <netinet6/in6_fib.h>
  119 #include <netinet6/in6_pcb.h>
  120 #include <netinet6/in6_rss.h>
  121 #include <netinet6/udp6_var.h>
  122 #include <netinet6/scope6_var.h>
  123 
  124 #include <netipsec/ipsec_support.h>
  125 
  126 #include <security/mac/mac_framework.h>
  127 
  128 VNET_DEFINE(int, zero_checksum_port) = 0;
  129 #define V_zero_checksum_port    VNET(zero_checksum_port)
  130 SYSCTL_INT(_net_inet6_udp6, OID_AUTO, rfc6935_port, CTLFLAG_VNET | CTLFLAG_RW,
  131     &VNET_NAME(zero_checksum_port), 0,
  132     "Zero UDP checksum allowed for traffic to/from this port.");
  133 
  134 /*
  135  * UDP protocol implementation.
  136  * Per RFC 768, August, 1980.
  137  */
  138 
  139 static void             udp6_detach(struct socket *so);
  140 
  141 static int
  142 udp6_append(struct inpcb *inp, struct mbuf *n, int off,
  143     struct sockaddr_in6 *fromsa)
  144 {
  145         struct socket *so;
  146         struct mbuf *opts = NULL, *tmp_opts;
  147         struct udpcb *up;
  148         bool filtered;
  149 
  150         INP_LOCK_ASSERT(inp);
  151 
  152         /*
  153          * Engage the tunneling protocol.
  154          */
  155         up = intoudpcb(inp);
  156         if (up->u_tun_func != NULL) {
  157                 in_pcbref(inp);
  158                 INP_RUNLOCK(inp);
  159                 filtered = (*up->u_tun_func)(n, off, inp,
  160                     (struct sockaddr *)&fromsa[0], up->u_tun_ctx);
  161                 INP_RLOCK(inp);
  162                 if (filtered)
  163                         return (in_pcbrele_rlocked(inp));
  164         }
  165 #if defined(IPSEC) || defined(IPSEC_SUPPORT)
  166         /* Check AH/ESP integrity. */
  167         if (IPSEC_ENABLED(ipv6)) {
  168                 if (IPSEC_CHECK_POLICY(ipv6, n, inp) != 0) {
  169                         m_freem(n);
  170                         return (0);
  171                 }
  172         }
  173 #endif /* IPSEC */
  174 #ifdef MAC
  175         if (mac_inpcb_check_deliver(inp, n) != 0) {
  176                 m_freem(n);
  177                 return (0);
  178         }
  179 #endif
  180         opts = NULL;
  181         if (inp->inp_flags & INP_CONTROLOPTS ||
  182             inp->inp_socket->so_options & SO_TIMESTAMP)
  183                 ip6_savecontrol(inp, n, &opts);
  184         if ((inp->inp_vflag & INP_IPV6) && (inp->inp_flags2 & INP_ORIGDSTADDR)) {
  185                 tmp_opts = sbcreatecontrol(&fromsa[1],
  186                     sizeof(struct sockaddr_in6), IPV6_ORIGDSTADDR,
  187                     IPPROTO_IPV6, M_NOWAIT);
  188                 if (tmp_opts) {
  189                         if (opts) {
  190                                 tmp_opts->m_next = opts;
  191                                 opts = tmp_opts;
  192                         } else
  193                                 opts = tmp_opts;
  194                 }
  195         }
  196         m_adj(n, off + sizeof(struct udphdr));
  197 
  198         so = inp->inp_socket;
  199         SOCKBUF_LOCK(&so->so_rcv);
  200         if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)&fromsa[0], n,
  201             opts) == 0) {
  202                 soroverflow_locked(so);
  203                 m_freem(n);
  204                 if (opts)
  205                         m_freem(opts);
  206                 UDPSTAT_INC(udps_fullsock);
  207         } else
  208                 sorwakeup_locked(so);
  209         return (0);
  210 }
  211 
  212 struct udp6_multi_match_ctx {
  213         struct ip6_hdr *ip6;
  214         struct udphdr *uh;
  215 };
  216 
  217 static bool
  218 udp6_multi_match(const struct inpcb *inp, void *v)
  219 {
  220         struct udp6_multi_match_ctx *ctx = v;
  221 
  222         if ((inp->inp_vflag & INP_IPV6) == 0)
  223                 return(false);
  224         if (inp->inp_lport != ctx->uh->uh_dport)
  225                 return(false);
  226         if (inp->inp_fport != 0 && inp->inp_fport != ctx->uh->uh_sport)
  227                 return(false);
  228         if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
  229             !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &ctx->ip6->ip6_dst))
  230                 return (false);
  231         if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
  232             (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &ctx->ip6->ip6_src) ||
  233             inp->inp_fport != ctx->uh->uh_sport))
  234                 return (false);
  235 
  236         return (true);
  237 }
  238 
  239 static int
  240 udp6_multi_input(struct mbuf *m, int off, int proto,
  241     struct sockaddr_in6 *fromsa)
  242 {
  243         struct udp6_multi_match_ctx ctx;
  244         struct inpcb_iterator inpi = INP_ITERATOR(udp_get_inpcbinfo(proto),
  245             INPLOOKUP_RLOCKPCB, udp6_multi_match, &ctx);
  246         struct inpcb *inp;
  247         struct ip6_moptions *imo;
  248         struct mbuf *n;
  249         int appends = 0;
  250 
  251         /*
  252          * In the event that laddr should be set to the link-local
  253          * address (this happens in RIPng), the multicast address
  254          * specified in the received packet will not match laddr.  To
  255          * handle this situation, matching is relaxed if the
  256          * receiving interface is the same as one specified in the
  257          * socket and if the destination multicast address matches
  258          * one of the multicast groups specified in the socket.
  259          */
  260 
  261         /*
  262          * KAME note: traditionally we dropped udpiphdr from mbuf
  263          * here.  We need udphdr for IPsec processing so we do that
  264          * later.
  265          */
  266         ctx.ip6 = mtod(m, struct ip6_hdr *);
  267         ctx.uh = (struct udphdr *)((char *)ctx.ip6 + off);
  268         while ((inp = inp_next(&inpi)) != NULL) {
  269                 INP_RLOCK_ASSERT(inp);
  270                 /*
  271                  * XXXRW: Because we weren't holding either the inpcb
  272                  * or the hash lock when we checked for a match
  273                  * before, we should probably recheck now that the
  274                  * inpcb lock is (supposed to be) held.
  275                  */
  276                 /*
  277                  * Handle socket delivery policy for any-source
  278                  * and source-specific multicast. [RFC3678]
  279                  */
  280                 if ((imo = inp->in6p_moptions) != NULL) {
  281                         struct sockaddr_in6      mcaddr;
  282                         int                      blocked;
  283 
  284                         bzero(&mcaddr, sizeof(struct sockaddr_in6));
  285                         mcaddr.sin6_len = sizeof(struct sockaddr_in6);
  286                         mcaddr.sin6_family = AF_INET6;
  287                         mcaddr.sin6_addr = ctx.ip6->ip6_dst;
  288 
  289                         blocked = im6o_mc_filter(imo, m->m_pkthdr.rcvif,
  290                                 (struct sockaddr *)&mcaddr,
  291                                 (struct sockaddr *)&fromsa[0]);
  292                         if (blocked != MCAST_PASS) {
  293                                 if (blocked == MCAST_NOTGMEMBER)
  294                                         IP6STAT_INC(ip6s_notmember);
  295                                 if (blocked == MCAST_NOTSMEMBER ||
  296                                     blocked == MCAST_MUTED)
  297                                         UDPSTAT_INC(udps_filtermcast);
  298                                 continue;
  299                         }
  300                 }
  301                 if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != NULL) {
  302                         if (proto == IPPROTO_UDPLITE)
  303                                 UDPLITE_PROBE(receive, NULL, inp, ctx.ip6,
  304                                     inp, ctx.uh);
  305                         else
  306                                 UDP_PROBE(receive, NULL, inp, ctx.ip6, inp,
  307                                     ctx.uh);
  308                         if (udp6_append(inp, n, off, fromsa)) {
  309                                 break;
  310                         } else
  311                                 appends++;
  312                 }
  313                 /*
  314                  * Don't look for additional matches if this one does
  315                  * not have either the SO_REUSEPORT or SO_REUSEADDR
  316                  * socket options set.  This heuristic avoids
  317                  * searching through all pcbs in the common case of a
  318                  * non-shared port.  It assumes that an application
  319                  * will never clear these options after setting them.
  320                  */
  321                 if ((inp->inp_socket->so_options &
  322                      (SO_REUSEPORT|SO_REUSEPORT_LB|SO_REUSEADDR)) == 0) {
  323                         INP_RUNLOCK(inp);
  324                         break;
  325                 }
  326         }
  327         m_freem(m);
  328 
  329         if (appends == 0) {
  330                 /*
  331                  * No matching pcb found; discard datagram.  (No need
  332                  * to send an ICMP Port Unreachable for a broadcast
  333                  * or multicast datgram.)
  334                  */
  335                 UDPSTAT_INC(udps_noport);
  336                 UDPSTAT_INC(udps_noportmcast);
  337         }
  338 
  339         return (IPPROTO_DONE);
  340 }
  341 
  342 int
  343 udp6_input(struct mbuf **mp, int *offp, int proto)
  344 {
  345         struct mbuf *m = *mp;
  346         struct ip6_hdr *ip6;
  347         struct udphdr *uh;
  348         struct inpcb *inp;
  349         struct inpcbinfo *pcbinfo;
  350         struct udpcb *up;
  351         int off = *offp;
  352         int cscov_partial;
  353         int plen, ulen;
  354         struct sockaddr_in6 fromsa[2];
  355         struct m_tag *fwd_tag;
  356         uint16_t uh_sum;
  357         uint8_t nxt;
  358 
  359         NET_EPOCH_ASSERT();
  360 
  361         if (m->m_len < off + sizeof(struct udphdr)) {
  362                 m = m_pullup(m, off + sizeof(struct udphdr));
  363                 if (m == NULL) {
  364                         IP6STAT_INC(ip6s_exthdrtoolong);
  365                         *mp = NULL;
  366                         return (IPPROTO_DONE);
  367                 }
  368         }
  369         ip6 = mtod(m, struct ip6_hdr *);
  370         uh = (struct udphdr *)((caddr_t)ip6 + off);
  371 
  372         UDPSTAT_INC(udps_ipackets);
  373 
  374         /*
  375          * Destination port of 0 is illegal, based on RFC768.
  376          */
  377         if (uh->uh_dport == 0)
  378                 goto badunlocked;
  379 
  380         plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6);
  381         ulen = ntohs((u_short)uh->uh_ulen);
  382 
  383         nxt = proto;
  384         cscov_partial = (nxt == IPPROTO_UDPLITE) ? 1 : 0;
  385         if (nxt == IPPROTO_UDPLITE) {
  386                 /* Zero means checksum over the complete packet. */
  387                 if (ulen == 0)
  388                         ulen = plen;
  389                 if (ulen == plen)
  390                         cscov_partial = 0;
  391                 if ((ulen < sizeof(struct udphdr)) || (ulen > plen)) {
  392                         /* XXX: What is the right UDPLite MIB counter? */
  393                         goto badunlocked;
  394                 }
  395                 if (uh->uh_sum == 0) {
  396                         /* XXX: What is the right UDPLite MIB counter? */
  397                         goto badunlocked;
  398                 }
  399         } else {
  400                 if ((ulen < sizeof(struct udphdr)) || (plen != ulen)) {
  401                         UDPSTAT_INC(udps_badlen);
  402                         goto badunlocked;
  403                 }
  404                 if (uh->uh_sum == 0) {
  405                         UDPSTAT_INC(udps_nosum);
  406                         /*
  407                          * dport 0 was rejected earlier so this is OK even if
  408                          * zero_checksum_port is 0 (which is its default value).
  409                          */
  410                         if (ntohs(uh->uh_dport) == V_zero_checksum_port)
  411                                 goto skip_checksum;
  412                         else
  413                                 goto badunlocked;
  414                 }
  415         }
  416 
  417         if ((m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) &&
  418             !cscov_partial) {
  419                 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
  420                         uh_sum = m->m_pkthdr.csum_data;
  421                 else
  422                         uh_sum = in6_cksum_pseudo(ip6, ulen, nxt,
  423                             m->m_pkthdr.csum_data);
  424                 uh_sum ^= 0xffff;
  425         } else
  426                 uh_sum = in6_cksum_partial(m, nxt, off, plen, ulen);
  427 
  428         if (uh_sum != 0) {
  429                 UDPSTAT_INC(udps_badsum);
  430                 goto badunlocked;
  431         }
  432 
  433 skip_checksum:
  434         /*
  435          * Construct sockaddr format source address.
  436          */
  437         init_sin6(&fromsa[0], m, 0);
  438         fromsa[0].sin6_port = uh->uh_sport;
  439         init_sin6(&fromsa[1], m, 1);
  440         fromsa[1].sin6_port = uh->uh_dport;
  441 
  442         pcbinfo = udp_get_inpcbinfo(nxt);
  443         if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))  {
  444                 *mp = NULL;
  445                 return (udp6_multi_input(m, off, proto, fromsa));
  446         }
  447 
  448         /*
  449          * Locate pcb for datagram.
  450          */
  451 
  452         /*
  453          * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
  454          */
  455         if ((m->m_flags & M_IP6_NEXTHOP) &&
  456             (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
  457                 struct sockaddr_in6 *next_hop6;
  458 
  459                 next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1);
  460 
  461                 /*
  462                  * Transparently forwarded. Pretend to be the destination.
  463                  * Already got one like this?
  464                  */
  465                 inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_src,
  466                     uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
  467                     INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m);
  468                 if (!inp) {
  469                         /*
  470                          * It's new.  Try to find the ambushing socket.
  471                          * Because we've rewritten the destination address,
  472                          * any hardware-generated hash is ignored.
  473                          */
  474                         inp = in6_pcblookup(pcbinfo, &ip6->ip6_src,
  475                             uh->uh_sport, &next_hop6->sin6_addr,
  476                             next_hop6->sin6_port ? htons(next_hop6->sin6_port) :
  477                             uh->uh_dport, INPLOOKUP_WILDCARD |
  478                             INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif);
  479                 }
  480                 /* Remove the tag from the packet. We don't need it anymore. */
  481                 m_tag_delete(m, fwd_tag);
  482                 m->m_flags &= ~M_IP6_NEXTHOP;
  483         } else
  484                 inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_src,
  485                     uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
  486                     INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
  487                     m->m_pkthdr.rcvif, m);
  488         if (inp == NULL) {
  489                 if (V_udp_log_in_vain) {
  490                         char ip6bufs[INET6_ADDRSTRLEN];
  491                         char ip6bufd[INET6_ADDRSTRLEN];
  492 
  493                         log(LOG_INFO,
  494                             "Connection attempt to UDP [%s]:%d from [%s]:%d\n",
  495                             ip6_sprintf(ip6bufd, &ip6->ip6_dst),
  496                             ntohs(uh->uh_dport),
  497                             ip6_sprintf(ip6bufs, &ip6->ip6_src),
  498                             ntohs(uh->uh_sport));
  499                 }
  500                 if (nxt == IPPROTO_UDPLITE)
  501                         UDPLITE_PROBE(receive, NULL, NULL, ip6, NULL, uh);
  502                 else
  503                         UDP_PROBE(receive, NULL, NULL, ip6, NULL, uh);
  504                 UDPSTAT_INC(udps_noport);
  505                 if (m->m_flags & M_MCAST) {
  506                         printf("UDP6: M_MCAST is set in a unicast packet.\n");
  507                         UDPSTAT_INC(udps_noportmcast);
  508                         goto badunlocked;
  509                 }
  510                 if (V_udp_blackhole && (V_udp_blackhole_local ||
  511                     !in6_localaddr(&ip6->ip6_src)))
  512                         goto badunlocked;
  513                 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
  514                 *mp = NULL;
  515                 return (IPPROTO_DONE);
  516         }
  517         INP_RLOCK_ASSERT(inp);
  518         up = intoudpcb(inp);
  519         if (cscov_partial) {
  520                 if (up->u_rxcslen == 0 || up->u_rxcslen > ulen) {
  521                         INP_RUNLOCK(inp);
  522                         m_freem(m);
  523                         *mp = NULL;
  524                         return (IPPROTO_DONE);
  525                 }
  526         }
  527         if (nxt == IPPROTO_UDPLITE)
  528                 UDPLITE_PROBE(receive, NULL, inp, ip6, inp, uh);
  529         else
  530                 UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
  531         if (udp6_append(inp, m, off, fromsa) == 0)
  532                 INP_RUNLOCK(inp);
  533         *mp = NULL;
  534         return (IPPROTO_DONE);
  535 
  536 badunlocked:
  537         m_freem(m);
  538         *mp = NULL;
  539         return (IPPROTO_DONE);
  540 }
  541 
  542 static void
  543 udp6_common_ctlinput(struct ip6ctlparam *ip6cp, struct inpcbinfo *pcbinfo)
  544 {
  545         struct udphdr uh;
  546         struct ip6_hdr *ip6;
  547         struct mbuf *m;
  548         struct inpcb *inp;
  549         int errno, off = 0;
  550         struct udp_portonly {
  551                 u_int16_t uh_sport;
  552                 u_int16_t uh_dport;
  553         } *uhp;
  554 
  555         if ((errno = icmp6_errmap(ip6cp->ip6c_icmp6)) == 0)
  556                 return;
  557 
  558         m = ip6cp->ip6c_m;
  559         ip6 = ip6cp->ip6c_ip6;
  560         off = ip6cp->ip6c_off;
  561 
  562         /* Check if we can safely examine src and dst ports. */
  563         if (m->m_pkthdr.len < off + sizeof(*uhp))
  564                 return;
  565 
  566         bzero(&uh, sizeof(uh));
  567         m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
  568 
  569         /* Check to see if its tunneled */
  570         inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_dst, uh.uh_dport,
  571             &ip6->ip6_src, uh.uh_sport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
  572             m->m_pkthdr.rcvif, m);
  573         if (inp != NULL) {
  574                 struct udpcb *up;
  575                 udp_tun_icmp_t *func;
  576 
  577                 up = intoudpcb(inp);
  578                 func = up->u_icmp_func;
  579                 INP_RUNLOCK(inp);
  580                 if (func != NULL)
  581                         func(ip6cp);
  582         }
  583         in6_pcbnotify(pcbinfo, ip6cp->ip6c_finaldst, uh.uh_dport,
  584             ip6cp->ip6c_src, uh.uh_sport, errno, ip6cp->ip6c_cmdarg,
  585             udp_notify);
  586 }
  587 
  588 static void
  589 udp6_ctlinput(struct ip6ctlparam *ctl)
  590 {
  591 
  592         return (udp6_common_ctlinput(ctl, &V_udbinfo));
  593 }
  594 
  595 static void
  596 udplite6_ctlinput(struct ip6ctlparam *ctl)
  597 {
  598 
  599         return (udp6_common_ctlinput(ctl, &V_ulitecbinfo));
  600 }
  601 
  602 static int
  603 udp6_getcred(SYSCTL_HANDLER_ARGS)
  604 {
  605         struct xucred xuc;
  606         struct sockaddr_in6 addrs[2];
  607         struct epoch_tracker et;
  608         struct inpcb *inp;
  609         int error;
  610 
  611         error = priv_check(req->td, PRIV_NETINET_GETCRED);
  612         if (error)
  613                 return (error);
  614 
  615         if (req->newlen != sizeof(addrs))
  616                 return (EINVAL);
  617         if (req->oldlen != sizeof(struct xucred))
  618                 return (EINVAL);
  619         error = SYSCTL_IN(req, addrs, sizeof(addrs));
  620         if (error)
  621                 return (error);
  622         if ((error = sa6_embedscope(&addrs[0], V_ip6_use_defzone)) != 0 ||
  623             (error = sa6_embedscope(&addrs[1], V_ip6_use_defzone)) != 0) {
  624                 return (error);
  625         }
  626         NET_EPOCH_ENTER(et);
  627         inp = in6_pcblookup(&V_udbinfo, &addrs[1].sin6_addr,
  628             addrs[1].sin6_port, &addrs[0].sin6_addr, addrs[0].sin6_port,
  629             INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL);
  630         NET_EPOCH_EXIT(et);
  631         if (inp != NULL) {
  632                 INP_RLOCK_ASSERT(inp);
  633                 if (inp->inp_socket == NULL)
  634                         error = ENOENT;
  635                 if (error == 0)
  636                         error = cr_canseesocket(req->td->td_ucred,
  637                             inp->inp_socket);
  638                 if (error == 0)
  639                         cru2x(inp->inp_cred, &xuc);
  640                 INP_RUNLOCK(inp);
  641         } else
  642                 error = ENOENT;
  643         if (error == 0)
  644                 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
  645         return (error);
  646 }
  647 
  648 SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred,
  649     CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_MPSAFE,
  650     0, 0, udp6_getcred, "S,xucred",
  651     "Get the xucred of a UDP6 connection");
  652 
  653 static int
  654 udp6_send(struct socket *so, int flags_arg, struct mbuf *m,
  655     struct sockaddr *addr6, struct mbuf *control, struct thread *td)
  656 {
  657         struct inpcb *inp;
  658         struct ip6_hdr *ip6;
  659         struct udphdr *udp6;
  660         struct in6_addr *laddr, *faddr, in6a;
  661         struct ip6_pktopts *optp, opt;
  662         struct sockaddr_in6 *sin6, tmp;
  663         struct epoch_tracker et;
  664         int cscov_partial, error, flags, hlen, scope_ambiguous;
  665         u_int32_t ulen, plen;
  666         uint16_t cscov;
  667         u_short fport;
  668         uint8_t nxt;
  669 
  670         if (addr6) {
  671                 error = 0;
  672                 if (addr6->sa_family != AF_INET6)
  673                         error = EAFNOSUPPORT;
  674                 else if (addr6->sa_len != sizeof(struct sockaddr_in6))
  675                         error = EINVAL;
  676                 if (__predict_false(error != 0)) {
  677                         m_freem(control);
  678                         m_freem(m);
  679                         return (error);
  680                 }
  681         }
  682 
  683         sin6 = (struct sockaddr_in6 *)addr6;
  684 
  685         /*
  686          * In contrast to IPv4 we do not validate the max. packet length
  687          * here due to IPv6 Jumbograms (RFC2675).
  688          */
  689 
  690         scope_ambiguous = 0;
  691         if (sin6) {
  692                 /* Protect *addr6 from overwrites. */
  693                 tmp = *sin6;
  694                 sin6 = &tmp;
  695 
  696                 /*
  697                  * Application should provide a proper zone ID or the use of
  698                  * default zone IDs should be enabled.  Unfortunately, some
  699                  * applications do not behave as it should, so we need a
  700                  * workaround.  Even if an appropriate ID is not determined,
  701                  * we'll see if we can determine the outgoing interface.  If we
  702                  * can, determine the zone ID based on the interface below.
  703                  */
  704                 if (sin6->sin6_scope_id == 0 && !V_ip6_use_defzone)
  705                         scope_ambiguous = 1;
  706                 if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) {
  707                         if (control)
  708                                 m_freem(control);
  709                         m_freem(m);
  710                         return (error);
  711                 }
  712         }
  713 
  714         inp = sotoinpcb(so);
  715         KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
  716         /*
  717          * In the following cases we want a write lock on the inp for either
  718          * local operations or for possible route cache updates in the IPv6
  719          * output path:
  720          * - on connected sockets (sin6 is NULL) for route cache updates,
  721          * - when we are not bound to an address and source port (it is
  722          *   in6_pcbsetport() which will require the write lock).
  723          *
  724          * We check the inp fields before actually locking the inp, so
  725          * here exists a race, and we may WLOCK the inp and end with already
  726          * bound one by other thread. This is fine.
  727          */
  728         if (sin6 == NULL || (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
  729             inp->inp_lport == 0))
  730                 INP_WLOCK(inp);
  731         else
  732                 INP_RLOCK(inp);
  733 
  734         nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ?
  735             IPPROTO_UDP : IPPROTO_UDPLITE;
  736 
  737 #ifdef INET
  738         if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
  739                 int hasv4addr;
  740 
  741                 if (sin6 == NULL)
  742                         hasv4addr = (inp->inp_vflag & INP_IPV4);
  743                 else
  744                         hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)
  745                             ? 1 : 0;
  746                 if (hasv4addr) {
  747                         /*
  748                          * XXXRW: We release UDP-layer locks before calling
  749                          * udp_send() in order to avoid recursion.  However,
  750                          * this does mean there is a short window where inp's
  751                          * fields are unstable.  Could this lead to a
  752                          * potential race in which the factors causing us to
  753                          * select the UDPv4 output routine are invalidated?
  754                          */
  755                         INP_UNLOCK(inp);
  756                         if (sin6)
  757                                 in6_sin6_2_sin_in_sock((struct sockaddr *)sin6);
  758                         /* addr will just be freed in sendit(). */
  759                         return (udp_send(so, flags_arg | PRUS_IPV6, m,
  760                             (struct sockaddr *)sin6, control, td));
  761                 }
  762         } else
  763 #endif
  764         if (sin6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
  765                 /*
  766                  * Given this is either an IPv6-only socket or no INET is
  767                  * supported we will fail the send if the given destination
  768                  * address is a v4mapped address.
  769                  *
  770                  * XXXGL: do we leak m and control?
  771                  */
  772                 INP_UNLOCK(inp);
  773                 return (EINVAL);
  774         }
  775 
  776         NET_EPOCH_ENTER(et);
  777         if (control) {
  778                 if ((error = ip6_setpktopts(control, &opt,
  779                     inp->in6p_outputopts, td->td_ucred, nxt)) != 0) {
  780                         goto release;
  781                 }
  782                 optp = &opt;
  783         } else
  784                 optp = inp->in6p_outputopts;
  785 
  786         if (sin6) {
  787                 /*
  788                  * Since we saw no essential reason for calling in_pcbconnect,
  789                  * we get rid of such kind of logic, and call in6_selectsrc
  790                  * and in6_pcbsetport in order to fill in the local address
  791                  * and the local port.
  792                  */
  793                 if (sin6->sin6_port == 0) {
  794                         error = EADDRNOTAVAIL;
  795                         goto release;
  796                 }
  797 
  798                 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
  799                         /* how about ::ffff:0.0.0.0 case? */
  800                         error = EISCONN;
  801                         goto release;
  802                 }
  803 
  804                 /*
  805                  * Given we handle the v4mapped case in the INET block above
  806                  * assert here that it must not happen anymore.
  807                  */
  808                 KASSERT(!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr),
  809                     ("%s: sin6(%p)->sin6_addr is v4mapped which we "
  810                     "should have handled.", __func__, sin6));
  811 
  812                 /* This only requires read-locking. */
  813                 error = in6_selectsrc_socket(sin6, optp, inp,
  814                     td->td_ucred, scope_ambiguous, &in6a, NULL);
  815                 if (error)
  816                         goto release;
  817                 laddr = &in6a;
  818 
  819                 if (inp->inp_lport == 0) {
  820                         struct inpcbinfo *pcbinfo;
  821 
  822                         INP_WLOCK_ASSERT(inp);
  823 
  824                         pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
  825                         INP_HASH_WLOCK(pcbinfo);
  826                         error = in6_pcbsetport(laddr, inp, td->td_ucred);
  827                         INP_HASH_WUNLOCK(pcbinfo);
  828                         if (error != 0) {
  829                                 /* Undo an address bind that may have occurred. */
  830                                 inp->in6p_laddr = in6addr_any;
  831                                 goto release;
  832                         }
  833                 }
  834                 faddr = &sin6->sin6_addr;
  835                 fport = sin6->sin6_port; /* allow 0 port */
  836 
  837         } else {
  838                 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
  839                         error = ENOTCONN;
  840                         goto release;
  841                 }
  842                 laddr = &inp->in6p_laddr;
  843                 faddr = &inp->in6p_faddr;
  844                 fport = inp->inp_fport;
  845         }
  846 
  847         ulen = m->m_pkthdr.len;
  848         plen = sizeof(struct udphdr) + ulen;
  849         hlen = sizeof(struct ip6_hdr);
  850 
  851         /*
  852          * Calculate data length and get a mbuf
  853          * for UDP and IP6 headers.
  854          */
  855         M_PREPEND(m, hlen + sizeof(struct udphdr), M_NOWAIT);
  856         if (m == NULL) {
  857                 error = ENOBUFS;
  858                 goto release;
  859         }
  860 
  861         /*
  862          * Stuff checksum and output datagram.
  863          */
  864         cscov = cscov_partial = 0;
  865         udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen);
  866         udp6->uh_sport = inp->inp_lport; /* lport is always set in the PCB */
  867         udp6->uh_dport = fport;
  868         if (nxt == IPPROTO_UDPLITE) {
  869                 struct udpcb *up;
  870 
  871                 up = intoudpcb(inp);
  872                 cscov = up->u_txcslen;
  873                 if (cscov >= plen)
  874                         cscov = 0;
  875                 udp6->uh_ulen = htons(cscov);
  876                 /*
  877                  * For UDP-Lite, checksum coverage length of zero means
  878                  * the entire UDPLite packet is covered by the checksum.
  879                  */
  880                 cscov_partial = (cscov == 0) ? 0 : 1;
  881         } else if (plen <= 0xffff)
  882                 udp6->uh_ulen = htons((u_short)plen);
  883         else
  884                 udp6->uh_ulen = 0;
  885         udp6->uh_sum = 0;
  886 
  887         ip6 = mtod(m, struct ip6_hdr *);
  888         ip6->ip6_flow   = inp->inp_flow & IPV6_FLOWINFO_MASK;
  889         ip6->ip6_vfc    &= ~IPV6_VERSION_MASK;
  890         ip6->ip6_vfc    |= IPV6_VERSION;
  891         ip6->ip6_plen   = htons((u_short)plen);
  892         ip6->ip6_nxt    = nxt;
  893         ip6->ip6_hlim   = in6_selecthlim(inp, NULL);
  894         ip6->ip6_src    = *laddr;
  895         ip6->ip6_dst    = *faddr;
  896 
  897 #ifdef MAC
  898         mac_inpcb_create_mbuf(inp, m);
  899 #endif
  900 
  901         if (cscov_partial) {
  902                 if ((udp6->uh_sum = in6_cksum_partial(m, nxt,
  903                     sizeof(struct ip6_hdr), plen, cscov)) == 0)
  904                         udp6->uh_sum = 0xffff;
  905         } else {
  906                 udp6->uh_sum = in6_cksum_pseudo(ip6, plen, nxt, 0);
  907                 m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
  908                 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
  909         }
  910 
  911         flags = 0;
  912 #if defined(ROUTE_MPATH) || defined(RSS)
  913         if (CALC_FLOWID_OUTBOUND_SENDTO) {
  914                 uint32_t hash_type, hash_val;
  915                 uint8_t pr;
  916 
  917                 pr = inp->inp_socket->so_proto->pr_protocol;
  918 
  919                 hash_val = fib6_calc_packet_hash(laddr, faddr,
  920                     inp->inp_lport, fport, pr, &hash_type);
  921                 m->m_pkthdr.flowid = hash_val;
  922                 M_HASHTYPE_SET(m, hash_type);
  923         }
  924         /* do not use inp flowid */
  925         flags |= IP_NODEFAULTFLOWID;
  926 #endif
  927 
  928         UDPSTAT_INC(udps_opackets);
  929         if (nxt == IPPROTO_UDPLITE)
  930                 UDPLITE_PROBE(send, NULL, inp, ip6, inp, udp6);
  931         else
  932                 UDP_PROBE(send, NULL, inp, ip6, inp, udp6);
  933         error = ip6_output(m, optp,
  934             INP_WLOCKED(inp) ? &inp->inp_route6 : NULL, flags,
  935             inp->in6p_moptions, NULL, inp);
  936         INP_UNLOCK(inp);
  937         NET_EPOCH_EXIT(et);
  938 
  939         if (control) {
  940                 ip6_clearpktopts(&opt, -1);
  941                 m_freem(control);
  942         }
  943         return (error);
  944 
  945 release:
  946         INP_UNLOCK(inp);
  947         NET_EPOCH_EXIT(et);
  948         if (control) {
  949                 ip6_clearpktopts(&opt, -1);
  950                 m_freem(control);
  951         }
  952         m_freem(m);
  953 
  954         return (error);
  955 }
  956 
  957 static void
  958 udp6_abort(struct socket *so)
  959 {
  960         struct inpcb *inp;
  961         struct inpcbinfo *pcbinfo;
  962 
  963         pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
  964         inp = sotoinpcb(so);
  965         KASSERT(inp != NULL, ("udp6_abort: inp == NULL"));
  966 
  967         INP_WLOCK(inp);
  968 #ifdef INET
  969         if (inp->inp_vflag & INP_IPV4) {
  970                 INP_WUNLOCK(inp);
  971                 udp_abort(so);
  972                 return;
  973         }
  974 #endif
  975 
  976         if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
  977                 INP_HASH_WLOCK(pcbinfo);
  978                 in6_pcbdisconnect(inp);
  979                 inp->in6p_laddr = in6addr_any;
  980                 INP_HASH_WUNLOCK(pcbinfo);
  981                 soisdisconnected(so);
  982         }
  983         INP_WUNLOCK(inp);
  984 }
  985 
  986 static int
  987 udp6_attach(struct socket *so, int proto, struct thread *td)
  988 {
  989         struct inpcbinfo *pcbinfo;
  990         struct inpcb *inp;
  991         struct udpcb *up;
  992         int error;
  993 
  994         pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
  995         inp = sotoinpcb(so);
  996         KASSERT(inp == NULL, ("udp6_attach: inp != NULL"));
  997 
  998         if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  999                 error = soreserve(so, udp_sendspace, udp_recvspace);
 1000                 if (error)
 1001                         return (error);
 1002         }
 1003         error = in_pcballoc(so, pcbinfo);
 1004         if (error)
 1005                 return (error);
 1006         inp = (struct inpcb *)so->so_pcb;
 1007         inp->in6p_cksum = -1;   /* just to be sure */
 1008         /*
 1009          * XXX: ugly!!
 1010          * IPv4 TTL initialization is necessary for an IPv6 socket as well,
 1011          * because the socket may be bound to an IPv6 wildcard address,
 1012          * which may match an IPv4-mapped IPv6 address.
 1013          */
 1014         inp->inp_ip_ttl = V_ip_defttl;
 1015         up = intoudpcb(inp);
 1016         bzero(&up->u_start_zero, u_zero_size);
 1017         INP_WUNLOCK(inp);
 1018         return (0);
 1019 }
 1020 
 1021 static int
 1022 udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
 1023 {
 1024         struct inpcb *inp;
 1025         struct inpcbinfo *pcbinfo;
 1026         int error;
 1027         u_char vflagsav;
 1028 
 1029         pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
 1030         inp = sotoinpcb(so);
 1031         KASSERT(inp != NULL, ("udp6_bind: inp == NULL"));
 1032 
 1033         if (nam->sa_family != AF_INET6)
 1034                 return (EAFNOSUPPORT);
 1035         if (nam->sa_len != sizeof(struct sockaddr_in6))
 1036                 return (EINVAL);
 1037 
 1038         INP_WLOCK(inp);
 1039         INP_HASH_WLOCK(pcbinfo);
 1040         vflagsav = inp->inp_vflag;
 1041         inp->inp_vflag &= ~INP_IPV4;
 1042         inp->inp_vflag |= INP_IPV6;
 1043         if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
 1044                 struct sockaddr_in6 *sin6_p;
 1045 
 1046                 sin6_p = (struct sockaddr_in6 *)nam;
 1047 
 1048                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr))
 1049                         inp->inp_vflag |= INP_IPV4;
 1050 #ifdef INET
 1051                 else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
 1052                         struct sockaddr_in sin;
 1053 
 1054                         in6_sin6_2_sin(&sin, sin6_p);
 1055                         inp->inp_vflag |= INP_IPV4;
 1056                         inp->inp_vflag &= ~INP_IPV6;
 1057                         error = in_pcbbind(inp, (struct sockaddr *)&sin,
 1058                             td->td_ucred);
 1059                         goto out;
 1060                 }
 1061 #endif
 1062         }
 1063 
 1064         error = in6_pcbbind(inp, nam, td->td_ucred);
 1065 #ifdef INET
 1066 out:
 1067 #endif
 1068         if (error != 0)
 1069                 inp->inp_vflag = vflagsav;
 1070         INP_HASH_WUNLOCK(pcbinfo);
 1071         INP_WUNLOCK(inp);
 1072         return (error);
 1073 }
 1074 
 1075 static void
 1076 udp6_close(struct socket *so)
 1077 {
 1078         struct inpcb *inp;
 1079         struct inpcbinfo *pcbinfo;
 1080 
 1081         pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
 1082         inp = sotoinpcb(so);
 1083         KASSERT(inp != NULL, ("udp6_close: inp == NULL"));
 1084 
 1085         INP_WLOCK(inp);
 1086 #ifdef INET
 1087         if (inp->inp_vflag & INP_IPV4) {
 1088                 INP_WUNLOCK(inp);
 1089                 (void)udp_disconnect(so);
 1090                 return;
 1091         }
 1092 #endif
 1093         if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
 1094                 INP_HASH_WLOCK(pcbinfo);
 1095                 in6_pcbdisconnect(inp);
 1096                 inp->in6p_laddr = in6addr_any;
 1097                 INP_HASH_WUNLOCK(pcbinfo);
 1098                 soisdisconnected(so);
 1099         }
 1100         INP_WUNLOCK(inp);
 1101 }
 1102 
 1103 static int
 1104 udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
 1105 {
 1106 #ifdef INET
 1107         struct epoch_tracker et;
 1108 #endif
 1109         struct inpcb *inp;
 1110         struct inpcbinfo *pcbinfo;
 1111         struct sockaddr_in6 *sin6;
 1112         int error;
 1113         u_char vflagsav;
 1114 
 1115         pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
 1116         inp = sotoinpcb(so);
 1117         KASSERT(inp != NULL, ("udp6_connect: inp == NULL"));
 1118 
 1119         sin6 = (struct sockaddr_in6 *)nam;
 1120         if (sin6->sin6_family != AF_INET6)
 1121                 return (EAFNOSUPPORT);
 1122         if (sin6->sin6_len != sizeof(*sin6))
 1123                 return (EINVAL);
 1124 
 1125         /*
 1126          * XXXRW: Need to clarify locking of v4/v6 flags.
 1127          */
 1128         INP_WLOCK(inp);
 1129 #ifdef INET
 1130         if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
 1131                 struct sockaddr_in sin;
 1132 
 1133                 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) {
 1134                         error = EINVAL;
 1135                         goto out;
 1136                 }
 1137                 if ((inp->inp_vflag & INP_IPV4) == 0) {
 1138                         error = EAFNOSUPPORT;
 1139                         goto out;
 1140                 }
 1141                 if (inp->inp_faddr.s_addr != INADDR_ANY) {
 1142                         error = EISCONN;
 1143                         goto out;
 1144                 }
 1145                 in6_sin6_2_sin(&sin, sin6);
 1146                 error = prison_remote_ip4(td->td_ucred, &sin.sin_addr);
 1147                 if (error != 0)
 1148                         goto out;
 1149                 vflagsav = inp->inp_vflag;
 1150                 inp->inp_vflag |= INP_IPV4;
 1151                 inp->inp_vflag &= ~INP_IPV6;
 1152                 NET_EPOCH_ENTER(et);
 1153                 INP_HASH_WLOCK(pcbinfo);
 1154                 error = in_pcbconnect(inp, (struct sockaddr *)&sin,
 1155                     td->td_ucred, true);
 1156                 INP_HASH_WUNLOCK(pcbinfo);
 1157                 NET_EPOCH_EXIT(et);
 1158                 /*
 1159                  * If connect succeeds, mark socket as connected. If
 1160                  * connect fails and socket is unbound, reset inp_vflag
 1161                  * field.
 1162                  */
 1163                 if (error == 0)
 1164                         soisconnected(so);
 1165                 else if (inp->inp_laddr.s_addr == INADDR_ANY &&
 1166                     inp->inp_lport == 0)
 1167                         inp->inp_vflag = vflagsav;
 1168                 goto out;
 1169         } else {
 1170                 if ((inp->inp_vflag & INP_IPV6) == 0) {
 1171                         error = EAFNOSUPPORT;
 1172                         goto out;
 1173                 }
 1174         }
 1175 #endif
 1176         if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
 1177                 error = EISCONN;
 1178                 goto out;
 1179         }
 1180         error = prison_remote_ip6(td->td_ucred, &sin6->sin6_addr);
 1181         if (error != 0)
 1182                 goto out;
 1183         vflagsav = inp->inp_vflag;
 1184         inp->inp_vflag &= ~INP_IPV4;
 1185         inp->inp_vflag |= INP_IPV6;
 1186         INP_HASH_WLOCK(pcbinfo);
 1187         error = in6_pcbconnect(inp, nam, td->td_ucred);
 1188         INP_HASH_WUNLOCK(pcbinfo);
 1189         /*
 1190          * If connect succeeds, mark socket as connected. If
 1191          * connect fails and socket is unbound, reset inp_vflag
 1192          * field.
 1193          */
 1194         if (error == 0)
 1195                 soisconnected(so);
 1196         else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
 1197             inp->inp_lport == 0)
 1198                 inp->inp_vflag = vflagsav;
 1199 out:
 1200         INP_WUNLOCK(inp);
 1201         return (error);
 1202 }
 1203 
 1204 static void
 1205 udp6_detach(struct socket *so)
 1206 {
 1207         struct inpcb *inp;
 1208 
 1209         inp = sotoinpcb(so);
 1210         KASSERT(inp != NULL, ("udp6_detach: inp == NULL"));
 1211 
 1212         INP_WLOCK(inp);
 1213         in_pcbdetach(inp);
 1214         in_pcbfree(inp);
 1215 }
 1216 
 1217 static int
 1218 udp6_disconnect(struct socket *so)
 1219 {
 1220         struct inpcb *inp;
 1221         struct inpcbinfo *pcbinfo;
 1222 
 1223         pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
 1224         inp = sotoinpcb(so);
 1225         KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL"));
 1226 
 1227         INP_WLOCK(inp);
 1228 #ifdef INET
 1229         if (inp->inp_vflag & INP_IPV4) {
 1230                 INP_WUNLOCK(inp);
 1231                 (void)udp_disconnect(so);
 1232                 return (0);
 1233         }
 1234 #endif
 1235 
 1236         if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
 1237                 INP_WUNLOCK(inp);
 1238                 return (ENOTCONN);
 1239         }
 1240 
 1241         INP_HASH_WLOCK(pcbinfo);
 1242         in6_pcbdisconnect(inp);
 1243         inp->in6p_laddr = in6addr_any;
 1244         INP_HASH_WUNLOCK(pcbinfo);
 1245         SOCK_LOCK(so);
 1246         so->so_state &= ~SS_ISCONNECTED;                /* XXX */
 1247         SOCK_UNLOCK(so);
 1248         INP_WUNLOCK(inp);
 1249         return (0);
 1250 }
 1251 
 1252 #define UDP6_PROTOSW                                                    \
 1253         .pr_type =              SOCK_DGRAM,                             \
 1254         .pr_flags =             PR_ATOMIC|PR_ADDR|PR_CAPATTACH,         \
 1255         .pr_ctloutput =         ip6_ctloutput,                          \
 1256         .pr_abort =             udp6_abort,                             \
 1257         .pr_attach =            udp6_attach,                            \
 1258         .pr_bind =              udp6_bind,                              \
 1259         .pr_connect =           udp6_connect,                           \
 1260         .pr_control =           in6_control,                            \
 1261         .pr_detach =            udp6_detach,                            \
 1262         .pr_disconnect =        udp6_disconnect,                        \
 1263         .pr_peeraddr =          in6_mapped_peeraddr,                    \
 1264         .pr_send =              udp6_send,                              \
 1265         .pr_shutdown =          udp_shutdown,                           \
 1266         .pr_sockaddr =          in6_mapped_sockaddr,                    \
 1267         .pr_soreceive =         soreceive_dgram,                        \
 1268         .pr_sosend =            sosend_dgram,                           \
 1269         .pr_sosetlabel =        in_pcbsosetlabel,                       \
 1270         .pr_close =             udp6_close
 1271 
 1272 struct protosw udp6_protosw = {
 1273         .pr_protocol =          IPPROTO_UDP,
 1274         UDP6_PROTOSW
 1275 };
 1276 
 1277 struct protosw udplite6_protosw = {
 1278         .pr_protocol =          IPPROTO_UDPLITE,
 1279         UDP6_PROTOSW
 1280 };
 1281 
 1282 static void
 1283 udp6_init(void *arg __unused)
 1284 {
 1285 
 1286         IP6PROTO_REGISTER(IPPROTO_UDP, udp6_input, udp6_ctlinput);
 1287         IP6PROTO_REGISTER(IPPROTO_UDPLITE, udp6_input, udplite6_ctlinput);
 1288 }
 1289 SYSINIT(udp6_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, udp6_init, NULL);

Cache object: a1a7320aa1ff70cae243431884aadf8f


[ 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.