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

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

Diff for /src/sys/kern/uipc_socket.c between version 1.164.2.2 and 1.177.4.3

version 1.164.2.2, 2008/09/18 04:31:44 version 1.177.4.3, 2009/05/03 13:18:55
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
 /*-  /*-
  * Copyright (c) 2002, 2007, 2008 The NetBSD Foundation, Inc.   * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc.
  * All rights reserved.   * All rights reserved.
  *   *
  * This code is derived from software contributed to The NetBSD Foundation   * This code is derived from software contributed to The NetBSD Foundation
  * by Jason R. Thorpe of Wasabi Systems, Inc.   * by Jason R. Thorpe of Wasabi Systems, Inc, and by Andrew Doran.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 65 
Line 65 
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD$");  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include "opt_inet.h"  
 #include "opt_sock_counters.h"  #include "opt_sock_counters.h"
 #include "opt_sosend_loan.h"  #include "opt_sosend_loan.h"
 #include "opt_mbuftrace.h"  #include "opt_mbuftrace.h"
Line 77  __KERNEL_RCSID(0, "$NetBSD$");
Line 76  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/proc.h>  #include <sys/proc.h>
 #include <sys/file.h>  #include <sys/file.h>
 #include <sys/filedesc.h>  #include <sys/filedesc.h>
 #include <sys/malloc.h>  #include <sys/kmem.h>
 #include <sys/mbuf.h>  #include <sys/mbuf.h>
 #include <sys/domain.h>  #include <sys/domain.h>
 #include <sys/kernel.h>  #include <sys/kernel.h>
Line 86  __KERNEL_RCSID(0, "$NetBSD$");
Line 85  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/socketvar.h>  #include <sys/socketvar.h>
 #include <sys/signalvar.h>  #include <sys/signalvar.h>
 #include <sys/resourcevar.h>  #include <sys/resourcevar.h>
   #include <sys/uidinfo.h>
 #include <sys/event.h>  #include <sys/event.h>
 #include <sys/poll.h>  #include <sys/poll.h>
 #include <sys/kauth.h>  #include <sys/kauth.h>
Line 614  sofree(struct socket *so)
Line 614  sofree(struct socket *so)
         KASSERT(!cv_has_waiters(&so->so_snd.sb_cv));          KASSERT(!cv_has_waiters(&so->so_snd.sb_cv));
         sorflush(so);          sorflush(so);
         refs = so->so_aborting; /* XXX */          refs = so->so_aborting; /* XXX */
 #ifdef INET          /* Remove acccept filter if one is present. */
         /* remove acccept filter if one is present. */  
         if (so->so_accf != NULL)          if (so->so_accf != NULL)
                 do_setopt_accept_filter(so, NULL);                  (void)accept_filt_clear(so);
 #endif  
         sounlock(so);          sounlock(so);
         if (refs == 0)          /* XXX */          if (refs == 0)          /* XXX */
                 soput(so);                  soput(so);
Line 639  soclose(struct socket *so)
Line 637  soclose(struct socket *so)
         error = 0;          error = 0;
         solock(so);          solock(so);
         if (so->so_options & SO_ACCEPTCONN) {          if (so->so_options & SO_ACCEPTCONN) {
                 do {                  for (;;) {
                         while ((so2 = TAILQ_FIRST(&so->so_q0)) != 0) {                          if ((so2 = TAILQ_FIRST(&so->so_q0)) != 0) {
                                 KASSERT(solocked2(so, so2));                                  KASSERT(solocked2(so, so2));
                                 (void) soqremque(so2, 0);                                  (void) soqremque(so2, 0);
                                 /* soabort drops the lock. */                                  /* soabort drops the lock. */
                                 (void) soabort(so2);                                  (void) soabort(so2);
                                 solock(so);                                  solock(so);
                                   continue;
                         }                          }
                         while ((so2 = TAILQ_FIRST(&so->so_q)) != 0) {                          if ((so2 = TAILQ_FIRST(&so->so_q)) != 0) {
                                 KASSERT(solocked2(so, so2));                                  KASSERT(solocked2(so, so2));
                                 (void) soqremque(so2, 1);                                  (void) soqremque(so2, 1);
                                 /* soabort drops the lock. */                                  /* soabort drops the lock. */
                                 (void) soabort(so2);                                  (void) soabort(so2);
                                 solock(so);                                  solock(so);
                                   continue;
                         }                          }
                 } while (!TAILQ_EMPTY(&so->so_q0));                          break;
                   }
         }          }
         if (so->so_pcb == 0)          if (so->so_pcb == 0)
                 goto discard;                  goto discard;
Line 668  soclose(struct socket *so)
Line 669  soclose(struct socket *so)
                         if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio)                          if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio)
                                 goto drop;                                  goto drop;
                         while (so->so_state & SS_ISCONNECTED) {                          while (so->so_state & SS_ISCONNECTED) {
                                 error = sowait(so, so->so_linger * hz);                                  error = sowait(so, true, so->so_linger * hz);
                                 if (error)                                  if (error)
                                         break;                                          break;
                         }                          }
Line 1535  soshutdown(struct socket *so, int how)
Line 1536  soshutdown(struct socket *so, int how)
         return error;          return error;
 }  }
   
   int
   sodrain(struct socket *so)
   {
           int error;
   
           solock(so);
           so->so_state |= SS_ISDRAINING;
           cv_broadcast(&so->so_cv);
           error = soshutdown(so, SHUT_RDWR);
           sounlock(so);
   
           return error;
   }
   
 void  void
 sorflush(struct socket *so)  sorflush(struct socket *so)
 {  {
Line 1576  sosetopt1(struct socket *so, const struc
Line 1591  sosetopt1(struct socket *so, const struc
   
         switch (sopt->sopt_name) {          switch (sopt->sopt_name) {
   
 #ifdef INET  
         case SO_ACCEPTFILTER:          case SO_ACCEPTFILTER:
                 error = do_setopt_accept_filter(so, sopt);                  error = accept_filt_setopt(so, sopt);
                 if (error)                  KASSERT(solocked(so));
                         return error;  
                 break;                  break;
 #endif  
   
         case SO_LINGER:          case SO_LINGER:
                 error = sockopt_get(sopt, &l, sizeof(l));                  error = sockopt_get(sopt, &l, sizeof(l));
                   solock(so);
                 if (error)                  if (error)
                         return (error);                          break;
   
                 if (l.l_linger < 0 || l.l_linger > USHRT_MAX ||                  if (l.l_linger < 0 || l.l_linger > USHRT_MAX ||
                     l.l_linger > (INT_MAX / hz))                      l.l_linger > (INT_MAX / hz)) {
                         return EDOM;                          error = EDOM;
                           break;
                   }
                 so->so_linger = l.l_linger;                  so->so_linger = l.l_linger;
                 if (l.l_onoff)                  if (l.l_onoff)
                         so->so_options |= SO_LINGER;                          so->so_options |= SO_LINGER;
                 else                  else
                         so->so_options &= ~SO_LINGER;                          so->so_options &= ~SO_LINGER;
                   break;
                 break;  
   
         case SO_DEBUG:          case SO_DEBUG:
         case SO_KEEPALIVE:          case SO_KEEPALIVE:
Line 1610  sosetopt1(struct socket *so, const struc
Line 1623  sosetopt1(struct socket *so, const struc
         case SO_OOBINLINE:          case SO_OOBINLINE:
         case SO_TIMESTAMP:          case SO_TIMESTAMP:
                 error = sockopt_getint(sopt, &optval);                  error = sockopt_getint(sopt, &optval);
                   solock(so);
                 if (error)                  if (error)
                         return (error);                          break;
   
                 if (optval)                  if (optval)
                         so->so_options |= sopt->sopt_name;                          so->so_options |= sopt->sopt_name;
                 else                  else
Line 1624  sosetopt1(struct socket *so, const struc
Line 1637  sosetopt1(struct socket *so, const struc
         case SO_SNDLOWAT:          case SO_SNDLOWAT:
         case SO_RCVLOWAT:          case SO_RCVLOWAT:
                 error = sockopt_getint(sopt, &optval);                  error = sockopt_getint(sopt, &optval);
                   solock(so);
                 if (error)                  if (error)
                         return (error);                          break;
   
                 /*                  /*
                  * Values < 1 make no sense for any of these                   * Values < 1 make no sense for any of these
                  * options, so disallow them.                   * options, so disallow them.
                  */                   */
                 if (optval < 1)                  if (optval < 1) {
                         return EINVAL;                          error = EINVAL;
                           break;
                   }
   
                 switch (sopt->sopt_name) {                  switch (sopt->sopt_name) {
                 case SO_SNDBUF:                  case SO_SNDBUF:
                         if (sbreserve(&so->so_snd, (u_long)optval, so) == 0)                          if (sbreserve(&so->so_snd, (u_long)optval, so) == 0) {
                                 return ENOBUFS;                                  error = ENOBUFS;
                                   break;
                           }
                         so->so_snd.sb_flags &= ~SB_AUTOSIZE;                          so->so_snd.sb_flags &= ~SB_AUTOSIZE;
                         break;                          break;
   
                 case SO_RCVBUF:                  case SO_RCVBUF:
                         if (sbreserve(&so->so_rcv, (u_long)optval, so) == 0)                          if (sbreserve(&so->so_rcv, (u_long)optval, so) == 0) {
                                 return ENOBUFS;                                  error = ENOBUFS;
                                   break;
                           }
                         so->so_rcv.sb_flags &= ~SB_AUTOSIZE;                          so->so_rcv.sb_flags &= ~SB_AUTOSIZE;
                         break;                          break;
   
Line 1672  sosetopt1(struct socket *so, const struc
Line 1690  sosetopt1(struct socket *so, const struc
         case SO_SNDTIMEO:          case SO_SNDTIMEO:
         case SO_RCVTIMEO:          case SO_RCVTIMEO:
                 error = sockopt_get(sopt, &tv, sizeof(tv));                  error = sockopt_get(sopt, &tv, sizeof(tv));
                   solock(so);
                 if (error)                  if (error)
                         return (error);                          break;
   
                 if (tv.tv_sec > (INT_MAX - tv.tv_usec / tick) / hz)                  if (tv.tv_sec > (INT_MAX - tv.tv_usec / tick) / hz) {
                         return EDOM;                          error = EDOM;
                           break;
                   }
   
                 optval = tv.tv_sec * hz + tv.tv_usec / tick;                  optval = tv.tv_sec * hz + tv.tv_usec / tick;
                 if (optval == 0 && tv.tv_usec != 0)                  if (optval == 0 && tv.tv_usec != 0)
Line 1693  sosetopt1(struct socket *so, const struc
Line 1714  sosetopt1(struct socket *so, const struc
                 break;                  break;
   
         default:          default:
                 return ENOPROTOOPT;                  solock(so);
                   error = ENOPROTOOPT;
                   break;
         }          }
         return 0;          KASSERT(solocked(so));
           return error;
 }  }
   
 int  int
Line 1703  sosetopt(struct socket *so, struct socko
Line 1727  sosetopt(struct socket *so, struct socko
 {  {
         int error, prerr;          int error, prerr;
   
         solock(so);          if (sopt->sopt_level == SOL_SOCKET) {
         if (sopt->sopt_level == SOL_SOCKET)  
                 error = sosetopt1(so, sopt);                  error = sosetopt1(so, sopt);
         else                  KASSERT(solocked(so));
           } else {
                 error = ENOPROTOOPT;                  error = ENOPROTOOPT;
                   solock(so);
           }
   
         if ((error == 0 || error == ENOPROTOOPT) &&          if ((error == 0 || error == ENOPROTOOPT) &&
             so->so_proto != NULL && so->so_proto->pr_ctloutput != NULL) {              so->so_proto != NULL && so->so_proto->pr_ctloutput != NULL) {
Line 1756  sogetopt1(struct socket *so, struct sock
Line 1782  sogetopt1(struct socket *so, struct sock
   
         switch (sopt->sopt_name) {          switch (sopt->sopt_name) {
   
 #ifdef INET  
         case SO_ACCEPTFILTER:          case SO_ACCEPTFILTER:
                 error = do_getopt_accept_filter(so, sopt);                  error = accept_filt_getopt(so, sopt);
                 break;                  break;
 #endif  
   
         case SO_LINGER:          case SO_LINGER:
                 l.l_onoff = (so->so_options & SO_LINGER) ? 1 : 0;                  l.l_onoff = (so->so_options & SO_LINGER) ? 1 : 0;
Line 1853  sogetopt(struct socket *so, struct socko
Line 1877  sogetopt(struct socket *so, struct socko
  * alloc sockopt data buffer buffer   * alloc sockopt data buffer buffer
  *      - will be released at destroy   *      - will be released at destroy
  */   */
 static void  static int
 sockopt_alloc(struct sockopt *sopt, size_t len)  sockopt_alloc(struct sockopt *sopt, size_t len, km_flag_t kmflag)
 {  {
   
         KASSERT(sopt->sopt_size == 0);          KASSERT(sopt->sopt_size == 0);
   
         if (len > sizeof(sopt->sopt_buf))          if (len > sizeof(sopt->sopt_buf)) {
                 sopt->sopt_data = malloc(len, M_SOOPTS, M_WAITOK | M_ZERO);                  sopt->sopt_data = kmem_zalloc(len, kmflag);
         else                  if (sopt->sopt_data == NULL)
                           return ENOMEM;
           } else
                 sopt->sopt_data = sopt->sopt_buf;                  sopt->sopt_data = sopt->sopt_buf;
   
         sopt->sopt_size = len;          sopt->sopt_size = len;
           return 0;
 }  }
   
 /*  /*
  * initialise sockopt storage   * initialise sockopt storage
    *      - MAY sleep during allocation
  */   */
 void  void
 sockopt_init(struct sockopt *sopt, int level, int name, size_t size)  sockopt_init(struct sockopt *sopt, int level, int name, size_t size)
Line 1878  sockopt_init(struct sockopt *sopt, int l
Line 1906  sockopt_init(struct sockopt *sopt, int l
   
         sopt->sopt_level = level;          sopt->sopt_level = level;
         sopt->sopt_name = name;          sopt->sopt_name = name;
         sockopt_alloc(sopt, size);          (void)sockopt_alloc(sopt, size, KM_SLEEP);
 }  }
   
 /*  /*
Line 1890  sockopt_destroy(struct sockopt *sopt)
Line 1918  sockopt_destroy(struct sockopt *sopt)
 {  {
   
         if (sopt->sopt_data != sopt->sopt_buf)          if (sopt->sopt_data != sopt->sopt_buf)
                 free(sopt->sopt_data, M_SOOPTS);                  kmem_free(sopt->sopt_data, sopt->sopt_size);
   
         memset(sopt, 0, sizeof(*sopt));          memset(sopt, 0, sizeof(*sopt));
 }  }
Line 1898  sockopt_destroy(struct sockopt *sopt)
Line 1926  sockopt_destroy(struct sockopt *sopt)
 /*  /*
  * set sockopt value   * set sockopt value
  *      - value is copied into sockopt   *      - value is copied into sockopt
  *      - memory is allocated when necessary   *      - memory is allocated when necessary, will not sleep
  */   */
 int  int
 sockopt_set(struct sockopt *sopt, const void *buf, size_t len)  sockopt_set(struct sockopt *sopt, const void *buf, size_t len)
 {  {
           int error;
   
         if (sopt->sopt_size == 0)          if (sopt->sopt_size == 0) {
                 sockopt_alloc(sopt, len);                  error = sockopt_alloc(sopt, len, KM_NOSLEEP);
                   if (error)
                           return error;
           }
   
         KASSERT(sopt->sopt_size == len);          KASSERT(sopt->sopt_size == len);
         memcpy(sopt->sopt_data, buf, len);          memcpy(sopt->sopt_data, buf, len);
Line 1951  sockopt_getint(const struct sockopt *sop
Line 1983  sockopt_getint(const struct sockopt *sop
  * set sockopt value from mbuf   * set sockopt value from mbuf
  *      - ONLY for legacy code   *      - ONLY for legacy code
  *      - mbuf is released by sockopt   *      - mbuf is released by sockopt
    *      - will not sleep
  */   */
 int  int
 sockopt_setmbuf(struct sockopt *sopt, struct mbuf *m)  sockopt_setmbuf(struct sockopt *sopt, struct mbuf *m)
 {  {
         size_t len;          size_t len;
           int error;
   
         len = m_length(m);          len = m_length(m);
   
         if (sopt->sopt_size == 0)          if (sopt->sopt_size == 0) {
                 sockopt_alloc(sopt, len);                  error = sockopt_alloc(sopt, len, KM_NOSLEEP);
                   if (error)
                           return error;
           }
   
         KASSERT(sopt->sopt_size == len);          KASSERT(sopt->sopt_size == len);
         m_copydata(m, 0, len, sopt->sopt_data);          m_copydata(m, 0, len, sopt->sopt_data);
Line 1973  sockopt_setmbuf(struct sockopt *sopt, st
Line 2010  sockopt_setmbuf(struct sockopt *sopt, st
  * get sockopt value into mbuf   * get sockopt value into mbuf
  *      - ONLY for legacy code   *      - ONLY for legacy code
  *      - mbuf to be released by the caller   *      - mbuf to be released by the caller
    *      - will not sleep
  */   */
 struct mbuf *  struct mbuf *
 sockopt_getmbuf(const struct sockopt *sopt)  sockopt_getmbuf(const struct sockopt *sopt)
 {  {
         struct mbuf *m;          struct mbuf *m;
   
         m = m_get(M_WAIT, MT_SOOPTS);          if (sopt->sopt_size > MCLBYTES)
         if (m == NULL)  
                 return NULL;                  return NULL;
   
         m->m_len = MLEN;          m = m_get(M_DONTWAIT, MT_SOOPTS);
         m_copyback(m, 0, sopt->sopt_size, sopt->sopt_data);          if (m == NULL)
         if (m_length(m) != max(sopt->sopt_size, MLEN)) {  
                 m_freem(m);  
                 return NULL;                  return NULL;
   
           if (sopt->sopt_size > MLEN) {
                   MCLGET(m, M_DONTWAIT);
                   if ((m->m_flags & M_EXT) == 0) {
                           m_free(m);
                           return NULL;
                   }
         }          }
         m->m_len = min(sopt->sopt_size, MLEN);  
           memcpy(mtod(m, void *), sopt->sopt_data, sopt->sopt_size);
           m->m_len = sopt->sopt_size;
   
         return m;          return m;
 }  }
Line 1999  sohasoutofband(struct socket *so)
Line 2043  sohasoutofband(struct socket *so)
 {  {
   
         fownsignal(so->so_pgid, SIGURG, POLL_PRI, POLLPRI|POLLRDBAND, so);          fownsignal(so->so_pgid, SIGURG, POLL_PRI, POLLPRI|POLLRDBAND, so);
         selnotify(&so->so_rcv.sb_sel, POLLPRI | POLLRDBAND, 0);          selnotify(&so->so_rcv.sb_sel, POLLPRI | POLLRDBAND, NOTE_SUBMIT);
 }  }
   
 static void  static void

Legend:
Removed from v.1.164.2.2  
changed lines
  Added in v.1.177.4.3

CVSweb <webmaster@jp.NetBSD.org>