📄 ccp.c
字号:
/* * 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. */#define RCSID "$Id: ccp.c,v 1.29 1999/08/13 06:46:11 paulus Exp $"#include <stdlib.h>#include <string.h>#include "pppd.h"#include "fsm.h"#include "ccp.h"#include <net/ppp-comp.h>static const char rcsid[] = RCSID;/* * Command-line options. */static int setbsdcomp __P((char **));static int setdeflate __P((char **));static option_t ccp_option_list[] = { { "noccp", o_bool, &ccp_protent.enabled_flag, "Disable CCP negotiation" }, { "-ccp", o_bool, &ccp_protent.enabled_flag, "Disable CCP negotiation" }, { "bsdcomp", o_special, setbsdcomp, "Request BSD-Compress packet compression" }, { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, "don't allow BSD-Compress", OPT_A2COPY, &ccp_allowoptions[0].bsd_compress }, { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, "don't allow BSD-Compress", OPT_A2COPY, &ccp_allowoptions[0].bsd_compress }, { "deflate", 1, setdeflate, "request Deflate compression" }, { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, "don't allow Deflate compression", OPT_A2COPY, &ccp_allowoptions[0].deflate }, { "-deflate", o_bool, &ccp_wantoptions[0].deflate, "don't allow Deflate compression", OPT_A2COPY, &ccp_allowoptions[0].deflate }, { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, "don't use draft deflate #", OPT_A2COPY, &ccp_allowoptions[0].deflate_draft }, { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1 }, { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, "don't allow Predictor-1", OPT_A2COPY, &ccp_allowoptions[0].predictor_1 }, { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, "don't allow Predictor-1", OPT_A2COPY, &ccp_allowoptions[0].predictor_1 }, { NULL }};/* * 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", "Compressed", ccp_option_list, 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 *//* * Option parsing. */static intsetbsdcomp(argv) char **argv;{ int rbits, abits; char *str, *endp; str = *argv; abits = rbits = strtol(str, &endp, 0); if (endp != str && *endp == ',') { str = endp + 1; abits = strtol(str, &endp, 0); } if (*endp != 0 || endp == str) { option_error("invalid parameter '%s' for bsdcomp option", *argv); return 0; } if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { option_error("bsdcomp option values must be 0 or %d .. %d", BSD_MIN_BITS, BSD_MAX_BITS); return 0; } if (rbits > 0) { ccp_wantoptions[0].bsd_compress = 1; ccp_wantoptions[0].bsd_bits = rbits; } else ccp_wantoptions[0].bsd_compress = 0; if (abits > 0) { ccp_allowoptions[0].bsd_compress = 1; ccp_allowoptions[0].bsd_bits = abits; } else ccp_allowoptions[0].bsd_compress = 0; return 1;}static intsetdeflate(argv) char **argv;{ int rbits, abits; char *str, *endp; str = *argv; abits = rbits = strtol(str, &endp, 0); if (endp != str && *endp == ',') { str = endp + 1; abits = strtol(str, &endp, 0); } if (*endp != 0 || endp == str) { option_error("invalid parameter '%s' for deflate option", *argv); return 0; } if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) || (abits != 0 && (abits < DEFLATE_MIN_SIZE || abits > DEFLATE_MAX_SIZE))) { option_error("deflate option values must be 0 or %d .. %d", DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); return 0; } if (rbits > 0) { ccp_wantoptions[0].deflate = 1; ccp_wantoptions[0].deflate_size = rbits; } else ccp_wantoptions[0].deflate = 0; if (abits > 0) { ccp_allowoptions[0].deflate = 1; ccp_allowoptions[0].deflate_size = abits; } else ccp_allowoptions[0].deflate = 0; return 1;}/* * ccp_init - initialize CCP. */static voidccp_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 voidccp_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 voidccp_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 voidccp_lowerup(unit) int unit;{ fsm_lowerup(&ccp_fsm[unit]);}/* * ccp_lowerdown - we may not transmit CCP packets. */static voidccp_lowerdown(unit) int unit;{ fsm_lowerdown(&ccp_fsm[unit]);}/* * ccp_input - process a received CCP packet. */static voidccp_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) 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 intccp_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 voidccp_protrej(unit) int unit;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -