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

📄 netppp.c

📁 ucos操作系统下TCPIP实现代码
💻 C
📖 第 1 页 / 共 3 页
字号:
}

/* Close a PPP connection and release the descriptor. 
 * Any outstanding packets in the queues are dropped.
 * Return 0 on success, an error code on failure. */
int pppClose(int pd)
{
	PPPControl *pc = &pppControl[pd];
	int st = 0;

	/* Disconnect */
	pc->kill_link = !0;
	pc->traceOffset = 0;
	
	while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
		msleep(500);
		if (buttonStatus() == YESNOBUTTON)
			st = PPPERR_USER;
	}

	/* Reset fd line discipline.  In our case, the framing character. */
	if (ioctl(pc->fd, SETFRAME, &pppControl[pd].oldFrame) < 0)
		st = PPPERR_DEVICE;
		
	pc->openFlag = 0;
	
	return st;
}

/* Send a packet on the given connection.
 * Return 0 on success, an error code on failure. */
#pragma argsused
int pppOutput(int pd, u_short protocol, NBuf *nb)
{
	PPPControl *pc = &pppControl[pd];
	u_int fcsOut = PPP_INITFCS;
	NBuf *headMB = NULL, *tailMB = NULL, *tnb;
	int st = 0;
	u_char c = 0;
	int n;
	u_char *sPtr;

	/* Grab an output buffer. */
	nGET(headMB);
	if (headMB == NULL) {
		st = PPPERR_ALLOC;
		PPPDEBUG((LOG_WARNING, TL_PPP, "pppOutput[%d]: first alloc fail", pd));
#if STATS_SUPPORT > 0
		pppStats.PPPoerrors++;
#endif
	
	/* Validate parameters. */
	/* We let any protocol value go through - it can't hurt us
	 * and the peer will just drop it if it's not accepting it. */
	} else if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !nb) {
		st = PPPERR_PARAM;
		PPPDEBUG((LOG_WARNING, TL_PPP, "pppOutput[%d]: bad parms prot=%d nb=%P",
					pd, protocol, nb));
#if STATS_SUPPORT > 0
		pppStats.PPPoerrors++;
#endif
		
	/* Check that the link is up. */
	} else if (lcp_phase[pd] == PHASE_DEAD) {
		PPPDEBUG((LOG_ERR, TL_PPP, "pppOutput[%d]: link not up", pd));
#if STATS_SUPPORT > 0
		pppStats.PPPderrors++;
#endif
		st = PPPERR_OPEN;
		
	} else {
#if VJ_SUPPORT > 0
		/* 
		 * Attempt Van Jacobson header compression if VJ is configured and
		 * this is an IP packet. 
		 */
		if (protocol == PPP_IP && pc->vjEnabled) {
			switch (vj_compress_tcp(&pc->vjComp, nb)) {
			case TYPE_IP:
				/* No change...
				protocol = PPP_IP_PROTOCOL;
				 */
				break;
			case TYPE_COMPRESSED_TCP:
				protocol = PPP_VJC_COMP;
				break;
			case TYPE_UNCOMPRESSED_TCP:
				protocol = PPP_VJC_UNCOMP;
				break;
			default:
				PPPDEBUG((LOG_WARNING, TL_PPP, "pppOutput[%d]: bad IP packet", pd));
#if STATS_SUPPORT > 0
				pppStats.PPPderrors++;
#endif
				return PPPERR_PROTOCOL;
			}
		}
#endif
		
		headMB->len = 0;
		tailMB = headMB;
			
		/* Build the PPP header. */
		if (diffTime(pc->lastXMit) <= MAXIDLEFLAG)
			tailMB = pppMPutRaw(PPP_FLAG, tailMB);
		if (!pc->accomp) {
			fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
			tailMB = pppMPutC(PPP_ALLSTATIONS, &pc->outACCM, tailMB);
			fcsOut = PPP_FCS(fcsOut, PPP_UI);
			tailMB = pppMPutC(PPP_UI, &pc->outACCM, tailMB);
		}
		if (!pc->pcomp || protocol > 0xFF) {
			c = (protocol >> 8) & 0xFF;
			fcsOut = PPP_FCS(fcsOut, c);
			tailMB = pppMPutC(c, &pc->outACCM, tailMB);
		}
		c = protocol & 0xFF;
		fcsOut = PPP_FCS(fcsOut, c);
		tailMB = pppMPutC(c, &pc->outACCM, tailMB);
		
		/* Load packet. */
		while (nb) {
			sPtr = nBUFTOPTR(nb, u_char *);
			n = nb->len;
			while (n-- > 0) {
				c = *sPtr++;
				
				/* Update FCS before checking for special characters. */
				fcsOut = PPP_FCS(fcsOut, c);
				
				/* Copy to output buffer escaping special characters. */
				tailMB = pppMPutC(c, &pc->outACCM, tailMB);
			}
			nFREE(nb, tnb);
			nb = tnb;
		}
			
		/* Add FCS and trailing flag. */
		c = ~fcsOut & 0xFF;
		tailMB = pppMPutC(c, &pc->outACCM, tailMB);
		c = (~fcsOut >> 8) & 0xFF;
		tailMB = pppMPutC(c, &pc->outACCM, tailMB);
		tailMB = pppMPutRaw(PPP_FLAG, tailMB);
			
		/* If we failed to complete the packet, throw it away.
		 * Otherwise send it. */
		if (!tailMB) {
			st = PPPERR_ALLOC;
			PPPDEBUG((pppControl[pd].traceOffset + LOG_WARNING, TL_PPP,
						"pppOutput[%d]: Alloc err - dropping proto=%d", 
						pd, protocol));
			nFreeChain(headMB);
#if STATS_SUPPORT > 0
			pppStats.PPPoerrors++;
#endif
		}
		else {
			PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
						"pppOutput[%d]: proto=x%X %d:%.*H", 
						pd, protocol,
						headMB->chainLen, MIN(headMB->len * 2, 50), headMB->data));
			nPut(pc->fd, headMB);
#if STATS_SUPPORT > 0
			pppStats.PPPopackets++;
#endif
		}
		headMB = NULL;
	}
	/* If we didn't consume the source buffer, drop it. */
	if (nb)
		nFreeChain(nb);
	/* If we didn't send the output buffer, drop it. */
	if (headMB) {
		nFreeChain(headMB);
#if STATS_SUPPORT > 0
		pppStats.PPPoerrors++;
#endif
	}
		
	return st;
}

/* Process an nBuf chain received on given connection.
 * The nBuf chain is always passed on or freed making the original
 * nBuf pointer invalid.  Note that this does not check for packet
 * chains.  This does not require complete packets but if a packet
 * spans calls, those calls must be in the correct order.  This is
 * designed to handle packets received from the serial interface
 * but could be used for a loopback interface.
 * Return 0 on success, an error code on failure.
 */
int pppInput(int pd, NBuf *nb)
{
	NBuf *nextNBuf;

	while (nb != NULL) {
		/* Consume the buffer.  Ideally we could just work on the
		 * recieved buffer but unless we get the serial driver to
		 * preprocess the escape sequences, it's easier to just
		 * work from one buffer to another. */
		pppInProc(pd, nb->data, nb->len);
		nFREE(nb, nextNBuf);
		nb = nextNBuf;
	}
	return 0;
}

/* Get and set parameters for the given connection.
 * Return 0 on success, an error code on failure. */
int  pppIOCtl(int pd, int cmd, void *arg)
{
	PPPControl *pc = &pppControl[pd];
	int st = 0;

	if (pd < 0 || pd >= NUM_PPP)
		st = PPPERR_PARAM;
	else {
		switch(cmd) {
		case PPPCTLG_UPSTATUS:		/* Get the PPP up status. */
			if (arg) 
				*(int *)arg = (int)(pc->if_up);
			else
				st = PPPERR_PARAM;
			break;
		case PPPCTLS_ERRCODE:		/* Set the PPP error code. */
			if (arg) 
				pc->errCode = *(int *)arg;
			else
				st = PPPERR_PARAM;
			break;
		case PPPCTLG_ERRCODE:		/* Get the PPP error code. */
			if (arg) 
				*(int *)arg = (int)(pc->errCode);
			else
				st = PPPERR_PARAM;
			break;
		case PPPCTLG_FD:
			if (arg) 
				*(int *)arg = (int)(pc->fd);
			else
				st = PPPERR_PARAM;
			break;
		default:
			st = PPPERR_PARAM;
			break;
		}
	}
	
	return st;
}

/*
 * Return the Maximum Transmission Unit for the given PPP connection.
 */
u_int pppMTU(int pd)
{
	PPPControl *pc = &pppControl[pd];
	u_int st;
	
	/* Validate parameters. */
	if (pd < 0 || pd >= NUM_PPP || !pc->openFlag)
		st = 0;
	else
		st = pc->mtu;
		
	return st;
}

/*
 * Write n characters to a ppp link.
 *	RETURN: >= 0 Number of characters written
 *		 	 -1 Failed to write to device
 */
int pppWrite(int pd, const char *s, int n)
{
	PPPControl *pc = &pppControl[pd];
	short st = 0;
	u_char c;
	u_int fcsOut = PPP_INITFCS;
	NBuf *headMB = NULL, *tailMB;

	nGET(headMB);
	if (headMB == NULL) {
		st = PPPERR_ALLOC;
#if STATS_SUPPORT > 0
		pppStats.PPPoerrors++;
#endif
	} else {
		headMB->len = 0;
		tailMB = headMB;
		
		/* If the link has been idle, we'll send a fresh flag character to
		 * flush any noise. */
		if (diffTime(pc->lastXMit) <= MAXIDLEFLAG)
			tailMB = pppMPutRaw(PPP_FLAG, tailMB);
		pc->lastXMit = mtime();
		 
		/* Load output buffer. */
		while (n-- > 0) {
			c = *s++;
			
			/* Update FCS before checking for special characters. */
			fcsOut = PPP_FCS(fcsOut, c);
			
			/* Copy to output buffer escaping special characters. */
			tailMB = pppMPutC(c, &pc->outACCM, tailMB);
		}
		
		/* Add FCS and trailing flag. */
		c = ~fcsOut & 0xFF;
		tailMB = pppMPutC(c, &pc->outACCM, tailMB);
		c = (~fcsOut >> 8) & 0xFF;
		tailMB = pppMPutC(c, &pc->outACCM, tailMB);
		tailMB = pppMPutRaw(PPP_FLAG, tailMB);
		
		/* If we failed to complete the packet, throw it away.
		 * Otherwise send it. */
		if (tailMB) {
			PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
						"pppWrite[%d]: %d:%.*H", 
						pd,
						headMB->len, MIN(headMB->len * 2, 40), headMB->data));
			nPut(pc->fd, headMB);
#if STATS_SUPPORT > 0
			pppStats.PPPopackets++;
#endif
		}
		else {
			PPPDEBUG((pppControl[pd].traceOffset + LOG_WARNING, TL_PPP,
						"pppWrite[%d]: Alloc err - dropping %d:%.*H", 
						pd,
						headMB->len, MIN(headMB->len * 2, 40), headMB->data));
			nFreeChain(headMB);
#if STATS_SUPPORT > 0
			pppStats.PPPoerrors++;
#endif
		}
	}
	
	return st;
}

/*
 * ppp_send_config - configure the transmit characteristics of
 * the ppp interface.
 */
void ppp_send_config(
	int unit, 
	int mtu,
	u_int32_t asyncmap,
	int pcomp, 
	int accomp
)
{
	PPPControl *pc = &pppControl[unit];
	int i;
	
	pc->mtu = mtu;
	pc->pcomp = pcomp;
	pc->accomp = accomp;
	
	/* Load the ACCM bits for the 32 control codes. */
	for (i = 0; i < 32/8; i++)
		pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF);
	PPPDEBUG((LOG_INFO, TL_PPP, "ppp_send_config[%d]: outACCM=%X %X %X %X",
				unit,
				pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
}


/*
 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
 */
void ppp_set_xaccm(int unit, ext_accm *accm)
{
	memcpy(pppControl[unit].outACCM, accm, sizeof(ext_accm));
	PPPDEBUG((LOG_INFO, TL_PPP, "ppp_set_xaccm[%d]: outACCM=%X %X %X %X",
				unit,
				pppControl[unit].outACCM[0],
				pppControl[unit].outACCM[1],
				pppControl[unit].outACCM[2],
				pppControl[unit].outACCM[3]));
}


/*
 * ppp_recv_config - configure the receive-side characteristics of
 * the ppp interface.
 */
#pragma argsused /* XXX */
void ppp_recv_config(
	int unit, 
	int mru,
	u_int32_t asyncmap,
	int pcomp, 
	int accomp
)
{
	PPPControl *pc = &pppControl[unit];
	int i;
	
	/* Load the ACCM bits for the 32 control codes. */
	for (i = 0; i < 32 / 8; i++)
		pc->inACCM[i] = (u_char)(asyncmap >> (i * 8));
	PPPDEBUG((LOG_INFO, TL_PPP, "ppp_recv_config[%d]: inACCM=%X %X %X %X",
				unit,
				pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3]));
}

/*
 * ccp_test - ask kernel whether a given compression method
 * is acceptable for use.  Returns 1 if the method and parameters
 * are OK, 0 if the method is known but the parameters are not OK
 * (e.g. code size should be reduced), or -1 if the method is unknown.
 */
#pragma argsused
int ccp_test(
	int unit, 
	int opt_len, 
	int for_transmit,
	u_char *opt_ptr
)
{
	return 0;	/* XXX Currently no compression. */
}

/*
 * ccp_flags_set - inform kernel about the current state of CCP.
 */
#pragma argsused
void ccp_flags_set(int unit, int isopen, int isup)
{
	/* XXX */
}

/*
 * ccp_fatal_error - returns 1 if decompression was disabled as a
 * result of an error detected after decompression of a packet,
 * 0 otherwise.  This is necessary because of patent nonsense.
 */
#pragma argsused
int ccp_fatal_error(int unit)
{
	/* XXX */
	return 0;
}

/*
 * get_idle_time - return how long the link has been idle.
 */
#pragma argsused
int get_idle_time(int u, struct ppp_idle *ip)
{	
	/* XXX */
	return 0;
}


/*
 * Return user specified netmask, modified by any mask we might determine
 * for address `addr' (in network byte order).
 * Here we scan through the system's list of interfaces, looking for
 * any non-point-to-point interfaces which might appear to be on the same
 * network as `addr'.  If we find any, we OR in their netmask to the
 * user-specified netmask.
 */
u_int32_t GetMask(u_int32_t addr)
{
	u_int32_t mask, nmask;
	
	asm {
		mov  ax, WORD PTR addr
		xchg ah, al
		xchg ax, WORD PTR addr + 2
		xchg ah, al
		mov  WORD PTR addr, ax
	}
	if (IN_CLASSA(addr))	/* determine network mask for address class */
		nmask = IN_CLASSA_NET;
	else if (IN_CLASSB(addr))
		nmask = IN_CLASSB_NET;
	else
		nmask = IN_CLASSC_NET;
	/* class D nets are disallowed by bad_ip_adrs */
	mask = netMask | htonl(nmask);
	
	/* XXX
	 * Scan through the system's network interfaces.
	 * Get each netmask and OR them into our mask.
	 */
	
	return mask;
}

/*
 * sifvjcomp - config tcp header compression
 */
#pragma argsused
int sifvjcomp(
	int pd, 
	int vjcomp, 
	int cidcomp, 
	int maxcid
)
{
#if VJ_SUPPORT > 0
	PPPControl *pc = &pppControl[pd];

⌨️ 快捷键说明

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