- Split out kern_accept(), kern_getpeername(), and kern_getsockname() for
use by ABI emulators. - Alter the interface of kern_recvit() somewhat. Specifically, go ahead and hard code UIO_USERSPACE in the uio as that's what all the callers specify. In place, add a new uioseg to indicate what type of pointer is in mp->msg_name. Previously it was always a userland address, but ABI emulators may pass in kernel-side sockaddrs. Also, remove the namelenp field and instead require the two places that used it to explicitly copy mp->msg_namelen out to userland. - Use the patched kern_recvit() to replace svr4_recvit() and the stock kern_sendit() to replace svr4_sendit(). - Use kern_bind() instead of stackgap use in ti_bind(). - Use kern_getpeername() and kern_getsockname() instead of stackgap in svr4_stream_ti_ioctl(). - Use kern_connect() instead of stackgap in svr4_do_putmsg(). - Use kern_getpeername() and kern_accept() instead of stackgap in svr4_do_getmsg(). - Retire the stackgap from SVR4 compat as it is no longer used.
This commit is contained in:
parent
ee41eea403
commit
cfc179a934
@ -1009,7 +1009,7 @@ freebsd32_recvmsg(td, uap)
|
||||
msg.msg_iov = iov;
|
||||
|
||||
controlp = (msg.msg_control != NULL) ? &control : NULL;
|
||||
error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp);
|
||||
error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
|
||||
if (error == 0) {
|
||||
msg.msg_iov = uiov;
|
||||
|
||||
@ -1149,8 +1149,10 @@ freebsd32_recvfrom(struct thread *td,
|
||||
aiov.iov_len = uap->len;
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_flags = uap->flags;
|
||||
error = kern_recvit(td, uap->s, &msg, PTRIN(uap->fromlenaddr),
|
||||
UIO_USERSPACE, NULL);
|
||||
error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
|
||||
if (error == 0 && uap->fromlenaddr)
|
||||
error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
|
||||
sizeof (msg.msg_namelen));
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -133,245 +133,6 @@ static int ti_getinfo(struct file *, int, struct svr4_strioctl *,
|
||||
struct thread *);
|
||||
static int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
|
||||
|
||||
/* infrastructure */
|
||||
static int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags);
|
||||
|
||||
static int svr4_recvit(struct thread *td, int s, struct msghdr *mp,
|
||||
caddr_t namelenp);
|
||||
|
||||
/* <sigh> Ok, so we shouldn't use sendit() in uipc_syscalls.c because
|
||||
* it isn't part of a "public" interface; We're supposed to use
|
||||
* pru_sosend instead. Same goes for recvit()/pru_soreceive() for
|
||||
* that matter. Solution: Suck sendit()/recvit() into here where we
|
||||
* can do what we like.
|
||||
*
|
||||
* I hate code duplication.
|
||||
*
|
||||
* I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
|
||||
*/
|
||||
static int
|
||||
svr4_sendit(td, s, mp, flags)
|
||||
register struct thread *td;
|
||||
int s;
|
||||
register struct msghdr *mp;
|
||||
int flags;
|
||||
{
|
||||
struct uio auio;
|
||||
register struct iovec *iov;
|
||||
register int i;
|
||||
struct mbuf *control;
|
||||
struct sockaddr *to;
|
||||
int len, error;
|
||||
struct socket *so;
|
||||
#ifdef KTRACE
|
||||
struct uio *ktruio = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXXRW: Instead of using fgetsock(), just rely on the file
|
||||
* descriptor reference.
|
||||
*/
|
||||
if ((error = fgetsock(td, s, &so, NULL)) != 0)
|
||||
return (error);
|
||||
|
||||
#ifdef MAC
|
||||
SOCK_LOCK(so);
|
||||
error = mac_check_socket_send(td->td_ucred, so);
|
||||
SOCK_UNLOCK(so);
|
||||
if (error)
|
||||
goto done1;
|
||||
#endif
|
||||
|
||||
auio.uio_iov = mp->msg_iov;
|
||||
auio.uio_iovcnt = mp->msg_iovlen;
|
||||
auio.uio_segflg = UIO_USERSPACE;
|
||||
auio.uio_rw = UIO_WRITE;
|
||||
auio.uio_td = td;
|
||||
auio.uio_offset = 0; /* XXX */
|
||||
auio.uio_resid = 0;
|
||||
iov = mp->msg_iov;
|
||||
for (i = 0; i < mp->msg_iovlen; i++, iov++) {
|
||||
if ((auio.uio_resid += iov->iov_len) < 0) {
|
||||
error = EINVAL;
|
||||
goto done1;
|
||||
}
|
||||
}
|
||||
if (mp->msg_name) {
|
||||
error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
|
||||
if (error)
|
||||
goto done1;
|
||||
} else {
|
||||
to = 0;
|
||||
}
|
||||
if (mp->msg_control) {
|
||||
if (mp->msg_controllen < sizeof(struct cmsghdr)) {
|
||||
error = EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
error = sockargs(&control, mp->msg_control,
|
||||
mp->msg_controllen, MT_CONTROL);
|
||||
if (error)
|
||||
goto bad;
|
||||
} else {
|
||||
control = 0;
|
||||
}
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(td, KTR_GENIO))
|
||||
ktruio = cloneuio(&auio);
|
||||
#endif
|
||||
len = auio.uio_resid;
|
||||
error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
|
||||
flags, td);
|
||||
if (error) {
|
||||
if (auio.uio_resid != len && (error == ERESTART ||
|
||||
error == EINTR || error == EWOULDBLOCK))
|
||||
error = 0;
|
||||
if (error == EPIPE) {
|
||||
PROC_LOCK(td->td_proc);
|
||||
psignal(td->td_proc, SIGPIPE);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
}
|
||||
}
|
||||
if (error == 0)
|
||||
td->td_retval[0] = len - auio.uio_resid;
|
||||
#ifdef KTRACE
|
||||
if (ktruio != NULL) {
|
||||
ktruio->uio_resid = td->td_retval[0];
|
||||
ktrgenio(s, UIO_WRITE, ktruio, error);
|
||||
}
|
||||
#endif
|
||||
bad:
|
||||
if (to)
|
||||
FREE(to, M_SONAME);
|
||||
done1:
|
||||
fputsock(so);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
svr4_recvit(td, s, mp, namelenp)
|
||||
register struct thread *td;
|
||||
int s;
|
||||
register struct msghdr *mp;
|
||||
caddr_t namelenp;
|
||||
{
|
||||
struct uio auio;
|
||||
register struct iovec *iov;
|
||||
register int i;
|
||||
int len, error;
|
||||
struct mbuf *m, *control = 0;
|
||||
caddr_t ctlbuf;
|
||||
struct socket *so;
|
||||
struct sockaddr *fromsa = 0;
|
||||
#ifdef KTRACE
|
||||
struct uio *ktruio = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXXRW: Instead of using fgetsock(), just rely on the file
|
||||
* descriptor reference.
|
||||
*/
|
||||
if ((error = fgetsock(td, s, &so, NULL)) != 0)
|
||||
return (error);
|
||||
|
||||
#ifdef MAC
|
||||
SOCK_LOCK(so);
|
||||
error = mac_check_socket_receive(td->td_ucred, so);
|
||||
SOCK_UNLOCK(so);
|
||||
if (error)
|
||||
goto done1;
|
||||
#endif
|
||||
|
||||
auio.uio_iov = mp->msg_iov;
|
||||
auio.uio_iovcnt = mp->msg_iovlen;
|
||||
auio.uio_segflg = UIO_USERSPACE;
|
||||
auio.uio_rw = UIO_READ;
|
||||
auio.uio_td = td;
|
||||
auio.uio_offset = 0; /* XXX */
|
||||
auio.uio_resid = 0;
|
||||
iov = mp->msg_iov;
|
||||
for (i = 0; i < mp->msg_iovlen; i++, iov++) {
|
||||
if ((auio.uio_resid += iov->iov_len) < 0) {
|
||||
error = EINVAL;
|
||||
goto done1;
|
||||
}
|
||||
}
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(td, KTR_GENIO))
|
||||
ktruio = cloneuio(&auio);
|
||||
#endif
|
||||
len = auio.uio_resid;
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
|
||||
(struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
|
||||
&mp->msg_flags);
|
||||
if (error) {
|
||||
if (auio.uio_resid != len && (error == ERESTART ||
|
||||
error == EINTR || error == EWOULDBLOCK))
|
||||
error = 0;
|
||||
}
|
||||
#ifdef KTRACE
|
||||
if (ktruio != NULL) {
|
||||
ktruio->uio_resid = len - auio.uio_resid;
|
||||
ktrgenio(s, UIO_READ, ktruio, error);
|
||||
}
|
||||
#endif
|
||||
if (error)
|
||||
goto out;
|
||||
td->td_retval[0] = len - auio.uio_resid;
|
||||
if (mp->msg_name) {
|
||||
len = mp->msg_namelen;
|
||||
if (len <= 0 || fromsa == 0)
|
||||
len = 0;
|
||||
else {
|
||||
/* save sa_len before it is destroyed by MSG_COMPAT */
|
||||
len = MIN(len, fromsa->sa_len);
|
||||
error = copyout(fromsa,
|
||||
(caddr_t)mp->msg_name, (unsigned)len);
|
||||
if (error)
|
||||
goto out;
|
||||
}
|
||||
mp->msg_namelen = len;
|
||||
if (namelenp &&
|
||||
(error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (mp->msg_control) {
|
||||
len = mp->msg_controllen;
|
||||
m = control;
|
||||
mp->msg_controllen = 0;
|
||||
ctlbuf = (caddr_t) mp->msg_control;
|
||||
|
||||
while (m && len > 0) {
|
||||
unsigned int tocopy;
|
||||
|
||||
if (len >= m->m_len)
|
||||
tocopy = m->m_len;
|
||||
else {
|
||||
mp->msg_flags |= MSG_CTRUNC;
|
||||
tocopy = len;
|
||||
}
|
||||
|
||||
if ((error = copyout((caddr_t)mtod(m, caddr_t),
|
||||
ctlbuf, tocopy)) != 0)
|
||||
goto out;
|
||||
|
||||
ctlbuf += tocopy;
|
||||
len -= tocopy;
|
||||
m = m->m_next;
|
||||
}
|
||||
mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
|
||||
}
|
||||
out:
|
||||
if (fromsa)
|
||||
FREE(fromsa, M_SONAME);
|
||||
if (control)
|
||||
m_freem(control);
|
||||
done1:
|
||||
fputsock(so);
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SVR4
|
||||
static void bufprint(u_char *, size_t);
|
||||
static int show_ioc(const char *, struct svr4_strioctl *);
|
||||
@ -989,11 +750,9 @@ ti_bind(fp, fd, ioc, td)
|
||||
struct svr4_strm *st = svr4_stream_get(fp);
|
||||
struct sockaddr_in sain;
|
||||
struct sockaddr_un saun;
|
||||
caddr_t sg;
|
||||
void *skp, *sup = NULL;
|
||||
struct sockaddr *skp;
|
||||
int sasize;
|
||||
struct svr4_strmcmd bnd;
|
||||
struct bind_args ba;
|
||||
|
||||
if (st == NULL) {
|
||||
DPRINTF(("ti_bind: bad file descriptor\n"));
|
||||
@ -1013,11 +772,11 @@ ti_bind(fp, fd, ioc, td)
|
||||
|
||||
switch (st->s_family) {
|
||||
case AF_INET:
|
||||
skp = &sain;
|
||||
skp = (struct sockaddr *)&sain;
|
||||
sasize = sizeof(sain);
|
||||
|
||||
if (bnd.offs == 0)
|
||||
goto reply;
|
||||
goto error;
|
||||
|
||||
netaddr_to_sockaddr_in(&sain, &bnd);
|
||||
|
||||
@ -1027,15 +786,15 @@ ti_bind(fp, fd, ioc, td)
|
||||
break;
|
||||
|
||||
case AF_LOCAL:
|
||||
skp = &saun;
|
||||
skp = (struct sockaddr *)&saun;
|
||||
sasize = sizeof(saun);
|
||||
if (bnd.offs == 0)
|
||||
goto reply;
|
||||
goto error;
|
||||
|
||||
netaddr_to_sockaddr_un(&saun, &bnd);
|
||||
|
||||
if (saun.sun_path[0] == '\0')
|
||||
goto reply;
|
||||
goto error;
|
||||
|
||||
DPRINTF(("TI_BIND: fam %d, path %s\n",
|
||||
saun.sun_family, saun.sun_path));
|
||||
@ -1052,29 +811,20 @@ ti_bind(fp, fd, ioc, td)
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
sg = stackgap_init();
|
||||
sup = stackgap_alloc(&sg, sasize);
|
||||
|
||||
if ((error = copyout(skp, sup, sasize)) != 0)
|
||||
return error;
|
||||
|
||||
ba.s = fd;
|
||||
DPRINTF(("TI_BIND: fileno %d\n", fd));
|
||||
ba.name = (void *) sup;
|
||||
ba.namelen = sasize;
|
||||
|
||||
if ((error = bind(td, &ba)) != 0) {
|
||||
if ((error = kern_bind(td, fd, skp)) != 0) {
|
||||
DPRINTF(("TI_BIND: bind failed %d\n", error));
|
||||
return error;
|
||||
}
|
||||
goto reply;
|
||||
|
||||
error:
|
||||
memset(&bnd, 0, sizeof(bnd));
|
||||
bnd.len = sasize + 4;
|
||||
bnd.offs = 0x10; /* XXX */
|
||||
|
||||
reply:
|
||||
if (sup == NULL) {
|
||||
memset(&bnd, 0, sizeof(bnd));
|
||||
bnd.len = sasize + 4;
|
||||
bnd.offs = 0x10; /* XXX */
|
||||
}
|
||||
|
||||
bnd.cmd = SVR4_TI_BIND_REPLY;
|
||||
|
||||
if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
|
||||
@ -1127,13 +877,9 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
|
||||
struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
|
||||
struct svr4_strm *st = svr4_stream_get(fp);
|
||||
int error;
|
||||
void *skp, *sup;
|
||||
struct sockaddr_in sain;
|
||||
struct sockaddr_un saun;
|
||||
struct sockaddr *sa;
|
||||
socklen_t sasize, oldsasize;
|
||||
struct svr4_strmcmd sc;
|
||||
int sasize, oldsasize;
|
||||
caddr_t sg;
|
||||
int *lenp;
|
||||
|
||||
DPRINTF(("svr4_stream_ti_ioctl\n"));
|
||||
|
||||
@ -1149,13 +895,11 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
|
||||
|
||||
switch (st->s_family) {
|
||||
case AF_INET:
|
||||
skp = &sain;
|
||||
sasize = sizeof(sain);
|
||||
sasize = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
|
||||
case AF_LOCAL:
|
||||
skp = &saun;
|
||||
sasize = sizeof(saun);
|
||||
sasize = sizeof(struct sockaddr_un);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1163,25 +907,14 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
|
||||
st->s_family));
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
sg = stackgap_init();
|
||||
sup = stackgap_alloc(&sg, sasize);
|
||||
lenp = stackgap_alloc(&sg, sizeof(*lenp));
|
||||
|
||||
if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
|
||||
DPRINTF(("ti_ioctl: error copying out lenp\n"));
|
||||
return error;
|
||||
}
|
||||
oldsasize = sasize;
|
||||
|
||||
switch (cmd) {
|
||||
case SVR4_TI_GETMYNAME:
|
||||
DPRINTF(("TI_GETMYNAME\n"));
|
||||
{
|
||||
struct getsockname_args ap;
|
||||
ap.fdes = fd;
|
||||
ap.asa = sup;
|
||||
ap.alen = lenp;
|
||||
if ((error = getsockname(td, &ap)) != 0) {
|
||||
error = kern_getsockname(td, fd, &sa, &sasize);
|
||||
if (error) {
|
||||
DPRINTF(("ti_ioctl: getsockname error\n"));
|
||||
return error;
|
||||
}
|
||||
@ -1191,11 +924,8 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
|
||||
case SVR4_TI_GETPEERNAME:
|
||||
DPRINTF(("TI_GETPEERNAME\n"));
|
||||
{
|
||||
struct getpeername_args ap;
|
||||
ap.fdes = fd;
|
||||
ap.asa = sup;
|
||||
ap.alen = lenp;
|
||||
if ((error = getpeername(td, &ap)) != 0) {
|
||||
error = kern_getpeername(td, fd, &sa, &sasize);
|
||||
if (error) {
|
||||
DPRINTF(("ti_ioctl: getpeername error\n"));
|
||||
return error;
|
||||
}
|
||||
@ -1214,36 +944,27 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
if ((error = copyin(sup, skp, sasize)) != 0) {
|
||||
DPRINTF(("ti_ioctl: error copying in socket data\n"));
|
||||
return error;
|
||||
}
|
||||
|
||||
oldsasize = sasize;
|
||||
|
||||
if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
|
||||
DPRINTF(("ti_ioctl: error copying in socket size\n"));
|
||||
return error;
|
||||
}
|
||||
|
||||
if (sasize < 0 || sasize > oldsasize)
|
||||
if (sasize < 0 || sasize > oldsasize) {
|
||||
free(sa, M_SONAME);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
switch (st->s_family) {
|
||||
case AF_INET:
|
||||
sockaddr_to_netaddr_in(&sc, &sain);
|
||||
sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa);
|
||||
skb.len = sasize;
|
||||
break;
|
||||
|
||||
case AF_LOCAL:
|
||||
sockaddr_to_netaddr_un(&sc, &saun);
|
||||
sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa);
|
||||
skb.len = sasize + 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
free(sa, M_SONAME);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
free(sa, M_SONAME);
|
||||
|
||||
if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
|
||||
DPRINTF(("ti_ioctl: error copying out socket data\n"));
|
||||
@ -1314,7 +1035,6 @@ i_fdinsert(fp, td, retval, fd, cmd, dat)
|
||||
struct svr4_strm *st = svr4_stream_get(fp);
|
||||
struct svr4_strfdinsert fdi;
|
||||
struct dup2_args d2p;
|
||||
struct close_args clp;
|
||||
|
||||
if (st == NULL) {
|
||||
DPRINTF(("fdinsert: bad file type\n"));
|
||||
@ -1340,9 +1060,7 @@ i_fdinsert(fp, td, retval, fd, cmd, dat)
|
||||
return error;
|
||||
}
|
||||
|
||||
clp.fd = st->s_afd;
|
||||
|
||||
if ((error = close(td, &clp)) != 0) {
|
||||
if ((error = kern_close(td, st->s_afd)) != 0) {
|
||||
DPRINTF(("fdinsert: close(%d) failed %d\n",
|
||||
st->s_afd, error));
|
||||
return error;
|
||||
@ -1742,11 +1460,10 @@ svr4_do_putmsg(td, uap, fp)
|
||||
struct svr4_strmcmd sc;
|
||||
struct sockaddr_in sain;
|
||||
struct sockaddr_un saun;
|
||||
void *skp, *sup;
|
||||
struct sockaddr *sa;
|
||||
int sasize, *retval;
|
||||
struct svr4_strm *st;
|
||||
int error;
|
||||
caddr_t sg;
|
||||
|
||||
retval = td->td_retval;
|
||||
|
||||
@ -1820,9 +1537,10 @@ svr4_do_putmsg(td, uap, fp)
|
||||
return EINVAL;
|
||||
}
|
||||
netaddr_to_sockaddr_in(&sain, &sc);
|
||||
skp = &sain;
|
||||
sa = (struct sockaddr *)&sain;
|
||||
sasize = sizeof(sain);
|
||||
error = sain.sin_family != st->s_family;
|
||||
if (sain.sin_family != st->s_family)
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
||||
case AF_LOCAL:
|
||||
@ -1836,11 +1554,12 @@ svr4_do_putmsg(td, uap, fp)
|
||||
/* Maybe we've been given a device/inode pair */
|
||||
dev_t *dev = SVR4_ADDROF(&sc);
|
||||
ino_t *ino = (ino_t *) &dev[1];
|
||||
skp = svr4_find_socket(td, fp, *dev, *ino);
|
||||
if (skp == NULL) {
|
||||
skp = &saun;
|
||||
sa = (struct sockaddr *)
|
||||
svr4_find_socket(td, fp, *dev, *ino);
|
||||
if (sa == NULL) {
|
||||
sa = (struct sockaddr *)&saun;
|
||||
/* I guess we have it by name */
|
||||
netaddr_to_sockaddr_un(skp, &sc);
|
||||
netaddr_to_sockaddr_un(&saun, &sc);
|
||||
}
|
||||
sasize = sizeof(saun);
|
||||
}
|
||||
@ -1852,22 +1571,11 @@ svr4_do_putmsg(td, uap, fp)
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
sg = stackgap_init();
|
||||
sup = stackgap_alloc(&sg, sasize);
|
||||
|
||||
if ((error = copyout(skp, sup, sasize)) != 0)
|
||||
return error;
|
||||
|
||||
switch (st->s_cmd = sc.cmd) {
|
||||
case SVR4_TI_CONNECT_REQUEST: /* connect */
|
||||
{
|
||||
struct connect_args co;
|
||||
|
||||
co.s = uap->fd;
|
||||
co.name = (void *) sup;
|
||||
co.namelen = (int) sasize;
|
||||
|
||||
return connect(td, &co);
|
||||
return (kern_connect(td, uap->fd, sa));
|
||||
}
|
||||
|
||||
case SVR4_TI_SENDTO_REQUEST: /* sendto */
|
||||
@ -1875,7 +1583,7 @@ svr4_do_putmsg(td, uap, fp)
|
||||
struct msghdr msg;
|
||||
struct iovec aiov;
|
||||
|
||||
msg.msg_name = (caddr_t) sup;
|
||||
msg.msg_name = sa;
|
||||
msg.msg_namelen = sasize;
|
||||
msg.msg_iov = &aiov;
|
||||
msg.msg_iovlen = 1;
|
||||
@ -1883,12 +1591,8 @@ svr4_do_putmsg(td, uap, fp)
|
||||
msg.msg_flags = 0;
|
||||
aiov.iov_base = dat.buf;
|
||||
aiov.iov_len = dat.len;
|
||||
#if 0
|
||||
error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
|
||||
uio, 0, 0, 0, uio->uio_td);
|
||||
#endif
|
||||
error = svr4_sendit(td, uap->fd, &msg,
|
||||
uap->flags);
|
||||
error = kern_sendit(td, uap->fd, &msg, uap->flags,
|
||||
NULL, UIO_USERSPACE);
|
||||
DPRINTF(("sendto_request error: %d\n", error));
|
||||
*retval = 0;
|
||||
return error;
|
||||
@ -1925,8 +1629,6 @@ svr4_do_getmsg(td, uap, fp)
|
||||
struct svr4_sys_getmsg_args *uap;
|
||||
struct file *fp;
|
||||
{
|
||||
struct getpeername_args ga;
|
||||
struct accept_args aa;
|
||||
struct svr4_strbuf dat, ctl;
|
||||
struct svr4_strmcmd sc;
|
||||
int error, *retval;
|
||||
@ -1934,14 +1636,13 @@ svr4_do_getmsg(td, uap, fp)
|
||||
struct iovec aiov;
|
||||
struct sockaddr_in sain;
|
||||
struct sockaddr_un saun;
|
||||
void *skp, *sup;
|
||||
int sasize;
|
||||
struct sockaddr *sa;
|
||||
socklen_t sasize;
|
||||
struct svr4_strm *st;
|
||||
int *flen;
|
||||
int fl;
|
||||
caddr_t sg;
|
||||
|
||||
retval = td->td_retval;
|
||||
error = 0;
|
||||
|
||||
FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
|
||||
|
||||
@ -1987,12 +1688,10 @@ svr4_do_getmsg(td, uap, fp)
|
||||
|
||||
switch (st->s_family) {
|
||||
case AF_INET:
|
||||
skp = &sain;
|
||||
sasize = sizeof(sain);
|
||||
break;
|
||||
|
||||
case AF_LOCAL:
|
||||
skp = &saun;
|
||||
sasize = sizeof(saun);
|
||||
break;
|
||||
|
||||
@ -2002,14 +1701,6 @@ svr4_do_getmsg(td, uap, fp)
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
sg = stackgap_init();
|
||||
sup = stackgap_alloc(&sg, sasize);
|
||||
flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
|
||||
|
||||
fl = sasize;
|
||||
if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
|
||||
return error;
|
||||
|
||||
switch (st->s_cmd) {
|
||||
case SVR4_TI_CONNECT_REQUEST:
|
||||
DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
|
||||
@ -2033,18 +1724,12 @@ svr4_do_getmsg(td, uap, fp)
|
||||
* a connect verification.
|
||||
*/
|
||||
|
||||
ga.fdes = uap->fd;
|
||||
ga.asa = (void *) sup;
|
||||
ga.alen = flen;
|
||||
|
||||
if ((error = getpeername(td, &ga)) != 0) {
|
||||
error = kern_getpeername(td, uap->fd, &sa, &sasize);
|
||||
if (error) {
|
||||
DPRINTF(("getmsg: getpeername failed %d\n", error));
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = copyin(sup, skp, sasize)) != 0)
|
||||
return error;
|
||||
|
||||
sc.cmd = SVR4_TI_CONNECT_REPLY;
|
||||
sc.pad[0] = 0x4;
|
||||
sc.offs = 0x18;
|
||||
@ -2054,17 +1739,19 @@ svr4_do_getmsg(td, uap, fp)
|
||||
switch (st->s_family) {
|
||||
case AF_INET:
|
||||
sc.len = sasize;
|
||||
sockaddr_to_netaddr_in(&sc, &sain);
|
||||
sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa);
|
||||
break;
|
||||
|
||||
case AF_LOCAL:
|
||||
sc.len = sasize + 4;
|
||||
sockaddr_to_netaddr_un(&sc, &saun);
|
||||
sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa);
|
||||
break;
|
||||
|
||||
default:
|
||||
free(sa, M_SONAME);
|
||||
return ENOSYS;
|
||||
}
|
||||
free(sa, M_SONAME);
|
||||
|
||||
ctl.len = 40;
|
||||
dat.len = -1;
|
||||
@ -2092,11 +1779,9 @@ svr4_do_getmsg(td, uap, fp)
|
||||
/*
|
||||
* We are after a listen, so we try to accept...
|
||||
*/
|
||||
aa.s = uap->fd;
|
||||
aa.name = (void *) sup;
|
||||
aa.anamelen = flen;
|
||||
|
||||
if ((error = accept(td, &aa)) != 0) {
|
||||
|
||||
error = kern_accept(td, uap->fd, &sa, &sasize);
|
||||
if (error) {
|
||||
DPRINTF(("getmsg: accept failed %d\n", error));
|
||||
return error;
|
||||
}
|
||||
@ -2105,9 +1790,6 @@ svr4_do_getmsg(td, uap, fp)
|
||||
|
||||
DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
|
||||
|
||||
if ((error = copyin(sup, skp, sasize)) != 0)
|
||||
return error;
|
||||
|
||||
sc.cmd = SVR4_TI_ACCEPT_REPLY;
|
||||
sc.offs = 0x18;
|
||||
sc.pad[0] = 0x0;
|
||||
@ -2115,7 +1797,7 @@ svr4_do_getmsg(td, uap, fp)
|
||||
switch (st->s_family) {
|
||||
case AF_INET:
|
||||
sc.pad[1] = 0x28;
|
||||
sockaddr_to_netaddr_in(&sc, &sain);
|
||||
sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)&sa);
|
||||
ctl.len = 40;
|
||||
sc.len = sasize;
|
||||
break;
|
||||
@ -2129,8 +1811,10 @@ svr4_do_getmsg(td, uap, fp)
|
||||
break;
|
||||
|
||||
default:
|
||||
free(sa, M_SONAME);
|
||||
return ENOSYS;
|
||||
}
|
||||
free(sa, M_SONAME);
|
||||
|
||||
dat.len = -1;
|
||||
fl = 0;
|
||||
@ -2150,10 +1834,12 @@ svr4_do_getmsg(td, uap, fp)
|
||||
|
||||
switch (st->s_family) {
|
||||
case AF_INET:
|
||||
sa = (struct sockaddr *)&sain;
|
||||
sockaddr_to_netaddr_in(&sc, &sain);
|
||||
break;
|
||||
|
||||
case AF_LOCAL:
|
||||
sa = (struct sockaddr *)&saun;
|
||||
sockaddr_to_netaddr_un(&sc, &saun);
|
||||
break;
|
||||
|
||||
@ -2161,7 +1847,7 @@ svr4_do_getmsg(td, uap, fp)
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
msg.msg_name = (caddr_t) sup;
|
||||
msg.msg_name = sa;
|
||||
msg.msg_namelen = sasize;
|
||||
msg.msg_iov = &aiov;
|
||||
msg.msg_iovlen = 1;
|
||||
@ -2170,16 +1856,13 @@ svr4_do_getmsg(td, uap, fp)
|
||||
aiov.iov_len = dat.maxlen;
|
||||
msg.msg_flags = 0;
|
||||
|
||||
error = svr4_recvit(td, uap->fd, &msg, (caddr_t) flen);
|
||||
error = kern_recvit(td, uap->fd, &msg, UIO_SYSSPACE, NULL);
|
||||
|
||||
if (error) {
|
||||
DPRINTF(("getmsg: recvit failed %d\n", error));
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
|
||||
return error;
|
||||
|
||||
sc.cmd = SVR4_TI_RECVFROM_IND;
|
||||
|
||||
switch (st->s_family) {
|
||||
@ -2233,6 +1916,7 @@ svr4_do_getmsg(td, uap, fp)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* XXX: We leak the accept fd if we get an error here. */
|
||||
if (uap->ctl) {
|
||||
if (ctl.len > sizeof(sc))
|
||||
ctl.len = sizeof(sc);
|
||||
|
@ -47,30 +47,6 @@
|
||||
#define DPRINTF(a)
|
||||
#endif
|
||||
|
||||
|
||||
static __inline caddr_t stackgap_init(void);
|
||||
static __inline void *stackgap_alloc(caddr_t *, size_t);
|
||||
|
||||
static __inline caddr_t
|
||||
stackgap_init()
|
||||
{
|
||||
#define szsigcode (*(curthread->td_proc->p_sysent->sv_szsigcode))
|
||||
return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE);
|
||||
}
|
||||
|
||||
static __inline void *
|
||||
stackgap_alloc(sgp, sz)
|
||||
caddr_t *sgp;
|
||||
size_t sz;
|
||||
{
|
||||
void *p = (void *) *sgp;
|
||||
sz = ALIGN(sz);
|
||||
if (*sgp + sz > (caddr_t)(PS_STRINGS - szsigcode))
|
||||
return NULL;
|
||||
*sgp += sz;
|
||||
return p;
|
||||
}
|
||||
|
||||
int svr4_emul_find(struct thread *, char *, enum uio_seg, char **, int);
|
||||
|
||||
#define CHECKALT(td, upath, pathp, i) \
|
||||
|
@ -295,11 +295,54 @@ accept1(td, uap, compat)
|
||||
socklen_t * __restrict anamelen;
|
||||
} */ *uap;
|
||||
int compat;
|
||||
{
|
||||
struct sockaddr *name;
|
||||
socklen_t namelen;
|
||||
int error;
|
||||
|
||||
if (uap->name == NULL)
|
||||
return (kern_accept(td, uap->s, NULL, NULL));
|
||||
|
||||
error = copyin(uap->anamelen, &namelen, sizeof (namelen));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = kern_accept(td, uap->s, &name, &namelen);
|
||||
|
||||
/*
|
||||
* return a namelen of zero for older code which might
|
||||
* ignore the return value from accept.
|
||||
*/
|
||||
if (error) {
|
||||
(void) copyout(&namelen,
|
||||
uap->anamelen, sizeof(*uap->anamelen));
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (error == 0 && name != NULL) {
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
if (compat)
|
||||
((struct osockaddr *)name)->sa_family =
|
||||
name->sa_family;
|
||||
#endif
|
||||
error = copyout(name, uap->name, namelen);
|
||||
}
|
||||
if (error == 0)
|
||||
error = copyout(&namelen, uap->anamelen,
|
||||
sizeof(namelen));
|
||||
if (error)
|
||||
kern_close(td, td->td_retval[0]);
|
||||
free(name, M_SONAME);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
kern_accept(struct thread *td, int s, struct sockaddr **name,
|
||||
socklen_t *namelen)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct file *headfp, *nfp = NULL;
|
||||
struct sockaddr *sa = NULL;
|
||||
socklen_t namelen;
|
||||
int error;
|
||||
struct socket *head, *so;
|
||||
int fd;
|
||||
@ -307,16 +350,15 @@ accept1(td, uap, compat)
|
||||
pid_t pgid;
|
||||
int tmp;
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
if (uap->name) {
|
||||
error = copyin(uap->anamelen, &namelen, sizeof (namelen));
|
||||
if(error)
|
||||
return (error);
|
||||
if (namelen < 0)
|
||||
if (name) {
|
||||
*name = NULL;
|
||||
if (*namelen < 0)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
NET_LOCK_GIANT();
|
||||
error = getsock(fdp, uap->s, &headfp, &fflag);
|
||||
error = getsock(fdp, s, &headfp, &fflag);
|
||||
if (error)
|
||||
goto done2;
|
||||
head = headfp->f_data;
|
||||
@ -407,34 +449,21 @@ accept1(td, uap, compat)
|
||||
* return a namelen of zero for older code which might
|
||||
* ignore the return value from accept.
|
||||
*/
|
||||
if (uap->name != NULL) {
|
||||
namelen = 0;
|
||||
(void) copyout(&namelen,
|
||||
uap->anamelen, sizeof(*uap->anamelen));
|
||||
}
|
||||
if (name)
|
||||
*namelen = 0;
|
||||
goto noconnection;
|
||||
}
|
||||
if (sa == NULL) {
|
||||
namelen = 0;
|
||||
if (uap->name)
|
||||
goto gotnoname;
|
||||
error = 0;
|
||||
if (name)
|
||||
*namelen = 0;
|
||||
goto done;
|
||||
}
|
||||
if (uap->name) {
|
||||
if (name) {
|
||||
/* check sa_len before it is destroyed */
|
||||
if (namelen > sa->sa_len)
|
||||
namelen = sa->sa_len;
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
if (compat)
|
||||
((struct osockaddr *)sa)->sa_family =
|
||||
sa->sa_family;
|
||||
#endif
|
||||
error = copyout(sa, uap->name, (u_int)namelen);
|
||||
if (!error)
|
||||
gotnoname:
|
||||
error = copyout(&namelen,
|
||||
uap->anamelen, sizeof (*uap->anamelen));
|
||||
if (*namelen > sa->sa_len)
|
||||
*namelen = sa->sa_len;
|
||||
*name = sa;
|
||||
sa = NULL;
|
||||
}
|
||||
noconnection:
|
||||
if (sa)
|
||||
@ -926,12 +955,11 @@ sendmsg(td, uap)
|
||||
}
|
||||
|
||||
int
|
||||
kern_recvit(td, s, mp, namelenp, segflg, controlp)
|
||||
kern_recvit(td, s, mp, fromseg, controlp)
|
||||
struct thread *td;
|
||||
int s;
|
||||
struct msghdr *mp;
|
||||
void *namelenp;
|
||||
enum uio_seg segflg;
|
||||
enum uio_seg fromseg;
|
||||
struct mbuf **controlp;
|
||||
{
|
||||
struct uio auio;
|
||||
@ -972,7 +1000,7 @@ kern_recvit(td, s, mp, namelenp, segflg, controlp)
|
||||
|
||||
auio.uio_iov = mp->msg_iov;
|
||||
auio.uio_iovcnt = mp->msg_iovlen;
|
||||
auio.uio_segflg = segflg;
|
||||
auio.uio_segflg = UIO_USERSPACE;
|
||||
auio.uio_rw = UIO_READ;
|
||||
auio.uio_td = td;
|
||||
auio.uio_offset = 0; /* XXX */
|
||||
@ -1020,20 +1048,15 @@ kern_recvit(td, s, mp, namelenp, segflg, controlp)
|
||||
((struct osockaddr *)fromsa)->sa_family =
|
||||
fromsa->sa_family;
|
||||
#endif
|
||||
error = copyout(fromsa, mp->msg_name, (unsigned)len);
|
||||
if (error)
|
||||
goto out;
|
||||
if (fromseg == UIO_USERSPACE) {
|
||||
error = copyout(fromsa, mp->msg_name,
|
||||
(unsigned)len);
|
||||
if (error)
|
||||
goto out;
|
||||
} else
|
||||
bcopy(fromsa, mp->msg_name, len);
|
||||
}
|
||||
mp->msg_namelen = len;
|
||||
if (namelenp &&
|
||||
(error = copyout(&len, namelenp, sizeof (socklen_t)))) {
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
if (mp->msg_flags & MSG_COMPAT)
|
||||
error = 0; /* old recvfrom didn't check */
|
||||
else
|
||||
#endif
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (mp->msg_control && controlp == NULL) {
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
@ -1102,8 +1125,19 @@ recvit(td, s, mp, namelenp)
|
||||
struct msghdr *mp;
|
||||
void *namelenp;
|
||||
{
|
||||
int error;
|
||||
|
||||
return (kern_recvit(td, s, mp, namelenp, UIO_USERSPACE, NULL));
|
||||
error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL);
|
||||
if (error)
|
||||
return (error);
|
||||
if (namelenp) {
|
||||
error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t));
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
if (mp->msg_flags & MSG_COMPAT)
|
||||
error = 0; /* old recvfrom didn't check */
|
||||
#endif
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1459,48 +1493,64 @@ getsockname1(td, uap, compat)
|
||||
} */ *uap;
|
||||
int compat;
|
||||
{
|
||||
struct socket *so;
|
||||
struct sockaddr *sa;
|
||||
socklen_t len;
|
||||
int error;
|
||||
|
||||
error = copyin(uap->alen, &len, sizeof(len));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = kern_getsockname(td, uap->fdes, &sa, &len);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (len != 0) {
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
if (compat)
|
||||
((struct osockaddr *)sa)->sa_family = sa->sa_family;
|
||||
#endif
|
||||
error = copyout(sa, uap->asa, (u_int)len);
|
||||
}
|
||||
free(sa, M_SONAME);
|
||||
if (error == 0)
|
||||
error = copyout(&len, uap->alen, sizeof(len));
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
|
||||
socklen_t *alen)
|
||||
{
|
||||
struct socket *so;
|
||||
struct file *fp;
|
||||
socklen_t len;
|
||||
int error;
|
||||
|
||||
if (*alen < 0)
|
||||
return (EINVAL);
|
||||
|
||||
NET_LOCK_GIANT();
|
||||
error = getsock(td->td_proc->p_fd, uap->fdes, &fp, NULL);
|
||||
error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
|
||||
if (error)
|
||||
goto done2;
|
||||
goto done;
|
||||
so = fp->f_data;
|
||||
error = copyin(uap->alen, &len, sizeof (len));
|
||||
if (error)
|
||||
goto done1;
|
||||
if (len < 0) {
|
||||
error = EINVAL;
|
||||
goto done1;
|
||||
}
|
||||
sa = 0;
|
||||
error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
|
||||
*sa = NULL;
|
||||
error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa);
|
||||
if (error)
|
||||
goto bad;
|
||||
if (sa == 0) {
|
||||
if (*sa == NULL)
|
||||
len = 0;
|
||||
goto gotnothing;
|
||||
}
|
||||
|
||||
len = MIN(len, sa->sa_len);
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
if (compat)
|
||||
((struct osockaddr *)sa)->sa_family = sa->sa_family;
|
||||
#endif
|
||||
error = copyout(sa, uap->asa, (u_int)len);
|
||||
if (error == 0)
|
||||
gotnothing:
|
||||
error = copyout(&len, uap->alen, sizeof (len));
|
||||
else
|
||||
len = MIN(*alen, (*sa)->sa_len);
|
||||
*alen = len;
|
||||
bad:
|
||||
if (sa)
|
||||
FREE(sa, M_SONAME);
|
||||
done1:
|
||||
fdrop(fp, td);
|
||||
done2:
|
||||
if (error && *sa) {
|
||||
free(*sa, M_SONAME);
|
||||
*sa = NULL;
|
||||
}
|
||||
done:
|
||||
NET_UNLOCK_GIANT();
|
||||
return (error);
|
||||
}
|
||||
@ -1547,14 +1597,45 @@ getpeername1(td, uap, compat)
|
||||
} */ *uap;
|
||||
int compat;
|
||||
{
|
||||
struct socket *so;
|
||||
struct sockaddr *sa;
|
||||
socklen_t len;
|
||||
int error;
|
||||
|
||||
error = copyin(uap->alen, &len, sizeof (len));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = kern_getpeername(td, uap->fdes, &sa, &len);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (len != 0) {
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
if (compat)
|
||||
((struct osockaddr *)sa)->sa_family = sa->sa_family;
|
||||
#endif
|
||||
error = copyout(sa, uap->asa, (u_int)len);
|
||||
}
|
||||
free(sa, M_SONAME);
|
||||
if (error == 0)
|
||||
error = copyout(&len, uap->alen, sizeof(len));
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
|
||||
socklen_t *alen)
|
||||
{
|
||||
struct socket *so;
|
||||
struct file *fp;
|
||||
socklen_t len;
|
||||
int error;
|
||||
|
||||
if (*alen < 0)
|
||||
return (EINVAL);
|
||||
|
||||
NET_LOCK_GIANT();
|
||||
error = getsock(td->td_proc->p_fd, uap->fdes, &fp, NULL);
|
||||
error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
|
||||
if (error)
|
||||
goto done2;
|
||||
so = fp->f_data;
|
||||
@ -1562,35 +1643,20 @@ getpeername1(td, uap, compat)
|
||||
error = ENOTCONN;
|
||||
goto done1;
|
||||
}
|
||||
error = copyin(uap->alen, &len, sizeof (len));
|
||||
if (error)
|
||||
goto done1;
|
||||
if (len < 0) {
|
||||
error = EINVAL;
|
||||
goto done1;
|
||||
}
|
||||
sa = 0;
|
||||
error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
|
||||
*sa = NULL;
|
||||
error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, sa);
|
||||
if (error)
|
||||
goto bad;
|
||||
if (sa == 0) {
|
||||
if (*sa == NULL)
|
||||
len = 0;
|
||||
goto gotnothing;
|
||||
}
|
||||
len = MIN(len, sa->sa_len);
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
if (compat)
|
||||
((struct osockaddr *)sa)->sa_family =
|
||||
sa->sa_family;
|
||||
#endif
|
||||
error = copyout(sa, uap->asa, (u_int)len);
|
||||
if (error)
|
||||
goto bad;
|
||||
gotnothing:
|
||||
error = copyout(&len, uap->alen, sizeof (len));
|
||||
else
|
||||
len = MIN(*alen, (*sa)->sa_len);
|
||||
*alen = len;
|
||||
bad:
|
||||
if (sa)
|
||||
FREE(sa, M_SONAME);
|
||||
if (error && *sa) {
|
||||
free(*sa, M_SONAME);
|
||||
*sa = NULL;
|
||||
}
|
||||
done1:
|
||||
fdrop(fp, td);
|
||||
done2:
|
||||
|
@ -50,6 +50,8 @@ struct sendfile_args;
|
||||
|
||||
int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg,
|
||||
u_int buflen);
|
||||
int kern_accept(struct thread *td, int s, struct sockaddr **name,
|
||||
socklen_t *namelen);
|
||||
int kern_access(struct thread *td, char *path, enum uio_seg pathseg,
|
||||
int flags);
|
||||
int kern_adjtime(struct thread *td, struct timeval *delta,
|
||||
@ -84,7 +86,11 @@ int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
|
||||
enum uio_seg bufseg, int flags);
|
||||
int kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups);
|
||||
int kern_getitimer(struct thread *, u_int, struct itimerval *);
|
||||
int kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
|
||||
socklen_t *alen);
|
||||
int kern_getrusage(struct thread *td, int who, struct rusage *rup);
|
||||
int kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
|
||||
socklen_t *alen);
|
||||
int kern_getsockopt(struct thread *td, int s, int level, int name,
|
||||
void *optval, enum uio_seg valseg, socklen_t *valsize);
|
||||
int kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data);
|
||||
@ -120,8 +126,8 @@ int kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset);
|
||||
int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg,
|
||||
char *buf, enum uio_seg bufseg, int count);
|
||||
int kern_readv(struct thread *td, int fd, struct uio *auio);
|
||||
int kern_recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp,
|
||||
enum uio_seg segflg, struct mbuf **controlp);
|
||||
int kern_recvit(struct thread *td, int s, struct msghdr *mp,
|
||||
enum uio_seg fromseg, struct mbuf **controlp);
|
||||
int kern_rename(struct thread *td, char *from, char *to,
|
||||
enum uio_seg pathseg);
|
||||
int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg);
|
||||
|
Loading…
Reference in New Issue
Block a user