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

📄 lapb.c

📁 ppp协议实现源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	    buffer_release(buffer);	else {	    ls->rxq[woffs].buffer = buffer;	    ls->rxq[woffs].length = count;	    ls->rhead = nr;	    if (ls->rcvnonempty != NULL &&		woffs == ls->rtail)		(*ls->rcvnonempty)(ls->userstate);	}	return;    } else {	/* Error; bad address. */	buffer_release(buffer);	return;    }    /* Next, extract the command/response code and sequence. */    DBG(("process input on %p\n",ls));    ns = nr = 0;	/* quiet down compiler */    crcode = buffer[1];    ilen = 2;    if (IS_U_TYPE(crcode)) {	pfbit = (crcode & 0x10)>>4;    } else switch (ls->mode) {    case MODE_BASIC:	ns = (crcode & 0x0E)>>1;	pfbit = (crcode & 0x10)>>4;	nr = (crcode & 0xE0)>>5;	break;    case MODE_EXTENDED:	if (count < 3) {	    errbits = 3;	    goto frmr_handler;	}	ns = (crcode & 0xFE)>>1;	pfbit = buffer[2] & 1;	nr = (buffer[2] & 0xFE)>>1;	ilen = 3;	break;    case MODE_SUPER:	if (count < 5) {	    errbits = 3;	    goto frmr_handler;	}	ns = ((crcode & 0xFE)>>1) | (buffer[2]<<7);	pfbit = buffer[3] & 1;	nr = ((buffer[3] & 0xFE)>>1) | (buffer[4]<<7);	ilen = 5;	break;    default:	/* This can't happen. */	buffer_release(buffer);	return;    }    if (IS_I_TYPE(crcode))	crcode &= ITYPE_MASK;    else if (IS_S_TYPE(crcode))	crcode &= STYPE_MASK;     else	crcode &= UTYPE_MASK;    /* Switch out on type of received frame. */    DBG(("code %d, nr %d, ns %d\n",crcode,nr,ns));    errbits = 0;    switch (crcode) {    case CRI_I:	DBG(("received I frame\n"));	/* Still setting up; silent discard. */	if (ls->phase == phInitial)	    break;	if (!iscmd) {	    errbits = 1;	    break;	}	handle_nr(ls,nr);	/*	 * Note:  LAP-B assumes that packets cannot be reordered on the	 * link.  For that reason, it is safe to assume that a sequence	 * number error implies a lost packet.	 */	if (INWINDOW(ns,ls->vr,ls->rxqsize,ls->rxkval)) {	    DBG(("inside window; vr is %d\n",ls->vr));	    /* Get non-negative window offset. */	    woffs = (ls->rtail+ns-ls->vr+ls->rxkval+1) % (ls->rxkval+1);	    if (ls->rxq[woffs].buffer != NULL) {		/* Discard duplicate buffer. */		DBG(("duplicate buffer; discarding.\n"));		break;	    }	    ls->rxq[woffs].buffer = buffer+ilen;	    ls->rxq[woffs].length = count-ilen;	    /* Check for sequence number error. */	    if (woffs != ls->rhead) {		DBG(("queue offset %d not equal to head %d; need reject.\n",		     woffs,ls->rhead));		need_transmit(ls,STF_NEEDREJ);	    }	    if (++woffs > ls->rxkval)		woffs = 0;	    if (ls->rhead >= ls->rtail) {		if (woffs > ls->rhead || woffs < ls->rtail)		    ls->rhead = woffs;	    } else {		if (woffs > ls->rhead && woffs < ls->rtail)		    ls->rhead = woffs;	    }	    /* While in sequence, send data to application */	    if (ls->rcvnonempty != NULL &&		ls->rxq[ls->rtail].buffer != NULL)		(*ls->rcvnonempty)(ls->userstate);	    /* Don't free queued packets. */	    buffer = NULL;	} else {	    DBG(("outside window; vr is %d\n",ls->vr));	}	if (pfbit) {	    need_transmit(ls,STF_NEEDSTATUS | STF_PFBIT);	}	break;    case CRS_RR:    case CRS_RNR:	if (crcode == CRS_RR)	    DBG(("received RR frame\n"));	else	    DBG(("received RNR frame\n"));	/* Still setting up; silent discard. */	if (ls->phase == phInitial)	    break;	if (count != ilen) {	    errbits = 3;	    break;	}	if (crcode == CRS_RR)	    ls->flags |= LBF_PEERREADY;	else	    ls->flags &= ~LBF_PEERREADY;	handle_nr(ls,nr);	if (iscmd && pfbit) {	    need_transmit(ls,STF_NEEDSTATUS | STF_PFBIT);	}	break;    case CRS_REJ:	DBG(("received REJ frame\n"));	/* Still setting up; silent discard. */	if (ls->phase == phInitial)	    break;	if (ls->mode == MODE_EXTENDED || (ls->flags & LBF_RXSREJ)) {	    errbits = 1;	    break;	}	if (count != ilen) {	    errbits = 3;	    break;	}	ls->flags |= LBF_PEERREADY;	handle_nr(ls,nr);	if (iscmd && pfbit)	    need_transmit(ls,STF_NEEDSTATUS | STF_PFBIT);	/* Drop back to sequence N(R) and try again on all. */	DBG(("reject marking retransmit %d to %d\n",nr,ls->vs));	mark_retransmit(ls,nr,ls->vs);	break;    case CRS_SREJ:	DBG(("received SREJ frame\n"));	/* Still setting up; silent discard. */	if (ls->phase == phInitial)	    break;	if (ls->mode == MODE_BASIC || iscmd || !(ls->flags & LBF_RXSREJ)) {	    errbits = 1;	    break;	}	if (pfbit)	    handle_nr(ls,nr);	/* Drop back to sequence N(R) and try again on some. */	mark_retransmit(ls,nr,nr);	bp = buffer+ilen;	count -= ilen;	while (count > 0) {	    nr = *bp++;	    count--;	    if (ls->mode == MODE_SUPER) {		if (--count < 0)		    break;		nr |= *bp++ << 8;	    }	    if ((nr & 1) && count > 0) {		woffs = *bp++;		if (ls->mode == MODE_SUPER) {		    if (--count < 0)	/* XXX */			break;		    woffs |= *bp++ << 8;		}		mark_retransmit(ls,nr>>1,woffs>>1);	    } else {		nr >>= 1;		mark_retransmit(ls,nr,nr);	    }	}	break;    case CRU_SABM:	DBG(("received SABM frame\n"));	if (ls->flags & LBF_PERMISSIVE)	    ls->mode = MODE_BASIC;	if (ls->mode != MODE_BASIC || !iscmd) {	    errbits = 1;	    break;	}	if (count != 2) {	    errbits = 3;	    break;	}    enter_data_phase:	DBG(("received entering data phase\n"));	if (ls->statflag & STF_T1RUNNING) {	    ls->t2ctr = 0;	    ls->statflag &= ~STF_T1RUNNING;	    untimeout(t1handler,(void *)ls);	}	ls->flags |= LBF_PEERREADY;	ls->vr = ls->vs = 0;	free_all_packets(ls);	ls->phase = phData;	ls->statflag &= ~STF_UAFBIT;	need_transmit(ls,STF_NEEDUA | (pfbit ? STF_UAFBIT : 0));	if (ls->xmthasroom != NULL)	    (*ls->xmthasroom)(ls->userstate);	break;    case CRU_SABME:	DBG(("received SABME frame\n"));	if (ls->flags & LBF_PERMISSIVE)	    ls->mode = MODE_EXTENDED;	if (ls->mode != MODE_EXTENDED || !iscmd) {	    errbits = 1;	    break;	}	if (count != 2) {	    errbits = 3;	    break;	}	goto enter_data_phase;    case CRU_SM:	DBG(("received SM frame\n"));	if (ls->flags & LBF_PERMISSIVE)	    ls->mode = MODE_SUPER;	ilen = (count > 6) ? 6 : count;	/* FRMR generation */	if (ls->mode != MODE_SUPER || !iscmd) {	    errbits = 1;	    break;	}	/* Should have one address byte and 5 Set Mode bytes */	if (count != 6 || buffer[2] != 0 || buffer[3] != 0x40 ||	    buffer[4] != 0x80 || buffer[5] != 0x20) {	    errbits = 3;	    break;	}	goto enter_data_phase;    case CRU_DISC:	DBG(("received DISC frame\n"));	if (!iscmd) {	    errbits = 1;	    break;	}	if (count != 2) {	    errbits = 3;	    break;	}	ls->phase = phDisconnected;	ls->statflag &= ~STF_UAFBIT;	need_transmit(ls,STF_NEEDUA | (pfbit ? STF_UAFBIT : 0));	break;    case CRU_DM:	DBG(("received DM frame\n"));	if (iscmd) {	    errbits = 1;	    break;	}	if (count != 2) {	    errbits = 3;	    break;	}	if (ls->phase != phInitial)	    ls->phase = phDisconnected;	break;    case CRU_UA:	DBG(("received UA frame\n"));	if (iscmd) {	    errbits = 1;	    break;	}	if (count != 2) {	    errbits = 3;	    break;	}	if (ls->phase == phDisconnecting)	    ls->phase = phDisconnected;	ls->flags |= LBF_PEERREADY;	break;    case CRU_FRMR:	DBG(("received FRMR frame\n"));	/* Still setting up; silent discard. */	if (ls->phase == phInitial)	    break;	if (iscmd) {	    /* Rejecting a rejection seems like a bad idea. */	    /* errbits = 1; */	    break;	}	break;    default:	DBG(("received bad frame\n"));	/* Error; bad code. */	errbits = 1;	break;    }frmr_handler:    if (errbits && !(ls->txpend.qflags & QF_SENDING)) {	/*	 * We don't assume here that the input buffer is big	 * enough to hold this error frame.  It probably is	 * (and certainly is with the example AHDLC code),	 * but better safe than sorry.	 */	DBG(("Generating FRMR in response\n"));	bp = (octet *)buffer_fetch(11);	if (bp != NULL) {	    bp[0] = ls->cmdaddr ^ ls->crabit;	    bp[1] = CRU_FRMR;	    bp[3] = bp[4] = bp[5] = 0;	    memcpy(bp+2,buffer+1,ilen-1);	    switch (ls->mode) {	    case MODE_BASIC:		bp[3] = (ls->vs<<1) | (iscmd?0:0x10) | (ls->vr<<5);		bp[4] = errbits;		ilen = 5;		break;	    case MODE_EXTENDED:		bp[4] = ls->vs<<1;		bp[5] = (iscmd?0:1) | (ls->vr<<1);		bp[6] = errbits;		ilen = 7;		break;	    case MODE_SUPER:		bp[6] = ls->vs<<1;		bp[7] = ls->vs>>7;		bp[8] = (iscmd?0:1) | (ls->vr<<1);		bp[9] = ls->vr>>1;		bp[10] = errbits;		ilen = 11;		break;	    }	    ls->txpend.qflags = QF_SEND;	    ls->txpend.length = ilen;	    if (ls->txpend.buffer != NULL)		buffer_release(ls->txpend.buffer);	    ls->txpend.buffer = bp;	}    }    if (buffer != NULL)	buffer_release(buffer);}/* * This creates a SABM, SABME, or SM message as appropriate for the * configured mode. */static octet *make_set_mode(struct lapb_state *ls, int *lengthp){    octet *bp,ctl;    int len;    len = 0;    bp = (octet *)buffer_fetch(6);    if (bp != NULL) {	bp[0] = ls->cmdaddr;	/* 2.4.4.1 -- DTE sets P bit in set-mode command */	ctl = (ls->flags & LBF_ISDTE) ? 0x10 : 0;	switch (ls->mode) {	case MODE_BASIC:	    bp[1] = CRU_SABM | ctl;	    len = 2;	    break;	case MODE_EXTENDED:	    bp[1] = CRU_SABME | ctl;	    len = 2;	    break;	case MODE_SUPER:	    bp[1] = CRU_SM | ctl;	    bp[2] = 0;	    bp[3] = 0x40;	    bp[4] = 0x80;	    bp[5] = 0x20;	    len = 6;	    break;	default:	    /* This can't happen. */	    buffer_release(bp);	    bp = NULL;	}    }    *lengthp = len;    return bp;}/* * This creates a Receive Ready or Receive Not Ready message as * appropriate for the current state and mode. */static octet *make_status(struct lapb_state *ls, int *lengthp){    octet *bp,ctl;    int len;    if ((bp = (octet *)buffer_fetch(5)) == NULL)	return NULL;    bp[0] = ls->cmdaddr ^ (0 ? 0 : ls->crabit);    ctl = ALLSET(ls->flags,LBF_IMREADY|LBF_USERREADY) ? CRS_RR : CRS_RNR;    switch (ls->mode) {    case MODE_BASIC:	bp[1] = ctl | (ls->statflag & STF_PFBIT ? 0x10 : 0) | (ls->vr<<5);	len = 2;	break;    case MODE_EXTENDED:	bp[1] = ctl;	bp[2] = (ls->statflag & STF_PFBIT ? 1 : 0) | (ls->vr<<1);	len = 3;	break;    case MODE_SUPER:	bp[1] = ctl;	bp[2] = 0;	bp[3] = (ls->statflag & STF_PFBIT ? 1 : 0) | (ls->vr<<1);	bp[4] = ls->vr>>7;	len = 5;	break;    default:	/* This can't happen. */	buffer_release(bp);	return NULL;    }    *lengthp = len;    return bp;}/* * Generate an unnumbered acknowledgement response.  This is used as a * reply to a received SABM/SABME/SM frame. */static octet *make_ua(struct lapb_state *ls, int *lengthp){    octet *bp;    if ((bp = (octet *)buffer_fetch(2)) == NULL)	return NULL;    bp[0] = ls->cmdaddr ^ ls->crabit;    bp[1] = CRU_UA | ((ls->statflag & STF_UAFBIT) ? 0x10 : 0);    *lengthp = 2;    return bp;}/* * Generate a disconnect mode response. */static octet *make_dm(struct lapb_state *ls, int *lengthp){    octet *bp;    if ((bp = (octet *)buffer_fetch(2)) == NULL)	return NULL;    bp[0] = ls->cmdaddr ^ ls->crabit;    bp[1] = CRU_DM;    *lengthp = 2;    return bp;}/* * Generate a disconnect command. */static octet *make_disc(struct lapb_state *ls, int *lengthp){    octet *bp;    if ((bp = (octet *)buffer_fetch(2)) == NULL)	return NULL;    bp[0] = ls->cmdaddr;    bp[1] = CRU_DISC | 0x10;    *lengthp = 2;    return bp;}/* * Make a reject or selective reject command frame as appropriate. */

⌨️ 快捷键说明

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