freebsd-dev/usr.sbin/ppp/physical.c

1070 lines
28 KiB
C
Raw Normal View History

/*
* Written by Eivind Eklund <eivind@yes.no>
* for Yes Interactive
*
* Copyright (C) 1998, Yes Interactive. All rights reserved.
*
* Redistribution and use in any form is permitted. Redistribution in
* source form should include the above copyright and this set of
* conditions, because large sections american law seems to have been
* created by a bunch of jerks on drugs that are now illegal, forcing
* me to include this copyright-stuff instead of placing this in the
* public domain. The name of of 'Yes Interactive' or 'Eivind Eklund'
* may not be used to endorse or promote products derived from this
* software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
1999-08-28 01:35:59 +00:00
* $FreeBSD$
*
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/un.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/tty.h> /* TIOCOUTQ */
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>
#include <utmp.h>
#if defined(__OpenBSD__) || defined(__NetBSD__)
#include <sys/ioctl.h>
#include <util.h>
#else
#include <libutil.h>
#endif
#include "layer.h"
#ifndef NONAT
#include "nat_cmd.h"
#endif
#include "proto.h"
#include "acf.h"
#include "vjcomp.h"
#include "defs.h"
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "id.h"
#include "timer.h"
#include "fsm.h"
#include "lqr.h"
#include "hdlc.h"
#include "lcp.h"
#include "throughput.h"
#include "sync.h"
#include "async.h"
#include "iplist.h"
#include "slcompress.h"
#include "ipcp.h"
#include "filter.h"
#include "descriptor.h"
#include "ccp.h"
#include "link.h"
#include "physical.h"
#include "mp.h"
#ifndef NORADIUS
#include "radius.h"
#endif
#include "bundle.h"
#include "prompt.h"
#include "chat.h"
#include "auth.h"
#include "chap.h"
#include "cbcp.h"
#include "datalink.h"
#include "tcp.h"
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
#include "udp.h"
#include "exec.h"
#include "tty.h"
#ifndef NOI4B
#include "i4b.h"
#endif
#define PPPOTCPLINE "ppp"
static int physical_DescriptorWrite(struct descriptor *, struct bundle *,
const fd_set *);
static void physical_DescriptorRead(struct descriptor *, struct bundle *,
const fd_set *);
static int
physical_DeviceSize(void)
{
return sizeof(struct device);
}
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
struct {
struct device *(*create)(struct physical *);
struct device *(*iov2device)(int, struct physical *, struct iovec *iov,
int *niov, int maxiov);
int (*DeviceSize)(void);
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
} devices[] = {
#ifndef NOI4B
{ i4b_Create, i4b_iov2device, i4b_DeviceSize },
#endif
{ tty_Create, tty_iov2device, tty_DeviceSize },
{ tcp_Create, tcp_iov2device, tcp_DeviceSize },
{ udp_Create, udp_iov2device, udp_DeviceSize },
{ exec_Create, exec_iov2device, exec_DeviceSize }
};
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
#define NDEVICES (sizeof devices / sizeof devices[0])
static int
physical_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
int *n)
{
return physical_doUpdateSet(d, r, w, e, n, 0);
}
struct physical *
physical_Create(struct datalink *dl, int type)
{
struct physical *p;
p = (struct physical *)malloc(sizeof(struct physical));
if (!p)
return NULL;
p->link.type = PHYSICAL_LINK;
p->link.name = dl->name;
p->link.len = sizeof *p;
/* The sample period is fixed - see physical2iov() & iov2physical() */
throughput_init(&p->link.throughput, SAMPLE_PERIOD);
memset(p->link.Queue, '\0', sizeof p->link.Queue);
memset(p->link.proto_in, '\0', sizeof p->link.proto_in);
memset(p->link.proto_out, '\0', sizeof p->link.proto_out);
link_EmptyStack(&p->link);
p->handler = NULL;
p->desc.type = PHYSICAL_DESCRIPTOR;
p->desc.UpdateSet = physical_UpdateSet;
p->desc.IsSet = physical_IsSet;
p->desc.Read = physical_DescriptorRead;
p->desc.Write = physical_DescriptorWrite;
p->type = type;
hdlc_Init(&p->hdlc, &p->link.lcp);
async_Init(&p->async);
p->fd = -1;
p->out = NULL;
p->connect_count = 0;
p->dl = dl;
p->input.sz = 0;
*p->name.full = '\0';
p->name.base = p->name.full;
p->Utmp = 0;
p->session_owner = (pid_t)-1;
p->cfg.rts_cts = MODEM_CTSRTS;
p->cfg.speed = MODEM_SPEED;
p->cfg.parity = CS8;
memcpy(p->cfg.devlist, MODEM_LIST, sizeof MODEM_LIST);
p->cfg.ndev = NMODEMS;
p->cfg.cd.necessity = CD_VARIABLE;
p->cfg.cd.delay = DEF_CDDELAY;
lcp_Init(&p->link.lcp, dl->bundle, &p->link, &dl->fsmp);
ccp_Init(&p->link.ccp, dl->bundle, &p->link, &dl->fsmp);
return p;
}
static const struct parity {
const char *name;
const char *name1;
int set;
} validparity[] = {
{ "even", "P_EVEN", CS7 | PARENB },
{ "odd", "P_ODD", CS7 | PARENB | PARODD },
{ "none", "P_ZERO", CS8 },
{ NULL, 0 },
};
static int
GetParityValue(const char *str)
{
const struct parity *pp;
for (pp = validparity; pp->name; pp++) {
if (strcasecmp(pp->name, str) == 0 ||
strcasecmp(pp->name1, str) == 0) {
return pp->set;
}
}
return (-1);
}
int
physical_SetParity(struct physical *p, const char *str)
{
struct termios rstio;
int val;
val = GetParityValue(str);
if (val > 0) {
p->cfg.parity = val;
if (p->fd >= 0) {
tcgetattr(p->fd, &rstio);
rstio.c_cflag &= ~(CSIZE | PARODD | PARENB);
rstio.c_cflag |= val;
tcsetattr(p->fd, TCSADRAIN, &rstio);
}
return 0;
}
log_Printf(LogWARN, "%s: %s: Invalid parity\n", p->link.name, str);
return -1;
}
int
physical_GetSpeed(struct physical *p)
{
if (p->handler && p->handler->speed)
return (*p->handler->speed)(p);
return 0;
}
int
physical_SetSpeed(struct physical *p, int speed)
{
if (IntToSpeed(speed) != B0) {
p->cfg.speed = speed;
return 1;
}
return 0;
}
int
physical_Raw(struct physical *p)
{
if (p->handler && p->handler->raw)
return (*p->handler->raw)(p);
return 1;
}
void
physical_Offline(struct physical *p)
{
if (p->handler && p->handler->offline)
(*p->handler->offline)(p);
log_Printf(LogPHASE, "%s: Disconnected!\n", p->link.name);
}
static int
physical_Lock(struct physical *p)
{
int res;
if (*p->name.full == '/' && p->type != PHYS_DIRECT &&
(res = ID0uu_lock(p->name.base)) != UU_LOCK_OK) {
if (res == UU_LOCK_INUSE)
log_Printf(LogPHASE, "%s: %s is in use\n", p->link.name, p->name.full);
else
log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n",
p->link.name, p->name.full, uu_lockerr(res));
return 0;
}
return 1;
}
static void
physical_Unlock(struct physical *p)
{
char fn[MAXPATHLEN];
if (*p->name.full == '/' && p->type != PHYS_DIRECT &&
ID0uu_unlock(p->name.base) == -1)
log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", p->link.name, fn);
}
void
physical_Close(struct physical *p)
{
int newsid;
char fn[MAXPATHLEN];
if (p->fd < 0)
return;
log_Printf(LogDEBUG, "%s: Close\n", p->link.name);
if (p->handler && p->handler->cooked)
(*p->handler->cooked)(p);
physical_StopDeviceTimer(p);
if (p->Utmp) {
if (p->handler && (p->handler->type == TCP_DEVICE ||
p->handler->type == UDP_DEVICE)) {
/*
* We've got to do more than logout() does here... we need to identify
* the entry that we made at login time....
*/
struct utmp ut, want;
char *colon;
int fd;
strncpy(want.ut_line, PPPOTCPLINE, sizeof want.ut_line);
strncpy(want.ut_host, p->name.base, sizeof want.ut_host);
colon = memchr(want.ut_host, ':', sizeof want.ut_host);
if (colon)
*colon = '\0';
if ((fd = ID0open(_PATH_WTMP, O_RDWR, 0)) >= 0) {
lseek(fd, -(off_t)sizeof(struct utmp), L_XTND);
while (read(fd, &ut, sizeof(struct utmp)) == sizeof(struct utmp)) {
if (*ut.ut_name &&
!memcmp(ut.ut_line, want.ut_line, sizeof ut.ut_line) &&
!memcmp(ut.ut_host, want.ut_host, sizeof ut.ut_host) &&
p->Utmp == ut.ut_time) {
memset(ut.ut_name, '\0', sizeof ut.ut_name);
memset(ut.ut_host, '\0', sizeof ut.ut_name);
time(&ut.ut_time);
lseek(fd, 0, L_XTND);
write(fd, &ut, sizeof ut);
*want.ut_line = '\0';
break;
}
lseek(fd, -((off_t)sizeof(struct utmp) << 1), L_INCR);
}
close(fd);
if (*want.ut_line)
log_Printf(LogWARN, "Cannot locate %s/%.*s in %s\n", PPPOTCPLINE,
(int)(sizeof want.ut_host), want.ut_host, _PATH_WTMP);
}
} else
ID0logout(p->name.base);
p->Utmp = 0;
}
newsid = tcgetpgrp(p->fd) == getpgrp();
close(p->fd);
p->fd = -1;
log_SetTtyCommandMode(p->dl);
throughput_stop(&p->link.throughput);
throughput_log(&p->link.throughput, LogPHASE, p->link.name);
if (p->session_owner != (pid_t)-1) {
ID0kill(p->session_owner, SIGHUP);
p->session_owner = (pid_t)-1;
}
if (newsid)
bundle_setsid(p->dl->bundle, 0);
if (*p->name.full == '/') {
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base);
#ifndef RELEASE_CRUNCH
if (ID0unlink(fn) == -1)
log_Printf(LogALERT, "%s: Can't remove %s: %s\n",
p->link.name, fn, strerror(errno));
#else
ID0unlink(fn);
#endif
}
physical_Unlock(p);
if (p->handler && p->handler->destroy)
(*p->handler->destroy)(p);
p->handler = NULL;
p->name.base = p->name.full;
*p->name.full = '\0';
}
void
physical_Destroy(struct physical *p)
{
physical_Close(p);
throughput_destroy(&p->link.throughput);
free(p);
}
static int
physical_DescriptorWrite(struct descriptor *d, struct bundle *bundle,
const fd_set *fdset)
{
struct physical *p = descriptor2physical(d);
int nw, result = 0;
if (p->out == NULL)
p->out = link_Dequeue(&p->link);
if (p->out) {
nw = physical_Write(p, MBUF_CTOP(p->out), p->out->cnt);
log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%d) to %d\n",
p->link.name, nw, p->out->cnt, p->fd);
if (nw > 0) {
p->out->cnt -= nw;
p->out->offset += nw;
if (p->out->cnt == 0)
p->out = mbuf_FreeSeg(p->out);
result = 1;
} else if (nw < 0) {
if (errno != EAGAIN) {
log_Printf(LogPHASE, "%s: write (%d): %s\n", p->link.name,
p->fd, strerror(errno));
datalink_Down(p->dl, CLOSE_NORMAL);
}
result = 1;
}
/* else we shouldn't really have been called ! select() is broken ! */
}
return result;
}
int
physical_ShowStatus(struct cmdargs const *arg)
{
struct physical *p = arg->cx->physical;
const char *dev;
int n;
prompt_Printf(arg->prompt, "Name: %s\n", p->link.name);
prompt_Printf(arg->prompt, " State: ");
if (p->fd < 0)
prompt_Printf(arg->prompt, "closed\n");
else if (p->handler && p->handler->openinfo)
prompt_Printf(arg->prompt, "open (%s)\n", (*p->handler->openinfo)(p));
else
prompt_Printf(arg->prompt, "open\n");
prompt_Printf(arg->prompt, " Device: %s",
*p->name.full ? p->name.full :
p->type == PHYS_DIRECT ? "unknown" : "N/A");
if (p->session_owner != (pid_t)-1)
prompt_Printf(arg->prompt, " (session owner: %d)", (int)p->session_owner);
prompt_Printf(arg->prompt, "\n Link Type: %s\n", mode2Nam(p->type));
prompt_Printf(arg->prompt, " Connect Count: %d\n", p->connect_count);
#ifdef TIOCOUTQ
if (p->fd >= 0 && ioctl(p->fd, TIOCOUTQ, &n) >= 0)
prompt_Printf(arg->prompt, " Physical outq: %d\n", n);
#endif
prompt_Printf(arg->prompt, " Queued Packets: %d\n",
link_QueueLen(&p->link));
prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen);
prompt_Printf(arg->prompt, "\nDefaults:\n");
prompt_Printf(arg->prompt, " Device List: ");
dev = p->cfg.devlist;
for (n = 0; n < p->cfg.ndev; n++) {
if (n)
prompt_Printf(arg->prompt, ", ");
prompt_Printf(arg->prompt, "\"%s\"", dev);
dev += strlen(dev) + 1;
}
prompt_Printf(arg->prompt, "\n Characteristics: ");
if (physical_IsSync(arg->cx->physical))
prompt_Printf(arg->prompt, "sync");
else
prompt_Printf(arg->prompt, "%dbps", p->cfg.speed);
switch (p->cfg.parity & CSIZE) {
case CS7:
prompt_Printf(arg->prompt, ", cs7");
break;
case CS8:
prompt_Printf(arg->prompt, ", cs8");
break;
}
if (p->cfg.parity & PARENB) {
if (p->cfg.parity & PARODD)
prompt_Printf(arg->prompt, ", odd parity");
else
prompt_Printf(arg->prompt, ", even parity");
} else
prompt_Printf(arg->prompt, ", no parity");
prompt_Printf(arg->prompt, ", CTS/RTS %s\n", (p->cfg.rts_cts ? "on" : "off"));
prompt_Printf(arg->prompt, " CD check delay: ");
if (p->cfg.cd.necessity == CD_NOTREQUIRED)
prompt_Printf(arg->prompt, "no cd");
else {
prompt_Printf(arg->prompt, "%d second%s", p->cfg.cd.delay,
p->cfg.cd.delay == 1 ? "" : "s");
if (p->cfg.cd.necessity == CD_REQUIRED)
prompt_Printf(arg->prompt, " (required!)");
}
prompt_Printf(arg->prompt, "\n\n");
throughput_disp(&p->link.throughput, arg->prompt);
return 0;
}
static void
physical_DescriptorRead(struct descriptor *d, struct bundle *bundle,
const fd_set *fdset)
{
struct physical *p = descriptor2physical(d);
u_char *rbuff;
int n, found;
rbuff = p->input.buf + p->input.sz;
/* something to read */
n = physical_Read(p, rbuff, sizeof p->input.buf - p->input.sz);
log_Printf(LogDEBUG, "%s: DescriptorRead: read %d/%d from %d\n",
p->link.name, n, (int)(sizeof p->input.buf - p->input.sz), p->fd);
if (n <= 0) {
if (n < 0)
log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd,
strerror(errno));
else
log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n",
p->link.name, p->fd);
datalink_Down(p->dl, CLOSE_NORMAL);
return;
}
rbuff -= p->input.sz;
n += p->input.sz;
if (p->link.lcp.fsm.state <= ST_CLOSED) {
if (p->type != PHYS_DEDICATED) {
found = hdlc_Detect((u_char const **)&rbuff, n, physical_IsSync(p));
if (rbuff != p->input.buf)
log_WritePrompts(p->dl, "%.*s", (int)(rbuff - p->input.buf),
p->input.buf);
p->input.sz = n - (rbuff - p->input.buf);
if (found) {
/* LCP packet is detected. Turn ourselves into packet mode */
log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n",
p->link.name);
log_SetTtyCommandMode(p->dl);
datalink_Up(p->dl, 0, 1);
link_PullPacket(&p->link, rbuff, p->input.sz, bundle);
p->input.sz = 0;
} else
bcopy(rbuff, p->input.buf, p->input.sz);
} else
/* In -dedicated mode, we just discard input until LCP is started */
p->input.sz = 0;
} else if (n > 0)
link_PullPacket(&p->link, rbuff, n, bundle);
}
struct physical *
iov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov,
int fd)
{
struct physical *p;
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
int len, h, type;
p = (struct physical *)iov[(*niov)++].iov_base;
p->link.name = dl->name;
memset(p->link.Queue, '\0', sizeof p->link.Queue);
p->desc.UpdateSet = physical_UpdateSet;
p->desc.IsSet = physical_IsSet;
p->desc.Read = physical_DescriptorRead;
p->desc.Write = physical_DescriptorWrite;
p->type = PHYS_DIRECT;
p->dl = dl;
len = strlen(_PATH_DEV);
p->out = NULL;
p->connect_count = 1;
physical_SetDevice(p, p->name.full);
p->link.lcp.fsm.bundle = dl->bundle;
p->link.lcp.fsm.link = &p->link;
memset(&p->link.lcp.fsm.FsmTimer, '\0', sizeof p->link.lcp.fsm.FsmTimer);
memset(&p->link.lcp.fsm.OpenTimer, '\0', sizeof p->link.lcp.fsm.OpenTimer);
memset(&p->link.lcp.fsm.StoppedTimer, '\0',
sizeof p->link.lcp.fsm.StoppedTimer);
p->link.lcp.fsm.parent = &dl->fsmp;
lcp_SetupCallbacks(&p->link.lcp);
p->link.ccp.fsm.bundle = dl->bundle;
p->link.ccp.fsm.link = &p->link;
/* Our in.state & out.state are NULL (no link-level ccp yet) */
memset(&p->link.ccp.fsm.FsmTimer, '\0', sizeof p->link.ccp.fsm.FsmTimer);
memset(&p->link.ccp.fsm.OpenTimer, '\0', sizeof p->link.ccp.fsm.OpenTimer);
memset(&p->link.ccp.fsm.StoppedTimer, '\0',
sizeof p->link.ccp.fsm.StoppedTimer);
p->link.ccp.fsm.parent = &dl->fsmp;
ccp_SetupCallbacks(&p->link.ccp);
p->hdlc.lqm.owner = &p->link.lcp;
p->hdlc.ReportTimer.state = TIMER_STOPPED;
p->hdlc.lqm.timer.state = TIMER_STOPPED;
p->fd = fd;
p->link.throughput.SampleOctets = (long long *)iov[(*niov)++].iov_base;
type = (long)p->handler;
p->handler = NULL;
for (h = 0; h < NDEVICES && p->handler == NULL; h++)
p->handler = (*devices[h].iov2device)(type, p, iov, niov, maxiov);
if (p->handler == NULL) {
log_Printf(LogPHASE, "%s: Device %s, unknown link type\n",
p->link.name, p->name.full);
free(iov[(*niov)++].iov_base);
physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE);
} else
log_Printf(LogPHASE, "%s: Device %s, link type is %s\n",
p->link.name, p->name.full, p->handler->name);
if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load)
lqr_reStart(&p->link.lcp);
hdlc_StartTimer(&p->hdlc);
throughput_restart(&p->link.throughput, "physical throughput",
Enabled(dl->bundle, OPT_THROUGHPUT));
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
return p;
}
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
int
physical_MaxDeviceSize()
{
int biggest, sz, n;
biggest = sizeof(struct device);
for (sz = n = 0; n < NDEVICES; n++)
if (devices[n].DeviceSize) {
sz = (*devices[n].DeviceSize)();
if (biggest < sz)
biggest = sz;
}
return biggest;
}
int
physical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov,
pid_t newpid)
{
struct device *h;
int sz;
h = NULL;
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);
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
if (p->handler) {
if (p->handler->device2iov)
h = p->handler;
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
p->handler = (struct device *)(long)p->handler->type;
}
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
if (Enabled(p->dl->bundle, OPT_KEEPSESSION) ||
tcgetpgrp(p->fd) == getpgrp())
p->session_owner = getpid(); /* So I'll eventually get HUP'd */
else
p->session_owner = (pid_t)-1;
timer_Stop(&p->link.throughput.Timer);
physical_ChangedPid(p, newpid);
}
if (*niov + 2 >= maxiov) {
log_Printf(LogERROR, "physical2iov: No room for physical + throughput"
" + device !\n");
if (p)
free(p);
return -1;
}
iov[*niov].iov_base = p ? (void *)p : malloc(sizeof *p);
iov[*niov].iov_len = sizeof *p;
(*niov)++;
iov[*niov].iov_base = p ? (void *)p->link.throughput.SampleOctets :
malloc(SAMPLE_PERIOD * sizeof(long long));
iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long);
(*niov)++;
sz = physical_MaxDeviceSize();
if (p) {
if (h)
(*h->device2iov)(h, iov, niov, maxiov, newpid);
else {
iov[*niov].iov_base = malloc(sz);
if (p->handler)
memcpy(iov[*niov].iov_base, p->handler, sizeof *p->handler);
iov[*niov].iov_len = sz;
(*niov)++;
}
} else {
iov[*niov].iov_base = malloc(sz);
iov[*niov].iov_len = sz;
(*niov)++;
}
return p ? p->fd : 0;
}
void
physical_ChangedPid(struct physical *p, pid_t newpid)
{
if (p->fd >= 0 && *p->name.full == '/' && p->type != PHYS_DIRECT) {
int res;
if ((res = ID0uu_lock_txfr(p->name.base, newpid)) != UU_LOCK_OK)
log_Printf(LogPHASE, "uu_lock_txfr: %s\n", uu_lockerr(res));
}
}
int
physical_IsSync(struct physical *p)
{
return p->cfg.speed == 0;
}
const char *physical_GetDevice(struct physical *p)
{
return p->name.full;
}
void
physical_SetDeviceList(struct physical *p, int argc, const char *const *argv)
{
int f, pos;
p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0';
for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) {
if (pos)
p->cfg.devlist[pos++] = '\0';
strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1);
pos += strlen(p->cfg.devlist + pos);
}
p->cfg.ndev = f;
}
void
physical_SetSync(struct physical *p)
{
p->cfg.speed = 0;
}
int
physical_SetRtsCts(struct physical *p, int enable)
{
p->cfg.rts_cts = enable ? 1 : 0;
return 1;
}
ssize_t
physical_Read(struct physical *p, void *buf, size_t nbytes)
{
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
ssize_t ret;
if (p->handler && p->handler->read)
ret = (*p->handler->read)(p, buf, nbytes);
else
ret = read(p->fd, buf, nbytes);
log_DumpBuff(LogPHYSICAL, "read", buf, ret);
return ret;
}
ssize_t
physical_Write(struct physical *p, const void *buf, size_t nbytes)
{
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
log_DumpBuff(LogPHYSICAL, "write", buf, nbytes);
if (p->handler && p->handler->write)
return (*p->handler->write)(p, buf, nbytes);
return write(p->fd, buf, nbytes);
}
int
physical_doUpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
int *n, int force)
{
struct physical *p = descriptor2physical(d);
int sets;
sets = 0;
if (p->fd >= 0) {
if (r) {
FD_SET(p->fd, r);
log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd);
sets++;
}
if (e) {
FD_SET(p->fd, e);
log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd);
sets++;
}
if (w && (force || link_QueueLen(&p->link) || p->out)) {
FD_SET(p->fd, w);
log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd);
sets++;
}
if (sets && *n < p->fd + 1)
*n = p->fd + 1;
}
return sets;
}
int
physical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e)
{
int sets;
sets = 0;
if (p->fd >= 0) {
if (r && FD_ISSET(p->fd, r)) {
FD_CLR(p->fd, r);
log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd);
sets++;
}
if (e && FD_ISSET(p->fd, e)) {
FD_CLR(p->fd, e);
log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd);
sets++;
}
if (w && FD_ISSET(p->fd, w)) {
FD_CLR(p->fd, w);
log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd);
sets++;
}
}
return sets;
}
int
physical_IsSet(struct descriptor *d, const fd_set *fdset)
{
struct physical *p = descriptor2physical(d);
return p->fd >= 0 && FD_ISSET(p->fd, fdset);
}
void
physical_Login(struct physical *p, const char *name)
{
if (p->type == PHYS_DIRECT && *p->name.base && !p->Utmp) {
struct utmp ut;
const char *connstr;
char *colon;
memset(&ut, 0, sizeof ut);
time(&ut.ut_time);
strncpy(ut.ut_name, name, sizeof ut.ut_name);
if (p->handler && (p->handler->type == TCP_DEVICE ||
p->handler->type == UDP_DEVICE)) {
strncpy(ut.ut_line, PPPOTCPLINE, sizeof ut.ut_line);
strncpy(ut.ut_host, p->name.base, sizeof ut.ut_host);
colon = memchr(ut.ut_host, ':', sizeof ut.ut_host);
if (colon)
*colon = '\0';
} else
strncpy(ut.ut_line, p->name.base, sizeof ut.ut_line);
if ((connstr = getenv("CONNECT")))
/* mgetty sets this to the connection speed */
strncpy(ut.ut_host, connstr, sizeof ut.ut_host);
ID0login(&ut);
p->Utmp = ut.ut_time;
}
}
int
physical_SetMode(struct physical *p, int mode)
{
if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) ||
mode & (PHYS_DIRECT|PHYS_DEDICATED)) &&
(!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) {
log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name,
mode2Nam(p->type), mode2Nam(mode));
return 0;
}
p->type = mode;
return 1;
}
void
physical_DeleteQueue(struct physical *p)
{
if (p->out) {
mbuf_Free(p->out);
p->out = NULL;
}
link_DeleteQueue(&p->link);
}
void
physical_SetDevice(struct physical *p, const char *name)
{
int len = strlen(_PATH_DEV);
if (name != p->name.full) {
strncpy(p->name.full, name, sizeof p->name.full - 1);
p->name.full[sizeof p->name.full - 1] = '\0';
}
p->name.base = *p->name.full == '!' ? p->name.full + 1 :
strncmp(p->name.full, _PATH_DEV, len) ?
p->name.full : p->name.full + len;
}
static void
physical_Found(struct physical *p)
{
FILE *lockfile;
char fn[MAXPATHLEN];
if (*p->name.full == '/') {
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base);
lockfile = ID0fopen(fn, "w");
if (lockfile != NULL) {
fprintf(lockfile, "%s%d\n", TUN_NAME, p->dl->bundle->unit);
fclose(lockfile);
}
#ifndef RELEASE_CRUNCH
else
log_Printf(LogALERT, "%s: Can't create %s: %s\n",
p->link.name, fn, strerror(errno));
#endif
}
throughput_start(&p->link.throughput, "physical throughput",
Enabled(p->dl->bundle, OPT_THROUGHPUT));
p->connect_count++;
p->input.sz = 0;
log_Printf(LogPHASE, "%s: Connected!\n", p->link.name);
}
int
physical_Open(struct physical *p, struct bundle *bundle)
{
int devno, h, wasopen, err;
char *dev;
if (p->fd >= 0)
log_Printf(LogDEBUG, "%s: Open: Modem is already open!\n", p->link.name);
/* We're going back into "term" mode */
else if (p->type == PHYS_DIRECT) {
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
physical_SetDevice(p, "");
p->fd = STDIN_FILENO;
for (h = 0; h < NDEVICES && p->handler == NULL && p->fd >= 0; h++)
p->handler = (*devices[h].create)(p);
if (p->fd >= 0) {
if (p->handler == NULL) {
physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE);
log_Printf(LogDEBUG, "%s: stdin is unidentified\n", p->link.name);
}
physical_Found(p);
}
} else {
dev = p->cfg.devlist;
devno = 0;
while (devno < p->cfg.ndev && p->fd < 0) {
physical_SetDevice(p, dev);
if (physical_Lock(p)) {
err = 0;
if (*p->name.full == '/') {
p->fd = ID0open(p->name.full, O_RDWR | O_NONBLOCK);
if (p->fd < 0)
err = errno;
}
wasopen = p->fd >= 0;
for (h = 0; h < NDEVICES && p->handler == NULL; h++)
if ((p->handler = (*devices[h].create)(p)) == NULL &&
wasopen && p->fd == -1)
break;
if (p->fd < 0) {
if (h == NDEVICES) {
if (err)
log_Printf(LogWARN, "%s: %s: %s\n", p->link.name, p->name.full,
strerror(errno));
else
log_Printf(LogWARN, "%s: Device (%s) must begin with a '/',"
" a '!' or be a host:port pair\n", p->link.name,
p->name.full);
}
physical_Unlock(p);
} else
physical_Found(p);
}
dev += strlen(dev) + 1;
devno++;
}
}
return p->fd;
}
void
physical_SetupStack(struct physical *p, const char *who, int how)
{
link_EmptyStack(&p->link);
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
if (how == PHYSICAL_FORCE_SYNC ||
(how == PHYSICAL_NOFORCE && physical_IsSync(p)))
link_Stack(&p->link, &synclayer);
else {
link_Stack(&p->link, &asynclayer);
link_Stack(&p->link, &hdlclayer);
}
link_Stack(&p->link, &acflayer);
link_Stack(&p->link, &protolayer);
link_Stack(&p->link, &lqrlayer);
link_Stack(&p->link, &ccplayer);
link_Stack(&p->link, &vjlayer);
#ifndef NONAT
link_Stack(&p->link, &natlayer);
#endif
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
if (how == PHYSICAL_FORCE_ASYNC && physical_IsSync(p)) {
log_Printf(LogWARN, "Sync device setting ignored for ``%s'' device\n", who);
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
p->cfg.speed = MODEM_SPEED;
} else if (how == PHYSICAL_FORCE_SYNC && !physical_IsSync(p)) {
log_Printf(LogWARN, "Async device setting ignored for ``%s'' device\n",
who);
Allow ``host:port/udp'' devices and support ``host:port/tcp'' as being the same as the previous (still supported) ``host:port'' syntax for tcp socket devices. A udp device uses synchronous ppp rather than async, and avoids the double-retransmit overhead that comes with ppp over tcp (it's usually a bad idea to transport IP over a reliable transport that itself is using an unreliable transport). PPP over UDP provides througput of ** 1.5Mb per second ** with all compression disabled, maxing out a PPro/200 when running ppp twice, back-to-back. This proves that PPPoE is plausable in userland.... This change adds a few more handler functions to struct device and allows derivations of struct device (which may contain their own data etc) to pass themselves through the unix domain socket for MP. ** At last **, struct physical has lost all the tty crud ! iov2physical() is now smart enough to restore the correct stack of layers so that MP servers will work again. The version number has bumped as our MP link transfer contents have changed (they now may contain a `struct device'). Don't extract the protocol twice in MP mode (resulting in protocol rejects for every MP packet). This was broken with my original layering changes. Add ``Physical'' and ``Sync'' log levels for logging the relevent raw packets and add protocol-tracking LogDEBUG stuff in various LayerPush & LayerPull functions. Assign our physical device name for incoming tcp connections by calling getpeername(). Assign our physical device name for incoming udp connections from the address retrieved by the first recvfrom().
1999-05-12 09:49:12 +00:00
physical_SetSync(p);
}
}
void
physical_StopDeviceTimer(struct physical *p)
{
if (p->handler && p->handler->stoptimer)
(*p->handler->stoptimer)(p);
}
int
physical_AwaitCarrier(struct physical *p)
{
if (p->handler && p->handler->awaitcarrier)
return (*p->handler->awaitcarrier)(p);
return CARRIER_OK;
}