version 1.23, 1996/05/23 17:07:03 |
version 1.24, 1997/04/10 01:51:21 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
|
|
/* |
/* |
|
* Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. |
* Copyright (c) 1982, 1986, 1989, 1991, 1993 |
* Copyright (c) 1982, 1986, 1989, 1991, 1993 |
* The Regents of the University of California. All rights reserved. |
* The Regents of the University of California. All rights reserved. |
* |
* |
Line 625 unp_externalize(rights) |
|
Line 626 unp_externalize(rights) |
|
struct mbuf *rights; |
struct mbuf *rights; |
{ |
{ |
struct proc *p = curproc; /* XXX */ |
struct proc *p = curproc; /* XXX */ |
register int i; |
|
register struct cmsghdr *cm = mtod(rights, struct cmsghdr *); |
register struct cmsghdr *cm = mtod(rights, struct cmsghdr *); |
register struct file **rp = (struct file **)(cm + 1); |
register int i, *fdp = (int *)(cm + 1); |
|
register struct file **rp = (struct file **)ALIGN(cm + 1); |
register struct file *fp; |
register struct file *fp; |
int newfds = (cm->cmsg_len - sizeof(*cm)) / sizeof (int); |
int nfds = (cm->cmsg_len - ALIGN(sizeof(*cm))) / sizeof (struct file *); |
int f; |
int f; |
|
|
if (!fdavail(p, newfds)) { |
/* Make sure that the recipient has space */ |
for (i = 0; i < newfds; i++) { |
if (!fdavail(p, nfds)) { |
|
for (i = 0; i < nfds; i++) { |
fp = *rp; |
fp = *rp; |
unp_discard(fp); |
unp_discard(fp); |
*rp++ = 0; |
*rp++ = 0; |
} |
} |
return (EMSGSIZE); |
return (EMSGSIZE); |
} |
} |
for (i = 0; i < newfds; i++) { |
|
|
/* |
|
* Add file to the recipient's open file table, converting them |
|
* to integer file descriptors as we go. Done in forward order |
|
* because an integer will always come in the same place or before |
|
* its corresponding struct file pointer. |
|
*/ |
|
for (i = 0; i < nfds; i++) { |
if (fdalloc(p, 0, &f)) |
if (fdalloc(p, 0, &f)) |
panic("unp_externalize"); |
panic("unp_externalize"); |
fp = *rp; |
fp = *rp; |
p->p_fd->fd_ofiles[f] = fp; |
p->p_fd->fd_ofiles[f] = fp; |
fp->f_msgcount--; |
fp->f_msgcount--; |
unp_rights--; |
unp_rights--; |
*(int *)rp++ = f; |
*fdp++ = f; |
} |
} |
|
|
|
/* |
|
* Adjust length, in case of transition from large struct file |
|
* pointers to ints. |
|
*/ |
|
cm->cmsg_len = sizeof(*cm) + (nfds * sizeof(int)); |
|
rights->m_len = cm->cmsg_len; |
return (0); |
return (0); |
} |
} |
|
|
Line 657 unp_internalize(control, p) |
|
Line 673 unp_internalize(control, p) |
|
struct mbuf *control; |
struct mbuf *control; |
struct proc *p; |
struct proc *p; |
{ |
{ |
struct filedesc *fdp = p->p_fd; |
struct filedesc *fdescp = p->p_fd; |
register struct cmsghdr *cm = mtod(control, struct cmsghdr *); |
register struct cmsghdr *cm = mtod(control, struct cmsghdr *); |
register struct file **rp; |
register struct file **rp; |
register struct file *fp; |
register struct file *fp; |
register int i, fd; |
register int i, fd, *fdp; |
int oldfds; |
int nfds; |
|
u_int neededspace; |
|
|
|
/* Sanity check the control message header */ |
if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET || |
if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET || |
cm->cmsg_len != control->m_len) |
cm->cmsg_len != control->m_len) |
return (EINVAL); |
return (EINVAL); |
oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int); |
|
rp = (struct file **)(cm + 1); |
/* Verify that the file descriptors are valid */ |
for (i = 0; i < oldfds; i++) { |
nfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int); |
fd = *(int *)rp++; |
fdp = (int *)(cm + 1); |
if ((unsigned)fd >= fdp->fd_nfiles || |
for (i = 0; i < nfds; i++) { |
fdp->fd_ofiles[fd] == NULL) |
fd = *fdp++; |
|
if ((unsigned)fd >= fdescp->fd_nfiles || |
|
fdescp->fd_ofiles[fd] == NULL) |
return (EBADF); |
return (EBADF); |
} |
} |
rp = (struct file **)(cm + 1); |
|
for (i = 0; i < oldfds; i++) { |
/* Make sure we have room for the struct file pointers */ |
fp = fdp->fd_ofiles[*(int *)rp]; |
morespace: |
*rp++ = fp; |
neededspace = (ALIGN(sizeof (*cm)) + nfds * sizeof (struct file *)) - |
|
control->m_len; |
|
if (neededspace > M_TRAILINGSPACE(control)) { |
|
|
|
/* if we already have a cluster, the message is just too big */ |
|
if (control->m_flags & M_EXT) |
|
return (E2BIG); |
|
|
|
/* allocate a cluster and try again */ |
|
MCLGET(control, M_WAIT); |
|
if ((control->m_flags & M_EXT) == 0) |
|
return (ENOBUFS); /* allocation failed */ |
|
|
|
/* copy the data to the cluster */ |
|
bcopy(cm, mtod(control, char *), cm->cmsg_len); |
|
cm = mtod(control, struct cmsghdr *); |
|
goto morespace; |
|
} |
|
|
|
/* adjust message & mbuf to note amount of space actually used. */ |
|
cm->cmsg_len += neededspace; |
|
control->m_len = cm->cmsg_len; |
|
|
|
/* |
|
* Transform the file descriptors into struct file pointers, in |
|
* reverse order so that if pointers are bigger than ints, the |
|
* int won't get until we're done. |
|
*/ |
|
fdp = ((int *)(cm + 1)) + nfds - 1; |
|
rp = ((struct file **)ALIGN(cm + 1)) + nfds - 1; |
|
for (i = 0; i < nfds; i++) { |
|
fp = fdescp->fd_ofiles[*fdp]; |
|
*rp-- = fp; |
fp->f_count++; |
fp->f_count++; |
fp->f_msgcount++; |
fp->f_msgcount++; |
unp_rights++; |
unp_rights++; |