| version 1.53, 2001/02/07 12:20:43 |
version 1.54, 2001/02/27 05:19:13 |
|
|
| #include <sys/resourcevar.h> |
#include <sys/resourcevar.h> |
| #include <sys/pool.h> |
#include <sys/pool.h> |
| |
|
| struct pool socket_pool; |
struct pool socket_pool; |
| |
|
| extern int somaxconn; /* patchable (XXX sysctl) */ |
extern int somaxconn; /* patchable (XXX sysctl) */ |
| int somaxconn = SOMAXCONN; |
int somaxconn = SOMAXCONN; |
| |
|
| void |
void |
| soinit() |
soinit(void) |
| { |
{ |
| |
|
| pool_init(&socket_pool, sizeof(struct socket), 0, 0, 0, |
pool_init(&socket_pool, sizeof(struct socket), 0, 0, 0, |
|
|
| */ |
*/ |
| /*ARGSUSED*/ |
/*ARGSUSED*/ |
| int |
int |
| socreate(dom, aso, type, proto) |
socreate(int dom, struct socket **aso, int type, int proto) |
| int dom; |
|
| struct socket **aso; |
|
| int type; |
|
| int proto; |
|
| { |
{ |
| struct proc *p = curproc; /* XXX */ |
struct proc *p; |
| struct protosw *prp; |
struct protosw *prp; |
| struct socket *so; |
struct socket *so; |
| int error; |
int error, s; |
| int s; |
|
| |
|
| |
p = curproc; /* XXX */ |
| if (proto) |
if (proto) |
| prp = pffindproto(dom, proto, type); |
prp = pffindproto(dom, proto, type); |
| else |
else |
| Line 126 socreate(dom, aso, type, proto) |
|
| Line 122 socreate(dom, aso, type, proto) |
|
| } |
} |
| |
|
| int |
int |
| sobind(so, nam, p) |
sobind(struct socket *so, struct mbuf *nam, struct proc *p) |
| struct socket *so; |
|
| struct mbuf *nam; |
|
| struct proc *p; |
|
| { |
{ |
| int s = splsoftnet(); |
int s, error; |
| int error; |
|
| |
|
| |
s = splsoftnet(); |
| error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, |
error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, |
| nam, (struct mbuf *)0, p); |
nam, (struct mbuf *)0, p); |
| splx(s); |
splx(s); |
| Line 141 sobind(so, nam, p) |
|
| Line 134 sobind(so, nam, p) |
|
| } |
} |
| |
|
| int |
int |
| solisten(so, backlog) |
solisten(struct socket *so, int backlog) |
| struct socket *so; |
|
| int backlog; |
|
| { |
{ |
| int s = splsoftnet(), error; |
int s, error; |
| |
|
| |
s = splsoftnet(); |
| error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, (struct mbuf *)0, |
error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, (struct mbuf *)0, |
| (struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); |
(struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); |
| if (error) { |
if (error) { |
| Line 163 solisten(so, backlog) |
|
| Line 155 solisten(so, backlog) |
|
| } |
} |
| |
|
| void |
void |
| sofree(so) |
sofree(struct socket *so) |
| struct socket *so; |
|
| { |
{ |
| |
|
| if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) |
if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) |
|
|
| * Free socket when disconnect complete. |
* Free socket when disconnect complete. |
| */ |
*/ |
| int |
int |
| soclose(so) |
soclose(struct socket *so) |
| struct socket *so; |
|
| { |
{ |
| struct socket *so2; |
struct socket *so2; |
| int s = splsoftnet(); /* conservative */ |
int s, error; |
| int error = 0; |
|
| |
|
| |
error = 0; |
| |
s = splsoftnet(); /* conservative */ |
| if (so->so_options & SO_ACCEPTCONN) { |
if (so->so_options & SO_ACCEPTCONN) { |
| while ((so2 = so->so_q0.tqh_first) != 0) { |
while ((so2 = so->so_q0.tqh_first) != 0) { |
| (void) soqremque(so2, 0); |
(void) soqremque(so2, 0); |
|
|
| } |
} |
| } |
} |
| } |
} |
| 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, |
(struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0, |
|
|
| if (error == 0) |
if (error == 0) |
| error = error2; |
error = error2; |
| } |
} |
| discard: |
discard: |
| if (so->so_state & SS_NOFDREF) |
if (so->so_state & SS_NOFDREF) |
| panic("soclose: NOFDREF"); |
panic("soclose: NOFDREF"); |
| so->so_state |= SS_NOFDREF; |
so->so_state |= SS_NOFDREF; |
|
|
| * Must be called at splsoftnet... |
* Must be called at splsoftnet... |
| */ |
*/ |
| int |
int |
| soabort(so) |
soabort(struct socket *so) |
| struct socket *so; |
|
| { |
{ |
| |
|
| return (*so->so_proto->pr_usrreq)(so, PRU_ABORT, (struct mbuf *)0, |
return (*so->so_proto->pr_usrreq)(so, PRU_ABORT, (struct mbuf *)0, |
|
|
| } |
} |
| |
|
| int |
int |
| soaccept(so, nam) |
soaccept(struct socket *so, struct mbuf *nam) |
| struct socket *so; |
|
| struct mbuf *nam; |
|
| { |
{ |
| int s = splsoftnet(); |
int s, error; |
| int error = 0; |
|
| |
|
| |
error = 0; |
| |
s = splsoftnet(); |
| if ((so->so_state & SS_NOFDREF) == 0) |
if ((so->so_state & SS_NOFDREF) == 0) |
| panic("soaccept: !NOFDREF"); |
panic("soaccept: !NOFDREF"); |
| so->so_state &= ~SS_NOFDREF; |
so->so_state &= ~SS_NOFDREF; |
| Line 278 soaccept(so, nam) |
|
| Line 267 soaccept(so, nam) |
|
| } |
} |
| |
|
| int |
int |
| soconnect(so, nam) |
soconnect(struct socket *so, struct mbuf *nam) |
| struct socket *so; |
|
| struct mbuf *nam; |
|
| { |
{ |
| struct proc *p = curproc; /* XXX */ |
struct proc *p; |
| int s; |
int s, error; |
| int error; |
|
| |
|
| |
p = curproc; /* XXX */ |
| if (so->so_options & SO_ACCEPTCONN) |
if (so->so_options & SO_ACCEPTCONN) |
| return (EOPNOTSUPP); |
return (EOPNOTSUPP); |
| s = splsoftnet(); |
s = splsoftnet(); |
| Line 307 soconnect(so, nam) |
|
| Line 294 soconnect(so, nam) |
|
| } |
} |
| |
|
| int |
int |
| soconnect2(so1, so2) |
soconnect2(struct socket *so1, struct socket *so2) |
| struct socket *so1; |
|
| struct socket *so2; |
|
| { |
{ |
| int s = splsoftnet(); |
int s, error; |
| int error; |
|
| |
|
| |
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, |
(struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0, |
| (struct proc *)0); |
(struct proc *)0); |
| Line 322 soconnect2(so1, so2) |
|
| Line 307 soconnect2(so1, so2) |
|
| } |
} |
| |
|
| int |
int |
| sodisconnect(so) |
sodisconnect(struct socket *so) |
| struct socket *so; |
|
| { |
{ |
| int s = splsoftnet(); |
int s, error; |
| int error; |
|
| |
|
| |
s = splsoftnet(); |
| if ((so->so_state & SS_ISCONNECTED) == 0) { |
if ((so->so_state & SS_ISCONNECTED) == 0) { |
| error = ENOTCONN; |
error = ENOTCONN; |
| goto bad; |
goto bad; |
| Line 339 sodisconnect(so) |
|
| Line 323 sodisconnect(so) |
|
| 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, |
(struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0, |
| (struct proc *)0); |
(struct proc *)0); |
| bad: |
bad: |
| splx(s); |
splx(s); |
| return (error); |
return (error); |
| } |
} |
|
|
| * Data and control buffers are freed on return. |
* Data and control buffers are freed on return. |
| */ |
*/ |
| int |
int |
| sosend(so, addr, uio, top, control, flags) |
sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top, |
| struct socket *so; |
struct mbuf *control, int flags) |
| struct mbuf *addr; |
|
| struct uio *uio; |
|
| struct mbuf *top; |
|
| struct mbuf *control; |
|
| int flags; |
|
| { |
{ |
| struct proc *p = curproc; /* XXX */ |
struct proc *p; |
| struct mbuf **mp; |
struct mbuf **mp, *m; |
| struct mbuf *m; |
long space, len, resid; |
| long space, len, resid; |
int clen, error, s, dontroute, mlen, atomic; |
| int clen = 0, error, s, dontroute, mlen; |
|
| int atomic = sosendallatonce(so) || top; |
p = curproc; /* XXX */ |
| |
clen = 0; |
| |
atomic = sosendallatonce(so) || top; |
| if (uio) |
if (uio) |
| resid = uio->uio_resid; |
resid = uio->uio_resid; |
| else |
else |
| Line 401 sosend(so, addr, uio, top, control, flag |
|
| Line 381 sosend(so, addr, uio, top, control, flag |
|
| clen = control->m_len; |
clen = control->m_len; |
| #define snderr(errno) { error = errno; splx(s); goto release; } |
#define snderr(errno) { error = errno; splx(s); goto release; } |
| |
|
| restart: |
restart: |
| if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) |
if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) |
| goto out; |
goto out; |
| do { |
do { |
|
|
| len = min(MCLBYTES, resid); |
len = min(MCLBYTES, resid); |
| #else |
#else |
| if (atomic && top == 0) { |
if (atomic && top == 0) { |
| len = min(MCLBYTES - max_hdr, resid); |
len = min(MCLBYTES - max_hdr, |
| |
resid); |
| m->m_data += max_hdr; |
m->m_data += max_hdr; |
| } else |
} else |
| len = min(MCLBYTES, resid); |
len = min(MCLBYTES, resid); |
|
|
| 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, uio); |
error = uiomove(mtod(m, caddr_t), (int)len, |
| |
uio); |
| resid = uio->uio_resid; |
resid = uio->uio_resid; |
| m->m_len = len; |
m->m_len = len; |
| *mp = m; |
*mp = m; |
|
|
| } while (resid && space > 0); |
} while (resid && space > 0); |
| } while (resid); |
} while (resid); |
| |
|
| release: |
release: |
| sbunlock(&so->so_snd); |
sbunlock(&so->so_snd); |
| out: |
out: |
| if (top) |
if (top) |
| m_freem(top); |
m_freem(top); |
| if (control) |
if (control) |
|
|
| * only for the count in uio_resid. |
* only for the count in uio_resid. |
| */ |
*/ |
| int |
int |
| soreceive(so, paddr, uio, mp0, controlp, flagsp) |
soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio, |
| struct socket *so; |
struct mbuf **mp0, struct mbuf **controlp, int *flagsp) |
| struct mbuf **paddr; |
|
| struct uio *uio; |
|
| struct mbuf **mp0; |
|
| struct mbuf **controlp; |
|
| int *flagsp; |
|
| { |
{ |
| struct mbuf *m, **mp; |
struct mbuf *m, **mp; |
| int flags, len, error, s, offset; |
int flags, len, error, s, offset, moff, type, orig_resid; |
| struct protosw *pr = so->so_proto; |
struct protosw *pr; |
| struct mbuf *nextrecord; |
struct mbuf *nextrecord; |
| int moff, type = 0; |
|
| int orig_resid = uio->uio_resid; |
|
| |
|
| |
pr = so->so_proto; |
| mp = mp0; |
mp = mp0; |
| |
type = 0; |
| |
orig_resid = uio->uio_resid; |
| if (paddr) |
if (paddr) |
| *paddr = 0; |
*paddr = 0; |
| if (controlp) |
if (controlp) |
| Line 591 soreceive(so, paddr, uio, mp0, controlp, |
|
| Line 569 soreceive(so, paddr, uio, mp0, controlp, |
|
| (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); |
| bad: |
bad: |
| if (m) |
if (m) |
| m_freem(m); |
m_freem(m); |
| return (error); |
return (error); |
|
|
| (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, |
(*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, |
| (struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); |
(struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); |
| |
|
| restart: |
restart: |
| if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) |
if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) |
| return (error); |
return (error); |
| s = splsoftnet(); |
s = splsoftnet(); |
|
|
| return (error); |
return (error); |
| goto restart; |
goto restart; |
| } |
} |
| dontblock: |
dontblock: |
| #ifdef notyet /* XXXX */ |
#ifdef notyet /* XXXX */ |
| if (uio->uio_procp) |
if (uio->uio_procp) |
| uio->uio_procp->p_stats->p_ru.ru_msgrcv++; |
uio->uio_procp->p_stats->p_ru.ru_msgrcv++; |
|
|
| |
|
| if (flagsp) |
if (flagsp) |
| *flagsp |= flags; |
*flagsp |= flags; |
| release: |
release: |
| sbunlock(&so->so_rcv); |
sbunlock(&so->so_rcv); |
| splx(s); |
splx(s); |
| return (error); |
return (error); |
| } |
} |
| |
|
| int |
int |
| soshutdown(so, how) |
soshutdown(struct socket *so, int how) |
| struct socket *so; |
|
| int how; |
|
| { |
{ |
| struct protosw *pr = so->so_proto; |
struct protosw *pr; |
| |
|
| |
pr = so->so_proto; |
| if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR)) |
if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR)) |
| return (EINVAL); |
return (EINVAL); |
| |
|
| Line 875 soshutdown(so, how) |
|
| Line 852 soshutdown(so, how) |
|
| } |
} |
| |
|
| void |
void |
| sorflush(so) |
sorflush(struct socket *so) |
| struct socket *so; |
|
| { |
{ |
| struct sockbuf *sb = &so->so_rcv; |
struct sockbuf *sb, asb; |
| struct protosw *pr = so->so_proto; |
struct protosw *pr; |
| int s; |
int s; |
| struct sockbuf asb; |
|
| |
|
| |
sb = &so->so_rcv; |
| |
pr = so->so_proto; |
| sb->sb_flags |= SB_NOINTR; |
sb->sb_flags |= SB_NOINTR; |
| (void) sblock(sb, M_WAITOK); |
(void) sblock(sb, M_WAITOK); |
| s = splimp(); |
s = splimp(); |
|
|
| } |
} |
| |
|
| int |
int |
| sosetopt(so, level, optname, m0) |
sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) |
| struct socket *so; |
|
| int level, optname; |
|
| struct mbuf *m0; |
|
| { |
{ |
| int error = 0; |
int error; |
| struct mbuf *m = m0; |
struct mbuf *m; |
| |
|
| |
error = 0; |
| |
m = m0; |
| if (level != SOL_SOCKET) { |
if (level != SOL_SOCKET) { |
| if (so->so_proto && so->so_proto->pr_ctloutput) |
if (so->so_proto && so->so_proto->pr_ctloutput) |
| return ((*so->so_proto->pr_ctloutput) |
return ((*so->so_proto->pr_ctloutput) |
| Line 1031 sosetopt(so, level, optname, m0) |
|
| Line 1007 sosetopt(so, level, optname, m0) |
|
| m = NULL; /* freed by protocol */ |
m = NULL; /* freed by protocol */ |
| } |
} |
| } |
} |
| bad: |
bad: |
| if (m) |
if (m) |
| (void) m_free(m); |
(void) m_free(m); |
| return (error); |
return (error); |
| } |
} |
| |
|
| int |
int |
| sogetopt(so, level, optname, mp) |
sogetopt(struct socket *so, int level, int optname, struct mbuf **mp) |
| struct socket *so; |
|
| int level, optname; |
|
| struct mbuf **mp; |
|
| { |
{ |
| struct mbuf *m; |
struct mbuf *m; |
| |
|
| if (level != SOL_SOCKET) { |
if (level != SOL_SOCKET) { |
| if (so->so_proto && so->so_proto->pr_ctloutput) { |
if (so->so_proto && so->so_proto->pr_ctloutput) { |
| Line 1124 sogetopt(so, level, optname, mp) |
|
| Line 1097 sogetopt(so, level, optname, mp) |
|
| } |
} |
| |
|
| void |
void |
| sohasoutofband(so) |
sohasoutofband(struct socket *so) |
| struct socket *so; |
|
| { |
{ |
| struct proc *p; |
struct proc *p; |
| |
|