forked from Imagelibrary/rtems
2001-10-12 Mike Siers <mikes@poliac.com>
* Update to stable working state. Congratulations Mike! :) * modem_example: Directory removed. * modem_example/16550.h, modem_example/README, modem_example/modem.c, modem_example/modem.h, modem_example/ppp.c, modem_example/ppp.h, modem_example/pppcompress.c: Files removed. * pppd/example/pppd.options: New file. * pppd/README, pppd/STATUS, pppd/cbcp.c, pppd/cbcp.h, pppd/chat.c, pppd/pppd.h, pppd/rtemsmain.c: Updated.
This commit is contained in:
@@ -1,3 +1,14 @@
|
|||||||
|
2001-10-12 Mike Siers <mikes@poliac.com>
|
||||||
|
|
||||||
|
* Update to stable working state. Congratulations Mike! :)
|
||||||
|
* modem_example: Directory removed.
|
||||||
|
* modem_example/16550.h, modem_example/README, modem_example/modem.c,
|
||||||
|
modem_example/modem.h, modem_example/ppp.c, modem_example/ppp.h,
|
||||||
|
modem_example/pppcompress.c: Files removed.
|
||||||
|
* pppd/example/pppd.options: New file.
|
||||||
|
* pppd/README, pppd/STATUS, pppd/cbcp.c, pppd/cbcp.h, pppd/chat.c,
|
||||||
|
pppd/pppd.h, pppd/rtemsmain.c: Updated.
|
||||||
|
|
||||||
2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||||
|
|
||||||
* .cvsignore: Add autom4te.cache for autoconf > 2.52.
|
* .cvsignore: Add autom4te.cache for autoconf > 2.52.
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
2001-10-12 Mike Siers <mikes@poliac.com>
|
||||||
|
|
||||||
|
* Update to stable working state. Congratulations Mike! :)
|
||||||
|
* modem_example: Directory removed.
|
||||||
|
* modem_example/16550.h, modem_example/README, modem_example/modem.c,
|
||||||
|
modem_example/modem.h, modem_example/ppp.c, modem_example/ppp.h,
|
||||||
|
modem_example/pppcompress.c: Files removed.
|
||||||
|
* pppd/example/pppd.options: New file.
|
||||||
|
* pppd/README, pppd/STATUS, pppd/cbcp.c, pppd/cbcp.h, pppd/chat.c,
|
||||||
|
pppd/pppd.h, pppd/rtemsmain.c: Updated.
|
||||||
|
|
||||||
2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||||
|
|
||||||
* .cvsignore: Add autom4te.cache for autoconf > 2.52.
|
* .cvsignore: Add autom4te.cache for autoconf > 2.52.
|
||||||
|
|||||||
@@ -16,5 +16,9 @@ provided the modem driver as well.
|
|||||||
|
|
||||||
The port was updated to 2.3.11 by Mike Siers <mikes@poliac.com>
|
The port was updated to 2.3.11 by Mike Siers <mikes@poliac.com>
|
||||||
who added an example test.
|
who added an example test.
|
||||||
|
|
||||||
|
Updated the chat program to return the correct errors and support
|
||||||
|
the ABORT commands. Removed some dead code and did a lot of
|
||||||
|
testing on a new Coldfire BSP. Version seems to be very stable.
|
||||||
=================================================================
|
=================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -2,39 +2,28 @@
|
|||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
|
|
||||||
|
The pppd application seems to very stable. It has been tested using
|
||||||
|
the example application with the i386/pc586 and m68k/sbc5206e BSPs.
|
||||||
|
The tests were executed using a null modem serial cable to connect
|
||||||
|
with a UNIX box running either the ppp or pppd application and with
|
||||||
|
an external modem to dial up a local ISP.
|
||||||
|
|
||||||
Notes from Mike Siers <mikes@poliac.com>
|
If you have problems getting your target to make consistent connections
|
||||||
========================================
|
with an ISP, the problem is most likely with the ppp options. First
|
||||||
|
try using the "novj" and "noaccomp" options. If you have questions
|
||||||
|
about what other option values are available for the rtems_pppd_set_option
|
||||||
|
function, please look at the pppd.8 man page file or the the source code.
|
||||||
|
The majority of options that are documented in man page should work
|
||||||
|
with this function call.
|
||||||
|
|
||||||
I know that several users have tried out this version of
|
The pppd application requires the BSP termios driver support task
|
||||||
pppd under RTEMS. It has been successfully used as both
|
driven I/O. Below is a list of known issues that need to be resolved:
|
||||||
a client and server. Below are the only issues that I
|
|
||||||
know of.
|
|
||||||
|
|
||||||
1) Large packet ping causes RTEMS box to lock up
|
- pppd locks up when it receives large packet pings (> 1500 bytes)
|
||||||
If you ping the RTEMS box over the ppp link with a packet
|
- pppd occasionaly locks up with mbuf allocation error
|
||||||
size greater than 1500, the RTEMS box locks up. I think
|
(problem is rare and may be BSP related)
|
||||||
the problem is in the pppd ethernet driver.
|
|
||||||
|
|
||||||
2) Upgrade the libnetworking/modem files
|
If you find any other problems or fix some problems, please post your
|
||||||
This upgrade did not modify the ppp ethernet driver files
|
changes to the RTEMS mailing list.
|
||||||
in the libnetworking/modem directory. Would like to
|
|
||||||
upgrade these files. Hopefully, it will fix the large
|
|
||||||
packet ping problem.
|
|
||||||
|
|
||||||
3) The files cbcp.c and cbcp.h provide a callback feature
|
|
||||||
that I have not tried to compile or use. The files in
|
|
||||||
this directory are identical to the 2.3.11 versions.
|
|
||||||
for completeness.
|
|
||||||
|
|
||||||
|
|
||||||
JOEL: Are the modifications to the original pppd such that the
|
|
||||||
real maintainers will accept them?
|
|
||||||
|
|
||||||
No. The pppd 2.3.11 branch is an old branch. The current
|
|
||||||
version is 2.4.x and it contains alot of extra items that
|
|
||||||
just did not make sense to have in an embedded environment.
|
|
||||||
I could make the RTEMS changes compatible with the standard
|
|
||||||
2.3.11 release by using compilation flags. I have not
|
|
||||||
contacted the maintainers to see if they are interested.
|
|
||||||
|
|
||||||
|
Good Luck
|
||||||
|
|||||||
@@ -0,0 +1,456 @@
|
|||||||
|
/*
|
||||||
|
* cbcp - Call Back Configuration Protocol.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1995 Pedro Roque Marques
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 Pedro Roque Marques. The name of the author 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RCSID "$Id$"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "pppd.h"
|
||||||
|
#include "cbcp.h"
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "lcp.h"
|
||||||
|
|
||||||
|
static const char rcsid[] = RCSID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Options.
|
||||||
|
*/
|
||||||
|
static int setcbcp __P((char **));
|
||||||
|
|
||||||
|
static option_t cbcp_option_list[] = {
|
||||||
|
{ "callback", o_special, setcbcp,
|
||||||
|
"Ask for callback" },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protocol entry points.
|
||||||
|
*/
|
||||||
|
static void cbcp_init __P((int unit));
|
||||||
|
static void cbcp_open __P((int unit));
|
||||||
|
static void cbcp_lowerup __P((int unit));
|
||||||
|
static void cbcp_input __P((int unit, u_char *pkt, int len));
|
||||||
|
static void cbcp_protrej __P((int unit));
|
||||||
|
static int cbcp_printpkt __P((u_char *pkt, int len,
|
||||||
|
void (*printer) __P((void *, char *, ...)),
|
||||||
|
void *arg));
|
||||||
|
|
||||||
|
struct protent cbcp_protent = {
|
||||||
|
PPP_CBCP,
|
||||||
|
cbcp_init,
|
||||||
|
cbcp_input,
|
||||||
|
cbcp_protrej,
|
||||||
|
cbcp_lowerup,
|
||||||
|
NULL,
|
||||||
|
cbcp_open,
|
||||||
|
NULL,
|
||||||
|
cbcp_printpkt,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
"CBCP",
|
||||||
|
NULL,
|
||||||
|
cbcp_option_list,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
cbcp_state cbcp[NUM_PPP];
|
||||||
|
|
||||||
|
/* internal prototypes */
|
||||||
|
|
||||||
|
static void cbcp_recvreq __P((cbcp_state *us, char *pckt, int len));
|
||||||
|
static void cbcp_resp __P((cbcp_state *us));
|
||||||
|
static void cbcp_up __P((cbcp_state *us));
|
||||||
|
static void cbcp_recvack __P((cbcp_state *us, char *pckt, int len));
|
||||||
|
static void cbcp_send __P((cbcp_state *us, u_char code, u_char *buf, int len));
|
||||||
|
|
||||||
|
/* option processing */
|
||||||
|
static int
|
||||||
|
setcbcp(argv)
|
||||||
|
char **argv;
|
||||||
|
{
|
||||||
|
lcp_wantoptions[0].neg_cbcp = 1;
|
||||||
|
cbcp_protent.enabled_flag = 1;
|
||||||
|
cbcp[0].us_number = strdup(*argv);
|
||||||
|
if (cbcp[0].us_number == 0)
|
||||||
|
novm("callback number");
|
||||||
|
cbcp[0].us_type |= (1 << CB_CONF_USER);
|
||||||
|
cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init state */
|
||||||
|
static void
|
||||||
|
cbcp_init(iface)
|
||||||
|
int iface;
|
||||||
|
{
|
||||||
|
cbcp_state *us;
|
||||||
|
|
||||||
|
us = &cbcp[iface];
|
||||||
|
memset(us, 0, sizeof(cbcp_state));
|
||||||
|
us->us_unit = iface;
|
||||||
|
us->us_type |= (1 << CB_CONF_NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lower layer is up */
|
||||||
|
static void
|
||||||
|
cbcp_lowerup(iface)
|
||||||
|
int iface;
|
||||||
|
{
|
||||||
|
cbcp_state *us = &cbcp[iface];
|
||||||
|
|
||||||
|
dbglog("cbcp_lowerup");
|
||||||
|
dbglog("want: %d", us->us_type);
|
||||||
|
|
||||||
|
if (us->us_type == CB_CONF_USER)
|
||||||
|
dbglog("phone no: %s", us->us_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cbcp_open(unit)
|
||||||
|
int unit;
|
||||||
|
{
|
||||||
|
dbglog("cbcp_open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process an incomming packet */
|
||||||
|
static void
|
||||||
|
cbcp_input(unit, inpacket, pktlen)
|
||||||
|
int unit;
|
||||||
|
u_char *inpacket;
|
||||||
|
int pktlen;
|
||||||
|
{
|
||||||
|
u_char *inp;
|
||||||
|
u_char code, id;
|
||||||
|
u_short len;
|
||||||
|
|
||||||
|
cbcp_state *us = &cbcp[unit];
|
||||||
|
|
||||||
|
inp = inpacket;
|
||||||
|
|
||||||
|
if (pktlen < CBCP_MINLEN) {
|
||||||
|
error("CBCP packet is too small");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GETCHAR(code, inp);
|
||||||
|
GETCHAR(id, inp);
|
||||||
|
GETSHORT(len, inp);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (len > pktlen) {
|
||||||
|
error("CBCP packet: invalid length");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
len -= CBCP_MINLEN;
|
||||||
|
|
||||||
|
switch(code) {
|
||||||
|
case CBCP_REQ:
|
||||||
|
us->us_id = id;
|
||||||
|
cbcp_recvreq(us, inp, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CBCP_RESP:
|
||||||
|
dbglog("CBCP_RESP received");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CBCP_ACK:
|
||||||
|
if (id != us->us_id)
|
||||||
|
dbglog("id doesn't match: expected %d recv %d",
|
||||||
|
us->us_id, id);
|
||||||
|
|
||||||
|
cbcp_recvack(us, inp, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* protocol was rejected by foe */
|
||||||
|
void cbcp_protrej(int iface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
char *cbcp_codenames[] = {
|
||||||
|
"Request", "Response", "Ack"
|
||||||
|
};
|
||||||
|
|
||||||
|
char *cbcp_optionnames[] = {
|
||||||
|
"NoCallback",
|
||||||
|
"UserDefined",
|
||||||
|
"AdminDefined",
|
||||||
|
"List"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* pretty print a packet */
|
||||||
|
static int
|
||||||
|
cbcp_printpkt(p, plen, printer, arg)
|
||||||
|
u_char *p;
|
||||||
|
int plen;
|
||||||
|
void (*printer) __P((void *, char *, ...));
|
||||||
|
void *arg;
|
||||||
|
{
|
||||||
|
int code, opt, id, len, olen, delay;
|
||||||
|
u_char *pstart;
|
||||||
|
|
||||||
|
if (plen < HEADERLEN)
|
||||||
|
return 0;
|
||||||
|
pstart = p;
|
||||||
|
GETCHAR(code, p);
|
||||||
|
GETCHAR(id, p);
|
||||||
|
GETSHORT(len, p);
|
||||||
|
if (len < HEADERLEN || len > plen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
|
||||||
|
printer(arg, " %s", cbcp_codenames[code-1]);
|
||||||
|
else
|
||||||
|
printer(arg, " code=0x%x", code);
|
||||||
|
|
||||||
|
printer(arg, " id=0x%x", id);
|
||||||
|
len -= HEADERLEN;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case CBCP_REQ:
|
||||||
|
case CBCP_RESP:
|
||||||
|
case CBCP_ACK:
|
||||||
|
while(len >= 2) {
|
||||||
|
GETCHAR(opt, p);
|
||||||
|
GETCHAR(olen, p);
|
||||||
|
|
||||||
|
if (olen < 2 || olen > len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printer(arg, " <");
|
||||||
|
len -= olen;
|
||||||
|
|
||||||
|
if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
|
||||||
|
printer(arg, " %s", cbcp_optionnames[opt-1]);
|
||||||
|
else
|
||||||
|
printer(arg, " option=0x%x", opt);
|
||||||
|
|
||||||
|
if (olen > 2) {
|
||||||
|
GETCHAR(delay, p);
|
||||||
|
printer(arg, " delay = %d", delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (olen > 3) {
|
||||||
|
int addrt;
|
||||||
|
char str[256];
|
||||||
|
|
||||||
|
GETCHAR(addrt, p);
|
||||||
|
memcpy(str, p, olen - 4);
|
||||||
|
str[olen - 4] = 0;
|
||||||
|
printer(arg, " number = %s", str);
|
||||||
|
}
|
||||||
|
printer(arg, ">");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; len > 0; --len) {
|
||||||
|
GETCHAR(code, p);
|
||||||
|
printer(arg, " %.2x", code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - pstart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* received CBCP request */
|
||||||
|
static void
|
||||||
|
cbcp_recvreq(us, pckt, pcktlen)
|
||||||
|
cbcp_state *us;
|
||||||
|
char *pckt;
|
||||||
|
int pcktlen;
|
||||||
|
{
|
||||||
|
u_char type, opt_len, delay, addr_type;
|
||||||
|
char address[256];
|
||||||
|
int len = pcktlen;
|
||||||
|
|
||||||
|
address[0] = 0;
|
||||||
|
|
||||||
|
while (len) {
|
||||||
|
dbglog("length: %d", len);
|
||||||
|
|
||||||
|
GETCHAR(type, pckt);
|
||||||
|
GETCHAR(opt_len, pckt);
|
||||||
|
|
||||||
|
if (opt_len > 2)
|
||||||
|
GETCHAR(delay, pckt);
|
||||||
|
|
||||||
|
us->us_allowed |= (1 << type);
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CB_CONF_NO:
|
||||||
|
dbglog("no callback allowed");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_CONF_USER:
|
||||||
|
dbglog("user callback allowed");
|
||||||
|
if (opt_len > 4) {
|
||||||
|
GETCHAR(addr_type, pckt);
|
||||||
|
memcpy(address, pckt, opt_len - 4);
|
||||||
|
address[opt_len - 4] = 0;
|
||||||
|
if (address[0])
|
||||||
|
dbglog("address: %s", address);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_CONF_ADMIN:
|
||||||
|
dbglog("user admin defined allowed");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_CONF_LIST:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len -= opt_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbcp_resp(us);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cbcp_resp(us)
|
||||||
|
cbcp_state *us;
|
||||||
|
{
|
||||||
|
u_char cb_type;
|
||||||
|
u_char buf[256];
|
||||||
|
u_char *bufp = buf;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
cb_type = us->us_allowed & us->us_type;
|
||||||
|
dbglog("cbcp_resp cb_type=%d", cb_type);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (!cb_type)
|
||||||
|
lcp_down(us->us_unit);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (cb_type & ( 1 << CB_CONF_USER ) ) {
|
||||||
|
dbglog("cbcp_resp CONF_USER");
|
||||||
|
PUTCHAR(CB_CONF_USER, bufp);
|
||||||
|
len = 3 + 1 + strlen(us->us_number) + 1;
|
||||||
|
PUTCHAR(len , bufp);
|
||||||
|
PUTCHAR(5, bufp); /* delay */
|
||||||
|
PUTCHAR(1, bufp);
|
||||||
|
BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
|
||||||
|
cbcp_send(us, CBCP_RESP, buf, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
|
||||||
|
dbglog("cbcp_resp CONF_ADMIN");
|
||||||
|
PUTCHAR(CB_CONF_ADMIN, bufp);
|
||||||
|
len = 3;
|
||||||
|
PUTCHAR(len, bufp);
|
||||||
|
PUTCHAR(5, bufp); /* delay */
|
||||||
|
cbcp_send(us, CBCP_RESP, buf, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cb_type & ( 1 << CB_CONF_NO ) ) {
|
||||||
|
dbglog("cbcp_resp CONF_NO");
|
||||||
|
PUTCHAR(CB_CONF_NO, bufp);
|
||||||
|
len = 3;
|
||||||
|
PUTCHAR(len , bufp);
|
||||||
|
PUTCHAR(0, bufp);
|
||||||
|
cbcp_send(us, CBCP_RESP, buf, len);
|
||||||
|
start_networks();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cbcp_send(us, code, buf, len)
|
||||||
|
cbcp_state *us;
|
||||||
|
u_char code;
|
||||||
|
u_char *buf;
|
||||||
|
int len;
|
||||||
|
{
|
||||||
|
u_char *outp;
|
||||||
|
int outlen;
|
||||||
|
|
||||||
|
outp = outpacket_buf;
|
||||||
|
|
||||||
|
outlen = 4 + len;
|
||||||
|
|
||||||
|
MAKEHEADER(outp, PPP_CBCP);
|
||||||
|
|
||||||
|
PUTCHAR(code, outp);
|
||||||
|
PUTCHAR(us->us_id, outp);
|
||||||
|
PUTSHORT(outlen, outp);
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
BCOPY(buf, outp, len);
|
||||||
|
|
||||||
|
output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cbcp_recvack(us, pckt, len)
|
||||||
|
cbcp_state *us;
|
||||||
|
char *pckt;
|
||||||
|
int len;
|
||||||
|
{
|
||||||
|
u_char type, delay, addr_type;
|
||||||
|
int opt_len;
|
||||||
|
char address[256];
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
GETCHAR(type, pckt);
|
||||||
|
GETCHAR(opt_len, pckt);
|
||||||
|
|
||||||
|
if (opt_len > 2)
|
||||||
|
GETCHAR(delay, pckt);
|
||||||
|
|
||||||
|
if (opt_len > 4) {
|
||||||
|
GETCHAR(addr_type, pckt);
|
||||||
|
memcpy(address, pckt, opt_len - 4);
|
||||||
|
address[opt_len - 4] = 0;
|
||||||
|
if (address[0])
|
||||||
|
dbglog("peer will call: %s", address);
|
||||||
|
}
|
||||||
|
if (type == CB_CONF_NO)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbcp_up(us);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ok peer will do callback */
|
||||||
|
static void
|
||||||
|
cbcp_up(us)
|
||||||
|
cbcp_state *us;
|
||||||
|
{
|
||||||
|
persist = 0;
|
||||||
|
lcp_close(0, "Call me back, please");
|
||||||
|
status = EXIT_CALLBACK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef CBCP_H
|
||||||
|
#define CBCP_H
|
||||||
|
|
||||||
|
typedef struct cbcp_state {
|
||||||
|
int us_unit; /* Interface unit number */
|
||||||
|
u_char us_id; /* Current id */
|
||||||
|
u_char us_allowed;
|
||||||
|
int us_type;
|
||||||
|
char *us_number; /* Telefone Number */
|
||||||
|
} cbcp_state;
|
||||||
|
|
||||||
|
extern cbcp_state cbcp[];
|
||||||
|
|
||||||
|
extern struct protent cbcp_protent;
|
||||||
|
|
||||||
|
#define CBCP_MINLEN 4
|
||||||
|
|
||||||
|
#define CBCP_REQ 1
|
||||||
|
#define CBCP_RESP 2
|
||||||
|
#define CBCP_ACK 3
|
||||||
|
|
||||||
|
#define CB_CONF_NO 1
|
||||||
|
#define CB_CONF_USER 2
|
||||||
|
#define CB_CONF_ADMIN 3
|
||||||
|
#define CB_CONF_LIST 4
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -14,6 +14,12 @@
|
|||||||
* This software is in the public domain.
|
* This software is in the public domain.
|
||||||
*
|
*
|
||||||
* -----------------
|
* -----------------
|
||||||
|
* 22-May-99 added environment substitutuion, enabled with -E switch.
|
||||||
|
* Andreas Arens <andras@cityweb.de>.
|
||||||
|
*
|
||||||
|
* 12-May-99 added a feature to read data to be sent from a file,
|
||||||
|
* if the send string starts with @. Idea from gpk <gpk@onramp.net>.
|
||||||
|
*
|
||||||
* added -T and -U option and \T and \U substitution to pass a phone
|
* added -T and -U option and \T and \U substitution to pass a phone
|
||||||
* number into chat script. Two are needed for some ISDN TA applications.
|
* number into chat script. Two are needed for some ISDN TA applications.
|
||||||
* Keith Dart <kdart@cisco.com>
|
* Keith Dart <kdart@cisco.com>
|
||||||
@@ -74,18 +80,12 @@
|
|||||||
* Columbus, OH 43221
|
* Columbus, OH 43221
|
||||||
* (614)451-1883
|
* (614)451-1883
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
/* static char rcsid[] = ""; */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -93,13 +93,13 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include "pppd.h"
|
||||||
|
|
||||||
#undef TERMIOS
|
#undef TERMIOS
|
||||||
#define TERMIOS
|
#define TERMIOS
|
||||||
|
|
||||||
|
|
||||||
#include <termios.h>
|
|
||||||
|
|
||||||
#define STR_LEN 1024
|
#define STR_LEN 1024
|
||||||
char temp2[STR_LEN];
|
char temp2[STR_LEN];
|
||||||
|
|
||||||
@@ -142,39 +142,34 @@ static int _O = 0; /* Internal state */
|
|||||||
|
|
||||||
char *program_name;
|
char *program_name;
|
||||||
|
|
||||||
#define MAX_ABORTS 5
|
#define MAX_ABORTS 16
|
||||||
#define MAX_REPORTS 5
|
#define MAX_REPORTS 16
|
||||||
#define DEFAULT_CHAT_TIMEOUT 45
|
#define DEFAULT_CHAT_TIMEOUT 45
|
||||||
#define fcntl(a, b,c ) 0
|
#define MAX_TIMEOUTS 10
|
||||||
#define MAX_TIMEOUTS 10
|
|
||||||
|
|
||||||
int echo = 0;
|
int echo = 0;
|
||||||
int verbose = 0;
|
int quiet = 0;
|
||||||
int to_log = 1;
|
int report = 0;
|
||||||
int to_stderr = 0;
|
int use_env = 0;
|
||||||
int Verbose = 0;
|
int exit_code = 0;
|
||||||
int quiet = 0;
|
char *report_file = (char *) 0;
|
||||||
int report = 0;
|
char *chat_file = (char *) 0;
|
||||||
int exit_code = 0;
|
char *phone_num = (char *) 0;
|
||||||
char *report_file = (char *) 0;
|
char *phone_num2 = (char *) 0;
|
||||||
char *chat_file = (char *) 0;
|
static int timeout = DEFAULT_CHAT_TIMEOUT;
|
||||||
char *phone_num = (char *) 0;
|
|
||||||
char *phone_num2 = (char *) 0;
|
|
||||||
int chat_timeout = DEFAULT_CHAT_TIMEOUT;
|
|
||||||
static int timeout = DEFAULT_CHAT_TIMEOUT;
|
|
||||||
int have_tty_parameters = 0;
|
|
||||||
|
|
||||||
#ifdef TERMIOS
|
#ifdef TERMIOS
|
||||||
#define term_parms struct termios
|
#define term_parms struct termios
|
||||||
#define get_term_param(param) tcgetattr(ttyfd, param)
|
#define get_term_param(param) tcgetattr(0, param)
|
||||||
#define set_term_param(param) tcsetattr(ttyfd, TCSANOW, param)
|
#define set_term_param(param) tcsetattr(0, TCSANOW, param)
|
||||||
struct termios saved_tty_parameters;
|
struct termios saved_tty_parameters;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *abort_string[MAX_ABORTS]={"BUSY","NO DIALTONE","NO CARRIER","NO ASWER","RINGING\r\n\r\nRINGING"};
|
char *fail_reason = (char *)0;
|
||||||
char *fail_reason = (char *)0,
|
char fail_buffer[50];
|
||||||
fail_buffer[50];
|
char *abort_string[MAX_ABORTS]={"BUSY","NO DIALTONE","NO CARRIER","NO ANSWER","RING\r\nRING"};
|
||||||
int n_aborts = MAX_ABORTS, abort_next = 0, timeout_next = 0, echo_next = 0;
|
int n_aborts = 5;
|
||||||
|
int abort_next = 0, timeout_next = 0, echo_next = 0;
|
||||||
int clear_abort_next = 0;
|
int clear_abort_next = 0;
|
||||||
|
|
||||||
char *report_string[MAX_REPORTS] ;
|
char *report_string[MAX_REPORTS] ;
|
||||||
@@ -186,19 +181,7 @@ int say_next = 0, hup_next = 0;
|
|||||||
|
|
||||||
void *dup_mem __P((void *b, size_t c));
|
void *dup_mem __P((void *b, size_t c));
|
||||||
void *copy_of __P((char *s));
|
void *copy_of __P((char *s));
|
||||||
/*
|
|
||||||
SIGTYPE sigalrm __P((int signo));
|
|
||||||
SIGTYPE sigint __P((int signo));
|
|
||||||
SIGTYPE sigterm __P((int signo));
|
|
||||||
SIGTYPE sighup __P((int signo));
|
|
||||||
*/
|
|
||||||
void unalarm __P((void));
|
|
||||||
void init __P((void));
|
|
||||||
void set_tty_parameters __P((void));
|
|
||||||
void echo_stderr __P((int));
|
|
||||||
void break_sequence __P((void));
|
void break_sequence __P((void));
|
||||||
void terminate __P((int status));
|
|
||||||
void do_file __P((char *chat_file));
|
|
||||||
int get_string __P((register char *string));
|
int get_string __P((register char *string));
|
||||||
int put_string __P((register char *s));
|
int put_string __P((register char *s));
|
||||||
int write_char __P((int c));
|
int write_char __P((int c));
|
||||||
@@ -208,19 +191,9 @@ void chat_send __P((register char *s));
|
|||||||
char *character __P((int c));
|
char *character __P((int c));
|
||||||
void chat_expect __P((register char *s));
|
void chat_expect __P((register char *s));
|
||||||
char *clean __P((register char *s, int sending));
|
char *clean __P((register char *s, int sending));
|
||||||
void break_sequence __P((void));
|
|
||||||
void terminate __P((int status));
|
|
||||||
void pack_array __P((char **array, int end));
|
|
||||||
char *expect_strtok __P((char *, char *));
|
char *expect_strtok __P((char *, char *));
|
||||||
int vfmtmsg __P((char *, int, const char *, va_list)); /* vsprintf++ */
|
int chatmain __P((char *));
|
||||||
|
|
||||||
#if 0
|
|
||||||
int usleep( long usec ); /* returns 0 if ok, else -1 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int input_fd,output_fd;
|
|
||||||
|
|
||||||
int main __P((int, char *[]));
|
|
||||||
|
|
||||||
void *dup_mem(b, c)
|
void *dup_mem(b, c)
|
||||||
void *b;
|
void *b;
|
||||||
@@ -228,29 +201,22 @@ size_t c;
|
|||||||
{
|
{
|
||||||
void *ans = malloc (c);
|
void *ans = malloc (c);
|
||||||
if (!ans)
|
if (!ans)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memcpy (ans, b, c);
|
memcpy(ans, b, c);
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *copy_of (s)
|
void *copy_of (s)
|
||||||
char *s;
|
char *s;
|
||||||
{
|
{
|
||||||
return dup_mem (s, strlen (s) + 1);
|
return dup_mem(s, strlen (s) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* chat [ -v ] [-T number] [-U number] [ -t timeout ] [ -f chat-file ] \
|
|
||||||
* [ -r report-file ] \
|
|
||||||
* [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]]
|
|
||||||
*
|
|
||||||
* Perform a UUCP-dialer-like chat script on stdin and stdout.
|
|
||||||
*/
|
|
||||||
char *getnextcommand(char **string)
|
char *getnextcommand(char **string)
|
||||||
{
|
{
|
||||||
char *buf=*string,*res;
|
char *buf=*string,*res;
|
||||||
res=strchr(buf,'@');
|
res=strchr(buf,'|');
|
||||||
if (res==NULL)
|
if (res==NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
*res='\0';
|
*res='\0';
|
||||||
@@ -258,8 +224,6 @@ char *getnextcommand(char **string)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern int ttyfd;
|
|
||||||
int chatmain(argv)
|
int chatmain(argv)
|
||||||
char *argv;
|
char *argv;
|
||||||
{
|
{
|
||||||
@@ -268,78 +232,40 @@ char *argv;
|
|||||||
/* initialize exit code */
|
/* initialize exit code */
|
||||||
exit_code = 0;
|
exit_code = 0;
|
||||||
|
|
||||||
printf("chat_main: %s\n", argv);
|
if ( debug ) {
|
||||||
|
dbglog("chat_main: %s\n", argv);
|
||||||
|
}
|
||||||
|
|
||||||
/* get first expect string */
|
/* get first expect string */
|
||||||
arg = getnextcommand(&argv);
|
arg = getnextcommand(&argv);
|
||||||
while ( arg != NULL ) {
|
while (( arg != NULL ) && ( exit_code == 0 )) {
|
||||||
/* process the expect string */
|
/* process the expect string */
|
||||||
chat_expect(arg);
|
chat_expect(arg);
|
||||||
|
if ( exit_code == 0 ) {
|
||||||
/* get the next send string */
|
/* get the next send string */
|
||||||
arg = getnextcommand(&argv);
|
|
||||||
if ( arg != NULL ) {
|
|
||||||
/* process the send string */
|
|
||||||
chat_send(arg);
|
|
||||||
|
|
||||||
/* get the next expect string */
|
|
||||||
arg = getnextcommand(&argv);
|
arg = getnextcommand(&argv);
|
||||||
|
if ( arg != NULL ) {
|
||||||
|
/* process the send string */
|
||||||
|
chat_send(arg);
|
||||||
|
|
||||||
|
/* get the next expect string */
|
||||||
|
arg = getnextcommand(&argv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if ( exit_code ) {
|
||||||
}
|
exit_code = -exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( exit_code );
|
||||||
|
|
||||||
/*
|
|
||||||
* Print an error message and terminate.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void init()
|
|
||||||
{
|
|
||||||
set_tty_parameters();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_tty_parameters()
|
|
||||||
{
|
|
||||||
term_parms t;
|
|
||||||
|
|
||||||
if (get_term_param (&t) < 0)
|
|
||||||
syslog(LOG_NOTICE,"Can't get terminal parameters:")
|
|
||||||
;
|
|
||||||
|
|
||||||
saved_tty_parameters = t;
|
|
||||||
have_tty_parameters = 1;
|
|
||||||
t.c_iflag |= IGNBRK | ISTRIP | IGNPAR;
|
|
||||||
t.c_oflag = 0;
|
|
||||||
t.c_lflag = 0;
|
|
||||||
t.c_cc[VERASE] =
|
|
||||||
t.c_cc[VKILL] = 0;
|
|
||||||
t.c_cc[VMIN] = 0;
|
|
||||||
t.c_cc[VTIME] = 1;
|
|
||||||
if (set_term_param (&t) < 0)
|
|
||||||
syslog(LOG_NOTICE,"Can't set terminal parameters:")
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void break_sequence()
|
void break_sequence()
|
||||||
{
|
{
|
||||||
|
tcsendbreak(ttyfd, 0);
|
||||||
/* tcsendbreak (0, 0);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void terminate(status)
|
|
||||||
int status;
|
|
||||||
{
|
|
||||||
echo_stderr(-1);
|
|
||||||
|
|
||||||
if (have_tty_parameters) {
|
|
||||||
if (set_term_param (&saved_tty_parameters) < 0)
|
|
||||||
fatal(2, "Can't restore terminal parameters: %m");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
* 'Clean up' this string.
|
* 'Clean up' this string.
|
||||||
*/
|
*/
|
||||||
@@ -347,10 +273,14 @@ char *clean(s, sending)
|
|||||||
register char *s;
|
register char *s;
|
||||||
int sending; /* set to 1 when sending (putting) this string. */
|
int sending; /* set to 1 when sending (putting) this string. */
|
||||||
{
|
{
|
||||||
char temp[STR_LEN], cur_chr;
|
char temp[STR_LEN], env_str[STR_LEN], cur_chr;
|
||||||
register char *s1, *phchar;
|
register char *s1, *phchar;
|
||||||
int add_return = sending;
|
int add_return = sending;
|
||||||
#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
|
#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
|
||||||
|
#define isalnumx(chr) ((((chr) >= '0') && ((chr) <= '9')) \
|
||||||
|
|| (((chr) >= 'a') && ((chr) <= 'z')) \
|
||||||
|
|| (((chr) >= 'A') && ((chr) <= 'Z')) \
|
||||||
|
|| (chr) == '_')
|
||||||
|
|
||||||
s1 = temp;
|
s1 = temp;
|
||||||
while (*s) {
|
while (*s) {
|
||||||
@@ -367,6 +297,18 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_env && cur_chr == '$') { /* ARI */
|
||||||
|
phchar = env_str;
|
||||||
|
while (isalnumx(*s))
|
||||||
|
*phchar++ = *s++;
|
||||||
|
*phchar = '\0';
|
||||||
|
phchar = getenv(env_str);
|
||||||
|
if (phchar)
|
||||||
|
while (*phchar)
|
||||||
|
*s1++ = *phchar++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (cur_chr != '\\') {
|
if (cur_chr != '\\') {
|
||||||
*s1++ = cur_chr;
|
*s1++ = cur_chr;
|
||||||
@@ -400,13 +342,12 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
case 'd':
|
case 'd':
|
||||||
if (sending)
|
if (sending)
|
||||||
*s1++ = '\\';
|
*s1++ = '\\';
|
||||||
|
|
||||||
*s1++ = cur_chr;
|
*s1++ = cur_chr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
if (sending && phone_num) {
|
if (sending && phone_num) {
|
||||||
for ( phchar = phone_num; *phchar != '\0'; phchar++)
|
for (phchar = phone_num; *phchar != '\0'; phchar++)
|
||||||
*s1++ = *phchar;
|
*s1++ = *phchar;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -417,7 +358,7 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
if (sending && phone_num2) {
|
if (sending && phone_num2) {
|
||||||
for ( phchar = phone_num2; *phchar != '\0'; phchar++)
|
for (phchar = phone_num2; *phchar != '\0'; phchar++)
|
||||||
*s1++ = *phchar;
|
*s1++ = *phchar;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -455,6 +396,13 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
*s1++ = 'N';
|
*s1++ = 'N';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '$': /* ARI */
|
||||||
|
if (use_env) {
|
||||||
|
*s1++ = cur_chr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* FALL THROUGH */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (isoctal (cur_chr)) {
|
if (isoctal (cur_chr)) {
|
||||||
cur_chr &= 0x07;
|
cur_chr &= 0x07;
|
||||||
@@ -493,7 +441,6 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
/*
|
/*
|
||||||
* A modified version of 'strtok'. This version skips \ sequences.
|
* A modified version of 'strtok'. This version skips \ sequences.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *expect_strtok (s, term)
|
char *expect_strtok (s, term)
|
||||||
char *s, *term;
|
char *s, *term;
|
||||||
{
|
{
|
||||||
@@ -548,8 +495,7 @@ char *expect_strtok (s, term)
|
|||||||
/*
|
/*
|
||||||
* Process the expect string
|
* Process the expect string
|
||||||
*/
|
*/
|
||||||
|
void chat_expect (s)
|
||||||
void chat_expect (s)
|
|
||||||
char *s;
|
char *s;
|
||||||
{
|
{
|
||||||
char *expect;
|
char *expect;
|
||||||
@@ -557,42 +503,42 @@ char *s;
|
|||||||
|
|
||||||
if (strcmp(s, "HANGUP") == 0) {
|
if (strcmp(s, "HANGUP") == 0) {
|
||||||
++hup_next;
|
++hup_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "ABORT") == 0) {
|
if (strcmp(s, "ABORT") == 0) {
|
||||||
++abort_next;
|
++abort_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "CLR_ABORT") == 0) {
|
if (strcmp(s, "CLR_ABORT") == 0) {
|
||||||
++clear_abort_next;
|
++clear_abort_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "REPORT") == 0) {
|
if (strcmp(s, "REPORT") == 0) {
|
||||||
++report_next;
|
++report_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "CLR_REPORT") == 0) {
|
if (strcmp(s, "CLR_REPORT") == 0) {
|
||||||
++clear_report_next;
|
++clear_report_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "TIMEOUT") == 0) {
|
if (strcmp(s, "TIMEOUT") == 0) {
|
||||||
++timeout_next;
|
++timeout_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "ECHO") == 0) {
|
if (strcmp(s, "ECHO") == 0) {
|
||||||
++echo_next;
|
++echo_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "SAY") == 0) {
|
if (strcmp(s, "SAY") == 0) {
|
||||||
++say_next;
|
++say_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -600,10 +546,10 @@ char *s;
|
|||||||
*/
|
*/
|
||||||
for (;;) {
|
for (;;) {
|
||||||
expect = expect_strtok (s, "-");
|
expect = expect_strtok (s, "-");
|
||||||
s = (char *)0 ;
|
s = (char *) 0;
|
||||||
|
|
||||||
if (expect == (char *) 0)
|
if (expect == (char *) 0)
|
||||||
return ;
|
return;
|
||||||
|
|
||||||
reply = expect_strtok (s, "-");
|
reply = expect_strtok (s, "-");
|
||||||
|
|
||||||
@@ -622,11 +568,30 @@ char *s;
|
|||||||
|
|
||||||
chat_send (reply);
|
chat_send (reply);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The expectation did not occur. This is terminal.
|
* Translate the input character to the appropriate string for printing
|
||||||
|
* the data.
|
||||||
*/
|
*/
|
||||||
return ;
|
|
||||||
|
char *character(c)
|
||||||
|
int c;
|
||||||
|
{
|
||||||
|
static char string[10];
|
||||||
|
char *meta;
|
||||||
|
|
||||||
|
meta = (c & 0x80) ? "M-" : "";
|
||||||
|
c &= 0x7F;
|
||||||
|
|
||||||
|
if (c < 32)
|
||||||
|
sprintf(string, "%s^%c", meta, (int)c + '@');
|
||||||
|
else if (c == 127)
|
||||||
|
sprintf(string, "%s^?", meta);
|
||||||
|
else
|
||||||
|
sprintf(string, "%s%c", meta, c);
|
||||||
|
|
||||||
|
return (string);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -635,16 +600,19 @@ char *s;
|
|||||||
void chat_send (s)
|
void chat_send (s)
|
||||||
register char *s;
|
register char *s;
|
||||||
{
|
{
|
||||||
|
char file_data[STR_LEN];
|
||||||
|
|
||||||
if (say_next) {
|
if (say_next) {
|
||||||
say_next = 0;
|
say_next = 0;
|
||||||
s = clean(s,0);
|
s = clean(s, 1);
|
||||||
write(ttyfd, s, strlen(s));
|
write(2, s, strlen(s));
|
||||||
free(s);
|
free(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hup_next) {
|
if (hup_next) {
|
||||||
hup_next = 0;
|
hup_next = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (echo_next) {
|
if (echo_next) {
|
||||||
@@ -654,36 +622,53 @@ register char *s;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (abort_next) {
|
if (abort_next) {
|
||||||
/* char *s1; */
|
char *s1;
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
|
abort_next = 0;
|
||||||
|
if ( n_aborts < MAX_ABORTS ) {
|
||||||
|
s1 = clean(s, 0);
|
||||||
|
if (( strlen(s1) <= strlen(s) ) &&
|
||||||
|
( strlen(s1) < sizeof(fail_buffer))) {
|
||||||
|
|
||||||
|
abort_string[n_aborts++] = s1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clear_abort_next) {
|
||||||
|
clear_abort_next = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report_next) {
|
||||||
|
report_next = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clear_report_next) {
|
||||||
|
clear_report_next = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout_next) {
|
if (timeout_next) {
|
||||||
timeout=atoi(s);
|
|
||||||
timeout_next = 0;
|
timeout_next = 0;
|
||||||
chat_timeout = atoi(s);
|
timeout = atoi(s);
|
||||||
|
|
||||||
if (chat_timeout <= 0)
|
if (timeout <= 0)
|
||||||
chat_timeout = DEFAULT_CHAT_TIMEOUT;
|
timeout = DEFAULT_CHAT_TIMEOUT;
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "EOT") == 0)
|
if (strcmp(s, "EOT") == 0)
|
||||||
s = "^D\\c";
|
s = "^D\\c";
|
||||||
else if (strcmp(s, "BREAK") == 0)
|
else if (strcmp(s, "BREAK") == 0)
|
||||||
s = "\\K\\c";
|
s = "\\K\\c";
|
||||||
|
|
||||||
if (!put_string(s))
|
if (!put_string(s)) {
|
||||||
{
|
exit_code = 2;
|
||||||
exit_code=1;
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_char()
|
int get_char()
|
||||||
@@ -708,21 +693,10 @@ int get_char()
|
|||||||
int put_char(c)
|
int put_char(c)
|
||||||
int c;
|
int c;
|
||||||
{
|
{
|
||||||
int status;
|
char ch = c;
|
||||||
char ch = c;
|
|
||||||
|
|
||||||
/* inter-character typing delay (?) */
|
write(ttyfd, &ch, 1);
|
||||||
|
|
||||||
status = write(ttyfd, &ch, 1);
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case 1:
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,44 +748,12 @@ register char *s;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* alarm(0);*/
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Echo a character to stderr.
|
|
||||||
* When called with -1, a '\n' character is generated when
|
|
||||||
* the cursor is not at the beginning of a line.
|
|
||||||
*/
|
|
||||||
void echo_stderr(n)
|
|
||||||
int n;
|
|
||||||
{
|
|
||||||
/* static int need_lf;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
switch (n) {
|
|
||||||
case '\r':
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
if (need_lf == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\n':
|
|
||||||
write(2, "\n", 1);
|
|
||||||
need_lf = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
s = character(n);
|
|
||||||
write(2, s, strlen(s));
|
|
||||||
need_lf = 1;
|
|
||||||
break;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 'Wait for' this string to appear on this file descriptor.
|
* 'Wait for' this string to appear on this file descriptor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int get_string(string)
|
int get_string(string)
|
||||||
register char *string;
|
register char *string;
|
||||||
{
|
{
|
||||||
@@ -820,6 +762,8 @@ register char *string;
|
|||||||
char *logged = temp2;
|
char *logged = temp2;
|
||||||
struct termios tios;
|
struct termios tios;
|
||||||
|
|
||||||
|
memset(temp2, 0, sizeof(temp2));
|
||||||
|
|
||||||
tcgetattr(ttyfd, &tios);
|
tcgetattr(ttyfd, &tios);
|
||||||
tios.c_cc[VMIN] = 0;
|
tios.c_cc[VMIN] = 0;
|
||||||
tios.c_cc[VTIME] = timeout*10/MAX_TIMEOUTS;
|
tios.c_cc[VTIME] = timeout*10/MAX_TIMEOUTS;
|
||||||
@@ -838,13 +782,12 @@ register char *string;
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
while ( (c = get_char()) >= 0) {
|
while ( (c = get_char()) >= 0) {
|
||||||
int n, abort_len;
|
int n, abort_len;
|
||||||
|
|
||||||
*s++ = c;
|
*s++ = c;
|
||||||
*s=0;
|
*s=0;
|
||||||
|
|
||||||
if (s - temp2 >= len &&
|
if (s - temp2 >= len &&
|
||||||
c == string[len - 1] &&
|
c == string[len - 1] &&
|
||||||
strncmp(s - len, string, len) == 0) {
|
strncmp(s - len, string, len) == 0) {
|
||||||
@@ -871,60 +814,7 @@ register char *string;
|
|||||||
s = temp2 + minlen;
|
s = temp2 + minlen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_code = 3;
|
exit_code = 3;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Gross kludge to handle Solaris versions >= 2.6 having usleep.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
usleep -- support routine for 4.2BSD system call emulations
|
|
||||||
last edit: 29-Oct-1984 D A Gwyn
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int
|
|
||||||
usleep( usec ) /* returns 0 if ok, else -1 */
|
|
||||||
long usec; /* delay in microseconds */
|
|
||||||
{
|
|
||||||
rtems_status_code status;
|
|
||||||
rtems_interval ticks_per_second;
|
|
||||||
rtems_interval ticks;
|
|
||||||
status = rtems_clock_get(
|
|
||||||
RTEMS_CLOCK_GET_TICKS_PER_SECOND,
|
|
||||||
&ticks_per_second);
|
|
||||||
ticks = (usec * (ticks_per_second/1000))/1000;
|
|
||||||
status = rtems_task_wake_after( ticks );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void pack_array (array, end)
|
|
||||||
char **array; /* The address of the array of string pointers */
|
|
||||||
int end; /* The index of the next free entry before CLR_ */
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
for (i = 0; i < end; i++) {
|
|
||||||
if (array[i] == NULL) {
|
|
||||||
for (j = i+1; j < end; ++j)
|
|
||||||
if (array[j] != NULL)
|
|
||||||
array[i++] = array[j];
|
|
||||||
for (; i < end; ++i)
|
|
||||||
array[i] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* vfmtmsg - format a message into a buffer. Like vsprintf except we
|
|
||||||
* also specify the length of the output buffer, and we handle the
|
|
||||||
* %m (error message) format.
|
|
||||||
* Doesn't do floating-point formats.
|
|
||||||
* Returns the number of chars put into buf.
|
|
||||||
*/
|
|
||||||
#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
|
|
||||||
|
|||||||
@@ -6,3 +6,10 @@ This is an example user application using pppd. It is built using
|
|||||||
the RTEMS application Makefiles. The file Makefile-user should
|
the RTEMS application Makefiles. The file Makefile-user should
|
||||||
be renamed to Makefile or the -f option given to make. The file
|
be renamed to Makefile or the -f option given to make. The file
|
||||||
is renamed to avoid bootstrap -c removing it.
|
is renamed to avoid bootstrap -c removing it.
|
||||||
|
|
||||||
|
The files ppp.conf and pppd.options are sample configuration files
|
||||||
|
that have successfully used to make ppp connections over a null
|
||||||
|
modem serial cable to a UNIX box. Please review the man pages
|
||||||
|
for either the ppp or pppd applications to ensure they are configured
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
|||||||
9
c/src/libnetworking/pppd/example/pppd.options
Normal file
9
c/src/libnetworking/pppd/example/pppd.options
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/dev/tty00
|
||||||
|
57600
|
||||||
|
crtscts
|
||||||
|
passive
|
||||||
|
local
|
||||||
|
noauth
|
||||||
|
debug
|
||||||
|
persist
|
||||||
|
192.168.2.222:192.168.2.111
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
*-------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* 16550 -- header file for National Semiconducor's 16550 UART
|
|
||||||
*
|
|
||||||
* This file has been created by John S. Gwynne for the efi68k
|
|
||||||
* project.
|
|
||||||
*
|
|
||||||
* The license and distribution terms for this file may in
|
|
||||||
* the file LICENSE in this distribution or at
|
|
||||||
* http://www.OARcorp.com/rtems/license.html.
|
|
||||||
*
|
|
||||||
*------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _16550_H_
|
|
||||||
#define _16550_H_
|
|
||||||
|
|
||||||
/* base address is the physical location of register 0 */
|
|
||||||
#define UART_BASE_ADDRESS 0xF0000000
|
|
||||||
|
|
||||||
/* definitions of register addresses and associate bits */
|
|
||||||
|
|
||||||
#define RBR (volatile unsigned char * const)(0+UART_BASE_ADDRESS)
|
|
||||||
/* Receiver Buffer Register (w/DLAB=0)*/
|
|
||||||
/* 8-bit data */
|
|
||||||
|
|
||||||
#define THR (volatile unsigned char * const)(0+UART_BASE_ADDRESS)
|
|
||||||
/* Transmitter Holding Register (w/DLAB=0) */
|
|
||||||
/* 8-bit data */
|
|
||||||
|
|
||||||
#define DLL (volatile unsigned char * const)(0+UART_BASE_ADDRESS)
|
|
||||||
/* Divisor Latch (LS) (w/DLAB=1) */
|
|
||||||
/* LSB of Divisor */
|
|
||||||
|
|
||||||
#define DLM (volatile unsigned char * const)(1+UART_BASE_ADDRESS)
|
|
||||||
/* Divisor Latch (MS) (w/DLAB=1) */
|
|
||||||
/* MSB of Divisor */
|
|
||||||
|
|
||||||
#define IER (volatile unsigned char * const)(1+UART_BASE_ADDRESS)
|
|
||||||
/* Interrupt Enable Register (w/DLAB=0) */
|
|
||||||
#define ERBFI 0x01 /* Enable Recv Data Available Interrupt */
|
|
||||||
#define ETBEI 0x02 /* Enable Trans Holding Reg Empty Inter */
|
|
||||||
#define ELSI 0x04 /* Enable Recv Line Status Interrupt */
|
|
||||||
#define EDSSI 0x08 /* Enable Modem Status Interrupt */
|
|
||||||
|
|
||||||
#define IIR (volatile unsigned char * const)(2+UART_BASE_ADDRESS)
|
|
||||||
/* Interrupt Ident Register (read only) */
|
|
||||||
#define NIP 0x01 /* No Interrupt Pending */
|
|
||||||
#define IID_MASK 0x0e /* Interrupt ID mask */
|
|
||||||
#define FE_MASK 0xc0 /* FIFO's Enabled */
|
|
||||||
|
|
||||||
#define FCR (volatile unsigned char * const)(2+UART_BASE_ADDRESS)
|
|
||||||
/* FIFO Control Register (write only) */
|
|
||||||
#define FIFO_E 0x01 /* FIFO Enable */
|
|
||||||
#define RFR 0x02 /* RCVR FIFO Reset */
|
|
||||||
#define XFR 0x04 /* XMIT FIFO Reset */
|
|
||||||
#define DMAMS 0x08 /* DMA Mode Select */
|
|
||||||
#define RCVRTG_MASK 0xC0 /* RCVR Triger MSBit/LSBit */
|
|
||||||
|
|
||||||
#define LCR (volatile unsigned char * const)(3+UART_BASE_ADDRESS)
|
|
||||||
/* Line Control Register */
|
|
||||||
#define WLS_MASK 0x03 /* Word Legth Select Mask */
|
|
||||||
#define WL_5 0x00 /* 5 bits */
|
|
||||||
#define WL_6 0x01 /* 6 bits */
|
|
||||||
#define WL_7 0x02 /* 7 bits */
|
|
||||||
#define WL_8 0x03 /* 8 bits */
|
|
||||||
#define NSB 0x04 /* Number of Stop Bits (set is 2/1.5) */
|
|
||||||
#define PEN 0x08 /* Parity Enable */
|
|
||||||
#define EPS 0x10 /* Even Parity Select */
|
|
||||||
#define STP 0x20 /* Stick Parity */
|
|
||||||
#define SETBK 0x40 /* Set Break */
|
|
||||||
#define DLAB 0x80 /* Divisor Latch Access Bit */
|
|
||||||
|
|
||||||
#define MCR (volatile unsigned char * const)(4+UART_BASE_ADDRESS)
|
|
||||||
/* Modem Control Register */
|
|
||||||
#define DTR 0x01 /* Data Terminal Ready */
|
|
||||||
#define RTS 0x02 /* Request to Send */
|
|
||||||
#define OUT1 0x04 /* Out 1 */
|
|
||||||
#define OUT2 0x08 /* Out 2 */
|
|
||||||
#define LOOP 0x10 /* Loop */
|
|
||||||
|
|
||||||
#define LSR (volatile unsigned char * const)(5+UART_BASE_ADDRESS)
|
|
||||||
/* Line Status Register */
|
|
||||||
#define DR 0x01 /* Data Ready */
|
|
||||||
#define OE 0x02 /* Overrun error */
|
|
||||||
#define PE 0x04 /* Parity error */
|
|
||||||
#define FE 0x08 /* Framing error */
|
|
||||||
#define BI 0x10 /* Break Interrupt */
|
|
||||||
#define THRE 0x20 /* Transmitter Holding Register */
|
|
||||||
#define TEMT 0x40 /* Transmitter Empty */
|
|
||||||
#define RCVFIE 0x80 /* Recv FIFO Error */
|
|
||||||
|
|
||||||
#define MDSR (volatile unsigned char * const)(6+UART_BASE_ADDRESS)
|
|
||||||
/* Modem Status Register */
|
|
||||||
#define DCTS 0x01 /* Delta Clear to Send */
|
|
||||||
#define DDSR 0x02 /* Delta Data Set Ready */
|
|
||||||
#define TERI 0x04 /* Trailing Edge Ring Indicator */
|
|
||||||
#define DDCD 0x08 /* Delta Data Carrier Detect */
|
|
||||||
#define CTS 0x10 /* Clear to Send */
|
|
||||||
#define DSR 0x20 /* Data Set Ready */
|
|
||||||
#define RI 0x40 /* Ring Indicator */
|
|
||||||
#define DCD 0x80 /* Data Carrier Detect */
|
|
||||||
|
|
||||||
#define SCR (volatile unsigned char * const)(7+UART_BASE_ADDRESS)
|
|
||||||
/* Scratch Register */
|
|
||||||
/* 8-bit register */
|
|
||||||
#endif
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
|
|
||||||
This is a modem driver which should work with limited modifications
|
|
||||||
on any 16550.
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,45 +0,0 @@
|
|||||||
#ifndef _MODEM_H_
|
|
||||||
#define _MODEM_H_
|
|
||||||
|
|
||||||
void modem_reserve_resources(
|
|
||||||
rtems_configuration_table * configuration
|
|
||||||
);
|
|
||||||
|
|
||||||
rtems_device_driver modem_initialize(
|
|
||||||
rtems_device_major_number,
|
|
||||||
rtems_device_minor_number,
|
|
||||||
void *
|
|
||||||
);
|
|
||||||
|
|
||||||
rtems_device_driver modem_open(
|
|
||||||
rtems_device_major_number,
|
|
||||||
rtems_device_minor_number,
|
|
||||||
void *
|
|
||||||
);
|
|
||||||
|
|
||||||
rtems_device_driver modem_close(
|
|
||||||
rtems_device_major_number,
|
|
||||||
rtems_device_minor_number,
|
|
||||||
void *
|
|
||||||
);
|
|
||||||
|
|
||||||
rtems_device_driver modem_read(
|
|
||||||
rtems_device_major_number,
|
|
||||||
rtems_device_minor_number,
|
|
||||||
void *
|
|
||||||
);
|
|
||||||
|
|
||||||
rtems_device_driver modem_write(
|
|
||||||
rtems_device_major_number,
|
|
||||||
rtems_device_minor_number,
|
|
||||||
void *
|
|
||||||
);
|
|
||||||
|
|
||||||
rtems_device_driver modem_control(
|
|
||||||
rtems_device_major_number,
|
|
||||||
rtems_device_minor_number,
|
|
||||||
void *
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
#ifndef __PPP_H__
|
|
||||||
#define __PPP_H__
|
|
||||||
#define NPPP 1
|
|
||||||
#define NBPFILER 0
|
|
||||||
#define VJC
|
|
||||||
/*#define PPP_COMPRESS*/
|
|
||||||
#endif
|
|
||||||
@@ -1,593 +0,0 @@
|
|||||||
/*-
|
|
||||||
* Copyright (c) 1989 The Regents of the University of California.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)slcompress.c 7.7 (Berkeley) 5/7/91
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Routines to compress and uncompess tcp packets (for transmission
|
|
||||||
* over low speed serial lines.
|
|
||||||
*
|
|
||||||
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
|
|
||||||
* - Initial distribution.
|
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/systm.h>
|
|
||||||
#include <sys/mbuf.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/socketvar.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/in_systm.h>
|
|
||||||
#include <netinet/ip.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
|
|
||||||
#include <net/pppcompress.h>
|
|
||||||
|
|
||||||
#ifndef SL_NO_STATS
|
|
||||||
#define INCR(counter) ++comp->counter;
|
|
||||||
#else
|
|
||||||
#define INCR(counter)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n))
|
|
||||||
#define BCOPY(p1, p2, n) bcopy((char *)(p1), (char *)(p2), (int)(n))
|
|
||||||
#ifndef KERNEL
|
|
||||||
#define ovbcopy bcopy
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
vj_compress_init(comp, max_state)
|
|
||||||
struct vjcompress *comp;
|
|
||||||
int max_state;
|
|
||||||
{
|
|
||||||
register u_int i;
|
|
||||||
register struct cstate *tstate = comp->tstate;
|
|
||||||
|
|
||||||
if ((unsigned) max_state > MAX_STATES - 1)
|
|
||||||
max_state = MAX_STATES - 1;
|
|
||||||
bzero((char *)comp, sizeof(*comp));
|
|
||||||
for (i = max_state; i > 0; --i) {
|
|
||||||
tstate[i].cs_id = i;
|
|
||||||
tstate[i].cs_next = &tstate[i - 1];
|
|
||||||
}
|
|
||||||
tstate[0].cs_next = &tstate[max_state];
|
|
||||||
tstate[0].cs_id = 0;
|
|
||||||
comp->last_cs = &tstate[0];
|
|
||||||
comp->last_recv = 255;
|
|
||||||
comp->last_xmit = 255;
|
|
||||||
comp->flags = SLF_TOSS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ENCODE encodes a number that is known to be non-zero. ENCODEZ
|
|
||||||
* checks for zero (since zero has to be encoded in the long, 3 byte
|
|
||||||
* form).
|
|
||||||
*/
|
|
||||||
#define ENCODE(n) { \
|
|
||||||
if ((u_short)(n) >= 256) { \
|
|
||||||
*cp++ = 0; \
|
|
||||||
cp[1] = (n); \
|
|
||||||
cp[0] = (n) >> 8; \
|
|
||||||
cp += 2; \
|
|
||||||
} else { \
|
|
||||||
*cp++ = (n); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#define ENCODEZ(n) { \
|
|
||||||
if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
|
|
||||||
*cp++ = 0; \
|
|
||||||
cp[1] = (n); \
|
|
||||||
cp[0] = (n) >> 8; \
|
|
||||||
cp += 2; \
|
|
||||||
} else { \
|
|
||||||
*cp++ = (n); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DECODEL(f) { \
|
|
||||||
if (*cp == 0) {\
|
|
||||||
(f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \
|
|
||||||
cp += 3; \
|
|
||||||
} else { \
|
|
||||||
(f) = htonl(ntohl(f) + (u_long)*cp++); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DECODES(f) { \
|
|
||||||
if (*cp == 0) {\
|
|
||||||
(f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \
|
|
||||||
cp += 3; \
|
|
||||||
} else { \
|
|
||||||
(f) = htons(ntohs(f) + (u_long)*cp++); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DECODEU(f) { \
|
|
||||||
if (*cp == 0) {\
|
|
||||||
(f) = htons((cp[1] << 8) | cp[2]); \
|
|
||||||
cp += 3; \
|
|
||||||
} else { \
|
|
||||||
(f) = htons((u_long)*cp++); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
u_int
|
|
||||||
vj_compress_tcp(m, ip, comp, compress_cid)
|
|
||||||
struct mbuf *m;
|
|
||||||
register struct ip *ip;
|
|
||||||
struct vjcompress *comp;
|
|
||||||
int compress_cid;
|
|
||||||
{
|
|
||||||
register struct cstate *cs = comp->last_cs->cs_next;
|
|
||||||
register u_int hlen = ip->ip_hl;
|
|
||||||
register struct tcphdr *oth;
|
|
||||||
register struct tcphdr *th;
|
|
||||||
register u_int deltaS, deltaA;
|
|
||||||
register u_int changes = 0;
|
|
||||||
u_char new_seq[16];
|
|
||||||
register u_char *cp = new_seq;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bail if this is an IP fragment or if the TCP packet isn't
|
|
||||||
* `compressible' (i.e., ACK isn't set or some other control bit is
|
|
||||||
* set). (We assume that the caller has already made sure the
|
|
||||||
* packet is IP proto TCP).
|
|
||||||
*/
|
|
||||||
if ((ip->ip_off & htons(0x3fff)) || m->m_len < 40)
|
|
||||||
return (TYPE_IP);
|
|
||||||
|
|
||||||
th = (struct tcphdr *)&((int *)ip)[hlen];
|
|
||||||
if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
|
|
||||||
return (TYPE_IP);
|
|
||||||
/*
|
|
||||||
* Packet is compressible -- we're going to send either a
|
|
||||||
* COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need
|
|
||||||
* to locate (or create) the connection state. Special case the
|
|
||||||
* most recently used connection since it's most likely to be used
|
|
||||||
* again & we don't have to do any reordering if it's used.
|
|
||||||
*/
|
|
||||||
INCR(sls_packets)
|
|
||||||
if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
|
|
||||||
ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
|
|
||||||
*(int *)th != ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl]) {
|
|
||||||
/*
|
|
||||||
* Wasn't the first -- search for it.
|
|
||||||
*
|
|
||||||
* States are kept in a circularly linked list with
|
|
||||||
* last_cs pointing to the end of the list. The
|
|
||||||
* list is kept in lru order by moving a state to the
|
|
||||||
* head of the list whenever it is referenced. Since
|
|
||||||
* the list is short and, empirically, the connection
|
|
||||||
* we want is almost always near the front, we locate
|
|
||||||
* states via linear search. If we don't find a state
|
|
||||||
* for the datagram, the oldest state is (re-)used.
|
|
||||||
*/
|
|
||||||
register struct cstate *lcs;
|
|
||||||
register struct cstate *lastcs = comp->last_cs;
|
|
||||||
|
|
||||||
do {
|
|
||||||
lcs = cs; cs = cs->cs_next;
|
|
||||||
INCR(sls_searches)
|
|
||||||
if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
|
|
||||||
&& ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
|
|
||||||
&& *(int *)th == ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl])
|
|
||||||
goto found;
|
|
||||||
} while (cs != lastcs);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Didn't find it -- re-use oldest cstate. Send an
|
|
||||||
* uncompressed packet that tells the other side what
|
|
||||||
* connection number we're using for this conversation.
|
|
||||||
* Note that since the state list is circular, the oldest
|
|
||||||
* state points to the newest and we only need to set
|
|
||||||
* last_cs to update the lru linkage.
|
|
||||||
*/
|
|
||||||
INCR(sls_misses)
|
|
||||||
comp->last_cs = lcs;
|
|
||||||
hlen += th->th_off;
|
|
||||||
hlen <<= 2;
|
|
||||||
goto uncompressed;
|
|
||||||
|
|
||||||
found:
|
|
||||||
/*
|
|
||||||
* Found it -- move to the front on the connection list.
|
|
||||||
*/
|
|
||||||
if (cs == lastcs)
|
|
||||||
comp->last_cs = lcs;
|
|
||||||
else {
|
|
||||||
lcs->cs_next = cs->cs_next;
|
|
||||||
cs->cs_next = lastcs->cs_next;
|
|
||||||
lastcs->cs_next = cs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure that only what we expect to change changed. The first
|
|
||||||
* line of the `if' checks the IP protocol version, header length &
|
|
||||||
* type of service. The 2nd line checks the "Don't fragment" bit.
|
|
||||||
* The 3rd line checks the time-to-live and protocol (the protocol
|
|
||||||
* check is unnecessary but costless). The 4th line checks the TCP
|
|
||||||
* header length. The 5th line checks IP options, if any. The 6th
|
|
||||||
* line checks TCP options, if any. If any of these things are
|
|
||||||
* different between the previous & current datagram, we send the
|
|
||||||
* current datagram `uncompressed'.
|
|
||||||
*/
|
|
||||||
oth = (struct tcphdr *)&((int *)&cs->cs_ip)[hlen];
|
|
||||||
deltaS = hlen;
|
|
||||||
hlen += th->th_off;
|
|
||||||
hlen <<= 2;
|
|
||||||
|
|
||||||
if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] ||
|
|
||||||
((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] ||
|
|
||||||
((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] ||
|
|
||||||
th->th_off != oth->th_off ||
|
|
||||||
(deltaS > 5 &&
|
|
||||||
BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
|
|
||||||
(th->th_off > 5 &&
|
|
||||||
BCMP(th + 1, oth + 1, (th->th_off - 5) << 2)))
|
|
||||||
goto uncompressed;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Figure out which of the changing fields changed. The
|
|
||||||
* receiver expects changes in the order: urgent, window,
|
|
||||||
* ack, seq (the order minimizes the number of temporaries
|
|
||||||
* needed in this section of code).
|
|
||||||
*/
|
|
||||||
if (th->th_flags & TH_URG) {
|
|
||||||
deltaS = ntohs(th->th_urp);
|
|
||||||
ENCODEZ(deltaS);
|
|
||||||
changes |= NEW_U;
|
|
||||||
} else if (th->th_urp != oth->th_urp)
|
|
||||||
/* argh! URG not set but urp changed -- a sensible
|
|
||||||
* implementation should never do this but RFC793
|
|
||||||
* doesn't prohibit the change so we have to deal
|
|
||||||
* with it. */
|
|
||||||
goto uncompressed;
|
|
||||||
|
|
||||||
if (deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) {
|
|
||||||
ENCODE(deltaS);
|
|
||||||
changes |= NEW_W;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack)) {
|
|
||||||
if (deltaA > 0xffff)
|
|
||||||
goto uncompressed;
|
|
||||||
ENCODE(deltaA);
|
|
||||||
changes |= NEW_A;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq)) {
|
|
||||||
if (deltaS > 0xffff)
|
|
||||||
goto uncompressed;
|
|
||||||
ENCODE(deltaS);
|
|
||||||
changes |= NEW_S;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(changes) {
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
/*
|
|
||||||
* Nothing changed. If this packet contains data and the
|
|
||||||
* last one didn't, this is probably a data packet following
|
|
||||||
* an ack (normal on an interactive connection) and we send
|
|
||||||
* it compressed. Otherwise it's probably a retransmit,
|
|
||||||
* retransmitted ack or window probe. Send it uncompressed
|
|
||||||
* in case the other side missed the compressed version.
|
|
||||||
*/
|
|
||||||
if (ip->ip_len != cs->cs_ip.ip_len &&
|
|
||||||
ntohs(cs->cs_ip.ip_len) == hlen)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* (fall through) */
|
|
||||||
|
|
||||||
case SPECIAL_I:
|
|
||||||
case SPECIAL_D:
|
|
||||||
/*
|
|
||||||
* actual changes match one of our special case encodings --
|
|
||||||
* send packet uncompressed.
|
|
||||||
*/
|
|
||||||
goto uncompressed;
|
|
||||||
|
|
||||||
case NEW_S|NEW_A:
|
|
||||||
if (deltaS == deltaA &&
|
|
||||||
deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
|
|
||||||
/* special case for echoed terminal traffic */
|
|
||||||
changes = SPECIAL_I;
|
|
||||||
cp = new_seq;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NEW_S:
|
|
||||||
if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
|
|
||||||
/* special case for data xfer */
|
|
||||||
changes = SPECIAL_D;
|
|
||||||
cp = new_seq;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);
|
|
||||||
if (deltaS != 1) {
|
|
||||||
ENCODEZ(deltaS);
|
|
||||||
changes |= NEW_I;
|
|
||||||
}
|
|
||||||
if (th->th_flags & TH_PUSH)
|
|
||||||
changes |= TCP_PUSH_BIT;
|
|
||||||
/*
|
|
||||||
* Grab the cksum before we overwrite it below. Then update our
|
|
||||||
* state with this packet's header.
|
|
||||||
*/
|
|
||||||
deltaA = ntohs(th->th_sum);
|
|
||||||
BCOPY(ip, &cs->cs_ip, hlen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We want to use the original packet as our compressed packet.
|
|
||||||
* (cp - new_seq) is the number of bytes we need for compressed
|
|
||||||
* sequence numbers. In addition we need one byte for the change
|
|
||||||
* mask, one for the connection id and two for the tcp checksum.
|
|
||||||
* So, (cp - new_seq) + 4 bytes of header are needed. hlen is how
|
|
||||||
* many bytes of the original packet to toss so subtract the two to
|
|
||||||
* get the new packet size.
|
|
||||||
*/
|
|
||||||
deltaS = cp - new_seq;
|
|
||||||
cp = (u_char *)ip;
|
|
||||||
if (compress_cid == 0 || comp->last_xmit != cs->cs_id) {
|
|
||||||
comp->last_xmit = cs->cs_id;
|
|
||||||
hlen -= deltaS + 4;
|
|
||||||
cp += hlen;
|
|
||||||
*cp++ = changes | NEW_C;
|
|
||||||
*cp++ = cs->cs_id;
|
|
||||||
} else {
|
|
||||||
hlen -= deltaS + 3;
|
|
||||||
cp += hlen;
|
|
||||||
*cp++ = changes;
|
|
||||||
}
|
|
||||||
m->m_len -= hlen;
|
|
||||||
m->m_data += hlen;
|
|
||||||
*cp++ = deltaA >> 8;
|
|
||||||
*cp++ = deltaA;
|
|
||||||
BCOPY(new_seq, cp, deltaS);
|
|
||||||
INCR(sls_compressed)
|
|
||||||
return (TYPE_COMPRESSED_TCP);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update connection state cs & send uncompressed packet ('uncompressed'
|
|
||||||
* means a regular ip/tcp packet but with the 'conversation id' we hope
|
|
||||||
* to use on future compressed packets in the protocol field).
|
|
||||||
*/
|
|
||||||
uncompressed:
|
|
||||||
BCOPY(ip, &cs->cs_ip, hlen);
|
|
||||||
ip->ip_p = cs->cs_id;
|
|
||||||
comp->last_xmit = cs->cs_id;
|
|
||||||
return (TYPE_UNCOMPRESSED_TCP);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
vj_uncompress_tcp(bufp, len, type, comp)
|
|
||||||
u_char **bufp;
|
|
||||||
int len;
|
|
||||||
u_int type;
|
|
||||||
struct vjcompress *comp;
|
|
||||||
{
|
|
||||||
u_char *hdr, *cp;
|
|
||||||
int hlen, vjlen;
|
|
||||||
|
|
||||||
cp = bufp? *bufp: NULL;
|
|
||||||
vjlen = vj_uncompress_tcp_core(cp, len, len, type, comp, &hdr, &hlen);
|
|
||||||
if (vjlen < 0)
|
|
||||||
return (0); /* error */
|
|
||||||
if (vjlen == 0)
|
|
||||||
return (len); /* was uncompressed already */
|
|
||||||
|
|
||||||
cp += vjlen;
|
|
||||||
len -= vjlen;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At this point, cp points to the first byte of data in the
|
|
||||||
* packet. If we're not aligned on a 4-byte boundary, copy the
|
|
||||||
* data down so the ip & tcp headers will be aligned. Then back up
|
|
||||||
* cp by the tcp/ip header length to make room for the reconstructed
|
|
||||||
* header (we assume the packet we were handed has enough space to
|
|
||||||
* prepend 128 bytes of header).
|
|
||||||
*/
|
|
||||||
if ((int)cp & 3) {
|
|
||||||
if (len > 0)
|
|
||||||
(void) ovbcopy(cp, (caddr_t)((int)cp &~ 3), len);
|
|
||||||
cp = (u_char *)((int)cp &~ 3);
|
|
||||||
}
|
|
||||||
cp -= hlen;
|
|
||||||
len += hlen;
|
|
||||||
BCOPY(hdr, cp, hlen);
|
|
||||||
|
|
||||||
*bufp = cp;
|
|
||||||
return (len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Uncompress a packet of total length total_len. The first buflen
|
|
||||||
* bytes are at buf; this must include the entire (compressed or
|
|
||||||
* uncompressed) TCP/IP header. This procedure returns the length
|
|
||||||
* of the VJ header, with a pointer to the uncompressed IP header
|
|
||||||
* in *hdrp and its length in *hlenp.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
vj_uncompress_tcp_core(buf, buflen, total_len, type, comp, hdrp, hlenp)
|
|
||||||
u_char *buf;
|
|
||||||
int buflen, total_len;
|
|
||||||
u_int type;
|
|
||||||
struct vjcompress *comp;
|
|
||||||
u_char **hdrp;
|
|
||||||
u_int *hlenp;
|
|
||||||
{
|
|
||||||
register u_char *cp;
|
|
||||||
register u_int hlen, changes;
|
|
||||||
register struct tcphdr *th;
|
|
||||||
register struct cstate *cs;
|
|
||||||
register struct ip *ip;
|
|
||||||
register u_short *bp;
|
|
||||||
register u_int vjlen;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
|
|
||||||
case TYPE_UNCOMPRESSED_TCP:
|
|
||||||
ip = (struct ip *) buf;
|
|
||||||
if (ip->ip_p >= MAX_STATES)
|
|
||||||
goto bad;
|
|
||||||
cs = &comp->rstate[comp->last_recv = ip->ip_p];
|
|
||||||
comp->flags &=~ SLF_TOSS;
|
|
||||||
ip->ip_p = IPPROTO_TCP;
|
|
||||||
/*
|
|
||||||
* Calculate the size of the TCP/IP header and make sure that
|
|
||||||
* we don't overflow the space we have available for it.
|
|
||||||
*/
|
|
||||||
hlen = ip->ip_hl << 2;
|
|
||||||
if (hlen + sizeof(struct tcphdr) > buflen)
|
|
||||||
goto bad;
|
|
||||||
hlen += ((struct tcphdr *)&((char *)ip)[hlen])->th_off << 2;
|
|
||||||
if (hlen > MAX_HDR || hlen > buflen)
|
|
||||||
goto bad;
|
|
||||||
BCOPY(ip, &cs->cs_ip, hlen);
|
|
||||||
cs->cs_hlen = hlen;
|
|
||||||
INCR(sls_uncompressedin)
|
|
||||||
*hdrp = (u_char *) &cs->cs_ip;
|
|
||||||
*hlenp = hlen;
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
default:
|
|
||||||
goto bad;
|
|
||||||
|
|
||||||
case TYPE_COMPRESSED_TCP:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* We've got a compressed packet. */
|
|
||||||
INCR(sls_compressedin)
|
|
||||||
cp = buf;
|
|
||||||
changes = *cp++;
|
|
||||||
if (changes & NEW_C) {
|
|
||||||
/* Make sure the state index is in range, then grab the state.
|
|
||||||
* If we have a good state index, clear the 'discard' flag. */
|
|
||||||
if (*cp >= MAX_STATES)
|
|
||||||
goto bad;
|
|
||||||
|
|
||||||
comp->flags &=~ SLF_TOSS;
|
|
||||||
comp->last_recv = *cp++;
|
|
||||||
} else {
|
|
||||||
/* this packet has an implicit state index. If we've
|
|
||||||
* had a line error since the last time we got an
|
|
||||||
* explicit state index, we have to toss the packet. */
|
|
||||||
if (comp->flags & SLF_TOSS) {
|
|
||||||
INCR(sls_tossed)
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cs = &comp->rstate[comp->last_recv];
|
|
||||||
hlen = cs->cs_ip.ip_hl << 2;
|
|
||||||
th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
|
|
||||||
th->th_sum = htons((*cp << 8) | cp[1]);
|
|
||||||
cp += 2;
|
|
||||||
if (changes & TCP_PUSH_BIT)
|
|
||||||
th->th_flags |= TH_PUSH;
|
|
||||||
else
|
|
||||||
th->th_flags &=~ TH_PUSH;
|
|
||||||
|
|
||||||
switch (changes & SPECIALS_MASK) {
|
|
||||||
case SPECIAL_I:
|
|
||||||
{
|
|
||||||
register u_int i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
|
|
||||||
th->th_ack = htonl(ntohl(th->th_ack) + i);
|
|
||||||
th->th_seq = htonl(ntohl(th->th_seq) + i);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SPECIAL_D:
|
|
||||||
th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len)
|
|
||||||
- cs->cs_hlen);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (changes & NEW_U) {
|
|
||||||
th->th_flags |= TH_URG;
|
|
||||||
DECODEU(th->th_urp)
|
|
||||||
} else
|
|
||||||
th->th_flags &=~ TH_URG;
|
|
||||||
if (changes & NEW_W)
|
|
||||||
DECODES(th->th_win)
|
|
||||||
if (changes & NEW_A)
|
|
||||||
DECODEL(th->th_ack)
|
|
||||||
if (changes & NEW_S)
|
|
||||||
DECODEL(th->th_seq)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (changes & NEW_I) {
|
|
||||||
DECODES(cs->cs_ip.ip_id)
|
|
||||||
} else
|
|
||||||
cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At this point, cp points to the first byte of data in the
|
|
||||||
* packet. Fill in the IP total length and update the IP
|
|
||||||
* header checksum.
|
|
||||||
*/
|
|
||||||
vjlen = cp - buf;
|
|
||||||
buflen -= vjlen;
|
|
||||||
if (buflen < 0)
|
|
||||||
/* we must have dropped some characters (crc should detect
|
|
||||||
* this but the old slip framing won't) */
|
|
||||||
goto bad;
|
|
||||||
|
|
||||||
total_len += cs->cs_hlen - vjlen;
|
|
||||||
cs->cs_ip.ip_len = htons(total_len);
|
|
||||||
|
|
||||||
/* recompute the ip header checksum */
|
|
||||||
bp = (u_short *) &cs->cs_ip;
|
|
||||||
cs->cs_ip.ip_sum = 0;
|
|
||||||
for (changes = 0; hlen > 0; hlen -= 2)
|
|
||||||
changes += *bp++;
|
|
||||||
changes = (changes & 0xffff) + (changes >> 16);
|
|
||||||
changes = (changes & 0xffff) + (changes >> 16);
|
|
||||||
cs->cs_ip.ip_sum = ~ changes;
|
|
||||||
|
|
||||||
*hdrp = (u_char *) &cs->cs_ip;
|
|
||||||
*hlenp = cs->cs_hlen;
|
|
||||||
return vjlen;
|
|
||||||
|
|
||||||
bad:
|
|
||||||
comp->flags |= SLF_TOSS;
|
|
||||||
INCR(sls_errorin)
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
@@ -589,6 +589,8 @@ extern void (*auth_linkdown_hook) __P((void));
|
|||||||
#define DEBUGCHAP 1
|
#define DEBUGCHAP 1
|
||||||
#endif
|
#endif
|
||||||
#define DEBUGMAIN 1
|
#define DEBUGMAIN 1
|
||||||
|
#define DEBUGUPAP 1
|
||||||
|
#define DEBUGCHAP 1
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUGMAIN
|
#ifdef DEBUGMAIN
|
||||||
|
|||||||
@@ -107,8 +107,6 @@ int phase; /* where the link is at */
|
|||||||
int kill_link;
|
int kill_link;
|
||||||
int open_ccp_flag;
|
int open_ccp_flag;
|
||||||
|
|
||||||
static int waiting;
|
|
||||||
|
|
||||||
char **script_env; /* Env. variable values for scripts */
|
char **script_env; /* Env. variable values for scripts */
|
||||||
int s_env_nalloc; /* # words avail at script_env */
|
int s_env_nalloc; /* # words avail at script_env */
|
||||||
|
|
||||||
@@ -234,8 +232,6 @@ pppdmain(argc, argv)
|
|||||||
setlogmask(LOG_UPTO(LOG_DEBUG));
|
setlogmask(LOG_UPTO(LOG_DEBUG));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
waiting = 0;
|
|
||||||
|
|
||||||
do_callback = 0;
|
do_callback = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
@@ -400,12 +396,10 @@ pppdmain(argc, argv)
|
|||||||
status = EXIT_NEGOTIATION_FAILED;
|
status = EXIT_NEGOTIATION_FAILED;
|
||||||
new_phase(PHASE_ESTABLISH);
|
new_phase(PHASE_ESTABLISH);
|
||||||
while (phase != PHASE_DEAD) {
|
while (phase != PHASE_DEAD) {
|
||||||
waiting = 1;
|
|
||||||
wait_input(timeleft(&timo));
|
wait_input(timeleft(&timo));
|
||||||
waiting = 0;
|
|
||||||
|
|
||||||
calltimeout();
|
calltimeout();
|
||||||
get_input();
|
get_input();
|
||||||
|
|
||||||
if (kill_link) {
|
if (kill_link) {
|
||||||
lcp_close(0, "User request");
|
lcp_close(0, "User request");
|
||||||
kill_link = 0;
|
kill_link = 0;
|
||||||
@@ -469,9 +463,7 @@ pppdmain(argc, argv)
|
|||||||
new_phase(PHASE_HOLDOFF);
|
new_phase(PHASE_HOLDOFF);
|
||||||
TIMEOUT(holdoff_end, NULL, t);
|
TIMEOUT(holdoff_end, NULL, t);
|
||||||
do {
|
do {
|
||||||
waiting = 1;
|
|
||||||
wait_input(timeleft(&timo));
|
wait_input(timeleft(&timo));
|
||||||
waiting = 0;
|
|
||||||
|
|
||||||
calltimeout();
|
calltimeout();
|
||||||
if (kill_link) {
|
if (kill_link) {
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
2001-10-12 Mike Siers <mikes@poliac.com>
|
||||||
|
|
||||||
|
* Update to stable working state. Congratulations Mike! :)
|
||||||
|
* modem_example: Directory removed.
|
||||||
|
* modem_example/16550.h, modem_example/README, modem_example/modem.c,
|
||||||
|
modem_example/modem.h, modem_example/ppp.c, modem_example/ppp.h,
|
||||||
|
modem_example/pppcompress.c: Files removed.
|
||||||
|
* pppd/example/pppd.options: New file.
|
||||||
|
* pppd/README, pppd/STATUS, pppd/cbcp.c, pppd/cbcp.h, pppd/chat.c,
|
||||||
|
pppd/pppd.h, pppd/rtemsmain.c: Updated.
|
||||||
|
|
||||||
2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||||
|
|
||||||
* .cvsignore: Add autom4te.cache for autoconf > 2.52.
|
* .cvsignore: Add autom4te.cache for autoconf > 2.52.
|
||||||
|
|||||||
@@ -16,5 +16,9 @@ provided the modem driver as well.
|
|||||||
|
|
||||||
The port was updated to 2.3.11 by Mike Siers <mikes@poliac.com>
|
The port was updated to 2.3.11 by Mike Siers <mikes@poliac.com>
|
||||||
who added an example test.
|
who added an example test.
|
||||||
|
|
||||||
|
Updated the chat program to return the correct errors and support
|
||||||
|
the ABORT commands. Removed some dead code and did a lot of
|
||||||
|
testing on a new Coldfire BSP. Version seems to be very stable.
|
||||||
=================================================================
|
=================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -2,39 +2,28 @@
|
|||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
|
|
||||||
|
The pppd application seems to very stable. It has been tested using
|
||||||
|
the example application with the i386/pc586 and m68k/sbc5206e BSPs.
|
||||||
|
The tests were executed using a null modem serial cable to connect
|
||||||
|
with a UNIX box running either the ppp or pppd application and with
|
||||||
|
an external modem to dial up a local ISP.
|
||||||
|
|
||||||
Notes from Mike Siers <mikes@poliac.com>
|
If you have problems getting your target to make consistent connections
|
||||||
========================================
|
with an ISP, the problem is most likely with the ppp options. First
|
||||||
|
try using the "novj" and "noaccomp" options. If you have questions
|
||||||
|
about what other option values are available for the rtems_pppd_set_option
|
||||||
|
function, please look at the pppd.8 man page file or the the source code.
|
||||||
|
The majority of options that are documented in man page should work
|
||||||
|
with this function call.
|
||||||
|
|
||||||
I know that several users have tried out this version of
|
The pppd application requires the BSP termios driver support task
|
||||||
pppd under RTEMS. It has been successfully used as both
|
driven I/O. Below is a list of known issues that need to be resolved:
|
||||||
a client and server. Below are the only issues that I
|
|
||||||
know of.
|
|
||||||
|
|
||||||
1) Large packet ping causes RTEMS box to lock up
|
- pppd locks up when it receives large packet pings (> 1500 bytes)
|
||||||
If you ping the RTEMS box over the ppp link with a packet
|
- pppd occasionaly locks up with mbuf allocation error
|
||||||
size greater than 1500, the RTEMS box locks up. I think
|
(problem is rare and may be BSP related)
|
||||||
the problem is in the pppd ethernet driver.
|
|
||||||
|
|
||||||
2) Upgrade the libnetworking/modem files
|
If you find any other problems or fix some problems, please post your
|
||||||
This upgrade did not modify the ppp ethernet driver files
|
changes to the RTEMS mailing list.
|
||||||
in the libnetworking/modem directory. Would like to
|
|
||||||
upgrade these files. Hopefully, it will fix the large
|
|
||||||
packet ping problem.
|
|
||||||
|
|
||||||
3) The files cbcp.c and cbcp.h provide a callback feature
|
|
||||||
that I have not tried to compile or use. The files in
|
|
||||||
this directory are identical to the 2.3.11 versions.
|
|
||||||
for completeness.
|
|
||||||
|
|
||||||
|
|
||||||
JOEL: Are the modifications to the original pppd such that the
|
|
||||||
real maintainers will accept them?
|
|
||||||
|
|
||||||
No. The pppd 2.3.11 branch is an old branch. The current
|
|
||||||
version is 2.4.x and it contains alot of extra items that
|
|
||||||
just did not make sense to have in an embedded environment.
|
|
||||||
I could make the RTEMS changes compatible with the standard
|
|
||||||
2.3.11 release by using compilation flags. I have not
|
|
||||||
contacted the maintainers to see if they are interested.
|
|
||||||
|
|
||||||
|
Good Luck
|
||||||
|
|||||||
@@ -0,0 +1,456 @@
|
|||||||
|
/*
|
||||||
|
* cbcp - Call Back Configuration Protocol.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1995 Pedro Roque Marques
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 Pedro Roque Marques. The name of the author 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RCSID "$Id$"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "pppd.h"
|
||||||
|
#include "cbcp.h"
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "lcp.h"
|
||||||
|
|
||||||
|
static const char rcsid[] = RCSID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Options.
|
||||||
|
*/
|
||||||
|
static int setcbcp __P((char **));
|
||||||
|
|
||||||
|
static option_t cbcp_option_list[] = {
|
||||||
|
{ "callback", o_special, setcbcp,
|
||||||
|
"Ask for callback" },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protocol entry points.
|
||||||
|
*/
|
||||||
|
static void cbcp_init __P((int unit));
|
||||||
|
static void cbcp_open __P((int unit));
|
||||||
|
static void cbcp_lowerup __P((int unit));
|
||||||
|
static void cbcp_input __P((int unit, u_char *pkt, int len));
|
||||||
|
static void cbcp_protrej __P((int unit));
|
||||||
|
static int cbcp_printpkt __P((u_char *pkt, int len,
|
||||||
|
void (*printer) __P((void *, char *, ...)),
|
||||||
|
void *arg));
|
||||||
|
|
||||||
|
struct protent cbcp_protent = {
|
||||||
|
PPP_CBCP,
|
||||||
|
cbcp_init,
|
||||||
|
cbcp_input,
|
||||||
|
cbcp_protrej,
|
||||||
|
cbcp_lowerup,
|
||||||
|
NULL,
|
||||||
|
cbcp_open,
|
||||||
|
NULL,
|
||||||
|
cbcp_printpkt,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
"CBCP",
|
||||||
|
NULL,
|
||||||
|
cbcp_option_list,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
cbcp_state cbcp[NUM_PPP];
|
||||||
|
|
||||||
|
/* internal prototypes */
|
||||||
|
|
||||||
|
static void cbcp_recvreq __P((cbcp_state *us, char *pckt, int len));
|
||||||
|
static void cbcp_resp __P((cbcp_state *us));
|
||||||
|
static void cbcp_up __P((cbcp_state *us));
|
||||||
|
static void cbcp_recvack __P((cbcp_state *us, char *pckt, int len));
|
||||||
|
static void cbcp_send __P((cbcp_state *us, u_char code, u_char *buf, int len));
|
||||||
|
|
||||||
|
/* option processing */
|
||||||
|
static int
|
||||||
|
setcbcp(argv)
|
||||||
|
char **argv;
|
||||||
|
{
|
||||||
|
lcp_wantoptions[0].neg_cbcp = 1;
|
||||||
|
cbcp_protent.enabled_flag = 1;
|
||||||
|
cbcp[0].us_number = strdup(*argv);
|
||||||
|
if (cbcp[0].us_number == 0)
|
||||||
|
novm("callback number");
|
||||||
|
cbcp[0].us_type |= (1 << CB_CONF_USER);
|
||||||
|
cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init state */
|
||||||
|
static void
|
||||||
|
cbcp_init(iface)
|
||||||
|
int iface;
|
||||||
|
{
|
||||||
|
cbcp_state *us;
|
||||||
|
|
||||||
|
us = &cbcp[iface];
|
||||||
|
memset(us, 0, sizeof(cbcp_state));
|
||||||
|
us->us_unit = iface;
|
||||||
|
us->us_type |= (1 << CB_CONF_NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lower layer is up */
|
||||||
|
static void
|
||||||
|
cbcp_lowerup(iface)
|
||||||
|
int iface;
|
||||||
|
{
|
||||||
|
cbcp_state *us = &cbcp[iface];
|
||||||
|
|
||||||
|
dbglog("cbcp_lowerup");
|
||||||
|
dbglog("want: %d", us->us_type);
|
||||||
|
|
||||||
|
if (us->us_type == CB_CONF_USER)
|
||||||
|
dbglog("phone no: %s", us->us_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cbcp_open(unit)
|
||||||
|
int unit;
|
||||||
|
{
|
||||||
|
dbglog("cbcp_open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process an incomming packet */
|
||||||
|
static void
|
||||||
|
cbcp_input(unit, inpacket, pktlen)
|
||||||
|
int unit;
|
||||||
|
u_char *inpacket;
|
||||||
|
int pktlen;
|
||||||
|
{
|
||||||
|
u_char *inp;
|
||||||
|
u_char code, id;
|
||||||
|
u_short len;
|
||||||
|
|
||||||
|
cbcp_state *us = &cbcp[unit];
|
||||||
|
|
||||||
|
inp = inpacket;
|
||||||
|
|
||||||
|
if (pktlen < CBCP_MINLEN) {
|
||||||
|
error("CBCP packet is too small");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GETCHAR(code, inp);
|
||||||
|
GETCHAR(id, inp);
|
||||||
|
GETSHORT(len, inp);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (len > pktlen) {
|
||||||
|
error("CBCP packet: invalid length");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
len -= CBCP_MINLEN;
|
||||||
|
|
||||||
|
switch(code) {
|
||||||
|
case CBCP_REQ:
|
||||||
|
us->us_id = id;
|
||||||
|
cbcp_recvreq(us, inp, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CBCP_RESP:
|
||||||
|
dbglog("CBCP_RESP received");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CBCP_ACK:
|
||||||
|
if (id != us->us_id)
|
||||||
|
dbglog("id doesn't match: expected %d recv %d",
|
||||||
|
us->us_id, id);
|
||||||
|
|
||||||
|
cbcp_recvack(us, inp, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* protocol was rejected by foe */
|
||||||
|
void cbcp_protrej(int iface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
char *cbcp_codenames[] = {
|
||||||
|
"Request", "Response", "Ack"
|
||||||
|
};
|
||||||
|
|
||||||
|
char *cbcp_optionnames[] = {
|
||||||
|
"NoCallback",
|
||||||
|
"UserDefined",
|
||||||
|
"AdminDefined",
|
||||||
|
"List"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* pretty print a packet */
|
||||||
|
static int
|
||||||
|
cbcp_printpkt(p, plen, printer, arg)
|
||||||
|
u_char *p;
|
||||||
|
int plen;
|
||||||
|
void (*printer) __P((void *, char *, ...));
|
||||||
|
void *arg;
|
||||||
|
{
|
||||||
|
int code, opt, id, len, olen, delay;
|
||||||
|
u_char *pstart;
|
||||||
|
|
||||||
|
if (plen < HEADERLEN)
|
||||||
|
return 0;
|
||||||
|
pstart = p;
|
||||||
|
GETCHAR(code, p);
|
||||||
|
GETCHAR(id, p);
|
||||||
|
GETSHORT(len, p);
|
||||||
|
if (len < HEADERLEN || len > plen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
|
||||||
|
printer(arg, " %s", cbcp_codenames[code-1]);
|
||||||
|
else
|
||||||
|
printer(arg, " code=0x%x", code);
|
||||||
|
|
||||||
|
printer(arg, " id=0x%x", id);
|
||||||
|
len -= HEADERLEN;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case CBCP_REQ:
|
||||||
|
case CBCP_RESP:
|
||||||
|
case CBCP_ACK:
|
||||||
|
while(len >= 2) {
|
||||||
|
GETCHAR(opt, p);
|
||||||
|
GETCHAR(olen, p);
|
||||||
|
|
||||||
|
if (olen < 2 || olen > len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printer(arg, " <");
|
||||||
|
len -= olen;
|
||||||
|
|
||||||
|
if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
|
||||||
|
printer(arg, " %s", cbcp_optionnames[opt-1]);
|
||||||
|
else
|
||||||
|
printer(arg, " option=0x%x", opt);
|
||||||
|
|
||||||
|
if (olen > 2) {
|
||||||
|
GETCHAR(delay, p);
|
||||||
|
printer(arg, " delay = %d", delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (olen > 3) {
|
||||||
|
int addrt;
|
||||||
|
char str[256];
|
||||||
|
|
||||||
|
GETCHAR(addrt, p);
|
||||||
|
memcpy(str, p, olen - 4);
|
||||||
|
str[olen - 4] = 0;
|
||||||
|
printer(arg, " number = %s", str);
|
||||||
|
}
|
||||||
|
printer(arg, ">");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; len > 0; --len) {
|
||||||
|
GETCHAR(code, p);
|
||||||
|
printer(arg, " %.2x", code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - pstart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* received CBCP request */
|
||||||
|
static void
|
||||||
|
cbcp_recvreq(us, pckt, pcktlen)
|
||||||
|
cbcp_state *us;
|
||||||
|
char *pckt;
|
||||||
|
int pcktlen;
|
||||||
|
{
|
||||||
|
u_char type, opt_len, delay, addr_type;
|
||||||
|
char address[256];
|
||||||
|
int len = pcktlen;
|
||||||
|
|
||||||
|
address[0] = 0;
|
||||||
|
|
||||||
|
while (len) {
|
||||||
|
dbglog("length: %d", len);
|
||||||
|
|
||||||
|
GETCHAR(type, pckt);
|
||||||
|
GETCHAR(opt_len, pckt);
|
||||||
|
|
||||||
|
if (opt_len > 2)
|
||||||
|
GETCHAR(delay, pckt);
|
||||||
|
|
||||||
|
us->us_allowed |= (1 << type);
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CB_CONF_NO:
|
||||||
|
dbglog("no callback allowed");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_CONF_USER:
|
||||||
|
dbglog("user callback allowed");
|
||||||
|
if (opt_len > 4) {
|
||||||
|
GETCHAR(addr_type, pckt);
|
||||||
|
memcpy(address, pckt, opt_len - 4);
|
||||||
|
address[opt_len - 4] = 0;
|
||||||
|
if (address[0])
|
||||||
|
dbglog("address: %s", address);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_CONF_ADMIN:
|
||||||
|
dbglog("user admin defined allowed");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CB_CONF_LIST:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len -= opt_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbcp_resp(us);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cbcp_resp(us)
|
||||||
|
cbcp_state *us;
|
||||||
|
{
|
||||||
|
u_char cb_type;
|
||||||
|
u_char buf[256];
|
||||||
|
u_char *bufp = buf;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
cb_type = us->us_allowed & us->us_type;
|
||||||
|
dbglog("cbcp_resp cb_type=%d", cb_type);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (!cb_type)
|
||||||
|
lcp_down(us->us_unit);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (cb_type & ( 1 << CB_CONF_USER ) ) {
|
||||||
|
dbglog("cbcp_resp CONF_USER");
|
||||||
|
PUTCHAR(CB_CONF_USER, bufp);
|
||||||
|
len = 3 + 1 + strlen(us->us_number) + 1;
|
||||||
|
PUTCHAR(len , bufp);
|
||||||
|
PUTCHAR(5, bufp); /* delay */
|
||||||
|
PUTCHAR(1, bufp);
|
||||||
|
BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
|
||||||
|
cbcp_send(us, CBCP_RESP, buf, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
|
||||||
|
dbglog("cbcp_resp CONF_ADMIN");
|
||||||
|
PUTCHAR(CB_CONF_ADMIN, bufp);
|
||||||
|
len = 3;
|
||||||
|
PUTCHAR(len, bufp);
|
||||||
|
PUTCHAR(5, bufp); /* delay */
|
||||||
|
cbcp_send(us, CBCP_RESP, buf, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cb_type & ( 1 << CB_CONF_NO ) ) {
|
||||||
|
dbglog("cbcp_resp CONF_NO");
|
||||||
|
PUTCHAR(CB_CONF_NO, bufp);
|
||||||
|
len = 3;
|
||||||
|
PUTCHAR(len , bufp);
|
||||||
|
PUTCHAR(0, bufp);
|
||||||
|
cbcp_send(us, CBCP_RESP, buf, len);
|
||||||
|
start_networks();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cbcp_send(us, code, buf, len)
|
||||||
|
cbcp_state *us;
|
||||||
|
u_char code;
|
||||||
|
u_char *buf;
|
||||||
|
int len;
|
||||||
|
{
|
||||||
|
u_char *outp;
|
||||||
|
int outlen;
|
||||||
|
|
||||||
|
outp = outpacket_buf;
|
||||||
|
|
||||||
|
outlen = 4 + len;
|
||||||
|
|
||||||
|
MAKEHEADER(outp, PPP_CBCP);
|
||||||
|
|
||||||
|
PUTCHAR(code, outp);
|
||||||
|
PUTCHAR(us->us_id, outp);
|
||||||
|
PUTSHORT(outlen, outp);
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
BCOPY(buf, outp, len);
|
||||||
|
|
||||||
|
output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cbcp_recvack(us, pckt, len)
|
||||||
|
cbcp_state *us;
|
||||||
|
char *pckt;
|
||||||
|
int len;
|
||||||
|
{
|
||||||
|
u_char type, delay, addr_type;
|
||||||
|
int opt_len;
|
||||||
|
char address[256];
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
GETCHAR(type, pckt);
|
||||||
|
GETCHAR(opt_len, pckt);
|
||||||
|
|
||||||
|
if (opt_len > 2)
|
||||||
|
GETCHAR(delay, pckt);
|
||||||
|
|
||||||
|
if (opt_len > 4) {
|
||||||
|
GETCHAR(addr_type, pckt);
|
||||||
|
memcpy(address, pckt, opt_len - 4);
|
||||||
|
address[opt_len - 4] = 0;
|
||||||
|
if (address[0])
|
||||||
|
dbglog("peer will call: %s", address);
|
||||||
|
}
|
||||||
|
if (type == CB_CONF_NO)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbcp_up(us);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ok peer will do callback */
|
||||||
|
static void
|
||||||
|
cbcp_up(us)
|
||||||
|
cbcp_state *us;
|
||||||
|
{
|
||||||
|
persist = 0;
|
||||||
|
lcp_close(0, "Call me back, please");
|
||||||
|
status = EXIT_CALLBACK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef CBCP_H
|
||||||
|
#define CBCP_H
|
||||||
|
|
||||||
|
typedef struct cbcp_state {
|
||||||
|
int us_unit; /* Interface unit number */
|
||||||
|
u_char us_id; /* Current id */
|
||||||
|
u_char us_allowed;
|
||||||
|
int us_type;
|
||||||
|
char *us_number; /* Telefone Number */
|
||||||
|
} cbcp_state;
|
||||||
|
|
||||||
|
extern cbcp_state cbcp[];
|
||||||
|
|
||||||
|
extern struct protent cbcp_protent;
|
||||||
|
|
||||||
|
#define CBCP_MINLEN 4
|
||||||
|
|
||||||
|
#define CBCP_REQ 1
|
||||||
|
#define CBCP_RESP 2
|
||||||
|
#define CBCP_ACK 3
|
||||||
|
|
||||||
|
#define CB_CONF_NO 1
|
||||||
|
#define CB_CONF_USER 2
|
||||||
|
#define CB_CONF_ADMIN 3
|
||||||
|
#define CB_CONF_LIST 4
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -14,6 +14,12 @@
|
|||||||
* This software is in the public domain.
|
* This software is in the public domain.
|
||||||
*
|
*
|
||||||
* -----------------
|
* -----------------
|
||||||
|
* 22-May-99 added environment substitutuion, enabled with -E switch.
|
||||||
|
* Andreas Arens <andras@cityweb.de>.
|
||||||
|
*
|
||||||
|
* 12-May-99 added a feature to read data to be sent from a file,
|
||||||
|
* if the send string starts with @. Idea from gpk <gpk@onramp.net>.
|
||||||
|
*
|
||||||
* added -T and -U option and \T and \U substitution to pass a phone
|
* added -T and -U option and \T and \U substitution to pass a phone
|
||||||
* number into chat script. Two are needed for some ISDN TA applications.
|
* number into chat script. Two are needed for some ISDN TA applications.
|
||||||
* Keith Dart <kdart@cisco.com>
|
* Keith Dart <kdart@cisco.com>
|
||||||
@@ -74,18 +80,12 @@
|
|||||||
* Columbus, OH 43221
|
* Columbus, OH 43221
|
||||||
* (614)451-1883
|
* (614)451-1883
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
/* static char rcsid[] = ""; */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -93,13 +93,13 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include "pppd.h"
|
||||||
|
|
||||||
#undef TERMIOS
|
#undef TERMIOS
|
||||||
#define TERMIOS
|
#define TERMIOS
|
||||||
|
|
||||||
|
|
||||||
#include <termios.h>
|
|
||||||
|
|
||||||
#define STR_LEN 1024
|
#define STR_LEN 1024
|
||||||
char temp2[STR_LEN];
|
char temp2[STR_LEN];
|
||||||
|
|
||||||
@@ -142,39 +142,34 @@ static int _O = 0; /* Internal state */
|
|||||||
|
|
||||||
char *program_name;
|
char *program_name;
|
||||||
|
|
||||||
#define MAX_ABORTS 5
|
#define MAX_ABORTS 16
|
||||||
#define MAX_REPORTS 5
|
#define MAX_REPORTS 16
|
||||||
#define DEFAULT_CHAT_TIMEOUT 45
|
#define DEFAULT_CHAT_TIMEOUT 45
|
||||||
#define fcntl(a, b,c ) 0
|
#define MAX_TIMEOUTS 10
|
||||||
#define MAX_TIMEOUTS 10
|
|
||||||
|
|
||||||
int echo = 0;
|
int echo = 0;
|
||||||
int verbose = 0;
|
int quiet = 0;
|
||||||
int to_log = 1;
|
int report = 0;
|
||||||
int to_stderr = 0;
|
int use_env = 0;
|
||||||
int Verbose = 0;
|
int exit_code = 0;
|
||||||
int quiet = 0;
|
char *report_file = (char *) 0;
|
||||||
int report = 0;
|
char *chat_file = (char *) 0;
|
||||||
int exit_code = 0;
|
char *phone_num = (char *) 0;
|
||||||
char *report_file = (char *) 0;
|
char *phone_num2 = (char *) 0;
|
||||||
char *chat_file = (char *) 0;
|
static int timeout = DEFAULT_CHAT_TIMEOUT;
|
||||||
char *phone_num = (char *) 0;
|
|
||||||
char *phone_num2 = (char *) 0;
|
|
||||||
int chat_timeout = DEFAULT_CHAT_TIMEOUT;
|
|
||||||
static int timeout = DEFAULT_CHAT_TIMEOUT;
|
|
||||||
int have_tty_parameters = 0;
|
|
||||||
|
|
||||||
#ifdef TERMIOS
|
#ifdef TERMIOS
|
||||||
#define term_parms struct termios
|
#define term_parms struct termios
|
||||||
#define get_term_param(param) tcgetattr(ttyfd, param)
|
#define get_term_param(param) tcgetattr(0, param)
|
||||||
#define set_term_param(param) tcsetattr(ttyfd, TCSANOW, param)
|
#define set_term_param(param) tcsetattr(0, TCSANOW, param)
|
||||||
struct termios saved_tty_parameters;
|
struct termios saved_tty_parameters;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *abort_string[MAX_ABORTS]={"BUSY","NO DIALTONE","NO CARRIER","NO ASWER","RINGING\r\n\r\nRINGING"};
|
char *fail_reason = (char *)0;
|
||||||
char *fail_reason = (char *)0,
|
char fail_buffer[50];
|
||||||
fail_buffer[50];
|
char *abort_string[MAX_ABORTS]={"BUSY","NO DIALTONE","NO CARRIER","NO ANSWER","RING\r\nRING"};
|
||||||
int n_aborts = MAX_ABORTS, abort_next = 0, timeout_next = 0, echo_next = 0;
|
int n_aborts = 5;
|
||||||
|
int abort_next = 0, timeout_next = 0, echo_next = 0;
|
||||||
int clear_abort_next = 0;
|
int clear_abort_next = 0;
|
||||||
|
|
||||||
char *report_string[MAX_REPORTS] ;
|
char *report_string[MAX_REPORTS] ;
|
||||||
@@ -186,19 +181,7 @@ int say_next = 0, hup_next = 0;
|
|||||||
|
|
||||||
void *dup_mem __P((void *b, size_t c));
|
void *dup_mem __P((void *b, size_t c));
|
||||||
void *copy_of __P((char *s));
|
void *copy_of __P((char *s));
|
||||||
/*
|
|
||||||
SIGTYPE sigalrm __P((int signo));
|
|
||||||
SIGTYPE sigint __P((int signo));
|
|
||||||
SIGTYPE sigterm __P((int signo));
|
|
||||||
SIGTYPE sighup __P((int signo));
|
|
||||||
*/
|
|
||||||
void unalarm __P((void));
|
|
||||||
void init __P((void));
|
|
||||||
void set_tty_parameters __P((void));
|
|
||||||
void echo_stderr __P((int));
|
|
||||||
void break_sequence __P((void));
|
void break_sequence __P((void));
|
||||||
void terminate __P((int status));
|
|
||||||
void do_file __P((char *chat_file));
|
|
||||||
int get_string __P((register char *string));
|
int get_string __P((register char *string));
|
||||||
int put_string __P((register char *s));
|
int put_string __P((register char *s));
|
||||||
int write_char __P((int c));
|
int write_char __P((int c));
|
||||||
@@ -208,19 +191,9 @@ void chat_send __P((register char *s));
|
|||||||
char *character __P((int c));
|
char *character __P((int c));
|
||||||
void chat_expect __P((register char *s));
|
void chat_expect __P((register char *s));
|
||||||
char *clean __P((register char *s, int sending));
|
char *clean __P((register char *s, int sending));
|
||||||
void break_sequence __P((void));
|
|
||||||
void terminate __P((int status));
|
|
||||||
void pack_array __P((char **array, int end));
|
|
||||||
char *expect_strtok __P((char *, char *));
|
char *expect_strtok __P((char *, char *));
|
||||||
int vfmtmsg __P((char *, int, const char *, va_list)); /* vsprintf++ */
|
int chatmain __P((char *));
|
||||||
|
|
||||||
#if 0
|
|
||||||
int usleep( long usec ); /* returns 0 if ok, else -1 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int input_fd,output_fd;
|
|
||||||
|
|
||||||
int main __P((int, char *[]));
|
|
||||||
|
|
||||||
void *dup_mem(b, c)
|
void *dup_mem(b, c)
|
||||||
void *b;
|
void *b;
|
||||||
@@ -228,29 +201,22 @@ size_t c;
|
|||||||
{
|
{
|
||||||
void *ans = malloc (c);
|
void *ans = malloc (c);
|
||||||
if (!ans)
|
if (!ans)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memcpy (ans, b, c);
|
memcpy(ans, b, c);
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *copy_of (s)
|
void *copy_of (s)
|
||||||
char *s;
|
char *s;
|
||||||
{
|
{
|
||||||
return dup_mem (s, strlen (s) + 1);
|
return dup_mem(s, strlen (s) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* chat [ -v ] [-T number] [-U number] [ -t timeout ] [ -f chat-file ] \
|
|
||||||
* [ -r report-file ] \
|
|
||||||
* [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]]
|
|
||||||
*
|
|
||||||
* Perform a UUCP-dialer-like chat script on stdin and stdout.
|
|
||||||
*/
|
|
||||||
char *getnextcommand(char **string)
|
char *getnextcommand(char **string)
|
||||||
{
|
{
|
||||||
char *buf=*string,*res;
|
char *buf=*string,*res;
|
||||||
res=strchr(buf,'@');
|
res=strchr(buf,'|');
|
||||||
if (res==NULL)
|
if (res==NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
*res='\0';
|
*res='\0';
|
||||||
@@ -258,8 +224,6 @@ char *getnextcommand(char **string)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern int ttyfd;
|
|
||||||
int chatmain(argv)
|
int chatmain(argv)
|
||||||
char *argv;
|
char *argv;
|
||||||
{
|
{
|
||||||
@@ -268,78 +232,40 @@ char *argv;
|
|||||||
/* initialize exit code */
|
/* initialize exit code */
|
||||||
exit_code = 0;
|
exit_code = 0;
|
||||||
|
|
||||||
printf("chat_main: %s\n", argv);
|
if ( debug ) {
|
||||||
|
dbglog("chat_main: %s\n", argv);
|
||||||
|
}
|
||||||
|
|
||||||
/* get first expect string */
|
/* get first expect string */
|
||||||
arg = getnextcommand(&argv);
|
arg = getnextcommand(&argv);
|
||||||
while ( arg != NULL ) {
|
while (( arg != NULL ) && ( exit_code == 0 )) {
|
||||||
/* process the expect string */
|
/* process the expect string */
|
||||||
chat_expect(arg);
|
chat_expect(arg);
|
||||||
|
if ( exit_code == 0 ) {
|
||||||
/* get the next send string */
|
/* get the next send string */
|
||||||
arg = getnextcommand(&argv);
|
|
||||||
if ( arg != NULL ) {
|
|
||||||
/* process the send string */
|
|
||||||
chat_send(arg);
|
|
||||||
|
|
||||||
/* get the next expect string */
|
|
||||||
arg = getnextcommand(&argv);
|
arg = getnextcommand(&argv);
|
||||||
|
if ( arg != NULL ) {
|
||||||
|
/* process the send string */
|
||||||
|
chat_send(arg);
|
||||||
|
|
||||||
|
/* get the next expect string */
|
||||||
|
arg = getnextcommand(&argv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if ( exit_code ) {
|
||||||
}
|
exit_code = -exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( exit_code );
|
||||||
|
|
||||||
/*
|
|
||||||
* Print an error message and terminate.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void init()
|
|
||||||
{
|
|
||||||
set_tty_parameters();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_tty_parameters()
|
|
||||||
{
|
|
||||||
term_parms t;
|
|
||||||
|
|
||||||
if (get_term_param (&t) < 0)
|
|
||||||
syslog(LOG_NOTICE,"Can't get terminal parameters:")
|
|
||||||
;
|
|
||||||
|
|
||||||
saved_tty_parameters = t;
|
|
||||||
have_tty_parameters = 1;
|
|
||||||
t.c_iflag |= IGNBRK | ISTRIP | IGNPAR;
|
|
||||||
t.c_oflag = 0;
|
|
||||||
t.c_lflag = 0;
|
|
||||||
t.c_cc[VERASE] =
|
|
||||||
t.c_cc[VKILL] = 0;
|
|
||||||
t.c_cc[VMIN] = 0;
|
|
||||||
t.c_cc[VTIME] = 1;
|
|
||||||
if (set_term_param (&t) < 0)
|
|
||||||
syslog(LOG_NOTICE,"Can't set terminal parameters:")
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void break_sequence()
|
void break_sequence()
|
||||||
{
|
{
|
||||||
|
tcsendbreak(ttyfd, 0);
|
||||||
/* tcsendbreak (0, 0);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void terminate(status)
|
|
||||||
int status;
|
|
||||||
{
|
|
||||||
echo_stderr(-1);
|
|
||||||
|
|
||||||
if (have_tty_parameters) {
|
|
||||||
if (set_term_param (&saved_tty_parameters) < 0)
|
|
||||||
fatal(2, "Can't restore terminal parameters: %m");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
* 'Clean up' this string.
|
* 'Clean up' this string.
|
||||||
*/
|
*/
|
||||||
@@ -347,10 +273,14 @@ char *clean(s, sending)
|
|||||||
register char *s;
|
register char *s;
|
||||||
int sending; /* set to 1 when sending (putting) this string. */
|
int sending; /* set to 1 when sending (putting) this string. */
|
||||||
{
|
{
|
||||||
char temp[STR_LEN], cur_chr;
|
char temp[STR_LEN], env_str[STR_LEN], cur_chr;
|
||||||
register char *s1, *phchar;
|
register char *s1, *phchar;
|
||||||
int add_return = sending;
|
int add_return = sending;
|
||||||
#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
|
#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
|
||||||
|
#define isalnumx(chr) ((((chr) >= '0') && ((chr) <= '9')) \
|
||||||
|
|| (((chr) >= 'a') && ((chr) <= 'z')) \
|
||||||
|
|| (((chr) >= 'A') && ((chr) <= 'Z')) \
|
||||||
|
|| (chr) == '_')
|
||||||
|
|
||||||
s1 = temp;
|
s1 = temp;
|
||||||
while (*s) {
|
while (*s) {
|
||||||
@@ -367,6 +297,18 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_env && cur_chr == '$') { /* ARI */
|
||||||
|
phchar = env_str;
|
||||||
|
while (isalnumx(*s))
|
||||||
|
*phchar++ = *s++;
|
||||||
|
*phchar = '\0';
|
||||||
|
phchar = getenv(env_str);
|
||||||
|
if (phchar)
|
||||||
|
while (*phchar)
|
||||||
|
*s1++ = *phchar++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (cur_chr != '\\') {
|
if (cur_chr != '\\') {
|
||||||
*s1++ = cur_chr;
|
*s1++ = cur_chr;
|
||||||
@@ -400,13 +342,12 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
case 'd':
|
case 'd':
|
||||||
if (sending)
|
if (sending)
|
||||||
*s1++ = '\\';
|
*s1++ = '\\';
|
||||||
|
|
||||||
*s1++ = cur_chr;
|
*s1++ = cur_chr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
if (sending && phone_num) {
|
if (sending && phone_num) {
|
||||||
for ( phchar = phone_num; *phchar != '\0'; phchar++)
|
for (phchar = phone_num; *phchar != '\0'; phchar++)
|
||||||
*s1++ = *phchar;
|
*s1++ = *phchar;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -417,7 +358,7 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
if (sending && phone_num2) {
|
if (sending && phone_num2) {
|
||||||
for ( phchar = phone_num2; *phchar != '\0'; phchar++)
|
for (phchar = phone_num2; *phchar != '\0'; phchar++)
|
||||||
*s1++ = *phchar;
|
*s1++ = *phchar;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -455,6 +396,13 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
*s1++ = 'N';
|
*s1++ = 'N';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '$': /* ARI */
|
||||||
|
if (use_env) {
|
||||||
|
*s1++ = cur_chr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* FALL THROUGH */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (isoctal (cur_chr)) {
|
if (isoctal (cur_chr)) {
|
||||||
cur_chr &= 0x07;
|
cur_chr &= 0x07;
|
||||||
@@ -493,7 +441,6 @@ int sending; /* set to 1 when sending (putting) this string. */
|
|||||||
/*
|
/*
|
||||||
* A modified version of 'strtok'. This version skips \ sequences.
|
* A modified version of 'strtok'. This version skips \ sequences.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *expect_strtok (s, term)
|
char *expect_strtok (s, term)
|
||||||
char *s, *term;
|
char *s, *term;
|
||||||
{
|
{
|
||||||
@@ -548,8 +495,7 @@ char *expect_strtok (s, term)
|
|||||||
/*
|
/*
|
||||||
* Process the expect string
|
* Process the expect string
|
||||||
*/
|
*/
|
||||||
|
void chat_expect (s)
|
||||||
void chat_expect (s)
|
|
||||||
char *s;
|
char *s;
|
||||||
{
|
{
|
||||||
char *expect;
|
char *expect;
|
||||||
@@ -557,42 +503,42 @@ char *s;
|
|||||||
|
|
||||||
if (strcmp(s, "HANGUP") == 0) {
|
if (strcmp(s, "HANGUP") == 0) {
|
||||||
++hup_next;
|
++hup_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "ABORT") == 0) {
|
if (strcmp(s, "ABORT") == 0) {
|
||||||
++abort_next;
|
++abort_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "CLR_ABORT") == 0) {
|
if (strcmp(s, "CLR_ABORT") == 0) {
|
||||||
++clear_abort_next;
|
++clear_abort_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "REPORT") == 0) {
|
if (strcmp(s, "REPORT") == 0) {
|
||||||
++report_next;
|
++report_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "CLR_REPORT") == 0) {
|
if (strcmp(s, "CLR_REPORT") == 0) {
|
||||||
++clear_report_next;
|
++clear_report_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "TIMEOUT") == 0) {
|
if (strcmp(s, "TIMEOUT") == 0) {
|
||||||
++timeout_next;
|
++timeout_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "ECHO") == 0) {
|
if (strcmp(s, "ECHO") == 0) {
|
||||||
++echo_next;
|
++echo_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "SAY") == 0) {
|
if (strcmp(s, "SAY") == 0) {
|
||||||
++say_next;
|
++say_next;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -600,10 +546,10 @@ char *s;
|
|||||||
*/
|
*/
|
||||||
for (;;) {
|
for (;;) {
|
||||||
expect = expect_strtok (s, "-");
|
expect = expect_strtok (s, "-");
|
||||||
s = (char *)0 ;
|
s = (char *) 0;
|
||||||
|
|
||||||
if (expect == (char *) 0)
|
if (expect == (char *) 0)
|
||||||
return ;
|
return;
|
||||||
|
|
||||||
reply = expect_strtok (s, "-");
|
reply = expect_strtok (s, "-");
|
||||||
|
|
||||||
@@ -622,11 +568,30 @@ char *s;
|
|||||||
|
|
||||||
chat_send (reply);
|
chat_send (reply);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The expectation did not occur. This is terminal.
|
* Translate the input character to the appropriate string for printing
|
||||||
|
* the data.
|
||||||
*/
|
*/
|
||||||
return ;
|
|
||||||
|
char *character(c)
|
||||||
|
int c;
|
||||||
|
{
|
||||||
|
static char string[10];
|
||||||
|
char *meta;
|
||||||
|
|
||||||
|
meta = (c & 0x80) ? "M-" : "";
|
||||||
|
c &= 0x7F;
|
||||||
|
|
||||||
|
if (c < 32)
|
||||||
|
sprintf(string, "%s^%c", meta, (int)c + '@');
|
||||||
|
else if (c == 127)
|
||||||
|
sprintf(string, "%s^?", meta);
|
||||||
|
else
|
||||||
|
sprintf(string, "%s%c", meta, c);
|
||||||
|
|
||||||
|
return (string);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -635,16 +600,19 @@ char *s;
|
|||||||
void chat_send (s)
|
void chat_send (s)
|
||||||
register char *s;
|
register char *s;
|
||||||
{
|
{
|
||||||
|
char file_data[STR_LEN];
|
||||||
|
|
||||||
if (say_next) {
|
if (say_next) {
|
||||||
say_next = 0;
|
say_next = 0;
|
||||||
s = clean(s,0);
|
s = clean(s, 1);
|
||||||
write(ttyfd, s, strlen(s));
|
write(2, s, strlen(s));
|
||||||
free(s);
|
free(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hup_next) {
|
if (hup_next) {
|
||||||
hup_next = 0;
|
hup_next = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (echo_next) {
|
if (echo_next) {
|
||||||
@@ -654,36 +622,53 @@ register char *s;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (abort_next) {
|
if (abort_next) {
|
||||||
/* char *s1; */
|
char *s1;
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
|
abort_next = 0;
|
||||||
|
if ( n_aborts < MAX_ABORTS ) {
|
||||||
|
s1 = clean(s, 0);
|
||||||
|
if (( strlen(s1) <= strlen(s) ) &&
|
||||||
|
( strlen(s1) < sizeof(fail_buffer))) {
|
||||||
|
|
||||||
|
abort_string[n_aborts++] = s1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clear_abort_next) {
|
||||||
|
clear_abort_next = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report_next) {
|
||||||
|
report_next = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clear_report_next) {
|
||||||
|
clear_report_next = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout_next) {
|
if (timeout_next) {
|
||||||
timeout=atoi(s);
|
|
||||||
timeout_next = 0;
|
timeout_next = 0;
|
||||||
chat_timeout = atoi(s);
|
timeout = atoi(s);
|
||||||
|
|
||||||
if (chat_timeout <= 0)
|
if (timeout <= 0)
|
||||||
chat_timeout = DEFAULT_CHAT_TIMEOUT;
|
timeout = DEFAULT_CHAT_TIMEOUT;
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(s, "EOT") == 0)
|
if (strcmp(s, "EOT") == 0)
|
||||||
s = "^D\\c";
|
s = "^D\\c";
|
||||||
else if (strcmp(s, "BREAK") == 0)
|
else if (strcmp(s, "BREAK") == 0)
|
||||||
s = "\\K\\c";
|
s = "\\K\\c";
|
||||||
|
|
||||||
if (!put_string(s))
|
if (!put_string(s)) {
|
||||||
{
|
exit_code = 2;
|
||||||
exit_code=1;
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_char()
|
int get_char()
|
||||||
@@ -708,21 +693,10 @@ int get_char()
|
|||||||
int put_char(c)
|
int put_char(c)
|
||||||
int c;
|
int c;
|
||||||
{
|
{
|
||||||
int status;
|
char ch = c;
|
||||||
char ch = c;
|
|
||||||
|
|
||||||
/* inter-character typing delay (?) */
|
write(ttyfd, &ch, 1);
|
||||||
|
|
||||||
status = write(ttyfd, &ch, 1);
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case 1:
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,44 +748,12 @@ register char *s;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* alarm(0);*/
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Echo a character to stderr.
|
|
||||||
* When called with -1, a '\n' character is generated when
|
|
||||||
* the cursor is not at the beginning of a line.
|
|
||||||
*/
|
|
||||||
void echo_stderr(n)
|
|
||||||
int n;
|
|
||||||
{
|
|
||||||
/* static int need_lf;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
switch (n) {
|
|
||||||
case '\r':
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
if (need_lf == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\n':
|
|
||||||
write(2, "\n", 1);
|
|
||||||
need_lf = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
s = character(n);
|
|
||||||
write(2, s, strlen(s));
|
|
||||||
need_lf = 1;
|
|
||||||
break;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 'Wait for' this string to appear on this file descriptor.
|
* 'Wait for' this string to appear on this file descriptor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int get_string(string)
|
int get_string(string)
|
||||||
register char *string;
|
register char *string;
|
||||||
{
|
{
|
||||||
@@ -820,6 +762,8 @@ register char *string;
|
|||||||
char *logged = temp2;
|
char *logged = temp2;
|
||||||
struct termios tios;
|
struct termios tios;
|
||||||
|
|
||||||
|
memset(temp2, 0, sizeof(temp2));
|
||||||
|
|
||||||
tcgetattr(ttyfd, &tios);
|
tcgetattr(ttyfd, &tios);
|
||||||
tios.c_cc[VMIN] = 0;
|
tios.c_cc[VMIN] = 0;
|
||||||
tios.c_cc[VTIME] = timeout*10/MAX_TIMEOUTS;
|
tios.c_cc[VTIME] = timeout*10/MAX_TIMEOUTS;
|
||||||
@@ -838,13 +782,12 @@ register char *string;
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
while ( (c = get_char()) >= 0) {
|
while ( (c = get_char()) >= 0) {
|
||||||
int n, abort_len;
|
int n, abort_len;
|
||||||
|
|
||||||
*s++ = c;
|
*s++ = c;
|
||||||
*s=0;
|
*s=0;
|
||||||
|
|
||||||
if (s - temp2 >= len &&
|
if (s - temp2 >= len &&
|
||||||
c == string[len - 1] &&
|
c == string[len - 1] &&
|
||||||
strncmp(s - len, string, len) == 0) {
|
strncmp(s - len, string, len) == 0) {
|
||||||
@@ -871,60 +814,7 @@ register char *string;
|
|||||||
s = temp2 + minlen;
|
s = temp2 + minlen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_code = 3;
|
exit_code = 3;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Gross kludge to handle Solaris versions >= 2.6 having usleep.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
usleep -- support routine for 4.2BSD system call emulations
|
|
||||||
last edit: 29-Oct-1984 D A Gwyn
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int
|
|
||||||
usleep( usec ) /* returns 0 if ok, else -1 */
|
|
||||||
long usec; /* delay in microseconds */
|
|
||||||
{
|
|
||||||
rtems_status_code status;
|
|
||||||
rtems_interval ticks_per_second;
|
|
||||||
rtems_interval ticks;
|
|
||||||
status = rtems_clock_get(
|
|
||||||
RTEMS_CLOCK_GET_TICKS_PER_SECOND,
|
|
||||||
&ticks_per_second);
|
|
||||||
ticks = (usec * (ticks_per_second/1000))/1000;
|
|
||||||
status = rtems_task_wake_after( ticks );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void pack_array (array, end)
|
|
||||||
char **array; /* The address of the array of string pointers */
|
|
||||||
int end; /* The index of the next free entry before CLR_ */
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
for (i = 0; i < end; i++) {
|
|
||||||
if (array[i] == NULL) {
|
|
||||||
for (j = i+1; j < end; ++j)
|
|
||||||
if (array[j] != NULL)
|
|
||||||
array[i++] = array[j];
|
|
||||||
for (; i < end; ++i)
|
|
||||||
array[i] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* vfmtmsg - format a message into a buffer. Like vsprintf except we
|
|
||||||
* also specify the length of the output buffer, and we handle the
|
|
||||||
* %m (error message) format.
|
|
||||||
* Doesn't do floating-point formats.
|
|
||||||
* Returns the number of chars put into buf.
|
|
||||||
*/
|
|
||||||
#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
|
|
||||||
|
|||||||
@@ -6,3 +6,10 @@ This is an example user application using pppd. It is built using
|
|||||||
the RTEMS application Makefiles. The file Makefile-user should
|
the RTEMS application Makefiles. The file Makefile-user should
|
||||||
be renamed to Makefile or the -f option given to make. The file
|
be renamed to Makefile or the -f option given to make. The file
|
||||||
is renamed to avoid bootstrap -c removing it.
|
is renamed to avoid bootstrap -c removing it.
|
||||||
|
|
||||||
|
The files ppp.conf and pppd.options are sample configuration files
|
||||||
|
that have successfully used to make ppp connections over a null
|
||||||
|
modem serial cable to a UNIX box. Please review the man pages
|
||||||
|
for either the ppp or pppd applications to ensure they are configured
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
|||||||
9
cpukit/pppd/example/pppd.options
Normal file
9
cpukit/pppd/example/pppd.options
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/dev/tty00
|
||||||
|
57600
|
||||||
|
crtscts
|
||||||
|
passive
|
||||||
|
local
|
||||||
|
noauth
|
||||||
|
debug
|
||||||
|
persist
|
||||||
|
192.168.2.222:192.168.2.111
|
||||||
@@ -589,6 +589,8 @@ extern void (*auth_linkdown_hook) __P((void));
|
|||||||
#define DEBUGCHAP 1
|
#define DEBUGCHAP 1
|
||||||
#endif
|
#endif
|
||||||
#define DEBUGMAIN 1
|
#define DEBUGMAIN 1
|
||||||
|
#define DEBUGUPAP 1
|
||||||
|
#define DEBUGCHAP 1
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUGMAIN
|
#ifdef DEBUGMAIN
|
||||||
|
|||||||
@@ -107,8 +107,6 @@ int phase; /* where the link is at */
|
|||||||
int kill_link;
|
int kill_link;
|
||||||
int open_ccp_flag;
|
int open_ccp_flag;
|
||||||
|
|
||||||
static int waiting;
|
|
||||||
|
|
||||||
char **script_env; /* Env. variable values for scripts */
|
char **script_env; /* Env. variable values for scripts */
|
||||||
int s_env_nalloc; /* # words avail at script_env */
|
int s_env_nalloc; /* # words avail at script_env */
|
||||||
|
|
||||||
@@ -234,8 +232,6 @@ pppdmain(argc, argv)
|
|||||||
setlogmask(LOG_UPTO(LOG_DEBUG));
|
setlogmask(LOG_UPTO(LOG_DEBUG));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
waiting = 0;
|
|
||||||
|
|
||||||
do_callback = 0;
|
do_callback = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
@@ -400,12 +396,10 @@ pppdmain(argc, argv)
|
|||||||
status = EXIT_NEGOTIATION_FAILED;
|
status = EXIT_NEGOTIATION_FAILED;
|
||||||
new_phase(PHASE_ESTABLISH);
|
new_phase(PHASE_ESTABLISH);
|
||||||
while (phase != PHASE_DEAD) {
|
while (phase != PHASE_DEAD) {
|
||||||
waiting = 1;
|
|
||||||
wait_input(timeleft(&timo));
|
wait_input(timeleft(&timo));
|
||||||
waiting = 0;
|
|
||||||
|
|
||||||
calltimeout();
|
calltimeout();
|
||||||
get_input();
|
get_input();
|
||||||
|
|
||||||
if (kill_link) {
|
if (kill_link) {
|
||||||
lcp_close(0, "User request");
|
lcp_close(0, "User request");
|
||||||
kill_link = 0;
|
kill_link = 0;
|
||||||
@@ -469,9 +463,7 @@ pppdmain(argc, argv)
|
|||||||
new_phase(PHASE_HOLDOFF);
|
new_phase(PHASE_HOLDOFF);
|
||||||
TIMEOUT(holdoff_end, NULL, t);
|
TIMEOUT(holdoff_end, NULL, t);
|
||||||
do {
|
do {
|
||||||
waiting = 1;
|
|
||||||
wait_input(timeleft(&timo));
|
wait_input(timeleft(&timo));
|
||||||
waiting = 0;
|
|
||||||
|
|
||||||
calltimeout();
|
calltimeout();
|
||||||
if (kill_link) {
|
if (kill_link) {
|
||||||
|
|||||||
Reference in New Issue
Block a user