[BACK]Return to udp_usrreq.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/netinet/udp_usrreq.c between version 1.35 and 1.47.4.1

version 1.35, 1996/09/15 18:11:11 version 1.47.4.1, 1999/07/01 23:47:04
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
 /*  /*
  * Copyright (c) 1982, 1986, 1988, 1990, 1993   * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    *    notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the
    *    documentation and/or other materials provided with the distribution.
    * 3. Neither the name of the project nor the names of its contributors
    *    may be used to endorse or promote products derived from this software
    *    without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    * SUCH DAMAGE.
    */
   
   /*
    * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
  *      The Regents of the University of California.  All rights reserved.   *      The Regents of the University of California.  All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
Line 32 
Line 61 
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.   * SUCH DAMAGE.
  *   *
  *      @(#)udp_usrreq.c        8.4 (Berkeley) 1/21/94   *      @(#)udp_usrreq.c        8.6 (Berkeley) 5/23/95
  */   */
   #include "ipkdb.h"
   
   /* XXX MAPPED_ADDR_ENABLED should be revisited */
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/malloc.h>  #include <sys/malloc.h>
 #include <sys/mbuf.h>  #include <sys/mbuf.h>
   #ifdef MAPPED_ADDR_ENABLED
   #include <sys/domain.h>
   #endif /* MAPPED_ADDR_ENABLED */
 #include <sys/protosw.h>  #include <sys/protosw.h>
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <sys/socketvar.h>  #include <sys/socketvar.h>
Line 64 
Line 99 
   
 #include <machine/stdarg.h>  #include <machine/stdarg.h>
   
   #ifdef IPSEC
   #include <netinet6/ipsec.h>
   #include <netkey/key.h>
   #include <netkey/key_debug.h>
   #endif /*IPSEC*/
   
 /*  /*
  * UDP protocol implementation.   * UDP protocol implementation.
  * Per RFC 768, August, 1980.   * Per RFC 768, August, 1980.
Line 75  int udpcksum = 0;  /* XXX */
Line 116  int udpcksum = 0;  /* XXX */
 #endif  #endif
   
 static  void udp_notify __P((struct inpcb *, int));  static  void udp_notify __P((struct inpcb *, int));
 static  struct mbuf *udp_saveopt __P((caddr_t, int, int));  
   
 #ifndef UDBHASHSIZE  #ifndef UDBHASHSIZE
 #define UDBHASHSIZE     128  #define UDBHASHSIZE     128
Line 98  udp_input(m, va_alist)
Line 138  udp_input(m, va_alist)
         va_dcl          va_dcl
 #endif  #endif
 {  {
           int proto;
         register struct ip *ip;          register struct ip *ip;
         register struct udphdr *uh;          register struct udphdr *uh;
         register struct inpcb *inp;          register struct inpcb *inp;
Line 107  udp_input(m, va_alist)
Line 148  udp_input(m, va_alist)
         int iphlen;          int iphlen;
         va_list ap;          va_list ap;
         struct sockaddr_in udpsrc;          struct sockaddr_in udpsrc;
   #ifdef MAPPED_ADDR_ENABLED
           struct sockaddr_in6 mapped;
   #endif
           struct sockaddr *sa;
   
         va_start(ap, m);          va_start(ap, m);
         iphlen = va_arg(ap, int);          iphlen = va_arg(ap, int);
           proto = va_arg(ap, int);
         va_end(ap);          va_end(ap);
   
         udpstat.udps_ipackets++;          udpstat.udps_ipackets++;
Line 143  udp_input(m, va_alist)
Line 189  udp_input(m, va_alist)
          * If not enough data to reflect UDP length, drop.           * If not enough data to reflect UDP length, drop.
          */           */
         len = ntohs((u_int16_t)uh->uh_ulen);          len = ntohs((u_int16_t)uh->uh_ulen);
         if (ip->ip_len != len) {          if (ip->ip_len != iphlen + len) {
                 if (len > ip->ip_len) {                  if (ip->ip_len < iphlen + len) {
                         udpstat.udps_badlen++;                          udpstat.udps_badlen++;
                         goto bad;                          goto bad;
                 }                  }
                 m_adj(m, len - ip->ip_len);                  m_adj(m, iphlen + len - ip->ip_len);
                 /* ip->ip_len = len; */  
         }          }
         /*          /*
          * Save a copy of the IP header in case we want restore it           * Save a copy of the IP header in case we want restore it
Line 164  udp_input(m, va_alist)
Line 209  udp_input(m, va_alist)
                 bzero(((struct ipovly *)ip)->ih_x1,                  bzero(((struct ipovly *)ip)->ih_x1,
                     sizeof ((struct ipovly *)ip)->ih_x1);                      sizeof ((struct ipovly *)ip)->ih_x1);
                 ((struct ipovly *)ip)->ih_len = uh->uh_ulen;                  ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
                 if ((uh->uh_sum = in_cksum(m, len + sizeof (struct ip))) != 0) {                  if (in_cksum(m, len + sizeof (struct ip)) != 0) {
                         udpstat.udps_badsum++;                          udpstat.udps_badsum++;
                         m_freem(m);                          m_freem(m);
                         return;                          return;
                 }                  }
         }          }
   
           /*
            * Construct sockaddr format source address.
            */
           udpsrc.sin_family = AF_INET;
           udpsrc.sin_len = sizeof(struct sockaddr_in);
           udpsrc.sin_addr = ip->ip_src;
           udpsrc.sin_port = uh->uh_sport;
           bzero((caddr_t)udpsrc.sin_zero, sizeof(udpsrc.sin_zero));
   
         if (IN_MULTICAST(ip->ip_dst.s_addr) ||          if (IN_MULTICAST(ip->ip_dst.s_addr) ||
             in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {              in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
                 struct socket *last;                  struct inpcb *last;
                 /*                  /*
                  * Deliver a multicast or broadcast datagram to *all* sockets                   * Deliver a multicast or broadcast datagram to *all* sockets
                  * for which the local and remote addresses and ports match                   * for which the local and remote addresses and ports match
Line 190  udp_input(m, va_alist)
Line 244  udp_input(m, va_alist)
                  * fixing the interface.  Maybe 4.5BSD will remedy this?)                   * fixing the interface.  Maybe 4.5BSD will remedy this?)
                  */                   */
   
                   iphlen += sizeof(struct udphdr);
                 /*                  /*
                  * Construct sockaddr format source address.                   * KAME note: usually we drop udpiphdr from mbuf here.
                    * we need udpiphdr for iPsec processing so we do that later.
                  */                   */
                 udpsrc.sin_family = AF_INET;  
                 udpsrc.sin_len = sizeof(struct sockaddr_in);  
                 udpsrc.sin_port = uh->uh_sport;  
                 udpsrc.sin_addr = ip->ip_src;  
   
                 m->m_len -= sizeof (struct udpiphdr);  
                 m->m_data += sizeof (struct udpiphdr);  
                 /*                  /*
                  * Locate pcb(s) for datagram.                   * Locate pcb(s) for datagram.
                  * (Algorithm copied from raw_intr().)                   * (Algorithm copied from raw_intr().)
Line 223  udp_input(m, va_alist)
Line 272  udp_input(m, va_alist)
                         if (last != NULL) {                          if (last != NULL) {
                                 struct mbuf *n;                                  struct mbuf *n;
   
   #ifdef IPSEC
                                   /* check AH/ESP integrity. */
                                   if (last != NULL && ipsec4_in_reject(m, last)) {
                                           ipsecstat.in_polvio++;
                                           /* do not inject data to pcb */
                                   } else
   #endif /*IPSEC*/
                                 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {                                  if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
                                         if (sbappendaddr(&last->so_rcv,                                          m_adj(m, iphlen);
                                                 sintosa(&udpsrc), n,                                          if (last->inp_flags & INP_CONTROLOPTS
                                                 (struct mbuf *)0) == 0) {                                              || last->inp_socket->so_options &
                                                  SO_TIMESTAMP) {
                                                   ip_savecontrol(last, &opts,
                                                       ip, n);
                                           }
                                           sa = (struct sockaddr *)&udpsrc;
   #ifdef MAPPED_ADDR_ENABLED
                                           if (last->inp_socket->so_proto->pr_domain->dom_family == AF_INET6) {
                                                   in6_sin_2_v4mapsin6(&udpsrc,
                                                                       &mapped);
                                                   sa = (struct sockaddr *)&mapped;
                                           }
   #endif /* MAPPED_ADDR_ENABLED */
                                           if (sbappendaddr(
                                               &last->inp_socket->so_rcv,
                                               sa, n, opts) == 0) {
                                                 m_freem(n);                                                  m_freem(n);
                                                 udpstat.udps_fullsock++;                                                  if (opts)
                                                           m_freem(opts);
                                         } else                                          } else
                                                 sorwakeup(last);                                                  sorwakeup(last->inp_socket);
                                           opts = 0;
                                 }                                  }
                         }                          }
                         last = inp->inp_socket;                          last = inp;
                         /*                          /*
                          * Don't look for additional matches if this one does                           * Don't look for additional matches if this one does
                          * not have either the SO_REUSEPORT or SO_REUSEADDR                           * not have either the SO_REUSEPORT or SO_REUSEADDR
Line 242  udp_input(m, va_alist)
Line 315  udp_input(m, va_alist)
                          * port.  It * assumes that an application will never                           * port.  It * assumes that an application will never
                          * clear these options after setting them.                           * clear these options after setting them.
                          */                           */
                         if ((last->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)                          if ((last->inp_socket->so_options &
                               (SO_REUSEPORT|SO_REUSEADDR)) == 0)
                                 break;                                  break;
                 }                  }
   
Line 252  udp_input(m, va_alist)
Line 326  udp_input(m, va_alist)
                          * (No need to send an ICMP Port Unreachable                           * (No need to send an ICMP Port Unreachable
                          * for a broadcast or multicast datgram.)                           * for a broadcast or multicast datgram.)
                          */                           */
                           udpstat.udps_noport++;
                         udpstat.udps_noportbcast++;                          udpstat.udps_noportbcast++;
                         goto bad;                          goto bad;
                 }                  }
                 if (sbappendaddr(&last->so_rcv, sintosa(&udpsrc), m,  #ifdef IPSEC
                     (struct mbuf *)0) == 0) {                  /* check AH/ESP integrity. */
                   if (last != NULL && ipsec4_in_reject(m, last)) {
                           ipsecstat.in_polvio++;
                           goto bad;
                   }
   #endif /*IPSEC*/
                   if (last->inp_flags & INP_CONTROLOPTS ||
                       last->inp_socket->so_options & SO_TIMESTAMP)
                           ip_savecontrol(last, &opts, ip, m);
                   sa = (struct sockaddr *)&udpsrc;
   #ifdef MAPPED_ADDR_ENABLED
                   if (last->inp_socket->so_proto->pr_domain->dom_family ==
                       AF_INET6) {
                           in6_sin_2_v4mapsin6(&udpsrc, &mapped);
                           sa = (struct sockaddr *)&mapped;
                   }
   #endif /* MAPPED_ADDR_ENABLED */
                   if (sbappendaddr(&last->inp_socket->so_rcv, sa, m, opts) == 0) {
                         udpstat.udps_fullsock++;                          udpstat.udps_fullsock++;
                         goto bad;                          goto bad;
                 }                  }
                 sorwakeup(last);                  sorwakeup(last->inp_socket);
                 return;                  return;
         }          }
         /*          /*
Line 278  udp_input(m, va_alist)
Line 370  udp_input(m, va_alist)
                                 goto bad;                                  goto bad;
                         }                          }
                         *ip = save_ip;                          *ip = save_ip;
                         ip->ip_len += iphlen;  #if NIPKDB > 0
                           if (checkipkdb(&ip->ip_src,
                                          uh->uh_sport,
                                          uh->uh_dport,
                                          m,
                                          iphlen + sizeof(struct udphdr),
                                          len - sizeof(struct udphdr)))
                           /* It was a debugger connect packet, just drop it now */
                                   goto bad;
   #endif
                         icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);                          icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
                         return;                          return;
                 }                  }
         }          }
   #ifdef IPSEC
           if (inp != NULL && ipsec4_in_reject(m, inp)) {
                   ipsecstat.in_polvio++;
                   goto bad;
           }
   #endif /*IPSEC*/
   
         /*          /*
          * Construct sockaddr format source address.  
          * Stuff source address and datagram in user buffer.           * Stuff source address and datagram in user buffer.
          */           */
         udpsrc.sin_family = AF_INET;          if (inp->inp_flags & INP_CONTROLOPTS ||
         udpsrc.sin_len = sizeof(struct sockaddr_in);              inp->inp_socket->so_options & SO_TIMESTAMP)
         udpsrc.sin_port = uh->uh_sport;                  ip_savecontrol(inp, &opts, ip, m);
         udpsrc.sin_addr = ip->ip_src;  
   
         if (inp->inp_flags & INP_CONTROLOPTS) {  
                 struct mbuf **mp = &opts;  
   
                 if (inp->inp_flags & INP_RECVDSTADDR) {  
                         *mp = udp_saveopt((caddr_t) &ip->ip_dst,  
                             sizeof(struct in_addr), IP_RECVDSTADDR);  
                         if (*mp)  
                                 mp = &(*mp)->m_next;  
                 }  
 #ifdef notyet  
                 /* options were tossed above */  
                 if (inp->inp_flags & INP_RECVOPTS) {  
                         *mp = udp_saveopt((caddr_t) opts_deleted_above,  
                             sizeof(struct in_addr), IP_RECVOPTS);  
                         if (*mp)  
                                 mp = &(*mp)->m_next;  
                 }  
                 /* ip_srcroute doesn't do what we want here, need to fix */  
                 if (inp->inp_flags & INP_RECVRETOPTS) {  
                         *mp = udp_saveopt((caddr_t) ip_srcroute(),  
                             sizeof(struct in_addr), IP_RECVRETOPTS);  
                         if (*mp)  
                                 mp = &(*mp)->m_next;  
                 }  
 #endif  
         }  
         iphlen += sizeof(struct udphdr);          iphlen += sizeof(struct udphdr);
         m->m_len -= iphlen;          m->m_len -= iphlen;
         m->m_pkthdr.len -= iphlen;          m->m_pkthdr.len -= iphlen;
         m->m_data += iphlen;          m->m_data += iphlen;
         if (sbappendaddr(&inp->inp_socket->so_rcv, sintosa(&udpsrc), m,          sa = (struct sockaddr *)&udpsrc;
             opts) == 0) {  #ifdef MAPPED_ADDR_ENABLED
           if (inp->inp_socket->so_proto->pr_domain->dom_family == AF_INET6) {
                   in6_sin_2_v4mapsin6(&udpsrc, &mapped);
                   sa = (struct sockaddr *)&mapped;
           }
   #endif /* MAPPED_ADDR_ENABLED */
           if (sbappendaddr(&inp->inp_socket->so_rcv, sa, m, opts) == 0) {
                 udpstat.udps_fullsock++;                  udpstat.udps_fullsock++;
                 goto bad;                  goto bad;
         }          }
Line 337  bad:
Line 421  bad:
 }  }
   
 /*  /*
  * Create a "control" mbuf containing the specified data  
  * with the specified type for presentation with a datagram.  
  */  
 struct mbuf *  
 udp_saveopt(p, size, type)  
         caddr_t p;  
         register int size;  
         int type;  
 {  
         register struct cmsghdr *cp;  
         struct mbuf *m;  
   
         if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL)  
                 return ((struct mbuf *) NULL);  
         cp = (struct cmsghdr *) mtod(m, struct cmsghdr *);  
         bcopy(p, CMSG_DATA(cp), size);  
         size += sizeof(*cp);  
         m->m_len = size;  
         cp->cmsg_len = size;  
         cp->cmsg_level = IPPROTO_IP;  
         cp->cmsg_type = type;  
         return (m);  
 }  
   
 /*  
  * Notify a udp user of an asynchronous error;   * Notify a udp user of an asynchronous error;
  * just wake up so that he can collect error status.   * just wake up so that he can collect error status.
  */   */
Line 437  udp_output(m, va_alist)
Line 496  udp_output(m, va_alist)
         }          }
   
         /*          /*
            * Compute the packet length of the IP header, and
            * punt if the length looks bogus.
            */
           if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) {
                   error = EMSGSIZE;
                   goto release;
           }
   
           /*
          * Fill in mbuf with extended UDP header           * Fill in mbuf with extended UDP header
          * and addresses and length put into network format.           * and addresses and length put into network format.
          */           */
Line 462  udp_output(m, va_alist)
Line 530  udp_output(m, va_alist)
         ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */          ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */
         ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */          ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */
         udpstat.udps_opackets++;          udpstat.udps_opackets++;
   
   #ifdef IPSEC
           m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket;
   #endif /*IPSEC*/
   
         return (ip_output(m, inp->inp_options, &inp->inp_route,          return (ip_output(m, inp->inp_options, &inp->inp_route,
             inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),              inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
             inp->inp_moptions));              inp->inp_moptions));
Line 471  release:
Line 544  release:
         return (error);          return (error);
 }  }
   
 u_long  udp_sendspace = 9216;           /* really max datagram size */  int     udp_sendspace = 9216;           /* really max datagram size */
 u_long  udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));  int     udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
                                         /* 40 1K datagrams */                                          /* 40 1K datagrams */
   
 /*ARGSUSED*/  /*ARGSUSED*/
Line 523  udp_usrreq(so, req, m, nam, control, p)
Line 596  udp_usrreq(so, req, m, nam, control, p)
                         break;                          break;
                 inp = sotoinpcb(so);                  inp = sotoinpcb(so);
                 inp->inp_ip.ip_ttl = ip_defttl;                  inp->inp_ip.ip_ttl = ip_defttl;
   #ifdef IPSEC
                   inp = (struct inpcb *)so->so_pcb;
                   error = ipsec_init_policy(&inp->inp_sp);
   #endif /*IPSEC*/
                 break;                  break;
   
         case PRU_DETACH:          case PRU_DETACH:
Line 654  udp_sysctl(name, namelen, oldp, oldlenp,
Line 731  udp_sysctl(name, namelen, oldp, oldlenp,
         switch (name[0]) {          switch (name[0]) {
         case UDPCTL_CHECKSUM:          case UDPCTL_CHECKSUM:
                 return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum));                  return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum));
           case UDPCTL_SENDSPACE:
                   return (sysctl_int(oldp, oldlenp, newp, newlen,
                       &udp_sendspace));
           case UDPCTL_RECVSPACE:
                   return (sysctl_int(oldp, oldlenp, newp, newlen,
                       &udp_recvspace));
         default:          default:
                 return (ENOPROTOOPT);                  return (ENOPROTOOPT);
         }          }

Legend:
Removed from v.1.35  
changed lines
  Added in v.1.47.4.1

CVSweb <webmaster@jp.NetBSD.org>