version 1.235.2.4, 2015/12/27 12:10:05 |
version 1.236, 2015/04/03 20:01:07 |
|
|
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
__KERNEL_RCSID(0, "$NetBSD$"); |
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
#ifdef _KERNEL_OPT |
|
#include "opt_compat_netbsd.h" |
#include "opt_compat_netbsd.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" |
#include "opt_somaxkva.h" |
#include "opt_somaxkva.h" |
#include "opt_multiprocessor.h" /* XXX */ |
#include "opt_multiprocessor.h" /* XXX */ |
#include "opt_sctp.h" |
|
#endif |
|
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/systm.h> |
Line 632 sobind(struct socket *so, struct sockadd |
|
Line 629 sobind(struct socket *so, struct sockadd |
|
int error; |
int error; |
|
|
solock(so); |
solock(so); |
if (nam->sa_family != so->so_proto->pr_domain->dom_family) { |
|
sounlock(so); |
|
return EAFNOSUPPORT; |
|
} |
|
error = (*so->so_proto->pr_usrreqs->pr_bind)(so, nam, l); |
error = (*so->so_proto->pr_usrreqs->pr_bind)(so, nam, l); |
sounlock(so); |
sounlock(so); |
return error; |
return error; |
|
|
solisten(struct socket *so, int backlog, struct lwp *l) |
solisten(struct socket *so, int backlog, struct lwp *l) |
{ |
{ |
int error; |
int error; |
short oldopt, oldqlimit; |
|
|
|
solock(so); |
solock(so); |
if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | |
if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | |
SS_ISDISCONNECTING)) != 0) { |
SS_ISDISCONNECTING)) != 0) { |
sounlock(so); |
sounlock(so); |
return EINVAL; |
return EINVAL; |
} |
} |
oldopt = so->so_options; |
|
oldqlimit = so->so_qlimit; |
|
if (TAILQ_EMPTY(&so->so_q)) |
|
so->so_options |= SO_ACCEPTCONN; |
|
if (backlog < 0) |
|
backlog = 0; |
|
so->so_qlimit = min(backlog, somaxconn); |
|
|
|
error = (*so->so_proto->pr_usrreqs->pr_listen)(so, l); |
error = (*so->so_proto->pr_usrreqs->pr_listen)(so, l); |
if (error != 0) { |
if (error != 0) { |
so->so_options = oldopt; |
|
so->so_qlimit = oldqlimit; |
|
sounlock(so); |
sounlock(so); |
return error; |
return error; |
} |
} |
|
if (TAILQ_EMPTY(&so->so_q)) |
|
so->so_options |= SO_ACCEPTCONN; |
|
if (backlog < 0) |
|
backlog = 0; |
|
so->so_qlimit = min(backlog, somaxconn); |
sounlock(so); |
sounlock(so); |
return 0; |
return 0; |
} |
} |
Line 786 soabort(struct socket *so) |
|
Line 773 soabort(struct socket *so) |
|
{ |
{ |
u_int refs; |
u_int refs; |
int error; |
int error; |
|
|
KASSERT(solocked(so)); |
KASSERT(solocked(so)); |
KASSERT(so->so_head == NULL); |
KASSERT(so->so_head == NULL); |
|
|
Line 802 soabort(struct socket *so) |
|
Line 789 soabort(struct socket *so) |
|
} |
} |
|
|
int |
int |
soaccept(struct socket *so, struct sockaddr *nam) |
soaccept(struct socket *so, struct mbuf *nam) |
{ |
{ |
int error; |
int error; |
|
|
Line 820 soaccept(struct socket *so, struct socka |
|
Line 807 soaccept(struct socket *so, struct socka |
|
} |
} |
|
|
int |
int |
soconnect(struct socket *so, struct sockaddr *nam, struct lwp *l) |
soconnect(struct socket *so, struct mbuf *nam, struct lwp *l) |
{ |
{ |
int error; |
int error; |
|
|
Line 836 soconnect(struct socket *so, struct sock |
|
Line 823 soconnect(struct socket *so, struct sock |
|
*/ |
*/ |
if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && |
if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && |
((so->so_proto->pr_flags & PR_CONNREQUIRED) || |
((so->so_proto->pr_flags & PR_CONNREQUIRED) || |
(error = sodisconnect(so)))) { |
(error = sodisconnect(so)))) |
error = EISCONN; |
error = EISCONN; |
} else { |
else |
if (nam->sa_family != so->so_proto->pr_domain->dom_family) { |
|
return EAFNOSUPPORT; |
|
} |
|
error = (*so->so_proto->pr_usrreqs->pr_connect)(so, nam, l); |
error = (*so->so_proto->pr_usrreqs->pr_connect)(so, nam, l); |
} |
|
|
|
return error; |
return error; |
} |
} |
Line 892 sodisconnect(struct socket *so) |
|
Line 875 sodisconnect(struct socket *so) |
|
* Data and control buffers are freed on return. |
* Data and control buffers are freed on return. |
*/ |
*/ |
int |
int |
sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, |
sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top, |
struct mbuf *top, struct mbuf *control, int flags, struct lwp *l) |
struct mbuf *control, int flags, struct lwp *l) |
{ |
{ |
struct mbuf **mp, *m; |
struct mbuf **mp, *m; |
long space, len, resid, clen, mlen; |
long space, len, resid, clen, mlen; |
Line 950 sosend(struct socket *so, struct sockadd |
|
Line 933 sosend(struct socket *so, struct sockadd |
|
error = ENOTCONN; |
error = ENOTCONN; |
goto release; |
goto release; |
} |
} |
} else if (addr == NULL) { |
} else if (addr == 0) { |
error = EDESTADDRREQ; |
error = EDESTADDRREQ; |
goto release; |
goto release; |
} |
} |
Line 1064 sosend(struct socket *so, struct sockadd |
|
Line 1047 sosend(struct socket *so, struct sockadd |
|
so->so_options |= SO_DONTROUTE; |
so->so_options |= SO_DONTROUTE; |
if (resid > 0) |
if (resid > 0) |
so->so_state |= SS_MORETOCOME; |
so->so_state |= SS_MORETOCOME; |
if (flags & MSG_OOB) { |
if (flags & MSG_OOB) |
error = (*so->so_proto->pr_usrreqs->pr_sendoob)(so, |
error = (*so->so_proto->pr_usrreqs->pr_sendoob)(so, |
top, control); |
top, control); |
} else { |
else |
error = (*so->so_proto->pr_usrreqs->pr_send)(so, |
error = (*so->so_proto->pr_usrreqs->pr_send)(so, |
top, addr, control, l); |
top, addr, control, l); |
} |
|
if (dontroute) |
if (dontroute) |
so->so_options &= ~SO_DONTROUTE; |
so->so_options &= ~SO_DONTROUTE; |
if (resid > 0) |
if (resid > 0) |
Line 1330 soreceive(struct socket *so, struct mbuf |
|
Line 1312 soreceive(struct socket *so, struct mbuf |
|
sbsync(&so->so_rcv, nextrecord); |
sbsync(&so->so_rcv, nextrecord); |
} |
} |
} |
} |
if (pr->pr_flags & PR_ADDR_OPT) { |
|
/* |
|
* For SCTP we may be getting a |
|
* whole message OR a partial delivery. |
|
*/ |
|
if (m->m_type == MT_SONAME) { |
|
orig_resid = 0; |
|
if (flags & MSG_PEEK) { |
|
if (paddr) |
|
*paddr = m_copy(m, 0, m->m_len); |
|
m = m->m_next; |
|
} else { |
|
sbfree(&so->so_rcv, m); |
|
if (paddr) { |
|
*paddr = m; |
|
so->so_rcv.sb_mb = m->m_next; |
|
m->m_next = 0; |
|
m = so->so_rcv.sb_mb; |
|
} else { |
|
MFREE(m, so->so_rcv.sb_mb); |
|
m = so->so_rcv.sb_mb; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* |
/* |
* Process one or more MT_CONTROL mbufs present before any data mbufs |
* Process one or more MT_CONTROL mbufs present before any data mbufs |
Line 1489 soreceive(struct socket *so, struct mbuf |
|
Line 1446 soreceive(struct socket *so, struct mbuf |
|
if (len == m->m_len - moff) { |
if (len == m->m_len - moff) { |
if (m->m_flags & M_EOR) |
if (m->m_flags & M_EOR) |
flags |= MSG_EOR; |
flags |= MSG_EOR; |
#ifdef SCTP |
|
if (m->m_flags & M_NOTIFICATION) |
|
flags |= MSG_NOTIFICATION; |
|
#endif /* SCTP */ |
|
if (flags & MSG_PEEK) { |
if (flags & MSG_PEEK) { |
m = m->m_next; |
m = m->m_next; |
moff = 0; |
moff = 0; |
Line 1918 so_setsockopt(struct lwp *l, struct sock |
|
Line 1871 so_setsockopt(struct lwp *l, struct sock |
|
|
|
return error; |
return error; |
} |
} |
|
|
/* |
/* |
* internal get SOL_SOCKET options |
* internal get SOL_SOCKET options |
*/ |
*/ |
Line 2247 filt_soread(struct knote *kn, long hint) |
|
Line 2200 filt_soread(struct knote *kn, long hint) |
|
rv = 1; |
rv = 1; |
else if (kn->kn_sfflags & NOTE_LOWAT) |
else if (kn->kn_sfflags & NOTE_LOWAT) |
rv = (kn->kn_data >= kn->kn_sdata); |
rv = (kn->kn_data >= kn->kn_sdata); |
else |
else |
rv = (kn->kn_data >= so->so_rcv.sb_lowat); |
rv = (kn->kn_data >= so->so_rcv.sb_lowat); |
if (hint != NOTE_SUBMIT) |
if (hint != NOTE_SUBMIT) |
sounlock(so); |
sounlock(so); |