o Don't try to transfer tty device descriptors as there's no way of

transferring session rights with them.  Instead, create two
  `/bin/cat' processes.  A new child is spawned and disassociated from
  the terminal and the parent, which continues with the rest of the ppp
  process.  Meanwhile, the parent spawns another child, and both the
  parent and child exec the `/bin/cat' commands with the appropriate
  descriptors.  This way, the session is owned by the parent, and the
  tty is held open.
o Close LCPs that have done a TLF and are now in ST_STOPPED before
  calling Down.  This prevents them from trying to come back up again
  after the peer has shut them down (it seems a bit strange that the
  rfc says that a Down in ST_STOPPED will cause a TLS etc).
o Don't try to set the physical link name pointer when we're receiving
  and renaming a datalink.  The physical hasn't been created yet, and as
  it happens, the garbage physical pointer happens to be the value of another
  physical - so we're pointing that other physical name at ourselves.
  yeuck.
o Re-arrange the order of things in main (DoLoop()).  We now handle
  signals only after the select and not before the UpdateSet.  It's
  possible that either a signal (FSM timeout) or a descriptor_Read()
  brings a link down, after which we'd better tidy up any dead direct
  and 1off descriptors before calling UpdateSet() again.
o Mention when we detect a PPP packet when we see one before the link
  is up (then start LCP as before).
This commit is contained in:
Brian Somers 1998-05-25 02:22:38 +00:00
parent 97c44d070c
commit 54cd8e13c6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=36345
5 changed files with 128 additions and 32 deletions

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: bundle.c,v 1.5 1998/05/23 22:27:53 brian Exp $
* $Id: bundle.c,v 1.6 1998/05/23 22:28:19 brian Exp $
*/
#include <sys/types.h>
@ -41,11 +41,13 @@
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
@ -1349,8 +1351,10 @@ bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun)
niov = 1;
iov[0].iov_len = strlen(Version) + 1;
iov[0].iov_base = (char *)malloc(iov[0].iov_len);
if (datalink2iov(NULL, iov, &niov, sizeof iov / sizeof *iov) == -1)
if (datalink2iov(NULL, iov, &niov, sizeof iov / sizeof *iov) == -1) {
close(s);
return;
}
for (f = expect = 0; f < niov; f++)
expect += iov[f].iov_len;
@ -1358,7 +1362,7 @@ bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun)
/* Set up our message */
cmsg->cmsg_len = sizeof cmsgbuf;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_type = 0;
memset(&msg, '\0', sizeof msg);
msg.msg_name = (caddr_t)sun;
@ -1378,13 +1382,22 @@ bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun)
log_Printf(LogERROR, "Failed recvmsg: Got %d, not %d\n", f, expect);
while (niov--)
free(iov[niov].iov_base);
close(s);
return;
}
/* We've successfully received an open file descriptor through our socket */
link_fd = *(int *)CMSG_DATA(cmsg);
write(s, "!", 1); /* ACK */
write(s, "!",1 ); /* ACK */
if (cmsg->cmsg_type == SCM_RIGHTS) {
/* We've successfully received an open file descriptor through our socket */
log_Printf(LogDEBUG, "Receiving non-tty device\n");
link_fd = *(int *)CMSG_DATA(cmsg);
} else {
/* It's a ``controlling'' tty device via CATPROG */
log_Printf(LogDEBUG, "Receiving tty device\n");
link_fd = dup(s);
fcntl(link_fd, F_SETFL, fcntl(link_fd, F_GETFL, 0) | O_NONBLOCK);
}
if (strncmp(Version, iov[0].iov_base, iov[0].iov_len)) {
log_Printf(LogWARN, "Cannot receive datalink, incorrect version"
@ -1405,6 +1418,7 @@ bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun)
close(link_fd);
free(iov[0].iov_base);
close(s);
}
void
@ -1429,18 +1443,30 @@ bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun)
link_fd = datalink2iov(dl, iov, &niov, sizeof iov / sizeof *iov);
if (link_fd != -1) {
cmsg->cmsg_len = sizeof cmsgbuf;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = link_fd;
memset(&msg, '\0', sizeof msg);
msg.msg_name = (caddr_t)sun;
msg.msg_namelen = sizeof *sun;
msg.msg_iov = iov;
msg.msg_iovlen = niov;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof cmsgbuf;
if (link_fd == STDIN_FILENO && isatty(link_fd)) {
/*
* We can't transfer this tty descriptor. If we do, then once the
* session leader exits, the descriptor becomes unusable by the
* other ppp process. Instead, we'll fork() two `/bin/cat'
* processes.....
*/
msg.msg_control = NULL;
msg.msg_controllen = 0;
} else {
cmsg->cmsg_len = sizeof cmsgbuf;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = link_fd;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof cmsgbuf;
}
for (f = expect = 0; f < niov; f++)
expect += iov[f].iov_len;
@ -1453,6 +1479,70 @@ bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun)
log_Printf(LogERROR, "Failed sendmsg: %s\n", strerror(errno));
/* We must get the ACK before closing the descriptor ! */
read(s, &ack, 1);
if (link_fd == STDIN_FILENO && isatty(link_fd)) {
/* We use `/bin/cat' to keep the tty session id */
pid_t pid;
int status, len, fd;
char name[50], *tname;
tname = ttyname(link_fd);
len = strlen(_PATH_DEV);
if (!strncmp(tname, _PATH_DEV, len))
tname += len;
log_Printf(LogPHASE, "%s: Using twin %s invocations\n", tname, CATPROG);
switch ((pid = fork())) {
case -1:
log_Printf(LogERROR, "fork: %s\n", strerror(errno));
break;
case 0:
if (fork()) /* Don't want to belong to the parent any more */
exit(0);
setsid();
log_Printf(LogPHASE, "%d: Continuing without controlling terminal\n",
(int)getpid());
break;
default:
/* Parent does the execs .... */
timer_TermService();
waitpid(pid, &status, 0);
fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */
fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) & ~O_NONBLOCK);
fcntl(link_fd, F_SETFL, fcntl(link_fd, F_GETFL, 0) & ~O_NONBLOCK);
s = fcntl(s, F_DUPFD, 3);
link_fd = fcntl(link_fd, F_DUPFD, 3);
dup2(open(_PATH_DEVNULL, O_WRONLY|O_APPEND), STDERR_FILENO);
setuid(geteuid());
switch (fork()) {
case -1:
_exit(0);
break;
case 0:
dup2(link_fd, STDIN_FILENO);
dup2(s, STDOUT_FILENO);
snprintf(name, sizeof name, "%s <- %s", dl->name, tname);
break;
default:
dup2(s, STDIN_FILENO);
dup2(link_fd, STDOUT_FILENO);
snprintf(name, sizeof name, "%s -> %s", dl->name, tname);
break;
}
signal(SIGPIPE, SIG_DFL);
signal(SIGALRM, SIG_DFL);
for (fd = getdtablesize(); fd > 2; fd--)
close(fd);
execl(CATPROG, name, NULL);
_exit(0);
break;
}
}
close(s);
close(link_fd);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: datalink.c,v 1.3 1998/05/23 13:38:06 brian Exp $
* $Id: datalink.c,v 1.4 1998/05/23 22:24:33 brian Exp $
*/
#include <sys/types.h>
@ -526,7 +526,9 @@ datalink_LayerFinish(void *v, struct fsm *fp)
struct datalink *dl = (struct datalink *)v;
if (fp->proto == PROTO_LCP) {
fsm_Down(fp); /* Bring us to INITIAL or STARTING */
if (fp->state == ST_STOPPED)
fsm_Close(fp); /* back to CLOSED */
fsm_Down(fp); /* Bring us to INITIAL or STARTING */
(*dl->parent->LayerFinish)(dl->parent->object, fp);
datalink_ComeDown(dl, 0);
} else if (fp->state == ST_CLOSED && fp->open_mode == OPEN_PASSIVE)
@ -761,6 +763,8 @@ datalink_Down(struct datalink *dl, int stay)
case DATALINK_AUTH:
case DATALINK_LCP:
if (dl->physical->link.lcp.fsm.state == ST_STOPPED)
fsm_Close(&dl->physical->link.lcp.fsm); /* back to CLOSED */
fsm_Down(&dl->physical->link.lcp.fsm);
if (stay)
fsm_Close(&dl->physical->link.lcp.fsm);
@ -965,7 +969,6 @@ iov2datalink(struct bundle *bundle, struct iovec *iov, int *niov, int maxiov,
free(oname);
} else {
dl->name = strdup(dl->name);
dl->physical->link.name = dl->name;
free(iov[*niov].iov_base);
}
(*niov)++;
@ -1076,7 +1079,8 @@ datalink_NextName(struct datalink *dl)
n = sprintf(name, "%.*s-", dl->name[f] == '-' ? f : f + 1, dl->name);
sprintf(name + n, "%d", atoi(dl->name + f + 1) + 1);
oname = dl->name;
dl->physical->link.name = dl->name = name;
dl->name = name;
/* our physical link name isn't updated (it probably isn't created yet) */
return oname;
}

View File

@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: main.c,v 1.123 1998/05/21 21:46:40 brian Exp $
* $Id: main.c,v 1.124 1998/05/23 22:24:43 brian Exp $
*
* TODO:
*/
@ -476,8 +476,6 @@ DoLoop(struct bundle *bundle, struct prompt *prompt)
FD_ZERO(&wfds);
FD_ZERO(&efds);
sig_Handle();
/* All our datalinks, the tun device and the MP socket */
descriptor_UpdateSet(&bundle->desc, &rfds, &wfds, &efds, &nfds);
@ -490,11 +488,7 @@ DoLoop(struct bundle *bundle, struct prompt *prompt)
i = select(nfds, &rfds, &wfds, &efds, NULL);
if (i == 0)
continue;
else if (i < 0) {
if (errno == EINTR)
continue;
if (i < 0 && errno != EINTR) {
log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno));
if (log_IsKept(LogTIMER)) {
struct timeval t;
@ -532,6 +526,11 @@ DoLoop(struct bundle *bundle, struct prompt *prompt)
break;
}
sig_Handle();
if (i <= 0)
continue;
for (i = 0; i <= nfds; i++)
if (FD_ISSET(i, &efds)) {
log_Printf(LogALERT, "Exception detected on descriptor %d\n", i);
@ -549,6 +548,7 @@ DoLoop(struct bundle *bundle, struct prompt *prompt)
if (descriptor_IsSet(&bundle->desc, &rfds))
descriptor_Read(&bundle->desc, bundle, &rfds);
} while (bundle_CleanDatalinks(bundle), !bundle_IsDead(bundle));
log_Printf(LogDEBUG, "DoLoop done.\n");

View File

@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: modem.c,v 1.82 1998/05/21 22:55:08 brian Exp $
* $Id: modem.c,v 1.83 1998/05/23 22:24:44 brian Exp $
*
* TODO:
*/
@ -954,6 +954,8 @@ modem_DescriptorRead(struct descriptor *d, struct bundle *bundle,
log_WritePrompts(p->dl, rbuff, cp - rbuff);
log_WritePrompts(p->dl, "\r\n", 2);
}
log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n",
p->link.name);
datalink_Up(p->dl, 0, 1);
} else
log_WritePrompts(p->dl, rbuff, n);
@ -1030,6 +1032,7 @@ iov2modem(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, int fd)
modem_StartTimer(dl->bundle, p);
}
/* Don't need to lock the device in -direct mode */
/* XXX: What if it's not a -direct link ! */
return p;
}
@ -1048,7 +1051,8 @@ modem2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov)
timer_Stop(&p->link.ccp.fsm.StoppedTimer);
if (p->Timer.state != TIMER_STOPPED) {
timer_Stop(&p->Timer);
p->Timer.state = TIMER_RUNNING; /* Special - see iov2modem() */
if (!physical_IsATTY(p) || p->fd != STDIN_FILENO)
p->Timer.state = TIMER_RUNNING; /* Special - see iov2modem() */
}
timer_Stop(&p->link.throughput.Timer);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp.c,v 1.4 1998/05/23 17:05:28 brian Exp $
* $Id: mp.c,v 1.5 1998/05/23 22:24:46 brian Exp $
*/
#include <sys/types.h>
@ -861,7 +861,6 @@ mpserver_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
result -= datalink_RemoveFromSet(s->send.dl, r, w, e);
bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
s->send.dl = NULL;
close(s->fd);
s->fd = -1;
} else
/* Never read from a datalink that's on death row ! */
@ -899,8 +898,8 @@ mpserver_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
if (in.sa_family == AF_LOCAL)
bundle_ReceiveDatalink(bundle, fd, (struct sockaddr_un *)&in);
close(fd);
else
close(fd);
}
static void
@ -994,7 +993,6 @@ mpserver_Close(struct mpserver *s)
if (s->send.dl != NULL) {
bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
s->send.dl = NULL;
close(s->fd);
s->fd = -1;
} else if (s->fd >= 0) {
close(s->fd);