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

📄 fsm.c

📁 经典的ppp程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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. */#define RCSID	"$Id: fsm.c,v 1.17 1999/08/13 06:46:12 paulus Exp $"/* * TODO: * Randomize fsm id on link/init. * Deal with variable outgoing MTU. */#include <stdio.h>#include <string.h>#include <sys/types.h>#include "pppd.h"#include "fsm.h"static const char rcsid[] = RCSID;static void fsm_timeout __P((void *));static void fsm_rconfreq __P((fsm *, int, u_char *, int));static void fsm_rconfack __P((fsm *, int, u_char *, int));static void fsm_rconfnakrej __P((fsm *, int, int, u_char *, int));static void fsm_rtermreq __P((fsm *, int, u_char *, int));static void fsm_rtermack __P((fsm *));static void fsm_rcoderej __P((fsm *, u_char *, int));static void fsm_sconfreq __P((fsm *, int));#define PROTO_NAME(f)	((f)->callbacks->proto_name)int peer_mru[NUM_PPP];/* * fsm_init - Initialize fsm. * * Initialize fsm state. */voidfsm_init(f)    fsm *f;{    f->state = INITIAL;    f->flags = 0;    f->id = 0;				/* XXX Start with random id? */    f->timeouttime = DEFTIMEOUT;    f->maxconfreqtransmits = DEFMAXCONFREQS;    f->maxtermtransmits = DEFMAXTERMREQS;    f->maxnakloops = DEFMAXNAKLOOPS;    f->term_reason_len = 0;}/* * fsm_lowerup - The lower layer is up. */voidfsm_lowerup(f)    fsm *f;{    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(("%s: Up event in state %d!", PROTO_NAME(f), f->state));    }}/* * fsm_lowerdown - The lower layer is down. * * Cancel all timeouts and inform upper layers. */voidfsm_lowerdown(f)    fsm *f;{    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(("%s: Down event in state %d!", PROTO_NAME(f), f->state));    }}/* * fsm_open - Link is allowed to come up. */voidfsm_open(f)    fsm *f;{    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;    }}/* * fsm_close - Start closing connection. * * Cancel timeouts and either initiate close or possibly go directly to * the CLOSED state. */voidfsm_close(f, reason)    fsm *f;    char *reason;{    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;    }}/* * fsm_timeout - Timeout expired. */static voidfsm_timeout(arg)    void *arg;{    fsm *f = (fsm *) arg;    switch (f->state) {    case CLOSING:    case STOPPING:	if( f->retransmits <= 0 ){	    /*	     * 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 {	    /* 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) {	    warn("%s: timeout sending Config-Requests\n", PROTO_NAME(f));	    f->state = STOPPED;	    if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )		(*f->callbacks->finished)(f);	} else {	    /* 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(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state));    }}/* * fsm_input - Input packet. */voidfsm_input(f, inpacket, l)    fsm *f;    u_char *inpacket;    int l;{    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 < HEADERLEN) {	FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol));	return;    }    GETCHAR(code, inp);    GETCHAR(id, inp);    GETSHORT(len, inp);    if (len < HEADERLEN) {	FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol));	return;    }    if (len > l) {	FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol));	return;    }    len -= HEADERLEN;		/* subtract header length */    if( f->state == INITIAL || f->state == STARTING ){	FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.",		  f->protocol, f->state));	return;    }    /*     * 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_rconfreq - Receive Configure-Request. */static voidfsm_rconfreq(f, id, inp, len)    fsm *f;    u_char id;    u_char *inp;    int len;{    int code, reject_if_disagree;    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 */

⌨️ 快捷键说明

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