diff options
author | wollman <wollman@FreeBSD.org> | 1997-08-16 19:16:27 +0000 |
---|---|---|
committer | wollman <wollman@FreeBSD.org> | 1997-08-16 19:16:27 +0000 |
commit | 4542c1cf5d7077caf33d6d9468f5e647cd9d19e5 (patch) | |
tree | 69fd093ef1e8c080592999507b664fe6315c0e10 /sys/kern/uipc_syscalls.c | |
parent | f4edc7fc6748272644fb845fc8636a5c261247d6 (diff) | |
download | FreeBSD-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.c | 158 |
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; |