- add missing files
git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@26 315a16e6-25f9-4109-90ae-ca3045a26c18
This commit is contained in:
parent
e806fd27e8
commit
54ff068137
27 changed files with 13727 additions and 0 deletions
990
lwip/src/netif/ppp/auth.c
Normal file
990
lwip/src/netif/ppp/auth.c
Normal file
|
@ -0,0 +1,990 @@
|
|||
/*****************************************************************************
|
||||
* auth.c - Network Authentication and Phase Control program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Ported from public pppd code.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* auth.c - PPP authentication and phase control.
|
||||
*
|
||||
* 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) 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 "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "fsm.h"
|
||||
#include "lcp.h"
|
||||
#include "pap.h"
|
||||
#include "chap.h"
|
||||
#include "auth.h"
|
||||
#include "ipcp.h"
|
||||
|
||||
#if CBCP_SUPPORT
|
||||
#include "cbcp.h"
|
||||
#endif /* CBCP_SUPPORT */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
||||
/* Bits in auth_pending[] */
|
||||
#define PAP_WITHPEER 1
|
||||
#define PAP_PEER 2
|
||||
#define CHAP_WITHPEER 4
|
||||
#define CHAP_PEER 8
|
||||
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
/* Used for storing a sequence of words. Usually malloced. */
|
||||
struct wordlist {
|
||||
struct wordlist *next;
|
||||
char word[1];
|
||||
};
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
extern char *crypt (const char *, const char *);
|
||||
|
||||
/* Prototypes for procedures local to this file. */
|
||||
|
||||
static void network_phase (int);
|
||||
static void check_idle (void *);
|
||||
static void connect_time_expired (void *);
|
||||
#if 0
|
||||
static int login (char *, char *, char **, int *);
|
||||
#endif
|
||||
static void logout (void);
|
||||
static int null_login (int);
|
||||
static int get_pap_passwd (int, char *, char *);
|
||||
static int have_pap_secret (void);
|
||||
static int have_chap_secret (char *, char *, u32_t);
|
||||
static int ip_addr_check (u32_t, struct wordlist *);
|
||||
#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
static void set_allowed_addrs(int unit, struct wordlist *addrs);
|
||||
static void free_wordlist (struct wordlist *);
|
||||
#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
#if CBCP_SUPPORT
|
||||
static void callback_phase (int);
|
||||
#endif /* CBCP_SUPPORT */
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
#if PAP_SUPPORT || CHAP_SUPPORT
|
||||
/* The name by which the peer authenticated itself to us. */
|
||||
static char peer_authname[MAXNAMELEN];
|
||||
#endif /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
|
||||
/* Records which authentication operations haven't completed yet. */
|
||||
static int auth_pending[NUM_PPP];
|
||||
|
||||
/* Set if we have successfully called login() */
|
||||
static int logged_in;
|
||||
|
||||
/* Set if we have run the /etc/ppp/auth-up script. */
|
||||
static int did_authup;
|
||||
|
||||
/* List of addresses which the peer may use. */
|
||||
static struct wordlist *addresses[NUM_PPP];
|
||||
|
||||
/* Number of network protocols which we have opened. */
|
||||
static int num_np_open;
|
||||
|
||||
/* Number of network protocols which have come up. */
|
||||
static int num_np_up;
|
||||
|
||||
#if PAP_SUPPORT || CHAP_SUPPORT
|
||||
/* Set if we got the contents of passwd[] from the pap-secrets file. */
|
||||
static int passwd_from_file;
|
||||
#endif /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* An Open on LCP has requested a change from Dead to Establish phase.
|
||||
* Do what's necessary to bring the physical layer up.
|
||||
*/
|
||||
void
|
||||
link_required(int unit)
|
||||
{
|
||||
LWIP_UNUSED_ARG(unit);
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "link_required: %d\n", unit));
|
||||
}
|
||||
|
||||
/*
|
||||
* LCP has terminated the link; go to the Dead phase and take the
|
||||
* physical layer down.
|
||||
*/
|
||||
void
|
||||
link_terminated(int unit)
|
||||
{
|
||||
AUTHDEBUG((LOG_INFO, "link_terminated: %d\n", unit));
|
||||
if (lcp_phase[unit] == PHASE_DEAD) {
|
||||
return;
|
||||
}
|
||||
if (logged_in) {
|
||||
logout();
|
||||
}
|
||||
lcp_phase[unit] = PHASE_DEAD;
|
||||
AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n"));
|
||||
pppLinkTerminated(unit);
|
||||
}
|
||||
|
||||
/*
|
||||
* LCP has gone down; it will either die or try to re-establish.
|
||||
*/
|
||||
void
|
||||
link_down(int unit)
|
||||
{
|
||||
int i;
|
||||
struct protent *protp;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "link_down: %d\n", unit));
|
||||
if (did_authup) {
|
||||
/* XXX Do link down processing. */
|
||||
did_authup = 0;
|
||||
}
|
||||
for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
|
||||
if (!protp->enabled_flag) {
|
||||
continue;
|
||||
}
|
||||
if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) {
|
||||
(*protp->lowerdown)(unit);
|
||||
}
|
||||
if (protp->protocol < 0xC000 && protp->close != NULL) {
|
||||
(*protp->close)(unit, "LCP down");
|
||||
}
|
||||
}
|
||||
num_np_open = 0;
|
||||
num_np_up = 0;
|
||||
if (lcp_phase[unit] != PHASE_DEAD) {
|
||||
lcp_phase[unit] = PHASE_TERMINATE;
|
||||
}
|
||||
pppLinkDown(unit);
|
||||
}
|
||||
|
||||
/*
|
||||
* The link is established.
|
||||
* Proceed to the Dead, Authenticate or Network phase as appropriate.
|
||||
*/
|
||||
void
|
||||
link_established(int unit)
|
||||
{
|
||||
int auth;
|
||||
int i;
|
||||
struct protent *protp;
|
||||
lcp_options *wo = &lcp_wantoptions[unit];
|
||||
lcp_options *go = &lcp_gotoptions[unit];
|
||||
#if PAP_SUPPORT || CHAP_SUPPORT
|
||||
lcp_options *ho = &lcp_hisoptions[unit];
|
||||
#endif /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "link_established: %d\n", unit));
|
||||
/*
|
||||
* Tell higher-level protocols that LCP is up.
|
||||
*/
|
||||
for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
|
||||
if (protp->protocol != PPP_LCP && protp->enabled_flag && protp->lowerup != NULL) {
|
||||
(*protp->lowerup)(unit);
|
||||
}
|
||||
}
|
||||
if (ppp_settings.auth_required && !(go->neg_chap || go->neg_upap)) {
|
||||
/*
|
||||
* We wanted the peer to authenticate itself, and it refused:
|
||||
* treat it as though it authenticated with PAP using a username
|
||||
* of "" and a password of "". If that's not OK, boot it out.
|
||||
*/
|
||||
if (!wo->neg_upap || !null_login(unit)) {
|
||||
AUTHDEBUG((LOG_WARNING, "peer refused to authenticate\n"));
|
||||
lcp_close(unit, "peer refused to authenticate");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lcp_phase[unit] = PHASE_AUTHENTICATE;
|
||||
auth = 0;
|
||||
#if CHAP_SUPPORT
|
||||
if (go->neg_chap) {
|
||||
ChapAuthPeer(unit, ppp_settings.our_name, go->chap_mdtype);
|
||||
auth |= CHAP_PEER;
|
||||
}
|
||||
#endif /* CHAP_SUPPORT */
|
||||
#if PAP_SUPPORT && CHAP_SUPPORT
|
||||
else
|
||||
#endif /* PAP_SUPPORT && CHAP_SUPPORT */
|
||||
#if PAP_SUPPORT
|
||||
if (go->neg_upap) {
|
||||
upap_authpeer(unit);
|
||||
auth |= PAP_PEER;
|
||||
}
|
||||
#endif /* PAP_SUPPORT */
|
||||
#if CHAP_SUPPORT
|
||||
if (ho->neg_chap) {
|
||||
ChapAuthWithPeer(unit, ppp_settings.user, ho->chap_mdtype);
|
||||
auth |= CHAP_WITHPEER;
|
||||
}
|
||||
#endif /* CHAP_SUPPORT */
|
||||
#if PAP_SUPPORT && CHAP_SUPPORT
|
||||
else
|
||||
#endif /* PAP_SUPPORT && CHAP_SUPPORT */
|
||||
#if PAP_SUPPORT
|
||||
if (ho->neg_upap) {
|
||||
if (ppp_settings.passwd[0] == 0) {
|
||||
passwd_from_file = 1;
|
||||
if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd)) {
|
||||
AUTHDEBUG((LOG_ERR, "No secret found for PAP login\n"));
|
||||
}
|
||||
}
|
||||
upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd);
|
||||
auth |= PAP_WITHPEER;
|
||||
}
|
||||
#endif /* PAP_SUPPORT */
|
||||
auth_pending[unit] = auth;
|
||||
|
||||
if (!auth) {
|
||||
network_phase(unit);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The peer has failed to authenticate himself using `protocol'.
|
||||
*/
|
||||
void
|
||||
auth_peer_fail(int unit, u16_t protocol)
|
||||
{
|
||||
LWIP_UNUSED_ARG(protocol);
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "auth_peer_fail: %d proto=%X\n", unit, protocol));
|
||||
/*
|
||||
* Authentication failure: take the link down
|
||||
*/
|
||||
lcp_close(unit, "Authentication failed");
|
||||
}
|
||||
|
||||
|
||||
#if PAP_SUPPORT || CHAP_SUPPORT
|
||||
/*
|
||||
* The peer has been successfully authenticated using `protocol'.
|
||||
*/
|
||||
void
|
||||
auth_peer_success(int unit, u16_t protocol, char *name, int namelen)
|
||||
{
|
||||
int pbit;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "auth_peer_success: %d proto=%X\n", unit, protocol));
|
||||
switch (protocol) {
|
||||
case PPP_CHAP:
|
||||
pbit = CHAP_PEER;
|
||||
break;
|
||||
case PPP_PAP:
|
||||
pbit = PAP_PEER;
|
||||
break;
|
||||
default:
|
||||
AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n", protocol));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the authenticated name of the peer for later.
|
||||
*/
|
||||
if (namelen > sizeof(peer_authname) - 1) {
|
||||
namelen = sizeof(peer_authname) - 1;
|
||||
}
|
||||
BCOPY(name, peer_authname, namelen);
|
||||
peer_authname[namelen] = 0;
|
||||
|
||||
/*
|
||||
* If there is no more authentication still to be done,
|
||||
* proceed to the network (or callback) phase.
|
||||
*/
|
||||
if ((auth_pending[unit] &= ~pbit) == 0) {
|
||||
network_phase(unit);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We have failed to authenticate ourselves to the peer using `protocol'.
|
||||
*/
|
||||
void
|
||||
auth_withpeer_fail(int unit, u16_t protocol)
|
||||
{
|
||||
int errCode = PPPERR_AUTHFAIL;
|
||||
|
||||
LWIP_UNUSED_ARG(protocol);
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "auth_withpeer_fail: %d proto=%X\n", unit, protocol));
|
||||
if (passwd_from_file) {
|
||||
BZERO(ppp_settings.passwd, MAXSECRETLEN);
|
||||
}
|
||||
/*
|
||||
* XXX Warning: the unit number indicates the interface which is
|
||||
* not necessarily the PPP connection. It works here as long
|
||||
* as we are only supporting PPP interfaces.
|
||||
*/
|
||||
pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode);
|
||||
|
||||
/*
|
||||
* We've failed to authenticate ourselves to our peer.
|
||||
* He'll probably take the link down, and there's not much
|
||||
* we can do except wait for that.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* We have successfully authenticated ourselves with the peer using `protocol'.
|
||||
*/
|
||||
void
|
||||
auth_withpeer_success(int unit, u16_t protocol)
|
||||
{
|
||||
int pbit;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "auth_withpeer_success: %d proto=%X\n", unit, protocol));
|
||||
switch (protocol) {
|
||||
case PPP_CHAP:
|
||||
pbit = CHAP_WITHPEER;
|
||||
break;
|
||||
case PPP_PAP:
|
||||
if (passwd_from_file) {
|
||||
BZERO(ppp_settings.passwd, MAXSECRETLEN);
|
||||
}
|
||||
pbit = PAP_WITHPEER;
|
||||
break;
|
||||
default:
|
||||
AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n", protocol));
|
||||
pbit = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no more authentication still being done,
|
||||
* proceed to the network (or callback) phase.
|
||||
*/
|
||||
if ((auth_pending[unit] &= ~pbit) == 0) {
|
||||
network_phase(unit);
|
||||
}
|
||||
}
|
||||
#endif /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
|
||||
|
||||
/*
|
||||
* np_up - a network protocol has come up.
|
||||
*/
|
||||
void
|
||||
np_up(int unit, u16_t proto)
|
||||
{
|
||||
LWIP_UNUSED_ARG(unit);
|
||||
LWIP_UNUSED_ARG(proto);
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "np_up: %d proto=%X\n", unit, proto));
|
||||
if (num_np_up == 0) {
|
||||
AUTHDEBUG((LOG_INFO, "np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit));
|
||||
/*
|
||||
* At this point we consider that the link has come up successfully.
|
||||
*/
|
||||
if (ppp_settings.idle_time_limit > 0) {
|
||||
TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a timeout to close the connection once the maximum
|
||||
* connect time has expired.
|
||||
*/
|
||||
if (ppp_settings.maxconnect > 0) {
|
||||
TIMEOUT(connect_time_expired, 0, ppp_settings.maxconnect);
|
||||
}
|
||||
}
|
||||
++num_np_up;
|
||||
}
|
||||
|
||||
/*
|
||||
* np_down - a network protocol has gone down.
|
||||
*/
|
||||
void
|
||||
np_down(int unit, u16_t proto)
|
||||
{
|
||||
LWIP_UNUSED_ARG(unit);
|
||||
LWIP_UNUSED_ARG(proto);
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "np_down: %d proto=%X\n", unit, proto));
|
||||
if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) {
|
||||
UNTIMEOUT(check_idle, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* np_finished - a network protocol has finished using the link.
|
||||
*/
|
||||
void
|
||||
np_finished(int unit, u16_t proto)
|
||||
{
|
||||
LWIP_UNUSED_ARG(unit);
|
||||
LWIP_UNUSED_ARG(proto);
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "np_finished: %d proto=%X\n", unit, proto));
|
||||
if (--num_np_open <= 0) {
|
||||
/* no further use for the link: shut up shop. */
|
||||
lcp_close(0, "No network protocols running");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* auth_reset - called when LCP is starting negotiations to recheck
|
||||
* authentication options, i.e. whether we have appropriate secrets
|
||||
* to use for authenticating ourselves and/or the peer.
|
||||
*/
|
||||
void
|
||||
auth_reset(int unit)
|
||||
{
|
||||
lcp_options *go = &lcp_gotoptions[unit];
|
||||
lcp_options *ao = &lcp_allowoptions[0];
|
||||
ipcp_options *ipwo = &ipcp_wantoptions[0];
|
||||
u32_t remote;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "auth_reset: %d\n", unit));
|
||||
ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL));
|
||||
ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/;
|
||||
|
||||
if (go->neg_upap && !have_pap_secret()) {
|
||||
go->neg_upap = 0;
|
||||
}
|
||||
if (go->neg_chap) {
|
||||
remote = ipwo->accept_remote? 0: ipwo->hisaddr;
|
||||
if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote)) {
|
||||
go->neg_chap = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if PAP_SUPPORT
|
||||
/*
|
||||
* check_passwd - Check the user name and passwd against the PAP secrets
|
||||
* file. If requested, also check against the system password database,
|
||||
* and login the user if OK.
|
||||
*
|
||||
* returns:
|
||||
* UPAP_AUTHNAK: Authentication failed.
|
||||
* UPAP_AUTHACK: Authentication succeeded.
|
||||
* In either case, msg points to an appropriate message.
|
||||
*/
|
||||
int
|
||||
check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen)
|
||||
{
|
||||
#if 1
|
||||
LWIP_UNUSED_ARG(unit);
|
||||
LWIP_UNUSED_ARG(auser);
|
||||
LWIP_UNUSED_ARG(userlen);
|
||||
LWIP_UNUSED_ARG(apasswd);
|
||||
LWIP_UNUSED_ARG(passwdlen);
|
||||
LWIP_UNUSED_ARG(msglen);
|
||||
*msg = (char *) 0;
|
||||
return UPAP_AUTHACK; /* XXX Assume all entries OK. */
|
||||
#else
|
||||
int ret = 0;
|
||||
struct wordlist *addrs = NULL;
|
||||
char passwd[256], user[256];
|
||||
char secret[MAXWORDLEN];
|
||||
static u_short attempts = 0;
|
||||
|
||||
/*
|
||||
* Make copies of apasswd and auser, then null-terminate them.
|
||||
*/
|
||||
BCOPY(apasswd, passwd, passwdlen);
|
||||
passwd[passwdlen] = '\0';
|
||||
BCOPY(auser, user, userlen);
|
||||
user[userlen] = '\0';
|
||||
*msg = (char *) 0;
|
||||
|
||||
/* XXX Validate user name and password. */
|
||||
ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */
|
||||
|
||||
if (ret == UPAP_AUTHNAK) {
|
||||
if (*msg == (char *) 0) {
|
||||
*msg = "Login incorrect";
|
||||
}
|
||||
*msglen = strlen(*msg);
|
||||
/*
|
||||
* Frustrate passwd stealer programs.
|
||||
* Allow 10 tries, but start backing off after 3 (stolen from login).
|
||||
* On 10'th, drop the connection.
|
||||
*/
|
||||
if (attempts++ >= 10) {
|
||||
AUTHDEBUG((LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user));
|
||||
/*ppp_panic("Excess Bad Logins");*/
|
||||
}
|
||||
if (attempts > 3) {
|
||||
sys_msleep((attempts - 3) * 5);
|
||||
}
|
||||
if (addrs != NULL) {
|
||||
free_wordlist(addrs);
|
||||
}
|
||||
} else {
|
||||
attempts = 0; /* Reset count */
|
||||
if (*msg == (char *) 0) {
|
||||
*msg = "Login ok";
|
||||
}
|
||||
*msglen = strlen(*msg);
|
||||
set_allowed_addrs(unit, addrs);
|
||||
}
|
||||
|
||||
BZERO(passwd, sizeof(passwd));
|
||||
BZERO(secret, sizeof(secret));
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
#endif /* PAP_SUPPORT */
|
||||
|
||||
|
||||
/*
|
||||
* auth_ip_addr - check whether the peer is authorized to use
|
||||
* a given IP address. Returns 1 if authorized, 0 otherwise.
|
||||
*/
|
||||
int
|
||||
auth_ip_addr(int unit, u32_t addr)
|
||||
{
|
||||
return ip_addr_check(addr, addresses[unit]);
|
||||
}
|
||||
|
||||
/*
|
||||
* bad_ip_adrs - return 1 if the IP address is one we don't want
|
||||
* to use, such as an address in the loopback net or a multicast address.
|
||||
* addr is in network byte order.
|
||||
*/
|
||||
int
|
||||
bad_ip_adrs(u32_t addr)
|
||||
{
|
||||
addr = ntohl(addr);
|
||||
return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
|
||||
|| IN_MULTICAST(addr) || IN_BADCLASS(addr);
|
||||
}
|
||||
|
||||
|
||||
#if CHAP_SUPPORT
|
||||
/*
|
||||
* get_secret - open the CHAP secret file and return the secret
|
||||
* for authenticating the given client on the given server.
|
||||
* (We could be either client or server).
|
||||
*/
|
||||
int get_secret( int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs)
|
||||
{
|
||||
#if 1
|
||||
int len;
|
||||
struct wordlist *addrs;
|
||||
|
||||
LWIP_UNUSED_ARG(unit);
|
||||
LWIP_UNUSED_ARG(server);
|
||||
LWIP_UNUSED_ARG(save_addrs);
|
||||
|
||||
addrs = NULL;
|
||||
|
||||
if(!client || !client[0] || strcmp(client, ppp_settings.user)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = strlen(ppp_settings.passwd);
|
||||
if (len > MAXSECRETLEN) {
|
||||
AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
|
||||
len = MAXSECRETLEN;
|
||||
}
|
||||
|
||||
BCOPY(ppp_settings.passwd, secret, len);
|
||||
*secret_len = len;
|
||||
|
||||
return 1;
|
||||
#else
|
||||
int ret = 0, len;
|
||||
struct wordlist *addrs;
|
||||
char secbuf[MAXWORDLEN];
|
||||
|
||||
addrs = NULL;
|
||||
secbuf[0] = 0;
|
||||
|
||||
/* XXX Find secret. */
|
||||
if (ret < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (save_addrs) {
|
||||
set_allowed_addrs(unit, addrs);
|
||||
}
|
||||
|
||||
len = strlen(secbuf);
|
||||
if (len > MAXSECRETLEN) {
|
||||
AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
|
||||
len = MAXSECRETLEN;
|
||||
}
|
||||
|
||||
BCOPY(secbuf, secret, len);
|
||||
BZERO(secbuf, sizeof(secbuf));
|
||||
*secret_len = len;
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
#endif /* CHAP_SUPPORT */
|
||||
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
/*
|
||||
* auth_check_options - called to check authentication options.
|
||||
*/
|
||||
void
|
||||
auth_check_options(void)
|
||||
{
|
||||
lcp_options *wo = &lcp_wantoptions[0];
|
||||
int can_auth;
|
||||
ipcp_options *ipwo = &ipcp_wantoptions[0];
|
||||
u32_t remote;
|
||||
|
||||
/* Default our_name to hostname, and user to our_name */
|
||||
if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname) {
|
||||
strcpy(ppp_settings.our_name, ppp_settings.hostname);
|
||||
}
|
||||
|
||||
if (ppp_settings.user[0] == 0) {
|
||||
strcpy(ppp_settings.user, ppp_settings.our_name);
|
||||
}
|
||||
|
||||
/* If authentication is required, ask peer for CHAP or PAP. */
|
||||
if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) {
|
||||
wo->neg_chap = 1;
|
||||
wo->neg_upap = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether we have appropriate secrets to use
|
||||
* to authenticate the peer.
|
||||
*/
|
||||
can_auth = wo->neg_upap && have_pap_secret();
|
||||
if (!can_auth && wo->neg_chap) {
|
||||
remote = ipwo->accept_remote? 0: ipwo->hisaddr;
|
||||
can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote);
|
||||
}
|
||||
|
||||
if (ppp_settings.auth_required && !can_auth) {
|
||||
ppp_panic("No auth secret");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
/*
|
||||
* Proceed to the network phase.
|
||||
*/
|
||||
static void
|
||||
network_phase(int unit)
|
||||
{
|
||||
int i;
|
||||
struct protent *protp;
|
||||
lcp_options *go = &lcp_gotoptions[unit];
|
||||
|
||||
/*
|
||||
* If the peer had to authenticate, run the auth-up script now.
|
||||
*/
|
||||
if ((go->neg_chap || go->neg_upap) && !did_authup) {
|
||||
/* XXX Do setup for peer authentication. */
|
||||
did_authup = 1;
|
||||
}
|
||||
|
||||
#if CBCP_SUPPORT
|
||||
/*
|
||||
* If we negotiated callback, do it now.
|
||||
*/
|
||||
if (go->neg_cbcp) {
|
||||
lcp_phase[unit] = PHASE_CALLBACK;
|
||||
(*cbcp_protent.open)(unit);
|
||||
return;
|
||||
}
|
||||
#endif /* CBCP_SUPPORT */
|
||||
|
||||
lcp_phase[unit] = PHASE_NETWORK;
|
||||
for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
|
||||
if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) {
|
||||
(*protp->open)(unit);
|
||||
if (protp->protocol != PPP_CCP) {
|
||||
++num_np_open;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_np_open == 0) {
|
||||
/* nothing to do */
|
||||
lcp_close(0, "No network protocols running");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* check_idle - check whether the link has been idle for long
|
||||
* enough that we can shut it down.
|
||||
*/
|
||||
static void
|
||||
check_idle(void *arg)
|
||||
{
|
||||
struct ppp_idle idle;
|
||||
u_short itime;
|
||||
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
if (!get_idle_time(0, &idle)) {
|
||||
return;
|
||||
}
|
||||
itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);
|
||||
if (itime >= ppp_settings.idle_time_limit) {
|
||||
/* link is idle: shut it down. */
|
||||
AUTHDEBUG((LOG_INFO, "Terminating connection due to lack of activity.\n"));
|
||||
lcp_close(0, "Link inactive");
|
||||
} else {
|
||||
TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* connect_time_expired - log a message and close the connection.
|
||||
*/
|
||||
static void
|
||||
connect_time_expired(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "Connect time expired\n"));
|
||||
lcp_close(0, "Connect time expired"); /* Close connection */
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* login - Check the user name and password against the system
|
||||
* password database, and login the user if OK.
|
||||
*
|
||||
* returns:
|
||||
* UPAP_AUTHNAK: Login failed.
|
||||
* UPAP_AUTHACK: Login succeeded.
|
||||
* In either case, msg points to an appropriate message.
|
||||
*/
|
||||
static int
|
||||
login(char *user, char *passwd, char **msg, int *msglen)
|
||||
{
|
||||
/* XXX Fail until we decide that we want to support logins. */
|
||||
return (UPAP_AUTHNAK);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* logout - Logout the user.
|
||||
*/
|
||||
static void
|
||||
logout(void)
|
||||
{
|
||||
logged_in = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* null_login - Check if a username of "" and a password of "" are
|
||||
* acceptable, and iff so, set the list of acceptable IP addresses
|
||||
* and return 1.
|
||||
*/
|
||||
static int
|
||||
null_login(int unit)
|
||||
{
|
||||
LWIP_UNUSED_ARG(unit);
|
||||
/* XXX Fail until we decide that we want to support logins. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_pap_passwd - get a password for authenticating ourselves with
|
||||
* our peer using PAP. Returns 1 on success, 0 if no suitable password
|
||||
* could be found.
|
||||
*/
|
||||
static int
|
||||
get_pap_passwd(int unit, char *user, char *passwd)
|
||||
{
|
||||
LWIP_UNUSED_ARG(unit);
|
||||
/* normally we would reject PAP if no password is provided,
|
||||
but this causes problems with some providers (like CHT in Taiwan)
|
||||
who incorrectly request PAP and expect a bogus/empty password, so
|
||||
always provide a default user/passwd of "none"/"none"
|
||||
*/
|
||||
if(user) {
|
||||
strcpy(user, "none");
|
||||
}
|
||||
if(passwd) {
|
||||
strcpy(passwd, "none");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* have_pap_secret - check whether we have a PAP file with any
|
||||
* secrets that we could possibly use for authenticating the peer.
|
||||
*/
|
||||
static int
|
||||
have_pap_secret(void)
|
||||
{
|
||||
/* XXX Fail until we set up our passwords. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* have_chap_secret - check whether we have a CHAP file with a
|
||||
* secret that we could possibly use for authenticating `client'
|
||||
* on `server'. Either can be the null string, meaning we don't
|
||||
* know the identity yet.
|
||||
*/
|
||||
static int
|
||||
have_chap_secret(char *client, char *server, u32_t remote)
|
||||
{
|
||||
LWIP_UNUSED_ARG(client);
|
||||
LWIP_UNUSED_ARG(server);
|
||||
LWIP_UNUSED_ARG(remote);
|
||||
/* XXX Fail until we set up our passwords. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
/*
|
||||
* set_allowed_addrs() - set the list of allowed addresses.
|
||||
*/
|
||||
static void
|
||||
set_allowed_addrs(int unit, struct wordlist *addrs)
|
||||
{
|
||||
if (addresses[unit] != NULL) {
|
||||
free_wordlist(addresses[unit]);
|
||||
}
|
||||
addresses[unit] = addrs;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* If there's only one authorized address we might as well
|
||||
* ask our peer for that one right away
|
||||
*/
|
||||
if (addrs != NULL && addrs->next == NULL) {
|
||||
char *p = addrs->word;
|
||||
struct ipcp_options *wo = &ipcp_wantoptions[unit];
|
||||
u32_t a;
|
||||
struct hostent *hp;
|
||||
|
||||
if (wo->hisaddr == 0 && *p != '!' && *p != '-' && strchr(p, '/') == NULL) {
|
||||
hp = gethostbyname(p);
|
||||
if (hp != NULL && hp->h_addrtype == AF_INET) {
|
||||
a = *(u32_t *)hp->h_addr;
|
||||
} else {
|
||||
a = inet_addr(p);
|
||||
}
|
||||
if (a != (u32_t) -1) {
|
||||
wo->hisaddr = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
|
||||
static int
|
||||
ip_addr_check(u32_t addr, struct wordlist *addrs)
|
||||
{
|
||||
/* don't allow loopback or multicast address */
|
||||
if (bad_ip_adrs(addr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (addrs == NULL) {
|
||||
return !ppp_settings.auth_required; /* no addresses authorized */
|
||||
}
|
||||
|
||||
/* XXX All other addresses allowed. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
/*
|
||||
* free_wordlist - release memory allocated for a wordlist.
|
||||
*/
|
||||
static void
|
||||
free_wordlist(struct wordlist *wp)
|
||||
{
|
||||
struct wordlist *next;
|
||||
|
||||
while (wp != NULL) {
|
||||
next = wp->next;
|
||||
free(wp);
|
||||
wp = next;
|
||||
}
|
||||
}
|
||||
#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
111
lwip/src/netif/ppp/auth.h
Normal file
111
lwip/src/netif/ppp/auth.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*****************************************************************************
|
||||
* auth.h - PPP Authentication and phase control header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1998 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original derived from BSD pppd.h.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTH_H
|
||||
#define AUTH_H
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
/* we are starting to use the link */
|
||||
void link_required (int);
|
||||
|
||||
/* we are finished with the link */
|
||||
void link_terminated (int);
|
||||
|
||||
/* the LCP layer has left the Opened state */
|
||||
void link_down (int);
|
||||
|
||||
/* the link is up; authenticate now */
|
||||
void link_established (int);
|
||||
|
||||
/* a network protocol has come up */
|
||||
void np_up (int, u16_t);
|
||||
|
||||
/* a network protocol has gone down */
|
||||
void np_down (int, u16_t);
|
||||
|
||||
/* a network protocol no longer needs link */
|
||||
void np_finished (int, u16_t);
|
||||
|
||||
/* peer failed to authenticate itself */
|
||||
void auth_peer_fail (int, u16_t);
|
||||
|
||||
/* peer successfully authenticated itself */
|
||||
void auth_peer_success (int, u16_t, char *, int);
|
||||
|
||||
/* we failed to authenticate ourselves */
|
||||
void auth_withpeer_fail (int, u16_t);
|
||||
|
||||
/* we successfully authenticated ourselves */
|
||||
void auth_withpeer_success (int, u16_t);
|
||||
|
||||
/* check authentication options supplied */
|
||||
void auth_check_options (void);
|
||||
|
||||
/* check what secrets we have */
|
||||
void auth_reset (int);
|
||||
|
||||
/* Check peer-supplied username/password */
|
||||
int check_passwd (int, char *, int, char *, int, char **, int *);
|
||||
|
||||
/* get "secret" for chap */
|
||||
int get_secret (int, char *, char *, char *, int *, int);
|
||||
|
||||
/* check if IP address is authorized */
|
||||
int auth_ip_addr (int, u32_t);
|
||||
|
||||
/* check if IP address is unreasonable */
|
||||
int bad_ip_adrs (u32_t);
|
||||
|
||||
#endif /* AUTH_H */
|
903
lwip/src/netif/ppp/chap.c
Normal file
903
lwip/src/netif/ppp/chap.c
Normal file
|
@ -0,0 +1,903 @@
|
|||
/*** WARNING - THIS HAS NEVER BEEN FINISHED ***/
|
||||
/*****************************************************************************
|
||||
* chap.c - Network Challenge Handshake Authentication Protocol program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original based on BSD chap.c.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "magic.h"
|
||||
#include "randm.h"
|
||||
#include "auth.h"
|
||||
#include "md5.h"
|
||||
#include "chap.h"
|
||||
#include "chpms.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* 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);
|
||||
#if 0
|
||||
static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *);
|
||||
#endif
|
||||
|
||||
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 *cstate, u_char *inp, u_char id, int len);
|
||||
static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
|
||||
static void ChapSendStatus (chap_state *, int);
|
||||
static void ChapSendChallenge (chap_state *);
|
||||
static void ChapSendResponse (chap_state *);
|
||||
static void ChapGenChallenge (chap_state *);
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
|
||||
|
||||
struct protent chap_protent = {
|
||||
PPP_CHAP,
|
||||
ChapInit,
|
||||
ChapInput,
|
||||
ChapProtocolReject,
|
||||
ChapLowerUp,
|
||||
ChapLowerDown,
|
||||
NULL,
|
||||
NULL,
|
||||
#if 0
|
||||
ChapPrintPkt,
|
||||
NULL,
|
||||
#endif
|
||||
1,
|
||||
"CHAP",
|
||||
#if 0
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
/*
|
||||
* 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 */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
CHAPDEBUG((LOG_ERR, "Peer failed to respond to CHAP challenge\n"));
|
||||
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((LOG_INFO, "ChapInput: rcvd short header.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
GETSHORT(len, inp);
|
||||
if (len < CHAP_HEADERLEN) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length.\n"));
|
||||
return;
|
||||
}
|
||||
if (len > packet_len) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet.\n"));
|
||||
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? */
|
||||
CHAPDEBUG((LOG_WARNING, "Unknown CHAP code (%d) received.\n", 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;
|
||||
char secret[MAXSECRETLEN];
|
||||
char rhostname[256];
|
||||
MD5_CTX mdContext;
|
||||
u_char hash[MD5_SIGNATURE_SIZE];
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.\n", id));
|
||||
if (cstate->clientstate == CHAPCS_CLOSED ||
|
||||
cstate->clientstate == CHAPCS_PENDING) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d\n",
|
||||
cstate->clientstate));
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < 2) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
GETCHAR(rchallenge_len, inp);
|
||||
len -= sizeof (u_char) + rchallenge_len; /* now name field length */
|
||||
if (len < 0) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
rchallenge = inp;
|
||||
INCPTR(rchallenge_len, inp);
|
||||
|
||||
if (len >= sizeof(rhostname)) {
|
||||
len = sizeof(rhostname) - 1;
|
||||
}
|
||||
BCOPY(inp, rhostname, len);
|
||||
rhostname[len] = '\000';
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'\n", rhostname));
|
||||
|
||||
/* Microsoft doesn't send their name back in the PPP packet */
|
||||
if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) {
|
||||
strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname));
|
||||
rhostname[sizeof(rhostname) - 1] = 0;
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name\n", 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 */
|
||||
CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating us to %s\n", 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, (u_char*)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((LOG_INFO, "unknown digest type %d\n", 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;
|
||||
char secret[MAXSECRETLEN];
|
||||
u_char hash[MD5_SIGNATURE_SIZE];
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.\n", id));
|
||||
|
||||
if (cstate->serverstate == CHAPSS_CLOSED ||
|
||||
cstate->serverstate == CHAPSS_PENDING) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d\n",
|
||||
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((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
|
||||
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((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
UNTIMEOUT(ChapChallengeTimeout, cstate);
|
||||
|
||||
if (len >= sizeof(rhostname)) {
|
||||
len = sizeof(rhostname) - 1;
|
||||
}
|
||||
BCOPY(inp, rhostname, len);
|
||||
rhostname[len] = '\000';
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s\n", rhostname));
|
||||
|
||||
/*
|
||||
* Get secret for authenticating them with us,
|
||||
* do the hash ourselves, and compare the result.
|
||||
*/
|
||||
code = CHAP_FAILURE;
|
||||
if (!get_secret(cstate->unit, rhostname, cstate->chal_name, secret, &secret_len, 1)) {
|
||||
/* CHAPDEBUG((LOG_WARNING, TL_CHAP, "No CHAP secret found for authenticating %s\n", rhostname)); */
|
||||
CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating %s\n",
|
||||
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, (u_char*)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((LOG_INFO, "unknown digest type %d\n", 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);
|
||||
}
|
||||
} else {
|
||||
CHAPDEBUG((LOG_ERR, "CHAP peer authentication failed\n"));
|
||||
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)
|
||||
{
|
||||
LWIP_UNUSED_ARG(id);
|
||||
LWIP_UNUSED_ARG(inp);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.\n", id));
|
||||
|
||||
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((LOG_INFO, "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)
|
||||
{
|
||||
LWIP_UNUSED_ARG(id);
|
||||
LWIP_UNUSED_ARG(inp);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.\n", id));
|
||||
|
||||
if (cstate->clientstate != CHAPCS_RESPONSE) {
|
||||
/* don't know what this is */
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n", cstate->clientstate));
|
||||
return;
|
||||
}
|
||||
|
||||
UNTIMEOUT(ChapResponseTimeout, cstate);
|
||||
|
||||
/*
|
||||
* Print message.
|
||||
*/
|
||||
if (len > 0) {
|
||||
PRINTMSG(inp, len);
|
||||
}
|
||||
|
||||
CHAPDEBUG((LOG_ERR, "CHAP authentication failed\n"));
|
||||
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[cstate->unit];
|
||||
|
||||
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 */
|
||||
|
||||
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
|
||||
|
||||
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) {
|
||||
strcpy(msg, "Welcome!");
|
||||
} else {
|
||||
strcpy(msg, "I don't like you. Go 'way.");
|
||||
}
|
||||
msglen = strlen(msg);
|
||||
|
||||
outlen = CHAP_HEADERLEN + msglen;
|
||||
outp = outpacket_buf[cstate->unit];
|
||||
|
||||
MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
|
||||
|
||||
PUTCHAR(code, outp);
|
||||
PUTCHAR(cstate->chal_id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
BCOPY(msg, outp, msglen);
|
||||
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.\n", code, cstate->chal_id));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
((((magic() >> 16) *
|
||||
(MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16)
|
||||
+ 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) (magic() & 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[cstate->unit];
|
||||
|
||||
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 */
|
||||
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
|
||||
|
||||
cstate->clientstate = CHAPCS_RESPONSE;
|
||||
TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
|
||||
++cstate->resp_transmits;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char *ChapCodenames[] = {
|
||||
"Challenge", "Response", "Success", "Failure"
|
||||
};
|
||||
/*
|
||||
* ChapPrintPkt - print the contents of a CHAP packet.
|
||||
*/
|
||||
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 = %.*Z", nlen, p);
|
||||
break;
|
||||
case CHAP_FAILURE:
|
||||
case CHAP_SUCCESS:
|
||||
printer(arg, " %.*Z", len, p);
|
||||
break;
|
||||
default:
|
||||
for (clen = len; clen > 0; --clen) {
|
||||
GETCHAR(x, p);
|
||||
printer(arg, " %.2x", x);
|
||||
}
|
||||
}
|
||||
|
||||
return len + CHAP_HEADERLEN;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CHAP_SUPPORT */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
166
lwip/src/netif/ppp/chap.h
Normal file
166
lwip/src/netif/ppp/chap.h
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*****************************************************************************
|
||||
* chap.h - Network Challenge Handshake Authentication Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1998 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-03 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original built from BSD network code.
|
||||
******************************************************************************/
|
||||
/*
|
||||
* 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: chap.h,v 1.4 2007/12/19 20:47:22 fbernon Exp $
|
||||
*/
|
||||
|
||||
#ifndef CHAP_H
|
||||
#define CHAP_H
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
|
||||
/* 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 32
|
||||
#define MAX_CHALLENGE_LENGTH 64
|
||||
#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
/******************
|
||||
*** PUBLIC DATA ***
|
||||
******************/
|
||||
extern chap_state chap[];
|
||||
|
||||
extern struct protent chap_protent;
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
void ChapAuthWithPeer (int, char *, int);
|
||||
void ChapAuthPeer (int, char *, int);
|
||||
|
||||
#endif /* CHAP_H */
|
399
lwip/src/netif/ppp/chpms.c
Normal file
399
lwip/src/netif/ppp/chpms.c
Normal file
|
@ -0,0 +1,399 @@
|
|||
/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/
|
||||
/*** The original PPPD code is written in a way to require either the UNIX DES
|
||||
encryption functions encrypt(3) and setkey(3) or the DES library libdes.
|
||||
Since both is not included in lwIP, MSCHAP currently does not work! */
|
||||
/*****************************************************************************
|
||||
* chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original based on BSD chap_ms.c.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 USE_CRYPT
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#if MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "md4.h"
|
||||
#ifndef USE_CRYPT
|
||||
#include "des.h"
|
||||
#endif
|
||||
#include "chap.h"
|
||||
#include "chpms.h"
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
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. */
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
|
||||
/* XXX Don't know what to do with these. */
|
||||
extern void setkey(const char *);
|
||||
extern void encrypt(char *, int);
|
||||
|
||||
static void DesEncrypt (u_char *, u_char *, u_char *);
|
||||
static void MakeKey (u_char *, u_char *);
|
||||
|
||||
#ifdef USE_CRYPT
|
||||
static void Expand (u_char *, u_char *);
|
||||
static void Collapse (u_char *, u_char *);
|
||||
#endif
|
||||
|
||||
static void ChallengeResponse(
|
||||
u_char *challenge, /* IN 8 octets */
|
||||
u_char *pwHash, /* IN 16 octets */
|
||||
u_char *response /* OUT 24 octets */
|
||||
);
|
||||
static void ChapMS_NT(
|
||||
char *rchallenge,
|
||||
int rchallenge_len,
|
||||
char *secret,
|
||||
int secret_len,
|
||||
MS_ChapResponse *response
|
||||
);
|
||||
static u_char Get7Bits(
|
||||
u_char *input,
|
||||
int startBit
|
||||
);
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
void
|
||||
ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len)
|
||||
{
|
||||
MS_ChapResponse response;
|
||||
#ifdef MSLANMAN
|
||||
extern int ms_lanman;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'\n", 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;
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
static void
|
||||
ChallengeResponse( 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, 16);
|
||||
|
||||
#if 0
|
||||
log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG);
|
||||
#endif
|
||||
|
||||
DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
|
||||
DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
|
||||
DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
|
||||
|
||||
#if 0
|
||||
log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_CRYPT
|
||||
static void
|
||||
DesEncrypt( 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 : %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
|
||||
#endif
|
||||
|
||||
Expand(clear, des_input);
|
||||
encrypt(des_input, 0);
|
||||
Collapse(des_input, cipher);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* USE_CRYPT */
|
||||
|
||||
static void
|
||||
DesEncrypt( 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 : %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
|
||||
#endif
|
||||
|
||||
des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* USE_CRYPT */
|
||||
|
||||
|
||||
static u_char
|
||||
Get7Bits( 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(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(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( 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 : %02X%02X%02X%02X%02X%02X%02X\n",
|
||||
key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
|
||||
CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ChapMS_NT( char *rchallenge,
|
||||
int rchallenge_len,
|
||||
char *secret,
|
||||
int secret_len,
|
||||
MS_ChapResponse *response)
|
||||
{
|
||||
int i;
|
||||
MDstruct md4Context;
|
||||
u_char unicodePassword[MAX_NT_PASSWORD * 2];
|
||||
static int low_byte_first = -1;
|
||||
|
||||
/* 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];
|
||||
}
|
||||
MDbegin(&md4Context);
|
||||
MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */
|
||||
|
||||
if (low_byte_first == -1) {
|
||||
low_byte_first = (htons((unsigned short int)1) != 1);
|
||||
}
|
||||
if (low_byte_first == 0) {
|
||||
MDreverse((u_long *)&md4Context); /* sfb 961105 */
|
||||
}
|
||||
|
||||
MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */
|
||||
|
||||
ChallengeResponse(rchallenge, (char *)md4Context.buffer, response->NTResp);
|
||||
}
|
||||
|
||||
#ifdef MSLANMAN
|
||||
static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
|
||||
|
||||
static void
|
||||
ChapMS_LANMan( 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[16];
|
||||
|
||||
/* 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
|
||||
|
||||
#endif /* MSCHAP_SUPPORT */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
64
lwip/src/netif/ppp/chpms.h
Normal file
64
lwip/src/netif/ppp/chpms.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*****************************************************************************
|
||||
* chpms.h - Network Microsoft Challenge Handshake Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1998 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 98-01-30 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original built from BSD network code.
|
||||
******************************************************************************/
|
||||
/*
|
||||
* 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: chpms.h,v 1.5 2007/12/19 20:47:23 fbernon Exp $
|
||||
*/
|
||||
|
||||
#ifndef CHPMS_H
|
||||
#define CHPMS_H
|
||||
|
||||
#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */
|
||||
|
||||
void ChapMS (chap_state *, char *, int, char *, int);
|
||||
|
||||
#endif /* CHPMS_H */
|
908
lwip/src/netif/ppp/fsm.c
Normal file
908
lwip/src/netif/ppp/fsm.c
Normal file
|
@ -0,0 +1,908 @@
|
|||
/*****************************************************************************
|
||||
* fsm.c - Network Control Protocol Finite State Machine program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original based on BSD fsm.c.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "fsm.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
||||
#if PPP_DEBUG
|
||||
|
||||
static const char *ppperr_strerr[] = {
|
||||
"LS_INITIAL", /* LS_INITIAL 0 */
|
||||
"LS_STARTING", /* LS_STARTING 1 */
|
||||
"LS_CLOSED", /* LS_CLOSED 2 */
|
||||
"LS_STOPPED", /* LS_STOPPED 3 */
|
||||
"LS_CLOSING", /* LS_CLOSING 4 */
|
||||
"LS_STOPPING", /* LS_STOPPING 5 */
|
||||
"LS_REQSENT", /* LS_REQSENT 6 */
|
||||
"LS_ACKRCVD", /* LS_ACKRCVD 7 */
|
||||
"LS_ACKSENT", /* LS_ACKSENT 8 */
|
||||
"LS_OPENED" /* LS_OPENED 9 */
|
||||
};
|
||||
|
||||
#endif /* PPP_DEBUG */
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
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)
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
int peer_mru[NUM_PPP];
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
|
||||
/*
|
||||
* fsm_init - Initialize fsm.
|
||||
*
|
||||
* Initialize fsm state.
|
||||
*/
|
||||
void
|
||||
fsm_init(fsm *f)
|
||||
{
|
||||
f->state = LS_INITIAL;
|
||||
f->flags = 0;
|
||||
f->id = 0; /* XXX Start with random id? */
|
||||
f->timeouttime = FSM_DEFTIMEOUT;
|
||||
f->maxconfreqtransmits = FSM_DEFMAXCONFREQS;
|
||||
f->maxtermtransmits = FSM_DEFMAXTERMREQS;
|
||||
f->maxnakloops = FSM_DEFMAXNAKLOOPS;
|
||||
f->term_reason_len = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_lowerup - The lower layer is up.
|
||||
*/
|
||||
void
|
||||
fsm_lowerup(fsm *f)
|
||||
{
|
||||
int oldState = f->state;
|
||||
|
||||
LWIP_UNUSED_ARG(oldState);
|
||||
|
||||
switch( f->state ) {
|
||||
case LS_INITIAL:
|
||||
f->state = LS_CLOSED;
|
||||
break;
|
||||
|
||||
case LS_STARTING:
|
||||
if( f->flags & OPT_SILENT ) {
|
||||
f->state = LS_STOPPED;
|
||||
} else {
|
||||
/* Send an initial configure-request */
|
||||
fsm_sconfreq(f, 0);
|
||||
f->state = LS_REQSENT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Up event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: lowerup state %d (%s) -> %d (%s)\n",
|
||||
PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_lowerdown - The lower layer is down.
|
||||
*
|
||||
* Cancel all timeouts and inform upper layers.
|
||||
*/
|
||||
void
|
||||
fsm_lowerdown(fsm *f)
|
||||
{
|
||||
int oldState = f->state;
|
||||
|
||||
LWIP_UNUSED_ARG(oldState);
|
||||
|
||||
switch( f->state ) {
|
||||
case LS_CLOSED:
|
||||
f->state = LS_INITIAL;
|
||||
break;
|
||||
|
||||
case LS_STOPPED:
|
||||
f->state = LS_STARTING;
|
||||
if( f->callbacks->starting ) {
|
||||
(*f->callbacks->starting)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_CLOSING:
|
||||
f->state = LS_INITIAL;
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
break;
|
||||
|
||||
case LS_STOPPING:
|
||||
case LS_REQSENT:
|
||||
case LS_ACKRCVD:
|
||||
case LS_ACKSENT:
|
||||
f->state = LS_STARTING;
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
break;
|
||||
|
||||
case LS_OPENED:
|
||||
if( f->callbacks->down ) {
|
||||
(*f->callbacks->down)(f);
|
||||
}
|
||||
f->state = LS_STARTING;
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Down event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: lowerdown state %d (%s) -> %d (%s)\n",
|
||||
PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_open - Link is allowed to come up.
|
||||
*/
|
||||
void
|
||||
fsm_open(fsm *f)
|
||||
{
|
||||
int oldState = f->state;
|
||||
|
||||
LWIP_UNUSED_ARG(oldState);
|
||||
|
||||
switch( f->state ) {
|
||||
case LS_INITIAL:
|
||||
f->state = LS_STARTING;
|
||||
if( f->callbacks->starting ) {
|
||||
(*f->callbacks->starting)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_CLOSED:
|
||||
if( f->flags & OPT_SILENT ) {
|
||||
f->state = LS_STOPPED;
|
||||
} else {
|
||||
/* Send an initial configure-request */
|
||||
fsm_sconfreq(f, 0);
|
||||
f->state = LS_REQSENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_CLOSING:
|
||||
f->state = LS_STOPPING;
|
||||
/* fall through */
|
||||
case LS_STOPPED:
|
||||
case LS_OPENED:
|
||||
if( f->flags & OPT_RESTART ) {
|
||||
fsm_lowerdown(f);
|
||||
fsm_lowerup(f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: open state %d (%s) -> %d (%s)\n",
|
||||
PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_close - Start closing connection.
|
||||
*
|
||||
* Cancel timeouts and either initiate close or possibly go directly to
|
||||
* the LS_CLOSED state.
|
||||
*/
|
||||
void
|
||||
fsm_close(fsm *f, char *reason)
|
||||
{
|
||||
int oldState = f->state;
|
||||
|
||||
LWIP_UNUSED_ARG(oldState);
|
||||
|
||||
f->term_reason = reason;
|
||||
f->term_reason_len = (reason == NULL? 0: strlen(reason));
|
||||
switch( f->state ) {
|
||||
case LS_STARTING:
|
||||
f->state = LS_INITIAL;
|
||||
break;
|
||||
case LS_STOPPED:
|
||||
f->state = LS_CLOSED;
|
||||
break;
|
||||
case LS_STOPPING:
|
||||
f->state = LS_CLOSING;
|
||||
break;
|
||||
|
||||
case LS_REQSENT:
|
||||
case LS_ACKRCVD:
|
||||
case LS_ACKSENT:
|
||||
case LS_OPENED:
|
||||
if( f->state != LS_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 = LS_CLOSING;
|
||||
break;
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: close reason=%s state %d (%s) -> %d (%s)\n",
|
||||
PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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[f->unit];
|
||||
if (datalen > peer_mru[f->unit] - (int)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);
|
||||
pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN);
|
||||
FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d,%d,%d.\n",
|
||||
PROTO_NAME(f), code, id, outlen));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_input - Input packet.
|
||||
*/
|
||||
void
|
||||
fsm_input(fsm *f, u_char *inpacket, int l)
|
||||
{
|
||||
u_char *inp = inpacket;
|
||||
u_char code, id;
|
||||
int len;
|
||||
|
||||
/*
|
||||
* Parse header (code, id and length).
|
||||
* If packet too short, drop it.
|
||||
*/
|
||||
if (l < HEADERLEN) {
|
||||
FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.\n",
|
||||
f->protocol));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
GETSHORT(len, inp);
|
||||
if (len < HEADERLEN) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.\n",
|
||||
f->protocol));
|
||||
return;
|
||||
}
|
||||
if (len > l) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.\n",
|
||||
f->protocol));
|
||||
return;
|
||||
}
|
||||
len -= HEADERLEN; /* subtract header length */
|
||||
|
||||
if( f->state == LS_INITIAL || f->state == LS_STARTING ) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d (%s).\n",
|
||||
f->protocol, f->state, ppperr_strerr[f->state]));
|
||||
return;
|
||||
}
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l));
|
||||
/*
|
||||
* 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_protreject - Peer doesn't speak this protocol.
|
||||
*
|
||||
* Treat this as a catastrophic error (RXJ-).
|
||||
*/
|
||||
void
|
||||
fsm_protreject(fsm *f)
|
||||
{
|
||||
switch( f->state ) {
|
||||
case LS_CLOSING:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
/* fall through */
|
||||
case LS_CLOSED:
|
||||
f->state = LS_CLOSED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_STOPPING:
|
||||
case LS_REQSENT:
|
||||
case LS_ACKRCVD:
|
||||
case LS_ACKSENT:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
/* fall through */
|
||||
case LS_STOPPED:
|
||||
f->state = LS_STOPPED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_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 = LS_STOPPING;
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
|
||||
/*
|
||||
* fsm_timeout - Timeout expired.
|
||||
*/
|
||||
static void
|
||||
fsm_timeout(void *arg)
|
||||
{
|
||||
fsm *f = (fsm *) arg;
|
||||
|
||||
switch (f->state) {
|
||||
case LS_CLOSING:
|
||||
case LS_STOPPING:
|
||||
if( f->retransmits <= 0 ) {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout sending Terminate-Request state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
/*
|
||||
* We've waited for an ack long enough. Peer probably heard us.
|
||||
*/
|
||||
f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
} else {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout resending Terminate-Requests state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
/* 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 LS_REQSENT:
|
||||
case LS_ACKRCVD:
|
||||
case LS_ACKSENT:
|
||||
if (f->retransmits <= 0) {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout sending Config-Requests state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
f->state = LS_STOPPED;
|
||||
if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
} else {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout resending Config-Request state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
/* Retransmit the configure-request */
|
||||
if (f->callbacks->retransmit) {
|
||||
(*f->callbacks->retransmit)(f);
|
||||
}
|
||||
fsm_sconfreq(f, 1); /* Re-send Configure-Request */
|
||||
if( f->state == LS_ACKRCVD ) {
|
||||
f->state = LS_REQSENT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: UNHANDLED timeout event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rconfreq - Receive Configure-Request.
|
||||
*/
|
||||
static void
|
||||
fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len)
|
||||
{
|
||||
int code, reject_if_disagree;
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n",
|
||||
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
|
||||
switch( f->state ) {
|
||||
case LS_CLOSED:
|
||||
/* Go away, we're closed */
|
||||
fsm_sdata(f, TERMACK, id, NULL, 0);
|
||||
return;
|
||||
case LS_CLOSING:
|
||||
case LS_STOPPING:
|
||||
return;
|
||||
|
||||
case LS_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 LS_STOPPED:
|
||||
/* Negotiation started by our peer */
|
||||
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
|
||||
f->state = LS_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, (u_char)code, id, inp, len);
|
||||
|
||||
if (code == CONFACK) {
|
||||
if (f->state == LS_ACKRCVD) {
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
f->state = LS_OPENED;
|
||||
if (f->callbacks->up) {
|
||||
(*f->callbacks->up)(f); /* Inform upper layers */
|
||||
}
|
||||
} else {
|
||||
f->state = LS_ACKSENT;
|
||||
}
|
||||
f->nakloops = 0;
|
||||
} else {
|
||||
/* we sent CONFACK or CONFREJ */
|
||||
if (f->state != LS_ACKRCVD) {
|
||||
f->state = LS_REQSENT;
|
||||
}
|
||||
if( code == CONFNAK ) {
|
||||
++f->nakloops;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rconfack - Receive Configure-Ack.
|
||||
*/
|
||||
static void
|
||||
fsm_rconfack(fsm *f, int id, u_char *inp, int len)
|
||||
{
|
||||
FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n",
|
||||
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
|
||||
|
||||
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 */
|
||||
FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)\n",
|
||||
PROTO_NAME(f), len));
|
||||
return;
|
||||
}
|
||||
f->seen_ack = 1;
|
||||
|
||||
switch (f->state) {
|
||||
case LS_CLOSED:
|
||||
case LS_STOPPED:
|
||||
fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
|
||||
break;
|
||||
|
||||
case LS_REQSENT:
|
||||
f->state = LS_ACKRCVD;
|
||||
f->retransmits = f->maxconfreqtransmits;
|
||||
break;
|
||||
|
||||
case LS_ACKRCVD:
|
||||
/* Huh? an extra valid Ack? oh well... */
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
fsm_sconfreq(f, 0);
|
||||
f->state = LS_REQSENT;
|
||||
break;
|
||||
|
||||
case LS_ACKSENT:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
f->state = LS_OPENED;
|
||||
f->retransmits = f->maxconfreqtransmits;
|
||||
if (f->callbacks->up) {
|
||||
(*f->callbacks->up)(f); /* Inform upper layers */
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_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 = LS_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;
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n",
|
||||
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
|
||||
|
||||
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 */
|
||||
FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)\n",
|
||||
PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
|
||||
return;
|
||||
}
|
||||
f->seen_ack = 1;
|
||||
|
||||
switch (f->state) {
|
||||
case LS_CLOSED:
|
||||
case LS_STOPPED:
|
||||
fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
|
||||
break;
|
||||
|
||||
case LS_REQSENT:
|
||||
case LS_ACKSENT:
|
||||
/* They didn't agree to what we wanted - try another request */
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
if (ret < 0) {
|
||||
f->state = LS_STOPPED; /* kludge for stopping CCP */
|
||||
} else {
|
||||
fsm_sconfreq(f, 0); /* Send Configure-Request */
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_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 = LS_REQSENT;
|
||||
break;
|
||||
|
||||
case LS_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 = LS_REQSENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rtermreq - Receive Terminate-Req.
|
||||
*/
|
||||
static void
|
||||
fsm_rtermreq(fsm *f, int id, u_char *p, int len)
|
||||
{
|
||||
LWIP_UNUSED_ARG(p);
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n",
|
||||
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
|
||||
|
||||
switch (f->state) {
|
||||
case LS_ACKRCVD:
|
||||
case LS_ACKSENT:
|
||||
f->state = LS_REQSENT; /* Start over but keep trying */
|
||||
break;
|
||||
|
||||
case LS_OPENED:
|
||||
if (len > 0) {
|
||||
FSMDEBUG((LOG_INFO, "%s terminated by peer (%x)\n", PROTO_NAME(f), p));
|
||||
} else {
|
||||
FSMDEBUG((LOG_INFO, "%s terminated by peer\n", PROTO_NAME(f)));
|
||||
}
|
||||
if (f->callbacks->down) {
|
||||
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||
}
|
||||
f->retransmits = 0;
|
||||
f->state = LS_STOPPING;
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
break;
|
||||
}
|
||||
|
||||
fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rtermack - Receive Terminate-Ack.
|
||||
*/
|
||||
static void
|
||||
fsm_rtermack(fsm *f)
|
||||
{
|
||||
FSMDEBUG((LOG_INFO, "fsm_rtermack(%s): state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
|
||||
switch (f->state) {
|
||||
case LS_CLOSING:
|
||||
UNTIMEOUT(fsm_timeout, f);
|
||||
f->state = LS_CLOSED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_STOPPING:
|
||||
UNTIMEOUT(fsm_timeout, f);
|
||||
f->state = LS_STOPPED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_ACKRCVD:
|
||||
f->state = LS_REQSENT;
|
||||
break;
|
||||
|
||||
case LS_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;
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s): state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
|
||||
if (len < HEADERLEN) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
FSMDEBUG((LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d\n",
|
||||
PROTO_NAME(f), code, id));
|
||||
|
||||
if( f->state == LS_ACKRCVD ) {
|
||||
f->state = LS_REQSENT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_sconfreq - Send a Configure-Request.
|
||||
*/
|
||||
static void
|
||||
fsm_sconfreq(fsm *f, int retransmit)
|
||||
{
|
||||
u_char *outp;
|
||||
int cilen;
|
||||
|
||||
if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_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[f->unit] + PPP_HDRLEN + HEADERLEN;
|
||||
if( f->callbacks->cilen && f->callbacks->addci ) {
|
||||
cilen = (*f->callbacks->cilen)(f);
|
||||
if( cilen > peer_mru[f->unit] - (int)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);
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d\n",
|
||||
PROTO_NAME(f), f->reqid));
|
||||
}
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
169
lwip/src/netif/ppp/fsm.h
Normal file
169
lwip/src/netif/ppp/fsm.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*****************************************************************************
|
||||
* fsm.h - Network Control Protocol Finite State Machine header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-11-05 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original based on BSD code.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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: fsm.h,v 1.4 2007/12/19 20:47:23 fbernon Exp $
|
||||
*/
|
||||
|
||||
#ifndef FSM_H
|
||||
#define FSM_H
|
||||
|
||||
/*****************************************************************************
|
||||
************************* PUBLIC DEFINITIONS *********************************
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* LCP Packet header = Code, id, length.
|
||||
*/
|
||||
#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short))
|
||||
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
/*
|
||||
* Link states.
|
||||
*/
|
||||
#define LS_INITIAL 0 /* Down, hasn't been opened */
|
||||
#define LS_STARTING 1 /* Down, been opened */
|
||||
#define LS_CLOSED 2 /* Up, hasn't been opened */
|
||||
#define LS_STOPPED 3 /* Open, waiting for down event */
|
||||
#define LS_CLOSING 4 /* Terminating the connection, not open */
|
||||
#define LS_STOPPING 5 /* Terminating, but open */
|
||||
#define LS_REQSENT 6 /* We've sent a Config Request */
|
||||
#define LS_ACKRCVD 7 /* We've received a Config Ack */
|
||||
#define LS_ACKSENT 8 /* We've sent a Config Ack */
|
||||
#define LS_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 */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
************************* PUBLIC DATA TYPES **********************************
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Each FSM is described by an fsm structure and fsm callbacks.
|
||||
*/
|
||||
typedef struct fsm {
|
||||
int unit; /* Interface unit number */
|
||||
u_short 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)(fsm*); /* Reset our Configuration Information */
|
||||
int (*cilen)(fsm*); /* Length of our Configuration Information */
|
||||
void (*addci)(fsm*, u_char*, int*); /* Add our Configuration Information */
|
||||
int (*ackci)(fsm*, u_char*, int); /* ACK our Configuration Information */
|
||||
int (*nakci)(fsm*, u_char*, int); /* NAK our Configuration Information */
|
||||
int (*rejci)(fsm*, u_char*, int); /* Reject our Configuration Information */
|
||||
int (*reqci)(fsm*, u_char*, int*, int); /* Request peer's Configuration Information */
|
||||
void (*up)(fsm*); /* Called when fsm reaches LS_OPENED state */
|
||||
void (*down)(fsm*); /* Called when fsm leaves LS_OPENED state */
|
||||
void (*starting)(fsm*); /* Called when we want the lower layer */
|
||||
void (*finished)(fsm*); /* Called when we don't want the lower layer */
|
||||
void (*protreject)(int); /* Called when Protocol-Reject received */
|
||||
void (*retransmit)(fsm*); /* Retransmission is necessary */
|
||||
int (*extcode)(fsm*, int, u_char, u_char*, int); /* Called when unknown code received */
|
||||
char *proto_name; /* String name for protocol (for messages) */
|
||||
} fsm_callbacks;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*********************** PUBLIC DATA STRUCTURES *******************************
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Variables
|
||||
*/
|
||||
extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
************************** PUBLIC FUNCTIONS **********************************
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
#endif /* FSM_H */
|
1427
lwip/src/netif/ppp/ipcp.c
Normal file
1427
lwip/src/netif/ppp/ipcp.c
Normal file
File diff suppressed because it is too large
Load diff
124
lwip/src/netif/ppp/ipcp.h
Normal file
124
lwip/src/netif/ppp/ipcp.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*****************************************************************************
|
||||
* ipcp.h - PPP IP NCP: Internet Protocol Network Control Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original derived from BSD codes.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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: ipcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $
|
||||
*/
|
||||
|
||||
#ifndef IPCP_H
|
||||
#define IPCP_H
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
/*
|
||||
* Options.
|
||||
*/
|
||||
#define CI_ADDRS 1 /* IP Addresses */
|
||||
#define CI_COMPRESSTYPE 2 /* Compression Type */
|
||||
#define CI_ADDR 3
|
||||
|
||||
#define CI_MS_WINS1 128 /* Primary WINS value */
|
||||
#define CI_MS_DNS1 129 /* Primary DNS value */
|
||||
#define CI_MS_WINS2 130 /* Secondary WINS value */
|
||||
#define CI_MS_DNS2 131 /* Secondary DNS value */
|
||||
|
||||
#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 */
|
||||
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
typedef struct ipcp_options {
|
||||
u_int neg_addr : 1; /* Negotiate IP Address? */
|
||||
u_int old_addrs : 1; /* Use old (IP-Addresses) option? */
|
||||
u_int req_addr : 1; /* Ask peer to send IP address? */
|
||||
u_int default_route : 1; /* Assign default route through interface? */
|
||||
u_int proxy_arp : 1; /* Make proxy ARP entry for peer? */
|
||||
u_int neg_vj : 1; /* Van Jacobson Compression? */
|
||||
u_int old_vj : 1; /* use old (short) form of VJ option? */
|
||||
u_int accept_local : 1; /* accept peer's value for ouraddr */
|
||||
u_int accept_remote : 1; /* accept peer's value for hisaddr */
|
||||
u_int req_dns1 : 1; /* Ask peer to send primary DNS address? */
|
||||
u_int req_dns2 : 1; /* Ask peer to send secondary DNS address? */
|
||||
u_short vj_protocol; /* protocol value to use in VJ option */
|
||||
u_char maxslotindex; /* VJ slots - 1. */
|
||||
u_char cflag; /* VJ slot compression flag. */
|
||||
u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */
|
||||
u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */
|
||||
u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */
|
||||
} ipcp_options;
|
||||
|
||||
|
||||
/*****************************
|
||||
*** PUBLIC DATA STRUCTURES ***
|
||||
*****************************/
|
||||
|
||||
extern fsm ipcp_fsm[];
|
||||
extern ipcp_options ipcp_wantoptions[];
|
||||
extern ipcp_options ipcp_gotoptions[];
|
||||
extern ipcp_options ipcp_allowoptions[];
|
||||
extern ipcp_options ipcp_hisoptions[];
|
||||
|
||||
extern struct protent ipcp_protent;
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
#endif /* IPCP_H */
|
2035
lwip/src/netif/ppp/lcp.c
Normal file
2035
lwip/src/netif/ppp/lcp.c
Normal file
File diff suppressed because it is too large
Load diff
167
lwip/src/netif/ppp/lcp.h
Normal file
167
lwip/src/netif/ppp/lcp.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*****************************************************************************
|
||||
* lcp.h - Network Link Control Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-11-05 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original derived from BSD codes.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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: lcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $
|
||||
*/
|
||||
|
||||
#ifndef LCP_H
|
||||
#define LCP_H
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
/*
|
||||
* 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 */
|
||||
#define CI_MRRU 17 /* max reconstructed receive unit; multilink */
|
||||
#define CI_SSNHF 18 /* short sequence numbers for multilink */
|
||||
#define CI_EPDISC 19 /* endpoint discriminator */
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
/*
|
||||
* The state of options is described by an lcp_options structure.
|
||||
*/
|
||||
typedef struct lcp_options {
|
||||
u_int passive : 1; /* Don't die if we don't get a response */
|
||||
u_int silent : 1; /* Wait for the other end to start first */
|
||||
u_int restart : 1; /* Restart vs. exit after close */
|
||||
u_int neg_mru : 1; /* Negotiate the MRU? */
|
||||
u_int neg_asyncmap : 1; /* Negotiate the async map? */
|
||||
u_int neg_upap : 1; /* Ask for UPAP authentication? */
|
||||
u_int neg_chap : 1; /* Ask for CHAP authentication? */
|
||||
u_int neg_magicnumber : 1; /* Ask for magic number? */
|
||||
u_int neg_pcompression : 1; /* HDLC Protocol Field Compression? */
|
||||
u_int neg_accompression : 1; /* HDLC Address/Control Field Compression? */
|
||||
u_int neg_lqr : 1; /* Negotiate use of Link Quality Reports */
|
||||
u_int neg_cbcp : 1; /* Negotiate use of CBCP */
|
||||
#ifdef PPP_MULTILINK
|
||||
u_int neg_mrru : 1; /* Negotiate multilink MRRU */
|
||||
u_int neg_ssnhf : 1; /* Negotiate short sequence numbers */
|
||||
u_int neg_endpoint : 1; /* Negotiate endpoint discriminator */
|
||||
#endif
|
||||
u_short mru; /* Value of MRU */
|
||||
#ifdef PPP_MULTILINK
|
||||
u_short mrru; /* Value of MRRU, and multilink enable */
|
||||
#endif
|
||||
u_char chap_mdtype; /* which MD type (hashing algorithm) */
|
||||
u32_t asyncmap; /* Value of async map */
|
||||
u32_t magicnumber;
|
||||
int numloops; /* Number of loops during magic number neg. */
|
||||
u32_t lqr_period; /* Reporting period for LQR 1/100ths second */
|
||||
#ifdef PPP_MULTILINK
|
||||
struct epdisc endpoint; /* endpoint discriminator */
|
||||
#endif
|
||||
} lcp_options;
|
||||
|
||||
/*
|
||||
* Values for phase from BSD pppd.h based on RFC 1661.
|
||||
*/
|
||||
typedef enum {
|
||||
PHASE_DEAD = 0,
|
||||
PHASE_INITIALIZE,
|
||||
PHASE_ESTABLISH,
|
||||
PHASE_AUTHENTICATE,
|
||||
PHASE_CALLBACK,
|
||||
PHASE_NETWORK,
|
||||
PHASE_TERMINATE
|
||||
} LinkPhase;
|
||||
|
||||
|
||||
/*****************************
|
||||
*** PUBLIC DATA STRUCTURES ***
|
||||
*****************************/
|
||||
|
||||
extern LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */
|
||||
extern lcp_options lcp_wantoptions[];
|
||||
extern lcp_options lcp_gotoptions[];
|
||||
extern lcp_options lcp_allowoptions[];
|
||||
extern lcp_options lcp_hisoptions[];
|
||||
extern ext_accm xmit_accm[];
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
void lcp_init (int);
|
||||
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
|
||||
|
||||
#endif /* LCP_H */
|
82
lwip/src/netif/ppp/magic.c
Normal file
82
lwip/src/netif/ppp/magic.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*****************************************************************************
|
||||
* magic.c - Network Random Number Generator program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original based on BSD magic.c.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT
|
||||
|
||||
#include "ppp.h"
|
||||
#include "randm.h"
|
||||
#include "magic.h"
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* magicInit - Initialize the magic number generator.
|
||||
*
|
||||
* Since we use another random number generator that has its own
|
||||
* initialization, we do nothing here.
|
||||
*/
|
||||
void magicInit()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* magic - Returns the next magic number.
|
||||
*/
|
||||
u32_t magic()
|
||||
{
|
||||
return avRandom();
|
||||
}
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
67
lwip/src/netif/ppp/magic.h
Normal file
67
lwip/src/netif/ppp/magic.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*****************************************************************************
|
||||
* magic.h - Network Random Number Generator header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original derived from BSD codes.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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: magic.h,v 1.2 2007/12/02 22:35:55 fbernon Exp $
|
||||
*/
|
||||
|
||||
#ifndef MAGIC_H
|
||||
#define MAGIC_H
|
||||
|
||||
/*****************************************************************************
|
||||
************************** PUBLIC FUNCTIONS **********************************
|
||||
*****************************************************************************/
|
||||
|
||||
/* Initialize the magic number generator */
|
||||
void magicInit(void);
|
||||
|
||||
/* Returns the next magic number */
|
||||
u32_t magic(void);
|
||||
|
||||
#endif /* MAGIC_H */
|
320
lwip/src/netif/ppp/md5.c
Normal file
320
lwip/src/netif/ppp/md5.c
Normal file
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
***********************************************************************
|
||||
** md5.c -- the source code for MD5 routines **
|
||||
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
|
||||
** Created: 2/17/90 RLR **
|
||||
** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** License to copy and use this software is granted provided that **
|
||||
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
|
||||
** Digest Algorithm" in all material mentioning or referencing this **
|
||||
** software or this function. **
|
||||
** **
|
||||
** License is also granted to make and use derivative works **
|
||||
** provided that such works are identified as "derived from the RSA **
|
||||
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
|
||||
** material mentioning or referencing the derived work. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#if CHAP_SUPPORT || MD5_SUPPORT
|
||||
|
||||
#include "ppp.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
** Message-digest routines: **
|
||||
** To form the message digest for a message M **
|
||||
** (1) Initialize a context buffer mdContext using MD5Init **
|
||||
** (2) Call MD5Update on mdContext and M **
|
||||
** (3) Call MD5Final on mdContext **
|
||||
** The message digest is now in mdContext->digest[0...15] **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
/* forward declaration */
|
||||
static void Transform (u32_t *buf, u32_t *in);
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* F, G, H and I are basic MD5 functions */
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits */
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
|
||||
/* Rotation is separate from addition to prevent recomputation */
|
||||
#define FF(a, b, c, d, x, s, ac) \
|
||||
{(a) += F ((b), (c), (d)) + (x) + (u32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) \
|
||||
{(a) += G ((b), (c), (d)) + (x) + (u32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) \
|
||||
{(a) += H ((b), (c), (d)) + (x) + (u32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) \
|
||||
{(a) += I ((b), (c), (d)) + (x) + (u32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
#define UL(x) x##UL
|
||||
#else
|
||||
#ifdef WIN32
|
||||
#define UL(x) x##UL
|
||||
#else
|
||||
#define UL(x) x
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The routine MD5Init initializes the message-digest context
|
||||
mdContext. All fields are set to zero.
|
||||
*/
|
||||
void
|
||||
MD5Init (MD5_CTX *mdContext)
|
||||
{
|
||||
mdContext->i[0] = mdContext->i[1] = (u32_t)0;
|
||||
|
||||
/* Load magic initialization constants. */
|
||||
mdContext->buf[0] = (u32_t)0x67452301UL;
|
||||
mdContext->buf[1] = (u32_t)0xefcdab89UL;
|
||||
mdContext->buf[2] = (u32_t)0x98badcfeUL;
|
||||
mdContext->buf[3] = (u32_t)0x10325476UL;
|
||||
}
|
||||
|
||||
/* The routine MD5Update updates the message-digest context to
|
||||
account for the presence of each of the characters inBuf[0..inLen-1]
|
||||
in the message whose digest is being computed.
|
||||
*/
|
||||
void
|
||||
MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen)
|
||||
{
|
||||
u32_t in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
|
||||
#if 0
|
||||
ppp_trace(LOG_INFO, "MD5Update: %u:%.*H\n", inLen, MIN(inLen, 20) * 2, inBuf);
|
||||
ppp_trace(LOG_INFO, "MD5Update: %u:%s\n", inLen, inBuf);
|
||||
#endif
|
||||
|
||||
/* compute number of bytes mod 64 */
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/* update number of bits */
|
||||
if ((mdContext->i[0] + ((u32_t)inLen << 3)) < mdContext->i[0]) {
|
||||
mdContext->i[1]++;
|
||||
}
|
||||
mdContext->i[0] += ((u32_t)inLen << 3);
|
||||
mdContext->i[1] += ((u32_t)inLen >> 29);
|
||||
|
||||
while (inLen--) {
|
||||
/* add new character to buffer, increment mdi */
|
||||
mdContext->in[mdi++] = *inBuf++;
|
||||
|
||||
/* transform if necessary */
|
||||
if (mdi == 0x40) {
|
||||
for (i = 0, ii = 0; i < 16; i++, ii += 4) {
|
||||
in[i] = (((u32_t)mdContext->in[ii+3]) << 24) |
|
||||
(((u32_t)mdContext->in[ii+2]) << 16) |
|
||||
(((u32_t)mdContext->in[ii+1]) << 8) |
|
||||
((u32_t)mdContext->in[ii]);
|
||||
}
|
||||
Transform (mdContext->buf, in);
|
||||
mdi = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The routine MD5Final terminates the message-digest computation and
|
||||
ends with the desired message digest in mdContext->digest[0...15].
|
||||
*/
|
||||
void
|
||||
MD5Final (unsigned char hash[], MD5_CTX *mdContext)
|
||||
{
|
||||
u32_t in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
unsigned int padLen;
|
||||
|
||||
/* save number of bits */
|
||||
in[14] = mdContext->i[0];
|
||||
in[15] = mdContext->i[1];
|
||||
|
||||
/* compute number of bytes mod 64 */
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/* pad out to 56 mod 64 */
|
||||
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
|
||||
MD5Update (mdContext, PADDING, padLen);
|
||||
|
||||
/* append length in bits and transform */
|
||||
for (i = 0, ii = 0; i < 14; i++, ii += 4) {
|
||||
in[i] = (((u32_t)mdContext->in[ii+3]) << 24) |
|
||||
(((u32_t)mdContext->in[ii+2]) << 16) |
|
||||
(((u32_t)mdContext->in[ii+1]) << 8) |
|
||||
((u32_t)mdContext->in[ii]);
|
||||
}
|
||||
Transform (mdContext->buf, in);
|
||||
|
||||
/* store buffer in digest */
|
||||
for (i = 0, ii = 0; i < 4; i++, ii += 4) {
|
||||
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
|
||||
mdContext->digest[ii+1] =
|
||||
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
|
||||
mdContext->digest[ii+2] =
|
||||
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
|
||||
mdContext->digest[ii+3] =
|
||||
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
|
||||
}
|
||||
SMEMCPY(hash, mdContext->digest, 16);
|
||||
}
|
||||
|
||||
/* Basic MD5 step. Transforms buf based on in.
|
||||
*/
|
||||
static void
|
||||
Transform (u32_t *buf, u32_t *in)
|
||||
{
|
||||
u32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3];
|
||||
|
||||
/* Round 1 */
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
|
||||
FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
|
||||
FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
|
||||
FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
|
||||
FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
|
||||
FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
|
||||
FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
|
||||
FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
|
||||
FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
|
||||
FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
|
||||
FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
|
||||
FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
|
||||
FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
|
||||
FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
|
||||
FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
|
||||
FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
|
||||
GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
|
||||
GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
|
||||
GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
|
||||
GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
|
||||
GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
|
||||
GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
|
||||
GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
|
||||
GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
|
||||
GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
|
||||
GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
|
||||
GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
|
||||
GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
|
||||
GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
|
||||
GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
|
||||
GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
|
||||
HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
|
||||
HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
|
||||
HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
|
||||
HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
|
||||
HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
|
||||
HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
|
||||
HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
|
||||
HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
|
||||
HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
|
||||
HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
|
||||
HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
|
||||
HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
|
||||
HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
|
||||
HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
|
||||
HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
|
||||
II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
|
||||
II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
|
||||
II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
|
||||
II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
|
||||
II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
|
||||
II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
|
||||
II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
|
||||
II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
|
||||
II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
|
||||
II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
|
||||
II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
|
||||
II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
|
||||
II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
|
||||
II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
|
||||
II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
#endif /* CHAP_SUPPORT || MD5_SUPPORT */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
55
lwip/src/netif/ppp/md5.h
Normal file
55
lwip/src/netif/ppp/md5.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
***********************************************************************
|
||||
** md5.h -- header file for implementation of MD5 **
|
||||
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
|
||||
** Created: 2/17/90 RLR **
|
||||
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
|
||||
** Revised (for MD5): RLR 4/27/91 **
|
||||
** -- G modified to have y&~z instead of y&z **
|
||||
** -- FF, GG, HH modified to add in last register done **
|
||||
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
|
||||
** -- distinct additive constant for each step **
|
||||
** -- round 4 added, working mod 7 **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** License to copy and use this software is granted provided that **
|
||||
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
|
||||
** Digest Algorithm" in all material mentioning or referencing this **
|
||||
** software or this function. **
|
||||
** **
|
||||
** License is also granted to make and use derivative works **
|
||||
** provided that such works are identified as "derived from the RSA **
|
||||
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
|
||||
** material mentioning or referencing the derived work. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
/* Data structure for MD5 (Message-Digest) computation */
|
||||
typedef struct {
|
||||
u32_t i[2]; /* number of _bits_ handled mod 2^64 */
|
||||
u32_t buf[4]; /* scratch buffer */
|
||||
unsigned char in[64]; /* input buffer */
|
||||
unsigned char digest[16]; /* actual digest after MD5Final call */
|
||||
} MD5_CTX;
|
||||
|
||||
void MD5Init ( MD5_CTX *mdContext);
|
||||
void MD5Update( MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen);
|
||||
void MD5Final ( unsigned char hash[], MD5_CTX *mdContext);
|
||||
|
||||
#endif /* MD5_H */
|
622
lwip/src/netif/ppp/pap.c
Normal file
622
lwip/src/netif/ppp/pap.c
Normal file
|
@ -0,0 +1,622 @@
|
|||
/*****************************************************************************
|
||||
* pap.c - Network Password Authentication Protocol program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-12 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "auth.h"
|
||||
#include "pap.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* 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 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);
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
struct protent pap_protent = {
|
||||
PPP_PAP,
|
||||
upap_init,
|
||||
upap_input,
|
||||
upap_protrej,
|
||||
upap_lowerup,
|
||||
upap_lowerdown,
|
||||
NULL,
|
||||
NULL,
|
||||
#if 0
|
||||
upap_printpkt,
|
||||
NULL,
|
||||
#endif
|
||||
1,
|
||||
"PAP",
|
||||
#if 0
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Set the default login name and password for the pap sessions
|
||||
*/
|
||||
void
|
||||
upap_setloginpasswd(int unit, const char *luser, const char *lpassword)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
|
||||
/* Save the username and password we're given */
|
||||
u->us_user = luser;
|
||||
u->us_userlen = strlen(luser);
|
||||
u->us_passwd = lpassword;
|
||||
u->us_passwdlen = strlen(lpassword);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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];
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%d\n",
|
||||
unit, user, password, u->us_clientstate));
|
||||
|
||||
upap_setloginpasswd(unit, user, 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
/*
|
||||
* upap_init - Initialize a UPAP unit.
|
||||
*/
|
||||
static void
|
||||
upap_init(int unit)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_init: %d\n", 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_timeout - Retransmission timer for sending auth-reqs expired.
|
||||
*/
|
||||
static void
|
||||
upap_timeout(void *arg)
|
||||
{
|
||||
upap_state *u = (upap_state *) arg;
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%d\n",
|
||||
u->us_unit, u->us_timeouttime, u->us_clientstate));
|
||||
|
||||
if (u->us_clientstate != UPAPCS_AUTHREQ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->us_transmits >= u->us_maxtransmits) {
|
||||
/* give up in disgust */
|
||||
UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requests\n"));
|
||||
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];
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%d\n", unit, u->us_clientstate));
|
||||
|
||||
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];
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%d\n", unit, u->us_clientstate));
|
||||
|
||||
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) {
|
||||
UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-reject\n"));
|
||||
auth_withpeer_fail(unit, PPP_PAP);
|
||||
}
|
||||
if (u->us_serverstate == UPAPSS_LISTEN) {
|
||||
UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n"));
|
||||
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((LOG_INFO, "pap_input: rcvd short header.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
GETSHORT(len, inp);
|
||||
if (len < UPAP_HEADERLEN) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n"));
|
||||
return;
|
||||
}
|
||||
if (len > l) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n"));
|
||||
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;
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id));
|
||||
|
||||
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 < sizeof (u_char)) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(ruserlen, inp);
|
||||
len -= sizeof (u_char) + ruserlen + sizeof (u_char);
|
||||
if (len < 0) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
ruser = (char *) inp;
|
||||
INCPTR(ruserlen, inp);
|
||||
GETCHAR(rpasswdlen, inp);
|
||||
if (len < rpasswdlen) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
rpasswd = (char *) inp;
|
||||
|
||||
/*
|
||||
* Check the username and password given.
|
||||
*/
|
||||
retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen);
|
||||
BZERO(rpasswd, rpasswdlen);
|
||||
|
||||
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;
|
||||
|
||||
LWIP_UNUSED_ARG(id);
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate));
|
||||
|
||||
if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse message.
|
||||
*/
|
||||
if (len < sizeof (u_char)) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(msglen, inp);
|
||||
len -= sizeof (u_char);
|
||||
if (len < msglen) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
msg = (char *) inp;
|
||||
PRINTMSG(msg, msglen);
|
||||
|
||||
UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
|
||||
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;
|
||||
|
||||
LWIP_UNUSED_ARG(id);
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));
|
||||
|
||||
if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse message.
|
||||
*/
|
||||
if (len < sizeof (u_char)) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
|
||||
} else {
|
||||
GETCHAR(msglen, inp);
|
||||
if(msglen > 0) {
|
||||
len -= sizeof (u_char);
|
||||
if (len < msglen) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
msg = (char *) inp;
|
||||
PRINTMSG(msg, msglen);
|
||||
}
|
||||
}
|
||||
|
||||
u->us_clientstate = UPAPCS_BADAUTH;
|
||||
|
||||
UPAPDEBUG((LOG_ERR, "PAP authentication failed\n"));
|
||||
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[u->us_unit];
|
||||
|
||||
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);
|
||||
|
||||
pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d\n", u->us_id));
|
||||
|
||||
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[u->us_unit];
|
||||
MAKEHEADER(outp, PPP_PAP);
|
||||
|
||||
PUTCHAR(code, outp);
|
||||
PUTCHAR(id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
PUTCHAR(msglen, outp);
|
||||
BCOPY(msg, outp, msglen);
|
||||
pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate));
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* upap_printpkt - print the contents of a PAP packet.
|
||||
*/
|
||||
static int upap_printpkt(
|
||||
u_char *p,
|
||||
int plen,
|
||||
void (*printer) (void *, char *, ...),
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
LWIP_UNUSED_ARG(p);
|
||||
LWIP_UNUSED_ARG(plen);
|
||||
LWIP_UNUSED_ARG(printer);
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
return 0;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
#endif /* PAP_SUPPORT */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
131
lwip/src/netif/ppp/pap.h
Normal file
131
lwip/src/netif/ppp/pap.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*****************************************************************************
|
||||
* pap.h - PPP Password Authentication Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original derived from BSD codes.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PAP_H
|
||||
#define PAP_H
|
||||
|
||||
#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
/*
|
||||
* Packet header = Code, id, length.
|
||||
*/
|
||||
#define UPAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short))
|
||||
|
||||
|
||||
/*
|
||||
* UPAP codes.
|
||||
*/
|
||||
#define UPAP_AUTHREQ 1 /* Authenticate-Request */
|
||||
#define UPAP_AUTHACK 2 /* Authenticate-Ack */
|
||||
#define UPAP_AUTHNAK 3 /* Authenticate-Nak */
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
/*
|
||||
* Each interface is described by upap structure.
|
||||
*/
|
||||
typedef struct upap_state {
|
||||
int us_unit; /* Interface unit number */
|
||||
const char *us_user; /* User */
|
||||
int us_userlen; /* User length */
|
||||
const 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;
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
extern upap_state upap[];
|
||||
|
||||
void upap_setloginpasswd(int unit, const char *luser, const char *lpassword);
|
||||
void upap_authwithpeer (int, char *, char *);
|
||||
void upap_authpeer (int);
|
||||
|
||||
extern struct protent pap_protent;
|
||||
|
||||
#endif /* PAP_SUPPORT */
|
||||
|
||||
#endif /* PAP_H */
|
1989
lwip/src/netif/ppp/ppp.c
Normal file
1989
lwip/src/netif/ppp/ppp.c
Normal file
File diff suppressed because it is too large
Load diff
465
lwip/src/netif/ppp/ppp.h
Normal file
465
lwip/src/netif/ppp/ppp.h
Normal file
|
@ -0,0 +1,465 @@
|
|||
/*****************************************************************************
|
||||
* ppp.h - Network Point to Point Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-11-05 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original derived from BSD codes.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef PPP_H
|
||||
#define PPP_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/sio.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* ppp_defs.h - PPP definitions.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define TIMEOUT(f, a, t) sys_untimeout((f), (a)), sys_timeout((t)*1000, (f), (a))
|
||||
#define UNTIMEOUT(f, a) sys_untimeout((f), (a))
|
||||
|
||||
|
||||
#ifndef __u_char_defined
|
||||
|
||||
/* Type definitions for BSD code. */
|
||||
typedef unsigned long u_long;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned char u_char;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Constants and structures defined by the internet system,
|
||||
* Per RFC 790, September 1981, and numerous additions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The basic PPP frame.
|
||||
*/
|
||||
#define PPP_HDRLEN 4 /* octets for standard ppp header */
|
||||
#define PPP_FCSLEN 2 /* octets for FCS */
|
||||
|
||||
|
||||
/*
|
||||
* Significant octet values.
|
||||
*/
|
||||
#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
|
||||
#define PPP_UI 0x03 /* Unnumbered Information */
|
||||
#define PPP_FLAG 0x7e /* Flag Sequence */
|
||||
#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */
|
||||
#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */
|
||||
|
||||
/*
|
||||
* Protocol field values.
|
||||
*/
|
||||
#define PPP_IP 0x21 /* Internet Protocol */
|
||||
#define PPP_AT 0x29 /* AppleTalk Protocol */
|
||||
#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
|
||||
#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
|
||||
#define PPP_COMP 0xfd /* compressed packet */
|
||||
#define PPP_IPCP 0x8021 /* IP Control Protocol */
|
||||
#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
|
||||
#define PPP_CCP 0x80fd /* Compression Control Protocol */
|
||||
#define PPP_LCP 0xc021 /* Link Control Protocol */
|
||||
#define PPP_PAP 0xc023 /* Password Authentication Protocol */
|
||||
#define PPP_LQR 0xc025 /* Link Quality Report protocol */
|
||||
#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
|
||||
#define PPP_CBCP 0xc029 /* Callback Control Protocol */
|
||||
|
||||
/*
|
||||
* Values for FCS calculations.
|
||||
*/
|
||||
#define PPP_INITFCS 0xffff /* Initial FCS value */
|
||||
#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */
|
||||
#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
|
||||
|
||||
/*
|
||||
* Extended asyncmap - allows any character to be escaped.
|
||||
*/
|
||||
typedef u_char ext_accm[32];
|
||||
|
||||
/*
|
||||
* What to do with network protocol (NP) packets.
|
||||
*/
|
||||
enum NPmode {
|
||||
NPMODE_PASS, /* pass the packet through */
|
||||
NPMODE_DROP, /* silently drop the packet */
|
||||
NPMODE_ERROR, /* return an error */
|
||||
NPMODE_QUEUE /* save it up for later. */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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); (cp)++; (s) <<= 8; \
|
||||
(s) |= *(cp); (cp)++; \
|
||||
}
|
||||
#define PUTSHORT(s, cp) { \
|
||||
*(cp)++ = (u_char) ((s) >> 8); \
|
||||
*(cp)++ = (u_char) (s & 0xff); \
|
||||
}
|
||||
|
||||
#define GETLONG(l, cp) { \
|
||||
(l) = *(cp); (cp)++; (l) <<= 8; \
|
||||
(l) |= *(cp); (cp)++; (l) <<= 8; \
|
||||
(l) |= *(cp); (cp)++; (l) <<= 8; \
|
||||
(l) |= *(cp); (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))
|
||||
|
||||
#define BCMP(s0, s1, l) memcmp((u_char *)(s0), (u_char *)(s1), (l))
|
||||
#define BCOPY(s, d, l) MEMCPY((d), (s), (l))
|
||||
#define BZERO(s, n) memset(s, 0, n)
|
||||
|
||||
#if PPP_DEBUG
|
||||
#define PRINTMSG(m, l) { m[l] = '\0'; ppp_trace(LOG_INFO, "Remote message: %s\n", m); }
|
||||
#else /* PPP_DEBUG */
|
||||
#define PRINTMSG(m, l)
|
||||
#endif /* PPP_DEBUG */
|
||||
|
||||
/*
|
||||
* MAKEHEADER - Add PPP Header fields to a packet.
|
||||
*/
|
||||
#define MAKEHEADER(p, t) { \
|
||||
PUTCHAR(PPP_ALLSTATIONS, p); \
|
||||
PUTCHAR(PPP_UI, p); \
|
||||
PUTSHORT(t, p); }
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
|
||||
/* Error codes. */
|
||||
#define PPPERR_NONE 0 /* No error. */
|
||||
#define PPPERR_PARAM -1 /* Invalid parameter. */
|
||||
#define PPPERR_OPEN -2 /* Unable to open PPP session. */
|
||||
#define PPPERR_DEVICE -3 /* Invalid I/O device for PPP. */
|
||||
#define PPPERR_ALLOC -4 /* Unable to allocate resources. */
|
||||
#define PPPERR_USER -5 /* User interrupt. */
|
||||
#define PPPERR_CONNECT -6 /* Connection lost. */
|
||||
#define PPPERR_AUTHFAIL -7 /* Failed authentication challenge. */
|
||||
#define PPPERR_PROTOCOL -8 /* Failed to meet protocol. */
|
||||
|
||||
/*
|
||||
* PPP IOCTL commands.
|
||||
*/
|
||||
/*
|
||||
* Get the up status - 0 for down, non-zero for up. The argument must
|
||||
* point to an int.
|
||||
*/
|
||||
#define PPPCTLG_UPSTATUS 100 /* Get the up status - 0 down else up */
|
||||
#define PPPCTLS_ERRCODE 101 /* Set the error code */
|
||||
#define PPPCTLG_ERRCODE 102 /* Get the error code */
|
||||
#define PPPCTLG_FD 103 /* Get the fd associated with the ppp */
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
/*
|
||||
* 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);
|
||||
#if 0
|
||||
/* 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);
|
||||
#endif
|
||||
int enabled_flag; /* 0 iff protocol is disabled */
|
||||
char *name; /* Text name of protocol */
|
||||
#if 0
|
||||
/* Check requested options, assign defaults */
|
||||
void (*check_options) (u_long);
|
||||
/* 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);
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure records the time in seconds since
|
||||
* the last NP packet was sent or received.
|
||||
*/
|
||||
struct ppp_idle {
|
||||
u_short xmit_idle; /* seconds since last NP packet sent */
|
||||
u_short recv_idle; /* seconds since last NP packet received */
|
||||
};
|
||||
|
||||
struct ppp_settings {
|
||||
|
||||
u_int disable_defaultip : 1; /* Don't use hostname for default IP addrs */
|
||||
u_int auth_required : 1; /* Peer is required to authenticate */
|
||||
u_int explicit_remote : 1; /* remote_name specified with remotename opt */
|
||||
u_int refuse_pap : 1; /* Don't wanna auth. ourselves with PAP */
|
||||
u_int refuse_chap : 1; /* Don't wanna auth. ourselves with CHAP */
|
||||
u_int usehostname : 1; /* Use hostname for our_name */
|
||||
u_int usepeerdns : 1; /* Ask peer for DNS adds */
|
||||
|
||||
u_short idle_time_limit; /* Shut down link if idle for this long */
|
||||
int maxconnect; /* Maximum connect time (seconds) */
|
||||
|
||||
char user [MAXNAMELEN + 1]; /* Username for PAP */
|
||||
char passwd [MAXSECRETLEN + 1]; /* Password for PAP, secret for CHAP */
|
||||
char our_name [MAXNAMELEN + 1]; /* Our name for authentication purposes */
|
||||
char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */
|
||||
};
|
||||
|
||||
struct ppp_addrs {
|
||||
struct ip_addr our_ipaddr, his_ipaddr, netmask, dns1, dns2;
|
||||
};
|
||||
|
||||
/*****************************
|
||||
*** PUBLIC DATA STRUCTURES ***
|
||||
*****************************/
|
||||
|
||||
/* Buffers for outgoing packets. */
|
||||
extern u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
|
||||
|
||||
extern struct ppp_settings ppp_settings;
|
||||
|
||||
extern struct protent *ppp_protocols[]; /* Table of pointers to supported protocols */
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
/* Initialize the PPP subsystem. */
|
||||
void pppInit(void);
|
||||
|
||||
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
|
||||
* RFC 1994 says:
|
||||
*
|
||||
* In practice, within or associated with each PPP server, there is a
|
||||
* database which associates "user" names with authentication
|
||||
* information ("secrets"). It is not anticipated that a particular
|
||||
* named user would be authenticated by multiple methods. This would
|
||||
* make the user vulnerable to attacks which negotiate the least secure
|
||||
* method from among a set (such as PAP rather than CHAP). If the same
|
||||
* secret was used, PAP would reveal the secret to be used later with
|
||||
* CHAP.
|
||||
*
|
||||
* Instead, for each user name there should be an indication of exactly
|
||||
* one method used to authenticate that user name. If a user needs to
|
||||
* make use of different authentication methods under different
|
||||
* circumstances, then distinct user names SHOULD be employed, each of
|
||||
* which identifies exactly one authentication method.
|
||||
*
|
||||
*/
|
||||
enum pppAuthType {
|
||||
PPPAUTHTYPE_NONE,
|
||||
PPPAUTHTYPE_ANY,
|
||||
PPPAUTHTYPE_PAP,
|
||||
PPPAUTHTYPE_CHAP
|
||||
};
|
||||
|
||||
void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd);
|
||||
|
||||
/*
|
||||
* Open a new PPP connection using the given serial I/O device.
|
||||
* This initializes the PPP control block but does not
|
||||
* attempt to negotiate the LCP session.
|
||||
* Return a new PPP connection descriptor on success or
|
||||
* an error code (negative) on failure.
|
||||
*/
|
||||
int pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx);
|
||||
|
||||
/*
|
||||
* Open a new PPP Over Ethernet (PPPOE) connection.
|
||||
*/
|
||||
int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx);
|
||||
|
||||
/* for source code compatibility */
|
||||
#define pppOpen(fd,cb,ls) pppOverSerialOpen(fd,cb,ls)
|
||||
|
||||
/*
|
||||
* Close a PPP connection and release the descriptor.
|
||||
* Any outstanding packets in the queues are dropped.
|
||||
* Return 0 on success, an error code on failure.
|
||||
*/
|
||||
int pppClose(int pd);
|
||||
|
||||
/*
|
||||
* Indicate to the PPP process that the line has disconnected.
|
||||
*/
|
||||
void pppSigHUP(int pd);
|
||||
|
||||
/*
|
||||
* Get and set parameters for the given connection.
|
||||
* Return 0 on success, an error code on failure.
|
||||
*/
|
||||
int pppIOCtl(int pd, int cmd, void *arg);
|
||||
|
||||
/*
|
||||
* Return the Maximum Transmission Unit for the given PPP connection.
|
||||
*/
|
||||
u_int pppMTU(int pd);
|
||||
|
||||
/*
|
||||
* Write n characters to a ppp link.
|
||||
* RETURN: >= 0 Number of characters written, -1 Failed to write to device.
|
||||
*/
|
||||
int pppWrite(int pd, const u_char *s, int n);
|
||||
|
||||
void pppInProcOverEthernet(int pd, struct pbuf *pb);
|
||||
|
||||
struct pbuf *pppSingleBuf(struct pbuf *p);
|
||||
|
||||
void pppLinkTerminated(int pd);
|
||||
|
||||
void pppLinkDown(int pd);
|
||||
|
||||
void pppMainWakeup(int pd);
|
||||
|
||||
/* Configure i/f transmit parameters */
|
||||
void ppp_send_config (int, int, u32_t, int, int);
|
||||
/* Set extended transmit ACCM */
|
||||
void ppp_set_xaccm (int, ext_accm *);
|
||||
/* Configure i/f receive parameters */
|
||||
void ppp_recv_config (int, int, u32_t, int, int);
|
||||
/* Find out how long link has been idle */
|
||||
int get_idle_time (int, struct ppp_idle *);
|
||||
|
||||
/* Configure VJ TCP header compression */
|
||||
int sifvjcomp (int, int, int, int);
|
||||
/* Configure i/f down (for IP) */
|
||||
int sifup (int);
|
||||
/* Set mode for handling packets for proto */
|
||||
int sifnpmode (int u, int proto, enum NPmode mode);
|
||||
/* Configure i/f down (for IP) */
|
||||
int sifdown (int);
|
||||
/* Configure IP addresses for i/f */
|
||||
int sifaddr (int, u32_t, u32_t, u32_t, u32_t, u32_t);
|
||||
/* Reset i/f IP addresses */
|
||||
int cifaddr (int, u32_t, u32_t);
|
||||
/* Create default route through i/f */
|
||||
int sifdefaultroute (int, u32_t, u32_t);
|
||||
/* Delete default route through i/f */
|
||||
int cifdefaultroute (int, u32_t, u32_t);
|
||||
|
||||
/* Get appropriate netmask for address */
|
||||
u32_t GetMask (u32_t);
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
||||
|
||||
#endif /* PPP_H */
|
1227
lwip/src/netif/ppp/ppp_oe.c
Normal file
1227
lwip/src/netif/ppp/ppp_oe.c
Normal file
File diff suppressed because it is too large
Load diff
86
lwip/src/netif/ppp/pppdebug.h
Normal file
86
lwip/src/netif/ppp/pppdebug.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*****************************************************************************
|
||||
* pppdebug.h - System debugging utilities.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1998 Global Election Systems Inc.
|
||||
* portions Copyright (c) 2001 by Cognizant Pty Ltd.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY (please don't use tabs!)
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 98-07-29 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original.
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#ifndef PPPDEBUG_H
|
||||
#define PPPDEBUG_H
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
/* Trace levels. */
|
||||
typedef enum {
|
||||
LOG_CRITICAL = 0,
|
||||
LOG_ERR = 1,
|
||||
LOG_NOTICE = 2,
|
||||
LOG_WARNING = 3,
|
||||
LOG_INFO = 5,
|
||||
LOG_DETAIL = 6,
|
||||
LOG_DEBUG = 7
|
||||
} LogCodes;
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
/*
|
||||
* ppp_trace - a form of printf to send tracing information to stderr
|
||||
*/
|
||||
void ppp_trace(int level, const char *format,...);
|
||||
|
||||
#define TRACELCP PPP_DEBUG
|
||||
|
||||
#if PPP_DEBUG
|
||||
|
||||
#define AUTHDEBUG(a) ppp_trace a
|
||||
#define IPCPDEBUG(a) ppp_trace a
|
||||
#define UPAPDEBUG(a) ppp_trace a
|
||||
#define LCPDEBUG(a) ppp_trace a
|
||||
#define FSMDEBUG(a) ppp_trace a
|
||||
#define CHAPDEBUG(a) ppp_trace a
|
||||
#define PPPDEBUG(a) ppp_trace a
|
||||
|
||||
#else /* PPP_DEBUG */
|
||||
|
||||
#define AUTHDEBUG(a)
|
||||
#define IPCPDEBUG(a)
|
||||
#define UPAPDEBUG(a)
|
||||
#define LCPDEBUG(a)
|
||||
#define FSMDEBUG(a)
|
||||
#define CHAPDEBUG(a)
|
||||
#define PPPDEBUG(a)
|
||||
|
||||
#endif /* PPP_DEBUG */
|
||||
|
||||
#endif /* PPPDEBUG_H */
|
249
lwip/src/netif/ppp/randm.c
Normal file
249
lwip/src/netif/ppp/randm.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*****************************************************************************
|
||||
* randm.c - Random number generator program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1998 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 98-06-03 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Extracted from avos.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "md5.h"
|
||||
#include "randm.h"
|
||||
|
||||
#include "ppp.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if MD5_SUPPORT /* this module depends on MD5 */
|
||||
#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
static char randPool[RANDPOOLSZ]; /* Pool of randomness. */
|
||||
static long randCount = 0; /* Pseudo-random incrementer */
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Initialize the random number generator.
|
||||
*
|
||||
* Since this is to be called on power up, we don't have much
|
||||
* system randomess to work with. Here all we use is the
|
||||
* real-time clock. We'll accumulate more randomness as soon
|
||||
* as things start happening.
|
||||
*/
|
||||
void
|
||||
avRandomInit()
|
||||
{
|
||||
avChurnRand(NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Churn the randomness pool on a random event. Call this early and often
|
||||
* on random and semi-random system events to build randomness in time for
|
||||
* usage. For randomly timed events, pass a null pointer and a zero length
|
||||
* and this will use the system timer and other sources to add randomness.
|
||||
* If new random data is available, pass a pointer to that and it will be
|
||||
* included.
|
||||
*
|
||||
* Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
|
||||
*/
|
||||
void
|
||||
avChurnRand(char *randData, u32_t randLen)
|
||||
{
|
||||
MD5_CTX md5;
|
||||
|
||||
/* ppp_trace(LOG_INFO, "churnRand: %u@%P\n", randLen, randData); */
|
||||
MD5Init(&md5);
|
||||
MD5Update(&md5, (u_char *)randPool, sizeof(randPool));
|
||||
if (randData) {
|
||||
MD5Update(&md5, (u_char *)randData, randLen);
|
||||
} else {
|
||||
struct {
|
||||
/* INCLUDE fields for any system sources of randomness */
|
||||
char foobar;
|
||||
} sysData;
|
||||
|
||||
/* Load sysData fields here. */
|
||||
MD5Update(&md5, (u_char *)&sysData, sizeof(sysData));
|
||||
}
|
||||
MD5Final((u_char *)randPool, &md5);
|
||||
/* ppp_trace(LOG_INFO, "churnRand: -> 0\n"); */
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the random pool to generate random data. This degrades to pseudo
|
||||
* random when used faster than randomness is supplied using churnRand().
|
||||
* Note: It's important that there be sufficient randomness in randPool
|
||||
* before this is called for otherwise the range of the result may be
|
||||
* narrow enough to make a search feasible.
|
||||
*
|
||||
* Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
|
||||
*
|
||||
* XXX Why does he not just call churnRand() for each block? Probably
|
||||
* so that you don't ever publish the seed which could possibly help
|
||||
* predict future values.
|
||||
* XXX Why don't we preserve md5 between blocks and just update it with
|
||||
* randCount each time? Probably there is a weakness but I wish that
|
||||
* it was documented.
|
||||
*/
|
||||
void
|
||||
avGenRand(char *buf, u32_t bufLen)
|
||||
{
|
||||
MD5_CTX md5;
|
||||
u_char tmp[16];
|
||||
u32_t n;
|
||||
|
||||
while (bufLen > 0) {
|
||||
n = LWIP_MIN(bufLen, RANDPOOLSZ);
|
||||
MD5Init(&md5);
|
||||
MD5Update(&md5, (u_char *)randPool, sizeof(randPool));
|
||||
MD5Update(&md5, (u_char *)&randCount, sizeof(randCount));
|
||||
MD5Final(tmp, &md5);
|
||||
randCount++;
|
||||
MEMCPY(buf, tmp, n);
|
||||
buf += n;
|
||||
bufLen -= n;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a new random number.
|
||||
*/
|
||||
u32_t
|
||||
avRandom()
|
||||
{
|
||||
u32_t newRand;
|
||||
|
||||
avGenRand((char *)&newRand, sizeof(newRand));
|
||||
|
||||
return newRand;
|
||||
}
|
||||
|
||||
#else /* MD5_SUPPORT */
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
static int avRandomized = 0; /* Set when truely randomized. */
|
||||
static u32_t avRandomSeed = 0; /* Seed used for random number generation. */
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Initialize the random number generator.
|
||||
*
|
||||
* Here we attempt to compute a random number seed but even if
|
||||
* it isn't random, we'll randomize it later.
|
||||
*
|
||||
* The current method uses the fields from the real time clock,
|
||||
* the idle process counter, the millisecond counter, and the
|
||||
* hardware timer tick counter. When this is invoked
|
||||
* in startup(), then the idle counter and timer values may
|
||||
* repeat after each boot and the real time clock may not be
|
||||
* operational. Thus we call it again on the first random
|
||||
* event.
|
||||
*/
|
||||
void
|
||||
avRandomInit()
|
||||
{
|
||||
#if 0
|
||||
/* Get a pointer into the last 4 bytes of clockBuf. */
|
||||
u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]);
|
||||
|
||||
/*
|
||||
* Initialize our seed using the real-time clock, the idle
|
||||
* counter, the millisecond timer, and the hardware timer
|
||||
* tick counter. The real-time clock and the hardware
|
||||
* tick counter are the best sources of randomness but
|
||||
* since the tick counter is only 16 bit (and truncated
|
||||
* at that), the idle counter and millisecond timer
|
||||
* (which may be small values) are added to help
|
||||
* randomize the lower 16 bits of the seed.
|
||||
*/
|
||||
readClk();
|
||||
avRandomSeed += *(u32_t *)clockBuf + *lptr1 + OSIdleCtr
|
||||
+ ppp_mtime() + ((u32_t)TM1 << 16) + TM1;
|
||||
#else
|
||||
avRandomSeed += sys_jiffies(); /* XXX */
|
||||
#endif
|
||||
|
||||
/* Initialize the Borland random number generator. */
|
||||
srand((unsigned)avRandomSeed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Randomize our random seed value. Here we use the fact that
|
||||
* this function is called at *truely random* times by the polling
|
||||
* and network functions. Here we only get 16 bits of new random
|
||||
* value but we use the previous value to randomize the other 16
|
||||
* bits.
|
||||
*/
|
||||
void
|
||||
avRandomize(void)
|
||||
{
|
||||
static u32_t last_jiffies;
|
||||
|
||||
if (!avRandomized) {
|
||||
avRandomized = !0;
|
||||
avRandomInit();
|
||||
/* The initialization function also updates the seed. */
|
||||
} else {
|
||||
/* avRandomSeed += (avRandomSeed << 16) + TM1; */
|
||||
avRandomSeed += (sys_jiffies() - last_jiffies); /* XXX */
|
||||
}
|
||||
last_jiffies = sys_jiffies();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a new random number.
|
||||
* Here we use the Borland rand() function to supply a pseudo random
|
||||
* number which we make truely random by combining it with our own
|
||||
* seed which is randomized by truely random events.
|
||||
* Thus the numbers will be truely random unless there have been no
|
||||
* operator or network events in which case it will be pseudo random
|
||||
* seeded by the real time clock.
|
||||
*/
|
||||
u32_t
|
||||
avRandom()
|
||||
{
|
||||
return ((((u32_t)rand() << 16) + rand()) + avRandomSeed);
|
||||
}
|
||||
|
||||
#endif /* MD5_SUPPORT */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
81
lwip/src/netif/ppp/randm.h
Normal file
81
lwip/src/netif/ppp/randm.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*****************************************************************************
|
||||
* randm.h - Random number generator header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1998 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 98-05-29 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Extracted from avos.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef RANDM_H
|
||||
#define RANDM_H
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
/*
|
||||
* Initialize the random number generator.
|
||||
*/
|
||||
void avRandomInit(void);
|
||||
|
||||
/*
|
||||
* Churn the randomness pool on a random event. Call this early and often
|
||||
* on random and semi-random system events to build randomness in time for
|
||||
* usage. For randomly timed events, pass a null pointer and a zero length
|
||||
* and this will use the system timer and other sources to add randomness.
|
||||
* If new random data is available, pass a pointer to that and it will be
|
||||
* included.
|
||||
*/
|
||||
void avChurnRand(char *randData, u32_t randLen);
|
||||
|
||||
/*
|
||||
* Randomize our random seed value. To be called for truely random events
|
||||
* such as user operations and network traffic.
|
||||
*/
|
||||
#if MD5_SUPPORT
|
||||
#define avRandomize() avChurnRand(NULL, 0)
|
||||
#else /* MD5_SUPPORT */
|
||||
void avRandomize(void);
|
||||
#endif /* MD5_SUPPORT */
|
||||
|
||||
/*
|
||||
* Use the random pool to generate random data. This degrades to pseudo
|
||||
* random when used faster than randomness is supplied using churnRand().
|
||||
* Thus it's important to make sure that the results of this are not
|
||||
* published directly because one could predict the next result to at
|
||||
* least some degree. Also, it's important to get a good seed before
|
||||
* the first use.
|
||||
*/
|
||||
void avGenRand(char *buf, u32_t bufLen);
|
||||
|
||||
/*
|
||||
* Return a new random number.
|
||||
*/
|
||||
u32_t avRandom(void);
|
||||
|
||||
|
||||
#endif /* RANDM_H */
|
660
lwip/src/netif/ppp/vj.c
Normal file
660
lwip/src/netif/ppp/vj.c
Normal file
|
@ -0,0 +1,660 @@
|
|||
/*
|
||||
* Routines to compress and uncompess tcp packets (for transmission
|
||||
* over low speed serial lines.
|
||||
*
|
||||
* Copyright (c) 1989 Regents of the University of California.
|
||||
* 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 University of California, Berkeley. 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.
|
||||
*
|
||||
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
|
||||
* Initial distribution.
|
||||
*
|
||||
* Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au,
|
||||
* so that the entire packet being decompressed doesn't have
|
||||
* to be in contiguous memory (just the compressed header).
|
||||
*
|
||||
* Modified March 1998 by Guy Lancaster, glanca@gesn.com,
|
||||
* for a 16 bit processor.
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "vj.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if VJ_SUPPORT
|
||||
|
||||
#if LINK_STATS
|
||||
#define INCR(counter) ++comp->stats.counter
|
||||
#else
|
||||
#define INCR(counter)
|
||||
#endif
|
||||
|
||||
#if defined(NO_CHAR_BITFIELDS)
|
||||
#define getip_hl(base) ((base).ip_hl_v&0xf)
|
||||
#define getth_off(base) (((base).th_x2_off&0xf0)>>4)
|
||||
#else
|
||||
#define getip_hl(base) ((base).ip_hl)
|
||||
#define getth_off(base) ((base).th_off)
|
||||
#endif
|
||||
|
||||
void
|
||||
vj_compress_init(struct vjcompress *comp)
|
||||
{
|
||||
register u_int i;
|
||||
register struct cstate *tstate = comp->tstate;
|
||||
|
||||
#if MAX_SLOTS == 0
|
||||
memset((char *)comp, 0, sizeof(*comp));
|
||||
#endif
|
||||
comp->maxSlotIndex = MAX_SLOTS - 1;
|
||||
comp->compressSlot = 0; /* Disable slot ID compression by default. */
|
||||
for (i = MAX_SLOTS - 1; i > 0; --i) {
|
||||
tstate[i].cs_id = i;
|
||||
tstate[i].cs_next = &tstate[i - 1];
|
||||
}
|
||||
tstate[0].cs_next = &tstate[MAX_SLOTS - 1];
|
||||
tstate[0].cs_id = 0;
|
||||
comp->last_cs = &tstate[0];
|
||||
comp->last_recv = 255;
|
||||
comp->last_xmit = 255;
|
||||
comp->flags = VJF_TOSS;
|
||||
}
|
||||
|
||||
|
||||
/* ENCODE encodes a number that is known to be non-zero. ENCODEZ
|
||||
* checks for zero (since zero has to be encoded in the long, 3 byte
|
||||
* form).
|
||||
*/
|
||||
#define ENCODE(n) { \
|
||||
if ((u_short)(n) >= 256) { \
|
||||
*cp++ = 0; \
|
||||
cp[1] = (n); \
|
||||
cp[0] = (n) >> 8; \
|
||||
cp += 2; \
|
||||
} else { \
|
||||
*cp++ = (n); \
|
||||
} \
|
||||
}
|
||||
#define ENCODEZ(n) { \
|
||||
if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
|
||||
*cp++ = 0; \
|
||||
cp[1] = (n); \
|
||||
cp[0] = (n) >> 8; \
|
||||
cp += 2; \
|
||||
} else { \
|
||||
*cp++ = (n); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DECODEL(f) { \
|
||||
if (*cp == 0) {\
|
||||
u32_t tmp = ntohl(f) + ((cp[1] << 8) | cp[2]); \
|
||||
(f) = htonl(tmp); \
|
||||
cp += 3; \
|
||||
} else { \
|
||||
u32_t tmp = ntohl(f) + (u32_t)*cp++; \
|
||||
(f) = htonl(tmp); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DECODES(f) { \
|
||||
if (*cp == 0) {\
|
||||
u_short tmp = ntohs(f) + (((u_short)cp[1] << 8) | cp[2]); \
|
||||
(f) = htons(tmp); \
|
||||
cp += 3; \
|
||||
} else { \
|
||||
u_short tmp = ntohs(f) + (u_short)*cp++; \
|
||||
(f) = htons(tmp); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DECODEU(f) { \
|
||||
if (*cp == 0) {\
|
||||
(f) = htons(((u_short)cp[1] << 8) | cp[2]); \
|
||||
cp += 3; \
|
||||
} else { \
|
||||
(f) = htons((u_short)*cp++); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* vj_compress_tcp - Attempt to do Van Jacobson header compression on a
|
||||
* packet. This assumes that nb and comp are not null and that the first
|
||||
* buffer of the chain contains a valid IP header.
|
||||
* Return the VJ type code indicating whether or not the packet was
|
||||
* compressed.
|
||||
*/
|
||||
u_int
|
||||
vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
|
||||
{
|
||||
register struct ip *ip = (struct ip *)pb->payload;
|
||||
register struct cstate *cs = comp->last_cs->cs_next;
|
||||
register u_short hlen = getip_hl(*ip);
|
||||
register struct tcphdr *oth;
|
||||
register struct tcphdr *th;
|
||||
register u_short deltaS, deltaA;
|
||||
register u_long deltaL;
|
||||
register u_int changes = 0;
|
||||
u_char new_seq[16];
|
||||
register u_char *cp = new_seq;
|
||||
|
||||
/*
|
||||
* Check that the packet is IP proto TCP.
|
||||
*/
|
||||
if (ip->ip_p != IPPROTO_TCP) {
|
||||
return (TYPE_IP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bail if this is an IP fragment or if the TCP packet isn't
|
||||
* `compressible' (i.e., ACK isn't set or some other control bit is
|
||||
* set).
|
||||
*/
|
||||
if ((ip->ip_off & htons(0x3fff)) || pb->tot_len < 40) {
|
||||
return (TYPE_IP);
|
||||
}
|
||||
th = (struct tcphdr *)&((long *)ip)[hlen];
|
||||
if ((th->th_flags & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) {
|
||||
return (TYPE_IP);
|
||||
}
|
||||
/*
|
||||
* Packet is compressible -- we're going to send either a
|
||||
* COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need
|
||||
* to locate (or create) the connection state. Special case the
|
||||
* most recently used connection since it's most likely to be used
|
||||
* again & we don't have to do any reordering if it's used.
|
||||
*/
|
||||
INCR(vjs_packets);
|
||||
if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr
|
||||
|| ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr
|
||||
|| *(long *)th != ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) {
|
||||
/*
|
||||
* Wasn't the first -- search for it.
|
||||
*
|
||||
* States are kept in a circularly linked list with
|
||||
* last_cs pointing to the end of the list. The
|
||||
* list is kept in lru order by moving a state to the
|
||||
* head of the list whenever it is referenced. Since
|
||||
* the list is short and, empirically, the connection
|
||||
* we want is almost always near the front, we locate
|
||||
* states via linear search. If we don't find a state
|
||||
* for the datagram, the oldest state is (re-)used.
|
||||
*/
|
||||
register struct cstate *lcs;
|
||||
register struct cstate *lastcs = comp->last_cs;
|
||||
|
||||
do {
|
||||
lcs = cs; cs = cs->cs_next;
|
||||
INCR(vjs_searches);
|
||||
if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
|
||||
&& ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
|
||||
&& *(long *)th == ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) {
|
||||
goto found;
|
||||
}
|
||||
} while (cs != lastcs);
|
||||
|
||||
/*
|
||||
* Didn't find it -- re-use oldest cstate. Send an
|
||||
* uncompressed packet that tells the other side what
|
||||
* connection number we're using for this conversation.
|
||||
* Note that since the state list is circular, the oldest
|
||||
* state points to the newest and we only need to set
|
||||
* last_cs to update the lru linkage.
|
||||
*/
|
||||
INCR(vjs_misses);
|
||||
comp->last_cs = lcs;
|
||||
hlen += getth_off(*th);
|
||||
hlen <<= 2;
|
||||
/* Check that the IP/TCP headers are contained in the first buffer. */
|
||||
if (hlen > pb->len) {
|
||||
return (TYPE_IP);
|
||||
}
|
||||
goto uncompressed;
|
||||
|
||||
found:
|
||||
/*
|
||||
* Found it -- move to the front on the connection list.
|
||||
*/
|
||||
if (cs == lastcs) {
|
||||
comp->last_cs = lcs;
|
||||
} else {
|
||||
lcs->cs_next = cs->cs_next;
|
||||
cs->cs_next = lastcs->cs_next;
|
||||
lastcs->cs_next = cs;
|
||||
}
|
||||
}
|
||||
|
||||
oth = (struct tcphdr *)&((long *)&cs->cs_ip)[hlen];
|
||||
deltaS = hlen;
|
||||
hlen += getth_off(*th);
|
||||
hlen <<= 2;
|
||||
/* Check that the IP/TCP headers are contained in the first buffer. */
|
||||
if (hlen > pb->len) {
|
||||
PPPDEBUG((LOG_INFO, "vj_compress_tcp: header len %d spans buffers\n", hlen));
|
||||
return (TYPE_IP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that only what we expect to change changed. The first
|
||||
* line of the `if' checks the IP protocol version, header length &
|
||||
* type of service. The 2nd line checks the "Don't fragment" bit.
|
||||
* The 3rd line checks the time-to-live and protocol (the protocol
|
||||
* check is unnecessary but costless). The 4th line checks the TCP
|
||||
* header length. The 5th line checks IP options, if any. The 6th
|
||||
* line checks TCP options, if any. If any of these things are
|
||||
* different between the previous & current datagram, we send the
|
||||
* current datagram `uncompressed'.
|
||||
*/
|
||||
if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0]
|
||||
|| ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3]
|
||||
|| ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4]
|
||||
|| getth_off(*th) != getth_off(*oth)
|
||||
|| (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2))
|
||||
|| (getth_off(*th) > 5 && BCMP(th + 1, oth + 1, (getth_off(*th) - 5) << 2))) {
|
||||
goto uncompressed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out which of the changing fields changed. The
|
||||
* receiver expects changes in the order: urgent, window,
|
||||
* ack, seq (the order minimizes the number of temporaries
|
||||
* needed in this section of code).
|
||||
*/
|
||||
if (th->th_flags & TCP_URG) {
|
||||
deltaS = ntohs(th->th_urp);
|
||||
ENCODEZ(deltaS);
|
||||
changes |= NEW_U;
|
||||
} else if (th->th_urp != oth->th_urp) {
|
||||
/* argh! URG not set but urp changed -- a sensible
|
||||
* implementation should never do this but RFC793
|
||||
* doesn't prohibit the change so we have to deal
|
||||
* with it. */
|
||||
goto uncompressed;
|
||||
}
|
||||
|
||||
if ((deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) != 0) {
|
||||
ENCODE(deltaS);
|
||||
changes |= NEW_W;
|
||||
}
|
||||
|
||||
if ((deltaL = ntohl(th->th_ack) - ntohl(oth->th_ack)) != 0) {
|
||||
if (deltaL > 0xffff) {
|
||||
goto uncompressed;
|
||||
}
|
||||
deltaA = (u_short)deltaL;
|
||||
ENCODE(deltaA);
|
||||
changes |= NEW_A;
|
||||
}
|
||||
|
||||
if ((deltaL = ntohl(th->th_seq) - ntohl(oth->th_seq)) != 0) {
|
||||
if (deltaL > 0xffff) {
|
||||
goto uncompressed;
|
||||
}
|
||||
deltaS = (u_short)deltaL;
|
||||
ENCODE(deltaS);
|
||||
changes |= NEW_S;
|
||||
}
|
||||
|
||||
switch(changes) {
|
||||
case 0:
|
||||
/*
|
||||
* Nothing changed. If this packet contains data and the
|
||||
* last one didn't, this is probably a data packet following
|
||||
* an ack (normal on an interactive connection) and we send
|
||||
* it compressed. Otherwise it's probably a retransmit,
|
||||
* retransmitted ack or window probe. Send it uncompressed
|
||||
* in case the other side missed the compressed version.
|
||||
*/
|
||||
if (ip->ip_len != cs->cs_ip.ip_len &&
|
||||
ntohs(cs->cs_ip.ip_len) == hlen) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* (fall through) */
|
||||
|
||||
case SPECIAL_I:
|
||||
case SPECIAL_D:
|
||||
/*
|
||||
* actual changes match one of our special case encodings --
|
||||
* send packet uncompressed.
|
||||
*/
|
||||
goto uncompressed;
|
||||
|
||||
case NEW_S|NEW_A:
|
||||
if (deltaS == deltaA && deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
|
||||
/* special case for echoed terminal traffic */
|
||||
changes = SPECIAL_I;
|
||||
cp = new_seq;
|
||||
}
|
||||
break;
|
||||
|
||||
case NEW_S:
|
||||
if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
|
||||
/* special case for data xfer */
|
||||
changes = SPECIAL_D;
|
||||
cp = new_seq;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
deltaS = (u_short)(ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id));
|
||||
if (deltaS != 1) {
|
||||
ENCODEZ(deltaS);
|
||||
changes |= NEW_I;
|
||||
}
|
||||
if (th->th_flags & TCP_PSH) {
|
||||
changes |= TCP_PUSH_BIT;
|
||||
}
|
||||
/*
|
||||
* Grab the cksum before we overwrite it below. Then update our
|
||||
* state with this packet's header.
|
||||
*/
|
||||
deltaA = ntohs(th->th_sum);
|
||||
BCOPY(ip, &cs->cs_ip, hlen);
|
||||
|
||||
/*
|
||||
* We want to use the original packet as our compressed packet.
|
||||
* (cp - new_seq) is the number of bytes we need for compressed
|
||||
* sequence numbers. In addition we need one byte for the change
|
||||
* mask, one for the connection id and two for the tcp checksum.
|
||||
* So, (cp - new_seq) + 4 bytes of header are needed. hlen is how
|
||||
* many bytes of the original packet to toss so subtract the two to
|
||||
* get the new packet size.
|
||||
*/
|
||||
deltaS = (u_short)(cp - new_seq);
|
||||
if (!comp->compressSlot || comp->last_xmit != cs->cs_id) {
|
||||
comp->last_xmit = cs->cs_id;
|
||||
hlen -= deltaS + 4;
|
||||
if(pbuf_header(pb, -hlen)){
|
||||
/* Can we cope with this failing? Just assert for now */
|
||||
LWIP_ASSERT("pbuf_header failed\n", 0);
|
||||
}
|
||||
cp = (u_char *)pb->payload;
|
||||
*cp++ = changes | NEW_C;
|
||||
*cp++ = cs->cs_id;
|
||||
} else {
|
||||
hlen -= deltaS + 3;
|
||||
if(pbuf_header(pb, -hlen)) {
|
||||
/* Can we cope with this failing? Just assert for now */
|
||||
LWIP_ASSERT("pbuf_header failed\n", 0);
|
||||
}
|
||||
cp = (u_char *)pb->payload;
|
||||
*cp++ = changes;
|
||||
}
|
||||
*cp++ = deltaA >> 8;
|
||||
*cp++ = deltaA;
|
||||
BCOPY(new_seq, cp, deltaS);
|
||||
INCR(vjs_compressed);
|
||||
return (TYPE_COMPRESSED_TCP);
|
||||
|
||||
/*
|
||||
* Update connection state cs & send uncompressed packet (that is,
|
||||
* a regular ip/tcp packet but with the 'conversation id' we hope
|
||||
* to use on future compressed packets in the protocol field).
|
||||
*/
|
||||
uncompressed:
|
||||
BCOPY(ip, &cs->cs_ip, hlen);
|
||||
ip->ip_p = cs->cs_id;
|
||||
comp->last_xmit = cs->cs_id;
|
||||
return (TYPE_UNCOMPRESSED_TCP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when we may have missed a packet.
|
||||
*/
|
||||
void
|
||||
vj_uncompress_err(struct vjcompress *comp)
|
||||
{
|
||||
comp->flags |= VJF_TOSS;
|
||||
INCR(vjs_errorin);
|
||||
}
|
||||
|
||||
/*
|
||||
* "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP.
|
||||
* Return 0 on success, -1 on failure.
|
||||
*/
|
||||
int
|
||||
vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp)
|
||||
{
|
||||
register u_int hlen;
|
||||
register struct cstate *cs;
|
||||
register struct ip *ip;
|
||||
|
||||
ip = (struct ip *)nb->payload;
|
||||
hlen = getip_hl(*ip) << 2;
|
||||
if (ip->ip_p >= MAX_SLOTS
|
||||
|| hlen + sizeof(struct tcphdr) > nb->len
|
||||
|| (hlen += getth_off(*((struct tcphdr *)&((char *)ip)[hlen])) << 2)
|
||||
> nb->len
|
||||
|| hlen > MAX_HDR) {
|
||||
PPPDEBUG((LOG_INFO, "vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n",
|
||||
ip->ip_p, hlen, nb->len));
|
||||
comp->flags |= VJF_TOSS;
|
||||
INCR(vjs_errorin);
|
||||
return -1;
|
||||
}
|
||||
cs = &comp->rstate[comp->last_recv = ip->ip_p];
|
||||
comp->flags &=~ VJF_TOSS;
|
||||
ip->ip_p = IPPROTO_TCP;
|
||||
BCOPY(ip, &cs->cs_ip, hlen);
|
||||
cs->cs_hlen = hlen;
|
||||
INCR(vjs_uncompressedin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uncompress a packet of type TYPE_COMPRESSED_TCP.
|
||||
* The packet is composed of a buffer chain and the first buffer
|
||||
* must contain an accurate chain length.
|
||||
* The first buffer must include the entire compressed TCP/IP header.
|
||||
* This procedure replaces the compressed header with the uncompressed
|
||||
* header and returns the length of the VJ header.
|
||||
*/
|
||||
int
|
||||
vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
|
||||
{
|
||||
u_char *cp;
|
||||
struct tcphdr *th;
|
||||
struct cstate *cs;
|
||||
u_short *bp;
|
||||
struct pbuf *n0 = *nb;
|
||||
u32_t tmp;
|
||||
u_int vjlen, hlen, changes;
|
||||
|
||||
INCR(vjs_compressedin);
|
||||
cp = (u_char *)n0->payload;
|
||||
changes = *cp++;
|
||||
if (changes & NEW_C) {
|
||||
/*
|
||||
* Make sure the state index is in range, then grab the state.
|
||||
* If we have a good state index, clear the 'discard' flag.
|
||||
*/
|
||||
if (*cp >= MAX_SLOTS) {
|
||||
PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: bad cid=%d\n", *cp));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
comp->flags &=~ VJF_TOSS;
|
||||
comp->last_recv = *cp++;
|
||||
} else {
|
||||
/*
|
||||
* this packet has an implicit state index. If we've
|
||||
* had a line error since the last time we got an
|
||||
* explicit state index, we have to toss the packet.
|
||||
*/
|
||||
if (comp->flags & VJF_TOSS) {
|
||||
PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: tossing\n"));
|
||||
INCR(vjs_tossed);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
cs = &comp->rstate[comp->last_recv];
|
||||
hlen = getip_hl(cs->cs_ip) << 2;
|
||||
th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
|
||||
th->th_sum = htons((*cp << 8) | cp[1]);
|
||||
cp += 2;
|
||||
if (changes & TCP_PUSH_BIT) {
|
||||
th->th_flags |= TCP_PSH;
|
||||
} else {
|
||||
th->th_flags &=~ TCP_PSH;
|
||||
}
|
||||
|
||||
switch (changes & SPECIALS_MASK) {
|
||||
case SPECIAL_I:
|
||||
{
|
||||
register u32_t i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
|
||||
/* some compilers can't nest inline assembler.. */
|
||||
tmp = ntohl(th->th_ack) + i;
|
||||
th->th_ack = htonl(tmp);
|
||||
tmp = ntohl(th->th_seq) + i;
|
||||
th->th_seq = htonl(tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case SPECIAL_D:
|
||||
/* some compilers can't nest inline assembler.. */
|
||||
tmp = ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
|
||||
th->th_seq = htonl(tmp);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (changes & NEW_U) {
|
||||
th->th_flags |= TCP_URG;
|
||||
DECODEU(th->th_urp);
|
||||
} else {
|
||||
th->th_flags &=~ TCP_URG;
|
||||
}
|
||||
if (changes & NEW_W) {
|
||||
DECODES(th->th_win);
|
||||
}
|
||||
if (changes & NEW_A) {
|
||||
DECODEL(th->th_ack);
|
||||
}
|
||||
if (changes & NEW_S) {
|
||||
DECODEL(th->th_seq);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (changes & NEW_I) {
|
||||
DECODES(cs->cs_ip.ip_id);
|
||||
} else {
|
||||
cs->cs_ip.ip_id = ntohs(cs->cs_ip.ip_id) + 1;
|
||||
cs->cs_ip.ip_id = htons(cs->cs_ip.ip_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, cp points to the first byte of data in the
|
||||
* packet. Fill in the IP total length and update the IP
|
||||
* header checksum.
|
||||
*/
|
||||
vjlen = (u_short)(cp - (u_char*)n0->payload);
|
||||
if (n0->len < vjlen) {
|
||||
/*
|
||||
* We must have dropped some characters (crc should detect
|
||||
* this but the old slip framing won't)
|
||||
*/
|
||||
PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: head buffer %d too short %d\n",
|
||||
n0->len, vjlen));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
tmp = n0->tot_len - vjlen + cs->cs_hlen;
|
||||
cs->cs_ip.ip_len = htons(tmp);
|
||||
#else
|
||||
cs->cs_ip.ip_len = htons(n0->tot_len - vjlen + cs->cs_hlen);
|
||||
#endif
|
||||
|
||||
/* recompute the ip header checksum */
|
||||
bp = (u_short *) &cs->cs_ip;
|
||||
cs->cs_ip.ip_sum = 0;
|
||||
for (tmp = 0; hlen > 0; hlen -= 2) {
|
||||
tmp += *bp++;
|
||||
}
|
||||
tmp = (tmp & 0xffff) + (tmp >> 16);
|
||||
tmp = (tmp & 0xffff) + (tmp >> 16);
|
||||
cs->cs_ip.ip_sum = (u_short)(~tmp);
|
||||
|
||||
/* Remove the compressed header and prepend the uncompressed header. */
|
||||
if(pbuf_header(n0, -((s16_t)(vjlen)))) {
|
||||
/* Can we cope with this failing? Just assert for now */
|
||||
LWIP_ASSERT("pbuf_header failed\n", 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) {
|
||||
struct pbuf *np, *q;
|
||||
u8_t *bufptr;
|
||||
|
||||
np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL);
|
||||
if(!np) {
|
||||
PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: realign failed\n"));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if(pbuf_header(np, -cs->cs_hlen)) {
|
||||
/* Can we cope with this failing? Just assert for now */
|
||||
LWIP_ASSERT("pbuf_header failed\n", 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
bufptr = n0->payload;
|
||||
for(q = np; q != NULL; q = q->next) {
|
||||
MEMCPY(q->payload, bufptr, q->len);
|
||||
bufptr += q->len;
|
||||
}
|
||||
|
||||
if(n0->next) {
|
||||
pbuf_chain(np, n0->next);
|
||||
pbuf_dechain(n0);
|
||||
}
|
||||
pbuf_free(n0);
|
||||
n0 = np;
|
||||
}
|
||||
|
||||
if(pbuf_header(n0, cs->cs_hlen)) {
|
||||
struct pbuf *np;
|
||||
|
||||
LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE);
|
||||
np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL);
|
||||
if(!np) {
|
||||
PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: prepend failed\n"));
|
||||
goto bad;
|
||||
}
|
||||
pbuf_cat(np, n0);
|
||||
n0 = np;
|
||||
}
|
||||
LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen);
|
||||
MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen);
|
||||
|
||||
*nb = n0;
|
||||
|
||||
return vjlen;
|
||||
|
||||
bad:
|
||||
comp->flags |= VJF_TOSS;
|
||||
INCR(vjs_errorin);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#endif /* VJ_SUPPORT */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
155
lwip/src/netif/ppp/vj.h
Normal file
155
lwip/src/netif/ppp/vj.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Definitions for tcp compression routines.
|
||||
*
|
||||
* $Id: vj.h,v 1.5 2007/12/19 20:47:23 fbernon Exp $
|
||||
*
|
||||
* Copyright (c) 1989 Regents of the University of California.
|
||||
* 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 University of California, Berkeley. 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.
|
||||
*
|
||||
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
|
||||
* - Initial distribution.
|
||||
*/
|
||||
|
||||
#ifndef VJ_H
|
||||
#define VJ_H
|
||||
|
||||
#include "vjbsdhdr.h"
|
||||
|
||||
#define MAX_SLOTS 16 /* must be > 2 and < 256 */
|
||||
#define MAX_HDR 128
|
||||
|
||||
/*
|
||||
* Compressed packet format:
|
||||
*
|
||||
* The first octet contains the packet type (top 3 bits), TCP
|
||||
* 'push' bit, and flags that indicate which of the 4 TCP sequence
|
||||
* numbers have changed (bottom 5 bits). The next octet is a
|
||||
* conversation number that associates a saved IP/TCP header with
|
||||
* the compressed packet. The next two octets are the TCP checksum
|
||||
* from the original datagram. The next 0 to 15 octets are
|
||||
* sequence number changes, one change per bit set in the header
|
||||
* (there may be no changes and there are two special cases where
|
||||
* the receiver implicitly knows what changed -- see below).
|
||||
*
|
||||
* There are 5 numbers which can change (they are always inserted
|
||||
* in the following order): TCP urgent pointer, window,
|
||||
* acknowlegement, sequence number and IP ID. (The urgent pointer
|
||||
* is different from the others in that its value is sent, not the
|
||||
* change in value.) Since typical use of SLIP links is biased
|
||||
* toward small packets (see comments on MTU/MSS below), changes
|
||||
* use a variable length coding with one octet for numbers in the
|
||||
* range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
|
||||
* range 256 - 65535 or 0. (If the change in sequence number or
|
||||
* ack is more than 65535, an uncompressed packet is sent.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Packet types (must not conflict with IP protocol version)
|
||||
*
|
||||
* The top nibble of the first octet is the packet type. There are
|
||||
* three possible types: IP (not proto TCP or tcp with one of the
|
||||
* control flags set); uncompressed TCP (a normal IP/TCP packet but
|
||||
* with the 8-bit protocol field replaced by an 8-bit connection id --
|
||||
* this type of packet syncs the sender & receiver); and compressed
|
||||
* TCP (described above).
|
||||
*
|
||||
* LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
|
||||
* is logically part of the 4-bit "changes" field that follows. Top
|
||||
* three bits are actual packet type. For backward compatibility
|
||||
* and in the interest of conserving bits, numbers are chosen so the
|
||||
* IP protocol version number (4) which normally appears in this nibble
|
||||
* means "IP packet".
|
||||
*/
|
||||
|
||||
/* packet types */
|
||||
#define TYPE_IP 0x40
|
||||
#define TYPE_UNCOMPRESSED_TCP 0x70
|
||||
#define TYPE_COMPRESSED_TCP 0x80
|
||||
#define TYPE_ERROR 0x00
|
||||
|
||||
/* Bits in first octet of compressed packet */
|
||||
#define NEW_C 0x40 /* flag bits for what changed in a packet */
|
||||
#define NEW_I 0x20
|
||||
#define NEW_S 0x08
|
||||
#define NEW_A 0x04
|
||||
#define NEW_W 0x02
|
||||
#define NEW_U 0x01
|
||||
|
||||
/* reserved, special-case values of above */
|
||||
#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
|
||||
#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */
|
||||
#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
|
||||
|
||||
#define TCP_PUSH_BIT 0x10
|
||||
|
||||
|
||||
/*
|
||||
* "state" data for each active tcp conversation on the wire. This is
|
||||
* basically a copy of the entire IP/TCP header from the last packet
|
||||
* we saw from the conversation together with a small identifier
|
||||
* the transmit & receive ends of the line use to locate saved header.
|
||||
*/
|
||||
struct cstate {
|
||||
struct cstate *cs_next; /* next most recently used state (xmit only) */
|
||||
u_short cs_hlen; /* size of hdr (receive only) */
|
||||
u_char cs_id; /* connection # associated with this state */
|
||||
u_char cs_filler;
|
||||
union {
|
||||
char csu_hdr[MAX_HDR];
|
||||
struct ip csu_ip; /* ip/tcp hdr from most recent packet */
|
||||
} vjcs_u;
|
||||
};
|
||||
#define cs_ip vjcs_u.csu_ip
|
||||
#define cs_hdr vjcs_u.csu_hdr
|
||||
|
||||
|
||||
struct vjstat {
|
||||
unsigned long vjs_packets; /* outbound packets */
|
||||
unsigned long vjs_compressed; /* outbound compressed packets */
|
||||
unsigned long vjs_searches; /* searches for connection state */
|
||||
unsigned long vjs_misses; /* times couldn't find conn. state */
|
||||
unsigned long vjs_uncompressedin; /* inbound uncompressed packets */
|
||||
unsigned long vjs_compressedin; /* inbound compressed packets */
|
||||
unsigned long vjs_errorin; /* inbound unknown type packets */
|
||||
unsigned long vjs_tossed; /* inbound packets tossed because of error */
|
||||
};
|
||||
|
||||
/*
|
||||
* all the state data for one serial line (we need one of these per line).
|
||||
*/
|
||||
struct vjcompress {
|
||||
struct cstate *last_cs; /* most recently used tstate */
|
||||
u_char last_recv; /* last rcvd conn. id */
|
||||
u_char last_xmit; /* last sent conn. id */
|
||||
u_short flags;
|
||||
u_char maxSlotIndex;
|
||||
u_char compressSlot; /* Flag indicating OK to compress slot ID. */
|
||||
#if LINK_STATS
|
||||
struct vjstat stats;
|
||||
#endif
|
||||
struct cstate tstate[MAX_SLOTS]; /* xmit connection states */
|
||||
struct cstate rstate[MAX_SLOTS]; /* receive connection states */
|
||||
};
|
||||
|
||||
/* flag values */
|
||||
#define VJF_TOSS 1U /* tossing rcvd frames because of input err */
|
||||
|
||||
extern void vj_compress_init (struct vjcompress *comp);
|
||||
extern u_int vj_compress_tcp (struct vjcompress *comp, struct pbuf *pb);
|
||||
extern void vj_uncompress_err (struct vjcompress *comp);
|
||||
extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp);
|
||||
extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp);
|
||||
|
||||
#endif /* VJ_H */
|
75
lwip/src/netif/ppp/vjbsdhdr.h
Normal file
75
lwip/src/netif/ppp/vjbsdhdr.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
#ifndef VJBSDHDR_H
|
||||
#define VJBSDHDR_H
|
||||
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
/*
|
||||
* Structure of an internet header, naked of options.
|
||||
*
|
||||
* We declare ip_len and ip_off to be short, rather than u_short
|
||||
* pragmatically since otherwise unsigned comparisons can result
|
||||
* against negative integers quite easily, and fail in subtle ways.
|
||||
*/
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip
|
||||
{
|
||||
#if defined(NO_CHAR_BITFIELDS)
|
||||
u_char ip_hl_v; /* bug in GCC for mips means the bitfield stuff will sometimes break - so we use a char for both and get round it with macro's instead... */
|
||||
#else
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
unsigned ip_hl:4, /* header length */
|
||||
ip_v :4; /* version */
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
unsigned ip_v :4, /* version */
|
||||
ip_hl:4; /* header length */
|
||||
#else
|
||||
COMPLAIN - NO BYTE ORDER SELECTED!
|
||||
#endif
|
||||
#endif
|
||||
u_char ip_tos; /* type of service */
|
||||
u_short ip_len; /* total length */
|
||||
u_short ip_id; /* identification */
|
||||
u_short ip_off; /* fragment offset field */
|
||||
#define IP_DF 0x4000 /* dont fragment flag */
|
||||
#define IP_MF 0x2000 /* more fragments flag */
|
||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||
u_char ip_ttl; /* time to live */
|
||||
u_char ip_p; /* protocol */
|
||||
u_short ip_sum; /* checksum */
|
||||
struct in_addr ip_src,ip_dst; /* source and dest address */
|
||||
};
|
||||
PACK_STRUCT_END
|
||||
|
||||
typedef u32_t tcp_seq;
|
||||
|
||||
/*
|
||||
* TCP header.
|
||||
* Per RFC 793, September, 1981.
|
||||
*/
|
||||
PACK_STRUCT_BEGIN
|
||||
struct tcphdr
|
||||
{
|
||||
u_short th_sport; /* source port */
|
||||
u_short th_dport; /* destination port */
|
||||
tcp_seq th_seq; /* sequence number */
|
||||
tcp_seq th_ack; /* acknowledgement number */
|
||||
#if defined(NO_CHAR_BITFIELDS)
|
||||
u_char th_x2_off;
|
||||
#else
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
unsigned th_x2 :4, /* (unused) */
|
||||
th_off:4; /* data offset */
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
unsigned th_off:4, /* data offset */
|
||||
th_x2 :4; /* (unused) */
|
||||
#endif
|
||||
#endif
|
||||
u_char th_flags;
|
||||
u_short th_win; /* window */
|
||||
u_short th_sum; /* checksum */
|
||||
u_short th_urp; /* urgent pointer */
|
||||
};
|
||||
PACK_STRUCT_END
|
||||
|
||||
#endif /* VJBSDHDR_H */
|
Loading…
Add table
Reference in a new issue