o Transfer file descriptors using {send,recv}msg & SCM_RIGHTS,

using the scatter/gather array to transfer the link
  information.  The whole link is now passed in one message.

This is far better than the two `/bin/cat' processes per additional
link :-)  I remember years ago thinking that file descriptor
transferral would be a really amazing facility !

Suggested by: Garrett Wollman <wollman@khavrinen.lcs.mit.edu>
         and: Eivind Eklund <eivind@yes.no>
This commit is contained in:
Brian Somers 1998-05-02 21:57:50 +00:00
parent b1ac9332fd
commit 96c9bb21aa
8 changed files with 219 additions and 277 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.1.2.67 1998/05/01 19:22:09 brian Exp $
* $Id: bundle.c,v 1.1.2.68 1998/05/01 19:23:55 brian Exp $
*/
#include <sys/types.h>
@ -45,6 +45,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <termios.h>
#include <unistd.h>
@ -81,6 +82,10 @@
#include "datalink.h"
#include "ip.h"
#define SCATTER_SEGMENTS 4 /* version, datalink, name, physical */
#define SOCKET_OVERHEAD 100 /* additional buffer space for large */
/* {recv,send}msg() calls */
static const char *PhaseNames[] = {
"Dead", "Establish", "Authenticate", "Network", "Terminate"
};
@ -1087,43 +1092,68 @@ bundle_GetLabel(struct bundle *bundle)
}
void
bundle_ReceiveDatalink(struct bundle *bundle, int fd)
bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun)
{
char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int)];
struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf;
struct msghdr msg;
struct iovec iov[SCATTER_SEGMENTS];
struct datalink *dl, *ndl;
u_char *buf;
int get, got, vlen;
/*
* We expect:
* .---------.---------.--------------.
* | ver len | Version | datalink len |
* `---------'---------'--------------'
* We then pass the rest of the stream to datalink.
*/
int niov, link_fd, expect, f;
log_Printf(LogPHASE, "Receiving datalink\n");
vlen = strlen(Version);
get = sizeof(int) * 2 + vlen;
buf = (u_char *)malloc(get);
got = fullread(fd, buf, get);
if (got != get) {
log_Printf(LogWARN, "Cannot receive datalink header"
" (got %d bytes, not %d)\n", got, get);
close(fd);
free(buf);
/* Create our scatter/gather array */
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)
return;
}
if (*(int *)buf != vlen || *(int *)(buf + sizeof(int) + vlen) != sizeof *dl ||
memcmp(buf + sizeof(int), Version, vlen)) {
log_Printf(LogWARN, "Cannot receive datalink, incorrect version\n");
close(fd);
free(buf);
return;
}
free(buf);
ndl = datalink_FromBinary(bundle, fd);
for (f = expect = 0; f < niov; f++)
expect += iov[f].iov_len;
/* Set up our message */
cmsg->cmsg_len = sizeof cmsgbuf;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
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;
log_Printf(LogDEBUG, "Expecting %d scatter/gather bytes\n", expect);
f = expect + 100;
setsockopt(s, SOL_SOCKET, SO_RCVBUF, &f, sizeof f);
if ((f = recvmsg(s, &msg, MSG_WAITALL)) != expect) {
if (f == -1)
log_Printf(LogERROR, "Failed recvmsg: %s\n", strerror(errno));
else
log_Printf(LogERROR, "Failed recvmsg: Got %d, not %d\n", f, expect);
while (niov--)
free(iov[niov].iov_base);
return;
}
/* We've successfully received an open file descriptor through our socket */
link_fd = *(int *)CMSG_DATA(cmsg);
if (strncmp(Version, iov[0].iov_base, iov[0].iov_len)) {
log_Printf(LogWARN, "Cannot receive datalink, incorrect version"
" (\"%.*s\", not \"%s\")\n", (int)iov[0].iov_len,
iov[0].iov_base, Version);
close(link_fd);
while (niov--)
free(iov[niov].iov_base);
return;
}
niov = 1;
ndl = iov2datalink(bundle, iov, &niov, sizeof iov / sizeof *iov, link_fd);
if (ndl) {
/* Make sure the name is unique ! */
do {
@ -1140,24 +1170,22 @@ bundle_ReceiveDatalink(struct bundle *bundle, int fd)
log_Printf(LogPHASE, "%s: Created in %s state\n",
ndl->name, datalink_State(ndl));
datalink_AuthOk(ndl);
}
} else
close(link_fd);
free(iov[0].iov_base);
}
void
bundle_SendDatalink(struct datalink *dl, int ppp_fd)
bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun)
{
int len, link_fd, err, nfd, flags;
char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int)]; /* pass ppp_fd */
struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf;
struct msghdr msg;
struct iovec iov[SCATTER_SEGMENTS];
int niov, link_fd, f, expect;
struct datalink **pdl;
struct bundle *bundle = dl->bundle;
char procname[100];
/*
* We send:
* .---------.---------.--------------.
* | ver len | Version | datalink len |
* `---------'---------'--------------'
* We then pass the rest of the stream to datalink.
*/
log_Printf(LogPHASE, "Transmitting datalink %s\n", dl->name);
@ -1169,70 +1197,39 @@ bundle_SendDatalink(struct datalink *dl, int ppp_fd)
break;
}
/* Write our bit of the data */
err = 0;
len = strlen(Version);
if (write(ppp_fd, &len, sizeof len) != sizeof len)
err++;
if (write(ppp_fd, Version, len) != len)
err++;
len = sizeof(struct datalink);
if (write(ppp_fd, &len, sizeof len) != sizeof len)
err++;
/* Build our scatter/gather array */
iov[0].iov_len = strlen(Version) + 1;
iov[0].iov_base = strdup(Version);
niov = 1;
if (err) {
log_Printf(LogERROR, "Failed sending version\n");
close(ppp_fd);
ppp_fd = -1;
}
link_fd = datalink_ToBinary(dl, ppp_fd);
link_fd = datalink2iov(dl, iov, &niov, sizeof iov / sizeof *iov);
if (link_fd != -1) {
switch (fork()) {
case 0:
timer_TermService();
cmsg->cmsg_len = sizeof cmsgbuf;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = link_fd;
ppp_fd = fcntl(ppp_fd, F_DUPFD, 3);
link_fd = fcntl(link_fd, F_DUPFD, 3);
nfd = dup2(open(_PATH_DEVNULL, O_WRONLY), STDERR_FILENO);
fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */
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;
setsid();
setuid(geteuid());
for (f = expect = 0; f < niov; f++)
expect += iov[f].iov_len;
flags = fcntl(ppp_fd, F_GETFL, 0);
fcntl(ppp_fd, F_SETFL, flags & ~O_NONBLOCK);
flags = fcntl(link_fd, F_GETFL, 0);
fcntl(link_fd, F_SETFL, flags & ~O_NONBLOCK);
log_Printf(LogDEBUG, "Sending %d bytes in scatter/gather array\n", expect);
switch (fork()) {
case 0:
dup2(ppp_fd, STDIN_FILENO);
dup2(link_fd, STDOUT_FILENO);
snprintf(procname, sizeof procname, "%s -> %s",
dl->name, *dl->physical->name.base ?
dl->physical->name.base : "network");
execl(CATPROG, procname, NULL);
log_Printf(LogERROR, "exec: %s: %s\n", CATPROG, strerror(errno));
break;
case -1:
break;
default:
dup2(link_fd, STDIN_FILENO);
dup2(ppp_fd, STDOUT_FILENO);
snprintf(procname, sizeof procname, "%s <- %s",
dl->name, *dl->physical->name.base ?
dl->physical->name.base : "network");
execl(CATPROG, procname, NULL);
log_Printf(LogERROR, "exec: %s: %s\n", CATPROG, strerror(errno));
break;
}
exit(1);
break;
case -1:
log_Printf(LogERROR, "fork: %s\n", strerror(errno));
break;
}
f = expect + SOCKET_OVERHEAD;
setsockopt(s, SOL_SOCKET, SO_SNDBUF, &f, sizeof f);
if (sendmsg(s, &msg, 0) == -1)
log_Printf(LogERROR, "Failed sendmsg: %s\n", strerror(errno));
close(link_fd);
}
while (niov--)
free(iov[niov].iov_base);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: bundle.h,v 1.1.2.33 1998/04/28 01:25:05 brian Exp $
* $Id: bundle.h,v 1.1.2.34 1998/04/30 23:53:22 brian Exp $
*/
#define PHASE_DEAD 0 /* Link is dead */
@ -44,6 +44,7 @@
#define Enabled(b, o) ((b)->cfg.opt & (o))
struct sockaddr_un;
struct datalink;
struct physical;
struct link;
@ -139,5 +140,5 @@ extern void bundle_DatalinkRemove(struct bundle *, struct datalink *);
extern void bundle_CleanDatalinks(struct bundle *);
extern void bundle_SetLabel(struct bundle *, const char *);
extern const char *bundle_GetLabel(struct bundle *);
extern void bundle_SendDatalink(struct datalink *, int);
extern void bundle_ReceiveDatalink(struct bundle *, int);
extern void bundle_SendDatalink(struct datalink *, int, struct sockaddr_un *);
extern void bundle_ReceiveDatalink(struct bundle *, int, struct sockaddr_un *);

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.1.2.52 1998/05/01 19:20:01 brian Exp $
* $Id: datalink.c,v 1.1.2.53 1998/05/01 19:24:23 brian Exp $
*/
#include <sys/types.h>
@ -36,6 +36,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/uio.h>
#include <termios.h>
#include <unistd.h>
@ -916,49 +917,22 @@ datalink_State(struct datalink *dl)
}
struct datalink *
datalink_FromBinary(struct bundle *bundle, int fd)
iov2datalink(struct bundle *bundle, struct iovec *iov, int *niov, int maxiov,
int fd)
{
struct datalink *dl = (struct datalink *)malloc(sizeof(struct datalink));
struct datalink *dl;
u_int retry;
int got, get;
/*
* We expect:
* .----------.----------.------.--------------.
* | datalink | name len | name | physical len |
* `----------'----------'------'--------------'
* We then pass the rest of the stream to physical.
*/
dl = (struct datalink *)iov[(*niov)++].iov_base;
dl->name = iov[*niov].iov_base;
got = fullread(fd, dl, sizeof *dl);
if (got != sizeof *dl) {
log_Printf(LogWARN, "Cannot receive datalink"
" (got %d bytes, not %d)\n", got, sizeof *dl);
close(fd);
free(dl);
return NULL;
if (dl->name[DATALINK_MAXNAME-1]) {
dl->name[DATALINK_MAXNAME-1] = '\0';
if (strlen(dl->name) == DATALINK_MAXNAME - 1)
log_Printf(LogWARN, "Datalink name truncated to \"%s\"\n", dl->name);
}
got = fullread(fd, &get, sizeof get);
if (got != sizeof get) {
log_Printf(LogWARN, "Cannot receive name length"
" (got %d bytes, not %d)\n", got, sizeof get);
close(fd);
free(dl);
return NULL;
}
dl->name = (char *)malloc(get + 1);
got = fullread(fd, dl->name, get);
if (got != get) {
log_Printf(LogWARN, "Cannot receive name"
" (got %d bytes, not %d)\n", got, get);
close(fd);
free(dl->name);
free(dl);
return NULL;
}
dl->name[get] = '\0';
dl->name = strdup(dl->name);
free(iov[(*niov)++].iov_base);
dl->desc.type = DATALINK_DESCRIPTOR;
dl->desc.next = NULL;
@ -993,15 +967,9 @@ datalink_FromBinary(struct bundle *bundle, int fd)
auth_Init(&dl->chap.auth);
dl->chap.auth.cfg.fsmretry = retry;
got = fullread(fd, &get, sizeof get);
if (got != sizeof get) {
log_Printf(LogWARN, "Cannot receive physical length"
" (got %d bytes, not %d)\n", got, sizeof get);
close(fd);
free(dl->name);
free(dl);
dl = NULL;
} else if ((dl->physical = modem_FromBinary(dl, fd)) == NULL) {
dl->physical = iov2modem(dl, iov, niov, maxiov, fd);
if (!dl->physical) {
free(dl->name);
free(dl);
dl = NULL;
@ -1012,47 +980,38 @@ datalink_FromBinary(struct bundle *bundle, int fd)
}
int
datalink_ToBinary(struct datalink *dl, int fd)
datalink2iov(struct datalink *dl, struct iovec *iov, int *niov, int maxiov)
{
int len, link_fd;
/* If `dl' is NULL, we're allocating before a Fromiov() */
int link_fd;
/*
* We send:
* .----------.----------.------.--------------.
* | datalink | name len | name | physical len |
* `----------'----------'------'--------------'
*/
timer_Stop(&dl->dial_timer);
timer_Stop(&dl->pap.authtimer);
timer_Stop(&dl->chap.auth.authtimer);
if (fd != -1) {
int err;
err = 0;
if (write(fd, dl, sizeof *dl) != sizeof *dl)
err++;
len = strlen(dl->name);
if (write(fd, &len, sizeof(int)) != sizeof(int))
err++;
if (write(fd, dl->name, len) != len)
err++;
len = sizeof(struct physical);
if (write(fd, &len, sizeof(int)) != sizeof(int))
err++;
if (err) {
log_Printf(LogERROR, "Failed sending datalink\n");
close(fd);
fd = -1;
}
if (dl) {
timer_Stop(&dl->dial_timer);
timer_Stop(&dl->pap.authtimer);
timer_Stop(&dl->chap.auth.authtimer);
}
link_fd = modem_ToBinary(dl->physical, fd);
if (*niov >= maxiov - 1) {
log_Printf(LogERROR, "Toiov: No room for datalink !\n");
if (dl) {
free(dl->name);
free(dl);
}
return -1;
}
free(dl->name);
free(dl);
iov[*niov].iov_base = dl ? dl : malloc(sizeof *dl);
iov[(*niov)++].iov_len = sizeof *dl;
iov[*niov].iov_base =
dl ? realloc(dl->name, DATALINK_MAXNAME) : malloc(DATALINK_MAXNAME);
iov[(*niov)++].iov_len = DATALINK_MAXNAME;
link_fd = modem2iov(dl ? dl->physical : NULL, iov, niov, maxiov);
if (link_fd == -1 && dl) {
free(dl->name);
free(dl);
}
return 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.h,v 1.1.2.20 1998/04/30 23:53:33 brian Exp $
* $Id: datalink.h,v 1.1.2.21 1998/05/01 19:24:24 brian Exp $
*/
#define DATALINK_CLOSED (0)
@ -36,6 +36,9 @@
#define DATALINK_AUTH (7)
#define DATALINK_OPEN (8)
#define DATALINK_MAXNAME (20)
struct iovec;
struct prompt;
struct physical;
struct bundle;
@ -105,8 +108,9 @@ struct datalink {
extern struct datalink *datalink_Create(const char *name, struct bundle *, int);
extern struct datalink *datalink_Clone(struct datalink *, const char *);
extern struct datalink *datalink_FromBinary(struct bundle *, int);
extern int datalink_ToBinary(struct datalink *, int);
extern struct datalink *iov2datalink(struct bundle *, struct iovec *, int *,
int, int);
extern int datalink2iov(struct datalink *, struct iovec *, int *, int);
extern struct datalink *datalink_Destroy(struct datalink *);
extern void datalink_GotAuthname(struct datalink *, const char *, int);
extern void datalink_Up(struct datalink *, int, int);

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.77.2.62 1998/05/01 19:22:19 brian Exp $
* $Id: modem.c,v 1.77.2.63 1998/05/01 19:25:25 brian Exp $
*
* TODO:
*/
@ -38,6 +38,7 @@
#include <string.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/uio.h>
#include <unistd.h>
#ifdef __OpenBSD__
#include <util.h>
@ -906,26 +907,11 @@ modem_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
}
struct physical *
modem_FromBinary(struct datalink *dl, int fd)
iov2modem(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, int fd)
{
struct physical *p = (struct physical *)malloc(sizeof(struct physical));
int got;
struct physical *p;
/*
* We expect:
* .----------.
* | physical |
* `----------'
*/
got = fullread(fd, p, sizeof *p);
if (got != sizeof *p) {
log_Printf(LogWARN, "Cannot receive physical"
" (got %d bytes, not %d)\n", got, sizeof *p);
close(fd);
free(p);
return NULL;
}
p = (struct physical *)iov[(*niov)++].iov_base;
p->link.name = dl->name;
throughput_init(&p->link.throughput);
memset(&p->Timer, '\0', sizeof p->Timer);
@ -970,7 +956,7 @@ modem_FromBinary(struct datalink *dl, int fd)
lqr_Start(&p->link.lcp);
hdlc_StartTimer(&p->hdlc);
p->fd = fd; /* Now talk down it :-) */
p->fd = fd;
throughput_start(&p->link.throughput, "modem throughput",
Enabled(dl->bundle, OPT_THROUGHPUT));
/* Don't need a modem timer.... */
@ -980,36 +966,31 @@ modem_FromBinary(struct datalink *dl, int fd)
}
int
modem_ToBinary(struct physical *p, int fd)
modem2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov)
{
int link_fd;
/*
* We send:
* .----------.
* | physical |
* `----------'
*/
hdlc_StopTimer(&p->hdlc);
lqr_StopTimer(p);
timer_Stop(&p->link.lcp.fsm.FsmTimer);
timer_Stop(&p->link.ccp.fsm.FsmTimer);
timer_Stop(&p->link.lcp.fsm.OpenTimer);
timer_Stop(&p->link.ccp.fsm.OpenTimer);
timer_Stop(&p->link.lcp.fsm.StoppedTimer);
timer_Stop(&p->link.ccp.fsm.StoppedTimer);
timer_Stop(&p->Timer);
timer_Stop(&p->link.throughput.Timer);
if (fd != -1 && write(fd, p, sizeof *p) != sizeof *p) {
log_Printf(LogERROR, "Failed sending physical\n");
close(fd);
fd = -1;
if (p) {
hdlc_StopTimer(&p->hdlc);
lqr_StopTimer(p);
timer_Stop(&p->link.lcp.fsm.FsmTimer);
timer_Stop(&p->link.ccp.fsm.FsmTimer);
timer_Stop(&p->link.lcp.fsm.OpenTimer);
timer_Stop(&p->link.ccp.fsm.OpenTimer);
timer_Stop(&p->link.lcp.fsm.StoppedTimer);
timer_Stop(&p->link.ccp.fsm.StoppedTimer);
timer_Stop(&p->Timer);
timer_Stop(&p->link.throughput.Timer);
}
link_fd = p->fd;
free(p);
if (*niov >= maxiov) {
log_Printf(LogERROR, "ToBinary: No room for physical !\n");
if (p)
free(p);
return -1;
}
return link_fd;
iov[*niov].iov_base = p ? p : malloc(sizeof *p);
iov[*niov].iov_len = sizeof *p;
(*niov)++;
return p ? p->fd : 0;
}

View File

@ -15,11 +15,12 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: modem.h,v 1.16.2.15 1998/04/10 13:19:14 brian Exp $
* $Id: modem.h,v 1.16.2.16 1998/04/30 23:53:50 brian Exp $
*
* TODO:
*/
struct iovec;
struct datalink;
struct physical;
struct bundle;
@ -36,5 +37,6 @@ extern int modem_ShowStatus(struct cmdargs const *);
extern void modem_Close(struct physical *);
extern void modem_Offline(struct physical *);
extern void modem_Destroy(struct physical *);
extern struct physical *modem_FromBinary(struct datalink *, int);
extern int modem_ToBinary(struct physical *, int fd);
extern struct physical *iov2modem(struct datalink *, struct iovec *, int *,
int, int);
extern int modem2iov(struct physical *, struct iovec *, int *, int);

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.1.2.18 1998/04/30 23:53:51 brian Exp $
* $Id: mp.c,v 1.1.2.19 1998/05/01 19:25:27 brian Exp $
*/
#include <sys/types.h>
@ -200,7 +200,6 @@ int
mp_Up(struct mp *mp, struct datalink *dl)
{
struct lcp *lcp = &dl->physical->link.lcp;
int fd;
if (mp->active) {
/* We're adding a link - do a last validation on our parameters */
@ -239,16 +238,15 @@ mp_Up(struct mp *mp, struct datalink *dl)
* Now we create our server socket.
* If it already exists, join it. Otherwise, create and own it
*/
fd = mpserver_Open(&mp->server, &mp->peer);
if (fd >= 0) {
switch (mpserver_Open(&mp->server, &mp->peer)) {
case MPSERVER_CONNECTED:
log_Printf(LogPHASE, "mp: Transfer link on %s\n",
mp->server.socket.sun_path);
mp->server.send.dl = dl;
mp->server.send.fd = fd;
mp->server.send.dl = dl; /* Defer 'till it's safe to send */
return MP_LINKSENT;
} else if (!mpserver_IsOpen(&mp->server))
case MPSERVER_FAILED:
return MP_FAILED;
else {
case MPSERVER_LISTENING:
log_Printf(LogPHASE, "mp: Listening on %s\n", mp->server.socket.sun_path);
log_Printf(LogPHASE, " First link: %s\n", dl->name);
@ -260,6 +258,7 @@ mp_Up(struct mp *mp, struct datalink *dl)
fsm_Open(&mp->link.ccp.fsm);
mp->active = 1;
break;
}
}
@ -787,12 +786,12 @@ mpserver_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
struct mpserver *s = descriptor2mpserver(d);
if (s->send.dl != NULL) {
bundle_SendDatalink(s->send.dl, s->send.fd);
/* We've connect()ed */
bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
s->send.dl = NULL;
s->send.fd = -1;
}
if (r && s->fd >= 0) {
close(s->fd);
s->fd = -1;
} else if (r && s->fd >= 0) {
if (*n < s->fd + 1)
*n = s->fd + 1;
FD_SET(s->fd, r);
@ -822,10 +821,10 @@ mpserver_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
return;
}
if (in.sa_family != AF_LOCAL) /* ??? */
close(fd);
else
bundle_ReceiveDatalink(bundle, fd);
if (in.sa_family == AF_LOCAL) /* ??? */
bundle_ReceiveDatalink(bundle, fd, (struct sockaddr_un *)&in);
close(fd);
}
static void
@ -845,7 +844,6 @@ mpserver_Init(struct mpserver *s)
s->desc.Read = mpserver_Read;
s->desc.Write = mpserver_Write;
s->send.dl = NULL;
s->send.fd = -1;
s->fd = -1;
memset(&s->socket, '\0', sizeof s->socket);
}
@ -853,7 +851,7 @@ mpserver_Init(struct mpserver *s)
int
mpserver_Open(struct mpserver *s, struct peerid *peer)
{
int f, l, fd;
int f, l;
mode_t mask;
if (s->fd != -1) {
@ -875,7 +873,7 @@ mpserver_Open(struct mpserver *s, struct peerid *peer)
s->fd = ID0socket(PF_LOCAL, SOCK_STREAM, 0);
if (s->fd < 0) {
log_Printf(LogERROR, "mpserver: socket: %s\n", strerror(errno));
return -1;
return MPSERVER_FAILED;
}
setsockopt(s->fd, SOL_SOCKET, SO_REUSEADDR, (struct sockaddr *)&s->socket,
@ -888,7 +886,7 @@ mpserver_Open(struct mpserver *s, struct peerid *peer)
umask(mask);
close(s->fd);
s->fd = -1;
return -1;
return MPSERVER_FAILED;
}
umask(mask);
if (ID0connect_un(s->fd, &s->socket) < 0) {
@ -898,13 +896,11 @@ mpserver_Open(struct mpserver *s, struct peerid *peer)
log_Printf(LogPHASE, " Has the previous server died badly ?\n");
close(s->fd);
s->fd = -1;
return -1;
return MPSERVER_FAILED;
}
/* Donate our link to the other guy */
fd = s->fd;
s->fd = -1;
return fd;
return MPSERVER_CONNECTED;
}
/* Listen for other ppp invocations that want to donate links */
@ -914,19 +910,18 @@ mpserver_Open(struct mpserver *s, struct peerid *peer)
mpserver_Close(s);
}
return -1;
return MPSERVER_LISTENING;
}
void
mpserver_Close(struct mpserver *s)
{
if (s->send.dl != NULL) {
bundle_SendDatalink(s->send.dl, s->send.fd);
bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
s->send.dl = NULL;
s->send.fd = -1;
}
if (s->fd >= 0) {
close(s->fd);
s->fd = -1;
} else if (s->fd >= 0) {
close(s->fd);
if (ID0unlink(s->socket.sun_path) == -1)
log_Printf(LogERROR, "%s: Failed to remove: %s\n", s->socket.sun_path,

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp.h,v 1.1.2.9 1998/04/30 23:53:52 brian Exp $
* $Id: mp.h,v 1.1.2.10 1998/05/01 19:25:28 brian Exp $
*/
struct mbuf;
@ -44,6 +44,10 @@ struct datalink;
#define MP_ADDED 2 /* We've added the link to our MP */
#define MP_FAILED 3 /* No go */
#define MPSERVER_CONNECTED 0
#define MPSERVER_LISTENING 1
#define MPSERVER_FAILED 2
struct enddisc {
u_char class;
char address[50];
@ -57,12 +61,11 @@ struct peerid {
struct mpserver {
struct descriptor desc;
int fd; /* listen()ing here */
int fd; /* listen()ing or connect()ing here */
struct sockaddr_un socket; /* On this socket */
struct {
struct datalink *dl; /* Send this datalink through */
int fd; /* this descriptor when it's safe */
struct datalink *dl; /* Send this datalink */
} send; /* (in UpdateSet()) */
};