cpukit: remove pppd

Update #3850
This commit is contained in:
Vijay Kumar Banerjee
2021-02-24 19:08:09 -07:00
parent 2a13ad389a
commit 369e6c5bf7
36 changed files with 0 additions and 18092 deletions

View File

@@ -1,49 +0,0 @@
/*
* COPYRIGHT (c) 2001, Michael Siers <mikes@poliac.com>.
* Poliac Research, Burnsville, Minnesota USA.
* COPYRIGHT (c) 2001, On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#ifndef RTEMSPPPD_H
#define RTEMSPPPD_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* define hook function identifiers */
#define RTEMS_PPPD_LINKUP_HOOK 1
#define RTEMS_PPPD_LINKDOWN_HOOK 2
#define RTEMS_PPPD_IPUP_HOOK 3
#define RTEMS_PPPD_IPDOWN_HOOK 4
#define RTEMS_PPPD_ERROR_HOOK 5
#define RTEMS_PPPD_EXIT_HOOK 6
/* define hook function pointer prototype */
typedef void (*rtems_pppd_hookfunction)(void);
typedef int (*rtems_pppd_dialerfunction)(int tty, int mode, char *pScript);
/* define pppd function prototyes */
int rtems_pppd_initialize(void);
int rtems_pppd_terminate(void);
int rtems_pppd_reset_options(void);
int rtems_pppd_set_hook(int id, rtems_pppd_hookfunction hookfp);
int rtems_pppd_set_dialer(rtems_pppd_dialerfunction dialerfp);
int rtems_pppd_set_option(const char *pOption, const char *pValue);
int rtems_pppd_connect(void);
int rtems_pppd_disconnect(void);
struct rtems_bsdnet_ifconfig;
int rtems_ppp_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@@ -1,25 +0,0 @@
This directory contains a port of ppp-2.3.11. The official site for
the original source for this PPP implementation is:
ftp://cs.anu.edu.au/pub/software/ppp
================================================================
History
The original port was of 2.3.5 by Tomasz Domin <dot@comarch.pl> of
ComArch SA and was initially only tested on the mpc823. He
provided the modem driver as well.
The port was updated to 2.3.11 by Mike Siers <mikes@poliac.com>
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.
Update code to use RTEMS pppd network drivers. Now the pppd
software is not dependent on using task driven mode. This
change improved stablity and performance. This was updated
by Mike Siers <mikes@poliac.com>.
=================================================================

View File

@@ -1,23 +0,0 @@
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.
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.
The pppd code had now been updated to use it's own RTEMS network
drivers. This removes the requirement for the task driven termios
support. This update has fixed the large packet ping problem.
Currently, I do not know of any problems with the port.
If you find any other problems or fix some problems, please post your
changes to the RTEMS mailing list.
Good Luck

File diff suppressed because it is too large Load Diff

View File

@@ -1,456 +0,0 @@
/*
* 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(char **);
static option_t cbcp_option_list[] = {
{ "callback", o_special, setcbcp,
"Ask for callback" },
{ NULL }
};
/*
* Protocol entry points.
*/
static void cbcp_init (int unit);
static void cbcp_open (int unit);
static void cbcp_lowerup (int unit);
static void cbcp_input (int unit, u_char *pkt, int len);
static void cbcp_protrej (int unit);
static int cbcp_printpkt (u_char *pkt, int len,
void (*printer)(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(cbcp_state *us, char *pckt, int len);
static void cbcp_resp(cbcp_state *us);
static void cbcp_up(cbcp_state *us);
static void cbcp_recvack(cbcp_state *us, char *pckt, int len);
static void cbcp_send(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)(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;
}

View File

@@ -1,26 +0,0 @@
#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

File diff suppressed because it is too large Load Diff

View File

@@ -1,48 +0,0 @@
/*
* ccp.h - Definitions for PPP Compression Control Protocol.
*
* Copyright (c) 1994 The Australian National University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, provided that the above copyright
* notice appears in all copies. This software is provided without any
* warranty, express or implied. The Australian National University
* makes no representations about the suitability of this software for
* any purpose.
*
* IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
* THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
*
* $Id$
*/
typedef struct ccp_options {
bool bsd_compress; /* do BSD Compress? */
bool deflate; /* do Deflate? */
bool predictor_1; /* do Predictor-1? */
bool predictor_2; /* do Predictor-2? */
bool deflate_correct; /* use correct code for deflate? */
bool deflate_draft; /* use draft RFC code for deflate? */
u_short bsd_bits; /* # bits/code for BSD Compress */
u_short deflate_size; /* lg(window size) for Deflate */
short method; /* code for chosen compression method */
} ccp_options;
extern fsm ccp_fsm[];
extern ccp_options ccp_wantoptions[];
extern ccp_options ccp_gotoptions[];
extern ccp_options ccp_allowoptions[];
extern ccp_options ccp_hisoptions[];
extern struct protent ccp_protent;

View File

@@ -1,854 +0,0 @@
/*
* chap.c - Challenge Handshake Authentication Protocol.
*
* Copyright (c) 1993 The Australian National University.
* 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 the Australian National University. The name of the University
* 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.
*
* Copyright (c) 1991 Gregory M. Christy.
* 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 Gregory M. Christy. 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.
*/
/*
* TODO:
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h> /* drand48, srand48 */
#include <sys/types.h>
#include <sys/time.h>
#include "pppd.h"
#include "chap.h"
#include "md5.h"
#ifdef CHAPMS
#include "chap_ms.h"
#endif
/*
* Command-line options.
*/
static option_t chap_option_list[] = {
{ "chap-restart", o_int, &chap[0].timeouttime,
"Set timeout for CHAP", 0, NULL, 0, 0 },
{ "chap-max-challenge", o_int, &chap[0].max_transmits,
"Set max #xmits for challenge", 0, NULL, 0, 0 },
{ "chap-interval", o_int, &chap[0].chal_interval,
"Set interval for rechallenge", 0, NULL, 0, 0 },
#ifdef MSLANMAN
{ "ms-lanman", o_bool, &ms_lanman,
"Use LanMan passwd when using MS-CHAP", 1, NULL, 0, 0 },
#endif
{ NULL, 0, NULL, NULL, 0, NULL, 0, 0 }
};
/*
* Protocol entry points.
*/
static void ChapInit(int);
static void ChapLowerUp(int);
static void ChapLowerDown(int);
static void ChapInput(int, u_char *, int);
static void ChapProtocolReject(int);
static int ChapPrintPkt(u_char *, int,
void (*)(void *, char *, ...), void *);
struct protent chap_protent = {
PPP_CHAP,
ChapInit,
ChapInput,
ChapProtocolReject,
ChapLowerUp,
ChapLowerDown,
NULL,
NULL,
ChapPrintPkt,
NULL,
1,
"CHAP",
NULL,
chap_option_list,
NULL,
NULL,
NULL
};
chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
static void ChapChallengeTimeout(void *);
static void ChapResponseTimeout(void *);
static void ChapReceiveChallenge(chap_state *, u_char *, int, int);
static void ChapRechallenge(void *);
static void ChapReceiveResponse(chap_state *, u_char *, int, int);
static void ChapReceiveSuccess(chap_state *, u_char *, u_char, int);
static void ChapReceiveFailure(chap_state *, u_char *, u_char, int);
static void ChapSendStatus(chap_state *, int);
static void ChapSendChallenge(chap_state *);
static void ChapSendResponse(chap_state *);
static void ChapGenChallenge(chap_state *);
/*
* ChapInit - Initialize a CHAP unit.
*/
static void
ChapInit(
int unit)
{
chap_state *cstate = &chap[unit];
BZERO(cstate, sizeof(*cstate));
cstate->unit = unit;
cstate->clientstate = CHAPCS_INITIAL;
cstate->serverstate = CHAPSS_INITIAL;
cstate->timeouttime = CHAP_DEFTIMEOUT;
cstate->max_transmits = CHAP_DEFTRANSMITS;
/* random number generator is initialized in magic_init */
}
/*
* ChapAuthWithPeer - Authenticate us with our peer (start client).
*
*/
void
ChapAuthWithPeer(
int unit,
char *our_name,
int digest)
{
chap_state *cstate = &chap[unit];
cstate->resp_name = our_name;
cstate->resp_type = digest;
if (cstate->clientstate == CHAPCS_INITIAL ||
cstate->clientstate == CHAPCS_PENDING) {
/* lower layer isn't up - wait until later */
cstate->clientstate = CHAPCS_PENDING;
return;
}
/*
* We get here as a result of LCP coming up.
* So even if CHAP was open before, we will
* have to re-authenticate ourselves.
*/
cstate->clientstate = CHAPCS_LISTEN;
}
/*
* ChapAuthPeer - Authenticate our peer (start server).
*/
void
ChapAuthPeer(
int unit,
char *our_name,
int digest)
{
chap_state *cstate = &chap[unit];
cstate->chal_name = our_name;
cstate->chal_type = digest;
if (cstate->serverstate == CHAPSS_INITIAL ||
cstate->serverstate == CHAPSS_PENDING) {
/* lower layer isn't up - wait until later */
cstate->serverstate = CHAPSS_PENDING;
return;
}
ChapGenChallenge(cstate);
ChapSendChallenge(cstate); /* crank it up dude! */
cstate->serverstate = CHAPSS_INITIAL_CHAL;
}
/*
* ChapChallengeTimeout - Timeout expired on sending challenge.
*/
static void
ChapChallengeTimeout(
void *arg)
{
chap_state *cstate = (chap_state *) arg;
/* if we aren't sending challenges, don't worry. then again we */
/* probably shouldn't be here either */
if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
cstate->serverstate != CHAPSS_RECHALLENGE)
return;
if (cstate->chal_transmits >= cstate->max_transmits) {
/* give up on peer */
error("Peer failed to respond to CHAP challenge");
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP);
return;
}
ChapSendChallenge(cstate); /* Re-send challenge */
}
/*
* ChapResponseTimeout - Timeout expired on sending response.
*/
static void
ChapResponseTimeout(
void *arg)
{
chap_state *cstate = (chap_state *) arg;
/* if we aren't sending a response, don't worry. */
if (cstate->clientstate != CHAPCS_RESPONSE)
return;
ChapSendResponse(cstate); /* re-send response */
}
/*
* ChapRechallenge - Time to challenge the peer again.
*/
static void
ChapRechallenge(
void *arg)
{
chap_state *cstate = (chap_state *) arg;
/* if we aren't sending a response, don't worry. */
if (cstate->serverstate != CHAPSS_OPEN)
return;
ChapGenChallenge(cstate);
ChapSendChallenge(cstate);
cstate->serverstate = CHAPSS_RECHALLENGE;
}
/*
* ChapLowerUp - The lower layer is up.
*
* Start up if we have pending requests.
*/
static void
ChapLowerUp(
int unit)
{
chap_state *cstate = &chap[unit];
if (cstate->clientstate == CHAPCS_INITIAL)
cstate->clientstate = CHAPCS_CLOSED;
else if (cstate->clientstate == CHAPCS_PENDING)
cstate->clientstate = CHAPCS_LISTEN;
if (cstate->serverstate == CHAPSS_INITIAL)
cstate->serverstate = CHAPSS_CLOSED;
else if (cstate->serverstate == CHAPSS_PENDING) {
ChapGenChallenge(cstate);
ChapSendChallenge(cstate);
cstate->serverstate = CHAPSS_INITIAL_CHAL;
}
}
/*
* ChapLowerDown - The lower layer is down.
*
* Cancel all timeouts.
*/
static void
ChapLowerDown(
int unit)
{
chap_state *cstate = &chap[unit];
/* Timeout(s) pending? Cancel if so. */
if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
cstate->serverstate == CHAPSS_RECHALLENGE)
UNTIMEOUT(ChapChallengeTimeout, cstate);
else if (cstate->serverstate == CHAPSS_OPEN
&& cstate->chal_interval != 0)
UNTIMEOUT(ChapRechallenge, cstate);
if (cstate->clientstate == CHAPCS_RESPONSE)
UNTIMEOUT(ChapResponseTimeout, cstate);
cstate->clientstate = CHAPCS_INITIAL;
cstate->serverstate = CHAPSS_INITIAL;
}
/*
* ChapProtocolReject - Peer doesn't grok CHAP.
*/
static void
ChapProtocolReject(
int unit)
{
chap_state *cstate = &chap[unit];
if (cstate->serverstate != CHAPSS_INITIAL &&
cstate->serverstate != CHAPSS_CLOSED)
auth_peer_fail(unit, PPP_CHAP);
if (cstate->clientstate != CHAPCS_INITIAL &&
cstate->clientstate != CHAPCS_CLOSED)
auth_withpeer_fail(unit, PPP_CHAP);
ChapLowerDown(unit); /* shutdown chap */
}
/*
* ChapInput - Input CHAP packet.
*/
static void
ChapInput(
int unit,
u_char *inpacket,
int packet_len)
{
chap_state *cstate = &chap[unit];
u_char *inp;
u_char code, id;
int len;
/*
* Parse header (code, id and length).
* If packet too short, drop it.
*/
inp = inpacket;
if (packet_len < CHAP_HEADERLEN) {
CHAPDEBUG(("ChapInput: rcvd short header."));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len < CHAP_HEADERLEN) {
CHAPDEBUG(("ChapInput: rcvd illegal length."));
return;
}
if (len > packet_len) {
CHAPDEBUG(("ChapInput: rcvd short packet."));
return;
}
len -= CHAP_HEADERLEN;
/*
* Action depends on code (as in fact it usually does :-).
*/
switch (code) {
case CHAP_CHALLENGE:
ChapReceiveChallenge(cstate, inp, id, len);
break;
case CHAP_RESPONSE:
ChapReceiveResponse(cstate, inp, id, len);
break;
case CHAP_FAILURE:
ChapReceiveFailure(cstate, inp, id, len);
break;
case CHAP_SUCCESS:
ChapReceiveSuccess(cstate, inp, id, len);
break;
default: /* Need code reject? */
warn("Unknown CHAP code (%d) received.", code);
break;
}
}
/*
* ChapReceiveChallenge - Receive Challenge and send Response.
*/
static void
ChapReceiveChallenge(
chap_state *cstate,
u_char *inp,
int id,
int len)
{
int rchallenge_len;
u_char *rchallenge;
int secret_len;
unsigned char secret[MAXSECRETLEN];
char rhostname[256];
MD5_CTX mdContext;
u_char hash[MD5_SIGNATURE_SIZE];
if (cstate->clientstate == CHAPCS_CLOSED ||
cstate->clientstate == CHAPCS_PENDING) {
CHAPDEBUG(("ChapReceiveChallenge: in state %d", cstate->clientstate));
return;
}
if (len < 2) {
CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
return;
}
GETCHAR(rchallenge_len, inp);
len -= sizeof (u_char) + rchallenge_len; /* now name field length */
if (len < 0) {
CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
return;
}
rchallenge = inp;
INCPTR(rchallenge_len, inp);
if (len >= sizeof(rhostname))
len = sizeof(rhostname) - 1;
BCOPY(inp, rhostname, len);
rhostname[len] = '\000';
/* Microsoft doesn't send their name back in the PPP packet */
if (explicit_remote || (remote_name[0] != 0 && rhostname[0] == 0)) {
strlcpy(rhostname, remote_name, sizeof(rhostname));
CHAPDEBUG(("ChapReceiveChallenge: using '%q' as remote name",
rhostname));
}
/* get secret for authenticating ourselves with the specified host */
if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
secret, &secret_len, 0)) {
secret_len = 0; /* assume null secret if can't find one */
warn("No CHAP secret found for authenticating us to %q", rhostname);
}
/* cancel response send timeout if necessary */
if (cstate->clientstate == CHAPCS_RESPONSE)
UNTIMEOUT(ChapResponseTimeout, cstate);
cstate->resp_id = id;
cstate->resp_transmits = 0;
/* generate MD based on negotiated type */
switch (cstate->resp_type) {
case CHAP_DIGEST_MD5:
MD5Init(&mdContext);
MD5Update(&mdContext, &cstate->resp_id, 1);
MD5Update(&mdContext, secret, secret_len);
MD5Update(&mdContext, rchallenge, rchallenge_len);
MD5Final(hash, &mdContext);
BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
cstate->resp_length = MD5_SIGNATURE_SIZE;
break;
#ifdef CHAPMS
case CHAP_MICROSOFT:
ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
break;
#endif
default:
CHAPDEBUG(("unknown digest type %d", cstate->resp_type));
return;
}
BZERO(secret, sizeof(secret));
ChapSendResponse(cstate);
}
/*
* ChapReceiveResponse - Receive and process response.
*/
static void
ChapReceiveResponse(
chap_state *cstate,
u_char *inp,
int id,
int len)
{
u_char *remmd, remmd_len;
int secret_len, old_state;
int code;
char rhostname[256];
MD5_CTX mdContext;
unsigned char secret[MAXSECRETLEN];
u_char hash[MD5_SIGNATURE_SIZE];
if (cstate->serverstate == CHAPSS_CLOSED ||
cstate->serverstate == CHAPSS_PENDING) {
CHAPDEBUG(("ChapReceiveResponse: in state %d", cstate->serverstate));
return;
}
if (id != cstate->chal_id)
return; /* doesn't match ID of last challenge */
/*
* If we have received a duplicate or bogus Response,
* we have to send the same answer (Success/Failure)
* as we did for the first Response we saw.
*/
if (cstate->serverstate == CHAPSS_OPEN) {
ChapSendStatus(cstate, CHAP_SUCCESS);
return;
}
if (cstate->serverstate == CHAPSS_BADAUTH) {
ChapSendStatus(cstate, CHAP_FAILURE);
return;
}
if (len < 2) {
CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
return;
}
GETCHAR(remmd_len, inp); /* get length of MD */
remmd = inp; /* get pointer to MD */
INCPTR(remmd_len, inp);
len -= sizeof (u_char) + remmd_len;
if (len < 0) {
CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
return;
}
UNTIMEOUT(ChapChallengeTimeout, cstate);
if (len >= sizeof(rhostname))
len = sizeof(rhostname) - 1;
BCOPY(inp, rhostname, len);
rhostname[len] = '\000';
/*
* Get secret for authenticating them with us,
* do the hash ourselves, and compare the result.
*/
code = CHAP_FAILURE;
if (!get_secret(cstate->unit, (explicit_remote? remote_name: rhostname),
cstate->chal_name, secret, &secret_len, 1)) {
warn("No CHAP secret found for authenticating %q", rhostname);
} else {
/* generate MD based on negotiated type */
switch (cstate->chal_type) {
case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
if (remmd_len != MD5_SIGNATURE_SIZE)
break; /* it's not even the right length */
MD5Init(&mdContext);
MD5Update(&mdContext, &cstate->chal_id, 1);
MD5Update(&mdContext, secret, secret_len);
MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
MD5Final(hash, &mdContext);
/* compare local and remote MDs and send the appropriate status */
if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0)
code = CHAP_SUCCESS; /* they are the same! */
break;
default:
CHAPDEBUG(("unknown digest type %d", cstate->chal_type));
}
}
BZERO(secret, sizeof(secret));
ChapSendStatus(cstate, code);
if (code == CHAP_SUCCESS) {
old_state = cstate->serverstate;
cstate->serverstate = CHAPSS_OPEN;
if (old_state == CHAPSS_INITIAL_CHAL) {
auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
}
if (cstate->chal_interval != 0)
TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
notice("CHAP peer authentication succeeded for %q", rhostname);
} else {
error("CHAP peer authentication failed for remote host %q", rhostname);
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP);
}
}
/*
* ChapReceiveSuccess - Receive Success
*/
static void
ChapReceiveSuccess(
chap_state *cstate,
u_char *inp,
u_char id,
int len)
{
if (cstate->clientstate == CHAPCS_OPEN)
/* presumably an answer to a duplicate response */
return;
if (cstate->clientstate != CHAPCS_RESPONSE) {
/* don't know what this is */
CHAPDEBUG(("ChapReceiveSuccess: in state %d\n", cstate->clientstate));
return;
}
UNTIMEOUT(ChapResponseTimeout, cstate);
/*
* Print message.
*/
if (len > 0)
PRINTMSG(inp, len);
cstate->clientstate = CHAPCS_OPEN;
auth_withpeer_success(cstate->unit, PPP_CHAP);
}
/*
* ChapReceiveFailure - Receive failure.
*/
static void
ChapReceiveFailure(
chap_state *cstate,
u_char *inp,
u_char id,
int len)
{
if (cstate->clientstate != CHAPCS_RESPONSE) {
/* don't know what this is */
CHAPDEBUG(("ChapReceiveFailure: in state %d\n", cstate->clientstate));
return;
}
UNTIMEOUT(ChapResponseTimeout, cstate);
/*
* Print message.
*/
if (len > 0)
PRINTMSG(inp, len);
error("CHAP authentication failed");
auth_withpeer_fail(cstate->unit, PPP_CHAP);
}
/*
* ChapSendChallenge - Send an Authenticate challenge.
*/
static void
ChapSendChallenge(
chap_state *cstate)
{
u_char *outp;
int chal_len, name_len;
int outlen;
chal_len = cstate->chal_len;
name_len = strlen(cstate->chal_name);
outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
PUTCHAR(CHAP_CHALLENGE, outp);
PUTCHAR(cstate->chal_id, outp);
PUTSHORT(outlen, outp);
PUTCHAR(chal_len, outp); /* put length of challenge */
BCOPY(cstate->challenge, outp, chal_len);
INCPTR(chal_len, outp);
BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
++cstate->chal_transmits;
}
/*
* ChapSendStatus - Send a status response (ack or nak).
*/
static void
ChapSendStatus(
chap_state *cstate,
int code)
{
u_char *outp;
int outlen, msglen;
char msg[256];
if (code == CHAP_SUCCESS)
slprintf(msg, sizeof(msg), "Welcome to %s.", hostname);
else
slprintf(msg, sizeof(msg), "I don't like you. Go 'way.");
msglen = strlen(msg);
outlen = CHAP_HEADERLEN + msglen;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
PUTCHAR(code, outp);
PUTCHAR(cstate->chal_id, outp);
PUTSHORT(outlen, outp);
BCOPY(msg, outp, msglen);
output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
}
/*
* ChapGenChallenge is used to generate a pseudo-random challenge string of
* a pseudo-random length between min_len and max_len. The challenge
* string and its length are stored in *cstate, and various other fields of
* *cstate are initialized.
*/
static void
ChapGenChallenge(
chap_state *cstate)
{
int chal_len;
u_char *ptr = cstate->challenge;
int i;
/* pick a random challenge length between MIN_CHALLENGE_LENGTH and
MAX_CHALLENGE_LENGTH */
chal_len = (unsigned) ((drand48() *
(MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
MIN_CHALLENGE_LENGTH);
cstate->chal_len = chal_len;
cstate->chal_id = ++cstate->id;
cstate->chal_transmits = 0;
/* generate a random string */
for (i = 0; i < chal_len; i++)
*ptr++ = (char) (drand48() * 0xff);
}
/*
* ChapSendResponse - send a response packet with values as specified
* in *cstate.
*/
/* ARGSUSED */
static void
ChapSendResponse(
chap_state *cstate)
{
u_char *outp;
int outlen, md_len, name_len;
md_len = cstate->resp_length;
name_len = strlen(cstate->resp_name);
outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_CHAP);
PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
PUTSHORT(outlen, outp); /* packet length */
PUTCHAR(md_len, outp); /* length of MD */
BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
INCPTR(md_len, outp);
BCOPY(cstate->resp_name, outp, name_len); /* append our name */
/* send the packet */
output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
cstate->clientstate = CHAPCS_RESPONSE;
TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
++cstate->resp_transmits;
}
/*
* ChapPrintPkt - print the contents of a CHAP packet.
*/
static char *ChapCodenames[] = {
"Challenge", "Response", "Success", "Failure"
};
static int
ChapPrintPkt(
u_char *p,
int plen,
void (*printer)(void *, char *, ...),
void *arg)
{
int code, id, len;
int clen, nlen;
u_char x;
if (plen < CHAP_HEADERLEN)
return 0;
GETCHAR(code, p);
GETCHAR(id, p);
GETSHORT(len, p);
if (len < CHAP_HEADERLEN || len > plen)
return 0;
if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *))
printer(arg, " %s", ChapCodenames[code-1]);
else
printer(arg, " code=0x%x", code);
printer(arg, " id=0x%x", id);
len -= CHAP_HEADERLEN;
switch (code) {
case CHAP_CHALLENGE:
case CHAP_RESPONSE:
if (len < 1)
break;
clen = p[0];
if (len < clen + 1)
break;
++p;
nlen = len - clen - 1;
printer(arg, " <");
for (; clen > 0; --clen) {
GETCHAR(x, p);
printer(arg, "%.2x", x);
}
printer(arg, ">, name = ");
print_string((char *)p, nlen, printer, arg);
break;
case CHAP_FAILURE:
case CHAP_SUCCESS:
printer(arg, " ");
print_string((char *)p, len, printer, arg);
break;
default:
for (clen = len; clen > 0; --clen) {
GETCHAR(x, p);
printer(arg, " %.2x", x);
}
}
return len + CHAP_HEADERLEN;
}

View File

@@ -1,124 +0,0 @@
/*
* chap.h - Challenge Handshake Authentication Protocol definitions.
*
* Copyright (c) 1993 The Australian National University.
* 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 the Australian National University. The name of the University
* 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.
*
* Copyright (c) 1991 Gregory M. Christy
* 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 the author.
*
* 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.
*
* $Id$
*/
#ifndef __CHAP_INCLUDE__
/* Code + ID + length */
#define CHAP_HEADERLEN 4
/*
* CHAP codes.
*/
#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */
#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */
#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */
#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */
#define CHAP_CHALLENGE 1
#define CHAP_RESPONSE 2
#define CHAP_SUCCESS 3
#define CHAP_FAILURE 4
/*
* Challenge lengths (for challenges we send) and other limits.
*/
#define MIN_CHALLENGE_LENGTH 16
#define MAX_CHALLENGE_LENGTH 24
#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */
/*
* Each interface is described by a chap structure.
*/
typedef struct chap_state {
int unit; /* Interface unit number */
int clientstate; /* Client state */
int serverstate; /* Server state */
u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */
u_char chal_len; /* challenge length */
u_char chal_id; /* ID of last challenge */
u_char chal_type; /* hash algorithm for challenges */
u_char id; /* Current id */
char *chal_name; /* Our name to use with challenge */
int chal_interval; /* Time until we challenge peer again */
int timeouttime; /* Timeout time in seconds */
int max_transmits; /* Maximum # of challenge transmissions */
int chal_transmits; /* Number of transmissions of challenge */
int resp_transmits; /* Number of transmissions of response */
u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */
u_char resp_length; /* length of response */
u_char resp_id; /* ID for response messages */
u_char resp_type; /* hash algorithm for responses */
char *resp_name; /* Our name to send with response */
} chap_state;
/*
* Client (peer) states.
*/
#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */
#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */
#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */
#define CHAPCS_LISTEN 3 /* Listening for a challenge */
#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */
#define CHAPCS_OPEN 5 /* We've received Success */
/*
* Server (authenticator) states.
*/
#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */
#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */
#define CHAPSS_PENDING 2 /* Auth peer when lower up */
#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */
#define CHAPSS_OPEN 4 /* We've sent a Success msg */
#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */
#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */
/*
* Timeouts.
*/
#define CHAP_DEFTIMEOUT 5 /* Timeout time in seconds */
#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */
extern chap_state chap[];
void ChapAuthWithPeer(int, char *, int);
void ChapAuthPeer(int, char *, int);
extern struct protent chap_protent;
#define __CHAP_INCLUDE__
#endif /* __CHAP_INCLUDE__ */

View File

@@ -1,338 +0,0 @@
/*
* chap_ms.c - Microsoft MS-CHAP compatible implementation.
*
* Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
* http://www.strataware.com/
*
* 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 Eric Rosenquist. 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.
*/
/*
* Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
*
* Implemented LANManager type password response to MS-CHAP challenges.
* Now pppd provides both NT style and LANMan style blocks, and the
* prefered is set by option "ms-lanman". Default is to use NT.
* The hash text (StdText) was taken from Win95 RASAPI32.DLL.
*
* You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
*/
#define RCSID "$Id$"
#ifdef CHAPMS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#include "pppd.h"
#include "chap.h"
#include "chap_ms.h"
#include "md4.h"
#ifndef USE_CRYPT
#include <des.h>
#endif
static const char rcsid[] = RCSID;
typedef struct {
u_char LANManResp[24];
u_char NTResp[24];
u_char UseNT; /* If 1, ignore the LANMan response field */
} MS_ChapResponse;
/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
in case this struct gets padded. */
static void ChallengeResponse(u_char *, u_char *, u_char *);
static void DesEncrypt(u_char *, u_char *, u_char *);
static void MakeKey(u_char *, u_char *);
static u_char Get7Bits(u_char *, int);
static void ChapMS_NT(char *, int, char *, int, MS_ChapResponse *);
#ifdef MSLANMAN
static void ChapMS_LANMan(char *, int, char *, int, MS_ChapResponse *);
#endif
#ifdef USE_CRYPT
static void Expand(u_char *, u_char *);
static void Collapse(u_char *, u_char *);
#endif
#ifdef MSLANMAN
bool ms_lanman = 0; /* Use LanMan password instead of NT */
/* Has meaning only with MS-CHAP challenges */
#endif
static void
ChallengeResponse(challenge, pwHash, response)
u_char *challenge; /* IN 8 octets */
u_char *pwHash; /* IN 16 octets */
u_char *response; /* OUT 24 octets */
{
char ZPasswordHash[21];
BZERO(ZPasswordHash, sizeof(ZPasswordHash));
BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
#if 0
dbglog("ChallengeResponse - ZPasswordHash %.*B",
sizeof(ZPasswordHash), ZPasswordHash);
#endif
DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
#if 0
dbglog("ChallengeResponse - response %.24B", response);
#endif
}
#ifdef USE_CRYPT
static void
DesEncrypt(clear, key, cipher)
u_char *clear; /* IN 8 octets */
u_char *key; /* IN 7 octets */
u_char *cipher; /* OUT 8 octets */
{
u_char des_key[8];
u_char crypt_key[66];
u_char des_input[66];
MakeKey(key, des_key);
Expand(des_key, crypt_key);
setkey(crypt_key);
#if 0
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
#endif
Expand(clear, des_input);
encrypt(des_input, 0);
Collapse(des_input, cipher);
#if 0
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
#endif
}
#else /* USE_CRYPT */
static void
DesEncrypt(clear, key, cipher)
u_char *clear; /* IN 8 octets */
u_char *key; /* IN 7 octets */
u_char *cipher; /* OUT 8 octets */
{
des_cblock des_key;
des_key_schedule key_schedule;
MakeKey(key, des_key);
des_set_key(&des_key, key_schedule);
#if 0
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
#endif
des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
#if 0
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
#endif
}
#endif /* USE_CRYPT */
static u_char Get7Bits(input, startBit)
u_char *input;
int startBit;
{
register unsigned int word;
word = (unsigned)input[startBit / 8] << 8;
word |= (unsigned)input[startBit / 8 + 1];
word >>= 15 - (startBit % 8 + 7);
return word & 0xFE;
}
#ifdef USE_CRYPT
/* in == 8-byte string (expanded version of the 56-bit key)
* out == 64-byte string where each byte is either 1 or 0
* Note that the low-order "bit" is always ignored by by setkey()
*/
static void Expand(in, out)
u_char *in;
u_char *out;
{
int j, c;
int i;
for(i = 0; i < 64; in++){
c = *in;
for(j = 7; j >= 0; j--)
*out++ = (c >> j) & 01;
i += 8;
}
}
/* The inverse of Expand
*/
static void Collapse(in, out)
u_char *in;
u_char *out;
{
int j;
int i;
unsigned int c;
for (i = 0; i < 64; i += 8, out++) {
c = 0;
for (j = 7; j >= 0; j--, in++)
c |= *in << j;
*out = c & 0xff;
}
}
#endif
static void MakeKey(key, des_key)
u_char *key; /* IN 56 bit DES key missing parity bits */
u_char *des_key; /* OUT 64 bit DES key with parity bits added */
{
des_key[0] = Get7Bits(key, 0);
des_key[1] = Get7Bits(key, 7);
des_key[2] = Get7Bits(key, 14);
des_key[3] = Get7Bits(key, 21);
des_key[4] = Get7Bits(key, 28);
des_key[5] = Get7Bits(key, 35);
des_key[6] = Get7Bits(key, 42);
des_key[7] = Get7Bits(key, 49);
#ifndef USE_CRYPT
des_set_odd_parity((des_cblock *)des_key);
#endif
#if 0
CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key));
CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key));
#endif
}
static void
ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response)
char *rchallenge;
int rchallenge_len;
char *secret;
int secret_len;
MS_ChapResponse *response;
{
int i;
#ifdef __NetBSD__
/* NetBSD uses the libc md4 routines which take bytes instead of bits */
int mdlen = secret_len * 2;
#else
int mdlen = secret_len * 2 * 8;
#endif
MD4_CTX md4Context;
u_char hash[MD4_SIGNATURE_SIZE];
u_char unicodePassword[MAX_NT_PASSWORD * 2];
/* Initialize the Unicode version of the secret (== password). */
/* This implicitly supports 8-bit ISO8859/1 characters. */
BZERO(unicodePassword, sizeof(unicodePassword));
for (i = 0; i < secret_len; i++)
unicodePassword[i * 2] = (u_char)secret[i];
MD4Init(&md4Context);
MD4Update(&md4Context, unicodePassword, mdlen);
MD4Final(hash, &md4Context); /* Tell MD4 we're done */
ChallengeResponse(rchallenge, hash, response->NTResp);
}
#ifdef MSLANMAN
static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
static void
ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response)
char *rchallenge;
int rchallenge_len;
char *secret;
int secret_len;
MS_ChapResponse *response;
{
int i;
u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
u_char PasswordHash[MD4_SIGNATURE_SIZE];
/* LANMan password is case insensitive */
BZERO(UcasePassword, sizeof(UcasePassword));
for (i = 0; i < secret_len; i++)
UcasePassword[i] = (u_char)toupper(secret[i]);
DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
}
#endif
void
ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len)
chap_state *cstate;
char *rchallenge;
int rchallenge_len;
char *secret;
int secret_len;
{
MS_ChapResponse response;
#if 0
CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
#endif
BZERO(&response, sizeof(response));
/* Calculate both always */
ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
#ifdef MSLANMAN
ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
/* prefered method is set by option */
response.UseNT = !ms_lanman;
#else
response.UseNT = 1;
#endif
BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
cstate->resp_length = MS_CHAP_RESPONSE_LEN;
}
#endif /* CHAPMS */

View File

@@ -1,33 +0,0 @@
/*
* chap.h - Challenge Handshake Authentication Protocol definitions.
*
* Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
* http://www.strataware.com/
*
* 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 Eric Rosenquist. 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.
*
* $Id$
*/
#ifndef __CHAPMS_INCLUDE__
#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */
#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */
void ChapMS(chap_state *, char *, int, char *, int);
#define __CHAPMS_INCLUDE__
#endif /* __CHAPMS_INCLUDE__ */

View File

@@ -1,854 +0,0 @@
/*
* Chat -- a program for automatic session establishment (i.e. dial
* the phone and log in).
*
* Standard termination codes:
* 0 - successful completion of the script
* 1 - invalid argument, expect string too large, etc.
* 2 - error on an I/O operation or fatal error condition.
* 3 - timeout waiting for a simple string.
* 4 - the first string declared as "ABORT"
* 5 - the second string declared as "ABORT"
* 6 - ... and so on for successive ABORT strings.
*
* 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
* number into chat script. Two are needed for some ISDN TA applications.
* Keith Dart <kdart@cisco.com>
*
*
* Added SAY keyword to send output to stderr.
* This allows to turn ECHO OFF and to output specific, user selected,
* text to give progress messages. This best works when stderr
* exists (i.e.: pppd in nodetach mode).
*
* Added HANGUP directives to allow for us to be called
* back. When HANGUP is set to NO, chat will not hangup at HUP signal.
* We rely on timeouts in that case.
*
* Added CLR_ABORT to clear previously set ABORT string. This has been
* dictated by the HANGUP above as "NO CARRIER" (for example) must be
* an ABORT condition until we know the other host is going to close
* the connection for call back. As soon as we have completed the
* first stage of the call back sequence, "NO CARRIER" is a valid, non
* fatal string. As soon as we got called back (probably get "CONNECT"),
* we should re-arm the ABORT "NO CARRIER". Hence the CLR_ABORT command.
* Note that CLR_ABORT packs the abort_strings[] array so that we do not
* have unused entries not being reclaimed.
*
* In the same vein as above, added CLR_REPORT keyword.
*
* Allow for comments. Line starting with '#' are comments and are
* ignored. If a '#' is to be expected as the first character, the
* expect string must be quoted.
*
*
* Francis Demierre <Francis@SwissMail.Com>
* Thu May 15 17:15:40 MET DST 1997
*
*
* Added -r "report file" switch & REPORT keyword.
* Robert Geer <bgeer@xmission.com>
*
* Added -s "use stderr" and -S "don't use syslog" switches.
* June 18, 1997
* Karl O. Pinc <kop@meme.com>
*
*
* Added -e "echo" switch & ECHO keyword
* Dick Streefland <dicks@tasking.nl>
*
*
* Considerable updates and modifications by
* Al Longyear <longyear@pobox.com>
* Paul Mackerras <paulus@cs.anu.edu.au>
*
*
* The original author is:
*
* Karl Fox <karl@MorningStar.Com>
* Morning Star Technologies, Inc.
* 1760 Zollinger Road
* Columbus, OH 43221
* (614)451-1883
*
*/
/* $Id$ */
/*
Fixes and some Changes by Wilfried Busalski Lancier-Monitoring GmbH Germany
wilfried.busalski@muenster.de
Fixes: put_string() Free memory allocated by clean()
get_string() Free memory allocated by clean()
chat_main() Will Distroy's no more the chat-script
getnextcommand() sepatator changed to '@'
*/
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include <termios.h>
#include "pppd.h"
#undef TERMIOS
#define TERMIOS
#define STR_LEN 1024
char temp2[STR_LEN];
#ifndef SIGTYPE
#define SIGTYPE void
#endif
#undef __V
#ifdef __STDC__
#include <stdarg.h>
#define __V(x) x
#else
#include <varargs.h>
#define __V(x) (va_alist) va_dcl
#define const
#endif
#ifndef O_NONBLOCK
#define O_NONBLOCK O_NDELAY
#endif
/*************** Micro getopt() *********************************************/
#define OPTION(c,v) (_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \
(--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\
&&!v[0][1]?(--c,++v,0):(_O=2,*(*v)++):0))
#define OPTARG(c,v) (_O&2?**v||(++v,--c)?(_O=1,--c,*v++): \
(_O=4,(char*)0):(char*)0)
#define OPTONLYARG(c,v) (_O&2&&**v?(_O=1,--c,*v++):(char*)0)
#define ARG(c,v) (c?(--c,*v++):(char*)0)
#if 0
static int _O = 0; /* Internal state */
#endif
/*************** Micro getopt() *********************************************/
#define MAX_ABORTS 16
#define MAX_REPORTS 16
#define DEFAULT_CHAT_TIMEOUT 45
#define MAX_TIMEOUTS 10
static int echo = 0;
static int quiet = 0;
static int use_env = 0;
static int exit_code = 0;
static char *phone_num = (char *) 0;
static char *phone_num2 = (char *) 0;
static int ttyfd;
static int timeout = DEFAULT_CHAT_TIMEOUT;
#ifdef TERMIOS
#define term_parms struct termios
#define get_term_param(param) tcgetattr(0, param)
#define set_term_param(param) tcsetattr(0, TCSANOW, param)
struct termios saved_tty_parameters;
#endif
char *fail_reason = (char *)0;
char fail_buffer[50];
char *abort_string[MAX_ABORTS]={"BUSY","NO DIALTONE","NO CARRIER","NO ANSWER","RING\r\nRING"};
int n_aborts = 5;
int abort_next = 0, timeout_next = 0, echo_next = 0;
int clear_abort_next = 0;
char *report_string[MAX_REPORTS] ;
char report_buffer[50] ;
int n_reports = 0, report_next = 0, report_gathering = 0 ;
int clear_report_next = 0;
int say_next = 0, hup_next = 0;
void *dup_mem(void *b, size_t c);
void *copy_of(char *s);
void break_sequence(void);
static int get_string(register char *string);
static int put_string(register char *s);
static int write_char(int c);
static int put_char(int c);
static int get_char(void);
void chat_send(register char *s);
/* static char *character(int c); */
void chat_expect(register char *s);
static char *clean(register char *s, int sending);
char *expect_strtok(char *, char *);
int chatmain(int, int, char *);
void *dup_mem(
void *b,
size_t c)
{
void *ans = malloc (c);
if (!ans)
return NULL;
memcpy(ans, b, c);
return ans;
}
void *copy_of(
char *s)
{
return dup_mem(s, strlen (s) + 1);
}
static char *getnextcommand(char *string,char *buff)
{
char *token;
int len;
token=strchr(string,'@');
if (token==NULL){
return NULL;
}
len=token-string;
if(len > 78 ){
len=78;
}
memcpy(buff,string,len);
buff[len]=0;
return(token+1);
}
int chatmain(int fd, int mode, char *pScript)
{
char arg[80];
char *script;
/* initialize exit code */
exit_code = 0;
ttyfd = fd;
script=pScript;
if ( debug ) {
dbglog("chat_main: %s\n", script);
}
/* get first expect string */
script = getnextcommand(script,arg);
while (( script != NULL ) && ( exit_code == 0 )) {
/* process the expect string */
chat_expect(arg);
if ( exit_code == 0 ) {
/* get the next send string */
script = getnextcommand(script,arg);
if ( script != NULL ) {
/* process the send string */
chat_send(arg);
/* get the next expect string */
script = getnextcommand(script,arg);
}
}
}
ttyfd = (int)-1;
return ( exit_code );
}
void break_sequence(void)
{
tcsendbreak(ttyfd, 0);
}
/*
* 'Clean up' this string.
*/
static char *clean(
char *s,
int sending ) /* set to 1 when sending (putting) this string. */
{
char temp[STR_LEN], env_str[STR_LEN], cur_chr;
register char *s1, *phchar;
int add_return = sending;
#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;
while (*s) {
cur_chr = *s++;
if (cur_chr == '^') {
cur_chr = *s++;
if (cur_chr == '\0') {
*s1++ = '^';
break;
}
cur_chr &= 0x1F;
if (cur_chr != 0) {
*s1++ = cur_chr;
}
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 != '\\') {
*s1++ = cur_chr;
continue;
}
cur_chr = *s++;
if (cur_chr == '\0') {
if (sending) {
*s1++ = '\\';
*s1++ = '\\';
}
break;
}
switch (cur_chr) {
case 'b':
*s1++ = '\b';
break;
case 'c':
if (sending && *s == '\0')
add_return = 0;
else
*s1++ = cur_chr;
break;
case '\\':
case 'K':
case 'p':
case 'd':
if (sending)
*s1++ = '\\';
*s1++ = cur_chr;
break;
case 'T':
if (sending && phone_num) {
for (phchar = phone_num; *phchar != '\0'; phchar++)
*s1++ = *phchar;
}
else {
*s1++ = '\\';
*s1++ = 'T';
}
break;
case 'U':
if (sending && phone_num2) {
for (phchar = phone_num2; *phchar != '\0'; phchar++)
*s1++ = *phchar;
}
else {
*s1++ = '\\';
*s1++ = 'U';
}
break;
case 'q':
quiet = 1;
break;
case 'r':
*s1++ = '\r';
break;
case 'n':
*s1++ = '\n';
break;
case 's':
*s1++ = ' ';
break;
case 't':
*s1++ = '\t';
break;
case 'N':
if (sending) {
*s1++ = '\\';
*s1++ = '\0';
}
else
*s1++ = 'N';
break;
case '$': /* ARI */
if (use_env) {
*s1++ = cur_chr;
break;
}
/* FALL THROUGH */
default:
if (isoctal (cur_chr)) {
cur_chr &= 0x07;
if (isoctal (*s)) {
cur_chr <<= 3;
cur_chr |= *s++ - '0';
if (isoctal (*s)) {
cur_chr <<= 3;
cur_chr |= *s++ - '0';
}
}
if (cur_chr != 0 || sending) {
if (sending && (cur_chr == '\\' || cur_chr == 0))
*s1++ = '\\';
*s1++ = cur_chr;
}
break;
}
if (sending)
*s1++ = '\\';
*s1++ = cur_chr;
break;
}
}
if (add_return)
*s1++ = '\r';
*s1++ = '\0'; /* guarantee closure */
*s1++ = '\0'; /* terminate the string */
return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */
}
/*
* A modified version of 'strtok'. This version skips \ sequences.
*/
char *expect_strtok (
char *s, char *term)
{
static char *str = "";
int escape_flag = 0;
char *result;
/*
* If a string was specified then do initial processing.
*/
if (s)
str = s;
/*
* If this is the escape flag then reset it and ignore the character.
*/
if (*str)
result = str;
else
result = (char *) 0;
while (*str) {
if (escape_flag) {
escape_flag = 0;
++str;
continue;
}
if (*str == '\\') {
++str;
escape_flag = 1;
continue;
}
/*
* If this is not in the termination string, continue.
*/
if (strchr (term, *str) == (char *) 0) {
++str;
continue;
}
/*
* This is the terminator. Mark the end of the string and stop.
*/
*str++ = '\0';
break;
}
return (result);
}
/*
* Process the expect string
*/
void chat_expect (
char *s)
{
char *expect;
char *reply;
if (strcmp(s, "HANGUP") == 0) {
++hup_next;
return;
}
if (strcmp(s, "ABORT") == 0) {
++abort_next;
return;
}
if (strcmp(s, "CLR_ABORT") == 0) {
++clear_abort_next;
return;
}
if (strcmp(s, "REPORT") == 0) {
++report_next;
return;
}
if (strcmp(s, "CLR_REPORT") == 0) {
++clear_report_next;
return;
}
if (strcmp(s, "TIMEOUT") == 0) {
++timeout_next;
return;
}
if (strcmp(s, "ECHO") == 0) {
++echo_next;
return;
}
if (strcmp(s, "SAY") == 0) {
++say_next;
return;
}
/*
* Fetch the expect and reply string.
*/
for (;;) {
expect = expect_strtok (s, "-");
s = (char *) 0;
if (expect == (char *) 0)
return;
reply = expect_strtok (s, "-");
/*
* Handle the expect string. If successful then exit.
*/
if (get_string (expect))
return;
/*
* If there is a sub-reply string then send it. Otherwise any condition
* is terminal.
*/
if (reply == (char *) 0 || exit_code != 3)
break;
chat_send (reply);
}
}
#if 0
/*
* Translate the input character to the appropriate string for printing
* the data.
*/
static char *character(
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);
}
#endif
/*
* process the reply string
*/
void chat_send (
char *s)
{
/* char file_data[STR_LEN]; */
if (say_next) {
say_next = 0;
s = clean(s, 1);
write(2, s, strlen(s));
free(s);
return;
}
if (hup_next) {
hup_next = 0;
return;
}
if (echo_next) {
echo_next = 0;
echo = (strcmp(s, "ON") == 0);
return;
}
if (abort_next) {
abort_next = 0;
if ( n_aborts < MAX_ABORTS ) {
char *s1;
s1 = clean(s, 0);
if (( strlen(s1) <= strlen(s) ) && ( strlen(s1) < sizeof(fail_buffer)))
abort_string[n_aborts++] = s1;
else
free(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;
}
if (timeout_next) {
timeout_next = 0;
timeout = atoi(s);
if (timeout <= 0){
timeout = DEFAULT_CHAT_TIMEOUT;
}
return;
}
if (strcmp(s, "EOT") == 0){
s = "^D\\c";
}
else{
if (strcmp(s, "BREAK") == 0){
s = "\\K\\c";
}
if (!put_string(s)) {
exit_code = 2;
}
}
}
static int get_char(void)
{
int status;
char c;
int tries=MAX_TIMEOUTS;
while(tries)
{
status = read(ttyfd, &c, 1);
switch (status) {
case 1:
return ((int)c & 0x7F);
default:
tries--;
}
}
return -1;
}
static int put_char(
int c)
{
char ch = c;
return(write(ttyfd, &ch, 1));
}
static int write_char (
int c)
{
if (put_char(c) < 1) {
return (0);
}
return (1);
}
static int put_string (
char *s)
{
char *out,*free_ptr=0;
quiet = 0;
out = free_ptr = clean(s, 1);
while (*out) {
register char c = *out++;
if (c != '\\') {
if (!write_char (c)){
free(free_ptr);
return 0;
}
continue;
}
c = *out++;
switch (c) {
case 'd':
sleep(1);
break;
case 'K':
break_sequence();
break;
case 'p':
#if 0 /* FIXME!!! */
usleep(10000); /* 1/100th of a second (arg is microseconds) */
#else
sleep(1);
#endif
break;
default:
if (!write_char (c)){
free(free_ptr);
return 0;
}
break;
}
}
free(free_ptr);
return (1);
}
/*
* 'Wait for' this string to appear on this file descriptor.
*/
static int get_string(
char *in_string)
{
int c, len, minlen;
register char *s = temp2, *end = s + STR_LEN;
char *logged = temp2;
char *string=0;
struct termios tios;
memset(temp2, 0, sizeof(temp2));
tcgetattr(ttyfd, &tios);
tios.c_cc[VMIN] = 0;
tios.c_cc[VTIME] = timeout*10/MAX_TIMEOUTS;
tcsetattr(ttyfd, TCSANOW, &tios);
string = clean(in_string, 0);
len = strlen(string);
minlen = (len > sizeof(fail_buffer)? len: sizeof(fail_buffer)) - 1;
if (len > STR_LEN) {
exit_code = 1;
free(string);
return 0;
}
if (len == 0) {
free(string);
return (1);
}
while ( (c = get_char()) >= 0) {
int n, abort_len;
if(c == '\n' || c == '\r'){
s = temp2;
*s=0;
}
else{
*s++ = c;
*s=0;
}
if (s - temp2 >= len &&
c == string[len - 1] &&
strncmp(s - len, string, len) == 0) {
free(string);
return (1);
}
for (n = 0; n < n_aborts; ++n) {
if (s - temp2 >= (abort_len = strlen(abort_string[n])) &&
strncmp(s - abort_len, abort_string[n], abort_len) == 0) {
exit_code = n + 4;
strcpy(fail_reason = fail_buffer, abort_string[n]);
free(string);
return (0);
}
}
if (s >= end) {
if (logged < s - minlen) {
logged = s;
}
s -= minlen;
memmove(temp2, s, minlen);
logged = temp2 + (logged - s);
s = temp2 + minlen;
}
}
exit_code = 3;
free(string);
return (0);
}

View File

@@ -1,343 +0,0 @@
/*
* demand.c - Support routines for demand-dialling.
*
* Copyright (c) 1993 The Australian National University.
* 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 the Australian National University. The name of the University
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
#ifdef PPP_FILTER
#include <net/if.h>
#include <net/bpf.h>
#include <pcap.h>
#endif
#include "pppd.h"
#include "fsm.h"
#include "ipcp.h"
#include "lcp.h"
static unsigned char *frame;
static int framelen;
static int framemax;
static int escape_flag;
static int flush_flag;
static int fcs;
struct packet {
int length;
struct packet *next;
unsigned char data[1];
};
struct packet *pend_q;
struct packet *pend_qtail;
static int active_packet(unsigned char *, int);
/*
* demand_conf - configure the interface for doing dial-on-demand.
*/
void
demand_conf(void)
{
int i;
struct protent *protp;
/* framemax = lcp_allowoptions[0].mru;
if (framemax < PPP_MRU) */
framemax = PPP_MRU;
framemax += PPP_HDRLEN + PPP_FCSLEN;
frame = malloc(framemax);
if (frame == NULL)
novm("demand frame");
framelen = 0;
pend_q = NULL;
escape_flag = 0;
flush_flag = 0;
fcs = PPP_INITFCS;
ppp_send_config(0, PPP_MRU, (uint32_t) 0, 0, 0);
ppp_recv_config(0, PPP_MRU, (uint32_t) 0, 0, 0);
#ifdef PPP_FILTER
set_filters(&pass_filter, &active_filter);
#endif
/*
* Call the demand_conf procedure for each protocol that's got one.
*/
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->enabled_flag && protp->demand_conf != NULL)
if (!((*protp->demand_conf)(0)))
die(1);
}
/*
* demand_block - set each network protocol to block further packets.
*/
void
demand_block(void)
{
int i;
struct protent *protp;
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->enabled_flag && protp->demand_conf != NULL)
sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
get_loop_output();
}
/*
* demand_discard - set each network protocol to discard packets
* with an error.
*/
void
demand_discard(void)
{
struct packet *pkt, *nextpkt;
int i;
struct protent *protp;
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->enabled_flag && protp->demand_conf != NULL)
sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
get_loop_output();
/* discard all saved packets */
for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
nextpkt = pkt->next;
free(pkt);
}
pend_q = NULL;
framelen = 0;
flush_flag = 0;
escape_flag = 0;
fcs = PPP_INITFCS;
}
/*
* demand_unblock - set each enabled network protocol to pass packets.
*/
void
demand_unblock(void)
{
int i;
struct protent *protp;
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->enabled_flag && protp->demand_conf != NULL)
sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
}
/*
* FCS lookup table as calculated by genfcstab.
*/
static u_short fcstab[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
/*
* loop_chars - process characters received from the loopback.
* Calls loop_frame when a complete frame has been accumulated.
* Return value is 1 if we need to bring up the link, 0 otherwise.
*/
int
loop_chars(
unsigned char *p,
int n)
{
int c, rv;
rv = 0;
for (; n > 0; --n) {
c = *p++;
if (c == PPP_FLAG) {
if (!escape_flag && !flush_flag
&& framelen > 2 && fcs == PPP_GOODFCS) {
framelen -= 2;
if (loop_frame(frame, framelen))
rv = 1;
}
framelen = 0;
flush_flag = 0;
escape_flag = 0;
fcs = PPP_INITFCS;
continue;
}
if (flush_flag)
continue;
if (escape_flag) {
c ^= PPP_TRANS;
escape_flag = 0;
} else if (c == PPP_ESCAPE) {
escape_flag = 1;
continue;
}
if (framelen >= framemax) {
flush_flag = 1;
continue;
}
frame[framelen++] = c;
fcs = PPP_FCS(fcs, c);
}
return rv;
}
/*
* loop_frame - given a frame obtained from the loopback,
* decide whether to bring up the link or not, and, if we want
* to transmit this frame later, put it on the pending queue.
* Return value is 1 if we need to bring up the link, 0 otherwise.
* We assume that the kernel driver has already applied the
* pass_filter, so we won't get packets it rejected.
* We apply the active_filter to see if we want this packet to
* bring up the link.
*/
int
loop_frame(
unsigned char *frame,
int len)
{
struct packet *pkt;
/* dbglog("from loop: %P", frame, len); */
if (len < PPP_HDRLEN)
return 0;
if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
return 0; /* shouldn't get any of these anyway */
if (!active_packet(frame, len))
return 0;
pkt = (struct packet *) malloc(sizeof(struct packet) + len);
if (pkt != NULL) {
pkt->length = len;
pkt->next = NULL;
memcpy(pkt->data, frame, len);
if (pend_q == NULL)
pend_q = pkt;
else
pend_qtail->next = pkt;
pend_qtail = pkt;
}
return 1;
}
/*
* demand_rexmit - Resend all those frames which we got via the
* loopback, now that the real serial link is up.
*/
void
demand_rexmit(
int proto)
{
struct packet *pkt, *prev, *nextpkt;
prev = NULL;
pkt = pend_q;
pend_q = NULL;
for (; pkt != NULL; pkt = nextpkt) {
nextpkt = pkt->next;
if (PPP_PROTOCOL(pkt->data) == proto) {
output(0, pkt->data, pkt->length);
free(pkt);
} else {
if (prev == NULL)
pend_q = pkt;
else
prev->next = pkt;
prev = pkt;
}
}
pend_qtail = prev;
if (prev != NULL)
prev->next = NULL;
}
/*
* Scan a packet to decide whether it is an "active" packet,
* that is, whether it is worth bringing up the link for.
*/
static int
active_packet(
unsigned char *p,
int len)
{
int proto, i;
struct protent *protp;
if (len < PPP_HDRLEN)
return 0;
proto = PPP_PROTOCOL(p);
#ifdef PPP_FILTER
if (active_filter.bf_len != 0
&& bpf_filter(active_filter.bf_insns, frame, len, len) == 0)
return 0;
#endif
for (i = 0; (protp = protocols[i]) != NULL; ++i) {
if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
if (!protp->enabled_flag)
return 0;
if (protp->active_pkt == NULL)
return 1;
return (*protp->active_pkt)(p, len);
}
}
return 0; /* not a supported protocol !!?? */
}

View File

@@ -1,760 +0,0 @@
/*
* fsm.c - {Link, IP} Control Protocol Finite State Machine.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*/
/*
* TODO:
* Randomize fsm id on link/init.
* Deal with variable outgoing MTU.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "pppd.h"
#include "fsm.h"
static void fsm_timeout(void *);
static void fsm_rconfreq(fsm *, u_char, u_char *, int);
static void fsm_rconfack(fsm *, int, u_char *, int);
static void fsm_rconfnakrej(fsm *, int, int, u_char *, int);
static void fsm_rtermreq(fsm *, int, u_char *, int);
static void fsm_rtermack(fsm *);
static void fsm_rcoderej(fsm *, u_char *, int);
static void fsm_sconfreq(fsm *, int);
#define PROTO_NAME(f) ((f)->callbacks->proto_name)
int peer_mru[NUM_PPP];
/*
* fsm_init - Initialize fsm.
*
* Initialize fsm state.
*/
void
fsm_init(
fsm *f)
{
f->state = INITIAL;
f->flags = 0;
f->id = 100; /* XXX Start with random id? */
f->timeouttime = DEFTIMEOUT;
f->maxconfreqtransmits = DEFMAXCONFREQS;
f->maxtermtransmits = DEFMAXTERMREQS;
f->maxnakloops = DEFMAXNAKLOOPS;
f->term_reason_len = 0;
}
/*
* fsm_lowerup - The lower layer is up.
*/
void
fsm_lowerup(
fsm *f)
{
switch( f->state ){
case INITIAL:
f->state = CLOSED;
break;
case STARTING:
if( f->flags & OPT_SILENT )
f->state = STOPPED;
else {
/* Send an initial configure-request */
fsm_sconfreq(f, 0);
f->state = REQSENT;
}
break;
default:
FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state));
}
}
/*
* fsm_lowerdown - The lower layer is down.
*
* Cancel all timeouts and inform upper layers.
*/
void
fsm_lowerdown(
fsm *f)
{
switch( f->state ){
case CLOSED:
f->state = INITIAL;
break;
case STOPPED:
f->state = STARTING;
if( f->callbacks->starting )
(*f->callbacks->starting)(f);
break;
case CLOSING:
f->state = INITIAL;
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
break;
case STOPPING:
case REQSENT:
case ACKRCVD:
case ACKSENT:
f->state = STARTING;
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
break;
case OPENED:
if( f->callbacks->down )
(*f->callbacks->down)(f);
f->state = STARTING;
break;
default:
FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state));
}
}
/*
* fsm_open - Link is allowed to come up.
*/
void
fsm_open(
fsm *f)
{
switch( f->state ){
case INITIAL:
f->state = STARTING;
if( f->callbacks->starting )
(*f->callbacks->starting)(f);
break;
case CLOSED:
if( f->flags & OPT_SILENT )
f->state = STOPPED;
else {
/* Send an initial configure-request */
fsm_sconfreq(f, 0);
f->state = REQSENT;
}
break;
case CLOSING:
f->state = STOPPING;
/* fall through */
case STOPPED:
case OPENED:
if( f->flags & OPT_RESTART ){
fsm_lowerdown(f);
fsm_lowerup(f);
}
break;
}
}
/*
* fsm_close - Start closing connection.
*
* Cancel timeouts and either initiate close or possibly go directly to
* the CLOSED state.
*/
void
fsm_close(
fsm *f,
char *reason)
{
f->term_reason = reason;
f->term_reason_len = (reason == NULL? 0: strlen(reason));
switch( f->state ){
case STARTING:
f->state = INITIAL;
break;
case STOPPED:
f->state = CLOSED;
break;
case STOPPING:
f->state = CLOSING;
break;
case REQSENT:
case ACKRCVD:
case ACKSENT:
case OPENED:
if( f->state != OPENED )
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
else if( f->callbacks->down )
(*f->callbacks->down)(f); /* Inform upper layers we're down */
/* Init restart counter, send Terminate-Request */
f->retransmits = f->maxtermtransmits;
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
(u_char *) f->term_reason, f->term_reason_len);
TIMEOUT(fsm_timeout, f, f->timeouttime);
--f->retransmits;
f->state = CLOSING;
break;
}
}
/*
* fsm_timeout - Timeout expired.
*/
static void
fsm_timeout(
void *arg)
{
fsm *f = (fsm *) arg;
switch (f->state) {
case CLOSING:
case STOPPING:
if( f->retransmits <= 0 ){
/*
* We've waited for an ack long enough. Peer probably heard us.
*/
f->state = (f->state == CLOSING)? CLOSED: STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
} else {
/* Send Terminate-Request */
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
(u_char *) f->term_reason, f->term_reason_len);
TIMEOUT(fsm_timeout, f, f->timeouttime);
--f->retransmits;
}
break;
case REQSENT:
case ACKRCVD:
case ACKSENT:
if (f->retransmits <= 0) {
warn("%s: timeout sending Config-Requests\n", PROTO_NAME(f));
f->state = STOPPED;
if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
(*f->callbacks->finished)(f);
} else {
/* Retransmit the configure-request */
if (f->callbacks->retransmit)
(*f->callbacks->retransmit)(f);
fsm_sconfreq(f, 1); /* Re-send Configure-Request */
if( f->state == ACKRCVD )
f->state = REQSENT;
}
break;
default:
FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state));
}
}
/*
* fsm_input - Input packet.
*/
void
fsm_input(
fsm *f,
u_char *inpacket,
int l)
{
u_char *inp;
u_char code, id;
int len;
/*
* Parse header (code, id and length).
* If packet too short, drop it.
*/
inp = inpacket;
if (l < HEADERLEN) {
FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len < HEADERLEN) {
FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol));
return;
}
if (len > l) {
FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol));
return;
}
len -= HEADERLEN; /* subtract header length */
if( f->state == INITIAL || f->state == STARTING ){
FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.",
f->protocol, f->state));
return;
}
/*
* Action depends on code.
*/
switch (code) {
case CONFREQ:
fsm_rconfreq(f, id, inp, len);
break;
case CONFACK:
fsm_rconfack(f, id, inp, len);
break;
case CONFNAK:
case CONFREJ:
fsm_rconfnakrej(f, code, id, inp, len);
break;
case TERMREQ:
fsm_rtermreq(f, id, inp, len);
break;
case TERMACK:
fsm_rtermack(f);
break;
case CODEREJ:
fsm_rcoderej(f, inp, len);
break;
default:
if( !f->callbacks->extcode
|| !(*f->callbacks->extcode)(f, code, id, inp, len) )
fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
break;
}
}
/*
* fsm_rconfreq - Receive Configure-Request.
*/
static void
fsm_rconfreq(
fsm *f,
u_char id,
u_char *inp,
int len)
{
int code, reject_if_disagree;
switch( f->state ){
case CLOSED:
/* Go away, we're closed */
fsm_sdata(f, TERMACK, id, NULL, 0);
return;
case CLOSING:
case STOPPING:
return;
case OPENED:
/* Go down and restart negotiation */
if( f->callbacks->down )
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
break;
case STOPPED:
/* Negotiation started by our peer */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
}
/*
* Pass the requested configuration options
* to protocol-specific code for checking.
*/
if (f->callbacks->reqci){ /* Check CI */
reject_if_disagree = (f->nakloops >= f->maxnakloops);
code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
} else if (len)
code = CONFREJ; /* Reject all CI */
else
code = CONFACK;
/* send the Ack, Nak or Rej to the peer */
fsm_sdata(f, code, id, inp, len);
if (code == CONFACK) {
if (f->state == ACKRCVD) {
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
f->state = OPENED;
if (f->callbacks->up)
(*f->callbacks->up)(f); /* Inform upper layers */
} else {
f->state = ACKSENT;
ppp_delay();
}
f->nakloops = 0;
} else {
/* we sent CONFACK or CONFREJ */
if (f->state != ACKRCVD)
f->state = REQSENT;
if( code == CONFNAK )
++f->nakloops;
}
}
/*
* fsm_rconfack - Receive Configure-Ack.
*/
static void
fsm_rconfack(
fsm *f,
int id,
u_char *inp,
int len)
{
if (id != f->reqid || f->seen_ack) /* Expected id? */
return; /* Nope, toss... */
if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
(len == 0)) ){
/* Ack is bad - ignore it */
error("Received bad configure-ack: %P", inp, len);
return;
}
f->seen_ack = 1;
switch (f->state) {
case CLOSED:
case STOPPED:
fsm_sdata(f, TERMACK, id, NULL, 0);
break;
case REQSENT:
f->state = ACKRCVD;
f->retransmits = f->maxconfreqtransmits;
break;
case ACKRCVD:
/* Huh? an extra valid Ack? oh well... */
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
fsm_sconfreq(f, 0);
f->state = REQSENT;
break;
case ACKSENT:
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
f->state = OPENED;
f->retransmits = f->maxconfreqtransmits;
if (f->callbacks->up)
(*f->callbacks->up)(f); /* Inform upper layers */
break;
case OPENED:
/* Go down and restart negotiation */
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
}
}
/*
* fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
*/
static void
fsm_rconfnakrej(
fsm *f,
int code, int id,
u_char *inp,
int len)
{
int (*proc)(fsm *, u_char *, int);
int ret;
if (id != f->reqid || f->seen_ack) /* Expected id? */
return; /* Nope, toss... */
proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
if (!proc || !(ret = proc(f, inp, len))) {
/* Nak/reject is bad - ignore it */
error("Received bad configure-nak/rej: %P", inp, len);
return;
}
f->seen_ack = 1;
switch (f->state) {
case CLOSED:
case STOPPED:
fsm_sdata(f, TERMACK, id, NULL, 0);
break;
case REQSENT:
case ACKSENT:
/* They didn't agree to what we wanted - try another request */
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
if (ret < 0)
f->state = STOPPED; /* kludge for stopping CCP */
else
fsm_sconfreq(f, 0); /* Send Configure-Request */
break;
case ACKRCVD:
/* Got a Nak/reject when we had already had an Ack?? oh well... */
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
fsm_sconfreq(f, 0);
f->state = REQSENT;
break;
case OPENED:
/* Go down and restart negotiation */
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
}
}
/*
* fsm_rtermreq - Receive Terminate-Req.
*/
static void
fsm_rtermreq(
fsm *f,
int id,
u_char *p,
int len)
{
switch (f->state) {
case ACKRCVD:
case ACKSENT:
f->state = REQSENT; /* Start over but keep trying */
break;
case OPENED:
if (len > 0) {
info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p);
} else
info("%s terminated by peer", PROTO_NAME(f));
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
f->retransmits = 0;
f->state = STOPPING;
TIMEOUT(fsm_timeout, f, f->timeouttime);
break;
}
fsm_sdata(f, TERMACK, id, NULL, 0);
}
/*
* fsm_rtermack - Receive Terminate-Ack.
*/
static void
fsm_rtermack(
fsm *f)
{
switch (f->state) {
case CLOSING:
UNTIMEOUT(fsm_timeout, f);
f->state = CLOSED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case STOPPING:
UNTIMEOUT(fsm_timeout, f);
f->state = STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case ACKRCVD:
f->state = REQSENT;
break;
case OPENED:
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0);
break;
}
}
/*
* fsm_rcoderej - Receive an Code-Reject.
*/
static void
fsm_rcoderej(
fsm *f,
u_char *inp,
int len)
{
u_char code, id;
if (len < HEADERLEN) {
FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!"));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id);
if( f->state == ACKRCVD )
f->state = REQSENT;
}
/*
* fsm_protreject - Peer doesn't speak this protocol.
*
* Treat this as a catastrophic error (RXJ-).
*/
void
fsm_protreject(
fsm *f)
{
switch( f->state ){
case CLOSING:
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
/* fall through */
case CLOSED:
f->state = CLOSED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case STOPPING:
case REQSENT:
case ACKRCVD:
case ACKSENT:
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
/* fall through */
case STOPPED:
f->state = STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case OPENED:
if( f->callbacks->down )
(*f->callbacks->down)(f);
/* Init restart counter, send Terminate-Request */
f->retransmits = f->maxtermtransmits;
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
(u_char *) f->term_reason, f->term_reason_len);
TIMEOUT(fsm_timeout, f, f->timeouttime);
--f->retransmits;
f->state = STOPPING;
break;
default:
FSMDEBUG(("%s: Protocol-reject event in state %d!",
PROTO_NAME(f), f->state));
}
}
/*
* fsm_sconfreq - Send a Configure-Request.
*/
static void
fsm_sconfreq(
fsm *f,
int retransmit)
{
u_char *outp;
int cilen;
if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
/* Not currently negotiating - reset options */
if( f->callbacks->resetci )
(*f->callbacks->resetci)(f);
f->nakloops = 0;
}
if( !retransmit ){
/* New request - reset retransmission counter, use new ID */
f->retransmits = f->maxconfreqtransmits;
f->reqid = ++f->id;
}
f->seen_ack = 0;
/*
* Make up the request packet
*/
outp = outpacket_buf + PPP_HDRLEN + HEADERLEN;
if( f->callbacks->cilen && f->callbacks->addci ){
cilen = (*f->callbacks->cilen)(f);
if( cilen > peer_mru[f->unit] - HEADERLEN )
cilen = peer_mru[f->unit] - HEADERLEN;
if (f->callbacks->addci)
(*f->callbacks->addci)(f, outp, &cilen);
} else
cilen = 0;
/* send the request to our peer */
fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
/* start the retransmit timer */
--f->retransmits;
TIMEOUT(fsm_timeout, f, f->timeouttime);
}
/*
* fsm_sdata - Send some data.
*
* Used for all packets sent to our peer by this module.
*/
void
fsm_sdata(
fsm *f,
u_char code, u_char id,
u_char *data,
int datalen)
{
u_char *outp;
int outlen;
/* Adjust length to be smaller than MTU */
outp = outpacket_buf;
if (datalen > peer_mru[f->unit] - HEADERLEN)
datalen = peer_mru[f->unit] - HEADERLEN;
if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)
BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
outlen = datalen + HEADERLEN;
MAKEHEADER(outp, f->protocol);
PUTCHAR(code, outp);
PUTCHAR(id, outp);
PUTSHORT(outlen, outp);
output(f->unit, outpacket_buf, outlen + PPP_HDRLEN);
}

View File

@@ -1,144 +0,0 @@
/*
* fsm.h - {Link, IP} Control Protocol Finite State Machine definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id$
*/
/*
* Packet header = Code, id, length.
*/
#define HEADERLEN 4
/*
* CP (LCP, IPCP, etc.) codes.
*/
#define CONFREQ 1 /* Configuration Request */
#define CONFACK 2 /* Configuration Ack */
#define CONFNAK 3 /* Configuration Nak */
#define CONFREJ 4 /* Configuration Reject */
#define TERMREQ 5 /* Termination Request */
#define TERMACK 6 /* Termination Ack */
#define CODEREJ 7 /* Code Reject */
/*
* Each FSM is described by an fsm structure and fsm callbacks.
*/
typedef struct fsm {
int unit; /* Interface unit number */
int protocol; /* Data Link Layer Protocol field value */
int state; /* State */
int flags; /* Contains option bits */
u_char id; /* Current id */
u_char reqid; /* Current request id */
u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */
int timeouttime; /* Timeout time in milliseconds */
int maxconfreqtransmits; /* Maximum Configure-Request transmissions */
int retransmits; /* Number of retransmissions left */
int maxtermtransmits; /* Maximum Terminate-Request transmissions */
int nakloops; /* Number of nak loops since last ack */
int maxnakloops; /* Maximum number of nak loops tolerated */
struct fsm_callbacks *callbacks; /* Callback routines */
char *term_reason; /* Reason for closing protocol */
int term_reason_len; /* Length of term_reason */
} fsm;
typedef struct fsm_callbacks {
void (*resetci) /* Reset our Configuration Information */
(fsm *);
int (*cilen) /* Length of our Configuration Information */
(fsm *);
void (*addci) /* Add our Configuration Information */
(fsm *, u_char *, int *);
int (*ackci) /* ACK our Configuration Information */
(fsm *, u_char *, int);
int (*nakci) /* NAK our Configuration Information */
(fsm *, u_char *, int);
int (*rejci) /* Reject our Configuration Information */
(fsm *, u_char *, int);
int (*reqci) /* Request peer's Configuration Information */
(fsm *, u_char *, int *, int);
void (*up) /* Called when fsm reaches OPENED state */
(fsm *);
void (*down) /* Called when fsm leaves OPENED state */
(fsm *);
void (*starting) /* Called when we want the lower layer */
(fsm *);
void (*finished) /* Called when we don't want the lower layer */
(fsm *);
void (*protreject) /* Called when Protocol-Reject received */
(int);
void (*retransmit) /* Retransmission is necessary */
(fsm *);
int (*extcode) /* Called when unknown code received */
(fsm *, int, int, u_char *, int);
char *proto_name; /* String name for protocol (for messages) */
} fsm_callbacks;
/*
* Link states.
*/
#define INITIAL 0 /* Down, hasn't been opened */
#define STARTING 1 /* Down, been opened */
#define CLOSED 2 /* Up, hasn't been opened */
#define STOPPED 3 /* Open, waiting for down event */
#define CLOSING 4 /* Terminating the connection, not open */
#define STOPPING 5 /* Terminating, but open */
#define REQSENT 6 /* We've sent a Config Request */
#define ACKRCVD 7 /* We've received a Config Ack */
#define ACKSENT 8 /* We've sent a Config Ack */
#define OPENED 9 /* Connection available */
/*
* Flags - indicate options controlling FSM operation
*/
#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
#define OPT_SILENT 4 /* Wait for peer to speak first */
/*
* Timeouts.
*/
#define DEFTIMEOUT 5 /* Timeout time in seconds */
#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
/*
* Prototypes
*/
void fsm_init(fsm *);
void fsm_lowerup(fsm *);
void fsm_lowerdown(fsm *);
void fsm_open(fsm *);
void fsm_close(fsm *, char *);
void fsm_input(fsm *, u_char *, int);
void fsm_protreject(fsm *);
void fsm_sdata(fsm *, u_char, u_char, u_char *, int);
/*
* Variables
*/
extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */

File diff suppressed because it is too large Load Diff

View File

@@ -1,73 +0,0 @@
/*
* ipcp.h - IP Control Protocol definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id$
*/
/*
* Options.
*/
#define CI_ADDRS 1 /* IP Addresses */
#define CI_COMPRESSTYPE 2 /* Compression Type */
#define CI_ADDR 3
#define CI_MS_DNS1 129 /* Primary DNS value */
#define CI_MS_WINS1 130 /* Primary WINS value */
#define CI_MS_DNS2 131 /* Secondary DNS value */
#define CI_MS_WINS2 132 /* Secondary WINS value */
#define MAX_STATES 16 /* from slcompress.h */
#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */
#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */
#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */
/* maxslot and slot number compression) */
#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/
#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */
/* compression option*/
typedef struct ipcp_options {
bool neg_addr; /* Negotiate IP Address? */
bool old_addrs; /* Use old (IP-Addresses) option? */
bool req_addr; /* Ask peer to send IP address? */
bool default_route; /* Assign default route through interface? */
bool proxy_arp; /* Make proxy ARP entry for peer? */
bool neg_vj; /* Van Jacobson Compression? */
bool old_vj; /* use old (short) form of VJ option? */
bool accept_local; /* accept peer's value for ouraddr */
bool accept_remote; /* accept peer's value for hisaddr */
bool req_dns1; /* Ask peer to send primary DNS address? */
bool req_dns2; /* Ask peer to send secondary DNS address? */
int vj_protocol; /* protocol value to use in VJ option */
int maxslotindex; /* values for RFC1332 VJ compression neg. */
bool cflag;
uint32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */
uint32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */
uint32_t winsaddr[2]; /* Primary and secondary MS WINS entries */
} ipcp_options;
extern fsm ipcp_fsm[];
extern ipcp_options ipcp_wantoptions[];
extern ipcp_options ipcp_gotoptions[];
extern ipcp_options ipcp_allowoptions[];
extern ipcp_options ipcp_hisoptions[];
char *ip_ntoa(uint32_t);
extern struct protent ipcp_protent;

File diff suppressed because it is too large Load Diff

View File

@@ -1,88 +0,0 @@
/*
* lcp.h - Link Control Protocol definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id$
*/
/*
* Options.
*/
#define CI_MRU 1 /* Maximum Receive Unit */
#define CI_ASYNCMAP 2 /* Async Control Character Map */
#define CI_AUTHTYPE 3 /* Authentication Type */
#define CI_QUALITY 4 /* Quality Protocol */
#define CI_MAGICNUMBER 5 /* Magic Number */
#define CI_PCOMPRESSION 7 /* Protocol Field Compression */
#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
#define CI_CALLBACK 13 /* callback */
/*
* LCP-specific packet types.
*/
#define PROTREJ 8 /* Protocol Reject */
#define ECHOREQ 9 /* Echo Request */
#define ECHOREP 10 /* Echo Reply */
#define DISCREQ 11 /* Discard Request */
#define CBCP_OPT 6 /* Use callback control protocol */
/*
* The state of options is described by an lcp_options structure.
*/
typedef struct lcp_options {
bool passive; /* Don't die if we don't get a response */
bool silent; /* Wait for the other end to start first */
bool restart; /* Restart vs. exit after close */
bool neg_mru; /* Negotiate the MRU? */
bool neg_asyncmap; /* Negotiate the async map? */
bool neg_upap; /* Ask for UPAP authentication? */
bool neg_chap; /* Ask for CHAP authentication? */
bool neg_magicnumber; /* Ask for magic number? */
bool neg_pcompression; /* HDLC Protocol Field Compression? */
bool neg_accompression; /* HDLC Address/Control Field Compression? */
bool neg_lqr; /* Negotiate use of Link Quality Reports */
bool neg_cbcp; /* Negotiate use of CBCP */
int mru; /* Value of MRU */
u_char chap_mdtype; /* which MD type (hashing algorithm) */
uint32_t asyncmap; /* Value of async map */
uint32_t magicnumber;
int numloops; /* Number of loops during magic number neg. */
uint32_t lqr_period; /* Reporting period for LQR 1/100ths second */
} lcp_options;
extern fsm lcp_fsm[];
extern lcp_options lcp_wantoptions[];
extern lcp_options lcp_gotoptions[];
extern lcp_options lcp_allowoptions[];
extern lcp_options lcp_hisoptions[];
extern uint32_t xmit_accm[][8];
#define DEFMRU 1500 /* Try for this */
#define MINMRU 128 /* No MRUs below this */
#define MAXMRU 16384 /* Normally limit MRU to this */
void lcp_open(int);
void lcp_close(int, char *);
void lcp_lowerup(int);
void lcp_lowerdown(int);
void lcp_sprotrej(int, u_char *, int); /* send protocol reject */
extern struct protent lcp_protent;
/* Default number of times we receive our magic number from the peer
before deciding the link is looped-back. */
#define DEFLOOPBACKFAIL 10

View File

@@ -1,54 +0,0 @@
/*
* magic.c - PPP Magic Number routines.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include "pppd.h"
#include "magic.h"
/*
* magic_init - Initialize the magic number generator.
*
* Attempts to compute a random number seed which will not repeat.
* The current method uses the current hostid, current process ID
* and current time, currently.
*/
void
magic_init(void)
{
long seed;
struct timeval t;
gettimeofday(&t, NULL);
seed = get_host_seed() ^ t.tv_sec ^ t.tv_usec ^ getpid();
srand48(seed);
}
/*
* magic - Returns the next magic number.
*/
uint32_t
magic(void)
{
return (uint32_t) mrand48();
}

View File

@@ -1,23 +0,0 @@
/*
* magic.h - PPP Magic Number definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id$
*/
void magic_init(void); /* Initialize the magic number generator */
uint32_t magic(void); /* Returns the next magic number */

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
/* $Id$ */
#define PATCHLEVEL 11
#define VERSION "2.3"
#define IMPLEMENTATION ""
#define DATE "23 December 1999"

View File

@@ -1,43 +0,0 @@
/*
* define path names
*
* $Id$
*/
#ifdef HAVE_PATHS_H
#include <paths.h>
#else
#ifndef _PATH_VARRUN
#define _PATH_VARRUN "/etc/ppp/"
#endif
#define _PATH_DEVNULL "/dev/null"
#endif
#ifndef _ROOT_PATH
#define _ROOT_PATH
#endif
#define _PATH_UPAPFILE _ROOT_PATH "/etc/ppp/pap-secrets"
#define _PATH_CHAPFILE _ROOT_PATH "/etc/ppp/chap-secrets"
#define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options"
#define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up"
#define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down"
#define _PATH_AUTHUP _ROOT_PATH "/etc/ppp/auth-up"
#define _PATH_AUTHDOWN _ROOT_PATH "/etc/ppp/auth-down"
#define _PATH_TTYOPT _ROOT_PATH "/etc/ppp/options."
#define _PATH_CONNERRS _ROOT_PATH "/etc/ppp/connect-errors"
#define _PATH_PEERFILES _ROOT_PATH "/etc/ppp/peers/"
#define _PATH_RESOLV _ROOT_PATH "/etc/ppp/resolv.conf"
#define _PATH_USEROPT ".ppprc"
#ifdef INET6
#define _PATH_IPV6UP _ROOT_PATH "/etc/ppp/ipv6-up"
#define _PATH_IPV6DOWN _ROOT_PATH "/etc/ppp/ipv6-down"
#endif
#ifdef IPX_CHANGE
#define _PATH_IPXUP _ROOT_PATH "/etc/ppp/ipx-up"
#define _PATH_IPXDOWN _ROOT_PATH "/etc/ppp/ipx-down"
#endif /* IPX_CHANGE */

File diff suppressed because it is too large Load Diff

View File

@@ -1,655 +0,0 @@
/*
* pppd.h - PPP daemon global declarations.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id$
*/
#ifndef __PPPD_H__
#define __PPPD_H__
#include <stdbool.h> /* bool */
#include <stdio.h> /* for FILE */
#include <limits.h> /* for NGROUPS_MAX */
#include <sys/param.h>
#include <sys/types.h> /* for uint32_t, if defined */
#include <sys/time.h> /* for struct timeval */
#include <net/ppp_defs.h>
#include <rtems/rtemsdialer.h>
#include <stdint.h>
#if defined(__STDC__)
#include <stdarg.h>
#define __V(x) x
#else
#include <varargs.h>
#define __V(x) (va_alist) va_dcl
#define const
#define volatile
#endif
#ifdef INET6
#include "eui64.h"
#endif
/*
* Limits.
*/
#define NUM_PPP 1 /* One PPP interface supported (per process) */
#define MAXWORDLEN 1024 /* max length of word in file (incl null) */
#define MAXARGS 1 /* max # args to a command */
#define MAXNAMELEN 256 /* max length of hostname or name for auth */
#define MAXSECRETLEN 256 /* max length of password or secret */
/*
* Option descriptor structure.
*/
enum opt_type {
o_special_noarg = 0,
o_special = 1,
o_bool,
o_int,
o_uint32,
o_string,
};
typedef struct {
char *name; /* name of the option */
enum opt_type type;
void *addr;
char *description;
uint32_t flags;
void *addr2;
int upper_limit;
int lower_limit;
} option_t;
/* Values for flags */
#define OPT_VALUE 0xffL /* mask for presupplied value */
#define OPT_HEX 0x100L /* int option is in hex */
#define OPT_NOARG 0x200L /* option doesn't take argument */
#define OPT_OR 0x400L /* OR in argument to value */
#define OPT_INC 0x800L /* increment value */
#define OPT_PRIV 0x1000L /* privileged option */
#define OPT_STATIC 0x2000L /* string option goes into static array */
#define OPT_LLIMIT 0x4000L /* check value against lower limit */
#define OPT_ULIMIT 0x8000L /* check value against upper limit */
#define OPT_LIMITS (OPT_LLIMIT|OPT_ULIMIT)
#define OPT_ZEROOK 0x10000L /* 0 value is OK even if not within limits */
#define OPT_NOINCR 0x20000L /* value mustn't be increased */
#define OPT_ZEROINF 0x40000L /* with OPT_NOINCR, 0 == infinity */
#define OPT_A2INFO 0x100000L /* addr2 -> option_info to update */
#define OPT_A2COPY 0x200000L /* addr2 -> second location to rcv value */
#define OPT_ENABLE 0x400000L /* use *addr2 as enable for option */
#define OPT_PRIVFIX 0x800000L /* can't be overridden if noauth */
#define OPT_PREPASS 0x1000000L /* do this opt in pre-pass to find device */
#define OPT_INITONLY 0x2000000L /* option can only be set in init phase */
#define OPT_DEVEQUIV 0x4000000L /* equiv to device name */
#define OPT_DEVNAM (OPT_PREPASS | OPT_INITONLY | OPT_DEVEQUIV)
#define OPT_VAL(x) ((x) & OPT_VALUE)
#ifndef GIDSET_TYPE
#define GIDSET_TYPE gid_t
#endif
/* Structure representing a list of permitted IP addresses. */
struct permitted_ip {
int permit; /* 1 = permit, 0 = forbid */
uint32_t base; /* match if (addr & mask) == base */
uint32_t mask; /* base and mask are in network byte order */
};
/*
* Unfortunately, the linux kernel driver uses a different structure
* for statistics from the rest of the ports.
* This structure serves as a common representation for the bits
* pppd needs.
*/
struct pppd_stats {
unsigned int bytes_in;
unsigned int bytes_out;
};
/* Used for storing a sequence of words. Usually malloced. */
struct wordlist {
struct wordlist *next;
char *word;
};
/*
* Global variables.
*/
extern int pppd_kill_link; /* Signal to terminate processing loop */
extern int hungup; /* Physical layer has disconnected */
extern int pppifunit; /* Interface unit number */
extern char ifname[]; /* Interface name */
extern int pppd_ttyfd; /* Serial device file descriptor */
extern char hostname[]; /* Our hostname */
extern u_char outpacket_buf[]; /* Buffer for outgoing packets */
extern int pppd_phase; /* Current state of link - see values below */
extern int baud_rate; /* Current link speed in bits/sec */
extern int redirect_stderr;/* Connector's stderr should go to file */
extern char peer_authname[];/* Authenticated name of peer */
extern int privileged; /* We were run by real-uid root */
extern int need_holdoff; /* Need holdoff period after link terminates */
extern char **script_env; /* Environment variables for scripts */
extern int detached; /* Have detached from controlling tty */
extern GIDSET_TYPE groups[NGROUPS_MAX]; /* groups the user is in */
extern int ngroups; /* How many groups valid in groups */
extern struct pppd_stats link_stats; /* byte/packet counts etc. for link */
extern int using_pty; /* using pty as device (notty or pty opt.) */
extern int log_to_fd; /* logging to this fd as well as syslog */
extern char *no_ppp_msg; /* message to print if ppp not in kernel */
extern volatile int pppd_status; /* exit status for pppd */
extern int devnam_fixed; /* can no longer change devnam */
extern int unsuccess; /* # unsuccessful connection attempts */
extern int do_callback; /* set if we want to do callback next */
extern int doing_callback; /* set if this is a callback */
extern dialerfp pppd_dialer; /* script dialer function callback */
/* Values for do_callback and doing_callback */
#define CALLBACK_DIALIN 1 /* we are expecting the call back */
#define CALLBACK_DIALOUT 2 /* we are dialling out to call back */
/*
* Variables set by command-line options.
*/
extern int debug; /* Debug flag */
extern int kdebugflag; /* Tell kernel to print debug messages */
extern int default_device; /* Using /dev/tty or equivalent */
extern char devnam[MAXPATHLEN]; /* Device name */
extern int crtscts; /* Use hardware flow control */
extern bool modem; /* Use modem control lines */
extern int inspeed; /* Input/Output speed requested */
extern uint32_t netmask; /* IP netmask to set on interface */
extern bool lockflag; /* Create lock file to lock the serial dev */
extern bool nodetach; /* Don't detach from controlling tty */
extern bool updetach; /* Detach from controlling tty when link up */
extern char *initializer; /* Script to initialize physical link */
extern char *connect_script; /* Script to establish physical link */
extern char *disconnect_script; /* Script to disestablish physical link */
extern char *welcomer; /* Script to welcome client after connection */
extern char *ptycommand; /* Command to run on other side of pty */
extern int maxconnect; /* Maximum connect time (seconds) */
extern char user[MAXNAMELEN];/* Our name for authenticating ourselves */
extern char passwd[MAXSECRETLEN]; /* Password for PAP or CHAP */
extern bool auth_required; /* Peer is required to authenticate */
extern bool persist; /* Reopen link after it goes down */
extern bool uselogin; /* Use /etc/passwd for checking PAP */
extern char our_name[MAXNAMELEN];/* Our name for authentication purposes */
extern char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
extern bool explicit_remote;/* remote_name specified with remotename opt */
extern bool demand; /* Do dial-on-demand */
extern char *ipparam; /* Extra parameter for ip up/down scripts */
extern bool cryptpap; /* Others' PAP passwords are encrypted */
extern int idle_time_limit;/* Shut down link if idle for this long */
extern int holdoff; /* Dead time before restarting */
extern bool holdoff_specified; /* true if user gave a holdoff value */
extern bool notty; /* Stdin/out is not a tty */
extern char *record_file; /* File to record chars sent/received */
extern bool sync_serial; /* Device is synchronous serial device */
extern int maxfail; /* Max # of unsuccessful connection attempts */
extern char linkname[MAXPATHLEN]; /* logical name for link */
extern bool tune_kernel; /* May alter kernel settings as necessary */
extern int connect_delay; /* Time to delay after connect script */
#ifdef PPP_FILTER
extern struct bpf_program pass_filter; /* Filter for pkts to pass */
extern struct bpf_program active_filter; /* Filter for link-active pkts */
#endif
#ifdef MSLANMAN
extern bool ms_lanman; /* Use LanMan password instead of NT */
/* Has meaning only with MS-CHAP challenges */
#endif
extern char *current_option; /* the name of the option being parsed */
extern int privileged_option; /* set iff the current option came from root */
extern char *option_source; /* string saying where the option came from */
/*
* Values for phase.
*/
#define PHASE_DEAD 0
#define PHASE_INITIALIZE 1
#define PHASE_SERIALCONN 2
#define PHASE_DORMANT 3
#define PHASE_ESTABLISH 4
#define PHASE_AUTHENTICATE 5
#define PHASE_CALLBACK 6
#define PHASE_NETWORK 7
#define PHASE_RUNNING 8
#define PHASE_TERMINATE 9
#define PHASE_DISCONNECT 10
#define PHASE_HOLDOFF 11
/*
* The following struct gives the addresses of procedures to call
* for a particular protocol.
*/
struct protent {
u_short protocol; /* PPP protocol number */
/* Initialization procedure */
void (*init)(int unit);
/* Process a received packet */
void (*input)(int unit, u_char *pkt, int len);
/* Process a received protocol-reject */
void (*protrej)(int unit);
/* Lower layer has come up */
void (*lowerup)(int unit);
/* Lower layer has gone down */
void (*lowerdown)(int unit);
/* Open the protocol */
void (*open)(int unit);
/* Close the protocol */
void (*close)(int unit, char *reason);
/* Print a packet in readable form */
int (*printpkt)(u_char *pkt, int len,
void (*printer)(void *, char *, ...),
void *arg);
/* Process a received data packet */
void (*datainput)(int unit, u_char *pkt, int len);
bool enabled_flag; /* 0 iff protocol is disabled */
char *name; /* Text name of protocol */
char *data_name; /* Text name of corresponding data protocol */
option_t *options; /* List of command-line options */
/* Check requested options, assign defaults */
void (*check_options)(void);
/* Configure interface for demand-dial */
int (*demand_conf)(int unit);
/* Say whether to bring up link for this pkt */
int (*active_pkt)(u_char *pkt, int len);
};
/* Table of pointers to supported protocols */
extern struct protent *protocols[];
/*
* Prototypes.
*/
/* Procedures exported from main.c. */
void die(int); /* Cleanup and exit */
void quit(void); /* like die(1) */
void novm(char *); /* Say we ran out of memory, and die */
void ppptimeout(void (*func)(void *), void *arg, int t);
/* Call func(arg) after t seconds */
void pppuntimeout(void (*func)(void *), void *arg);
/* Cancel call to func(arg) */
void update_link_stats(int); /* Get stats at link termination */
void new_phase(int); /* signal start of new phase */
/* Procedures exported from utils.c. */
void log_packet(u_char *, int, char *, int);
/* Format a packet and log it with syslog */
void print_string(void *, int, void (*) (void *, char *, ...),
void *); /* Format a string for output */
int slprintf(char *, int, char *, ...); /* sprintf++ */
int vslprintf(char *, int, char *, va_list); /* vsprintf++ */
size_t strlcpy(char *, const char *, size_t); /* safe strcpy */
size_t strlcat(char *, const char *, size_t); /* safe strncpy */
void pppd_dbglog(char *, ...); /* log a debug message */
void pppd_info(char *, ...); /* log an informational message */
void pppd_notice(char *, ...); /* log a notice-level message */
void pppd_warn(char *, ...); /* log a warning message */
void pppd_error(char *, ...); /* log an error message */
void pppd_fatal(char *, ...); /* log an error message and die(1) */
#define dbglog pppd_dbglog
#define info pppd_info
#define notice pppd_notice
#define warn pppd_warn
#define error pppd_error
#define fatal pppd_fatal
/* Procedures exported from auth.c */
void link_required(int); /* we are starting to use the link */
void link_terminated(int); /* we are finished with the link */
void link_down(int); /* the LCP layer has left the Opened state */
void link_established(int); /* the link is up; authenticate now */
void start_networks(void); /* start all the network control protos */
void np_up(int, int); /* a network protocol has come up */
void np_down(int, int); /* a network protocol has gone down */
void np_finished(int, int); /* a network protocol no longer needs link */
void auth_peer_fail(int, int);
/* peer failed to authenticate itself */
void auth_peer_success(int, int, char *, int);
/* peer successfully authenticated itself */
void auth_withpeer_fail(int, int);
/* we failed to authenticate ourselves */
void auth_withpeer_success(int, int);
/* we successfully authenticated ourselves */
int auth_check_options(void);
/* check authentication options supplied */
void auth_reset(int); /* check what secrets we have */
int check_passwd(int, char *, int, char *, int, char **);
/* Check peer-supplied username/password */
int get_secret(int, char *, char *, unsigned char *, int *, int);
/* get "secret" for chap */
int auth_ip_addr(int, uint32_t);
/* check if IP address is authorized */
int bad_ip_adrs(uint32_t);
/* check if IP address is unreasonable */
/* Procedures exported from demand.c */
void demand_conf(void); /* config interface(s) for demand-dial */
void demand_block(void); /* set all NPs to queue up packets */
void demand_unblock(void); /* set all NPs to pass packets */
void demand_discard(void); /* set all NPs to discard packets */
void demand_rexmit(int); /* retransmit saved frames for an NP */
int loop_chars(unsigned char *, int); /* process chars from loopback */
int loop_frame(unsigned char *, int); /* should we bring link up? */
/* Procedures exported from sys-*.c */
void sys_init(void); /* Do system-dependent initialization */
void sys_cleanup(void); /* Restore system state before exiting */
int sys_check_options(void); /* Check options specified */
void sys_close(void); /* Clean up in a child before execing */
int ppp_available(void); /* Test whether ppp kernel support exists */
int open_ppp_loopback(void); /* Open loopback for demand-dialling */
int establish_ppp(int); /* Turn serial port into a ppp interface */
void restore_loop(void); /* Transfer ppp unit back to loopback */
void disestablish_ppp(int); /* Restore port to normal operation */
void clean_check(void); /* Check if line was 8-bit clean */
void set_up_tty(int, int); /* Set up port's speed, parameters, etc. */
void restore_tty(int); /* Restore port's original parameters */
void setdtr(int, int); /* Raise or lower port's DTR line */
void output(int, u_char *, int); /* Output a PPP packet */
void wait_input(struct timeval *); /* Wait for input, with timeout */
void ppp_delay(void); /* delay task for a little while */
int read_packet(u_char *); /* Read PPP packet */
int get_loop_output(void); /* Read pkts from loopback */
void ppp_send_config(int, int, uint32_t, int, int);
/* Configure i/f transmit parameters */
void ppp_set_xaccm(int, ext_accm);
/* Set extended transmit ACCM */
void ppp_recv_config(int, int, uint32_t, int, int);
/* Configure i/f receive parameters */
int ccp_test(int, u_char *, int, int);
/* Test support for compression scheme */
void ccp_flags_set(int, int, int);
/* Set kernel CCP state */
int ccp_fatal_error(int); /* Test for fatal decomp error in kernel */
int get_idle_time(int, struct ppp_idle *);
/* Find out how long link has been idle */
int get_ppp_stats(int, struct pppd_stats *);
/* Return link statistics */
int sifvjcomp(int, int, int, int);
/* Configure VJ TCP header compression */
int sifup(int); /* Configure i/f up for one protocol */
int sifnpmode(int u, int proto, enum NPmode mode);
/* Set mode for handling packets for proto */
int sifdown(int); /* Configure i/f down for one protocol */
int sifaddr(int, uint32_t, uint32_t, uint32_t);
/* Configure IPv4 addresses for i/f */
int cifaddr(int, uint32_t, uint32_t);
/* Reset i/f IP addresses */
#ifdef INET6
int sif6addr(int, eui64_t, eui64_t);
/* Configure IPv6 addresses for i/f */
int cif6addr(int, eui64_t, eui64_t);
/* Remove an IPv6 address from i/f */
#endif
int sifdefaultroute(int, uint32_t, uint32_t);
/* Create default route through i/f */
int cifdefaultroute(int, uint32_t, uint32_t);
/* Delete default route through i/f */
int sifproxyarp(int, uint32_t);
/* Add proxy ARP entry for peer */
int cifproxyarp(int, uint32_t);
/* Delete proxy ARP entry for peer */
uint32_t GetMask(uint32_t); /* Get appropriate netmask for address */
int lock(char *); /* Create lock file for device */
int relock(int); /* Rewrite lock file with new pid */
void unlock(void); /* Delete previously-created lock file */
void logwtmp(const char *, const char *, const char *);
/* Write entry to wtmp file */
int get_host_seed(void); /* Get host-dependent random number seed */
int have_route_to(uint32_t); /* Check if route to addr exists */
#ifdef PPP_FILTER
int set_filters(struct bpf_program *pass, struct bpf_program *active);
/* Set filter programs in kernel */
#endif
#ifdef IPX_CHANGE
int sipxfaddr(int, unsigned long, unsigned char *);
int cipxfaddr(int);
#endif
/* Procedures exported from options.c */
int parse_args(int argc, char **argv);
/* Parse options from arguments given */
int options_from_file(char *filename, int must_exist, int check_prot,
int privileged);
/* Parse options from an options file */
int options_from_user(void); /* Parse options from user's .ppprc */
int options_for_tty(void); /* Parse options from /etc/ppp/options.tty */
int options_from_list(struct wordlist *, int privileged);
/* Parse options from a wordlist */
int getword(FILE *f, char *word, int *newlinep, char *filename);
/* Read a word from a file */
void option_error(char *fmt, ...);
/* Print an error message about an option */
int int_option(char *, int *);
/* Simplified number_option for decimal ints */
void add_options(option_t *); /* Add extra options */
/*
* This structure is used to store information about certain
* options, such as where the option value came from (/etc/ppp/options,
* command line, etc.) and whether it came from a privileged source.
*/
struct option_info {
int priv; /* was value set by sysadmin? */
char *source; /* where option came from */
};
extern struct option_info devnam_info;
extern struct option_info initializer_info;
extern struct option_info connect_script_info;
extern struct option_info disconnect_script_info;
extern struct option_info welcomer_info;
extern struct option_info ptycommand_info;
/*
* Hooks to enable plugins to change various things.
*/
extern int (*new_phase_hook)(int);
extern int (*idle_time_hook)(struct ppp_idle *);
extern int (*holdoff_hook)(void);
extern int (*pap_check_hook)(void);
extern int (*pap_auth_hook)(char *user, char *passwd/*, char **msgp,
struct wordlist **paddrs,
struct wordlist **popts*/);
extern void (*pap_logout_hook)(void);
extern int (*pap_passwd_hook)(char *user, char *passwd);
extern void (*ip_up_hook)(void);
extern void (*ip_down_hook)(void);
extern void (*auth_linkup_hook)(void);
extern void (*auth_linkdown_hook)(void);
/*
* Inline versions of get/put char/short/long.
* Pointer is advanced; we assume that both arguments
* are lvalues and will already be in registers.
* cp MUST be u_char *.
*/
#define GETCHAR(c, cp) { \
(c) = *(cp)++; \
}
#define PUTCHAR(c, cp) { \
*(cp)++ = (u_char) (c); \
}
#define GETSHORT(s, cp) { \
(s) = *(cp)++ << 8; \
(s) |= *(cp)++; \
}
#define PUTSHORT(s, cp) { \
*(cp)++ = (u_char) ((s) >> 8); \
*(cp)++ = (u_char) (s); \
}
#define GETLONG(l, cp) { \
(l) = *(cp)++ << 8; \
(l) |= *(cp)++; (l) <<= 8; \
(l) |= *(cp)++; (l) <<= 8; \
(l) |= *(cp)++; \
}
#define PUTLONG(l, cp) { \
*(cp)++ = (u_char) ((l) >> 24); \
*(cp)++ = (u_char) ((l) >> 16); \
*(cp)++ = (u_char) ((l) >> 8); \
*(cp)++ = (u_char) (l); \
}
#define INCPTR(n, cp) ((cp) += (n))
#define DECPTR(n, cp) ((cp) -= (n))
/*
* System dependent definitions for user-level 4.3BSD UNIX implementation.
*/
#define TIMEOUT(r, f, t) ppptimeout((r), (f), (t))
#define UNTIMEOUT(r, f) pppuntimeout((r), (f))
#define BCOPY(s, d, l) memcpy(d, s, l)
#define BZERO(s, n) memset(s, 0, n)
#define PRINTMSG(m, l) { info("Remote message: %0.*v", l, m); }
/*
* MAKEHEADER - Add Header fields to a packet.
*/
#define MAKEHEADER(p, t) { \
PUTCHAR(PPP_ALLSTATIONS, p); \
PUTCHAR(PPP_UI, p); \
PUTSHORT(t, p); }
/*
* Exit status values.
*/
#define EXIT_OK 0
#define EXIT_FATAL_ERROR 1
#define EXIT_OPTION_ERROR 2
#define EXIT_NOT_ROOT 3
#define EXIT_NO_KERNEL_SUPPORT 4
#define EXIT_USER_REQUEST 5
#define EXIT_LOCK_FAILED 6
#define EXIT_OPEN_FAILED 7
#define EXIT_CONNECT_FAILED 8
#define EXIT_PTYCMD_FAILED 9
#define EXIT_NEGOTIATION_FAILED 10
#define EXIT_PEER_AUTH_FAILED 11
#define EXIT_IDLE_TIMEOUT 12
#define EXIT_CONNECT_TIME 13
#define EXIT_CALLBACK 14
#define EXIT_PEER_DEAD 15
#define EXIT_HANGUP 16
#define EXIT_LOOPBACK 17
#define EXIT_INIT_FAILED 18
#define EXIT_AUTH_TOPEER_FAILED 19
/*
* Debug macros. Slightly useful for finding bugs in pppd, not particularly
* useful for finding out why your connection isn't being established.
*/
#ifdef DEBUGALL
#define DEBUGMAIN 1
#define DEBUGFSM 1
#define DEBUGLCP 1
#define DEBUGIPCP 1
#define DEBUGIPV6CP 1
#define DEBUGUPAP 1
#define DEBUGCHAP 1
#endif
#define DEBUGMAIN 1
#define DEBUGUPAP 1
#define DEBUGCHAP 1
#ifdef DEBUGMAIN
#define MAINDEBUG(x) if (debug) dbglog x
#else
#define MAINDEBUG(x)
#endif
#ifdef DEBUGSYS
#define SYSDEBUG(x) if (debug) dbglog x
#else
#define SYSDEBUG(x)
#endif
#ifdef DEBUGFSM
#define FSMDEBUG(x) if (debug) dbglog x
#else
#define FSMDEBUG(x)
#endif
#ifdef DEBUGLCP
#define LCPDEBUG(x) if (debug) dbglog x
#else
#define LCPDEBUG(x)
#endif
#ifdef DEBUGIPCP
#define IPCPDEBUG(x) if (debug) dbglog x
#else
#define IPCPDEBUG(x)
#endif
#ifdef DEBUGIPV6CP
#define IPV6CPDEBUG(x) if (debug) dbglog x
#else
#define IPV6CPDEBUG(x)
#endif
#ifdef DEBUGUPAP
#define UPAPDEBUG(x) if (debug) dbglog x
#else
#define UPAPDEBUG(x)
#endif
#ifdef DEBUGCHAP
#define CHAPDEBUG(x) if (debug) dbglog x
#else
#define CHAPDEBUG(x)
#endif
#ifdef DEBUGIPXCP
#define IPXCPDEBUG(x) if (debug) dbglog x
#else
#define IPXCPDEBUG(x)
#endif
#ifndef SIGTYPE
#if defined(sun) || defined(SYSV) || defined(POSIX_SOURCE)
#define SIGTYPE void
#else
#define SIGTYPE int
#endif /* defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) */
#endif /* SIGTYPE */
#endif /* __PPP_H__ */

View File

@@ -1,892 +0,0 @@
/*
* main.c - Point-to-Point Protocol main module
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <pwd.h>
#include <setjmp.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <rtems.h>
#include <rtems/rtems_bsdnet.h>
#include "pppd.h"
#include "magic.h"
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
#ifdef INET6
#include "ipv6cp.h"
#endif
#include "upap.h"
#include "chap.h"
#include "ccp.h"
#include "pathnames.h"
#include "patchlevel.h"
#include <rtems/rtemsdialer.h>
#ifdef CBCP_SUPPORT
#include "cbcp.h"
#endif
#ifdef IPX_CHANGE
#include "ipxcp.h"
#endif /* IPX_CHANGE */
#ifdef AT_CHANGE
#include "atcp.h"
#endif
/* interface vars */
char ifname[32]; /* Interface name */
int pppifunit; /* Interface unit number */
char hostname[MAXNAMELEN]; /* Our hostname */
static char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */
int pppd_ttyfd; /* Serial port file descriptor */
int baud_rate; /* Actual bits/second for serial device */
int hungup; /* terminal has been hung up */
int privileged; /* we're running as real uid root */
int need_holdoff; /* need holdoff period before restarting */
int detached; /* have detached from terminal */
struct stat devstat; /* result of stat() on devnam */
int prepass = 0; /* doing prepass to find device name */
int devnam_fixed; /* set while in options.ttyxx file */
volatile int pppd_status; /* exit status for pppd */
int unsuccess; /* # unsuccessful connection attempts */
int do_callback; /* != 0 if we should do callback next */
int doing_callback; /* != 0 if we are doing callback */
char *callback_script; /* script for doing callback */
dialerfp pppd_dialer;
int (*holdoff_hook)(void) = NULL;
int (*new_phase_hook)(int) = NULL;
static int fd_ppp = -1; /* fd for talking PPP */
static int pty_master; /* fd for master side of pty */
static int pty_slave; /* fd for slave side of pty */
static int real_ttyfd; /* fd for actual serial port (not pty) */
int pppd_phase; /* where the link is at */
int pppd_kill_link;
int open_ccp_flag;
char **script_env; /* Env. variable values for scripts */
int s_env_nalloc; /* # words avail at script_env */
u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
static struct timeval start_time; /* Time when link was started. */
struct pppd_stats link_stats;
int link_connect_time;
int link_stats_valid;
/* Prototypes for procedures local to this file. */
static void cleanup(void);
static void close_tty(void);
static void get_input(void);
static void calltimeout(void);
static struct timeval *timeleft(struct timeval *);
static void holdoff_end(void *);
static int device_script(int, int, char *);
extern char *ttyname(int);
extern char *getlogin(void);
int pppdmain(int, char *[]);
/*
* PPP Data Link Layer "protocol" table.
* One entry per supported protocol.
* The last entry must be NULL.
*/
struct protent *protocols[] = {
&lcp_protent,
&pap_protent,
&chap_protent,
#ifdef CBCP_SUPPORT
&cbcp_protent,
#endif
&ipcp_protent,
#ifdef INET6
&ipv6cp_protent,
#endif
&ccp_protent,
#ifdef IPX_CHANGE
&ipxcp_protent,
#endif
#ifdef AT_CHANGE
&atcp_protent,
#endif
NULL
};
int
pppdmain(
int argc,
char *argv[])
{
int i, fdflags, t;
char *connector;
struct timeval timo;
struct protent *protp;
new_phase(PHASE_INITIALIZE);
script_env = NULL;
hostname[MAXNAMELEN-1] = 0;
privileged = 1;
privileged_option = 1;
/*
* Initialize magic number generator now so that protocols may
* use magic numbers in initialization.
*/
magic_init();
#ifdef XXX_XXX
/* moved code the the rtems_pppd_reset_options function */
/*
* Initialize to the standard option set, then parse, in order,
* the system options file, the user's options file,
* the tty's options file, and the command line arguments.
*/
for (i = 0; (protp = protocols[i]) != NULL; ++i)
(*protp->init)(0);
#endif
if (!ppp_available()) {
option_error(no_ppp_msg);
return(EXIT_NO_KERNEL_SUPPORT);
}
/*
* Check that the options given are valid and consistent.
*/
if (!sys_check_options()) {
return(EXIT_OPTION_ERROR);
}
if (!auth_check_options()) {
return(EXIT_OPTION_ERROR);
}
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->check_options != NULL)
(*protp->check_options)();
/* default holdoff to 0 if no connect script has been given */
if (connect_script == 0 && !holdoff_specified)
holdoff = 0;
if (default_device)
nodetach = 1;
/*
* Initialize system-dependent stuff.
*/
sys_init();
/* if (debug)
setlogmask(LOG_UPTO(LOG_DEBUG));
*/
do_callback = 0;
for (;;) {
need_holdoff = 1;
pppd_ttyfd = -1;
real_ttyfd = -1;
pppd_status = EXIT_OK;
++unsuccess;
doing_callback = do_callback;
do_callback = 0;
new_phase(PHASE_SERIALCONN);
/*
* Get a pty master/slave pair if the pty, notty, or record
* options were specified.
*/
strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
pty_master = -1;
pty_slave = -1;
/*
* Open the serial device and set it up to be the ppp interface.
* First we open it in non-blocking mode so we can set the
* various termios flags appropriately. If we aren't dialling
* out and we want to use the modem lines, we reopen it later
* in order to wait for the carrier detect signal from the modem.
*/
hungup = 0;
pppd_kill_link = 0;
connector = doing_callback? callback_script: connect_script;
if (devnam[0] != 0) {
for (;;) {
/* If the user specified the device name, become the
user before opening it. */
int err;
pppd_ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0);
err = errno;
if (pppd_ttyfd >= 0) {
break;
}
errno = err;
if (err != EINTR) {
error("Failed to open %s: %m", devnam);
pppd_status = EXIT_OPEN_FAILED;
}
if (!persist || err != EINTR)
goto fail;
}
if ((fdflags = fcntl(pppd_ttyfd, F_GETFL)) == -1
|| fcntl(pppd_ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
warn("Couldn't reset non-blocking mode on device: %m");
/*
* Set line speed, flow control, etc.
* If we have a non-null connection or initializer script,
* on most systems we set CLOCAL for now so that we can talk
* to the modem before carrier comes up. But this has the
* side effect that we might miss it if CD drops before we
* get to clear CLOCAL below. On systems where we can talk
* successfully to the modem with CLOCAL clear and CD down,
* we could clear CLOCAL at this point.
*/
set_up_tty(pppd_ttyfd, ((connector != NULL && connector[0] != 0)
|| initializer != NULL));
real_ttyfd = pppd_ttyfd;
}
/* run connection script */
if ((connector && connector[0]) || initializer) {
if (real_ttyfd != -1) {
/* XXX do this if doing_callback == CALLBACK_DIALIN? */
if (!default_device && modem) {
setdtr(real_ttyfd, 0); /* in case modem is off hook */
sleep(1);
setdtr(real_ttyfd, 1);
}
}
if (initializer && initializer[0]) {
if (device_script(pppd_ttyfd, DIALER_INIT, initializer) < 0) {
error("Initializer script failed");
pppd_status = EXIT_INIT_FAILED;
goto fail;
}
if (pppd_kill_link)
goto disconnect;
info("Serial port initialized.");
}
if (connector && connector[0]) {
if (device_script(pppd_ttyfd, DIALER_CONNECT, connector) < 0) {
error("Connect script failed");
pppd_status = EXIT_CONNECT_FAILED;
goto fail;
}
if (pppd_kill_link)
goto disconnect;
info("Serial connection established.");
}
/* set line speed, flow control, etc.;
clear CLOCAL if modem option */
if (real_ttyfd != -1)
set_up_tty(real_ttyfd, 0);
if (doing_callback == CALLBACK_DIALIN)
connector = NULL;
}
/* reopen tty if necessary to wait for carrier */
if (connector == NULL && modem && devnam[0] != 0) {
for (;;) {
if ((i = open(devnam, O_RDWR)) >= 0)
break;
if (errno != EINTR) {
error("Failed to reopen %s: %m", devnam);
pppd_status = EXIT_OPEN_FAILED;
}
if (!persist || errno != EINTR || hungup || pppd_kill_link)
goto fail;
}
close(i);
}
info("Serial connection established.");
sleep(1);
/* run welcome script, if any */
if (welcomer && welcomer[0]) {
if (device_script(pppd_ttyfd, DIALER_WELCOME, welcomer) < 0)
warn("Welcome script failed");
}
/* set up the serial device as a ppp interface */
fd_ppp = establish_ppp(pppd_ttyfd);
if (fd_ppp < 0) {
pppd_status = EXIT_FATAL_ERROR;
goto disconnect;
}
if (!demand) {
info("Using interface ppp%d", pppifunit);
slprintf(ifname, sizeof(ifname), "ppp%d", pppifunit);
}
/*
* Start opening the connection and wait for
* incoming events (reply, timeout, etc.).
*/
notice("Connect: %s <--> %s", ifname, ppp_devnam);
gettimeofday(&start_time, NULL);
lcp_lowerup(0);
lcp_open(0); /* Start protocol */
open_ccp_flag = 0;
pppd_status = EXIT_NEGOTIATION_FAILED;
new_phase(PHASE_ESTABLISH);
while (pppd_phase != PHASE_DEAD) {
wait_input(timeleft(&timo));
calltimeout();
get_input();
if (pppd_kill_link) {
lcp_close(0, "User request");
pppd_kill_link = 0;
}
if (open_ccp_flag) {
if (pppd_phase == PHASE_NETWORK || pppd_phase == PHASE_RUNNING) {
ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
(*ccp_protent.open)(0);
}
open_ccp_flag = 0;
}
}
/*
* If we may want to bring the link up again, transfer
* the ppp unit back to the loopback. Set the
* real serial device back to its normal mode of operation.
*/
clean_check();
if (demand)
restore_loop();
disestablish_ppp(pppd_ttyfd);
fd_ppp = -1;
if (!hungup)
lcp_lowerdown(0);
/*
* Run disconnector script, if requested.
* XXX we may not be able to do this if the line has hung up!
*/
disconnect:
if (disconnect_script && !hungup) {
new_phase(PHASE_DISCONNECT);
if (real_ttyfd >= 0)
set_up_tty(real_ttyfd, 1);
if (device_script(pppd_ttyfd, DIALER_DISCONNECT, disconnect_script) < 0) {
warn("disconnect script failed");
} else {
info("Serial link disconnected.");
}
}
fail:
if (pty_master >= 0)
close(pty_master);
if (pty_slave >= 0)
close(pty_slave);
if (real_ttyfd >= 0)
close_tty();
if (!persist || (maxfail > 0 && unsuccess >= maxfail))
break;
pppd_kill_link = 0;
if (demand)
demand_discard();
t = need_holdoff? holdoff: 0;
if (holdoff_hook)
t = (*holdoff_hook)();
if (t > 0) {
new_phase(PHASE_HOLDOFF);
TIMEOUT(holdoff_end, NULL, t);
do {
wait_input(timeleft(&timo));
calltimeout();
if (pppd_kill_link) {
pppd_kill_link = 0;
new_phase(PHASE_DORMANT); /* allow signal to end holdoff */
}
} while (pppd_phase == PHASE_HOLDOFF);
if (!persist)
break;
}
}
die(pppd_status);
return pppd_status;
}
/*
* holdoff_end - called via a timeout when the holdoff period ends.
*/
static void
holdoff_end(
void *arg)
{
new_phase(PHASE_DORMANT);
}
/* List of protocol names, to make our messages a little more informative. */
struct protocol_list {
u_short proto;
const char *name;
} protocol_list[] = {
{ 0x21, "IP" },
{ 0x23, "OSI Network Layer" },
{ 0x25, "Xerox NS IDP" },
{ 0x27, "DECnet Phase IV" },
{ 0x29, "Appletalk" },
{ 0x2b, "Novell IPX" },
{ 0x2d, "VJ compressed TCP/IP" },
{ 0x2f, "VJ uncompressed TCP/IP" },
{ 0x31, "Bridging PDU" },
{ 0x33, "Stream Protocol ST-II" },
{ 0x35, "Banyan Vines" },
{ 0x39, "AppleTalk EDDP" },
{ 0x3b, "AppleTalk SmartBuffered" },
{ 0x3d, "Multi-Link" },
{ 0x3f, "NETBIOS Framing" },
{ 0x41, "Cisco Systems" },
{ 0x43, "Ascom Timeplex" },
{ 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" },
{ 0x47, "DCA Remote Lan" },
{ 0x49, "Serial Data Transport Protocol (PPP-SDTP)" },
{ 0x4b, "SNA over 802.2" },
{ 0x4d, "SNA" },
{ 0x4f, "IP6 Header Compression" },
{ 0x6f, "Stampede Bridging" },
{ 0xfb, "single-link compression" },
{ 0xfd, "1st choice compression" },
{ 0x0201, "802.1d Hello Packets" },
{ 0x0203, "IBM Source Routing BPDU" },
{ 0x0205, "DEC LANBridge100 Spanning Tree" },
{ 0x0231, "Luxcom" },
{ 0x0233, "Sigma Network Systems" },
{ 0x8021, "Internet Protocol Control Protocol" },
{ 0x8023, "OSI Network Layer Control Protocol" },
{ 0x8025, "Xerox NS IDP Control Protocol" },
{ 0x8027, "DECnet Phase IV Control Protocol" },
{ 0x8029, "Appletalk Control Protocol" },
{ 0x802b, "Novell IPX Control Protocol" },
{ 0x8031, "Bridging NCP" },
{ 0x8033, "Stream Protocol Control Protocol" },
{ 0x8035, "Banyan Vines Control Protocol" },
{ 0x803d, "Multi-Link Control Protocol" },
{ 0x803f, "NETBIOS Framing Control Protocol" },
{ 0x8041, "Cisco Systems Control Protocol" },
{ 0x8043, "Ascom Timeplex" },
{ 0x8045, "Fujitsu LBLB Control Protocol" },
{ 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" },
{ 0x8049, "Serial Data Control Protocol (PPP-SDCP)" },
{ 0x804b, "SNA over 802.2 Control Protocol" },
{ 0x804d, "SNA Control Protocol" },
{ 0x804f, "IP6 Header Compression Control Protocol" },
{ 0x006f, "Stampede Bridging Control Protocol" },
{ 0x80fb, "Single Link Compression Control Protocol" },
{ 0x80fd, "Compression Control Protocol" },
{ 0xc021, "Link Control Protocol" },
{ 0xc023, "Password Authentication Protocol" },
{ 0xc025, "Link Quality Report" },
{ 0xc027, "Shiva Password Authentication Protocol" },
{ 0xc029, "CallBack Control Protocol (CBCP)" },
{ 0xc081, "Container Control Protocol" },
{ 0xc223, "Challenge Handshake Authentication Protocol" },
{ 0xc281, "Proprietary Authentication Protocol" },
{ 0, NULL },
};
/*
* protocol_name - find a name for a PPP protocol.
*/
static const char *
protocol_name(
int proto)
{
struct protocol_list *lp;
for (lp = protocol_list; lp->proto != 0; ++lp)
if (proto == lp->proto)
return lp->name;
return NULL;
}
/*
* get_input - called when incoming data is available.
*/
static void
get_input(void)
{
int len, i;
u_char *p;
u_short protocol;
struct protent *protp;
p = inpacket_buf; /* point to beginning of packet buffer */
len = read_packet(inpacket_buf);
if (len < 0)
return;
if (len == 0) {
notice("Modem hangup");
hungup = 1;
pppd_status = EXIT_HANGUP;
lcp_lowerdown(0); /* serial link is no longer available */
link_terminated(0);
return;
}
if (debug /*&& (debugflags & DBG_INPACKET)*/)
dbglog("rcvd %P", p, len);
if (len < PPP_HDRLEN) {
MAINDEBUG(("io(): Received short packet."));
return;
}
p += 2; /* Skip address and control */
GETSHORT(protocol, p);
len -= PPP_HDRLEN;
/*
* Toss all non-LCP packets unless LCP is OPEN.
*/
if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
MAINDEBUG(("get_input: Received non-LCP packet when LCP not open."));
return;
}
/*
* Until we get past the authentication phase, toss all packets
* except LCP, LQR and authentication packets.
*/
if (pppd_phase <= PHASE_AUTHENTICATE
&& !(protocol == PPP_LCP || protocol == PPP_LQR
|| protocol == PPP_PAP || protocol == PPP_CHAP)) {
MAINDEBUG(("get_input: discarding proto 0x%x in phase %d",
protocol, pppd_phase));
return;
}
/*
* Upcall the proper protocol input routine.
*/
for (i = 0; (protp = protocols[i]) != NULL; ++i) {
if (protp->protocol == protocol && protp->enabled_flag) {
(*protp->input)(0, p, len);
return;
}
if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
&& protp->datainput != NULL) {
(*protp->datainput)(0, p, len);
return;
}
}
if (debug) {
const char *pname = protocol_name(protocol);
if (pname != NULL)
warn("Unsupported protocol '%s' (0x%x) received", pname, protocol);
else
warn("Unsupported protocol 0x%x received", protocol);
}
lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
return;
}
/*
* new_phase - signal the start of a new phase of pppd's operation.
*/
void
new_phase(
int p)
{
pppd_phase = p;
if (new_phase_hook)
(*new_phase_hook)(p);
}
/*
* die - clean up state and exit with the specified status.
*/
void
die(
int status)
{
cleanup();
}
/*
* cleanup - restore anything which needs to be restored before we exit
*/
/* ARGSUSED */
static void
cleanup(void)
{
sys_cleanup();
if (fd_ppp >= 0)
disestablish_ppp(pppd_ttyfd);
if (real_ttyfd >= 0)
close_tty();
sys_close();
}
/*
* close_tty - restore the terminal device and close it.
*/
static void
close_tty(void)
{
/* drop dtr to hang up */
if (!default_device && modem) {
setdtr(real_ttyfd, 0);
/*
* This sleep is in case the serial port has CLOCAL set by default,
* and consequently will reassert DTR when we close the device.
*/
sleep(1);
}
restore_tty(real_ttyfd);
close(real_ttyfd);
real_ttyfd = -1;
}
/*
* update_link_stats - get stats at link termination.
*/
void
update_link_stats(
int u)
{
struct timeval now;
char numbuf[32];
if (!get_ppp_stats(u, &link_stats)
|| gettimeofday(&now, NULL) < 0)
return;
link_connect_time = now.tv_sec - start_time.tv_sec;
link_stats_valid = 1;
slprintf(numbuf, sizeof(numbuf), "%d", link_connect_time);
slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_out);
slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_in);
}
struct callout {
struct timeval c_time; /* time at which to call routine */
void *c_arg; /* argument to routine */
void (*c_func)(void *); /* routine */
struct callout *c_next;
};
static struct callout *callout = NULL; /* Callout list */
static struct timeval timenow; /* Current time */
/*
* timeout - Schedule a timeout.
*
* Note that this timeout takes the number of seconds, NOT hz (as in
* the kernel).
*/
void
ppptimeout(
void (*func)(void *),
void *arg,
int time)
{
struct callout *newp, *p, **pp;
MAINDEBUG(("Timeout %p:%p in %d seconds.", func, arg, time));
/*
* Allocate timeout.
*/
if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL)
fatal("Out of memory in timeout()!");
newp->c_arg = arg;
newp->c_func = func;
gettimeofday(&timenow, NULL);
newp->c_time.tv_sec = timenow.tv_sec + time;
newp->c_time.tv_usec = timenow.tv_usec;
/*
* Find correct place and link it in.
*/
for (pp = &callout; (p = *pp); pp = &p->c_next)
if (newp->c_time.tv_sec < p->c_time.tv_sec
|| (newp->c_time.tv_sec == p->c_time.tv_sec
&& newp->c_time.tv_usec < p->c_time.tv_usec))
break;
newp->c_next = p;
*pp = newp;
}
/*
* untimeout - Unschedule a timeout.
*/
void
pppuntimeout(
void (*func)(void *),
void *arg)
{
struct callout **copp, *freep;
MAINDEBUG(("Untimeout %p:%p.", func, arg));
/*
* Find first matching timeout and remove it from the list.
*/
for (copp = &callout; (freep = *copp); copp = &freep->c_next)
if (freep->c_func == func && freep->c_arg == arg) {
*copp = freep->c_next;
free((char *) freep);
break;
}
}
/*
* calltimeout - Call any timeout routines which are now due.
*/
static void
calltimeout(void)
{
struct callout *p;
while (callout != NULL) {
p = callout;
if (gettimeofday(&timenow, NULL) < 0)
fatal("Failed to get time of day: %m");
if (!(p->c_time.tv_sec < timenow.tv_sec
|| (p->c_time.tv_sec == timenow.tv_sec
&& p->c_time.tv_usec <= timenow.tv_usec)))
break; /* no, it's not time yet */
callout = p->c_next;
(*p->c_func)(p->c_arg);
free((char *) p);
}
}
/*
* timeleft - return the length of time until the next timeout is due.
*/
static struct timeval *
timeleft(
struct timeval *tvp)
{
if (callout == NULL)
return NULL;
gettimeofday(&timenow, NULL);
tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
if (tvp->tv_usec < 0) {
tvp->tv_usec += 1000000;
tvp->tv_sec -= 1;
}
if (tvp->tv_sec < 0)
tvp->tv_sec = tvp->tv_usec = 0;
return tvp;
}
/*
* device_script - run a program to talk to the serial device
* (e.g. to run the connector or disconnector script).
*/
static int device_script(int fd, int mode, char *program)
{
int iReturn = -1;
char pScript[128];
/* copyt script into temporary location */
strcpy(pScript, program);
/* check to see if dialer was initialized */
if ( !pppd_dialer ) {
/* set default dialer to chatmain */
pppd_dialer = chatmain;
}
/* check to see if dialer is set */
if ( pppd_dialer ) {
/* call the dialer */
iReturn = (*pppd_dialer)(fd, mode, program);
}
return ( -iReturn );
}
/*
* novm - log an error message saying we ran out of memory, and die.
*/
void
novm(
char *msg)
{
fatal("Virtual memory exhausted allocating %s\n", msg);
}

View File

@@ -1,228 +0,0 @@
/*
* COPYRIGHT (c) 2001, Michael Siers <mikes@poliac.com>.
* Poliac Research, Burnsville, Minnesota USA.
* COPYRIGHT (c) 2001, On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*
* $Id$
*/
#include <rtems.h>
#include <rtems/rtems_bsdnet.h>
#include "pppd.h"
#include <rtems/rtemspppd.h>
/* define pppd function prototypes */
extern void pppasyncattach(void);
extern int pppdmain(int, char **);
/* define global variables */
rtems_id rtems_pppd_taskid;
rtems_pppd_hookfunction rtems_pppd_errorfp;
rtems_pppd_hookfunction rtems_pppd_exitfp;
static rtems_task pppTask(rtems_task_argument arg)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_option options;
rtems_event_set in;
rtems_event_set out;
int iStatus;
/* call function to setup ppp line discipline */
pppasyncattach();
/* enter processing loop */
in = (RTEMS_EVENT_29 | RTEMS_EVENT_30);
options = (RTEMS_EVENT_ANY | RTEMS_WAIT);
while ( sc == RTEMS_SUCCESSFUL ) {
/* wait for the next event */
sc = rtems_event_receive(in, options, RTEMS_NO_TIMEOUT, &out);
if ( sc == RTEMS_SUCCESSFUL ) {
/* determine which event was sent */
if ( out & RTEMS_EVENT_29 ) {
/* terminate event received */
/* set value to break out of event loop */
sc = RTEMS_UNSATISFIED;
}
else if ( out & RTEMS_EVENT_30 ) {
/* connect request */
/* execute the pppd main code */
iStatus = pppdmain(0, NULL);
if ( iStatus == EXIT_OK ) {
/* check exit callback */
if ( rtems_pppd_exitfp ) {
(*rtems_pppd_exitfp)();
}
}
else {
/* check error callback */
if ( rtems_pppd_errorfp ) {
(*rtems_pppd_errorfp)();
}
}
}
}
}
/* terminate myself */
rtems_pppd_taskid = 0;
rtems_task_exit();
}
int rtems_pppd_initialize(void)
{
int iReturn = (int)-1;
rtems_task_priority priority = 100;
rtems_status_code status;
rtems_name taskName;
/* determine priority value */
if ( rtems_bsdnet_config.network_task_priority ) {
priority = rtems_bsdnet_config.network_task_priority;
}
/* initialize the exit hook */
rtems_pppd_exitfp = (rtems_pppd_hookfunction)0;
/* create the rtems task */
taskName = rtems_build_name( 'p', 'p', 'p', 'd' );
status = rtems_task_create(taskName, priority, 8192,
(RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0)),
RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
&rtems_pppd_taskid);
if ( status == RTEMS_SUCCESSFUL ) {
status = rtems_task_start(rtems_pppd_taskid, pppTask, 0);
if ( status == RTEMS_SUCCESSFUL ) {
iReturn = rtems_pppd_reset_options();
}
}
return ( iReturn );
}
int rtems_pppd_terminate(void)
{
/* send terminate signal to pppd task */
rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_29);
/* call the disconnect function */
rtems_pppd_disconnect();
return ( 0 );
}
int rtems_pppd_reset_options(void)
{
int i;
struct protent *protp;
/*
* Initialize to the standard option set, then parse, in order,
* the system options file, the user's options file,
* the tty's options file, and the command line arguments.
*/
for (i = 0; (protp = protocols[i]) != NULL; ++i)
(*protp->init)(0);
return ( 0 );
}
int rtems_pppd_set_hook(int id, rtems_pppd_hookfunction hookfp)
{
int iReturn = (int)0;
switch ( id ) {
case RTEMS_PPPD_LINKUP_HOOK:
auth_linkup_hook = hookfp;
break;
case RTEMS_PPPD_LINKDOWN_HOOK:
auth_linkdown_hook = hookfp;
break;
case RTEMS_PPPD_IPUP_HOOK:
ip_up_hook = hookfp;
break;
case RTEMS_PPPD_IPDOWN_HOOK:
ip_down_hook = hookfp;
break;
case RTEMS_PPPD_ERROR_HOOK:
rtems_pppd_errorfp = hookfp;
break;
case RTEMS_PPPD_EXIT_HOOK:
rtems_pppd_exitfp = hookfp;
break;
default:
iReturn = (int)-1;
break;
}
return ( iReturn );
}
int rtems_pppd_set_dialer(rtems_pppd_dialerfunction dialerfp)
{
pppd_dialer = dialerfp;
return ( (int)0 );
}
int rtems_pppd_set_option(const char *pOption, const char *pValue)
{
int iReturn = (int)0;
int prevPhase;
struct wordlist option;
struct wordlist value;
if ( pOption != (const char *)0 ) {
/* initialize the values */
option.word = (char *)pOption;
option.next = (struct wordlist *)0;
if ( pValue != (const char *)0 ) {
option.next = &value;
value.word = (char *)pValue;
value.next = (struct wordlist *)0;
}
/* save current phase value */
prevPhase = pppd_phase;
pppd_phase = PHASE_INITIALIZE;
/* process option and reset phase value */
iReturn = options_from_list(&option, 1);
pppd_phase = prevPhase;
}
return ( iReturn );
}
int rtems_pppd_connect(void)
{
/* send connect signal to pppd task */
rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_30);
return ( 0 );
}
static void timeout_terminate(void *arg)
{
/* set pppd global variables to disconnect */
persist = 0;
pppd_kill_link = 1;
}
int rtems_pppd_disconnect(void)
{
/* need to wait a little time before we can bring the link down */
/* set up time out in 1 seconds */
TIMEOUT(timeout_terminate, NULL, 1);
/* send event to wake up the pppd code */
/* pretend its a serial interrput */
rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_31);
return ( 0 );
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,627 +0,0 @@
/*
* upap.c - User/Password Authentication Protocol.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*/
/*
* TODO:
*/
#include <stdio.h>
#include <string.h>
#include "pppd.h"
#include "upap.h"
static bool hide_password = true;
/*
* Command-line options.
*/
static option_t pap_option_list[] = {
{ "hide-password", o_bool, &hide_password,
"Don't output passwords to log", 1, NULL, 0, 0 },
{ "show-password", o_bool, &hide_password,
"Show password string in debug log messages", 0, NULL, 0, 0 },
{ "pap-restart", o_int, &upap[0].us_timeouttime,
"Set retransmit timeout for PAP", 0, NULL, 0, 0 },
{ "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
"Set max number of transmissions for auth-reqs", 0, NULL, 0, 0 },
{ "pap-timeout", o_int, &upap[0].us_reqtimeout,
"Set time limit for peer PAP authentication", 0, NULL, 0, 0 },
{ NULL, 0, NULL, NULL, 0, NULL, 0, 0 }
};
/*
* Protocol entry points.
*/
static void upap_init(int);
static void upap_lowerup(int);
static void upap_lowerdown(int);
static void upap_input(int, u_char *, int);
static void upap_protrej(int);
static int upap_printpkt(u_char *, int,
void (*)(void *, char *, ...), void *);
struct protent pap_protent = {
PPP_PAP,
upap_init,
upap_input,
upap_protrej,
upap_lowerup,
upap_lowerdown,
NULL,
NULL,
upap_printpkt,
NULL,
1,
"PAP",
NULL,
pap_option_list,
NULL,
NULL,
NULL
};
upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
static void upap_timeout(void *);
static void upap_reqtimeout(void *);
static void upap_rauthreq(upap_state *, u_char *, int, int);
static void upap_rauthack(upap_state *, u_char *, int, int);
static void upap_rauthnak(upap_state *, u_char *, int, int);
static void upap_sauthreq(upap_state *);
static void upap_sresp(upap_state *, u_char, u_char, char *, int);
/*
* upap_init - Initialize a UPAP unit.
*/
static void
upap_init(int unit)
{
upap_state *u = &upap[unit];
u->us_unit = unit;
u->us_user = NULL;
u->us_userlen = 0;
u->us_passwd = NULL;
u->us_passwdlen = 0;
u->us_clientstate = UPAPCS_INITIAL;
u->us_serverstate = UPAPSS_INITIAL;
u->us_id = 0;
u->us_timeouttime = UPAP_DEFTIMEOUT;
u->us_maxtransmits = 10;
u->us_reqtimeout = UPAP_DEFREQTIME;
}
/*
* upap_authwithpeer - Authenticate us with our peer (start client).
*
* Set new state and send authenticate's.
*/
void
upap_authwithpeer(
int unit,
char *user,
char *password)
{
upap_state *u = &upap[unit];
/* Save the username and password we're given */
u->us_user = user;
u->us_userlen = strlen(user);
u->us_passwd = password;
u->us_passwdlen = strlen(password);
u->us_transmits = 0;
/* Lower layer up yet? */
if (u->us_clientstate == UPAPCS_INITIAL ||
u->us_clientstate == UPAPCS_PENDING) {
u->us_clientstate = UPAPCS_PENDING;
return;
}
upap_sauthreq(u); /* Start protocol */
}
/*
* upap_authpeer - Authenticate our peer (start server).
*
* Set new state.
*/
void
upap_authpeer(int unit)
{
upap_state *u = &upap[unit];
/* Lower layer up yet? */
if (u->us_serverstate == UPAPSS_INITIAL ||
u->us_serverstate == UPAPSS_PENDING) {
u->us_serverstate = UPAPSS_PENDING;
return;
}
u->us_serverstate = UPAPSS_LISTEN;
if (u->us_reqtimeout > 0)
TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
}
/*
* upap_timeout - Retransmission timer for sending auth-reqs expired.
*/
static void
upap_timeout(void *arg)
{
upap_state *u = (upap_state *) arg;
if (u->us_clientstate != UPAPCS_AUTHREQ)
return;
if (u->us_transmits >= u->us_maxtransmits) {
/* give up in disgust */
error("No response to PAP authenticate-requests");
u->us_clientstate = UPAPCS_BADAUTH;
auth_withpeer_fail(u->us_unit, PPP_PAP);
return;
}
upap_sauthreq(u); /* Send Authenticate-Request */
}
/*
* upap_reqtimeout - Give up waiting for the peer to send an auth-req.
*/
static void
upap_reqtimeout(void *arg)
{
upap_state *u = (upap_state *) arg;
if (u->us_serverstate != UPAPSS_LISTEN)
return; /* huh?? */
auth_peer_fail(u->us_unit, PPP_PAP);
u->us_serverstate = UPAPSS_BADAUTH;
}
/*
* upap_lowerup - The lower layer is up.
*
* Start authenticating if pending.
*/
static void
upap_lowerup(int unit)
{
upap_state *u = &upap[unit];
if (u->us_clientstate == UPAPCS_INITIAL)
u->us_clientstate = UPAPCS_CLOSED;
else if (u->us_clientstate == UPAPCS_PENDING) {
upap_sauthreq(u); /* send an auth-request */
}
if (u->us_serverstate == UPAPSS_INITIAL)
u->us_serverstate = UPAPSS_CLOSED;
else if (u->us_serverstate == UPAPSS_PENDING) {
u->us_serverstate = UPAPSS_LISTEN;
if (u->us_reqtimeout > 0)
TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
}
}
/*
* upap_lowerdown - The lower layer is down.
*
* Cancel all timeouts.
*/
static void
upap_lowerdown(int unit)
{
upap_state *u = &upap[unit];
if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
UNTIMEOUT(upap_reqtimeout, u);
u->us_clientstate = UPAPCS_INITIAL;
u->us_serverstate = UPAPSS_INITIAL;
}
/*
* upap_protrej - Peer doesn't speak this protocol.
*
* This shouldn't happen. In any case, pretend lower layer went down.
*/
static void
upap_protrej(int unit)
{
upap_state *u = &upap[unit];
if (u->us_clientstate == UPAPCS_AUTHREQ) {
error("PAP authentication failed due to protocol-reject");
auth_withpeer_fail(unit, PPP_PAP);
}
if (u->us_serverstate == UPAPSS_LISTEN) {
error("PAP authentication of peer failed (protocol-reject)");
auth_peer_fail(unit, PPP_PAP);
}
upap_lowerdown(unit);
}
/*
* upap_input - Input UPAP packet.
*/
static void
upap_input(
int unit,
u_char *inpacket,
int l)
{
upap_state *u = &upap[unit];
u_char *inp;
u_char code, id;
int len;
/*
* Parse header (code, id and length).
* If packet too short, drop it.
*/
inp = inpacket;
if (l < UPAP_HEADERLEN) {
UPAPDEBUG(("pap_input: rcvd short header."));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len < UPAP_HEADERLEN) {
UPAPDEBUG(("pap_input: rcvd illegal length."));
return;
}
if (len > l) {
UPAPDEBUG(("pap_input: rcvd short packet."));
return;
}
len -= UPAP_HEADERLEN;
/*
* Action depends on code.
*/
switch (code) {
case UPAP_AUTHREQ:
upap_rauthreq(u, inp, id, len);
break;
case UPAP_AUTHACK:
upap_rauthack(u, inp, id, len);
break;
case UPAP_AUTHNAK:
upap_rauthnak(u, inp, id, len);
break;
default: /* XXX Need code reject */
break;
}
}
/*
* upap_rauth - Receive Authenticate.
*/
static void
upap_rauthreq(
upap_state *u,
u_char *inp,
int id,
int len)
{
u_char ruserlen, rpasswdlen;
char *ruser, *rpasswd;
int retcode;
char *msg;
int msglen;
if (u->us_serverstate < UPAPSS_LISTEN)
return;
/*
* If we receive a duplicate authenticate-request, we are
* supposed to return the same status as for the first request.
*/
if (u->us_serverstate == UPAPSS_OPEN) {
upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
return;
}
if (u->us_serverstate == UPAPSS_BADAUTH) {
upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
return;
}
/*
* Parse user/passwd.
*/
if (len < 1) {
UPAPDEBUG(("pap_rauth: rcvd short packet."));
return;
}
GETCHAR(ruserlen, inp);
len -= sizeof (u_char) + ruserlen + sizeof (u_char);
if (len < 0) {
UPAPDEBUG(("pap_rauth: rcvd short packet."));
return;
}
ruser = (char *) inp;
INCPTR(ruserlen, inp);
GETCHAR(rpasswdlen, inp);
if (len < rpasswdlen) {
UPAPDEBUG(("pap_rauth: rcvd short packet."));
return;
}
rpasswd = (char *) inp;
/*
* Check the username and password given.
*/
retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
rpasswdlen, &msg);
BZERO(rpasswd, rpasswdlen);
msglen = strlen(msg);
if (msglen > 255)
msglen = 255;
upap_sresp(u, retcode, id, msg, msglen);
if (retcode == UPAP_AUTHACK) {
u->us_serverstate = UPAPSS_OPEN;
auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
} else {
u->us_serverstate = UPAPSS_BADAUTH;
auth_peer_fail(u->us_unit, PPP_PAP);
}
if (u->us_reqtimeout > 0)
UNTIMEOUT(upap_reqtimeout, u);
}
/*
* upap_rauthack - Receive Authenticate-Ack.
*/
static void
upap_rauthack(
upap_state *u,
u_char *inp,
int id,
int len)
{
u_char msglen;
char *msg;
if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
return;
/*
* Parse message.
*/
if (len < 1) {
UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
} else {
GETCHAR(msglen, inp);
if (msglen > 0) {
len -= sizeof (u_char);
if (len < msglen) {
UPAPDEBUG(("pap_rauthack: rcvd short packet."));
return;
}
msg = (char *) inp;
PRINTMSG(msg, msglen);
}
}
u->us_clientstate = UPAPCS_OPEN;
auth_withpeer_success(u->us_unit, PPP_PAP);
}
/*
* upap_rauthnak - Receive Authenticate-Nakk.
*/
static void
upap_rauthnak(
upap_state *u,
u_char *inp,
int id,
int len)
{
u_char msglen;
char *msg;
if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
return;
/*
* Parse message.
*/
if (len < 1) {
UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
} else {
GETCHAR(msglen, inp);
if (msglen > 0) {
len -= sizeof (u_char);
if (len < msglen) {
UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
return;
}
msg = (char *) inp;
PRINTMSG(msg, msglen);
}
}
u->us_clientstate = UPAPCS_BADAUTH;
error("PAP authentication failed");
auth_withpeer_fail(u->us_unit, PPP_PAP);
}
/*
* upap_sauthreq - Send an Authenticate-Request.
*/
static void
upap_sauthreq(upap_state *u)
{
u_char *outp;
int outlen;
outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
u->us_userlen + u->us_passwdlen;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_PAP);
PUTCHAR(UPAP_AUTHREQ, outp);
PUTCHAR(++u->us_id, outp);
PUTSHORT(outlen, outp);
PUTCHAR(u->us_userlen, outp);
BCOPY(u->us_user, outp, u->us_userlen);
INCPTR(u->us_userlen, outp);
PUTCHAR(u->us_passwdlen, outp);
BCOPY(u->us_passwd, outp, u->us_passwdlen);
output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
TIMEOUT(upap_timeout, u, u->us_timeouttime);
++u->us_transmits;
u->us_clientstate = UPAPCS_AUTHREQ;
}
/*
* upap_sresp - Send a response (ack or nak).
*/
static void
upap_sresp(
upap_state *u,
u_char code, u_char id,
char *msg,
int msglen)
{
u_char *outp;
int outlen;
outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_PAP);
PUTCHAR(code, outp);
PUTCHAR(id, outp);
PUTSHORT(outlen, outp);
PUTCHAR(msglen, outp);
BCOPY(msg, outp, msglen);
output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
}
/*
* upap_printpkt - print the contents of a PAP packet.
*/
static char *upap_codenames[] = {
"AuthReq", "AuthAck", "AuthNak"
};
static int
upap_printpkt(
u_char *p,
int plen,
void (*printer)(void *, char *, ...),
void *arg)
{
int code, id, len;
int mlen, ulen, wlen;
char *user, *pwd, *msg;
u_char *pstart;
if (plen < UPAP_HEADERLEN)
return 0;
pstart = p;
GETCHAR(code, p);
GETCHAR(id, p);
GETSHORT(len, p);
if (len < UPAP_HEADERLEN || len > plen)
return 0;
if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *))
printer(arg, " %s", upap_codenames[code-1]);
else
printer(arg, " code=0x%x", code);
printer(arg, " id=0x%x", id);
len -= UPAP_HEADERLEN;
switch (code) {
case UPAP_AUTHREQ:
if (len < 1)
break;
ulen = p[0];
if (len < ulen + 2)
break;
wlen = p[ulen + 1];
if (len < ulen + wlen + 2)
break;
user = (char *) (p + 1);
pwd = (char *) (p + ulen + 2);
p += ulen + wlen + 2;
len -= ulen + wlen + 2;
printer(arg, " user=");
print_string(user, ulen, printer, arg);
printer(arg, " password=");
if (!hide_password)
print_string(pwd, wlen, printer, arg);
else
printer(arg, "<hidden>");
break;
case UPAP_AUTHACK:
case UPAP_AUTHNAK:
if (len < 1)
break;
mlen = p[0];
if (len < mlen + 1)
break;
msg = (char *) (p + 1);
p += mlen + 1;
len -= mlen + 1;
printer(arg, " ");
print_string(msg, mlen, printer, arg);
break;
}
/* print the rest of the bytes in the packet */
for (; len > 0; --len) {
GETCHAR(code, p);
printer(arg, " %.2x", code);
}
return p - pstart;
}

View File

@@ -1,87 +0,0 @@
/*
* upap.h - User/Password Authentication Protocol definitions.
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. The name of the
* University 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.
*
* $Id$
*/
/*
* Packet header = Code, id, length.
*/
#define UPAP_HEADERLEN 4
/*
* UPAP codes.
*/
#define UPAP_AUTHREQ 1 /* Authenticate-Request */
#define UPAP_AUTHACK 2 /* Authenticate-Ack */
#define UPAP_AUTHNAK 3 /* Authenticate-Nak */
/*
* Each interface is described by upap structure.
*/
typedef struct upap_state {
int us_unit; /* Interface unit number */
char *us_user; /* User */
int us_userlen; /* User length */
char *us_passwd; /* Password */
int us_passwdlen; /* Password length */
int us_clientstate; /* Client state */
int us_serverstate; /* Server state */
u_char us_id; /* Current id */
int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */
int us_transmits; /* Number of auth-reqs sent */
int us_maxtransmits; /* Maximum number of auth-reqs to send */
int us_reqtimeout; /* Time to wait for auth-req from peer */
} upap_state;
/*
* Client states.
*/
#define UPAPCS_INITIAL 0 /* Connection down */
#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */
#define UPAPCS_PENDING 2 /* Connection down, have requested auth */
#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */
#define UPAPCS_OPEN 4 /* We've received an Ack */
#define UPAPCS_BADAUTH 5 /* We've received a Nak */
/*
* Server states.
*/
#define UPAPSS_INITIAL 0 /* Connection down */
#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */
#define UPAPSS_PENDING 2 /* Connection down, have requested auth */
#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */
#define UPAPSS_OPEN 4 /* We've sent an Ack */
#define UPAPSS_BADAUTH 5 /* We've sent a Nak */
/*
* Timeouts.
*/
#define UPAP_DEFTIMEOUT 5 /* Timeout (seconds) for retransmitting req */
#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */
extern upap_state upap[];
void upap_authwithpeer(int, char *, char *);
void upap_authpeer(int);
extern struct protent pap_protent;

View File

@@ -1,823 +0,0 @@
/*
* utils.c - various utility functions used in pppd.
*
* Copyright (c) 1999 The Australian National University.
* 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 the Australian National University. The name of the University
* 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.
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <syslog.h>
#include <pwd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef SVR4
#include <sys/mkdev.h>
#endif
#include "pppd.h"
static void pr_log(void *, char *, ...);
static void logit(int, char *, va_list);
static void vslp_printer(void *, char *, ...);
static void format_packet(u_char *, int, void (*) (void *, char *, ...),
void *);
struct buffer_info {
char *ptr;
int len;
};
/*
* slprintf - format a message into a buffer. Like sprintf except we
* also specify the length of the output buffer, and we handle
* %r (recursive format), %m (error message), %v (visible string),
* %q (quoted string), %t (current time) and %I (IP address) formats.
* Doesn't do floating-point formats.
* Returns the number of chars put into buf.
*/
int
slprintf __V((char *buf, int buflen, char *fmt, ...))
{
va_list args;
int n;
#if defined(__STDC__)
va_start(args, fmt);
#else
char *buf;
int buflen;
char *fmt;
va_start(args);
buf = va_arg(args, char *);
buflen = va_arg(args, int);
fmt = va_arg(args, char *);
#endif
n = vslprintf(buf, buflen, fmt, args);
va_end(args);
return n;
}
/*
* vslprintf - like slprintf, takes a va_list instead of a list of args.
*/
#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
int
vslprintf(
char *buf,
int buflen,
char *fmt,
va_list args)
{
int c, i, n;
int width, prec, fillch;
int base, len, neg, quoted;
uintptr_t val = 0;
char *str, *f, *buf0;
unsigned char *p;
char num[32];
time_t t;
uint32_t ip;
static char hexchars[] = "0123456789abcdef";
struct buffer_info bufinfo;
buf0 = buf;
--buflen;
while (buflen > 0) {
for (f = fmt; *f != '%' && *f != 0; ++f)
;
if (f > fmt) {
len = f - fmt;
if (len > buflen)
len = buflen;
memcpy(buf, fmt, len);
buf += len;
buflen -= len;
fmt = f;
}
if (*fmt == 0)
break;
c = *++fmt;
width = 0;
prec = -1;
fillch = ' ';
if (c == '0') {
fillch = '0';
c = *++fmt;
}
if (c == '*') {
width = va_arg(args, int);
c = *++fmt;
} else {
while (isdigit(c)) {
width = width * 10 + c - '0';
c = *++fmt;
}
}
if (c == '.') {
c = *++fmt;
if (c == '*') {
prec = va_arg(args, int);
c = *++fmt;
} else {
prec = 0;
while (isdigit(c)) {
prec = prec * 10 + c - '0';
c = *++fmt;
}
}
}
str = 0;
base = 0;
neg = 0;
++fmt;
switch (c) {
case 'd':
i = va_arg(args, int);
if (i < 0) {
neg = 1;
val = -i;
} else
val = i;
base = 10;
break;
case 'o':
val = va_arg(args, unsigned int);
base = 8;
break;
case 'x':
case 'X':
val = va_arg(args, unsigned int);
base = 16;
break;
case 'p':
val = (uintptr_t) va_arg(args, void *);
base = 16;
neg = 2;
break;
case 's':
str = va_arg(args, char *);
break;
case 'c':
num[0] = va_arg(args, int);
num[1] = 0;
str = num;
break;
case 'm':
str = strerror(errno);
break;
case 'I':
ip = va_arg(args, uint32_t);
ip = ntohl(ip);
slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff,
(ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
str = num;
break;
case 'r':
f = va_arg(args, char *);
#if !defined(__PPC__)
n = vslprintf(buf, buflen + 1, f, va_arg(args, va_list));
#else
/* HACK: On the powerpc, a va_list is an array of 1 structure */
n = vslprintf(buf, buflen + 1, f, va_arg(args, void *));
#endif
buf += n;
buflen -= n;
continue;
case 't':
time(&t);
str = ctime(&t);
str += 4; /* chop off the day name */
str[15] = 0; /* chop off year and newline */
break;
case 'v': /* "visible" string */
case 'q': /* quoted string */
quoted = c == 'q';
p = va_arg(args, unsigned char *);
if (fillch == '0' && prec >= 0) {
n = prec;
} else {
n = strlen((char *)p);
if (prec >= 0 && n > prec)
n = prec;
}
while (n > 0 && buflen > 0) {
c = *p++;
--n;
if (!quoted && c >= 0x80) {
OUTCHAR('M');
OUTCHAR('-');
c -= 0x80;
}
if (quoted && (c == '"' || c == '\\'))
OUTCHAR('\\');
if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
if (quoted) {
OUTCHAR('\\');
switch (c) {
case '\t': OUTCHAR('t'); break;
case '\n': OUTCHAR('n'); break;
case '\b': OUTCHAR('b'); break;
case '\f': OUTCHAR('f'); break;
default:
OUTCHAR('x');
OUTCHAR(hexchars[c >> 4]);
OUTCHAR(hexchars[c & 0xf]);
}
} else {
if (c == '\t')
OUTCHAR(c);
else {
OUTCHAR('^');
OUTCHAR(c ^ 0x40);
}
}
} else
OUTCHAR(c);
}
continue;
case 'P': /* print PPP packet */
bufinfo.ptr = buf;
bufinfo.len = buflen + 1;
p = va_arg(args, unsigned char *);
n = va_arg(args, int);
format_packet(p, n, vslp_printer, &bufinfo);
buf = bufinfo.ptr;
buflen = bufinfo.len - 1;
continue;
case 'B':
p = va_arg(args, unsigned char *);
for (n = prec; n > 0; --n) {
c = *p++;
if (fillch == ' ')
OUTCHAR(' ');
OUTCHAR(hexchars[(c >> 4) & 0xf]);
OUTCHAR(hexchars[c & 0xf]);
}
continue;
default:
*buf++ = '%';
if (c != '%')
--fmt; /* so %z outputs %z etc. */
--buflen;
continue;
}
if (base != 0) {
str = num + sizeof(num);
*--str = 0;
while (str > num + neg) {
*--str = hexchars[val % base];
val = val / base;
if (--prec <= 0 && val == 0)
break;
}
switch (neg) {
case 1:
*--str = '-';
break;
case 2:
*--str = 'x';
*--str = '0';
break;
}
len = num + sizeof(num) - 1 - str;
} else {
len = strlen(str);
if (prec >= 0 && len > prec)
len = prec;
}
if (width > 0) {
if (width > buflen)
width = buflen;
if ((n = width - len) > 0) {
buflen -= n;
for (; n > 0; --n)
*buf++ = fillch;
}
}
if (len > buflen)
len = buflen;
memcpy(buf, str, len);
buf += len;
buflen -= len;
}
*buf = 0;
return buf - buf0;
}
/*
* vslp_printer - used in processing a %P format
*/
static void
vslp_printer __V((void *arg, char *fmt, ...))
{
int n;
va_list pvar;
struct buffer_info *bi;
#if defined(__STDC__)
va_start(pvar, fmt);
#else
void *arg;
char *fmt;
va_start(pvar);
arg = va_arg(pvar, void *);
fmt = va_arg(pvar, char *);
#endif
bi = (struct buffer_info *) arg;
n = vslprintf(bi->ptr, bi->len, fmt, pvar);
va_end(pvar);
bi->ptr += n;
bi->len -= n;
}
/*
* log_packet - format a packet and log it.
*/
char line[256]; /* line to be logged accumulated here */
char *linep;
void
log_packet(
u_char *p,
int len,
char *prefix,
int level)
{
strlcpy(line, prefix, sizeof(line));
linep = line + strlen(line);
format_packet(p, len, pr_log, NULL);
}
/*
* format_packet - make a readable representation of a packet,
* calling `printer(arg, format, ...)' to output it.
*/
static void
format_packet(
u_char *p,
int len,
void (*printer)(void *, char *, ...),
void *arg)
{
int i, n;
u_short proto;
struct protent *protp;
if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
p += 2;
GETSHORT(proto, p);
len -= PPP_HDRLEN;
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (proto == protp->protocol)
break;
if (protp != NULL) {
printer(arg, "[%s", protp->name);
n = (*protp->printpkt)(p, len, printer, arg);
printer(arg, "]");
p += n;
len -= n;
} else {
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (proto == (protp->protocol & ~0x8000))
break;
if (protp != 0 && protp->data_name != 0) {
printer(arg, "[%s data]", protp->data_name);
if (len > 8)
printer(arg, "%.8B ...", p);
else
printer(arg, "%.*B", len, p);
len = 0;
} else
printer(arg, "[proto=0x%x]", proto);
}
}
if (len > 32)
printer(arg, "%.32B ...", p);
else
printer(arg, "%.*B", len, p);
}
static void
pr_log __V((void *arg, char *fmt, ...))
{
int n;
va_list pvar;
char buf[256];
#if defined(__STDC__)
va_start(pvar, fmt);
#else
void *arg;
char *fmt;
va_start(pvar);
arg = va_arg(pvar, void *);
fmt = va_arg(pvar, char *);
#endif
n = vslprintf(buf, sizeof(buf), fmt, pvar);
va_end(pvar);
if (linep + n + 1 > line + sizeof(line)) {
linep = line;
}
strlcpy(linep, buf, line + sizeof(line) - linep);
linep += n;
}
/*
* print_string - print a readable representation of a string using
* printer.
*/
void
print_string(
void *p_arg,
int len,
void (*printer)(void *, char *, ...),
void *arg)
{
int c;
unsigned char *p = (unsigned char *)p_arg;
printer(arg, "\"");
for (; len > 0; --len) {
c = *p++;
if (' ' <= c && c <= '~') {
if (c == '\\' || c == '"')
printer(arg, "\\");
printer(arg, "%c", c);
} else {
switch (c) {
case '\n':
printer(arg, "\\n");
break;
case '\r':
printer(arg, "\\r");
break;
case '\t':
printer(arg, "\\t");
break;
default:
printer(arg, "\\%.3o", c);
}
}
}
printer(arg, "\"");
}
/*
* logit - does the hard work for fatal et al.
*/
static void
logit(
int level,
char *fmt,
va_list args)
{
int n;
char buf[256];
n = vslprintf(buf, sizeof(buf), fmt, args);
/* if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { */
if (log_to_fd >= 0 && (debug)) {
if (buf[n-1] != '\n')
buf[n++] = '\n';
if (write(log_to_fd, buf, n) != n)
log_to_fd = -1;
}
}
/*
* fatal - log an error message and die horribly.
*/
void
pppd_fatal __V((char *fmt, ...))
{
va_list pvar;
#if defined(__STDC__)
va_start(pvar, fmt);
#else
char *fmt;
va_start(pvar);
fmt = va_arg(pvar, char *);
#endif
logit(LOG_ERR, fmt, pvar);
va_end(pvar);
die(1); /* as promised */
}
/*
* error - log an error message.
*/
void
pppd_error __V((char *fmt, ...))
{
va_list pvar;
#if defined(__STDC__)
va_start(pvar, fmt);
#else
char *fmt;
va_start(pvar);
fmt = va_arg(pvar, char *);
#endif
logit(LOG_ERR, fmt, pvar);
va_end(pvar);
}
/*
* warn - log a warning message.
*/
void
pppd_warn __V((char *fmt, ...))
{
va_list pvar;
#if defined(__STDC__)
va_start(pvar, fmt);
#else
char *fmt;
va_start(pvar);
fmt = va_arg(pvar, char *);
#endif
logit(LOG_WARNING, fmt, pvar);
va_end(pvar);
}
/*
* notice - log a notice-level message.
*/
void
pppd_notice __V((char *fmt, ...))
{
va_list pvar;
#if defined(__STDC__)
va_start(pvar, fmt);
#else
char *fmt;
va_start(pvar);
fmt = va_arg(pvar, char *);
#endif
logit(LOG_NOTICE, fmt, pvar);
va_end(pvar);
}
/*
* info - log an informational message.
*/
void
pppd_info __V((char *fmt, ...))
{
va_list pvar;
#if defined(__STDC__)
va_start(pvar, fmt);
#else
char *fmt;
va_start(pvar);
fmt = va_arg(pvar, char *);
#endif
logit(LOG_INFO, fmt, pvar);
va_end(pvar);
}
/*
* dbglog - log a debug message.
*/
void
pppd_dbglog __V((char *fmt, ...))
{
va_list pvar;
#if defined(__STDC__)
va_start(pvar, fmt);
#else
char *fmt;
va_start(pvar);
fmt = va_arg(pvar, char *);
#endif
logit(LOG_DEBUG, fmt, pvar);
va_end(pvar);
}
/* Procedures for locking the serial device using a lock file. */
#ifndef LOCK_DIR
#ifdef _linux_
#define LOCK_DIR "/var/lock"
#else
#ifdef SVR4
#define LOCK_DIR "/var/spool/locks"
#else
#define LOCK_DIR "/var/spool/lock"
#endif
#endif
#endif /* LOCK_DIR */
static char lock_file[MAXPATHLEN];
/*
* lock - create a lock file for the named device
*/
int
lock(char *dev)
{
#ifdef LOCKLIB
int result;
result = mklock (dev, (void *) 0);
if (result == 0) {
strlcpy(lock_file, sizeof(lock_file), dev);
return 0;
}
if (result > 0)
notice("Device %s is locked by pid %d", dev, result);
else
error("Can't create lock file %s", lock_file);
return -1;
#else /* LOCKLIB */
char lock_buffer[12];
int fd, pid, n;
#ifdef SVR4
struct stat sbuf;
if (stat(dev, &sbuf) < 0) {
error("Can't get device number for %s: %m", dev);
return -1;
}
if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
error("Can't lock %s: not a character device", dev);
return -1;
}
slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d",
LOCK_DIR, major(sbuf.st_dev),
major(sbuf.st_rdev), minor(sbuf.st_rdev));
#else
char *p;
if ((p = strrchr(dev, '/')) != NULL)
dev = p + 1;
slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev);
#endif
while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
if (errno != EEXIST) {
error("Can't create lock file %s: %m", lock_file);
break;
}
/* Read the lock file to find out who has the device locked. */
fd = open(lock_file, O_RDONLY, 0);
if (fd < 0) {
if (errno == ENOENT) /* This is just a timing problem. */
continue;
error("Can't open existing lock file %s: %m", lock_file);
break;
}
#ifndef LOCK_BINARY
n = read(fd, lock_buffer, 11);
#else
n = read(fd, &pid, sizeof(pid));
#endif /* LOCK_BINARY */
close(fd);
fd = -1;
if (n <= 0) {
error("Can't read pid from lock file %s", lock_file);
break;
}
/* See if the process still exists. */
#ifndef LOCK_BINARY
lock_buffer[n] = 0;
pid = atoi(lock_buffer);
#endif /* LOCK_BINARY */
if (pid == getpid())
return 1; /* somebody else locked it for us */
if (pid == 0
|| (kill(pid, 0) == -1 && errno == ESRCH)) {
if (unlink (lock_file) == 0) {
notice("Removed stale lock on %s (pid %d)", dev, pid);
continue;
}
warn("Couldn't remove stale lock on %s", dev);
} else
notice("Device %s is locked by pid %d", dev, pid);
break;
}
if (fd < 0) {
lock_file[0] = 0;
return -1;
}
pid = getpid();
#ifndef LOCK_BINARY
slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
write (fd, lock_buffer, 11);
#else
write(fd, &pid, sizeof (pid));
#endif
close(fd);
return 0;
#endif
}
/*
* relock - called to update our lockfile when we are about to detach,
* thus changing our pid (we fork, the child carries on, and the parent dies).
* Note that this is called by the parent, with pid equal to the pid
* of the child. This avoids a potential race which would exist if
* we had the child rewrite the lockfile (the parent might die first,
* and another process could think the lock was stale if it checked
* between when the parent died and the child rewrote the lockfile).
*/
int
relock(int pid)
{
#ifdef LOCKLIB
/* XXX is there a way to do this? */
return -1;
#else /* LOCKLIB */
int fd;
char lock_buffer[12];
if (lock_file[0] == 0)
return -1;
fd = open(lock_file, O_WRONLY, 0);
if (fd < 0) {
error("Couldn't reopen lock file %s: %m", lock_file);
lock_file[0] = 0;
return -1;
}
#ifndef LOCK_BINARY
slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
write (fd, lock_buffer, 11);
#else
write(fd, &pid, sizeof(pid));
#endif /* LOCK_BINARY */
close(fd);
return 0;
#endif /* LOCKLIB */
}
/*
* unlock - remove our lockfile
*/
void
unlock(void)
{
if (lock_file[0]) {
#ifdef LOCKLIB
(void) rmlock(lock_file, (void *) 0);
#else
unlink(lock_file);
#endif
lock_file[0] = 0;
}
}

View File

@@ -23,8 +23,6 @@ links:
uid: libmghttpd
- role: build-dependency
uid: libnfs
- role: build-dependency
uid: libpppd
- role: build-dependency
uid: librtemscpu
- role: build-dependency

View File

@@ -1,33 +0,0 @@
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
build-type: library
cflags: []
copyrights:
- Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
cppflags: []
cxxflags: []
enabled-by:
- RTEMS_NETWORKING
includes:
- cpukit/libnetworking
install: []
install-path: ${BSP_LIBDIR}
links: []
source:
- cpukit/pppd/auth.c
- cpukit/pppd/ccp.c
- cpukit/pppd/chap.c
- cpukit/pppd/chap_ms.c
- cpukit/pppd/chat.c
- cpukit/pppd/demand.c
- cpukit/pppd/fsm.c
- cpukit/pppd/ipcp.c
- cpukit/pppd/lcp.c
- cpukit/pppd/magic.c
- cpukit/pppd/options.c
- cpukit/pppd/rtemsmain.c
- cpukit/pppd/rtemspppd.c
- cpukit/pppd/sys-rtems.c
- cpukit/pppd/upap.c
- cpukit/pppd/utils.c
target: pppd
type: build

View File

@@ -157,7 +157,6 @@ install:
- cpukit/include/rtems/rtems-rfs-shell.h
- cpukit/include/rtems/rtems-rfs.h
- cpukit/include/rtems/rtemsdialer.h
- cpukit/include/rtems/rtemspppd.h
- cpukit/include/rtems/scheduler.h
- cpukit/include/rtems/serdbg.h
- cpukit/include/rtems/serdbgcnf.h