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:
parent
b1ac9332fd
commit
96c9bb21aa
@ -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);
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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()) */
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user