summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_syscalls.c
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1997-08-16 19:16:27 +0000
committerwollman <wollman@FreeBSD.org>1997-08-16 19:16:27 +0000
commit4542c1cf5d7077caf33d6d9468f5e647cd9d19e5 (patch)
tree69fd093ef1e8c080592999507b664fe6315c0e10 /sys/kern/uipc_syscalls.c
parentf4edc7fc6748272644fb845fc8636a5c261247d6 (diff)
downloadFreeBSD-src-4542c1cf5d7077caf33d6d9468f5e647cd9d19e5.zip
FreeBSD-src-4542c1cf5d7077caf33d6d9468f5e647cd9d19e5.tar.gz
Fix all areas of the system (or at least all those in LINT) to avoid storing
socket addresses in mbufs. (Socket buffers are the one exception.) A number of kernel APIs needed to get fixed in order to make this happen. Also, fix three protocol families which kept PCBs in mbufs to not malloc them instead. Delete some old compatibility cruft while we're at it, and add some new routines in the in_cksum family.
Diffstat (limited to 'sys/kern/uipc_syscalls.c')
-rw-r--r--sys/kern/uipc_syscalls.c158
1 files changed, 100 insertions, 58 deletions
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index fb8f428..409f68f 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
- * $Id: uipc_syscalls.c,v 1.25 1997/04/09 16:53:40 bde Exp $
+ * $Id: uipc_syscalls.c,v 1.26 1997/04/27 20:00:45 wollman Exp $
*/
#include "opt_ktrace.h"
@@ -121,17 +121,17 @@ bind(p, uap, retval)
int *retval;
{
struct file *fp;
- struct mbuf *nam;
+ struct sockaddr *sa;
int error;
error = getsock(p->p_fd, uap->s, &fp);
if (error)
return (error);
- error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
+ error = getsockaddr(&sa, uap->name, uap->namelen);
if (error)
return (error);
- error = sobind((struct socket *)fp->f_data, nam, p);
- m_freem(nam);
+ error = sobind((struct socket *)fp->f_data, sa, p);
+ FREE(sa, M_SONAME);
return (error);
}
@@ -166,7 +166,7 @@ accept1(p, uap, retval, compat)
int compat;
{
struct file *fp;
- struct mbuf *nam;
+ struct sockaddr *sa;
int namelen, error, s;
struct socket *head, *so;
short fflag; /* type must match fp->f_flag */
@@ -243,24 +243,32 @@ accept1(p, uap, retval, compat)
fp->f_flag = fflag;
fp->f_ops = &socketops;
fp->f_data = (caddr_t)so;
- nam = m_get(M_WAIT, MT_SONAME);
- (void) soaccept(so, nam);
+ sa = 0;
+ (void) soaccept(so, &sa);
+ if (sa == 0) {
+ namelen = 0;
+ if (uap->name)
+ goto gotnoname;
+ return 0;
+ }
+ if ((u_long)sa < 0xf0000000) {
+ panic("accept1 bad sa");
+ }
if (uap->name) {
#ifdef COMPAT_OLDSOCK
if (compat)
- mtod(nam, struct osockaddr *)->sa_family =
- mtod(nam, struct sockaddr *)->sa_family;
+ ((struct osockaddr *)sa)->sa_family =
+ sa->sa_family;
#endif
- if (namelen > nam->m_len)
- namelen = nam->m_len;
- /* SHOULD COPY OUT A CHAIN HERE */
- error = copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
- (u_int)namelen);
+ if (namelen > sa->sa_len)
+ namelen = sa->sa_len;
+ error = copyout(sa, (caddr_t)uap->name, (u_int)namelen);
if (!error)
+gotnoname:
error = copyout((caddr_t)&namelen,
(caddr_t)uap->anamelen, sizeof (*uap->anamelen));
}
- m_freem(nam);
+ FREE(sa, M_SONAME);
splx(s);
return (error);
}
@@ -300,7 +308,7 @@ connect(p, uap, retval)
{
struct file *fp;
register struct socket *so;
- struct mbuf *nam;
+ struct sockaddr *sa;
int error, s;
error = getsock(p->p_fd, uap->s, &fp);
@@ -309,14 +317,14 @@ connect(p, uap, retval)
so = (struct socket *)fp->f_data;
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
return (EALREADY);
- error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
+ error = getsockaddr(&sa, uap->name, uap->namelen);
if (error)
return (error);
- error = soconnect(so, nam, p);
+ error = soconnect(so, sa, p);
if (error)
goto bad;
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
- m_freem(nam);
+ FREE(sa, M_SONAME);
return (EINPROGRESS);
}
s = splnet();
@@ -333,7 +341,7 @@ connect(p, uap, retval)
splx(s);
bad:
so->so_state &= ~SS_ISCONNECTING;
- m_freem(nam);
+ FREE(sa, M_SONAME);
if (error == ERESTART)
error = EINTR;
return (error);
@@ -418,7 +426,8 @@ sendit(p, s, mp, flags, retsize)
struct uio auio;
register struct iovec *iov;
register int i;
- struct mbuf *to, *control;
+ struct mbuf *control;
+ struct sockaddr *to;
int len, error;
struct socket *so;
#ifdef KTRACE
@@ -441,7 +450,7 @@ sendit(p, s, mp, flags, retsize)
return (EINVAL);
}
if (mp->msg_name) {
- error = sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
+ error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
if (error)
return (error);
} else
@@ -488,7 +497,7 @@ sendit(p, s, mp, flags, retsize)
len = auio.uio_resid;
so = (struct socket *)fp->f_data;
error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
- flags);
+ flags, p);
if (error) {
if (auio.uio_resid != len && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
@@ -508,7 +517,7 @@ sendit(p, s, mp, flags, retsize)
#endif
bad:
if (to)
- m_freem(to);
+ FREE(to, M_SONAME);
return (error);
}
@@ -659,9 +668,10 @@ recvit(p, s, mp, namelenp, retsize)
register struct iovec *iov;
register int i;
int len, error;
- struct mbuf *m, *from = 0, *control = 0;
+ struct mbuf *m, *control = 0;
caddr_t ctlbuf;
struct socket *so;
+ struct sockaddr *fromsa = 0;
#ifdef KTRACE
struct iovec *ktriov = NULL;
#endif
@@ -691,7 +701,7 @@ recvit(p, s, mp, namelenp, retsize)
#endif
len = auio.uio_resid;
so = (struct socket *)fp->f_data;
- error = so->so_proto->pr_usrreqs->pru_soreceive(so, &from, &auio,
+ 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) {
@@ -712,18 +722,19 @@ recvit(p, s, mp, namelenp, retsize)
*retsize = len - auio.uio_resid;
if (mp->msg_name) {
len = mp->msg_namelen;
- if (len <= 0 || from == 0)
+ if (len <= 0 || fromsa == 0)
len = 0;
else {
#ifdef COMPAT_OLDSOCK
if (mp->msg_flags & MSG_COMPAT)
- mtod(from, struct osockaddr *)->sa_family =
- mtod(from, struct sockaddr *)->sa_family;
+ ((struct osockaddr *)fromsa)->sa_family =
+ fromsa->sa_family;
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a)>(b)?(b):(a))
#endif
- if (len > from->m_len)
- len = from->m_len;
- /* else if len < from->m_len ??? */
- error = copyout(mtod(from, caddr_t),
+ len = MIN(len, fromsa->sa_len);
+ error = copyout(fromsa,
(caddr_t)mp->msg_name, (unsigned)len);
if (error)
goto out;
@@ -786,8 +797,8 @@ recvit(p, s, mp, namelenp, retsize)
mp->msg_controllen = ctlbuf - mp->msg_control;
}
out:
- if (from)
- m_freem(from);
+ if (fromsa)
+ FREE(fromsa, M_SONAME);
if (control)
m_freem(control);
return (error);
@@ -1084,7 +1095,7 @@ getsockname1(p, uap, retval, compat)
{
struct file *fp;
register struct socket *so;
- struct mbuf *m;
+ struct sockaddr *sa;
int len, error;
error = getsock(p->p_fd, uap->fdes, &fp);
@@ -1094,25 +1105,28 @@ getsockname1(p, uap, retval, compat)
if (error)
return (error);
so = (struct socket *)fp->f_data;
- m = m_getclr(M_WAIT, MT_SONAME);
- if (m == NULL)
- return (ENOBUFS);
- error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, m);
+ sa = 0;
+ error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
if (error)
goto bad;
- if (len > m->m_len)
- len = m->m_len;
+ if (sa == 0) {
+ len = 0;
+ goto gotnothing;
+ }
+
+ len = MIN(len, sa->sa_len);
#ifdef COMPAT_OLDSOCK
if (compat)
- mtod(m, struct osockaddr *)->sa_family =
- mtod(m, struct sockaddr *)->sa_family;
+ ((struct osockaddr *)sa)->sa_family = sa->sa_family;
#endif
- error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
+ error = copyout(sa, (caddr_t)uap->asa, (u_int)len);
if (error == 0)
+gotnothing:
error = copyout((caddr_t)&len, (caddr_t)uap->alen,
sizeof (len));
bad:
- m_freem(m);
+ if (sa)
+ FREE(sa, M_SONAME);
return (error);
}
@@ -1155,7 +1169,7 @@ getpeername1(p, uap, retval, compat)
{
struct file *fp;
register struct socket *so;
- struct mbuf *m;
+ struct sockaddr *sa;
int len, error;
error = getsock(p->p_fd, uap->fdes, &fp);
@@ -1167,25 +1181,27 @@ getpeername1(p, uap, retval, compat)
error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
if (error)
return (error);
- m = m_getclr(M_WAIT, MT_SONAME);
- if (m == NULL)
- return (ENOBUFS);
- error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, m);
+ sa = 0;
+ error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
if (error)
goto bad;
- if (len > m->m_len)
- len = m->m_len;
+ if (sa == 0) {
+ len = 0;
+ goto gotnothing;
+ }
+ len = MIN(len, sa->sa_len);
#ifdef COMPAT_OLDSOCK
if (compat)
- mtod(m, struct osockaddr *)->sa_family =
- mtod(m, struct sockaddr *)->sa_family;
+ ((struct osockaddr *)sa)->sa_family =
+ sa->sa_family;
#endif
- error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
+ error = copyout(sa, (caddr_t)uap->asa, (u_int)len);
if (error)
goto bad;
+gotnothing:
error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
bad:
- m_freem(m);
+ if (sa) FREE(sa, M_SONAME);
return (error);
}
@@ -1253,6 +1269,32 @@ sockargs(mp, buf, buflen, type)
}
int
+getsockaddr(namp, uaddr, len)
+ struct sockaddr **namp;
+ caddr_t uaddr;
+ size_t len;
+{
+ struct sockaddr *sa;
+ int error;
+
+ if (len > SOCK_MAXADDRLEN)
+ return ENAMETOOLONG;
+ MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
+ error = copyin(uaddr, sa, len);
+ if (error) {
+ FREE(sa, M_SONAME);
+ } else {
+#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
+ if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
+ sa->sa_family = sa->sa_len;
+#endif
+ sa->sa_len = len;
+ *namp = sa;
+ }
+ return error;
+}
+
+int
getsock(fdp, fdes, fpp)
struct filedesc *fdp;
int fdes;
OpenPOWER on IntegriCloud