mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-10-01 12:24:22 +00:00
add PPP stack from Marc. Work in progress
This commit is contained in:
parent
6719f10034
commit
31776e23fe
910
src/netif/ppp/auth.c
Normal file
910
src/netif/ppp/auth.c
Normal file
@ -0,0 +1,910 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 "ppp.h"
|
||||||
|
#if PPP_SUPPORT > 0
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "lcp.h"
|
||||||
|
#include "pap.h"
|
||||||
|
#include "chap.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "ipcp.h"
|
||||||
|
|
||||||
|
#if CBCP_SUPPORT > 0
|
||||||
|
#include "cbcp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "pppdebug.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 PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
|
||||||
|
static void set_allowed_addrs(int unit, struct wordlist *addrs);
|
||||||
|
static void free_wordlist (struct wordlist *);
|
||||||
|
#endif
|
||||||
|
#if CBCP_SUPPORT > 0
|
||||||
|
static void callback_phase (int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/******************************/
|
||||||
|
/*** PUBLIC DATA STRUCTURES ***/
|
||||||
|
/******************************/
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************/
|
||||||
|
/*** LOCAL DATA STRUCTURES ***/
|
||||||
|
/*****************************/
|
||||||
|
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
|
||||||
|
/* The name by which the peer authenticated itself to us. */
|
||||||
|
static char peer_authname[MAXNAMELEN];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 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 > 0 || CHAP_SUPPORT > 0
|
||||||
|
/* Set if we got the contents of passwd[] from the pap-secrets file. */
|
||||||
|
static int passwd_from_file;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************/
|
||||||
|
/*** 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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
ppp_trace(LOG_NOTICE, "Connection terminated.\n");
|
||||||
|
pppMainWakeup(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;
|
||||||
|
pppMainWakeup(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 > 0 || CHAP_SUPPORT > 0
|
||||||
|
lcp_options *ho = &lcp_hisoptions[unit];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
ppp_trace(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 > 0
|
||||||
|
if (go->neg_chap) {
|
||||||
|
ChapAuthPeer(unit, ppp_settings.our_name, go->chap_mdtype);
|
||||||
|
auth |= CHAP_PEER;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#if PAP_SUPPORT > 0
|
||||||
|
if (go->neg_upap) {
|
||||||
|
upap_authpeer(unit);
|
||||||
|
auth |= PAP_PEER;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if CHAP_SUPPORT > 0
|
||||||
|
if (ho->neg_chap) {
|
||||||
|
ChapAuthWithPeer(unit, ppp_settings.user, ho->chap_mdtype);
|
||||||
|
auth |= CHAP_WITHPEER;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#if PAP_SUPPORT > 0
|
||||||
|
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))
|
||||||
|
ppp_trace(LOG_ERR, "No secret found for PAP login\n");
|
||||||
|
}
|
||||||
|
upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd);
|
||||||
|
auth |= PAP_WITHPEER;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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 > 0 || CHAP_SUPPORT > 0
|
||||||
|
/*
|
||||||
|
* 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:
|
||||||
|
ppp_trace(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;
|
||||||
|
|
||||||
|
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:
|
||||||
|
ppp_trace(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
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* np_up - a network protocol has come up.
|
||||||
|
*/
|
||||||
|
void np_up(int unit, u16_t 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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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 && 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 > 0
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*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) {
|
||||||
|
ppp_trace(LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user);
|
||||||
|
ppp_panic("Excess Bad Logins");
|
||||||
|
}
|
||||||
|
if (attempts > 3) {
|
||||||
|
ppp_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
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 > 0
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
return 0;
|
||||||
|
#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) {
|
||||||
|
ppp_trace(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
|
||||||
|
|
||||||
|
|
||||||
|
#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 > 0
|
||||||
|
/*
|
||||||
|
* If we negotiated callback, do it now.
|
||||||
|
*/
|
||||||
|
if (go->neg_cbcp) {
|
||||||
|
lcp_phase[unit] = PHASE_CALLBACK;
|
||||||
|
(*cbcp_protent.open)(unit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
(void)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. */
|
||||||
|
ppp_trace(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)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
ppp_trace(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)
|
||||||
|
{
|
||||||
|
(void)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)
|
||||||
|
{
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
(void)client;
|
||||||
|
(void)server;
|
||||||
|
(void)remote;
|
||||||
|
/* XXX Fail until we set up our passwords. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
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 PAP_SUPPORT > 0 || 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
|
||||||
|
|
||||||
|
#endif /* PPP_SUPPORT */
|
94
src/netif/ppp/auth.h
Normal file
94
src/netif/ppp/auth.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 ***
|
||||||
|
***********************/
|
||||||
|
void link_required (int); /* we are starting to use the link */
|
||||||
|
void link_terminated (int); /* we are finished with the link */
|
||||||
|
void link_down (int); /* the LCP layer has left the Opened state */
|
||||||
|
void link_established (int); /* the link is up; authenticate now */
|
||||||
|
void np_up (int, u16_t); /* a network protocol has come up */
|
||||||
|
void np_down (int, u16_t); /* a network protocol has gone down */
|
||||||
|
void np_finished (int, u16_t); /* a network protocol no longer needs link */
|
||||||
|
void auth_peer_fail (int, u16_t);/* peer failed to authenticate itself */
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
void auth_reset (int); /* check what secrets we have */
|
||||||
|
|
||||||
|
/* 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 */
|
872
src/netif/ppp/chap.c
Normal file
872
src/netif/ppp/chap.c
Normal file
@ -0,0 +1,872 @@
|
|||||||
|
/*** 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 "ppp.h"
|
||||||
|
#if PPP_SUPPORT > 0
|
||||||
|
#include "magic.h"
|
||||||
|
|
||||||
|
#if CHAP_SUPPORT > 0
|
||||||
|
|
||||||
|
#include "randm.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "md5.h"
|
||||||
|
#include "chap.h"
|
||||||
|
#include "chpms.h"
|
||||||
|
#include "pppdebug.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);
|
||||||
|
static int ChapPrintPkt (u_char *, int,
|
||||||
|
void (*) (void *, char *, ...), void *);
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************/
|
||||||
|
/*** LOCAL DATA STRUCTURES ***/
|
||||||
|
/*****************************/
|
||||||
|
static char *ChapCodenames[] = {
|
||||||
|
"Challenge", "Response", "Success", "Failure"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************/
|
||||||
|
/*** 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 */
|
||||||
|
ppp_trace(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? */
|
||||||
|
ppp_trace(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 */
|
||||||
|
ppp_trace(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));
|
||||||
|
ppp_trace(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 {
|
||||||
|
ppp_trace(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)
|
||||||
|
{
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
ppp_trace(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 /* PPP_SUPPORT */
|
167
src/netif/ppp/chap.h
Normal file
167
src/netif/ppp/chap.h
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.1 2003/05/27 14:37:56 jani 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 */
|
||||||
|
|
398
src/netif/ppp/chpms.c
Normal file
398
src/netif/ppp/chpms.c
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/
|
||||||
|
/*****************************************************************************
|
||||||
|
* 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 "ppp.h"
|
||||||
|
|
||||||
|
#if MSCHAP_SUPPORT > 0
|
||||||
|
|
||||||
|
#include "md4.h"
|
||||||
|
#ifndef USE_CRYPT
|
||||||
|
#include "des.h"
|
||||||
|
#endif
|
||||||
|
#include "chap.h"
|
||||||
|
#include "chpms.h"
|
||||||
|
#include "pppdebug.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 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 */
|
||||||
|
|
64
src/netif/ppp/chpms.h
Normal file
64
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.1 2003/05/27 14:37:56 jani 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 */
|
838
src/netif/ppp/fsm.c
Normal file
838
src/netif/ppp/fsm.c
Normal file
@ -0,0 +1,838 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 "ppp.h"
|
||||||
|
#if PPP_SUPPORT > 0
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "pppdebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*************************/
|
||||||
|
/*** LOCAL DEFINITIONS ***/
|
||||||
|
/*************************/
|
||||||
|
|
||||||
|
|
||||||
|
/************************/
|
||||||
|
/*** 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 = 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;
|
||||||
|
|
||||||
|
switch( f->state ){
|
||||||
|
case INITIAL:
|
||||||
|
f->state = CLOSED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STARTING:
|
||||||
|
if( f->flags & OPT_SILENT )
|
||||||
|
f->state = STOPPED;
|
||||||
|
else {
|
||||||
|
/* Send an initial configure-request */
|
||||||
|
fsm_sconfreq(f, 0);
|
||||||
|
f->state = REQSENT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FSMDEBUG((LOG_INFO, "%s: Up event in state %d!\n",
|
||||||
|
PROTO_NAME(f), f->state));
|
||||||
|
}
|
||||||
|
|
||||||
|
FSMDEBUG((LOG_INFO, "%s: lowerup state %d -> %d\n",
|
||||||
|
PROTO_NAME(f), oldState, 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;
|
||||||
|
|
||||||
|
switch( f->state ){
|
||||||
|
case CLOSED:
|
||||||
|
f->state = INITIAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STOPPED:
|
||||||
|
f->state = STARTING;
|
||||||
|
if( f->callbacks->starting )
|
||||||
|
(*f->callbacks->starting)(f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLOSING:
|
||||||
|
f->state = INITIAL;
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STOPPING:
|
||||||
|
case REQSENT:
|
||||||
|
case ACKRCVD:
|
||||||
|
case ACKSENT:
|
||||||
|
f->state = STARTING;
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPENED:
|
||||||
|
if( f->callbacks->down )
|
||||||
|
(*f->callbacks->down)(f);
|
||||||
|
f->state = STARTING;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FSMDEBUG((LOG_INFO, "%s: Down event in state %d!\n",
|
||||||
|
PROTO_NAME(f), f->state));
|
||||||
|
}
|
||||||
|
|
||||||
|
FSMDEBUG((LOG_INFO, "%s: lowerdown state %d -> %d\n",
|
||||||
|
PROTO_NAME(f), oldState, f->state));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsm_open - Link is allowed to come up.
|
||||||
|
*/
|
||||||
|
void fsm_open(fsm *f)
|
||||||
|
{
|
||||||
|
int oldState = f->state;
|
||||||
|
|
||||||
|
switch( f->state ){
|
||||||
|
case INITIAL:
|
||||||
|
f->state = STARTING;
|
||||||
|
if( f->callbacks->starting )
|
||||||
|
(*f->callbacks->starting)(f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLOSED:
|
||||||
|
if( f->flags & OPT_SILENT )
|
||||||
|
f->state = STOPPED;
|
||||||
|
else {
|
||||||
|
/* Send an initial configure-request */
|
||||||
|
fsm_sconfreq(f, 0);
|
||||||
|
f->state = REQSENT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLOSING:
|
||||||
|
f->state = STOPPING;
|
||||||
|
/* fall through */
|
||||||
|
case STOPPED:
|
||||||
|
case OPENED:
|
||||||
|
if( f->flags & OPT_RESTART ){
|
||||||
|
fsm_lowerdown(f);
|
||||||
|
fsm_lowerup(f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSMDEBUG((LOG_INFO, "%s: open state %d -> %d\n",
|
||||||
|
PROTO_NAME(f), oldState, f->state));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsm_close - Start closing connection.
|
||||||
|
*
|
||||||
|
* Cancel timeouts and either initiate close or possibly go directly to
|
||||||
|
* the CLOSED state.
|
||||||
|
*/
|
||||||
|
void fsm_close(fsm *f, char *reason)
|
||||||
|
{
|
||||||
|
int oldState = f->state;
|
||||||
|
|
||||||
|
f->term_reason = reason;
|
||||||
|
f->term_reason_len = (reason == NULL? 0: strlen(reason));
|
||||||
|
switch( f->state ){
|
||||||
|
case STARTING:
|
||||||
|
f->state = INITIAL;
|
||||||
|
break;
|
||||||
|
case STOPPED:
|
||||||
|
f->state = CLOSED;
|
||||||
|
break;
|
||||||
|
case STOPPING:
|
||||||
|
f->state = CLOSING;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REQSENT:
|
||||||
|
case ACKRCVD:
|
||||||
|
case ACKSENT:
|
||||||
|
case OPENED:
|
||||||
|
if( f->state != OPENED )
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
else if( f->callbacks->down )
|
||||||
|
(*f->callbacks->down)(f); /* Inform upper layers we're down */
|
||||||
|
|
||||||
|
/* Init restart counter, send Terminate-Request */
|
||||||
|
f->retransmits = f->maxtermtransmits;
|
||||||
|
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
|
||||||
|
(u_char *) f->term_reason, f->term_reason_len);
|
||||||
|
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||||
|
--f->retransmits;
|
||||||
|
|
||||||
|
f->state = CLOSING;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSMDEBUG((LOG_INFO, "%s: close reason=%s state %d -> %d\n",
|
||||||
|
PROTO_NAME(f), reason, oldState, 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 == INITIAL || f->state == STARTING ){
|
||||||
|
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d.\n",
|
||||||
|
f->protocol, 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 CLOSING:
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
/* fall through */
|
||||||
|
case CLOSED:
|
||||||
|
f->state = CLOSED;
|
||||||
|
if( f->callbacks->finished )
|
||||||
|
(*f->callbacks->finished)(f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STOPPING:
|
||||||
|
case REQSENT:
|
||||||
|
case ACKRCVD:
|
||||||
|
case ACKSENT:
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
/* fall through */
|
||||||
|
case STOPPED:
|
||||||
|
f->state = STOPPED;
|
||||||
|
if( f->callbacks->finished )
|
||||||
|
(*f->callbacks->finished)(f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPENED:
|
||||||
|
if( f->callbacks->down )
|
||||||
|
(*f->callbacks->down)(f);
|
||||||
|
|
||||||
|
/* Init restart counter, send Terminate-Request */
|
||||||
|
f->retransmits = f->maxtermtransmits;
|
||||||
|
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
|
||||||
|
(u_char *) f->term_reason, f->term_reason_len);
|
||||||
|
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||||
|
--f->retransmits;
|
||||||
|
|
||||||
|
f->state = STOPPING;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d!\n",
|
||||||
|
PROTO_NAME(f), f->state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************/
|
||||||
|
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||||
|
/**********************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsm_timeout - Timeout expired.
|
||||||
|
*/
|
||||||
|
static void fsm_timeout(void *arg)
|
||||||
|
{
|
||||||
|
fsm *f = (fsm *) arg;
|
||||||
|
|
||||||
|
switch (f->state) {
|
||||||
|
case CLOSING:
|
||||||
|
case STOPPING:
|
||||||
|
if( f->retransmits <= 0 ){
|
||||||
|
FSMDEBUG((LOG_WARNING, "%s: timeout sending Terminate-Request state=%d\n",
|
||||||
|
PROTO_NAME(f), f->state));
|
||||||
|
/*
|
||||||
|
* We've waited for an ack long enough. Peer probably heard us.
|
||||||
|
*/
|
||||||
|
f->state = (f->state == CLOSING)? CLOSED: STOPPED;
|
||||||
|
if( f->callbacks->finished )
|
||||||
|
(*f->callbacks->finished)(f);
|
||||||
|
} else {
|
||||||
|
FSMDEBUG((LOG_WARNING, "%s: timeout resending Terminate-Requests state=%d\n",
|
||||||
|
PROTO_NAME(f), 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 REQSENT:
|
||||||
|
case ACKRCVD:
|
||||||
|
case ACKSENT:
|
||||||
|
if (f->retransmits <= 0) {
|
||||||
|
FSMDEBUG((LOG_WARNING, "%s: timeout sending Config-Requests state=%d\n",
|
||||||
|
PROTO_NAME(f), f->state));
|
||||||
|
f->state = 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\n",
|
||||||
|
PROTO_NAME(f), 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 == ACKRCVD )
|
||||||
|
f->state = REQSENT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FSMDEBUG((LOG_INFO, "%s: Timeout event in state %d!\n",
|
||||||
|
PROTO_NAME(f), 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\n",
|
||||||
|
PROTO_NAME(f), id, f->state));
|
||||||
|
switch( f->state ){
|
||||||
|
case CLOSED:
|
||||||
|
/* Go away, we're closed */
|
||||||
|
fsm_sdata(f, TERMACK, id, NULL, 0);
|
||||||
|
return;
|
||||||
|
case CLOSING:
|
||||||
|
case STOPPING:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case OPENED:
|
||||||
|
/* Go down and restart negotiation */
|
||||||
|
if( f->callbacks->down )
|
||||||
|
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||||
|
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STOPPED:
|
||||||
|
/* Negotiation started by our peer */
|
||||||
|
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
|
||||||
|
f->state = REQSENT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pass the requested configuration options
|
||||||
|
* to protocol-specific code for checking.
|
||||||
|
*/
|
||||||
|
if (f->callbacks->reqci){ /* Check CI */
|
||||||
|
reject_if_disagree = (f->nakloops >= f->maxnakloops);
|
||||||
|
code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
|
||||||
|
}
|
||||||
|
else if (len)
|
||||||
|
code = CONFREJ; /* Reject all CI */
|
||||||
|
else
|
||||||
|
code = CONFACK;
|
||||||
|
|
||||||
|
/* send the Ack, Nak or Rej to the peer */
|
||||||
|
fsm_sdata(f, (u_char)code, id, inp, len);
|
||||||
|
|
||||||
|
if (code == CONFACK) {
|
||||||
|
if (f->state == ACKRCVD) {
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
f->state = OPENED;
|
||||||
|
if (f->callbacks->up)
|
||||||
|
(*f->callbacks->up)(f); /* Inform upper layers */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f->state = ACKSENT;
|
||||||
|
f->nakloops = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* we sent CONFACK or CONFREJ */
|
||||||
|
if (f->state != ACKRCVD)
|
||||||
|
f->state = REQSENT;
|
||||||
|
if( code == CONFNAK )
|
||||||
|
++f->nakloops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsm_rconfack - Receive Configure-Ack.
|
||||||
|
*/
|
||||||
|
static void fsm_rconfack(fsm *f, int id, u_char *inp, int len)
|
||||||
|
{
|
||||||
|
FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d state=%d\n",
|
||||||
|
PROTO_NAME(f), id, 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 CLOSED:
|
||||||
|
case STOPPED:
|
||||||
|
fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REQSENT:
|
||||||
|
f->state = ACKRCVD;
|
||||||
|
f->retransmits = f->maxconfreqtransmits;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACKRCVD:
|
||||||
|
/* Huh? an extra valid Ack? oh well... */
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
fsm_sconfreq(f, 0);
|
||||||
|
f->state = REQSENT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACKSENT:
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
f->state = OPENED;
|
||||||
|
f->retransmits = f->maxconfreqtransmits;
|
||||||
|
if (f->callbacks->up)
|
||||||
|
(*f->callbacks->up)(f); /* Inform upper layers */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPENED:
|
||||||
|
/* Go down and restart negotiation */
|
||||||
|
if (f->callbacks->down)
|
||||||
|
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||||
|
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
|
||||||
|
f->state = REQSENT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
|
||||||
|
*/
|
||||||
|
static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len)
|
||||||
|
{
|
||||||
|
int (*proc) (fsm *, u_char *, int);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d state=%d\n",
|
||||||
|
PROTO_NAME(f), id, 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 CLOSED:
|
||||||
|
case STOPPED:
|
||||||
|
fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REQSENT:
|
||||||
|
case ACKSENT:
|
||||||
|
/* They didn't agree to what we wanted - try another request */
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
if (ret < 0)
|
||||||
|
f->state = STOPPED; /* kludge for stopping CCP */
|
||||||
|
else
|
||||||
|
fsm_sconfreq(f, 0); /* Send Configure-Request */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACKRCVD:
|
||||||
|
/* Got a Nak/reject when we had already had an Ack?? oh well... */
|
||||||
|
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||||
|
fsm_sconfreq(f, 0);
|
||||||
|
f->state = REQSENT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPENED:
|
||||||
|
/* Go down and restart negotiation */
|
||||||
|
if (f->callbacks->down)
|
||||||
|
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||||
|
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
|
||||||
|
f->state = REQSENT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsm_rtermreq - Receive Terminate-Req.
|
||||||
|
*/
|
||||||
|
static void fsm_rtermreq(fsm *f, int id, u_char *p, int len)
|
||||||
|
{
|
||||||
|
FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d state=%d\n",
|
||||||
|
PROTO_NAME(f), id, f->state));
|
||||||
|
|
||||||
|
switch (f->state) {
|
||||||
|
case ACKRCVD:
|
||||||
|
case ACKSENT:
|
||||||
|
f->state = REQSENT; /* Start over but keep trying */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 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 = 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\n",
|
||||||
|
PROTO_NAME(f), f->state));
|
||||||
|
|
||||||
|
switch (f->state) {
|
||||||
|
case CLOSING:
|
||||||
|
UNTIMEOUT(fsm_timeout, f);
|
||||||
|
f->state = CLOSED;
|
||||||
|
if( f->callbacks->finished )
|
||||||
|
(*f->callbacks->finished)(f);
|
||||||
|
break;
|
||||||
|
case STOPPING:
|
||||||
|
UNTIMEOUT(fsm_timeout, f);
|
||||||
|
f->state = STOPPED;
|
||||||
|
if( f->callbacks->finished )
|
||||||
|
(*f->callbacks->finished)(f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACKRCVD:
|
||||||
|
f->state = REQSENT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPENED:
|
||||||
|
if (f->callbacks->down)
|
||||||
|
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||||
|
fsm_sconfreq(f, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsm_rcoderej - Receive an Code-Reject.
|
||||||
|
*/
|
||||||
|
static void fsm_rcoderej(fsm *f, u_char *inp, int len)
|
||||||
|
{
|
||||||
|
u_char code, id;
|
||||||
|
|
||||||
|
FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s): state=%d\n",
|
||||||
|
PROTO_NAME(f), 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 == ACKRCVD )
|
||||||
|
f->state = REQSENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fsm_sconfreq - Send a Configure-Request.
|
||||||
|
*/
|
||||||
|
static void fsm_sconfreq(fsm *f, int retransmit)
|
||||||
|
{
|
||||||
|
u_char *outp;
|
||||||
|
int cilen;
|
||||||
|
|
||||||
|
if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
|
||||||
|
/* Not currently negotiating - reset options */
|
||||||
|
if( f->callbacks->resetci )
|
||||||
|
(*f->callbacks->resetci)(f);
|
||||||
|
f->nakloops = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !retransmit ){
|
||||||
|
/* New request - reset retransmission counter, use new ID */
|
||||||
|
f->retransmits = f->maxconfreqtransmits;
|
||||||
|
f->reqid = ++f->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->seen_ack = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make up the request packet
|
||||||
|
*/
|
||||||
|
outp = outpacket_buf[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 */
|
187
src/netif/ppp/fsm.h
Normal file
187
src/netif/ppp/fsm.h
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.1 2003/05/27 14:37:56 jani 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 INITIAL 0 /* Down, hasn't been opened */
|
||||||
|
#define STARTING 1 /* Down, been opened */
|
||||||
|
#define CLOSED 2 /* Up, hasn't been opened */
|
||||||
|
#define STOPPED 3 /* Open, waiting for down event */
|
||||||
|
#define CLOSING 4 /* Terminating the connection, not open */
|
||||||
|
#define STOPPING 5 /* Terminating, but open */
|
||||||
|
#define REQSENT 6 /* We've sent a Config Request */
|
||||||
|
#define ACKRCVD 7 /* We've received a Config Ack */
|
||||||
|
#define ACKSENT 8 /* We've sent a Config Ack */
|
||||||
|
#define OPENED 9 /* Connection available */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags - indicate options controlling FSM operation
|
||||||
|
*/
|
||||||
|
#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
|
||||||
|
#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
|
||||||
|
#define OPT_SILENT 4 /* Wait for peer to speak first */
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
************************* 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) /* Reset our Configuration Information */
|
||||||
|
(fsm*);
|
||||||
|
int (*cilen) /* Length of our Configuration Information */
|
||||||
|
(fsm*);
|
||||||
|
void (*addci) /* Add our Configuration Information */
|
||||||
|
(fsm*, u_char*, int*);
|
||||||
|
int (*ackci) /* ACK our Configuration Information */
|
||||||
|
(fsm*, u_char*, int);
|
||||||
|
int (*nakci) /* NAK our Configuration Information */
|
||||||
|
(fsm*, u_char*, int);
|
||||||
|
int (*rejci) /* Reject our Configuration Information */
|
||||||
|
(fsm*, u_char*, int);
|
||||||
|
int (*reqci) /* Request peer's Configuration Information */
|
||||||
|
(fsm*, u_char*, int*, int);
|
||||||
|
void (*up) /* Called when fsm reaches OPENED state */
|
||||||
|
(fsm*);
|
||||||
|
void (*down) /* Called when fsm leaves OPENED state */
|
||||||
|
(fsm*);
|
||||||
|
void (*starting) /* Called when we want the lower layer */
|
||||||
|
(fsm*);
|
||||||
|
void (*finished) /* Called when we don't want the lower layer */
|
||||||
|
(fsm*);
|
||||||
|
void (*protreject) /* Called when Protocol-Reject received */
|
||||||
|
(int);
|
||||||
|
void (*retransmit) /* Retransmission is necessary */
|
||||||
|
(fsm*);
|
||||||
|
int (*extcode) /* Called when unknown code received */
|
||||||
|
(fsm*, int, u_char, u_char*, int);
|
||||||
|
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 */
|
||||||
|
|
1370
src/netif/ppp/ipcp.c
Normal file
1370
src/netif/ppp/ipcp.c
Normal file
File diff suppressed because it is too large
Load Diff
126
src/netif/ppp/ipcp.h
Normal file
126
src/netif/ppp/ipcp.h
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.1 2003/05/27 14:37:56 jani 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 */
|
||||||
|
|
1990
src/netif/ppp/lcp.c
Normal file
1990
src/netif/ppp/lcp.c
Normal file
File diff suppressed because it is too large
Load Diff
169
src/netif/ppp/lcp.h
Normal file
169
src/netif/ppp/lcp.h
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.1 2003/05/27 14:37:56 jani 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 */
|
||||||
|
|
79
src/netif/ppp/magic.c
Normal file
79
src/netif/ppp/magic.c
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 "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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
64
src/netif/ppp/magic.h
Normal file
64
src/netif/ppp/magic.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.1 2003/05/27 14:37:56 jani Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAGIC_H
|
||||||
|
#define MAGIC_H
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
************************** PUBLIC FUNCTIONS **********************************
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
void magicInit(void); /* Initialize the magic number generator */
|
||||||
|
u32_t magic(void); /* Returns the next magic number */
|
||||||
|
|
||||||
|
#endif /* MAGIC_H */
|
304
src/netif/ppp/md5.c
Normal file
304
src/netif/ppp/md5.c
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
***********************************************************************
|
||||||
|
** 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 "ppp.h"
|
||||||
|
#include "md5.h"
|
||||||
|
#include "pppdebug.h"
|
||||||
|
|
||||||
|
#if CHAP_SUPPORT > 0 || MD5_SUPPORT > 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
***********************************************************************
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
// ppp_trace(LOG_INFO, "MD5Update: %u:%.*H\n", inLen, MIN(inLen, 20) * 2, inBuf);
|
||||||
|
// ppp_trace(LOG_INFO, "MD5Update: %u:%s\n", inLen, inBuf);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
memcpy(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
|
||||||
|
|
55
src/netif/ppp/md5.h
Normal file
55
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 */
|
608
src/netif/ppp/pap.c
Normal file
608
src/netif/ppp/pap.c
Normal file
@ -0,0 +1,608 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 "ppp.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "pap.h"
|
||||||
|
#include "pppdebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if PAP_SUPPORT > 0
|
||||||
|
|
||||||
|
/***********************************/
|
||||||
|
/*** 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 */
|
||||||
|
ppp_trace(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) {
|
||||||
|
ppp_trace(LOG_ERR, "PAP authentication failed due to protocol-reject\n");
|
||||||
|
auth_withpeer_fail(unit, PPP_PAP);
|
||||||
|
}
|
||||||
|
if (u->us_serverstate == UPAPSS_LISTEN) {
|
||||||
|
ppp_trace(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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GETCHAR(msglen, inp);
|
||||||
|
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;
|
||||||
|
|
||||||
|
ppp_trace(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
|
||||||
|
)
|
||||||
|
{
|
||||||
|
(void)p;
|
||||||
|
(void)plen;
|
||||||
|
(void)printer;
|
||||||
|
(void)arg;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PAP_SUPPORT */
|
||||||
|
|
129
src/netif/ppp/pap.h
Normal file
129
src/netif/ppp/pap.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
*** 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_H */
|
||||||
|
|
1592
src/netif/ppp/ppp.c
Normal file
1592
src/netif/ppp/ppp.c
Normal file
File diff suppressed because it is too large
Load Diff
426
src/netif/ppp/ppp.h
Normal file
426
src/netif/ppp/ppp.h
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 "target.h"
|
||||||
|
|
||||||
|
#if PPP_SUPPORT > 0
|
||||||
|
/*
|
||||||
|
* pppd.h - PPP daemon global declarations.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1989 Carnegie Mellon University.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms are permitted
|
||||||
|
* provided that the above copyright notice and this paragraph are
|
||||||
|
* duplicated in all such forms and that any documentation,
|
||||||
|
* advertising materials, and other materials related to such
|
||||||
|
* distribution and use acknowledge that the software was developed
|
||||||
|
* by Carnegie Mellon University. The name of the
|
||||||
|
* University may not be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)++ << 8; \
|
||||||
|
(s) |= *(cp)++; \
|
||||||
|
}
|
||||||
|
#define PUTSHORT(s, cp) { \
|
||||||
|
*(cp)++ = (u_char) ((s) >> 8); \
|
||||||
|
*(cp)++ = (u_char) (s); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GETLONG(l, cp) { \
|
||||||
|
(l) = *(cp)++ << 8; \
|
||||||
|
(l) |= *(cp)++; (l) <<= 8; \
|
||||||
|
(l) |= *(cp)++; (l) <<= 8; \
|
||||||
|
(l) |= *(cp)++; \
|
||||||
|
}
|
||||||
|
#define PUTLONG(l, cp) { \
|
||||||
|
*(cp)++ = (u_char) ((l) >> 24); \
|
||||||
|
*(cp)++ = (u_char) ((l) >> 16); \
|
||||||
|
*(cp)++ = (u_char) ((l) >> 8); \
|
||||||
|
*(cp)++ = (u_char) (l); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define INCPTR(n, cp) ((cp) += (n))
|
||||||
|
#define DECPTR(n, cp) ((cp) -= (n))
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
|
#define PRINTMSG(m, l) { m[l] = '\0'; ppp_trace(LOG_INFO, "Remote message: %s\n", m); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MAKEHEADER - Add PPP Header fields to a packet.
|
||||||
|
*/
|
||||||
|
#define MAKEHEADER(p, t) { \
|
||||||
|
PUTCHAR(PPP_ALLSTATIONS, p); \
|
||||||
|
PUTCHAR(PPP_UI, p); \
|
||||||
|
PUTSHORT(t, p); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions of bits in internet address integers.
|
||||||
|
* On subnets, the decomposition of addresses to host and net parts
|
||||||
|
* is done according to subnet mask, not the masks here.
|
||||||
|
*/
|
||||||
|
#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0)
|
||||||
|
#define IN_CLASSA_NET 0xff000000
|
||||||
|
#define IN_CLASSA_NSHIFT 24
|
||||||
|
#define IN_CLASSA_HOST 0x00ffffff
|
||||||
|
#define IN_CLASSA_MAX 128
|
||||||
|
|
||||||
|
#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
|
||||||
|
#define IN_CLASSB_NET 0xffff0000
|
||||||
|
#define IN_CLASSB_NSHIFT 16
|
||||||
|
#define IN_CLASSB_HOST 0x0000ffff
|
||||||
|
#define IN_CLASSB_MAX 65536
|
||||||
|
|
||||||
|
#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
|
||||||
|
#define IN_CLASSC_NET 0xffffff00
|
||||||
|
#define IN_CLASSC_NSHIFT 8
|
||||||
|
#define IN_CLASSC_HOST 0x000000ff
|
||||||
|
|
||||||
|
#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
|
||||||
|
#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
|
||||||
|
#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
|
||||||
|
#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
|
||||||
|
#define IN_MULTICAST(i) IN_CLASSD(i)
|
||||||
|
|
||||||
|
#define IN_EXPERIMENTAL(i) (((long)(i) & 0xf0000000) == 0xf0000000)
|
||||||
|
#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000)
|
||||||
|
|
||||||
|
#define IN_LOOPBACKNET 127 /* official! */
|
||||||
|
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
*** 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[MAXNAMELEN + 1]; /* Password for PAP */
|
||||||
|
char our_name[MAXNAMELEN + 1]; /* Our name for authentication purposes */
|
||||||
|
char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
*** 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);
|
||||||
|
|
||||||
|
void pppSetAuth(const char *user, const char *passwd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open a new PPP connection using the given 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 pppOpen(ppp_sio_fd_t fd, void (*linkStatusCB)(void *arg, int errCode), void *linkStatusArg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 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);
|
||||||
|
/* 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 */
|
91
src/netif/ppp/pppdebug.h
Normal file
91
src/netif/ppp/pppdebug.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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,...);
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if PPP_DEBUG > 0
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#define TRACELCP 1
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define AUTHDEBUG(a)
|
||||||
|
#define IPCPDEBUG(a)
|
||||||
|
#define UPAPDEBUG(a)
|
||||||
|
#define LCPDEBUG(a)
|
||||||
|
#define FSMDEBUG(a)
|
||||||
|
#define CHAPDEBUG(a)
|
||||||
|
|
||||||
|
#define PPPDEBUG(a)
|
||||||
|
|
||||||
|
#define TRACELCP 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PPPDEBUG_H */
|
240
src/netif/ppp/randm.c
Normal file
240
src/netif/ppp/randm.c
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 "ppp.h"
|
||||||
|
#include "md5.h"
|
||||||
|
#include "randm.h"
|
||||||
|
|
||||||
|
#include "pppdebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if MD5_SUPPORT>0 /* 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()
|
||||||
|
{
|
||||||
|
/* Get a pointer into the last 4 bytes of clockBuf. */
|
||||||
|
u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* 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 += ppp_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 += (ppp_jiffies() - last_jiffies); /* XXX */
|
||||||
|
}
|
||||||
|
last_jiffies = ppp_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 */
|
||||||
|
|
88
src/netif/ppp/randm.h
Normal file
88
src/netif/ppp/randm.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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
|
||||||
|
void avRandomize(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize Borland's random number generator. This is a library function
|
||||||
|
* but we declare it here rather than including the entire header file
|
||||||
|
* for it.
|
||||||
|
*/
|
||||||
|
//void srand(unsigned seed);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* RANDM_H */
|
38
src/netif/ppp/target.c
Normal file
38
src/netif/ppp/target.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "ppp.h"
|
||||||
|
|
||||||
|
void ppp_panic(char * msg)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("PPP panic: %s\n", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ppp_msleep(unsigned long ms)
|
||||||
|
{
|
||||||
|
sys_sem_t delaysem = sys_sem_new(0);
|
||||||
|
|
||||||
|
sys_sem_wait_timeout(delaysem, ms);
|
||||||
|
|
||||||
|
sys_sem_free(delaysem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make a string representation of a network IP address.
|
||||||
|
* WARNING: NOT RE-ENTRANT!
|
||||||
|
*/
|
||||||
|
char *ip_ntoa(u32_t ipaddr)
|
||||||
|
{
|
||||||
|
static char b[20];
|
||||||
|
|
||||||
|
ipaddr = ntohl(ipaddr);
|
||||||
|
#if 0
|
||||||
|
// FIXME
|
||||||
|
sprintf(b, "%d.%d.%d.%d",
|
||||||
|
(u_char)(ipaddr >> 24),
|
||||||
|
(u_char)(ipaddr >> 16),
|
||||||
|
(u_char)(ipaddr >> 8),
|
||||||
|
(u_char)(ipaddr));
|
||||||
|
#endif
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
61
src/netif/ppp/target.h
Normal file
61
src/netif/ppp/target.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#ifndef TARGET_H_
|
||||||
|
#define TARGET_H_
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/debug.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"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* the following is temporary until sio_common.h defines SIO_ERROR */
|
||||||
|
#if defined(ERROR) && !defined(SIO_ERROR)
|
||||||
|
#define SIO_ERROR ERROR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TIMEOUT(f, a, t) sys_untimeout((f), (a)), sys_timeout((t)*1000, (f), (a))
|
||||||
|
#define UNTIMEOUT(f, a) sys_untimeout((f), (a))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sleep ms milliseconds. Note that this only has a (close to) 1 Jiffy
|
||||||
|
* resolution.
|
||||||
|
* Note: Since there may me less than a ms left before the next clock
|
||||||
|
* tick, 1 tick is added to ensure we delay at least ms time.
|
||||||
|
*/
|
||||||
|
void ppp_msleep(unsigned long ms);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the number of jiffies that have passed since power up.
|
||||||
|
*/
|
||||||
|
unsigned long ppp_jiffies(void);
|
||||||
|
|
||||||
|
/* Display a panic message and HALT the system. */
|
||||||
|
void ppp_panic(char *msg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make a string representation of a network IP address.
|
||||||
|
* WARNING: NOT RE-ENTRANT!
|
||||||
|
*/
|
||||||
|
char *ip_ntoa(u32_t ipaddr);
|
||||||
|
|
||||||
|
typedef void * ppp_sio_fd_t;
|
||||||
|
|
||||||
|
/*FIXME */
|
||||||
|
#define sio_read_abort(fd) do { \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* TARGET_H */
|
605
src/netif/ppp/vj.c
Normal file
605
src/netif/ppp/vj.c
Normal file
@ -0,0 +1,605 @@
|
|||||||
|
/*
|
||||||
|
* 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 "ppp.h"
|
||||||
|
#include "vj.h"
|
||||||
|
#include "pppdebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if VJ_SUPPORT > 0
|
||||||
|
|
||||||
|
#ifdef 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 Jacobsen 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;
|
||||||
|
pbuf_header(pb, -hlen);
|
||||||
|
cp = (u_char *)pb->payload;
|
||||||
|
*cp++ = changes | NEW_C;
|
||||||
|
*cp++ = cs->cs_id;
|
||||||
|
} else {
|
||||||
|
hlen -= deltaS + 3;
|
||||||
|
pbuf_header(pb, -hlen);
|
||||||
|
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. */
|
||||||
|
pbuf_header(n0, -vjlen);
|
||||||
|
|
||||||
|
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"));
|
||||||
|
*nb = NULL;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
pbuf_chain(np, n0);
|
||||||
|
n0 = np;
|
||||||
|
}
|
||||||
|
memcpy(n0->payload, &cs->cs_ip, cs->cs_hlen);
|
||||||
|
|
||||||
|
*nb = n0;
|
||||||
|
|
||||||
|
return vjlen;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
comp->flags |= VJF_TOSS;
|
||||||
|
INCR(vjs_errorin);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
155
src/netif/ppp/vj.h
Normal file
155
src/netif/ppp/vj.h
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Definitions for tcp compression routines.
|
||||||
|
*
|
||||||
|
* $Id: vj.h,v 1.1 2003/05/27 14:37:56 jani 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. */
|
||||||
|
#ifdef 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 1 /* 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 */
|
76
src/netif/ppp/vjbsdhdr.h
Normal file
76
src/netif/ppp/vjbsdhdr.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#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
|
||||||
|
u_char ip_hl:4, /* header length */
|
||||||
|
ip_v:4; /* version */
|
||||||
|
#elif BYTE_ORDER == BIG_ENDIAN
|
||||||
|
u_char 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
|
||||||
|
u_char th_x2:4, /* (unused) */
|
||||||
|
th_off:4; /* data offset */
|
||||||
|
#endif
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
u_char 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…
Reference in New Issue
Block a user