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

📄 ahdlc.c

📁 ppp协议实现源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	    chr ^= PPP_ESCAPE_BIT;	} else if (chr == PPP_FRAME) {      /* End of frame. */	    if (as->sbdpt && as->rx_sbdptr > 0) {		/*		 * If we're handling seven-bit data path transparency, then		 * finish out this decode.		 */		as->rx_sbdptr--;		if (as->rx_sbdptr == 0 ||		    as->rx_octets+as->rx_sbdptr > MAXIMUM_MRU)		    goto notify_error;		as->rx_octets += as->rx_sbdptr;		chr = as->rx_sbdbuf[as->rx_sbdptr] << (7-as->rx_sbdptr);		for (i = 0; i < as->rx_sbdptr; i++) {		    chr <<= 1;		    chr2 = as->rx_sbdbuf[i] | (chr & 0x80);		    as->rx_crc = (as->rx_crc >> 8) ^			fcstab_16[(as->rx_crc ^ chr2) & 0xFF];		    as->rx_crcl = (as->rx_crcl >> 8) ^			fcstab_32[(as->rx_crcl ^ chr2) & 0xFF];		    *as->rx_bufp++ = (char)chr2;		}	    }	    if (as->userrcv != NULL &&		((as->usecrc32 && as->rx_crcl == PPPGOODFCS32) ||		 (!as->usecrc32 && as->rx_crc == PPPGOODFCS16))) {		(*as->userrcv)(as->userstate,as->rx_buffer,			       as->rx_octets - (as->usecrc32 ? 4 : 2));		as->rx_buffer = buffer_fetch(MAXIMUM_MRU);	    } else if (as->rx_octets > 3)		goto notify_error;	    goto reset_buffer;	} else if (chr == PPP_ESCAPE) {	    as->escaped = 1;	    continue;	}	/* Handle seven-bit data path transparency mode. */	if (as->sbdpt) {	    if (as->rx_sbdptr < 7) {		as->rx_sbdbuf[as->rx_sbdptr++] = chr;		continue;	    }	    if (as->rx_octets+7 > MAXIMUM_MRU)		goto notify_error;	    as->rx_octets += 7;	    for (i = 0; i < 7; i++) {		chr <<= 1;		chr2 = as->rx_sbdbuf[i] | (chr & 0x80);		as->rx_crc = (as->rx_crc >> 8) ^		    fcstab_16[(as->rx_crc ^ chr2) & 0xFF];		as->rx_crcl = (as->rx_crcl >> 8) ^		    fcstab_32[(as->rx_crcl ^ chr2) & 0xFF];		*as->rx_bufp++ = (char)chr2;	    }	    as->rx_sbdptr = 0;	    continue;	}	/* If we're here, then we have an input data octet. */	if (as->rx_octets >= MAXIMUM_MRU) {	notify_error:	    /*	     * Notify PPP of receive error here!  Some protocols, like VJ	     * compressed TCP/IP, work much better when receive errors are	     * caught and reported by the driver.	     */	reset_buffer:	    as->rx_bufp = as->rx_buffer;	    as->rx_crc = PPPINITFCS16;	    as->rx_crcl = PPPINITFCS32;	    as->rx_octets = 0;	    as->rx_sbdptr = 0;	} else {	    /*	     * On most systems, it's faster to just calculate both of these	     * than to attempt to conditionally calculate one based on the	     * type of CRC negotiated.	     */	    as->rx_crc = (as->rx_crc >> 8) ^		fcstab_16[(as->rx_crc ^ chr) & 0xFF];	    as->rx_crcl = (as->rx_crcl >> 8) ^		fcstab_32[(as->rx_crcl ^ chr) & 0xFF];	    *as->rx_bufp++ = (char)chr;	    as->rx_octets++;	}    }}/* * This routine will place up to 'maxcount' characters for * transmission on the serial link in the given buffer.  It should be * called by a FIFO-empty interrupt on the serial link.  It returns a * count of the actual number of characters written to the buffer, * which may be less than the maximum given if no more data from PPP * is ready to be sent. * * When PPP places a message on the output queue, it must determine if * the queue was empty when it did this.  If so, then the PPP output * routine should arrange to have the serial driver call this routine * once to get the ball rolling. */intahdlc_transmit(void *statep, char *buffer, int maxcount){    struct ahdlc_state *as = (struct ahdlc_state *)statep;    int omaxcount = maxcount;    octet chr;    while (--maxcount >= 0) {	if (as->escaping) {	    as->escaping = 0;	    *buffer = as->tx_savechr ^ PPP_ESCAPE_BIT;#ifndef TRANSMIT_TO_HARDWARE	    buffer++;#endif	    continue;	}	/* If we need a new buffer to transmit, then go get one from PPP. */	if (as->tx_buffer == NULL) {	    /* If the user is trying to synchronize, then break out here. */	    if (as->outputsync)		break;	    if (as->userxmt != NULL)		(*as->userxmt)(as->userstate,&as->tx_buffer,&as->tx_octets);	    if (as->tx_buffer == NULL || as->tx_octets == 0) {		/* Nothing left in queue; will need PPP frame marker                   next time. */		as->needstart = 1;		break;	    }	    as->tx_bufp = as->tx_buffer;	    as->tx_crc = PPPINITFCS16;	    as->tx_crcl = PPPINITFCS32;	    /* If we need a frame marker at the beginning, then insert               it now. */	    if (as->needstart) {		as->needstart = 0;		*buffer = (char)PPP_FRAME;#ifndef TRANSMIT_TO_HARDWARE		buffer++;#endif		continue;	    }	}	if (as->tx_octets == 0) {	    /* If no more octets of data left, then set up to send the               CRC. */	    if (as->usecrc32) {		as->tx_crcl = ~as->tx_crcl;		as->localfcs[0] = as->tx_crcl & 0xFF;		as->localfcs[1] = (as->tx_crcl >> 8) & 0xFF;		as->localfcs[2] = (as->tx_crcl >> 16) & 0xFF;		as->localfcs[3] = (as->tx_crcl >> 24) & 0xFF;	    } else {		as->tx_crc = ~as->tx_crc;		as->localfcs[0] = as->tx_crc & 0xFF;		as->localfcs[1] = (as->tx_crc >> 8) & 0xFF;		as->tx_octets = -2;	    }	    /*	     * Note that the CRC is sent as though it were data -- we have	     * to escape characters in the CRC also!  Neglecting this is a	     * common AHDLC implementation bug.	     */	    as->tx_bufp = as->localfcs;	} else if (as->tx_octets == -4 &&		   (!as->sbdpt || as->tx_sbdcnt == 0)) {	    /* All out of CRC octets; give back the buffer and end the               frame. */	    /* buffer_release(as->tx_buffer); */	    as->tx_buffer = NULL;	    *buffer = (char)PPP_FRAME;#ifndef TRANSMIT_TO_HARDWARE	    buffer++;#endif	    continue;	}	if (as->sbdpt) {	    if (as->tx_sbdcnt < 7 && as->tx_octets != -4) {		as->tx_sbdcnt++;		as->tx_octets--;		chr = (int)*as->tx_bufp++;		as->tx_crc = (as->tx_crc >> 8) ^		    fcstab_16[(as->tx_crc ^ chr) & 0xFF];		as->tx_crcl = (as->tx_crcl >> 8) ^		    fcstab_32[(as->tx_crcl ^ chr) & 0xFF];		as->tx_sbdval = (as->tx_sbdval<<1) | ((chr&0x80)?1:0);		chr &= 0x7F;	    } else {		as->tx_sbdcnt = 0;		chr = as->tx_sbdval;		as->tx_sbdval = 0;	    }	} else {	    as->tx_octets--;	    chr = 0xFF&(int)*as->tx_bufp++;	    as->tx_crc = (as->tx_crc >> 8) ^		fcstab_16[(as->tx_crc ^ chr) & 0xFF];	    as->tx_crcl = (as->tx_crcl >> 8) ^		fcstab_32[(as->tx_crcl ^ chr) & 0xFF];	}	if (as->tx_accm[chr/8] & (1 << (chr&7))) {	    as->tx_savechr = chr;	    chr = PPP_ESCAPE;	    as->escaping = 1;	}	*buffer = (char)chr;#ifndef TRANSMIT_TO_HARDWARE	buffer++;#endif    }    /*     * This block is only here to support the optional synchronization     * routine below.  It is not necessary for proper operation.  It     * relies on the BSD kernel sleep/wakeup() mechanism to operate.     */    if (as->tx_buffer == NULL && as->outputsync) {	as->needstart = 1;	as->outputsync = 0;	wakeup(as);    }    /* Calculate number of bytes in buffer and return. */    return omaxcount-maxcount-1;}/* * This is an optional routine which achieves synchronization with the * output function.  This can be necessary to change some variables, * such as the ACCM.  It relies on the BSD kernel sleep()/wakeup() * mechanism.  If you are programming at the normal user level, these * functions do not exist. */voidahdlc_sync_wait(void *statep){    struct ahdlc_state *as = (struct ahdlc_state *)statep;    as->outputsync = 1;    while (as->outputsync)	sleep(as,0);}/* * This routine sets the standard PPP receive and transmit ACCM.  It * should be called by LCP.  Again, like the sync routine above, it * assumes a number of BSD kernel functions. */voidahdlc_set_accm(void *statep, uint32 rx_accm, uint32 tx_accm){    struct ahdlc_state *as = (struct ahdlc_state *)statep;    interrupts_off();    ahdlc_sync_wait(statep);    as->rx_accm[0] = rx_accm & 0xFF;    as->rx_accm[1] = (rx_accm >> 8) & 0xFF;    as->rx_accm[2] = (rx_accm >> 16) & 0xFF;    as->rx_accm[3] = (rx_accm >> 24) & 0xFF;    as->tx_accm[0] = tx_accm & 0xFF;    as->tx_accm[1] = (tx_accm >> 8) & 0xFF;    as->tx_accm[2] = (tx_accm >> 16) & 0xFF;    as->tx_accm[3] = (tx_accm >> 24) & 0xFF;    interrupts_on();}/* * This is an example of a wrapper routine to change the CRC mode * flag.  Note that because both CRCs are always calculated, no * synchronization is necessary. */voidahdlc_set_crc_mode(void *statep, int mode){    struct ahdlc_state *as = (struct ahdlc_state *)statep;    as->usecrc32 = mode;}/* * This is in ISO/IEC 3309:1993(E), but is not part of RFC 1662. * Enabling this option will allow operation over seven bit data * paths, but is not compliant with the RFC. */voidahdlc_set_sbdpt(void *statep, int onoff){    struct ahdlc_state *as = (struct ahdlc_state *)statep;    as->sbdpt = onoff;}/* * This is an example routine to report physical-layer * misconfiguration to the user.  You'll probably need to modify this * routine. */voidahdlc_report_on_failure(void *statep){    struct ahdlc_state *as = (struct ahdlc_state *)statep;    if (as->magicvar & MCT_NODATA)	syslog(LOG_ERR,"no data was received from the peer.");    else if (as->magicvar & MCT_ZEROPAR) {	syslog(LOG_ERR,"all bytes received from peer had bit 8 cleared;");	syslog(LOG_ERR,"7 bit data path with no parity suspected.");    } else if (as->magicvar & MCT_ONEPAR) {	syslog(LOG_ERR,"all bytes received from peer had bit 8 set;");	syslog(LOG_ERR,"7 bit data path with mark parity suspected.");    } else if (as->magicvar & MCT_ODDPAR) {	syslog(LOG_ERR,"all bytes received from peer had odd parity;");	syslog(LOG_ERR,"7 bit data path with odd parity suspected.");    } else if (as->magicvar & MCT_EVENPAR) {	syslog(LOG_ERR,"all bytes received from peer had even parity;");	syslog(LOG_ERR,"7 bit data path with even parity suspected.");    } else if (as->magicvar & MCT_NOTCTL) {	syslog(LOG_INFO,"no bytes in 00-1f or 80-9f received;");	syslog(LOG_INFO,"control transparency left enabled");    } else if (as->magicvar & MCT_NOTLOW) {	syslog(LOG_INFO,"no bytes in 00-1f received;");	syslog(LOG_INFO,"control transparency left enabled");    }}

⌨️ 快捷键说明

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