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.116.2.4 2004/05/28 07:24:17 tron 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 #include <sys/cdefs.h>
   64 __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.116.2.4 2004/05/28 07:24:17 tron Exp $");
   65 
   66 #include "opt_inet.h"
   67 #include "opt_ipsec.h"
   68 #include "opt_inet_csum.h"
   69 #include "opt_ipkdb.h"
   70 #include "opt_mbuftrace.h"
   71 
   72 #include <sys/param.h>
   73 #include <sys/malloc.h>
   74 #include <sys/mbuf.h>
   75 #include <sys/protosw.h>
   76 #include <sys/socket.h>
   77 #include <sys/socketvar.h>
   78 #include <sys/errno.h>
   79 #include <sys/stat.h>
   80 #include <sys/systm.h>
   81 #include <sys/proc.h>
   82 #include <sys/domain.h>
   83 #include <sys/sysctl.h>
   84 
   85 #include <net/if.h>
   86 #include <net/route.h>
   87 
   88 #include <netinet/in.h>
   89 #include <netinet/in_systm.h>
   90 #include <netinet/in_var.h>
   91 #include <netinet/ip.h>
   92 #include <netinet/in_pcb.h>
   93 #include <netinet/ip_var.h>
   94 #include <netinet/ip_icmp.h>
   95 #include <netinet/udp.h>
   96 #include <netinet/udp_var.h>
   97 
   98 #ifdef INET6
   99 #include <netinet/ip6.h>
  100 #include <netinet/icmp6.h>
  101 #include <netinet6/ip6_var.h>
  102 #include <netinet6/in6_pcb.h>
  103 #include <netinet6/udp6_var.h>
  104 #endif
  105 
  106 #ifndef INET6
  107 /* always need ip6.h for IP6_EXTHDR_GET */
  108 #include <netinet/ip6.h>
  109 #endif
  110 
  111 #include "faith.h"
  112 #if defined(NFAITH) && NFAITH > 0
  113 #include <net/if_faith.h>
  114 #endif
  115 
  116 #include <machine/stdarg.h>
  117 
  118 #ifdef FAST_IPSEC
  119 #include <netipsec/ipsec.h>
  120 #include <netipsec/ipsec_var.h>                 /* XXX ipsecstat namespace */
  121 #ifdef INET6
  122 #include <netipsec/ipsec6.h>
  123 #endif
  124 #endif  /* FAST_IPSEC*/
  125 
  126 #ifdef IPSEC
  127 #include <netinet6/ipsec.h>
  128 #include <netkey/key.h>
  129 #endif /*IPSEC*/
  130 
  131 #ifdef IPKDB
  132 #include <ipkdb/ipkdb.h>
  133 #endif
  134 
  135 /*
  136  * UDP protocol implementation.
  137  * Per RFC 768, August, 1980.
  138  */
  139 #ifndef COMPAT_42
  140 int     udpcksum = 1;
  141 #else
  142 int     udpcksum = 0;           /* XXX */
  143 #endif
  144 
  145 struct  inpcbtable udbtable;
  146 struct  udpstat udpstat;
  147 
  148 #ifdef INET
  149 static void udp4_sendup __P((struct mbuf *, int, struct sockaddr *,
  150         struct socket *));
  151 static int udp4_realinput __P((struct sockaddr_in *, struct sockaddr_in *,
  152         struct mbuf *, int));
  153 #endif
  154 #ifdef INET6
  155 static void udp6_sendup __P((struct mbuf *, int, struct sockaddr *,
  156         struct socket *));
  157 static int udp6_realinput __P((int, struct sockaddr_in6 *,
  158         struct sockaddr_in6 *, struct mbuf *, int));
  159 #endif
  160 #ifdef INET
  161 static  void udp_notify __P((struct inpcb *, int));
  162 #endif
  163 
  164 #ifndef UDBHASHSIZE
  165 #define UDBHASHSIZE     128
  166 #endif
  167 int     udbhashsize = UDBHASHSIZE;
  168 
  169 #ifdef MBUFTRACE
  170 struct mowner udp_mowner = { "udp" };
  171 struct mowner udp_rx_mowner = { "udp", "rx" };
  172 struct mowner udp_tx_mowner = { "udp", "tx" };
  173 #endif
  174 
  175 #ifdef UDP_CSUM_COUNTERS
  176 #include <sys/device.h>
  177 
  178 struct evcnt udp_hwcsum_bad = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  179     NULL, "udp", "hwcsum bad");
  180 struct evcnt udp_hwcsum_ok = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  181     NULL, "udp", "hwcsum ok");
  182 struct evcnt udp_hwcsum_data = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  183     NULL, "udp", "hwcsum data");
  184 struct evcnt udp_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  185     NULL, "udp", "swcsum");
  186 
  187 #define UDP_CSUM_COUNTER_INCR(ev)       (ev)->ev_count++
  188 
  189 #else
  190 
  191 #define UDP_CSUM_COUNTER_INCR(ev)       /* nothing */
  192 
  193 #endif /* UDP_CSUM_COUNTERS */
  194 
  195 void
  196 udp_init()
  197 {
  198 
  199         in_pcbinit(&udbtable, udbhashsize, udbhashsize);
  200 
  201 #ifdef UDP_CSUM_COUNTERS
  202         evcnt_attach_static(&udp_hwcsum_bad);
  203         evcnt_attach_static(&udp_hwcsum_ok);
  204         evcnt_attach_static(&udp_hwcsum_data);
  205         evcnt_attach_static(&udp_swcsum);
  206 #endif /* UDP_CSUM_COUNTERS */
  207 
  208         MOWNER_ATTACH(&udp_tx_mowner);
  209         MOWNER_ATTACH(&udp_rx_mowner);
  210         MOWNER_ATTACH(&udp_mowner);
  211 }
  212 
  213 #ifdef INET
  214 void
  215 #if __STDC__
  216 udp_input(struct mbuf *m, ...)
  217 #else
  218 udp_input(m, va_alist)
  219         struct mbuf *m;
  220         va_dcl
  221 #endif
  222 {
  223         va_list ap;
  224         struct sockaddr_in src, dst;
  225         struct ip *ip;
  226         struct udphdr *uh;
  227         int iphlen;
  228         int len;
  229         int n;
  230         u_int16_t ip_len;
  231 
  232         va_start(ap, m);
  233         iphlen = va_arg(ap, int);
  234         (void)va_arg(ap, int);          /* ignore value, advance ap */
  235         va_end(ap);
  236 
  237         MCLAIM(m, &udp_rx_mowner);
  238         udpstat.udps_ipackets++;
  239 
  240         /*
  241          * Get IP and UDP header together in first mbuf.
  242          */
  243         ip = mtod(m, struct ip *);
  244         IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
  245         if (uh == NULL) {
  246                 udpstat.udps_hdrops++;
  247                 return;
  248         }
  249         KASSERT(UDP_HDR_ALIGNED_P(uh));
  250 
  251         /* destination port of 0 is illegal, based on RFC768. */
  252         if (uh->uh_dport == 0)
  253                 goto bad;
  254 
  255         /*
  256          * Make mbuf data length reflect UDP length.
  257          * If not enough data to reflect UDP length, drop.
  258          */
  259         ip_len = ntohs(ip->ip_len);
  260         len = ntohs((u_int16_t)uh->uh_ulen);
  261         if (ip_len != iphlen + len) {
  262                 if (ip_len < iphlen + len || len < sizeof(struct udphdr)) {
  263                         udpstat.udps_badlen++;
  264                         goto bad;
  265                 }
  266                 m_adj(m, iphlen + len - ip_len);
  267         }
  268 
  269         /*
  270          * Checksum extended UDP header and data.
  271          */
  272         if (uh->uh_sum) {
  273                 switch (m->m_pkthdr.csum_flags &
  274                     ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_UDPv4) |
  275                     M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
  276                 case M_CSUM_UDPv4|M_CSUM_TCP_UDP_BAD:
  277                         UDP_CSUM_COUNTER_INCR(&udp_hwcsum_bad);
  278                         goto badcsum;
  279 
  280                 case M_CSUM_UDPv4|M_CSUM_DATA: {
  281                         u_int32_t hw_csum = m->m_pkthdr.csum_data;
  282                         UDP_CSUM_COUNTER_INCR(&udp_hwcsum_data);
  283                         if (m->m_pkthdr.csum_flags & M_CSUM_NO_PSEUDOHDR)
  284                                 hw_csum = in_cksum_phdr(ip->ip_src.s_addr,
  285                                     ip->ip_dst.s_addr,
  286                                     htons(hw_csum + len + IPPROTO_UDP));
  287                         if ((hw_csum ^ 0xffff) != 0)
  288                                 goto badcsum;
  289                         break;
  290                 }
  291 
  292                 case M_CSUM_UDPv4:
  293                         /* Checksum was okay. */
  294                         UDP_CSUM_COUNTER_INCR(&udp_hwcsum_ok);
  295                         break;
  296 
  297                 default:
  298                         /* Need to compute it ourselves. */
  299                         UDP_CSUM_COUNTER_INCR(&udp_swcsum);
  300                         if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0)
  301                                 goto badcsum;
  302                         break;
  303                 }
  304         }
  305 
  306         /* construct source and dst sockaddrs. */
  307         bzero(&src, sizeof(src));
  308         src.sin_family = AF_INET;
  309         src.sin_len = sizeof(struct sockaddr_in);
  310         bcopy(&ip->ip_src, &src.sin_addr, sizeof(src.sin_addr));
  311         src.sin_port = uh->uh_sport;
  312         bzero(&dst, sizeof(dst));
  313         dst.sin_family = AF_INET;
  314         dst.sin_len = sizeof(struct sockaddr_in);
  315         bcopy(&ip->ip_dst, &dst.sin_addr, sizeof(dst.sin_addr));
  316         dst.sin_port = uh->uh_dport;
  317 
  318         n = udp4_realinput(&src, &dst, m, iphlen);
  319 #ifdef INET6
  320         if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) {
  321                 struct sockaddr_in6 src6, dst6;
  322 
  323                 bzero(&src6, sizeof(src6));
  324                 src6.sin6_family = AF_INET6;
  325                 src6.sin6_len = sizeof(struct sockaddr_in6);
  326                 src6.sin6_addr.s6_addr[10] = src6.sin6_addr.s6_addr[11] = 0xff;
  327                 bcopy(&ip->ip_src, &src6.sin6_addr.s6_addr[12],
  328                         sizeof(ip->ip_src));
  329                 src6.sin6_port = uh->uh_sport;
  330                 bzero(&dst6, sizeof(dst6));
  331                 dst6.sin6_family = AF_INET6;
  332                 dst6.sin6_len = sizeof(struct sockaddr_in6);
  333                 dst6.sin6_addr.s6_addr[10] = dst6.sin6_addr.s6_addr[11] = 0xff;
  334                 bcopy(&ip->ip_dst, &dst6.sin6_addr.s6_addr[12],
  335                         sizeof(ip->ip_dst));
  336                 dst6.sin6_port = uh->uh_dport;
  337 
  338                 n += udp6_realinput(AF_INET, &src6, &dst6, m, iphlen);
  339         }
  340 #endif
  341 
  342         if (n == 0) {
  343                 if (m->m_flags & (M_BCAST | M_MCAST)) {
  344                         udpstat.udps_noportbcast++;
  345                         goto bad;
  346                 }
  347                 udpstat.udps_noport++;
  348 #ifdef IPKDB
  349                 if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport,
  350                                 m, iphlen + sizeof(struct udphdr),
  351                                 m->m_pkthdr.len - iphlen - sizeof(struct udphdr))) {
  352                         /*
  353                          * It was a debugger connect packet,
  354                          * just drop it now
  355                          */
  356                         goto bad;
  357                 }
  358 #endif
  359                 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
  360                 m = NULL;
  361         }
  362 
  363 bad:
  364         if (m)
  365                 m_freem(m);
  366         return;
  367 
  368 badcsum:
  369         m_freem(m);
  370         udpstat.udps_badsum++;
  371 }
  372 #endif
  373 
  374 #ifdef INET6
  375 int
  376 udp6_input(mp, offp, proto)
  377         struct mbuf **mp;
  378         int *offp, proto;
  379 {
  380         struct mbuf *m = *mp;
  381         int off = *offp;
  382         struct sockaddr_in6 src, dst;
  383         struct ip6_hdr *ip6;
  384         struct udphdr *uh;
  385         u_int32_t plen, ulen;
  386 
  387         ip6 = mtod(m, struct ip6_hdr *);
  388 
  389 #if defined(NFAITH) && 0 < NFAITH
  390         if (faithprefix(&ip6->ip6_dst)) {
  391                 /* send icmp6 host unreach? */
  392                 m_freem(m);
  393                 return IPPROTO_DONE;
  394         }
  395 #endif
  396 
  397         udp6stat.udp6s_ipackets++;
  398 
  399         /* check for jumbogram is done in ip6_input.  we can trust pkthdr.len */
  400         plen = m->m_pkthdr.len - off;
  401         IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr));
  402         if (uh == NULL) {
  403                 ip6stat.ip6s_tooshort++;
  404                 return IPPROTO_DONE;
  405         }
  406         KASSERT(UDP_HDR_ALIGNED_P(uh));
  407         ulen = ntohs((u_short)uh->uh_ulen);
  408         /*
  409          * RFC2675 section 4: jumbograms will have 0 in the UDP header field,
  410          * iff payload length > 0xffff.
  411          */
  412         if (ulen == 0 && plen > 0xffff)
  413                 ulen = plen;
  414 
  415         if (plen != ulen) {
  416                 udp6stat.udp6s_badlen++;
  417                 goto bad;
  418         }
  419 
  420         /* destination port of 0 is illegal, based on RFC768. */
  421         if (uh->uh_dport == 0)
  422                 goto bad;
  423 
  424         /* Be proactive about malicious use of IPv4 mapped address */
  425         if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
  426             IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
  427                 /* XXX stat */
  428                 goto bad;
  429         }
  430 
  431         /*
  432          * Checksum extended UDP header and data.
  433          */
  434         if (uh->uh_sum == 0) {
  435                 udp6stat.udp6s_nosum++;
  436                 goto bad;
  437         }
  438         if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
  439                 udp6stat.udp6s_badsum++;
  440                 goto bad;
  441         }
  442 
  443         /*
  444          * Construct source and dst sockaddrs.
  445          * Note that ifindex (s6_addr16[1]) is already filled.
  446          */
  447         bzero(&src, sizeof(src));
  448         src.sin6_family = AF_INET6;
  449         src.sin6_len = sizeof(struct sockaddr_in6);
  450         /* KAME hack: recover scopeid */
  451         (void)in6_recoverscope(&src, &ip6->ip6_src, m->m_pkthdr.rcvif);
  452         src.sin6_port = uh->uh_sport;
  453         bzero(&dst, sizeof(dst));
  454         dst.sin6_family = AF_INET6;
  455         dst.sin6_len = sizeof(struct sockaddr_in6);
  456         /* KAME hack: recover scopeid */
  457         (void)in6_recoverscope(&dst, &ip6->ip6_dst, m->m_pkthdr.rcvif);
  458         dst.sin6_port = uh->uh_dport;
  459 
  460         if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) {
  461                 if (m->m_flags & M_MCAST) {
  462                         udp6stat.udp6s_noportmcast++;
  463                         goto bad;
  464                 }
  465                 udp6stat.udp6s_noport++;
  466                 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
  467                 m = NULL;
  468         }
  469 
  470 bad:
  471         if (m)
  472                 m_freem(m);
  473         return IPPROTO_DONE;
  474 }
  475 #endif
  476 
  477 #ifdef INET
  478 static void
  479 udp4_sendup(m, off, src, so)
  480         struct mbuf *m;
  481         int off;        /* offset of data portion */
  482         struct sockaddr *src;
  483         struct socket *so;
  484 {
  485         struct mbuf *opts = NULL;
  486         struct mbuf *n;
  487         struct inpcb *inp = NULL;
  488 
  489         if (!so)
  490                 return;
  491         switch (so->so_proto->pr_domain->dom_family) {
  492         case AF_INET:
  493                 inp = sotoinpcb(so);
  494                 break;
  495 #ifdef INET6
  496         case AF_INET6:
  497                 break;
  498 #endif
  499         default:
  500                 return;
  501         }
  502 
  503 #if defined(IPSEC) || defined(FAST_IPSEC)
  504         /* check AH/ESP integrity. */
  505         if (so != NULL && ipsec4_in_reject_so(m, so)) {
  506                 ipsecstat.in_polvio++;
  507                 if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
  508                         icmp_error(n, ICMP_UNREACH, ICMP_UNREACH_ADMIN_PROHIBIT,
  509                             0, 0);
  510                 return;
  511         }
  512 #endif /*IPSEC*/
  513 
  514         if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
  515                 if (inp && (inp->inp_flags & INP_CONTROLOPTS
  516                          || so->so_options & SO_TIMESTAMP)) {
  517                         struct ip *ip = mtod(n, struct ip *);
  518                         ip_savecontrol(inp, &opts, ip, n);
  519                 }
  520 
  521                 m_adj(n, off);
  522                 if (sbappendaddr(&so->so_rcv, src, n,
  523                                 opts) == 0) {
  524                         m_freem(n);
  525                         if (opts)
  526                                 m_freem(opts);
  527                         udpstat.udps_fullsock++;
  528                 } else
  529                         sorwakeup(so);
  530         }
  531 }
  532 #endif
  533 
  534 #ifdef INET6
  535 static void
  536 udp6_sendup(m, off, src, so)
  537         struct mbuf *m;
  538         int off;        /* offset of data portion */
  539         struct sockaddr *src;
  540         struct socket *so;
  541 {
  542         struct mbuf *opts = NULL;
  543         struct mbuf *n;
  544         struct in6pcb *in6p = NULL;
  545 
  546         if (!so)
  547                 return;
  548         if (so->so_proto->pr_domain->dom_family != AF_INET6)
  549                 return;
  550         in6p = sotoin6pcb(so);
  551 
  552 #if defined(IPSEC) || defined(FAST_IPSEC)
  553         /* check AH/ESP integrity. */
  554         if (so != NULL && ipsec6_in_reject_so(m, so)) {
  555                 ipsec6stat.in_polvio++;
  556                 if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
  557                         icmp6_error(n, ICMP6_DST_UNREACH,
  558                             ICMP6_DST_UNREACH_ADMIN, 0);
  559                 return;
  560         }
  561 #endif /*IPSEC*/
  562 
  563         if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
  564                 if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS
  565                           || in6p->in6p_socket->so_options & SO_TIMESTAMP)) {
  566                         struct ip6_hdr *ip6 = mtod(n, struct ip6_hdr *);
  567                         ip6_savecontrol(in6p, &opts, ip6, n);
  568                 }
  569 
  570                 m_adj(n, off);
  571                 if (sbappendaddr(&so->so_rcv, src, n, opts) == 0) {
  572                         m_freem(n);
  573                         if (opts)
  574                                 m_freem(opts);
  575                         udp6stat.udp6s_fullsock++;
  576                 } else
  577                         sorwakeup(so);
  578         }
  579 }
  580 #endif
  581 
  582 #ifdef INET
  583 static int
  584 udp4_realinput(src, dst, m, off)
  585         struct sockaddr_in *src;
  586         struct sockaddr_in *dst;
  587         struct mbuf *m;
  588         int off;        /* offset of udphdr */
  589 {
  590         u_int16_t *sport, *dport;
  591         int rcvcnt;
  592         struct in_addr *src4, *dst4;
  593         struct inpcb_hdr *inph;
  594         struct inpcb *inp;
  595 
  596         rcvcnt = 0;
  597         off += sizeof(struct udphdr);   /* now, offset of payload */
  598 
  599         if (src->sin_family != AF_INET || dst->sin_family != AF_INET)
  600                 goto bad;
  601 
  602         src4 = &src->sin_addr;
  603         sport = &src->sin_port;
  604         dst4 = &dst->sin_addr;
  605         dport = &dst->sin_port;
  606 
  607         if (IN_MULTICAST(dst4->s_addr) ||
  608             in_broadcast(*dst4, m->m_pkthdr.rcvif)) {
  609                 /*
  610                  * Deliver a multicast or broadcast datagram to *all* sockets
  611                  * for which the local and remote addresses and ports match
  612                  * those of the incoming datagram.  This allows more than
  613                  * one process to receive multi/broadcasts on the same port.
  614                  * (This really ought to be done for unicast datagrams as
  615                  * well, but that would cause problems with existing
  616                  * applications that open both address-specific sockets and
  617                  * a wildcard socket listening to the same port -- they would
  618                  * end up receiving duplicates of every unicast datagram.
  619                  * Those applications open the multiple sockets to overcome an
  620                  * inadequacy of the UDP socket interface, but for backwards
  621                  * compatibility we avoid the problem here rather than
  622                  * fixing the interface.  Maybe 4.5BSD will remedy this?)
  623                  */
  624 
  625                 /*
  626                  * KAME note: traditionally we dropped udpiphdr from mbuf here.
  627                  * we need udpiphdr for IPsec processing so we do that later.
  628                  */
  629                 /*
  630                  * Locate pcb(s) for datagram.
  631                  */
  632                 CIRCLEQ_FOREACH(inph, &udbtable.inpt_queue, inph_queue) {
  633                         inp = (struct inpcb *)inph;
  634                         if (inp->inp_af != AF_INET)
  635                                 continue;
  636 
  637                         if (inp->inp_lport != *dport)
  638                                 continue;
  639                         if (!in_nullhost(inp->inp_laddr)) {
  640                                 if (!in_hosteq(inp->inp_laddr, *dst4))
  641                                         continue;
  642                         }
  643                         if (!in_nullhost(inp->inp_faddr)) {
  644                                 if (!in_hosteq(inp->inp_faddr, *src4) ||
  645                                     inp->inp_fport != *sport)
  646                                         continue;
  647                         }
  648 
  649                         udp4_sendup(m, off, (struct sockaddr *)src,
  650                                 inp->inp_socket);
  651                         rcvcnt++;
  652 
  653                         /*
  654                          * Don't look for additional matches if this one does
  655                          * not have either the SO_REUSEPORT or SO_REUSEADDR
  656                          * socket options set.  This heuristic avoids searching
  657                          * through all pcbs in the common case of a non-shared
  658                          * port.  It assumes that an application will never
  659                          * clear these options after setting them.
  660                          */
  661                         if ((inp->inp_socket->so_options &
  662                             (SO_REUSEPORT|SO_REUSEADDR)) == 0)
  663                                 break;
  664                 }
  665         } else {
  666                 /*
  667                  * Locate pcb for datagram.
  668                  */
  669                 inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4, *dport);
  670                 if (inp == 0) {
  671                         ++udpstat.udps_pcbhashmiss;
  672                         inp = in_pcblookup_bind(&udbtable, *dst4, *dport);
  673                         if (inp == 0)
  674                                 return rcvcnt;
  675                 }
  676 
  677                 udp4_sendup(m, off, (struct sockaddr *)src, inp->inp_socket);
  678                 rcvcnt++;
  679         }
  680 
  681 bad:
  682         return rcvcnt;
  683 }
  684 #endif
  685 
  686 #ifdef INET6
  687 static int
  688 udp6_realinput(af, src, dst, m, off)
  689         int af;         /* af on packet */
  690         struct sockaddr_in6 *src;
  691         struct sockaddr_in6 *dst;
  692         struct mbuf *m;
  693         int off;        /* offset of udphdr */
  694 {
  695         u_int16_t sport, dport;
  696         int rcvcnt;
  697         struct in6_addr src6, dst6;
  698         const struct in_addr *dst4;
  699         struct inpcb_hdr *inph;
  700         struct in6pcb *in6p;
  701 
  702         rcvcnt = 0;
  703         off += sizeof(struct udphdr);   /* now, offset of payload */
  704 
  705         if (af != AF_INET && af != AF_INET6)
  706                 goto bad;
  707         if (src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6)
  708                 goto bad;
  709 
  710         in6_embedscope(&src6, src, NULL, NULL);
  711         sport = src->sin6_port;
  712         in6_embedscope(&dst6, dst, NULL, NULL);
  713         dport = dst->sin6_port;
  714         dst4 = (struct in_addr *)&dst->sin6_addr.s6_addr[12];
  715 
  716         if (IN6_IS_ADDR_MULTICAST(&dst6) ||
  717             (af == AF_INET && IN_MULTICAST(dst4->s_addr))) {
  718                 /*
  719                  * Deliver a multicast or broadcast datagram to *all* sockets
  720                  * for which the local and remote addresses and ports match
  721                  * those of the incoming datagram.  This allows more than
  722                  * one process to receive multi/broadcasts on the same port.
  723                  * (This really ought to be done for unicast datagrams as
  724                  * well, but that would cause problems with existing
  725                  * applications that open both address-specific sockets and
  726                  * a wildcard socket listening to the same port -- they would
  727                  * end up receiving duplicates of every unicast datagram.
  728                  * Those applications open the multiple sockets to overcome an
  729                  * inadequacy of the UDP socket interface, but for backwards
  730                  * compatibility we avoid the problem here rather than
  731                  * fixing the interface.  Maybe 4.5BSD will remedy this?)
  732                  */
  733 
  734                 /*
  735                  * KAME note: traditionally we dropped udpiphdr from mbuf here.
  736                  * we need udpiphdr for IPsec processing so we do that later.
  737                  */
  738                 /*
  739                  * Locate pcb(s) for datagram.
  740                  */
  741                 CIRCLEQ_FOREACH(inph, &udbtable.inpt_queue, inph_queue) {
  742                         in6p = (struct in6pcb *)inph;
  743                         if (in6p->in6p_af != AF_INET6)
  744                                 continue;
  745 
  746                         if (in6p->in6p_lport != dport)
  747                                 continue;
  748                         if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
  749                                 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &dst6))
  750                                         continue;
  751                         } else {
  752                                 if (IN6_IS_ADDR_V4MAPPED(&dst6) &&
  753                                     (in6p->in6p_flags & IN6P_IPV6_V6ONLY))
  754                                         continue;
  755                         }
  756                         if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
  757                                 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
  758                                     &src6) || in6p->in6p_fport != sport)
  759                                         continue;
  760                         } else {
  761                                 if (IN6_IS_ADDR_V4MAPPED(&src6) &&
  762                                     (in6p->in6p_flags & IN6P_IPV6_V6ONLY))
  763                                         continue;
  764                         }
  765 
  766                         udp6_sendup(m, off, (struct sockaddr *)src,
  767                                 in6p->in6p_socket);
  768                         rcvcnt++;
  769 
  770                         /*
  771                          * Don't look for additional matches if this one does
  772                          * not have either the SO_REUSEPORT or SO_REUSEADDR
  773                          * socket options set.  This heuristic avoids searching
  774                          * through all pcbs in the common case of a non-shared
  775                          * port.  It assumes that an application will never
  776                          * clear these options after setting them.
  777                          */
  778                         if ((in6p->in6p_socket->so_options &
  779                             (SO_REUSEPORT|SO_REUSEADDR)) == 0)
  780                                 break;
  781                 }
  782         } else {
  783                 /*
  784                  * Locate pcb for datagram.
  785                  */
  786                 in6p = in6_pcblookup_connect(&udbtable, &src6, sport,
  787                     &dst6, dport, 0);
  788                 if (in6p == 0) {
  789                         ++udpstat.udps_pcbhashmiss;
  790                         in6p = in6_pcblookup_bind(&udbtable, &dst6, dport, 0);
  791                         if (in6p == 0)
  792                                 return rcvcnt;
  793                 }
  794 
  795                 udp6_sendup(m, off, (struct sockaddr *)src, in6p->in6p_socket);
  796                 rcvcnt++;
  797         }
  798 
  799 bad:
  800         return rcvcnt;
  801 }
  802 #endif
  803 
  804 #ifdef INET
  805 /*
  806  * Notify a udp user of an asynchronous error;
  807  * just wake up so that he can collect error status.
  808  */
  809 static void
  810 udp_notify(inp, errno)
  811         struct inpcb *inp;
  812         int errno;
  813 {
  814 
  815         inp->inp_socket->so_error = errno;
  816         sorwakeup(inp->inp_socket);
  817         sowwakeup(inp->inp_socket);
  818 }
  819 
  820 void *
  821 udp_ctlinput(cmd, sa, v)
  822         int cmd;
  823         struct sockaddr *sa;
  824         void *v;
  825 {
  826         struct ip *ip = v;
  827         struct udphdr *uh;
  828         void (*notify) __P((struct inpcb *, int)) = udp_notify;
  829         int errno;
  830 
  831         if (sa->sa_family != AF_INET
  832          || sa->sa_len != sizeof(struct sockaddr_in))
  833                 return NULL;
  834         if ((unsigned)cmd >= PRC_NCMDS)
  835                 return NULL;
  836         errno = inetctlerrmap[cmd];
  837         if (PRC_IS_REDIRECT(cmd))
  838                 notify = in_rtchange, ip = 0;
  839         else if (cmd == PRC_HOSTDEAD)
  840                 ip = 0;
  841         else if (errno == 0)
  842                 return NULL;
  843         if (ip) {
  844                 uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
  845                 in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport,
  846                     ip->ip_src, uh->uh_sport, errno, notify);
  847 
  848                 /* XXX mapped address case */
  849         } else
  850                 in_pcbnotifyall(&udbtable, satosin(sa)->sin_addr, errno,
  851                     notify);
  852         return NULL;
  853 }
  854 
  855 int
  856 #if __STDC__
  857 udp_output(struct mbuf *m, ...)
  858 #else
  859 udp_output(m, va_alist)
  860         struct mbuf *m;
  861         va_dcl
  862 #endif
  863 {
  864         struct inpcb *inp;
  865         struct udpiphdr *ui;
  866         int len = m->m_pkthdr.len;
  867         int error = 0;
  868         va_list ap;
  869 
  870         MCLAIM(m, &udp_tx_mowner);
  871         va_start(ap, m);
  872         inp = va_arg(ap, struct inpcb *);
  873         va_end(ap);
  874 
  875         /*
  876          * Calculate data length and get a mbuf
  877          * for UDP and IP headers.
  878          */
  879         M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
  880         if (m == 0) {
  881                 error = ENOBUFS;
  882                 goto release;
  883         }
  884 
  885         /*
  886          * Compute the packet length of the IP header, and
  887          * punt if the length looks bogus.
  888          */
  889         if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
  890                 error = EMSGSIZE;
  891                 goto release;
  892         }
  893 
  894         /*
  895          * Fill in mbuf with extended UDP header
  896          * and addresses and length put into network format.
  897          */
  898         ui = mtod(m, struct udpiphdr *);
  899         ui->ui_pr = IPPROTO_UDP;
  900         ui->ui_src = inp->inp_laddr;
  901         ui->ui_dst = inp->inp_faddr;
  902         ui->ui_sport = inp->inp_lport;
  903         ui->ui_dport = inp->inp_fport;
  904         ui->ui_ulen = htons((u_int16_t)len + sizeof(struct udphdr));
  905 
  906         /*
  907          * Set up checksum and output datagram.
  908          */
  909         if (udpcksum) {
  910                 /*
  911                  * XXX Cache pseudo-header checksum part for
  912                  * XXX "connected" UDP sockets.
  913                  */
  914                 ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
  915                     ui->ui_dst.s_addr, htons((u_int16_t)len +
  916                     sizeof(struct udphdr) + IPPROTO_UDP));
  917                 m->m_pkthdr.csum_flags = M_CSUM_UDPv4;
  918                 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
  919         } else
  920                 ui->ui_sum = 0;
  921         ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len);
  922         ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */
  923         ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */
  924         udpstat.udps_opackets++;
  925 
  926         return (ip_output(m, inp->inp_options, &inp->inp_route,
  927             inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
  928             inp->inp_moptions, inp->inp_socket));
  929 
  930 release:
  931         m_freem(m);
  932         return (error);
  933 }
  934 
  935 int     udp_sendspace = 9216;           /* really max datagram size */
  936 int     udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
  937                                         /* 40 1K datagrams */
  938 
  939 /*ARGSUSED*/
  940 int
  941 udp_usrreq(so, req, m, nam, control, p)
  942         struct socket *so;
  943         int req;
  944         struct mbuf *m, *nam, *control;
  945         struct proc *p;
  946 {
  947         struct inpcb *inp;
  948         int s;
  949         int error = 0;
  950 
  951         if (req == PRU_CONTROL)
  952                 return (in_control(so, (long)m, (caddr_t)nam,
  953                     (struct ifnet *)control, p));
  954 
  955         if (req == PRU_PURGEIF) {
  956                 in_pcbpurgeif0(&udbtable, (struct ifnet *)control);
  957                 in_purgeif((struct ifnet *)control);
  958                 in_pcbpurgeif(&udbtable, (struct ifnet *)control);
  959                 return (0);
  960         }
  961 
  962         s = splsoftnet();
  963         inp = sotoinpcb(so);
  964 #ifdef DIAGNOSTIC
  965         if (req != PRU_SEND && req != PRU_SENDOOB && control)
  966                 panic("udp_usrreq: unexpected control mbuf");
  967 #endif
  968         if (inp == 0 && req != PRU_ATTACH) {
  969                 error = EINVAL;
  970                 goto release;
  971         }
  972 
  973         /*
  974          * Note: need to block udp_input while changing
  975          * the udp pcb queue and/or pcb addresses.
  976          */
  977         switch (req) {
  978 
  979         case PRU_ATTACH:
  980                 if (inp != 0) {
  981                         error = EISCONN;
  982                         break;
  983                 }
  984 #ifdef MBUFTRACE
  985                 so->so_mowner = &udp_mowner;
  986                 so->so_rcv.sb_mowner = &udp_rx_mowner;
  987                 so->so_snd.sb_mowner = &udp_tx_mowner;
  988 #endif
  989                 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  990                         error = soreserve(so, udp_sendspace, udp_recvspace);
  991                         if (error)
  992                                 break;
  993                 }
  994                 error = in_pcballoc(so, &udbtable);
  995                 if (error)
  996                         break;
  997                 inp = sotoinpcb(so);
  998                 inp->inp_ip.ip_ttl = ip_defttl;
  999                 break;
 1000 
 1001         case PRU_DETACH:
 1002                 in_pcbdetach(inp);
 1003                 break;
 1004 
 1005         case PRU_BIND:
 1006                 error = in_pcbbind(inp, nam, p);
 1007                 break;
 1008 
 1009         case PRU_LISTEN:
 1010                 error = EOPNOTSUPP;
 1011                 break;
 1012 
 1013         case PRU_CONNECT:
 1014                 error = in_pcbconnect(inp, nam);
 1015                 if (error)
 1016                         break;
 1017                 soisconnected(so);
 1018                 break;
 1019 
 1020         case PRU_CONNECT2:
 1021                 error = EOPNOTSUPP;
 1022                 break;
 1023 
 1024         case PRU_DISCONNECT:
 1025                 /*soisdisconnected(so);*/
 1026                 so->so_state &= ~SS_ISCONNECTED;        /* XXX */
 1027                 in_pcbdisconnect(inp);
 1028                 inp->inp_laddr = zeroin_addr;           /* XXX */
 1029                 in_pcbstate(inp, INP_BOUND);            /* XXX */
 1030                 break;
 1031 
 1032         case PRU_SHUTDOWN:
 1033                 socantsendmore(so);
 1034                 break;
 1035 
 1036         case PRU_RCVD:
 1037                 error = EOPNOTSUPP;
 1038                 break;
 1039 
 1040         case PRU_SEND:
 1041                 if (control && control->m_len) {
 1042                         m_freem(control);
 1043                         m_freem(m);
 1044                         error = EINVAL;
 1045                         break;
 1046                 }
 1047         {
 1048                 struct in_addr laddr;                   /* XXX */
 1049 
 1050                 if (nam) {
 1051                         laddr = inp->inp_laddr;         /* XXX */
 1052                         if ((so->so_state & SS_ISCONNECTED) != 0) {
 1053                                 error = EISCONN;
 1054                                 goto die;
 1055                         }
 1056                         error = in_pcbconnect(inp, nam);
 1057                         if (error)
 1058                                 goto die;
 1059                 } else {
 1060                         if ((so->so_state & SS_ISCONNECTED) == 0) {
 1061                                 error = ENOTCONN;
 1062                                 goto die;
 1063                         }
 1064                 }
 1065                 error = udp_output(m, inp);
 1066                 m = NULL;
 1067                 if (nam) {
 1068                         in_pcbdisconnect(inp);
 1069                         inp->inp_laddr = laddr;         /* XXX */
 1070                         in_pcbstate(inp, INP_BOUND);    /* XXX */
 1071                 }
 1072           die:
 1073                 if (m)
 1074                         m_freem(m);
 1075         }
 1076                 break;
 1077 
 1078         case PRU_SENSE:
 1079                 /*
 1080                  * stat: don't bother with a blocksize.
 1081                  */
 1082                 splx(s);
 1083                 return (0);
 1084 
 1085         case PRU_RCVOOB:
 1086                 error =  EOPNOTSUPP;
 1087                 break;
 1088 
 1089         case PRU_SENDOOB:
 1090                 m_freem(control);
 1091                 m_freem(m);
 1092                 error =  EOPNOTSUPP;
 1093                 break;
 1094 
 1095         case PRU_SOCKADDR:
 1096                 in_setsockaddr(inp, nam);
 1097                 break;
 1098 
 1099         case PRU_PEERADDR:
 1100                 in_setpeeraddr(inp, nam);
 1101                 break;
 1102 
 1103         default:
 1104                 panic("udp_usrreq");
 1105         }
 1106 
 1107 release:
 1108         splx(s);
 1109         return (error);
 1110 }
 1111 
 1112 /*
 1113  * Sysctl for udp variables.
 1114  */
 1115 SYSCTL_SETUP(sysctl_net_inet_udp_setup, "sysctl net.inet.udp subtree setup")
 1116 {
 1117 
 1118         sysctl_createv(clog, 0, NULL, NULL,
 1119                        CTLFLAG_PERMANENT,
 1120                        CTLTYPE_NODE, "net", NULL,
 1121                        NULL, 0, NULL, 0,
 1122                        CTL_NET, CTL_EOL);
 1123         sysctl_createv(clog, 0, NULL, NULL,
 1124                        CTLFLAG_PERMANENT,
 1125                        CTLTYPE_NODE, "inet", NULL,
 1126                        NULL, 0, NULL, 0,
 1127                        CTL_NET, PF_INET, CTL_EOL);
 1128         sysctl_createv(clog, 0, NULL, NULL,
 1129                        CTLFLAG_PERMANENT,
 1130                        CTLTYPE_NODE, "udp",
 1131                        SYSCTL_DESCR("UDPv4 related settings"),
 1132                        NULL, 0, NULL, 0,
 1133                        CTL_NET, PF_INET, IPPROTO_UDP, CTL_EOL);
 1134 
 1135         sysctl_createv(clog, 0, NULL, NULL,
 1136                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1137                        CTLTYPE_INT, "checksum",
 1138                        SYSCTL_DESCR("Compute and check UDP checksums"),
 1139                        NULL, 0, &udpcksum, 0,
 1140                        CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_CHECKSUM,
 1141                        CTL_EOL);
 1142         sysctl_createv(clog, 0, NULL, NULL,
 1143                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1144                        CTLTYPE_INT, "sendspace",
 1145                        SYSCTL_DESCR("Default UDP send buffer size"),
 1146                        NULL, 0, &udp_sendspace, 0,
 1147                        CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_SENDSPACE,
 1148                        CTL_EOL);
 1149         sysctl_createv(clog, 0, NULL, NULL,
 1150                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1151                        CTLTYPE_INT, "recvspace",
 1152                        SYSCTL_DESCR("Default UDP receive buffer size"),
 1153                        NULL, 0, &udp_recvspace, 0,
 1154                        CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_RECVSPACE,
 1155                        CTL_EOL);
 1156 }
 1157 #endif

Cache object: a6ae3ccc05ace34b7875b1665eafa309


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