forked from Imagelibrary/rtems
@@ -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
|
||||
@@ -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>.
|
||||
=================================================================
|
||||
|
||||
@@ -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
|
||||
1124
cpukit/pppd/auth.c
1124
cpukit/pppd/auth.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
1224
cpukit/pppd/ccp.c
1224
cpukit/pppd/ccp.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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 */
|
||||
@@ -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__ */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 !!?? */
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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) */
|
||||
1768
cpukit/pppd/ipcp.c
1768
cpukit/pppd/ipcp.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
1949
cpukit/pppd/lcp.c
1949
cpukit/pppd/lcp.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
@@ -1,6 +0,0 @@
|
||||
/* $Id$ */
|
||||
#define PATCHLEVEL 11
|
||||
|
||||
#define VERSION "2.3"
|
||||
#define IMPLEMENTATION ""
|
||||
#define DATE "23 December 1999"
|
||||
@@ -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 */
|
||||
1479
cpukit/pppd/pppd.8
1479
cpukit/pppd/pppd.8
File diff suppressed because it is too large
Load Diff
@@ -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__ */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user