Enable SCM_RIGHTS on alpha. Allocate necessary buffer as conversion between

int and struct file *.

Approved by: jkh

Submitted by: brian
Reviewed by: bde, brian, peter
This commit is contained in:
Yoshinobu Inoue 2000-03-09 15:15:27 +00:00
parent 9deb82d478
commit 8692c02553
1 changed files with 108 additions and 28 deletions

View File

@ -865,19 +865,26 @@ unp_externalize(rights)
struct proc *p = curproc; /* XXX */ struct proc *p = curproc; /* XXX */
register int i; 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 *fdp;
register struct file **rp;
register struct file *fp; register struct file *fp;
int newfds = (cm->cmsg_len - sizeof(*cm)) / sizeof (int); int newfds = (cm->cmsg_len - (CMSG_DATA(cm) - (u_char *)cm))
/ sizeof (struct file *);
int f; int f;
/* /*
* if the new FD's will not fit, then we free them all * if the new FD's will not fit, then we free them all
*/ */
if (!fdavail(p, newfds)) { if (!fdavail(p, newfds)) {
rp = (struct file **)CMSG_DATA(cm);
for (i = 0; i < newfds; i++) { for (i = 0; i < newfds; i++) {
fp = *rp; fp = *rp;
unp_discard(fp); /*
* zero the pointer before calling unp_discard,
* since it may end up in unp_gc()..
*/
*rp++ = 0; *rp++ = 0;
unp_discard(fp);
} }
return (EMSGSIZE); return (EMSGSIZE);
} }
@ -885,17 +892,45 @@ unp_externalize(rights)
* now change each pointer to an fd in the global table to * now change each pointer to an fd in the global table to
* an integer that is the index to the local fd table entry * an integer that is the index to the local fd table entry
* that we set up to point to the global one we are transferring. * that we set up to point to the global one we are transferring.
* XXX this assumes a pointer and int are the same size...! * If sizeof (struct file *) is bigger than or equal to sizeof int,
* then do it in forward order. In that case, an integer will
* always come in the same place or before its corresponding
* struct file pointer.
* If sizeof (struct file *) is smaller than sizeof int, then
* do it in reverse order.
*/ */
for (i = 0; i < newfds; i++) { if (sizeof (struct file *) >= sizeof (int)) {
if (fdalloc(p, 0, &f)) fdp = (int *)(cm + 1);
panic("unp_externalize"); rp = (struct file **)CMSG_DATA(cm);
fp = *rp; for (i = 0; i < newfds; i++) {
p->p_fd->fd_ofiles[f] = fp; if (fdalloc(p, 0, &f))
fp->f_msgcount--; panic("unp_externalize");
unp_rights--; fp = *rp++;
*(int *)rp++ = f; p->p_fd->fd_ofiles[f] = fp;
fp->f_msgcount--;
unp_rights--;
*fdp++ = f;
}
} else {
fdp = (int *)(cm + 1) + newfds - 1;
rp = (struct file **)CMSG_DATA(cm) + newfds - 1;
for (i = 0; i < newfds; i++) {
if (fdalloc(p, 0, &f))
panic("unp_externalize");
fp = *rp--;
p->p_fd->fd_ofiles[f] = fp;
fp->f_msgcount--;
unp_rights--;
*fdp-- = f;
}
} }
/*
* Adjust length, in case sizeof(struct file *) and sizeof(int)
* differs.
*/
cm->cmsg_len = CMSG_LEN(newfds * sizeof(int));
rights->m_len = cm->cmsg_len;
return (0); return (0);
} }
@ -918,13 +953,14 @@ 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;
register struct cmsgcred *cmcred; register struct cmsgcred *cmcred;
int oldfds; int oldfds;
u_int newlen;
if ((cm->cmsg_type != SCM_RIGHTS && cm->cmsg_type != SCM_CREDS) || if ((cm->cmsg_type != SCM_RIGHTS && cm->cmsg_type != SCM_CREDS) ||
cm->cmsg_level != SOL_SOCKET || cm->cmsg_len != control->m_len) cm->cmsg_level != SOL_SOCKET || cm->cmsg_len != control->m_len)
@ -951,25 +987,68 @@ unp_internalize(control, p)
* check that all the FDs passed in refer to legal OPEN files * check that all the FDs passed in refer to legal OPEN files
* If not, reject the entire operation. * If not, reject the entire operation.
*/ */
rp = (struct file **)(cm + 1); fdp = (int *)(cm + 1);
for (i = 0; i < oldfds; i++) { for (i = 0; i < oldfds; i++) {
fd = *(int *)rp++; fd = *fdp++;
if ((unsigned)fd >= fdp->fd_nfiles || if ((unsigned)fd >= fdescp->fd_nfiles ||
fdp->fd_ofiles[fd] == NULL) fdescp->fd_ofiles[fd] == NULL)
return (EBADF); return (EBADF);
} }
/* /*
* Now replace the integer FDs with pointers to * Now replace the integer FDs with pointers to
* the associated global file table entry.. * the associated global file table entry..
* XXX this assumes a pointer and an int are the same size! * Allocate a bigger buffer as necessary. But if an cluster is not
* enough, return E2BIG.
*/ */
rp = (struct file **)(cm + 1); newlen = CMSG_LEN(oldfds * sizeof(struct file *));
for (i = 0; i < oldfds; i++) { if (newlen > MCLBYTES)
fp = fdp->fd_ofiles[*(int *)rp]; return (E2BIG);
*rp++ = fp; if (newlen - control->m_len > M_TRAILINGSPACE(control)) {
fp->f_count++; if (control->m_flags & M_EXT)
fp->f_msgcount++; return (E2BIG);
unp_rights++; MCLGET(control, M_WAIT);
if ((control->m_flags & M_EXT) == 0)
return (ENOBUFS);
/* copy the data to the cluster */
memcpy(mtod(control, char *), cm, cm->cmsg_len);
cm = mtod(control, struct cmsghdr *);
}
/*
* Adjust length, in case sizeof(struct file *) and sizeof(int)
* differs.
*/
control->m_len = cm->cmsg_len = newlen;
/*
* Transform the file descriptors into struct file pointers.
* If sizeof (struct file *) is bigger than or equal to sizeof int,
* then do it in reverse order so that the int won't get until
* we're done.
* If sizeof (struct file *) is smaller than sizeof int, then
* do it in forward order.
*/
if (sizeof (struct file *) >= sizeof (int)) {
fdp = (int *)(cm + 1) + oldfds - 1;
rp = (struct file **)CMSG_DATA(cm) + oldfds - 1;
for (i = 0; i < oldfds; i++) {
fp = fdescp->fd_ofiles[*fdp--];
*rp-- = fp;
fp->f_count++;
fp->f_msgcount++;
unp_rights++;
}
} else {
fdp = (int *)(cm + 1);
rp = (struct file **)CMSG_DATA(cm);
for (i = 0; i < oldfds; i++) {
fp = fdescp->fd_ofiles[*fdp++];
*rp++ = fp;
fp->f_count++;
fp->f_msgcount++;
unp_rights++;
}
} }
return (0); return (0);
} }
@ -1168,9 +1247,10 @@ unp_scan(m0, op)
if (cm->cmsg_level != SOL_SOCKET || if (cm->cmsg_level != SOL_SOCKET ||
cm->cmsg_type != SCM_RIGHTS) cm->cmsg_type != SCM_RIGHTS)
continue; continue;
qfds = (cm->cmsg_len - sizeof *cm) qfds = (cm->cmsg_len -
(CMSG_DATA(cm) - (u_char *)cm))
/ sizeof (struct file *); / sizeof (struct file *);
rp = (struct file **)(cm + 1); rp = (struct file **)CMSG_DATA(cm);
for (i = 0; i < qfds; i++) for (i = 0; i < qfds; i++)
(*op)(*rp++); (*op)(*rp++);
break; /* XXX, but saves time */ break; /* XXX, but saves time */