📄 ccp.c
字号:
//==========================================================================
//
// src/ccp.c
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Portions created by Nick Garnett are
// Copyright (C) 2003 eCosCentric Ltd.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
//
// Portions of this software may have been derived from OpenBSD,
// FreeBSD or other sources, and are covered by the appropriate
// copyright disclaimers included herein.
//
// -------------------------------------------
//
//####BSDCOPYRIGHTEND####
//==========================================================================
/*
* ccp.c - PPP Compression Control Protocol.
*
* Copyright (c) 1994 The Australian National University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, provided that the above copyright
* notice appears in all copies. This software is provided without any
* warranty, express or implied. The Australian National University
* makes no representations about the suitability of this software for
* any purpose.
*
* IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
* THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
*/
#ifndef lint
//static char rcsid[] = "$FreeBSD: src/usr.sbin/pppd/ccp.c,v 1.10 1999/08/28 01:19:00 peter Exp $";
#endif
#include <string.h>
#include <cyg/ppp/syslog.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include "cyg/ppp/pppd.h"
#include "cyg/ppp/fsm.h"
#include "cyg/ppp/ccp.h"
#include <cyg/ppp/net/ppp_comp.h>
/*
* Protocol entry points from main code.
*/
static void ccp_init __P((int unit));
static void ccp_open __P((int unit));
static void ccp_close __P((int unit, char *));
static void ccp_lowerup __P((int unit));
static void ccp_lowerdown __P((int));
static void ccp_input __P((int unit, u_char *pkt, int len));
static void ccp_protrej __P((int unit));
static int ccp_printpkt __P((u_char *pkt, int len,
void (*printer) __P((void *, char *, ...)),
void *arg));
static void ccp_datainput __P((int unit, u_char *pkt, int len));
struct protent ccp_protent = {
PPP_CCP,
ccp_init,
ccp_input,
ccp_protrej,
ccp_lowerup,
ccp_lowerdown,
ccp_open,
ccp_close,
ccp_printpkt,
ccp_datainput,
1,
"CCP",
NULL,
NULL,
NULL
};
fsm ccp_fsm[NUM_PPP];
ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */
ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */
ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */
/*
* Callbacks for fsm code.
*/
static void ccp_resetci __P((fsm *));
static int ccp_cilen __P((fsm *));
static void ccp_addci __P((fsm *, u_char *, int *));
static int ccp_ackci __P((fsm *, u_char *, int));
static int ccp_nakci __P((fsm *, u_char *, int));
static int ccp_rejci __P((fsm *, u_char *, int));
static int ccp_reqci __P((fsm *, u_char *, int *, int));
static void ccp_up __P((fsm *));
static void ccp_down __P((fsm *));
static int ccp_extcode __P((fsm *, int, int, u_char *, int));
static void ccp_rack_timeout __P((void *));
static char *method_name __P((ccp_options *, ccp_options *));
static fsm_callbacks ccp_callbacks = {
ccp_resetci,
ccp_cilen,
ccp_addci,
ccp_ackci,
ccp_nakci,
ccp_rejci,
ccp_reqci,
ccp_up,
ccp_down,
NULL,
NULL,
NULL,
NULL,
ccp_extcode,
"CCP"
};
/*
* Do we want / did we get any compression?
*/
#define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \ || (opt).predictor_1 || (opt).predictor_2)
/*
* Local state (mainly for handling reset-reqs and reset-acks).
*/
static int ccp_localstate[NUM_PPP];
#define RACK_PENDING 1 /* waiting for reset-ack */
#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */
#define RACKTIMEOUT 1 /* second */
static int all_rejected[NUM_PPP]; /* we rejected all peer's options */
/*
* ccp_init - initialize CCP.
*/
static void
ccp_init(unit)
int unit;
{
fsm *f = &ccp_fsm[unit];
f->unit = unit;
f->protocol = PPP_CCP;
f->callbacks = &ccp_callbacks;
fsm_init(f);
memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options));
memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options));
memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options));
ccp_wantoptions[0].deflate = 1;
ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
ccp_wantoptions[0].deflate_correct = 1;
ccp_wantoptions[0].deflate_draft = 1;
ccp_allowoptions[0].deflate = 1;
ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
ccp_allowoptions[0].deflate_correct = 1;
ccp_allowoptions[0].deflate_draft = 1;
ccp_wantoptions[0].bsd_compress = 1;
ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
ccp_allowoptions[0].bsd_compress = 1;
ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
ccp_allowoptions[0].predictor_1 = 1;
}
/*
* ccp_open - CCP is allowed to come up.
*/
static void
ccp_open(unit)
int unit;
{
fsm *f = &ccp_fsm[unit];
if (f->state != OPENED)
ccp_flags_set(unit, 1, 0);
/*
* Find out which compressors the kernel supports before
* deciding whether to open in silent mode.
*/
ccp_resetci(f);
if (!ANY_COMPRESS(ccp_gotoptions[unit]))
f->flags |= OPT_SILENT;
fsm_open(f);
}
/*
* ccp_close - Terminate CCP.
*/
static void
ccp_close(unit, reason)
int unit;
char *reason;
{
ccp_flags_set(unit, 0, 0);
fsm_close(&ccp_fsm[unit], reason);
}
/*
* ccp_lowerup - we may now transmit CCP packets.
*/
static void
ccp_lowerup(unit)
int unit;
{
fsm_lowerup(&ccp_fsm[unit]);
}
/*
* ccp_lowerdown - we may not transmit CCP packets.
*/
static void
ccp_lowerdown(unit)
int unit;
{
fsm_lowerdown(&ccp_fsm[unit]);
}
/*
* ccp_input - process a received CCP packet.
*/
static void
ccp_input(unit, p, len)
int unit;
u_char *p;
int len;
{
fsm *f = &ccp_fsm[unit];
int oldstate;
/*
* Check for a terminate-request so we can print a message.
*/
oldstate = f->state;
fsm_input(f, p, len);
if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
syslog(LOG_NOTICE, "Compression disabled by peer.");
/*
* If we get a terminate-ack and we're not asking for compression,
* close CCP.
*/
if (oldstate == REQSENT && p[0] == TERMACK
&& !ANY_COMPRESS(ccp_gotoptions[unit]))
ccp_close(unit, "No compression negotiated");
}
/*
* Handle a CCP-specific code.
*/
static int
ccp_extcode(f, code, id, p, len)
fsm *f;
int code, id;
u_char *p;
int len;
{
switch (code) {
case CCP_RESETREQ:
if (f->state != OPENED)
break;
/* send a reset-ack, which the transmitter will see and
reset its compression state. */
fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
break;
case CCP_RESETACK:
if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
UNTIMEOUT(ccp_rack_timeout, f);
}
break;
default:
return 0;
}
return 1;
}
/*
* ccp_protrej - peer doesn't talk CCP.
*/
static void
ccp_protrej(unit)
int unit;
{
ccp_flags_set(unit, 0, 0);
fsm_lowerdown(&ccp_fsm[unit]);
}
/*
* ccp_resetci - initialize at start of negotiation.
*/
static void
ccp_resetci(f)
fsm *f;
{
ccp_options *go = &ccp_gotoptions[f->unit];
u_char opt_buf[16];
*go = ccp_wantoptions[f->unit];
all_rejected[f->unit] = 0;
/*
* Check whether the kernel knows about the various
* compression methods we might request.
*/
if (go->bsd_compress) {
opt_buf[0] = CI_BSD_COMPRESS;
opt_buf[1] = CILEN_BSD_COMPRESS;
opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
go->bsd_compress = 0;
}
if (go->deflate) {
if (go->deflate_correct) {
opt_buf[0] = CI_DEFLATE;
opt_buf[1] = CILEN_DEFLATE;
opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
opt_buf[3] = DEFLATE_CHK_SEQUENCE;
if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
go->deflate_correct = 0;
}
if (go->deflate_draft) {
opt_buf[0] = CI_DEFLATE_DRAFT;
opt_buf[1] = CILEN_DEFLATE;
opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
opt_buf[3] = DEFLATE_CHK_SEQUENCE;
if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
go->deflate_draft = 0;
}
if (!go->deflate_correct && !go->deflate_draft)
go->deflate = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -