1995-01-31 06:29:58 +00:00
|
|
|
/*
|
|
|
|
* PPP Modem handling module
|
|
|
|
*
|
|
|
|
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
|
|
|
|
*
|
|
|
|
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms are permitted
|
|
|
|
* provided that the above copyright notice and this paragraph are
|
|
|
|
* duplicated in all such forms and that any documentation,
|
|
|
|
* advertising materials, and other materials related to such
|
|
|
|
* distribution and use acknowledge that the software was developed
|
|
|
|
* by the Internet Initiative Japan, Inc. The name of the
|
|
|
|
* IIJ 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-04-21 08:03:35 +00:00
|
|
|
* $Id: modem.c,v 1.109 1999/04/03 12:01:38 brian Exp $
|
1995-05-30 03:57:47 +00:00
|
|
|
*
|
1995-01-31 06:29:58 +00:00
|
|
|
* TODO:
|
|
|
|
*/
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <sys/param.h>
|
1997-06-09 03:27:43 +00:00
|
|
|
#include <sys/socket.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <netinet/in.h>
|
1997-06-09 03:27:43 +00:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <netdb.h>
|
1998-03-16 22:54:35 +00:00
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/ip.h>
|
1998-04-28 01:25:46 +00:00
|
|
|
#include <sys/un.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
|
1995-02-27 10:57:54 +00:00
|
|
|
#include <errno.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <fcntl.h>
|
1997-09-22 00:46:56 +00:00
|
|
|
#include <paths.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/tty.h>
|
1998-05-02 21:57:50 +00:00
|
|
|
#include <sys/uio.h>
|
1998-05-13 19:06:27 +00:00
|
|
|
#include <sys/wait.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <unistd.h>
|
1998-01-29 00:49:32 +00:00
|
|
|
#ifdef __OpenBSD__
|
1998-08-07 18:42:51 +00:00
|
|
|
#include <sys/ioctl.h>
|
1998-04-25 10:49:52 +00:00
|
|
|
#include <util.h>
|
1998-01-29 00:49:32 +00:00
|
|
|
#else
|
|
|
|
#include <libutil.h>
|
|
|
|
#endif
|
1997-10-26 01:04:02 +00:00
|
|
|
|
1998-06-15 19:06:25 +00:00
|
|
|
#include "defs.h"
|
1997-11-22 03:37:54 +00:00
|
|
|
#include "command.h"
|
1997-10-26 01:04:02 +00:00
|
|
|
#include "mbuf.h"
|
|
|
|
#include "log.h"
|
1997-11-09 06:22:49 +00:00
|
|
|
#include "id.h"
|
1997-10-26 01:04:02 +00:00
|
|
|
#include "timer.h"
|
|
|
|
#include "fsm.h"
|
1998-03-13 00:44:26 +00:00
|
|
|
#include "lqr.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
#include "hdlc.h"
|
|
|
|
#include "lcp.h"
|
|
|
|
#include "modem.h"
|
1997-11-18 14:52:08 +00:00
|
|
|
#include "throughput.h"
|
1998-02-02 19:33:40 +00:00
|
|
|
#include "async.h"
|
1998-03-13 21:07:46 +00:00
|
|
|
#include "iplist.h"
|
1998-03-16 22:54:35 +00:00
|
|
|
#include "slcompress.h"
|
1998-03-13 21:07:46 +00:00
|
|
|
#include "ipcp.h"
|
1998-03-16 22:52:54 +00:00
|
|
|
#include "filter.h"
|
1998-03-20 19:48:28 +00:00
|
|
|
#include "descriptor.h"
|
1998-04-03 19:21:56 +00:00
|
|
|
#include "ccp.h"
|
1998-01-30 19:46:07 +00:00
|
|
|
#include "link.h"
|
1998-01-29 00:49:32 +00:00
|
|
|
#include "physical.h"
|
1998-04-03 19:21:56 +00:00
|
|
|
#include "mp.h"
|
1999-01-28 01:56:34 +00:00
|
|
|
#ifndef NORADIUS
|
|
|
|
#include "radius.h"
|
|
|
|
#endif
|
1998-04-03 19:21:56 +00:00
|
|
|
#include "bundle.h"
|
1998-02-10 03:23:50 +00:00
|
|
|
#include "prompt.h"
|
1998-02-13 05:10:26 +00:00
|
|
|
#include "chat.h"
|
1998-03-01 01:07:49 +00:00
|
|
|
#include "auth.h"
|
|
|
|
#include "chap.h"
|
1998-08-07 18:42:51 +00:00
|
|
|
#include "cbcp.h"
|
1998-02-16 19:10:03 +00:00
|
|
|
#include "datalink.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
|
1998-06-24 19:33:36 +00:00
|
|
|
static int modem_DescriptorWrite(struct descriptor *, struct bundle *,
|
|
|
|
const fd_set *);
|
1998-02-10 03:22:05 +00:00
|
|
|
static void modem_DescriptorRead(struct descriptor *, struct bundle *,
|
|
|
|
const fd_set *);
|
1998-02-13 05:10:26 +00:00
|
|
|
static int modem_UpdateSet(struct descriptor *, fd_set *, fd_set *, fd_set *,
|
|
|
|
int *);
|
1997-10-29 01:19:51 +00:00
|
|
|
|
1998-02-06 02:22:52 +00:00
|
|
|
struct physical *
|
1998-04-10 13:19:23 +00:00
|
|
|
modem_Create(struct datalink *dl, int type)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-02-06 02:22:52 +00:00
|
|
|
struct physical *p;
|
|
|
|
|
|
|
|
p = (struct physical *)malloc(sizeof(struct physical));
|
|
|
|
if (!p)
|
|
|
|
return NULL;
|
1998-02-21 01:45:26 +00:00
|
|
|
|
1998-02-06 02:22:52 +00:00
|
|
|
p->link.type = PHYSICAL_LINK;
|
1998-04-03 19:21:56 +00:00
|
|
|
p->link.name = dl->name;
|
1998-02-06 02:22:52 +00:00
|
|
|
p->link.len = sizeof *p;
|
1998-04-03 19:21:56 +00:00
|
|
|
throughput_init(&p->link.throughput);
|
1998-04-20 00:20:41 +00:00
|
|
|
memset(&p->Timer, '\0', sizeof p->Timer);
|
1998-02-21 01:45:26 +00:00
|
|
|
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);
|
|
|
|
|
1998-02-09 19:21:11 +00:00
|
|
|
p->desc.type = PHYSICAL_DESCRIPTOR;
|
1998-02-13 05:10:26 +00:00
|
|
|
p->desc.UpdateSet = modem_UpdateSet;
|
1998-05-01 19:26:12 +00:00
|
|
|
p->desc.IsSet = physical_IsSet;
|
1998-02-09 19:21:11 +00:00
|
|
|
p->desc.Read = modem_DescriptorRead;
|
1998-04-03 19:21:56 +00:00
|
|
|
p->desc.Write = modem_DescriptorWrite;
|
1998-04-10 13:19:23 +00:00
|
|
|
p->type = type;
|
1998-02-09 19:21:11 +00:00
|
|
|
|
1998-04-24 19:16:15 +00:00
|
|
|
hdlc_Init(&p->hdlc, &p->link.lcp);
|
1998-02-21 01:45:26 +00:00
|
|
|
async_Init(&p->async);
|
|
|
|
|
|
|
|
p->fd = -1;
|
|
|
|
p->mbits = 0;
|
1999-01-10 01:26:30 +00:00
|
|
|
p->isatty = 0;
|
1998-02-21 01:45:26 +00:00
|
|
|
p->out = NULL;
|
|
|
|
p->connect_count = 0;
|
1998-03-13 00:44:51 +00:00
|
|
|
p->dl = dl;
|
1999-04-03 11:54:00 +00:00
|
|
|
p->input.sz = 0;
|
1998-03-06 00:34:47 +00:00
|
|
|
*p->name.full = '\0';
|
|
|
|
p->name.base = p->name.full;
|
|
|
|
|
1998-03-10 03:06:07 +00:00
|
|
|
p->Utmp = 0;
|
1998-05-29 18:33:10 +00:00
|
|
|
p->session_owner = (pid_t)-1;
|
1998-03-10 03:06:07 +00:00
|
|
|
|
1998-02-21 01:45:26 +00:00
|
|
|
p->cfg.rts_cts = MODEM_CTSRTS;
|
|
|
|
p->cfg.speed = MODEM_SPEED;
|
|
|
|
p->cfg.parity = CS8;
|
1998-03-06 00:34:47 +00:00
|
|
|
strncpy(p->cfg.devlist, MODEM_LIST, sizeof p->cfg.devlist - 1);
|
|
|
|
p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0';
|
1999-02-16 00:16:56 +00:00
|
|
|
p->cfg.cd.required = 0;
|
|
|
|
p->cfg.cd.delay = DEF_CDDELAY;
|
1998-02-21 01:45:26 +00:00
|
|
|
|
1998-04-03 19:21:56 +00:00
|
|
|
lcp_Init(&p->link.lcp, dl->bundle, &p->link, &dl->fsmp);
|
|
|
|
ccp_Init(&p->link.ccp, dl->bundle, &p->link, &dl->fsmp);
|
|
|
|
|
1998-02-06 02:22:52 +00:00
|
|
|
return p;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-01-29 00:49:32 +00:00
|
|
|
/* XXX-ML this should probably change when we add support for other
|
|
|
|
types of devices */
|
1998-02-02 19:32:16 +00:00
|
|
|
#define Online(modem) ((modem)->mbits & TIOCM_CD)
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-02-06 02:22:28 +00:00
|
|
|
static void modem_LogicalClose(struct physical *);
|
Implement Reset{Req,Ack} properly, as per rfc 1962.
(I completely mis-read the rfc last time 'round!)
This means:
o Better CCP/WARN Reset diagnostics.
o After we've sent a REQ and before we've received an ACK, we drop
incoming compressed data and send another REQ.
o Before sending an ACK, re-sequence all pending PRI_NORMAL data in
the modem queue so that pending packets won't get to the peer
*after* the ResetAck.
o Send ACKs with the `identifier' from the REQ frame.
o After we've received a correct ACK, duplicate ACKs are ok (and will
reset our history).
o Incorrect ACKs (not matching the last REQ) are moaned about and dropped.
Also,
o Calculate the correct FCS after compressing a packet. DEFLATE
*may* produce an mbuf with more than a single link in the chain,
but HdlcOutput didn't know how to calculate the FCS :-(
o Make `struct fsm'::reqid a u_char, not an int.
This fix will prevent us from sending id `255' 2,000,000,000 times
before wrapping to `0' for another 2,000,000,000 sends :-/
o Bump the version number a little.
The end result: DEFLATE now works over an unreliable link layer.
I can txfr a 1.5Mb kernel over a (rather bad) null-modem
cable at an average of 21679 bytes per second using rcp.
Repeat after me: Don't test compression using a loopback ppp/tcp setup as
we never lose packets and therefore never have to reset!
1998-01-10 01:55:11 +00:00
|
|
|
|
1998-05-06 18:49:45 +00:00
|
|
|
static const struct speeds {
|
1995-02-26 12:18:08 +00:00
|
|
|
int nspeed;
|
|
|
|
speed_t speed;
|
1998-02-06 02:22:28 +00:00
|
|
|
} speeds[] = {
|
1995-02-26 12:18:08 +00:00
|
|
|
#ifdef B50
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 50, B50, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B75
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 75, B75, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B110
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 110, B110, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B134
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 134, B134, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B150
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 150, B150, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B200
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 200, B200, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B300
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 300, B300, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B600
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 600, B600, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B1200
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 1200, B1200, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B1800
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 1800, B1800, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B2400
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 2400, B2400, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B4800
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 4800, B4800, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B9600
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 9600, B9600, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B19200
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 19200, B19200, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B38400
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 38400, B38400, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
1995-02-27 10:57:54 +00:00
|
|
|
#ifndef _POSIX_SOURCE
|
1995-02-26 12:18:08 +00:00
|
|
|
#ifdef B7200
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 7200, B7200, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B14400
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 14400, B14400, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B28800
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 28800, B28800, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B57600
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 57600, B57600, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B76800
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 76800, B76800, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B115200
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 115200, B115200, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef B230400
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 230400, B230400, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef EXTA
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 19200, EXTA, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef EXTB
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 38400, EXTB, },
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
1997-08-25 00:29:32 +00:00
|
|
|
#endif /* _POSIX_SOURCE */
|
1997-11-18 14:52:08 +00:00
|
|
|
{ 0, 0 }
|
1995-02-26 12:18:08 +00:00
|
|
|
};
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static int
|
1997-08-25 00:29:32 +00:00
|
|
|
SpeedToInt(speed_t speed)
|
1995-02-26 12:18:08 +00:00
|
|
|
{
|
1998-05-06 18:49:45 +00:00
|
|
|
const struct speeds *sp;
|
1995-02-26 12:18:08 +00:00
|
|
|
|
|
|
|
for (sp = speeds; sp->nspeed; sp++) {
|
|
|
|
if (sp->speed == speed) {
|
1997-08-25 00:29:32 +00:00
|
|
|
return (sp->nspeed);
|
1995-02-26 12:18:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
speed_t
|
|
|
|
IntToSpeed(int nspeed)
|
1995-02-26 12:18:08 +00:00
|
|
|
{
|
1998-05-06 18:49:45 +00:00
|
|
|
const struct speeds *sp;
|
1995-02-26 12:18:08 +00:00
|
|
|
|
|
|
|
for (sp = speeds; sp->nspeed; sp++) {
|
|
|
|
if (sp->nspeed == nspeed) {
|
1997-08-25 00:29:32 +00:00
|
|
|
return (sp->speed);
|
1995-02-26 12:18:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return B0;
|
|
|
|
}
|
|
|
|
|
1998-03-06 00:35:30 +00:00
|
|
|
static void
|
1998-03-06 00:34:47 +00:00
|
|
|
modem_SetDevice(struct physical *physical, const char *name)
|
1998-03-06 00:35:30 +00:00
|
|
|
{
|
1998-05-01 19:22:23 +00:00
|
|
|
int len = strlen(_PATH_DEV);
|
1998-03-06 00:35:30 +00:00
|
|
|
|
1998-03-06 00:34:47 +00:00
|
|
|
strncpy(physical->name.full, name, sizeof physical->name.full - 1);
|
|
|
|
physical->name.full[sizeof physical->name.full - 1] = '\0';
|
1998-05-01 19:22:23 +00:00
|
|
|
physical->name.base = strncmp(physical->name.full, _PATH_DEV, len) ?
|
|
|
|
physical->name.full : physical->name.full + len;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1998-02-06 02:22:28 +00:00
|
|
|
* modem_Timeout() watches DCD signal and notifies if it's status is changed.
|
1995-01-31 06:29:58 +00:00
|
|
|
*
|
|
|
|
*/
|
1998-02-02 19:32:16 +00:00
|
|
|
static void
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_Timeout(void *data)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-04-20 00:20:41 +00:00
|
|
|
struct physical *modem = data;
|
|
|
|
int ombits = modem->mbits;
|
1995-01-31 06:29:58 +00:00
|
|
|
int change;
|
|
|
|
|
1998-05-01 19:26:12 +00:00
|
|
|
timer_Stop(&modem->Timer);
|
1999-02-16 00:16:56 +00:00
|
|
|
modem->Timer.load = SECTICKS; /* Once a second please */
|
1998-05-01 19:26:12 +00:00
|
|
|
timer_Start(&modem->Timer);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1999-01-10 01:26:30 +00:00
|
|
|
if (modem->isatty || physical_IsSync(modem)) {
|
1999-02-16 00:16:56 +00:00
|
|
|
ombits = modem->mbits;
|
|
|
|
|
1998-04-20 00:20:41 +00:00
|
|
|
if (modem->fd >= 0) {
|
|
|
|
if (ioctl(modem->fd, TIOCMGET, &modem->mbits) < 0) {
|
1999-04-21 08:03:35 +00:00
|
|
|
log_Printf(LogPHASE, "%s: Carrier not required (pseudo tty ?)\n",
|
|
|
|
modem->link.name);
|
|
|
|
timer_Stop(&modem->Timer);
|
|
|
|
modem->mbits = TIOCM_CD;
|
1997-08-25 00:29:32 +00:00
|
|
|
return;
|
1997-05-19 02:00:16 +00:00
|
|
|
}
|
|
|
|
} else
|
1998-04-20 00:20:41 +00:00
|
|
|
modem->mbits = 0;
|
1999-02-16 00:16:56 +00:00
|
|
|
|
|
|
|
if (ombits == -1) {
|
|
|
|
/* First time looking for carrier */
|
|
|
|
if (Online(modem))
|
|
|
|
log_Printf(LogDEBUG, "%s: %s: CD detected\n",
|
|
|
|
modem->link.name, modem->name.full);
|
|
|
|
else if (modem->cfg.cd.required) {
|
|
|
|
log_Printf(LogPHASE, "%s: %s: Required CD not detected\n",
|
|
|
|
modem->link.name, modem->name.full);
|
1998-06-15 19:05:27 +00:00
|
|
|
datalink_Down(modem->dl, CLOSE_NORMAL);
|
1999-02-16 00:16:56 +00:00
|
|
|
} else {
|
|
|
|
log_Printf(LogPHASE, "%s: %s doesn't support CD\n",
|
|
|
|
modem->link.name, modem->name.full);
|
|
|
|
timer_Stop(&modem->Timer);
|
|
|
|
modem->mbits = TIOCM_CD;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1999-02-16 00:16:56 +00:00
|
|
|
} else {
|
|
|
|
change = ombits ^ modem->mbits;
|
|
|
|
if (change & TIOCM_CD) {
|
|
|
|
if (modem->mbits & TIOCM_CD)
|
|
|
|
log_Printf(LogDEBUG, "%s: offline -> online\n", modem->link.name);
|
|
|
|
else {
|
|
|
|
log_Printf(LogDEBUG, "%s: online -> offline\n", modem->link.name);
|
|
|
|
log_Printf(LogPHASE, "%s: Carrier lost\n", modem->link.name);
|
|
|
|
datalink_Down(modem->dl, CLOSE_NORMAL);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
log_Printf(LogDEBUG, "%s: Still %sline\n", modem->link.name,
|
|
|
|
Online(modem) ? "on" : "off");
|
|
|
|
}
|
1998-04-20 00:20:41 +00:00
|
|
|
} else if (!Online(modem)) {
|
1998-02-06 02:22:28 +00:00
|
|
|
/* mbits was set to zero in modem_Open() */
|
1998-04-20 00:20:41 +00:00
|
|
|
modem->mbits = TIOCM_CD;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_StartTimer(struct bundle *bundle, struct physical *modem)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1999-02-16 00:16:56 +00:00
|
|
|
timer_Stop(&modem->Timer);
|
|
|
|
modem->Timer.load = SECTICKS * modem->cfg.cd.delay;
|
|
|
|
modem->Timer.func = modem_Timeout;
|
|
|
|
modem->Timer.name = "modem CD";
|
|
|
|
modem->Timer.arg = modem;
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Using modem_Timeout [%p]\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, modem_Timeout);
|
1999-02-16 00:16:56 +00:00
|
|
|
modem->mbits = -1; /* So we know it's the first time */
|
|
|
|
timer_Start(&modem->Timer);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-06 18:49:45 +00:00
|
|
|
static const struct parity {
|
1997-11-22 03:37:54 +00:00
|
|
|
const char *name;
|
|
|
|
const char *name1;
|
1997-08-25 00:29:32 +00:00
|
|
|
int set;
|
1997-11-22 03:37:54 +00:00
|
|
|
} validparity[] = {
|
|
|
|
{ "even", "P_EVEN", CS7 | PARENB },
|
|
|
|
{ "odd", "P_ODD", CS7 | PARENB | PARODD },
|
|
|
|
{ "none", "P_ZERO", CS8 },
|
|
|
|
{ NULL, 0 },
|
1995-01-31 06:29:58 +00:00
|
|
|
};
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
GetParityValue(const char *str)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-06 18:49:45 +00:00
|
|
|
const struct parity *pp;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
for (pp = validparity; pp->name; pp++) {
|
|
|
|
if (strcasecmp(pp->name, str) == 0 ||
|
|
|
|
strcasecmp(pp->name1, str) == 0) {
|
1998-01-29 00:49:32 +00:00
|
|
|
return pp->set;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
}
|
1997-08-25 00:29:32 +00:00
|
|
|
return (-1);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_SetParity(struct physical *modem, const char *str)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
struct termios rstio;
|
|
|
|
int val;
|
|
|
|
|
|
|
|
val = GetParityValue(str);
|
|
|
|
if (val > 0) {
|
1998-02-17 19:29:03 +00:00
|
|
|
modem->cfg.parity = val;
|
1998-01-29 00:49:32 +00:00
|
|
|
tcgetattr(modem->fd, &rstio);
|
1997-08-25 00:29:32 +00:00
|
|
|
rstio.c_cflag &= ~(CSIZE | PARODD | PARENB);
|
1995-01-31 06:29:58 +00:00
|
|
|
rstio.c_cflag |= val;
|
1998-01-29 00:49:32 +00:00
|
|
|
tcsetattr(modem->fd, TCSADRAIN, &rstio);
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogWARN, "%s: %s: Invalid parity\n", modem->link.name, str);
|
1997-06-09 03:27:43 +00:00
|
|
|
return -1;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static int
|
1998-04-28 01:25:46 +00:00
|
|
|
OpenConnection(const char *name, char *host, char *port)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_in dest;
|
|
|
|
int sock;
|
|
|
|
struct servent *sp;
|
|
|
|
|
|
|
|
dest.sin_family = AF_INET;
|
|
|
|
dest.sin_addr.s_addr = inet_addr(host);
|
1999-02-25 20:05:55 +00:00
|
|
|
dest.sin_addr = GetIpAddr(host);
|
1995-01-31 06:29:58 +00:00
|
|
|
if (dest.sin_addr.s_addr == INADDR_NONE) {
|
1999-02-25 20:05:55 +00:00
|
|
|
log_Printf(LogWARN, "%s: %s: unknown host\n", name, host);
|
|
|
|
return (-1);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
dest.sin_port = htons(atoi(port));
|
|
|
|
if (dest.sin_port == 0) {
|
|
|
|
sp = getservbyname(port, "tcp");
|
|
|
|
if (sp) {
|
|
|
|
dest.sin_port = sp->s_port;
|
|
|
|
} else {
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogWARN, "%s: %s: unknown service\n", name, port);
|
1997-08-25 00:29:32 +00:00
|
|
|
return (-1);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
}
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogPHASE, "%s: Connecting to %s:%s\n", name, host, port);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
sock = socket(PF_INET, SOCK_STREAM, 0);
|
|
|
|
if (sock < 0) {
|
1997-08-25 00:29:32 +00:00
|
|
|
return (sock);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-12-24 09:29:17 +00:00
|
|
|
if (connect(sock, (struct sockaddr *)&dest, sizeof dest) < 0) {
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogWARN, "%s: connect: %s\n", name, strerror(errno));
|
1998-05-19 21:51:24 +00:00
|
|
|
close(sock);
|
1997-08-25 00:29:32 +00:00
|
|
|
return (-1);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-08-25 00:29:32 +00:00
|
|
|
return (sock);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static int
|
1998-02-07 20:50:08 +00:00
|
|
|
modem_lock(struct physical *modem, int tunno)
|
1997-09-22 00:46:56 +00:00
|
|
|
{
|
|
|
|
int res;
|
|
|
|
FILE *lockfile;
|
1998-01-29 00:49:32 +00:00
|
|
|
char fn[MAXPATHLEN];
|
1997-09-22 00:46:56 +00:00
|
|
|
|
1998-03-06 00:34:47 +00:00
|
|
|
if (*modem->name.full != '/')
|
1997-09-22 00:46:56 +00:00
|
|
|
return 0;
|
|
|
|
|
1998-04-30 23:53:56 +00:00
|
|
|
if (modem->type != PHYS_DIRECT &&
|
1998-03-06 00:34:47 +00:00
|
|
|
(res = ID0uu_lock(modem->name.base)) != UU_LOCK_OK) {
|
1997-09-22 00:46:56 +00:00
|
|
|
if (res == UU_LOCK_INUSE)
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogPHASE, "%s: %s is in use\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, modem->name.full);
|
1997-09-22 00:46:56 +00:00
|
|
|
else
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, modem->name.full, uu_lockerr(res));
|
1997-09-22 00:46:56 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
1998-03-06 00:34:47 +00:00
|
|
|
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, modem->name.base);
|
1997-11-09 06:22:49 +00:00
|
|
|
lockfile = ID0fopen(fn, "w");
|
|
|
|
if (lockfile != NULL) {
|
1998-05-28 23:17:51 +00:00
|
|
|
fprintf(lockfile, "%s%d\n", TUN_NAME, tunno);
|
1997-09-22 00:46:56 +00:00
|
|
|
fclose(lockfile);
|
1998-01-29 00:44:15 +00:00
|
|
|
}
|
|
|
|
#ifndef RELEASE_CRUNCH
|
|
|
|
else
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogALERT, "%s: Can't create %s: %s\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, fn, strerror(errno));
|
1998-01-29 00:44:15 +00:00
|
|
|
#endif
|
1997-09-22 00:46:56 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_Unlock(struct physical *modem)
|
1997-09-22 00:46:56 +00:00
|
|
|
{
|
1998-01-29 00:49:32 +00:00
|
|
|
char fn[MAXPATHLEN];
|
|
|
|
|
1998-03-06 00:34:47 +00:00
|
|
|
if (*modem->name.full != '/')
|
1997-09-22 00:46:56 +00:00
|
|
|
return;
|
|
|
|
|
1998-03-06 00:34:47 +00:00
|
|
|
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, modem->name.base);
|
1998-01-29 00:44:15 +00:00
|
|
|
#ifndef RELEASE_CRUNCH
|
1997-11-09 06:22:49 +00:00
|
|
|
if (ID0unlink(fn) == -1)
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogALERT, "%s: Can't remove %s: %s\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, fn, strerror(errno));
|
1998-01-29 00:44:15 +00:00
|
|
|
#else
|
|
|
|
ID0unlink(fn);
|
|
|
|
#endif
|
1997-09-22 00:46:56 +00:00
|
|
|
|
1998-04-30 23:53:56 +00:00
|
|
|
if (modem->type != PHYS_DIRECT && ID0uu_unlock(modem->name.base) == -1)
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", modem->link.name, fn);
|
1997-09-22 00:46:56 +00:00
|
|
|
}
|
|
|
|
|
1997-10-29 01:19:51 +00:00
|
|
|
static void
|
1998-04-16 00:26:21 +00:00
|
|
|
modem_Found(struct physical *modem, struct bundle *bundle)
|
1997-10-29 01:19:51 +00:00
|
|
|
{
|
1998-04-16 00:26:21 +00:00
|
|
|
throughput_start(&modem->link.throughput, "modem throughput",
|
|
|
|
Enabled(bundle, OPT_THROUGHPUT));
|
1998-01-29 00:49:32 +00:00
|
|
|
modem->connect_count++;
|
1999-04-03 11:54:00 +00:00
|
|
|
modem->input.sz = 0;
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogPHASE, "%s: Connected!\n", modem->link.name);
|
1997-10-29 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
int
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_Open(struct physical *modem, struct bundle *bundle)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
struct termios rstio;
|
|
|
|
int oldflag;
|
1997-11-22 03:37:54 +00:00
|
|
|
char *host, *port;
|
|
|
|
char *cp;
|
1998-03-06 00:34:47 +00:00
|
|
|
char tmpDeviceList[sizeof modem->cfg.devlist];
|
1997-12-21 03:16:19 +00:00
|
|
|
char *tmpDevice;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-01-29 00:49:32 +00:00
|
|
|
if (modem->fd >= 0)
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Open: Modem is already open!\n", modem->link.name);
|
1997-09-16 23:15:16 +00:00
|
|
|
/* We're going back into "term" mode */
|
1998-04-30 23:53:56 +00:00
|
|
|
else if (modem->type == PHYS_DIRECT) {
|
1997-12-30 23:22:31 +00:00
|
|
|
if (isatty(STDIN_FILENO)) {
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Open(direct): Modem is a tty\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name);
|
1998-03-06 00:34:47 +00:00
|
|
|
modem_SetDevice(modem, ttyname(STDIN_FILENO));
|
1998-02-07 20:50:08 +00:00
|
|
|
if (modem_lock(modem, bundle->unit) == -1) {
|
1997-12-30 23:22:31 +00:00
|
|
|
close(STDIN_FILENO);
|
1997-09-22 00:46:56 +00:00
|
|
|
return -1;
|
|
|
|
}
|
1998-02-07 22:22:45 +00:00
|
|
|
modem->fd = STDIN_FILENO;
|
1998-04-16 00:26:21 +00:00
|
|
|
modem_Found(modem, bundle);
|
1997-09-22 00:46:56 +00:00
|
|
|
} else {
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Open(direct): Modem is not a tty\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name);
|
1998-03-06 00:34:47 +00:00
|
|
|
modem_SetDevice(modem, "");
|
1998-02-06 02:22:28 +00:00
|
|
|
/* We don't call modem_Timeout() with this type of connection */
|
1998-04-16 00:26:21 +00:00
|
|
|
modem_Found(modem, bundle);
|
1998-01-29 00:49:32 +00:00
|
|
|
return modem->fd = STDIN_FILENO;
|
1997-09-22 00:46:56 +00:00
|
|
|
}
|
1997-09-16 23:15:16 +00:00
|
|
|
} else {
|
1998-03-06 00:34:47 +00:00
|
|
|
strncpy(tmpDeviceList, modem->cfg.devlist, sizeof tmpDeviceList - 1);
|
1997-12-24 09:29:17 +00:00
|
|
|
tmpDeviceList[sizeof tmpDeviceList - 1] = '\0';
|
1997-12-21 03:16:19 +00:00
|
|
|
|
1998-04-17 22:04:36 +00:00
|
|
|
for(tmpDevice=strtok(tmpDeviceList, ", "); tmpDevice && modem->fd < 0;
|
1998-03-06 00:34:47 +00:00
|
|
|
tmpDevice=strtok(NULL,", ")) {
|
|
|
|
modem_SetDevice(modem, tmpDevice);
|
1998-01-29 00:44:16 +00:00
|
|
|
|
1998-03-06 00:34:47 +00:00
|
|
|
if (*modem->name.full == '/') {
|
1998-04-17 22:04:36 +00:00
|
|
|
if (modem_lock(modem, bundle->unit) != -1) {
|
1998-03-06 00:34:47 +00:00
|
|
|
modem->fd = ID0open(modem->name.full, O_RDWR | O_NONBLOCK);
|
1998-01-29 00:49:32 +00:00
|
|
|
if (modem->fd < 0) {
|
1998-05-13 19:06:27 +00:00
|
|
|
log_Printf(LogPHASE, "%s: Open(\"%s\"): %s\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, modem->name.full, strerror(errno));
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_Unlock(modem);
|
1998-04-17 22:04:36 +00:00
|
|
|
} else {
|
1998-04-16 00:26:21 +00:00
|
|
|
modem_Found(modem, bundle);
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Opened %s\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, modem->name.full);
|
1997-12-21 03:16:19 +00:00
|
|
|
}
|
|
|
|
}
|
1998-05-13 19:06:27 +00:00
|
|
|
} else if (*modem->name.full == '!') {
|
|
|
|
/* PPP via an external program */
|
|
|
|
/*
|
|
|
|
* XXX: Fix me - this should be another sort of link (similar to a
|
|
|
|
* physical
|
|
|
|
*/
|
|
|
|
int fids[2];
|
|
|
|
|
|
|
|
modem->name.base = modem->name.full + 1;
|
1999-03-07 01:41:27 +00:00
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fids) < 0)
|
1998-05-13 19:06:27 +00:00
|
|
|
log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
|
|
|
|
strerror(errno));
|
|
|
|
else {
|
|
|
|
int stat;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
stat = fcntl(fids[0], F_GETFL, 0);
|
|
|
|
if (stat > 0) {
|
|
|
|
stat |= O_NONBLOCK;
|
|
|
|
fcntl(fids[0], F_SETFL, stat);
|
|
|
|
}
|
|
|
|
switch ((pid = fork())) {
|
|
|
|
case -1:
|
|
|
|
log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
|
|
|
|
strerror(errno));
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
close(fids[0]);
|
|
|
|
timer_TermService();
|
|
|
|
|
|
|
|
fids[1] = fcntl(fids[1], F_DUPFD, 3);
|
|
|
|
dup2(fids[1], STDIN_FILENO);
|
|
|
|
dup2(fids[1], STDOUT_FILENO);
|
|
|
|
dup2(fids[1], STDERR_FILENO);
|
|
|
|
setuid(geteuid());
|
|
|
|
if (fork())
|
|
|
|
exit(127);
|
|
|
|
execlp(modem->name.base, modem->name.base, NULL);
|
|
|
|
fprintf(stderr, "execvp failed: %s: %s\n", modem->name.base,
|
|
|
|
strerror(errno));
|
|
|
|
exit(127);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
close(fids[1]);
|
|
|
|
modem->fd = fids[0];
|
|
|
|
waitpid(pid, &stat, 0);
|
1999-03-07 01:02:39 +00:00
|
|
|
log_Printf(LogDEBUG, "Using descriptor %d for child\n",
|
|
|
|
modem->fd);
|
1999-03-07 20:58:48 +00:00
|
|
|
modem_Found(modem, bundle);
|
1998-05-13 19:06:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1997-12-21 03:16:19 +00:00
|
|
|
} else {
|
|
|
|
/* PPP over TCP */
|
1998-03-06 00:34:47 +00:00
|
|
|
/*
|
|
|
|
* XXX: Fix me - this should be another sort of link (similar to a
|
|
|
|
* physical
|
|
|
|
*/
|
|
|
|
cp = strchr(modem->name.full, ':');
|
1997-12-21 03:16:19 +00:00
|
|
|
if (cp) {
|
|
|
|
*cp = '\0';
|
1998-03-06 00:34:47 +00:00
|
|
|
host = modem->name.full;
|
1997-12-21 03:16:19 +00:00
|
|
|
port = cp + 1;
|
|
|
|
if (*host && *port) {
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->fd = OpenConnection(modem->link.name, host, port);
|
1998-03-06 00:34:47 +00:00
|
|
|
*cp = ':'; /* Don't destroy name.full */
|
1998-05-13 19:06:27 +00:00
|
|
|
if (modem->fd >= 0) {
|
|
|
|
modem_Found(modem, bundle);
|
|
|
|
log_Printf(LogDEBUG, "%s: Opened socket %s\n", modem->link.name,
|
|
|
|
modem->name.full);
|
|
|
|
}
|
1997-12-21 03:16:19 +00:00
|
|
|
} else {
|
1998-03-06 00:34:47 +00:00
|
|
|
*cp = ':'; /* Don't destroy name.full */
|
1998-06-16 19:40:42 +00:00
|
|
|
log_Printf(LogWARN, "%s: Invalid host:port: \"%s\"\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, modem->name.full);
|
1997-12-21 03:16:19 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
} else {
|
1998-06-16 19:40:42 +00:00
|
|
|
log_Printf(LogWARN, "%s: Device (%s) must begin with a '/',"
|
1998-05-13 19:06:27 +00:00
|
|
|
" a '!' or be a host:port pair\n", modem->link.name,
|
|
|
|
modem->name.full);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-09-16 23:15:16 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-12-21 03:16:19 +00:00
|
|
|
|
1998-01-29 00:49:32 +00:00
|
|
|
if (modem->fd < 0)
|
|
|
|
return modem->fd;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-08-25 00:29:32 +00:00
|
|
|
* If we are working on tty device, change it's mode into the one desired
|
1998-05-08 01:15:19 +00:00
|
|
|
* for further operation.
|
1995-01-31 06:29:58 +00:00
|
|
|
*/
|
1998-01-29 00:49:32 +00:00
|
|
|
modem->mbits = 0;
|
1999-01-10 01:26:30 +00:00
|
|
|
modem->isatty = isatty(modem->fd);
|
|
|
|
if (modem->isatty) {
|
1998-01-29 00:49:32 +00:00
|
|
|
tcgetattr(modem->fd, &rstio);
|
|
|
|
modem->ios = rstio;
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Open: modem (get): fd = %d, iflag = %lx, "
|
1998-04-28 01:25:46 +00:00
|
|
|
"oflag = %lx, cflag = %lx\n", modem->link.name, modem->fd,
|
|
|
|
(u_long)rstio.c_iflag, (u_long)rstio.c_oflag,
|
|
|
|
(u_long)rstio.c_cflag);
|
1996-03-27 21:40:55 +00:00
|
|
|
cfmakeraw(&rstio);
|
1998-02-17 19:29:03 +00:00
|
|
|
if (modem->cfg.rts_cts)
|
1997-08-25 00:29:32 +00:00
|
|
|
rstio.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW;
|
1996-12-22 17:09:17 +00:00
|
|
|
else {
|
1997-08-25 00:29:32 +00:00
|
|
|
rstio.c_cflag |= CLOCAL;
|
|
|
|
rstio.c_iflag |= IXOFF;
|
1996-12-22 17:09:17 +00:00
|
|
|
}
|
1996-03-27 22:58:21 +00:00
|
|
|
rstio.c_iflag |= IXON;
|
1998-04-10 13:19:23 +00:00
|
|
|
if (modem->type != PHYS_DEDICATED)
|
1996-03-09 08:18:41 +00:00
|
|
|
rstio.c_cflag |= HUPCL;
|
1997-08-25 00:29:32 +00:00
|
|
|
|
1998-04-30 23:53:56 +00:00
|
|
|
if (modem->type != PHYS_DIRECT) {
|
1998-04-10 13:19:23 +00:00
|
|
|
/* Change tty speed when we're not in -direct mode */
|
1997-08-25 00:29:32 +00:00
|
|
|
rstio.c_cflag &= ~(CSIZE | PARODD | PARENB);
|
1998-02-17 19:29:03 +00:00
|
|
|
rstio.c_cflag |= modem->cfg.parity;
|
1998-04-10 13:19:23 +00:00
|
|
|
if (cfsetspeed(&rstio, IntToSpeed(modem->cfg.speed)) == -1)
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogWARN, "%s: %s: Unable to set speed to %d\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, modem->name.full, modem->cfg.speed);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-01-29 00:49:32 +00:00
|
|
|
tcsetattr(modem->fd, TCSADRAIN, &rstio);
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: modem (put): iflag = %lx, oflag = %lx, "
|
1998-04-28 01:25:46 +00:00
|
|
|
"cflag = %lx\n", modem->link.name, (u_long)rstio.c_iflag,
|
|
|
|
(u_long)rstio.c_oflag, (u_long)rstio.c_cflag);
|
1998-01-29 00:44:16 +00:00
|
|
|
|
1998-04-25 10:49:52 +00:00
|
|
|
if (ioctl(modem->fd, TIOCMGET, &modem->mbits) == -1) {
|
1998-04-30 23:53:56 +00:00
|
|
|
if (modem->type != PHYS_DIRECT) {
|
1998-06-16 19:40:42 +00:00
|
|
|
log_Printf(LogWARN, "%s: Open: Cannot get modem status: %s\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, strerror(errno));
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_LogicalClose(modem);
|
1997-09-22 00:46:56 +00:00
|
|
|
return (-1);
|
1998-04-10 13:19:23 +00:00
|
|
|
} else
|
|
|
|
modem->mbits = TIOCM_CD;
|
1998-04-25 10:49:52 +00:00
|
|
|
}
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Open: modem control = %o\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, modem->mbits);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-01-29 00:49:32 +00:00
|
|
|
oldflag = fcntl(modem->fd, F_GETFL, 0);
|
1997-09-16 23:15:16 +00:00
|
|
|
if (oldflag < 0) {
|
1998-06-16 19:40:42 +00:00
|
|
|
log_Printf(LogWARN, "%s: Open: Cannot get modem flags: %s\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, strerror(errno));
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_LogicalClose(modem);
|
1997-09-22 00:46:56 +00:00
|
|
|
return (-1);
|
1997-09-16 23:15:16 +00:00
|
|
|
}
|
1998-04-10 13:19:23 +00:00
|
|
|
fcntl(modem->fd, F_SETFL, oldflag & ~O_NONBLOCK);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-04-10 13:19:23 +00:00
|
|
|
return modem->fd;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_Speed(struct physical *modem)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
struct termios rstio;
|
|
|
|
|
1999-01-10 01:26:30 +00:00
|
|
|
if (!modem->isatty)
|
1998-05-05 03:01:32 +00:00
|
|
|
return 115200;
|
|
|
|
|
1998-01-29 00:49:32 +00:00
|
|
|
tcgetattr(modem->fd, &rstio);
|
1997-08-25 00:29:32 +00:00
|
|
|
return (SpeedToInt(cfgetispeed(&rstio)));
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put modem tty line into raw mode which is necessary in packet mode operation
|
|
|
|
*/
|
|
|
|
int
|
1998-02-16 00:01:12 +00:00
|
|
|
modem_Raw(struct physical *modem, struct bundle *bundle)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
struct termios rstio;
|
|
|
|
int oldflag;
|
|
|
|
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Entering modem_Raw\n", modem->link.name);
|
1998-02-17 19:28:01 +00:00
|
|
|
|
1999-01-10 01:26:30 +00:00
|
|
|
if (!modem->isatty || physical_IsSync(modem))
|
1998-02-17 19:28:01 +00:00
|
|
|
return 0;
|
|
|
|
|
1998-04-30 23:53:56 +00:00
|
|
|
if (modem->type != PHYS_DIRECT && modem->fd >= 0 && !Online(modem))
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Raw: modem = %d, mbits = %x\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name, modem->fd, modem->mbits);
|
1998-04-10 13:19:23 +00:00
|
|
|
|
1998-01-29 00:49:32 +00:00
|
|
|
tcgetattr(modem->fd, &rstio);
|
1996-03-27 21:40:55 +00:00
|
|
|
cfmakeraw(&rstio);
|
1998-02-17 19:29:03 +00:00
|
|
|
if (modem->cfg.rts_cts)
|
1997-08-25 00:29:32 +00:00
|
|
|
rstio.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW;
|
1996-12-22 17:09:17 +00:00
|
|
|
else
|
1997-08-25 00:29:32 +00:00
|
|
|
rstio.c_cflag |= CLOCAL;
|
1996-12-22 17:09:17 +00:00
|
|
|
|
1998-04-10 13:19:23 +00:00
|
|
|
if (modem->type != PHYS_DEDICATED)
|
1996-03-09 08:18:41 +00:00
|
|
|
rstio.c_cflag |= HUPCL;
|
1998-04-10 13:19:23 +00:00
|
|
|
|
1998-07-29 18:20:53 +00:00
|
|
|
tcsetattr(modem->fd, TCSANOW, &rstio);
|
|
|
|
|
1998-01-29 00:49:32 +00:00
|
|
|
oldflag = fcntl(modem->fd, F_GETFL, 0);
|
1997-05-10 01:22:19 +00:00
|
|
|
if (oldflag < 0)
|
1997-08-25 00:29:32 +00:00
|
|
|
return (-1);
|
1998-04-10 13:19:23 +00:00
|
|
|
fcntl(modem->fd, F_SETFL, oldflag | O_NONBLOCK);
|
1998-02-16 00:01:12 +00:00
|
|
|
|
1999-02-16 00:16:56 +00:00
|
|
|
modem_StartTimer(bundle, modem);
|
1998-02-16 00:01:12 +00:00
|
|
|
|
1998-02-27 21:46:00 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_Unraw(struct physical *modem)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
int oldflag;
|
|
|
|
|
1999-01-10 01:26:30 +00:00
|
|
|
if (modem->isatty && !physical_IsSync(modem)) {
|
1998-01-29 00:49:32 +00:00
|
|
|
tcsetattr(modem->fd, TCSAFLUSH, &modem->ios);
|
|
|
|
oldflag = fcntl(modem->fd, F_GETFL, 0);
|
1997-05-10 01:22:19 +00:00
|
|
|
if (oldflag < 0)
|
1997-08-25 00:29:32 +00:00
|
|
|
return;
|
1998-01-29 00:49:32 +00:00
|
|
|
(void) fcntl(modem->fd, F_SETFL, oldflag & ~O_NONBLOCK);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-01-29 00:44:16 +00:00
|
|
|
static void
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_PhysicalClose(struct physical *modem)
|
1997-10-29 01:19:51 +00:00
|
|
|
{
|
1998-05-28 23:17:51 +00:00
|
|
|
int newsid;
|
|
|
|
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Physical Close\n", modem->link.name);
|
1998-07-03 17:24:38 +00:00
|
|
|
timer_Stop(&modem->Timer);
|
1998-05-28 23:17:51 +00:00
|
|
|
newsid = tcgetpgrp(modem->fd) == getpgrp();
|
1998-01-29 00:49:32 +00:00
|
|
|
close(modem->fd);
|
|
|
|
modem->fd = -1;
|
1998-05-23 22:24:50 +00:00
|
|
|
log_SetTtyCommandMode(modem->dl);
|
1998-04-17 22:04:36 +00:00
|
|
|
throughput_stop(&modem->link.throughput);
|
1998-04-25 00:09:28 +00:00
|
|
|
throughput_log(&modem->link.throughput, LogPHASE, modem->link.name);
|
1998-05-29 18:33:10 +00:00
|
|
|
if (modem->session_owner != (pid_t)-1) {
|
|
|
|
ID0kill(modem->session_owner, SIGHUP);
|
|
|
|
modem->session_owner = (pid_t)-1;
|
|
|
|
}
|
1998-05-28 23:17:51 +00:00
|
|
|
if (newsid)
|
|
|
|
bundle_setsid(modem->dl->bundle, 0);
|
1997-10-29 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
1997-11-18 14:52:08 +00:00
|
|
|
void
|
1998-02-16 00:01:12 +00:00
|
|
|
modem_Offline(struct physical *modem)
|
1997-10-29 01:19:51 +00:00
|
|
|
{
|
1998-02-16 00:01:12 +00:00
|
|
|
if (modem->fd >= 0) {
|
|
|
|
struct termios tio;
|
1998-02-13 05:10:26 +00:00
|
|
|
|
1998-07-03 17:24:38 +00:00
|
|
|
timer_Stop(&modem->Timer);
|
1998-02-16 00:01:12 +00:00
|
|
|
modem->mbits &= ~TIOCM_DTR;
|
1999-01-10 01:26:30 +00:00
|
|
|
if (modem->isatty && Online(modem)) {
|
1998-02-16 00:01:12 +00:00
|
|
|
tcgetattr(modem->fd, &tio);
|
|
|
|
if (cfsetspeed(&tio, B0) == -1)
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogWARN, "%s: Unable to set modem to speed 0\n",
|
1998-04-28 01:25:46 +00:00
|
|
|
modem->link.name);
|
1998-02-16 00:01:12 +00:00
|
|
|
else
|
|
|
|
tcsetattr(modem->fd, TCSANOW, &tio);
|
|
|
|
/* nointr_sleep(1); */
|
|
|
|
}
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogPHASE, "%s: Disconnected!\n", modem->link.name);
|
1998-02-13 05:10:26 +00:00
|
|
|
}
|
1997-10-29 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
void
|
1998-02-13 05:10:26 +00:00
|
|
|
modem_Close(struct physical *modem)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-01-29 00:49:32 +00:00
|
|
|
if (modem->fd < 0)
|
1997-10-29 01:19:51 +00:00
|
|
|
return;
|
|
|
|
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Close\n", modem->link.name);
|
1997-11-18 14:52:08 +00:00
|
|
|
|
1999-01-10 01:26:30 +00:00
|
|
|
if (!modem->isatty) {
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_PhysicalClose(modem);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
if (*modem->name.full == '/')
|
|
|
|
modem_Unlock(modem);
|
1998-04-10 14:55:11 +00:00
|
|
|
*modem->name.full = '\0';
|
|
|
|
modem->name.base = modem->name.full;
|
1997-10-29 01:19:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-01-29 00:49:32 +00:00
|
|
|
if (modem->fd >= 0) {
|
1998-04-17 22:04:36 +00:00
|
|
|
tcflush(modem->fd, TCIOFLUSH);
|
|
|
|
modem_Unraw(modem);
|
|
|
|
modem_LogicalClose(modem);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-04-03 19:21:56 +00:00
|
|
|
modem_Destroy(struct physical *modem)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-04-03 19:21:56 +00:00
|
|
|
modem_Close(modem);
|
|
|
|
free(modem);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-01-29 00:44:16 +00:00
|
|
|
static void
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_LogicalClose(struct physical *modem)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-01 19:26:12 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: Logical Close\n", modem->link.name);
|
1998-01-29 00:49:32 +00:00
|
|
|
if (modem->fd >= 0) {
|
1998-05-01 19:26:12 +00:00
|
|
|
physical_Logout(modem);
|
1998-02-19 02:08:53 +00:00
|
|
|
modem_PhysicalClose(modem);
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_Unlock(modem);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-04-10 14:55:11 +00:00
|
|
|
*modem->name.full = '\0';
|
|
|
|
modem->name.base = modem->name.full;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-06-24 19:33:36 +00:00
|
|
|
static int
|
1998-04-03 19:21:56 +00:00
|
|
|
modem_DescriptorWrite(struct descriptor *d, struct bundle *bundle,
|
|
|
|
const fd_set *fdset)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-04-03 19:21:56 +00:00
|
|
|
struct physical *modem = descriptor2physical(d);
|
1999-04-03 11:54:00 +00:00
|
|
|
int nw, result = 0;
|
1998-01-29 00:44:16 +00:00
|
|
|
|
1998-04-03 19:21:56 +00:00
|
|
|
if (modem->out == NULL)
|
|
|
|
modem->out = link_Dequeue(&modem->link);
|
1998-01-30 19:46:07 +00:00
|
|
|
|
1998-01-29 00:49:32 +00:00
|
|
|
if (modem->out) {
|
1999-04-03 11:54:00 +00:00
|
|
|
nw = physical_Write(modem, MBUF_CTOP(modem->out), modem->out->cnt);
|
1998-05-08 01:15:19 +00:00
|
|
|
log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%d) to %d\n",
|
1999-04-03 11:54:00 +00:00
|
|
|
modem->link.name, nw, modem->out->cnt, modem->fd);
|
1995-01-31 06:29:58 +00:00
|
|
|
if (nw > 0) {
|
1998-01-29 00:49:32 +00:00
|
|
|
modem->out->cnt -= nw;
|
|
|
|
modem->out->offset += nw;
|
1998-04-03 19:21:56 +00:00
|
|
|
if (modem->out->cnt == 0)
|
1998-05-01 19:26:12 +00:00
|
|
|
modem->out = mbuf_FreeSeg(modem->out);
|
1998-06-24 19:33:36 +00:00
|
|
|
result = 1;
|
1995-02-27 10:57:54 +00:00
|
|
|
} else if (nw < 0) {
|
1997-06-11 03:57:51 +00:00
|
|
|
if (errno != EAGAIN) {
|
1998-05-08 01:15:19 +00:00
|
|
|
log_Printf(LogPHASE, "%s: write (%d): %s\n", modem->link.name,
|
|
|
|
modem->fd, strerror(errno));
|
1998-06-15 19:05:27 +00:00
|
|
|
datalink_Down(modem->dl, CLOSE_NORMAL);
|
1997-06-11 03:57:51 +00:00
|
|
|
}
|
1998-06-24 19:33:36 +00:00
|
|
|
result = 1;
|
1995-02-27 10:57:54 +00:00
|
|
|
}
|
1998-06-24 19:33:36 +00:00
|
|
|
/* else we shouldn't really have been called ! select() is broken ! */
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-06-24 19:33:36 +00:00
|
|
|
|
|
|
|
return result;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1998-02-06 02:22:28 +00:00
|
|
|
modem_ShowStatus(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-04-03 19:26:02 +00:00
|
|
|
struct physical *modem = arg->cx->physical;
|
1995-02-26 12:18:08 +00:00
|
|
|
#ifdef TIOCOUTQ
|
1995-01-31 06:29:58 +00:00
|
|
|
int nb;
|
1995-02-26 12:18:08 +00:00
|
|
|
#endif
|
|
|
|
|
1998-04-10 13:19:23 +00:00
|
|
|
prompt_Printf(arg->prompt, "Name: %s\n", modem->link.name);
|
|
|
|
prompt_Printf(arg->prompt, " State: ");
|
1998-04-25 10:49:52 +00:00
|
|
|
if (modem->fd >= 0) {
|
1999-01-10 01:26:30 +00:00
|
|
|
if (modem->isatty)
|
1998-04-10 13:19:23 +00:00
|
|
|
prompt_Printf(arg->prompt, "open, %s carrier\n",
|
|
|
|
Online(modem) ? "with" : "no");
|
|
|
|
else
|
|
|
|
prompt_Printf(arg->prompt, "open\n");
|
1998-04-25 10:49:52 +00:00
|
|
|
} else
|
1998-04-10 13:19:23 +00:00
|
|
|
prompt_Printf(arg->prompt, "closed\n");
|
1998-05-29 18:33:10 +00:00
|
|
|
prompt_Printf(arg->prompt, " Device: %s",
|
1998-04-10 13:19:23 +00:00
|
|
|
*modem->name.full ? modem->name.full :
|
1998-05-12 17:34:29 +00:00
|
|
|
modem->type == PHYS_DIRECT ? "unknown" : "N/A");
|
1998-05-29 18:33:10 +00:00
|
|
|
if (modem->session_owner != (pid_t)-1)
|
|
|
|
prompt_Printf(arg->prompt, " (session owner: %d)",
|
|
|
|
(int)modem->session_owner);
|
1998-01-29 00:44:16 +00:00
|
|
|
|
1998-05-29 18:33:10 +00:00
|
|
|
prompt_Printf(arg->prompt, "\n Link Type: %s\n", mode2Nam(modem->type));
|
1998-04-10 13:19:23 +00:00
|
|
|
prompt_Printf(arg->prompt, " Connect Count: %d\n",
|
|
|
|
modem->connect_count);
|
|
|
|
#ifdef TIOCOUTQ
|
|
|
|
if (modem->fd >= 0 && ioctl(modem->fd, TIOCOUTQ, &nb) >= 0)
|
|
|
|
prompt_Printf(arg->prompt, " Physical outq: %d\n", nb);
|
|
|
|
#endif
|
1997-06-09 03:27:43 +00:00
|
|
|
|
1998-04-10 13:22:38 +00:00
|
|
|
prompt_Printf(arg->prompt, " Queued Packets: %d\n",
|
1998-04-10 13:19:23 +00:00
|
|
|
link_QueueLen(&modem->link));
|
|
|
|
prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen);
|
1997-09-16 23:15:16 +00:00
|
|
|
|
1998-04-10 13:19:23 +00:00
|
|
|
prompt_Printf(arg->prompt, "\nDefaults:\n");
|
|
|
|
prompt_Printf(arg->prompt, " Device List: %s\n", modem->cfg.devlist);
|
|
|
|
prompt_Printf(arg->prompt, " Characteristics: ");
|
1998-05-01 19:26:12 +00:00
|
|
|
if (physical_IsSync(arg->cx->physical))
|
1998-04-03 19:26:02 +00:00
|
|
|
prompt_Printf(arg->prompt, "sync");
|
1995-02-26 12:18:08 +00:00
|
|
|
else
|
1998-04-03 19:26:02 +00:00
|
|
|
prompt_Printf(arg->prompt, "%dbps", modem->cfg.speed);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-04-03 19:26:02 +00:00
|
|
|
switch (modem->cfg.parity & CSIZE) {
|
1995-01-31 06:29:58 +00:00
|
|
|
case CS7:
|
1998-04-03 19:26:02 +00:00
|
|
|
prompt_Printf(arg->prompt, ", cs7");
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case CS8:
|
1998-04-03 19:26:02 +00:00
|
|
|
prompt_Printf(arg->prompt, ", cs8");
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
1998-04-03 19:26:02 +00:00
|
|
|
if (modem->cfg.parity & PARENB) {
|
|
|
|
if (modem->cfg.parity & PARODD)
|
|
|
|
prompt_Printf(arg->prompt, ", odd parity");
|
1995-01-31 06:29:58 +00:00
|
|
|
else
|
1998-04-03 19:26:02 +00:00
|
|
|
prompt_Printf(arg->prompt, ", even parity");
|
1995-01-31 06:29:58 +00:00
|
|
|
} else
|
1998-04-03 19:26:02 +00:00
|
|
|
prompt_Printf(arg->prompt, ", no parity");
|
1996-12-22 17:09:17 +00:00
|
|
|
|
1998-04-03 19:26:02 +00:00
|
|
|
prompt_Printf(arg->prompt, ", CTS/RTS %s\n",
|
|
|
|
(modem->cfg.rts_cts ? "on" : "off"));
|
1996-12-22 17:09:17 +00:00
|
|
|
|
1999-02-16 00:16:56 +00:00
|
|
|
prompt_Printf(arg->prompt, " CD check delay: %d second%s",
|
|
|
|
modem->cfg.cd.delay, modem->cfg.cd.delay == 1 ? "" : "s");
|
|
|
|
if (modem->cfg.cd.required)
|
|
|
|
prompt_Printf(arg->prompt, " (required!)\n\n");
|
|
|
|
else
|
|
|
|
prompt_Printf(arg->prompt, "\n\n");
|
1998-01-29 00:44:16 +00:00
|
|
|
|
1998-04-03 19:26:02 +00:00
|
|
|
throughput_disp(&modem->link.throughput, arg->prompt);
|
1998-01-30 19:46:07 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1998-01-29 00:44:16 +00:00
|
|
|
|
1998-02-09 19:21:11 +00:00
|
|
|
static void
|
1998-02-10 03:22:05 +00:00
|
|
|
modem_DescriptorRead(struct descriptor *d, struct bundle *bundle,
|
|
|
|
const fd_set *fdset)
|
1998-02-09 19:21:11 +00:00
|
|
|
{
|
|
|
|
struct physical *p = descriptor2physical(d);
|
1999-04-03 11:54:00 +00:00
|
|
|
u_char *rbuff;
|
|
|
|
int n, found;
|
|
|
|
|
|
|
|
rbuff = p->input.buf + p->input.sz;
|
1998-02-09 19:21:11 +00:00
|
|
|
|
|
|
|
/* something to read from modem */
|
1999-04-03 11:54:00 +00:00
|
|
|
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);
|
1998-05-08 01:15:19 +00:00
|
|
|
if (n <= 0) {
|
|
|
|
if (n < 0)
|
|
|
|
log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd,
|
|
|
|
strerror(errno));
|
1997-07-24 02:42:34 +00:00
|
|
|
else
|
1998-05-08 01:15:19 +00:00
|
|
|
log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n",
|
|
|
|
p->link.name, p->fd);
|
1998-06-15 19:05:27 +00:00
|
|
|
datalink_Down(p->dl, CLOSE_NORMAL);
|
1998-05-08 01:15:19 +00:00
|
|
|
return;
|
1998-03-13 01:36:10 +00:00
|
|
|
}
|
1999-04-03 11:54:00 +00:00
|
|
|
|
1998-05-08 01:15:19 +00:00
|
|
|
log_DumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
|
1999-04-03 11:54:00 +00:00
|
|
|
rbuff -= p->input.sz;
|
|
|
|
n += p->input.sz;
|
1998-02-09 19:21:11 +00:00
|
|
|
|
1998-04-03 19:21:56 +00:00
|
|
|
if (p->link.lcp.fsm.state <= ST_CLOSED) {
|
1998-04-10 13:19:23 +00:00
|
|
|
if (p->type != PHYS_DEDICATED) {
|
1999-04-03 11:54:00 +00:00
|
|
|
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) {
|
1998-02-09 19:21:11 +00:00
|
|
|
/* LCP packet is detected. Turn ourselves into packet mode */
|
1998-05-25 02:22:38 +00:00
|
|
|
log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n",
|
|
|
|
p->link.name);
|
1999-04-03 11:54:00 +00:00
|
|
|
log_SetTtyCommandMode(p->dl);
|
1998-04-03 19:26:29 +00:00
|
|
|
datalink_Up(p->dl, 0, 1);
|
1999-04-03 11:54:00 +00:00
|
|
|
async_Input(bundle, rbuff, p->input.sz, p);
|
|
|
|
p->input.sz = 0;
|
1998-02-10 03:23:50 +00:00
|
|
|
} else
|
1999-04-03 11:54:00 +00:00
|
|
|
bcopy(rbuff, p->input.buf, p->input.sz);
|
|
|
|
} else
|
|
|
|
/* In -dedicated mode, we just discard input until LCP is started */
|
|
|
|
p->input.sz = 0;
|
1998-02-09 19:21:11 +00:00
|
|
|
} else if (n > 0)
|
|
|
|
async_Input(bundle, rbuff, n, p);
|
|
|
|
}
|
1997-06-09 03:27:43 +00:00
|
|
|
|
1998-02-13 05:10:26 +00:00
|
|
|
static int
|
|
|
|
modem_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
|
|
|
|
{
|
1998-05-01 19:26:12 +00:00
|
|
|
return physical_UpdateSet(d, r, w, e, n, 0);
|
1998-02-13 05:10:26 +00:00
|
|
|
}
|
1997-11-18 14:52:08 +00:00
|
|
|
|
1998-04-30 23:53:56 +00:00
|
|
|
struct physical *
|
1998-05-02 21:57:50 +00:00
|
|
|
iov2modem(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, int fd)
|
1998-04-30 23:53:56 +00:00
|
|
|
{
|
1998-05-02 21:57:50 +00:00
|
|
|
struct physical *p;
|
1998-05-12 17:34:29 +00:00
|
|
|
int len;
|
1998-04-30 23:53:56 +00:00
|
|
|
|
1998-05-02 21:57:50 +00:00
|
|
|
p = (struct physical *)iov[(*niov)++].iov_base;
|
1998-04-30 23:53:56 +00:00
|
|
|
p->link.name = dl->name;
|
|
|
|
throughput_init(&p->link.throughput);
|
|
|
|
memset(&p->Timer, '\0', sizeof p->Timer);
|
|
|
|
memset(p->link.Queue, '\0', sizeof p->link.Queue);
|
|
|
|
|
|
|
|
p->desc.UpdateSet = modem_UpdateSet;
|
1998-05-01 19:26:12 +00:00
|
|
|
p->desc.IsSet = physical_IsSet;
|
1998-04-30 23:53:56 +00:00
|
|
|
p->desc.Read = modem_DescriptorRead;
|
|
|
|
p->desc.Write = modem_DescriptorWrite;
|
|
|
|
p->type = PHYS_DIRECT;
|
|
|
|
p->dl = dl;
|
1998-05-21 22:55:08 +00:00
|
|
|
len = strlen(_PATH_DEV);
|
1998-05-12 17:34:29 +00:00
|
|
|
p->name.base = strncmp(p->name.full, _PATH_DEV, len) ?
|
|
|
|
p->name.full : p->name.full + len;
|
1998-04-30 23:53:56 +00:00
|
|
|
p->out = NULL;
|
|
|
|
p->connect_count = 1;
|
|
|
|
|
|
|
|
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;
|
1998-05-08 01:15:19 +00:00
|
|
|
|
|
|
|
p->fd = fd;
|
|
|
|
|
1998-04-30 23:53:56 +00:00
|
|
|
if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load)
|
1998-05-08 01:15:19 +00:00
|
|
|
lqr_reStart(&p->link.lcp);
|
1998-04-30 23:53:56 +00:00
|
|
|
hdlc_StartTimer(&p->hdlc);
|
|
|
|
|
|
|
|
throughput_start(&p->link.throughput, "modem throughput",
|
|
|
|
Enabled(dl->bundle, OPT_THROUGHPUT));
|
1999-04-03 11:54:00 +00:00
|
|
|
p->input.sz = 0;
|
1998-05-03 11:24:16 +00:00
|
|
|
if (p->Timer.state != TIMER_STOPPED) {
|
|
|
|
p->Timer.state = TIMER_STOPPED; /* Special - see modem2iov() */
|
1999-02-16 00:16:56 +00:00
|
|
|
modem_StartTimer(dl->bundle, p); /* XXX: Should we set cd.required ? */
|
1998-05-03 11:24:16 +00:00
|
|
|
}
|
1998-04-30 23:53:56 +00:00
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1998-05-28 23:15:40 +00:00
|
|
|
modem2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov,
|
|
|
|
pid_t newpid)
|
1998-04-30 23:53:56 +00:00
|
|
|
{
|
1998-05-02 21:57:50 +00:00
|
|
|
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);
|
1998-05-03 11:24:16 +00:00
|
|
|
if (p->Timer.state != TIMER_STOPPED) {
|
|
|
|
timer_Stop(&p->Timer);
|
1998-05-29 18:33:10 +00:00
|
|
|
p->Timer.state = TIMER_RUNNING; /* Special - see iov2modem() */
|
1998-05-03 11:24:16 +00:00
|
|
|
}
|
1998-06-18 22:43:18 +00:00
|
|
|
if (tcgetpgrp(p->fd) == getpgrp())
|
|
|
|
p->session_owner = getpid(); /* So I'll eventually get HUP'd */
|
1998-05-02 21:57:50 +00:00
|
|
|
timer_Stop(&p->link.throughput.Timer);
|
1998-05-28 23:15:40 +00:00
|
|
|
modem_ChangedPid(p, newpid);
|
1998-05-02 21:57:50 +00:00
|
|
|
}
|
1998-04-30 23:53:56 +00:00
|
|
|
|
1998-05-02 21:57:50 +00:00
|
|
|
if (*niov >= maxiov) {
|
1998-06-16 19:40:42 +00:00
|
|
|
log_Printf(LogERROR, "modem2iov: No room for physical !\n");
|
1998-05-02 21:57:50 +00:00
|
|
|
if (p)
|
|
|
|
free(p);
|
|
|
|
return -1;
|
1998-04-30 23:53:56 +00:00
|
|
|
}
|
|
|
|
|
1998-05-02 21:57:50 +00:00
|
|
|
iov[*niov].iov_base = p ? p : malloc(sizeof *p);
|
|
|
|
iov[*niov].iov_len = sizeof *p;
|
|
|
|
(*niov)++;
|
1998-04-30 23:53:56 +00:00
|
|
|
|
1998-05-02 21:57:50 +00:00
|
|
|
return p ? p->fd : 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-05-28 23:15:40 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
modem_ChangedPid(struct physical *p, pid_t newpid)
|
|
|
|
{
|
1998-05-28 23:17:51 +00:00
|
|
|
if (p->fd >= 0 && p->type != PHYS_DIRECT) {
|
1998-05-28 23:15:40 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|