[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.175 and 1.177.4.3

version 1.175, 2008/10/11 16:39:07 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 615  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 */
         /* 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);
         sounlock(so);          sounlock(so);
         if (refs == 0)          /* XXX */          if (refs == 0)          /* XXX */
                 soput(so);                  soput(so);
Line 670  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 1537  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 1579  sosetopt1(struct socket *so, const struc
Line 1592  sosetopt1(struct socket *so, const struc
         switch (sopt->sopt_name) {          switch (sopt->sopt_name) {
   
         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;
   
         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 1757  sogetopt1(struct socket *so, struct sock
Line 1783  sogetopt1(struct socket *so, struct sock
         switch (sopt->sopt_name) {          switch (sopt->sopt_name) {
   
         case SO_ACCEPTFILTER:          case SO_ACCEPTFILTER:
                 error = do_getopt_accept_filter(so, sopt);                  error = accept_filt_getopt(so, sopt);
                 break;                  break;
   
         case SO_LINGER:          case SO_LINGER:
Line 1851  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 = kmem_zalloc(len, KM_SLEEP);                  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 1876  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 1896  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 1949  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 1971  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 1997  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.175  
changed lines
  Added in v.1.177.4.3

CVSweb <webmaster@jp.NetBSD.org>