⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcp.c

📁 Unix/Linux NAPT协议解析源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * lcp.c - PPP Link Control 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. */#ifndef lintstatic char rcsid[] = "$Id: lcp.c,v 1.20 1995/06/30 01:47:15 paulus Exp $";#endif/* * TODO: */#include <stdio.h>#include <string.h>#include <syslog.h>#include <assert.h>#include <sys/types.h>#include <sys/time.h>#include "pppd.h"#include "fsm.h"#include "lcp.h"#include "magic.h"#include "chap.h"#include "upap.h"#include "ipcp.h"/* global vars */fsm lcp_fsm[NUM_PPP];			/* LCP fsm structure (global)*/lcp_options lcp_wantoptions[NUM_PPP];	/* Options that we want to request */lcp_options lcp_gotoptions[NUM_PPP];	/* Options that peer ack'd */lcp_options lcp_allowoptions[NUM_PPP];	/* Options we allow peer to request */lcp_options lcp_hisoptions[NUM_PPP];	/* Options that we ack'd */u_int32_t xmit_accm[NUM_PPP][8];		/* extended transmit ACCM */static u_int32_t lcp_echos_pending = 0;	/* Number of outstanding echo msgs */static u_int32_t lcp_echo_number   = 0;	/* ID number of next echo frame */static u_int32_t lcp_echo_timer_running = 0;  /* TRUE if a timer is running */static u_char nak_buffer[PPP_MRU];	/* where we construct a nak packet *//* * Callbacks for fsm code.  (CI = Configuration Information) */static void lcp_resetci __P((fsm *));	/* Reset our CI */static int  lcp_cilen __P((fsm *));		/* Return length of our CI */static void lcp_addci __P((fsm *, u_char *, int *)); /* Add our CI to pkt */static int  lcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */static int  lcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */static int  lcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */static int  lcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv peer CI */static void lcp_up __P((fsm *));		/* We're UP */static void lcp_down __P((fsm *));		/* We're DOWN */static void lcp_starting __P((fsm *));	/* We need lower layer up */static void lcp_finished __P((fsm *));	/* We need lower layer down */static int  lcp_extcode __P((fsm *, int, int, u_char *, int));static void lcp_rprotrej __P((fsm *, u_char *, int));/* * routines to send LCP echos to peer */static void lcp_echo_lowerup __P((int));static void lcp_echo_lowerdown __P((int));static void LcpEchoTimeout __P((caddr_t));static void lcp_received_echo_reply __P((fsm *, int, u_char *, int));static void LcpSendEchoRequest __P((fsm *));static void LcpLinkFailure __P((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_loopbackfail = DEFLOOPBACKFAIL;/* * 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")/* * lcp_init - Initialize LCP. */voidlcp_init(unit)    int unit;{    fsm *f = &lcp_fsm[unit];    lcp_options *wo = &lcp_wantoptions[unit];    lcp_options *ao = &lcp_allowoptions[unit];    f->unit = unit;    f->protocol = PPP_LCP;    f->callbacks = &lcp_callbacks;    fsm_init(f);    wo->passive = 0;    wo->silent = 1; /* Silent by default */    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 */    memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));    xmit_accm[unit][3] = 0x60000000;}/* * lcp_open - LCP is allowed to come up. */voidlcp_open(unit)    int unit;{    fsm *f = &lcp_fsm[unit];    lcp_options *wo = &lcp_wantoptions[unit];    f->flags = 0;    if (wo->passive)	f->flags |= OPT_PASSIVE;    if (wo->silent)	f->flags |= OPT_SILENT;    fsm_open(f);}/* * lcp_close - Take LCP down. */voidlcp_close(unit)    int unit;{    fsm *f = &lcp_fsm[unit];    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(&lcp_fsm[unit]);}/* * lcp_lowerup - The lower layer is up. */voidlcp_lowerup(unit)    int unit;{    sifdown(unit);    ppp_set_xaccm(unit, xmit_accm[unit]);    ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0);    ppp_recv_config(unit, PPP_MRU, 0x00000000, 0, 0);    peer_mru[unit] = PPP_MRU;    lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0];    fsm_lowerup(&lcp_fsm[unit]);}/* * lcp_lowerdown - The lower layer is down. */voidlcp_lowerdown(unit)    int unit;{    fsm_lowerdown(&lcp_fsm[unit]);}/* * lcp_input - Input LCP packet. */voidlcp_input(unit, p, len)    int unit;    u_char *p;    int len;{    int oldstate;    fsm *f = &lcp_fsm[unit];    lcp_options *go = &lcp_gotoptions[f->unit];    oldstate = f->state;    fsm_input(f, p, len);    if (oldstate == REQSENT && f->state == ACKSENT) {	/*	 * The peer will probably send us an ack soon and then	 * immediately start sending packets with the negotiated	 * options.  So as to be ready when that happens, we set	 * our receive side to accept packets as negotiated now.	 */	ppp_recv_config(f->unit, PPP_MRU,			go->neg_asyncmap? go->asyncmap: 0x00000000,			go->neg_pcompression, go->neg_accompression);    }}/* * 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(lcp_gotoptions[f->unit].magicnumber, magp);	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(&lcp_fsm[unit]);}/* * 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(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,	      p, len);}/* * lcp_resetci - Reset our CI. */static void  lcp_resetci(f)fsm *f;{    lcp_wantoptions[f->unit].magicnumber = magic();    lcp_wantoptions[f->unit].numloops = 0;    lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];    peer_mru[f->unit] = PPP_MRU;}/* * lcp_cilen - Return length of our CI. */static intlcp_cilen(f)    fsm *f;{    lcp_options *go = &lcp_gotoptions[f->unit];#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 = &lcp_gotoptions[f->unit];    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(PPP_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, PPP_CHAP, go->chap_mdtype);    ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);    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 */	do_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 = &lcp_gotoptions[f->unit];    u_char cilen, citype, cichar;    u_short cishort;    u_int32_t 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 != opt) \	    goto bad; \	GETSHORT(cishort, p); \	if (cishort != 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 != opt) \	    goto bad; \	GETSHORT(cishort, p); \	if (cishort != val) \	    goto bad; \	GETCHAR(cichar, p); \	if (cichar != 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 != opt) \	    goto bad; \	GETLONG(cilong, p); \	if (cilong != 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 != opt) \	    goto bad; \	GETSHORT(cishort, p); \

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -