[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.118 and 1.135.2.1

version 1.118, 2006/05/14 21:15:12 version 1.135.2.1, 2007/07/11 20:10:18
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
 /*-  /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.   * Copyright (c) 2002, 2007 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
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/event.h>  #include <sys/event.h>
 #include <sys/poll.h>  #include <sys/poll.h>
 #include <sys/kauth.h>  #include <sys/kauth.h>
   #include <sys/mutex.h>
   #include <sys/condvar.h>
   
 #include <uvm/uvm.h>  #include <uvm/uvm.h>
   
 POOL_INIT(socket_pool, sizeof(struct socket), 0, 0, 0, "sockpl", NULL);  POOL_INIT(socket_pool, sizeof(struct socket), 0, 0, 0, "sockpl", NULL,
       IPL_SOFTNET);
   
 MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options");  MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options");
 MALLOC_DEFINE(M_SONAME, "soname", "socket name");  MALLOC_DEFINE(M_SONAME, "soname", "socket name");
Line 127  EVCNT_ATTACH_STATIC(sosend_kvalimit);
Line 130  EVCNT_ATTACH_STATIC(sosend_kvalimit);
   
 #endif /* SOSEND_COUNTERS */  #endif /* SOSEND_COUNTERS */
   
 void  static struct callback_entry sokva_reclaimerentry;
 soinit(void)  
 {  
   
         /* Set the initial adjusted socket buffer size. */  
         if (sb_max_set(sb_max))  
                 panic("bad initial sb_max value: %lu", sb_max);  
   
 }  
   
 #ifdef SOSEND_NO_LOAN  #ifdef SOSEND_NO_LOAN
 int use_sosend_loan = 0;  int sock_loan_thresh = -1;
 #else  #else
 int use_sosend_loan = 1;  int sock_loan_thresh = 4096;
 #endif  #endif
   
 static struct simplelock so_pendfree_slock = SIMPLELOCK_INITIALIZER;  static kmutex_t so_pendfree_lock;
 static struct mbuf *so_pendfree;  static struct mbuf *so_pendfree;
   
 #ifndef SOMAXKVA  #ifndef SOMAXKVA
Line 151  static struct mbuf *so_pendfree;
Line 146  static struct mbuf *so_pendfree;
 #endif  #endif
 int somaxkva = SOMAXKVA;  int somaxkva = SOMAXKVA;
 static int socurkva;  static int socurkva;
 static int sokvawaiters;  static kcondvar_t socurkva_cv;
   
 #define SOCK_LOAN_THRESH        4096  
 #define SOCK_LOAN_CHUNK         65536  #define SOCK_LOAN_CHUNK         65536
   
 static size_t sodopendfree(void);  static size_t sodopendfree(void);
Line 162  static size_t sodopendfreel(void);
Line 156  static size_t sodopendfreel(void);
 static vsize_t  static vsize_t
 sokvareserve(struct socket *so, vsize_t len)  sokvareserve(struct socket *so, vsize_t len)
 {  {
         int s;  
         int error;          int error;
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         while (socurkva + len > somaxkva) {          while (socurkva + len > somaxkva) {
                 size_t freed;                  size_t freed;
   
Line 184  sokvareserve(struct socket *so, vsize_t 
Line 176  sokvareserve(struct socket *so, vsize_t 
                         continue;                          continue;
   
                 SOSEND_COUNTER_INCR(&sosend_kvalimit);                  SOSEND_COUNTER_INCR(&sosend_kvalimit);
                 sokvawaiters++;                  error = cv_wait_sig(&socurkva_cv, &so_pendfree_lock);
                 error = ltsleep(&socurkva, PVM | PCATCH, "sokva", 0,  
                     &so_pendfree_slock);  
                 sokvawaiters--;  
                 if (error) {                  if (error) {
                         len = 0;                          len = 0;
                         break;                          break;
                 }                  }
         }          }
         socurkva += len;          socurkva += len;
         simple_unlock(&so_pendfree_slock);          mutex_exit(&so_pendfree_lock);
         splx(s);  
         return len;          return len;
 }  }
   
 static void  static void
 sokvaunreserve(vsize_t len)  sokvaunreserve(vsize_t len)
 {  {
         int s;  
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         socurkva -= len;          socurkva -= len;
         if (sokvawaiters)          cv_broadcast(&socurkva_cv);
                 wakeup(&socurkva);          mutex_exit(&so_pendfree_lock);
         simple_unlock(&so_pendfree_slock);  
         splx(s);  
 }  }
   
 /*  /*
Line 264  sokvafree(vaddr_t sva, vsize_t len)
Line 248  sokvafree(vaddr_t sva, vsize_t len)
 }  }
   
 static void  static void
 sodoloanfree(struct vm_page **pgs, caddr_t buf, size_t size)  sodoloanfree(struct vm_page **pgs, void *buf, size_t size)
 {  {
         vaddr_t va, sva, eva;          vaddr_t va, sva, eva;
         vsize_t len;          vsize_t len;
Line 280  sodoloanfree(struct vm_page **pgs, caddr
Line 264  sodoloanfree(struct vm_page **pgs, caddr
                 pgs = alloca(npgs * sizeof(*pgs));                  pgs = alloca(npgs * sizeof(*pgs));
   
                 for (i = 0, va = sva; va < eva; i++, va += PAGE_SIZE) {                  for (i = 0, va = sva; va < eva; i++, va += PAGE_SIZE) {
                         if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)                          if (pmap_extract(pmap_kernel(), va, &pa) == false)
                                 panic("sodoloanfree: va 0x%lx not mapped", va);                                  panic("sodoloanfree: va 0x%lx not mapped", va);
                         pgs[i] = PHYS_TO_VM_PAGE(pa);                          pgs[i] = PHYS_TO_VM_PAGE(pa);
                 }                  }
Line 295  sodoloanfree(struct vm_page **pgs, caddr
Line 279  sodoloanfree(struct vm_page **pgs, caddr
 static size_t  static size_t
 sodopendfree()  sodopendfree()
 {  {
         int s;  
         size_t rv;          size_t rv;
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         rv = sodopendfreel();          rv = sodopendfreel();
         simple_unlock(&so_pendfree_slock);          mutex_exit(&so_pendfree_lock);
         splx(s);  
   
         return rv;          return rv;
 }  }
   
 /*  /*
  * sodopendfreel: free mbufs on "pendfree" list.   * sodopendfreel: free mbufs on "pendfree" list.
  * unlock and relock so_pendfree_slock when freeing mbufs.   * unlock and relock so_pendfree_lock when freeing mbufs.
  *   *
  * => called with so_pendfree_slock held.   * => called with so_pendfree_lock held.
  * => called at splvm.  
  */   */
   
 static size_t  static size_t
 sodopendfreel()  sodopendfreel()
 {  {
           struct mbuf *m, *next;
         size_t rv = 0;          size_t rv = 0;
           int s;
   
         LOCK_ASSERT(simple_lock_held(&so_pendfree_slock));          KASSERT(mutex_owned(&so_pendfree_lock));
   
         for (;;) {  
                 struct mbuf *m;  
                 struct mbuf *next;  
   
           while (so_pendfree != NULL) {
                 m = so_pendfree;                  m = so_pendfree;
                 if (m == NULL)  
                         break;  
                 so_pendfree = NULL;                  so_pendfree = NULL;
                 simple_unlock(&so_pendfree_slock);                  mutex_exit(&so_pendfree_lock);
                 /* XXX splx */  
   
                 for (; m != NULL; m = next) {                  for (; m != NULL; m = next) {
                         next = m->m_next;                          next = m->m_next;
Line 340  sodopendfreel()
Line 316  sodopendfreel()
                         sodoloanfree((m->m_flags & M_EXT_PAGES) ?                          sodoloanfree((m->m_flags & M_EXT_PAGES) ?
                             m->m_ext.ext_pgs : NULL, m->m_ext.ext_buf,                              m->m_ext.ext_pgs : NULL, m->m_ext.ext_buf,
                             m->m_ext.ext_size);                              m->m_ext.ext_size);
                           s = splvm();
                         pool_cache_put(&mbpool_cache, m);                          pool_cache_put(&mbpool_cache, m);
                           splx(s);
                 }                  }
   
                 /* XXX splvm */                  mutex_enter(&so_pendfree_lock);
                 simple_lock(&so_pendfree_slock);  
         }          }
   
         return (rv);          return (rv);
 }  }
   
 void  void
 soloanfree(struct mbuf *m, caddr_t buf, size_t size, void *arg)  soloanfree(struct mbuf *m, void *buf, size_t size, void *arg)
 {  {
         int s;  
   
         if (m == NULL) {          if (m == NULL) {
   
Line 372  soloanfree(struct mbuf *m, caddr_t buf, 
Line 348  soloanfree(struct mbuf *m, caddr_t buf, 
          * because we need to put kva back to kernel_map.           * because we need to put kva back to kernel_map.
          */           */
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         m->m_next = so_pendfree;          m->m_next = so_pendfree;
         so_pendfree = m;          so_pendfree = m;
         if (sokvawaiters)          cv_broadcast(&socurkva_cv);
                 wakeup(&socurkva);          mutex_exit(&so_pendfree_lock);
         simple_unlock(&so_pendfree_slock);  
         splx(s);  
 }  }
   
 static long  static long
Line 425  sosend_loan(struct socket *so, struct ui
Line 398  sosend_loan(struct socket *so, struct ui
   
         lva += (vaddr_t) iov->iov_base & PAGE_MASK;          lva += (vaddr_t) iov->iov_base & PAGE_MASK;
   
         MEXTADD(m, (caddr_t) lva, space, M_MBUF, soloanfree, so);          MEXTADD(m, (void *) lva, space, M_MBUF, soloanfree, so);
         m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;          m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;
   
         uio->uio_resid -= space;          uio->uio_resid -= space;
         /* uio_offset not updated, not set/used for write(2) */          /* uio_offset not updated, not set/used for write(2) */
         uio->uio_iov->iov_base = (caddr_t) uio->uio_iov->iov_base + space;          uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + space;
         uio->uio_iov->iov_len -= space;          uio->uio_iov->iov_len -= space;
         if (uio->uio_iov->iov_len == 0) {          if (uio->uio_iov->iov_len == 0) {
                 uio->uio_iov++;                  uio->uio_iov++;
Line 440  sosend_loan(struct socket *so, struct ui
Line 413  sosend_loan(struct socket *so, struct ui
         return (space);          return (space);
 }  }
   
   static int
   sokva_reclaim_callback(struct callback_entry *ce, void *obj, void *arg)
   {
   
           KASSERT(ce == &sokva_reclaimerentry);
           KASSERT(obj == NULL);
   
           sodopendfree();
           if (!vm_map_starved_p(kernel_map)) {
                   return CALLBACK_CHAIN_ABORT;
           }
           return CALLBACK_CHAIN_CONTINUE;
   }
   
   void
   soinit(void)
   {
   
           mutex_init(&so_pendfree_lock, MUTEX_DRIVER, IPL_VM);
           cv_init(&socurkva_cv, "sokva");
   
           /* Set the initial adjusted socket buffer size. */
           if (sb_max_set(sb_max))
                   panic("bad initial sb_max value: %lu", sb_max);
   
           callback_register(&vm_map_to_kernel(kernel_map)->vmk_reclaim_callback,
               &sokva_reclaimerentry, NULL, sokva_reclaim_callback);
   }
   
 /*  /*
  * Socket operation routines.   * Socket operation routines.
  * These routines are called by the routines in   * These routines are called by the routines in
Line 456  socreate(int dom, struct socket **aso, i
Line 458  socreate(int dom, struct socket **aso, i
         uid_t           uid;          uid_t           uid;
         int             error, s;          int             error, s;
   
           error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_SOCKET,
               KAUTH_REQ_NETWORK_SOCKET_OPEN, KAUTH_ARG(dom), KAUTH_ARG(type),
               KAUTH_ARG(proto));
           if (error != 0)
                   return error;
   
         if (proto)          if (proto)
                 prp = pffindproto(dom, proto, type);                  prp = pffindproto(dom, proto, type);
         else          else
                 prp = pffindtype(dom, type);                  prp = pffindtype(dom, type);
         if (prp == 0 || prp->pr_usrreq == 0)          if (prp == NULL) {
                 return (EPROTONOSUPPORT);                  /* no support for domain */
                   if (pffinddomain(dom) == 0)
                           return EAFNOSUPPORT;
                   /* no support for socket type */
                   if (proto == 0 && type != 0)
                           return EPROTOTYPE;
                   return EPROTONOSUPPORT;
           }
           if (prp->pr_usrreq == NULL)
                   return EPROTONOSUPPORT;
         if (prp->pr_type != type)          if (prp->pr_type != type)
                 return (EPROTOTYPE);                  return EPROTOTYPE;
         s = splsoftnet();          s = splsoftnet();
         so = pool_get(&socket_pool, PR_WAITOK);          so = pool_get(&socket_pool, PR_WAITOK);
         memset((caddr_t)so, 0, sizeof(*so));          memset(so, 0, sizeof(*so));
         TAILQ_INIT(&so->so_q0);          TAILQ_INIT(&so->so_q0);
         TAILQ_INIT(&so->so_q);          TAILQ_INIT(&so->so_q);
         so->so_type = type;          so->so_type = type;
Line 478  socreate(int dom, struct socket **aso, i
Line 495  socreate(int dom, struct socket **aso, i
         so->so_snd.sb_mowner = &prp->pr_domain->dom_mowner;          so->so_snd.sb_mowner = &prp->pr_domain->dom_mowner;
         so->so_mowner = &prp->pr_domain->dom_mowner;          so->so_mowner = &prp->pr_domain->dom_mowner;
 #endif  #endif
         if (l != NULL) {          uid = kauth_cred_geteuid(l->l_cred);
                 uid = kauth_cred_geteuid(l->l_proc->p_cred);  
         } else {  
                 uid = 0;  
         }  
         so->so_uidinfo = uid_find(uid);          so->so_uidinfo = uid_find(uid);
         error = (*prp->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0,          error = (*prp->pr_usrreq)(so, PRU_ATTACH, NULL,
             (struct mbuf *)(long)proto, (struct mbuf *)0, l);              (struct mbuf *)(long)proto, NULL, l);
         if (error) {          if (error != 0) {
                 so->so_state |= SS_NOFDREF;                  so->so_state |= SS_NOFDREF;
                 sofree(so);                  sofree(so);
                 splx(s);                  splx(s);
                 return (error);                  return error;
         }          }
         splx(s);          splx(s);
         *aso = so;          *aso = so;
         return (0);          return 0;
 }  }
   
 int  int
Line 503  sobind(struct socket *so, struct mbuf *n
Line 516  sobind(struct socket *so, struct mbuf *n
         int     s, error;          int     s, error;
   
         s = splsoftnet();          s = splsoftnet();
         error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0,          error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, NULL, nam, NULL, l);
             nam, (struct mbuf *)0, l);  
         splx(s);          splx(s);
         return (error);          return error;
 }  }
   
 int  int
Line 515  solisten(struct socket *so, int backlog)
Line 527  solisten(struct socket *so, int backlog)
         int     s, error;          int     s, error;
   
         s = splsoftnet();          s = splsoftnet();
         error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, (struct mbuf *)0,          error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL,
             (struct mbuf *)0, (struct mbuf *)0, (struct lwp *)0);              NULL, NULL, NULL);
         if (error) {          if (error != 0) {
                 splx(s);                  splx(s);
                 return (error);                  return error;
         }          }
         if (TAILQ_EMPTY(&so->so_q))          if (TAILQ_EMPTY(&so->so_q))
                 so->so_options |= SO_ACCEPTCONN;                  so->so_options |= SO_ACCEPTCONN;
Line 527  solisten(struct socket *so, int backlog)
Line 539  solisten(struct socket *so, int backlog)
                 backlog = 0;                  backlog = 0;
         so->so_qlimit = min(backlog, somaxconn);          so->so_qlimit = min(backlog, somaxconn);
         splx(s);          splx(s);
         return (0);          return 0;
 }  }
   
 void  void
Line 592  soclose(struct socket *so)
Line 604  soclose(struct socket *so)
                             (so->so_state & SS_NBIO))                              (so->so_state & SS_NBIO))
                                 goto drop;                                  goto drop;
                         while (so->so_state & SS_ISCONNECTED) {                          while (so->so_state & SS_ISCONNECTED) {
                                 error = tsleep((caddr_t)&so->so_timeo,                                  error = tsleep((void *)&so->so_timeo,
                                                PSOCK | PCATCH, netcls,                                                 PSOCK | PCATCH, netcls,
                                                so->so_linger * hz);                                                 so->so_linger * hz);
                                 if (error)                                  if (error)
Line 603  soclose(struct socket *so)
Line 615  soclose(struct socket *so)
  drop:   drop:
         if (so->so_pcb) {          if (so->so_pcb) {
                 int error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,                  int error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
                     (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,                      NULL, NULL, NULL, NULL);
                     (struct lwp *)0);  
                 if (error == 0)                  if (error == 0)
                         error = error2;                          error = error2;
         }          }
Line 623  soclose(struct socket *so)
Line 634  soclose(struct socket *so)
 int  int
 soabort(struct socket *so)  soabort(struct socket *so)
 {  {
           int error;
   
         return (*so->so_proto->pr_usrreq)(so, PRU_ABORT, (struct mbuf *)0,          KASSERT(so->so_head == NULL);
             (struct mbuf *)0, (struct mbuf *)0, (struct lwp *)0);          error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, NULL,
               NULL, NULL, NULL);
           if (error) {
                   sofree(so);
           }
           return error;
 }  }
   
 int  int
Line 641  soaccept(struct socket *so, struct mbuf 
Line 658  soaccept(struct socket *so, struct mbuf 
         if ((so->so_state & SS_ISDISCONNECTED) == 0 ||          if ((so->so_state & SS_ISDISCONNECTED) == 0 ||
             (so->so_proto->pr_flags & PR_ABRTACPTDIS) == 0)              (so->so_proto->pr_flags & PR_ABRTACPTDIS) == 0)
                 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,                  error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
                     (struct mbuf *)0, nam, (struct mbuf *)0, (struct lwp *)0);                      NULL, nam, NULL, NULL);
         else          else
                 error = ECONNABORTED;                  error = ECONNABORTED;
   
Line 669  soconnect(struct socket *so, struct mbuf
Line 686  soconnect(struct socket *so, struct mbuf
                 error = EISCONN;                  error = EISCONN;
         else          else
                 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,                  error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
                     (struct mbuf *)0, nam, (struct mbuf *)0, l);                      NULL, nam, NULL, l);
         splx(s);          splx(s);
         return (error);          return (error);
 }  }
Line 681  soconnect2(struct socket *so1, struct so
Line 698  soconnect2(struct socket *so1, struct so
   
         s = splsoftnet();          s = splsoftnet();
         error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,          error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
             (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0,              NULL, (struct mbuf *)so2, NULL, NULL);
             (struct lwp *)0);  
         splx(s);          splx(s);
         return (error);          return (error);
 }  }
Line 702  sodisconnect(struct socket *so)
Line 718  sodisconnect(struct socket *so)
                 goto bad;                  goto bad;
         }          }
         error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,          error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
             (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,              NULL, NULL, NULL, NULL);
             (struct lwp *)0);  
  bad:   bad:
         splx(s);          splx(s);
         sodopendfree();          sodopendfree();
Line 820  sosend(struct socket *so, struct mbuf *a
Line 835  sosend(struct socket *so, struct mbuf *a
                                         m = m_gethdr(M_WAIT, MT_DATA);                                          m = m_gethdr(M_WAIT, MT_DATA);
                                         mlen = MHLEN;                                          mlen = MHLEN;
                                         m->m_pkthdr.len = 0;                                          m->m_pkthdr.len = 0;
                                         m->m_pkthdr.rcvif = (struct ifnet *)0;                                          m->m_pkthdr.rcvif = NULL;
                                 } else {                                  } else {
                                         m = m_get(M_WAIT, MT_DATA);                                          m = m_get(M_WAIT, MT_DATA);
                                         mlen = MLEN;                                          mlen = MLEN;
                                 }                                  }
                                 MCLAIM(m, so->so_snd.sb_mowner);                                  MCLAIM(m, so->so_snd.sb_mowner);
                                 if (use_sosend_loan &&                                  if (sock_loan_thresh >= 0 &&
                                     uio->uio_iov->iov_len >= SOCK_LOAN_THRESH &&                                      uio->uio_iov->iov_len >= sock_loan_thresh &&
                                     space >= SOCK_LOAN_THRESH &&                                      space >= sock_loan_thresh &&
                                     (len = sosend_loan(so, uio, m,                                      (len = sosend_loan(so, uio, m,
                                                        space)) != 0) {                                                         space)) != 0) {
                                         SOSEND_COUNTER_INCR(&sosend_loan_big);                                          SOSEND_COUNTER_INCR(&sosend_loan_big);
Line 860  sosend(struct socket *so, struct mbuf *a
Line 875  sosend(struct socket *so, struct mbuf *a
                                         if (atomic && top == 0 && len < mlen)                                          if (atomic && top == 0 && len < mlen)
                                                 MH_ALIGN(m, len);                                                  MH_ALIGN(m, len);
                                 }                                  }
                                 error = uiomove(mtod(m, caddr_t), (int)len,                                  error = uiomove(mtod(m, void *), (int)len,
                                     uio);                                      uio);
  have_data:   have_data:
                                 resid = uio->uio_resid;                                  resid = uio->uio_resid;
Line 961  soreceive(struct socket *so, struct mbuf
Line 976  soreceive(struct socket *so, struct mbuf
         if (flags & MSG_OOB) {          if (flags & MSG_OOB) {
                 m = m_get(M_WAIT, MT_DATA);                  m = m_get(M_WAIT, MT_DATA);
                 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,                  error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
                     (struct mbuf *)(long)(flags & MSG_PEEK),                      (struct mbuf *)(long)(flags & MSG_PEEK), NULL, l);
                     (struct mbuf *)0, l);  
                 if (error)                  if (error)
                         goto bad;                          goto bad;
                 do {                  do {
                         error = uiomove(mtod(m, caddr_t),                          error = uiomove(mtod(m, void *),
                             (int) min(uio->uio_resid, m->m_len), uio);                              (int) min(uio->uio_resid, m->m_len), uio);
                         m = m_free(m);                          m = m_free(m);
                 } while (uio->uio_resid && error == 0 && m);                  } while (uio->uio_resid && error == 0 && m);
Line 976  soreceive(struct socket *so, struct mbuf
Line 990  soreceive(struct socket *so, struct mbuf
                 return (error);                  return (error);
         }          }
         if (mp)          if (mp)
                 *mp = (struct mbuf *)0;                  *mp = NULL;
         if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)          if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
                 (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,                  (*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, l);
                     (struct mbuf *)0, (struct mbuf *)0, l);  
   
  restart:   restart:
         if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0)          if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0)
Line 1180  soreceive(struct socket *so, struct mbuf
Line 1193  soreceive(struct socket *so, struct mbuf
                         SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");                          SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");
                         SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");                          SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");
                         splx(s);                          splx(s);
                         error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);                          error = uiomove(mtod(m, char *) + moff, (int)len, uio);
                         s = splsoftnet();                          s = splsoftnet();
                         if (error) {                          if (error) {
                                 /*                                  /*
Line 1215  soreceive(struct socket *so, struct mbuf
Line 1228  soreceive(struct socket *so, struct mbuf
                                         *mp = m;                                          *mp = m;
                                         mp = &m->m_next;                                          mp = &m->m_next;
                                         so->so_rcv.sb_mb = m = m->m_next;                                          so->so_rcv.sb_mb = m = m->m_next;
                                         *mp = (struct mbuf *)0;                                          *mp = NULL;
                                 } else {                                  } else {
                                         MFREE(m, so->so_rcv.sb_mb);                                          MFREE(m, so->so_rcv.sb_mb);
                                         m = so->so_rcv.sb_mb;                                          m = so->so_rcv.sb_mb;
Line 1286  soreceive(struct socket *so, struct mbuf
Line 1299  soreceive(struct socket *so, struct mbuf
                          */                           */
                         if ((pr->pr_flags & PR_WANTRCVD) && so->so_pcb)                          if ((pr->pr_flags & PR_WANTRCVD) && so->so_pcb)
                                 (*pr->pr_usrreq)(so, PRU_RCVD,                                  (*pr->pr_usrreq)(so, PRU_RCVD,
                                     (struct mbuf *)0,                                      NULL, (struct mbuf *)(long)flags, NULL, l);
                                     (struct mbuf *)(long)flags,  
                                     (struct mbuf *)0, l);  
                         SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2");                          SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2");
                         SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2");                          SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2");
                         error = sbwait(&so->so_rcv);                          error = sbwait(&so->so_rcv);
Line 1324  soreceive(struct socket *so, struct mbuf
Line 1335  soreceive(struct socket *so, struct mbuf
                 SBLASTRECORDCHK(&so->so_rcv, "soreceive 4");                  SBLASTRECORDCHK(&so->so_rcv, "soreceive 4");
                 SBLASTMBUFCHK(&so->so_rcv, "soreceive 4");                  SBLASTMBUFCHK(&so->so_rcv, "soreceive 4");
                 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)                  if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
                         (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,                          (*pr->pr_usrreq)(so, PRU_RCVD, NULL,
                             (struct mbuf *)(long)flags, (struct mbuf *)0, l);                              (struct mbuf *)(long)flags, NULL, l);
         }          }
         if (orig_resid == uio->uio_resid && orig_resid &&          if (orig_resid == uio->uio_resid && orig_resid &&
             (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {              (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
Line 1354  soshutdown(struct socket *so, int how)
Line 1365  soshutdown(struct socket *so, int how)
         if (how == SHUT_RD || how == SHUT_RDWR)          if (how == SHUT_RD || how == SHUT_RDWR)
                 sorflush(so);                  sorflush(so);
         if (how == SHUT_WR || how == SHUT_RDWR)          if (how == SHUT_WR || how == SHUT_RDWR)
                 return (*pr->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0,                  return (*pr->pr_usrreq)(so, PRU_SHUTDOWN, NULL,
                     (struct mbuf *)0, (struct mbuf *)0, (struct lwp *)0);                      NULL, NULL, NULL);
         return (0);          return (0);
 }  }
   
Line 1391  sosetopt(struct socket *so, int level, i
Line 1402  sosetopt(struct socket *so, int level, i
 {  {
         int             error;          int             error;
         struct mbuf     *m;          struct mbuf     *m;
           struct linger   *l;
   
         error = 0;          error = 0;
         m = m0;          m = m0;
Line 1407  sosetopt(struct socket *so, int level, i
Line 1419  sosetopt(struct socket *so, int level, i
                                 error = EINVAL;                                  error = EINVAL;
                                 goto bad;                                  goto bad;
                         }                          }
                         if (mtod(m, struct linger *)->l_linger < 0 ||                          l = mtod(m, struct linger *);
                             mtod(m, struct linger *)->l_linger > (INT_MAX / hz)) {                          if (l->l_linger < 0 || l->l_linger > USHRT_MAX ||
                               l->l_linger > (INT_MAX / hz)) {
                                 error = EDOM;                                  error = EDOM;
                                 goto bad;                                  goto bad;
                         }                          }
                         so->so_linger = mtod(m, struct linger *)->l_linger;                          so->so_linger = l->l_linger;
                         /* fall thru... */                          if (l->l_onoff)
                                   so->so_options |= SO_LINGER;
                           else
                                   so->so_options &= ~SO_LINGER;
                           break;
   
                 case SO_DEBUG:                  case SO_DEBUG:
                 case SO_KEEPALIVE:                  case SO_KEEPALIVE:
Line 1553  sogetopt(struct socket *so, int level, i
Line 1570  sogetopt(struct socket *so, int level, i
                 case SO_LINGER:                  case SO_LINGER:
                         m->m_len = sizeof(struct linger);                          m->m_len = sizeof(struct linger);
                         mtod(m, struct linger *)->l_onoff =                          mtod(m, struct linger *)->l_onoff =
                                 so->so_options & SO_LINGER;                              (so->so_options & SO_LINGER) ? 1 : 0;
                         mtod(m, struct linger *)->l_linger = so->so_linger;                          mtod(m, struct linger *)->l_linger = so->so_linger;
                         break;                          break;
   
Line 1566  sogetopt(struct socket *so, int level, i
Line 1583  sogetopt(struct socket *so, int level, i
                 case SO_BROADCAST:                  case SO_BROADCAST:
                 case SO_OOBINLINE:                  case SO_OOBINLINE:
                 case SO_TIMESTAMP:                  case SO_TIMESTAMP:
                         *mtod(m, int *) = so->so_options & optname;                          *mtod(m, int *) = (so->so_options & optname) ? 1 : 0;
                         break;                          break;
   
                 case SO_TYPE:                  case SO_TYPE:
Line 1756  sysctl_kern_somaxkva(SYSCTLFN_ARGS)
Line 1773  sysctl_kern_somaxkva(SYSCTLFN_ARGS)
 {  {
         int error, new_somaxkva;          int error, new_somaxkva;
         struct sysctlnode node;          struct sysctlnode node;
         int s;  
   
         new_somaxkva = somaxkva;          new_somaxkva = somaxkva;
         node = *rnode;          node = *rnode;
Line 1768  sysctl_kern_somaxkva(SYSCTLFN_ARGS)
Line 1784  sysctl_kern_somaxkva(SYSCTLFN_ARGS)
         if (new_somaxkva < (16 * 1024 * 1024)) /* sanity */          if (new_somaxkva < (16 * 1024 * 1024)) /* sanity */
                 return (EINVAL);                  return (EINVAL);
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         somaxkva = new_somaxkva;          somaxkva = new_somaxkva;
         wakeup(&socurkva);          cv_broadcast(&socurkva_cv);
         simple_unlock(&so_pendfree_slock);          mutex_exit(&so_pendfree_lock);
         splx(s);  
   
         return (error);          return (error);
 }  }

Legend:
Removed from v.1.118  
changed lines
  Added in v.1.135.2.1

CVSweb <webmaster@jp.NetBSD.org>