📄 lcp.c
字号:
/* lcp.c - PPP Link Control Protocol *//* Copyright 1995 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * 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. *//*modification history--------------------01d,14apr97,vin lcp state machine fixes from ppp-2.3b3, corrected the problem of lcp_reqci generating CONFREJ instead of CONFNAKs.01e,10dec96,vin fixed additional problem with lcp_finished(), SPR7604.01d,15nov96,vin fixed lcp_finished(), calls fsm_open() if OPT_RESTART is specified. This will cause the ppp deamon task to wait for the next connection. This is typically useful when vxWorks target is acting as a ppp server. Added flag OPT_RESTART if passive or silent options are specified.01c,16jun95,dzb header file consolidation. changed [UN]TIMEOUT macros to PPP_[UN]TIMEOUT.01b,09feb95,dab ensure ao->mru is not 0 when setting interface mtu. removed lcp_echo_fails_reached variable.01a,21dec94,dab VxWorks port - first WRS version. +dzb added: path for ppp header files, WRS copyright.*/#include "vxWorks.h"#include "stdio.h"#include "string.h"#include "sys/ioctl.h"#include "sys/types.h"#include "sys/socket.h"#include "sys/times.h"#include "netinet/in.h"#include "pppLib.h"/* * Callbacks for fsm code. (CI = Configuration Information) */static void lcp_resetci __ARGS((fsm *)); /* Reset our CI */static int lcp_cilen __ARGS((fsm *)); /* Return length of our CI */static void lcp_addci __ARGS((fsm *, u_char *, int *)); /* Add our CI to pkt */static int lcp_ackci __ARGS((fsm *, u_char *, int)); /* Peer ack'd our CI */static int lcp_nakci __ARGS((fsm *, u_char *, int)); /* Peer nak'd our CI */static int lcp_rejci __ARGS((fsm *, u_char *, int)); /* Peer rej'd our CI */static int lcp_reqci __ARGS((fsm *, u_char *, int *, int)); /* Rcv peer CI */static void lcp_up __ARGS((fsm *)); /* We're UP */static void lcp_down __ARGS((fsm *)); /* We're DOWN */static void lcp_starting __ARGS((fsm *)); /* We need lower layer up */static void lcp_finished __ARGS((fsm *)); /* We need lower layer down */static int lcp_extcode __ARGS((fsm *, int, int, u_char *, int));static void lcp_rprotrej __ARGS((fsm *, u_char *, int));/* * routines to send LCP echos to peer */static void lcp_echo_lowerup __ARGS((int));static void lcp_echo_lowerdown __ARGS((int));static void LcpEchoTimeout __ARGS((caddr_t));static void lcp_received_echo_reply __ARGS((fsm *, int, u_char *, int));static void LcpSendEchoRequest __ARGS((fsm *));static void LcpLinkFailure __ARGS((fsm *));static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ lcp_resetci, /* Reset our Configuration Information */ lcp_cilen, /* Length of our Configuration Information */ lcp_addci, /* Add our Configuration Information */ lcp_ackci, /* ACK our Configuration Information */ lcp_nakci, /* NAK our Configuration Information */ lcp_rejci, /* Reject our Configuration Information */ lcp_reqci, /* Request peer's Configuration Information */ lcp_up, /* Called when fsm reaches OPENED state */ lcp_down, /* Called when fsm leaves OPENED state */ lcp_starting, /* Called when we want the lower layer up */ lcp_finished, /* Called when we want the lower layer down */ NULL, /* Called when Protocol-Reject received */ NULL, /* Retransmission is necessary */ lcp_extcode, /* Called to handle LCP-specific codes */ "LCP" /* String name of protocol */};int lcp_warnloops = DEFWARNLOOPS; /* Warn about a loopback this often *//* * Length of each type of configuration option (in octets) */#define CILEN_VOID 2#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ (x) == CONFNAK ? "NAK" : "REJ")static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet *//* * lcp_init - Initialize LCP. */voidlcp_init(unit) int unit;{ fsm *f = &ppp_if[unit]->lcp_fsm; lcp_options *wo = &ppp_if[unit]->lcp_wantoptions; lcp_options *ao = &ppp_if[unit]->lcp_allowoptions; f->unit = unit; f->protocol = LCP; f->callbacks = &lcp_callbacks; fsm_init(f); wo->passive = 0; wo->silent = 0; wo->restart = 0; /* Set to 1 in kernels or multi-line implementations */ wo->neg_mru = 1; wo->mru = DEFMRU; wo->neg_asyncmap = 0; wo->asyncmap = 0; wo->neg_chap = 0; /* Set to 1 on server */ wo->neg_upap = 0; /* Set to 1 on server */ wo->chap_mdtype = CHAP_DIGEST_MD5; wo->neg_magicnumber = 1; wo->neg_pcompression = 1; wo->neg_accompression = 1; wo->neg_lqr = 0; /* no LQR implementation yet */ ao->neg_mru = 1; ao->mru = MAXMRU; ao->neg_asyncmap = 1; ao->asyncmap = 0; ao->neg_chap = 1; ao->chap_mdtype = CHAP_DIGEST_MD5; ao->neg_upap = 1; ao->neg_magicnumber = 1; ao->neg_pcompression = 1; ao->neg_accompression = 1; ao->neg_lqr = 0; /* no LQR implementation yet */ bzero((char *)ppp_if[unit]->xmit_accm, sizeof(ppp_if[unit]->xmit_accm[0])); ppp_if[unit]->xmit_accm[3] = 0x60000000;}/* * lcp_open - LCP is allowed to come up. */voidlcp_open(unit) int unit;{ fsm *f = &ppp_if[unit]->lcp_fsm; lcp_options *wo = &ppp_if[unit]->lcp_wantoptions; f->flags = 0; if (wo->passive) f->flags |= (OPT_PASSIVE | OPT_RESTART) ; if (wo->silent) f->flags |= (OPT_SILENT | OPT_RESTART); fsm_open(f);}/* * lcp_close - Take LCP down. */voidlcp_close(unit) int unit;{ fsm *f = &ppp_if[unit]->lcp_fsm; if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { /* * This action is not strictly according to the FSM in RFC1548, * but it does mean that the program terminates if you do a * lcp_close(0) in passive/silent mode when a connection hasn't * been established. */ f->state = CLOSED; lcp_finished(f); } else fsm_close(&ppp_if[unit]->lcp_fsm);}/* * lcp_lowerup - The lower layer is up. */voidlcp_lowerup(unit) int unit;{ sifdown(unit); ppp_set_xaccm(unit, ppp_if[unit]->xmit_accm); ppp_send_config(unit, MTU, 0xffffffff, 0, 0); ppp_recv_config(unit, MTU, 0x00000000, 0, 0); ppp_if[unit]->peer_mru = MTU; ppp_if[unit]->lcp_allowoptions.asyncmap = ppp_if[unit]->xmit_accm[0]; fsm_lowerup(&ppp_if[unit]->lcp_fsm);}/* * lcp_lowerdown - The lower layer is down. */voidlcp_lowerdown(unit) int unit;{ fsm_lowerdown(&ppp_if[unit]->lcp_fsm);}/* * lcp_input - Input LCP packet. */voidlcp_input(unit, p, len) int unit; u_char *p; int len;{ fsm_input(&ppp_if[unit]->lcp_fsm, p, len);}/* * lcp_extcode - Handle a LCP-specific code. */static intlcp_extcode(f, code, id, inp, len) fsm *f; int code, id; u_char *inp; int len;{ u_char *magp; switch( code ){ case PROTREJ: lcp_rprotrej(f, inp, len); break; case ECHOREQ: if (f->state != OPENED) break; LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d", id)); magp = inp; PUTLONG(ppp_if[f->unit]->lcp_gotoptions.magicnumber, magp); if (len < CILEN_LONG) len = CILEN_LONG; fsm_sdata(f, ECHOREP, id, inp, len); break; case ECHOREP: lcp_received_echo_reply(f, id, inp, len); break; case DISCREQ: break; default: return 0; } return 1;} /* * lcp_rprotrej - Receive an Protocol-Reject. * * Figure out which protocol is rejected and inform it. */static voidlcp_rprotrej(f, inp, len) fsm *f; u_char *inp; int len;{ u_short prot; LCPDEBUG((LOG_INFO, "lcp_rprotrej.")); if (len < sizeof (u_short)) { LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd short Protocol-Reject packet!")); return; } GETSHORT(prot, inp); LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!", prot)); /* * Protocol-Reject packets received in any state other than the LCP * OPENED state SHOULD be silently discarded. */ if( f->state != OPENED ){ LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d", f->state)); return; } DEMUXPROTREJ(f->unit, prot); /* Inform protocol */}/* * lcp_protrej - A Protocol-Reject was received. *//*ARGSUSED*/voidlcp_protrej(unit) int unit;{ /* * Can't reject LCP! */ LCPDEBUG((LOG_WARNING, "lcp_protrej: Received Protocol-Reject for LCP!")); fsm_protreject(&ppp_if[unit]->lcp_fsm);}/* * lcp_sprotrej - Send a Protocol-Reject for some protocol. */voidlcp_sprotrej(unit, p, len) int unit; u_char *p; int len;{ /* * Send back the protocol and the information field of the * rejected packet. We only get here if LCP is in the OPENED state. */ p += 2; len -= 2; fsm_sdata(&ppp_if[unit]->lcp_fsm, PROTREJ, ++ppp_if[unit]->lcp_fsm.id, p, len);}/* * lcp_resetci - Reset our CI. */static void lcp_resetci(f)fsm *f;{ ppp_if[f->unit]->lcp_wantoptions.magicnumber = magic(); ppp_if[f->unit]->lcp_wantoptions.numloops = 0; ppp_if[f->unit]->lcp_gotoptions = ppp_if[f->unit]->lcp_wantoptions; ppp_if[f->unit]->peer_mru = MTU;}/* * lcp_cilen - Return length of our CI. */static intlcp_cilen(f) fsm *f;{ lcp_options *go = &ppp_if[f->unit]->lcp_gotoptions;#define LENCIVOID(neg) (neg ? CILEN_VOID : 0)#define LENCICHAP(neg) (neg ? CILEN_CHAP : 0)#define LENCISHORT(neg) (neg ? CILEN_SHORT : 0)#define LENCILONG(neg) (neg ? CILEN_LONG : 0)#define LENCILQR(neg) (neg ? CILEN_LQR: 0) /* * NB: we only ask for one of CHAP and UPAP, even if we will * accept either. */ return (LENCISHORT(go->neg_mru) + LENCILONG(go->neg_asyncmap) + LENCICHAP(go->neg_chap) + LENCISHORT(!go->neg_chap && go->neg_upap) + LENCILQR(go->neg_lqr) + LENCILONG(go->neg_magicnumber) + LENCIVOID(go->neg_pcompression) + LENCIVOID(go->neg_accompression));}/* * lcp_addci - Add our desired CIs to a packet. */static voidlcp_addci(f, ucp, lenp) fsm *f; u_char *ucp; int *lenp;{ lcp_options *go = &ppp_if[f->unit]->lcp_gotoptions; u_char *start_ucp = ucp;#define ADDCIVOID(opt, neg) \ if (neg) { \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_VOID, ucp); \ }#define ADDCISHORT(opt, neg, val) \ if (neg) { \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_SHORT, ucp); \ PUTSHORT(val, ucp); \ }#define ADDCICHAP(opt, neg, val, digest) \ if (neg) { \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_CHAP, ucp); \ PUTSHORT(val, ucp); \ PUTCHAR(digest, ucp); \ }#define ADDCILONG(opt, neg, val) \ if (neg) { \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_LONG, ucp); \ PUTLONG(val, ucp); \ }#define ADDCILQR(opt, neg, val) \ if (neg) { \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_LQR, ucp); \ PUTSHORT(LQR, ucp); \ PUTLONG(val, ucp); \ } ADDCISHORT(CI_MRU, go->neg_mru, go->mru); ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap); ADDCICHAP(CI_AUTHTYPE, go->neg_chap, CHAP, go->chap_mdtype); ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, UPAP); ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); if (ucp - start_ucp != *lenp) { /* this should never happen, because peer_mtu should be 1500 */ syslog(LOG_ERR, "Bug in lcp_addci: wrong length"); }}/* * lcp_ackci - Ack our CIs. * This should not modify any state if the Ack is bad. * * Returns: * 0 - Ack was bad. * 1 - Ack was good. */static intlcp_ackci(f, p, len) fsm *f; u_char *p; int len;{ lcp_options *go = &ppp_if[f->unit]->lcp_gotoptions; u_char cilen, citype, cichar; u_short cishort; u_long cilong; /* * CIs must be in exactly the same order that we sent. * Check packet length and CI length at each step. * If we find any deviations, then this packet is bad. */#define ACKCIVOID(opt, neg) \ if (neg) { \ if ((len -= CILEN_VOID) < 0) \ goto bad; \ GETCHAR(citype, p); \ GETCHAR(cilen, p); \ if (cilen != CILEN_VOID || \ citype != opt) \ goto bad; \ }#define ACKCISHORT(opt, neg, val) \ if (neg) { \ if ((len -= CILEN_SHORT) < 0) \ goto bad; \ GETCHAR(citype, p); \ GETCHAR(cilen, p); \ if (cilen != CILEN_SHORT || \ citype != (u_char)opt) \ goto bad; \ GETSHORT(cishort, p); \ if (cishort != (u_short)val) \ goto bad; \ }#define ACKCICHAP(opt, neg, val, digest) \ if (neg) { \ if ((len -= CILEN_CHAP) < 0) \ goto bad; \ GETCHAR(citype, p); \ GETCHAR(cilen, p); \ if (cilen != CILEN_CHAP || \ citype != (u_char)opt) \ goto bad; \ GETSHORT(cishort, p); \ if (cishort != (u_short)val) \ goto bad; \ GETCHAR(cichar, p); \ if (cichar != (u_char)digest) \ goto bad; \ }#define ACKCILONG(opt, neg, val) \ if (neg) { \ if ((len -= CILEN_LONG) < 0) \ goto bad; \ GETCHAR(citype, p); \ GETCHAR(cilen, p); \ if (cilen != CILEN_LONG || \ citype != (u_char)opt) \ goto bad; \ GETLONG(cilong, p); \ if (cilong != (u_long)val) \ goto bad; \ }#define ACKCILQR(opt, neg, val) \ if (neg) { \ if ((len -= CILEN_LQR) < 0) \ goto bad; \ GETCHAR(citype, p); \ GETCHAR(cilen, p); \ if (cilen != CILEN_LQR || \ citype != (u_char)opt) \ goto bad; \ GETSHORT(cishort, p); \ if (cishort != LQR) \ goto bad; \ GETLONG(cilong, p); \ if (cilong != (u_long)val) \ goto bad; \ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -