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

📄 netipcp.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (neg) { \
		int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
		if ((len -= vjlen) < 0) \
			goto bad; \
		GETCHAR(citype, p); \
		GETCHAR(cilen, p); \
		if (cilen != vjlen || \
				citype != opt)  \
			goto bad; \
		GETSHORT(cishort, p); \
		if (cishort != val) \
			goto bad; \
		if (!old) { \
			GETCHAR(cimaxslotindex, p); \
			if (cimaxslotindex != maxslotindex) \
				goto bad; \
			GETCHAR(cicflag, p); \
			if (cicflag != cflag) \
				goto bad; \
		} \
	}

	

#define ACKCIADDR(opt, neg, old, val1, val2) \
	if (neg) { \
		int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
		u_int32_t l; \
		if ((len -= addrlen) < 0) \
			goto bad; \
		GETCHAR(citype, p); \
		GETCHAR(cilen, p); \
		if (cilen != addrlen || \
				citype != opt) \
			goto bad; \
		GETLONG(l, p); \
		cilong = htonl(l); \
		if (val1 != cilong) \
			goto bad; \
		if (old) { \
			GETLONG(l, p); \
			cilong = htonl(l); \
			if (val2 != cilong) \
				goto bad; \
		} \
	}

	

	ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
			  go->old_addrs, go->ouraddr, go->hisaddr);

	

	ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
			go->maxslotindex, go->cflag);

	

	/*

	 * If there are any remaining CIs, then this packet is bad.

	 */

	if (len != 0)

		goto bad;

	return (1);

	

bad:

	IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!"));

	return (0);

}

                                          /*******************************************************297***********/

/*

 * ipcp_nakci - Peer has sent a NAK for some of our CIs.

 * This should not modify any state if the Nak is bad

 * or if IPCP is in the OPENED state.

 *

 * Returns:

 *	0 - Nak was bad.

 *	1 - Nak was good.

 */                              /*9*/

static int ipcp_nakci(fsm *f, u_char *p, int len)

{

	ipcp_options *go = &ipcp_gotoptions[f->unit];

	u_char cimaxslotindex, cicflag;

	u_char citype, cilen, *next;

	u_short cishort;

	u_int32_t ciaddr1, ciaddr2, l;

	ipcp_options no;		/* options we've seen Naks for */

	ipcp_options try;		/* options to request next time */

	

	BZERO(&no, sizeof(no));

	try = *go;

	

	/*

	 * Any Nak'd 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 NAKCIADDR(opt, neg, old, code) \
	if (go->neg && \
			len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
			p[1] == cilen && \
			p[0] == opt) { \
		len -= cilen; \
		INCPTR(2, p); \
		GETLONG(l, p); \
		ciaddr1 = htonl(l); \
		if (old) { \
			GETLONG(l, p); \
			ciaddr2 = htonl(l); \
			no.old_addrs = 1; \
		} else \
			ciaddr2 = 0; \
		no.neg = 1; \
		code \
	}

	

#define NAKCIVJ(opt, neg, code) \
	if (go->neg && \
			((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
			len >= cilen && \
			p[0] == opt) { \
		len -= cilen; \
		INCPTR(2, p); \
		GETSHORT(cishort, p); \
		no.neg = 1; \
		code \
	}

	

	/*

	 * Accept the peer's idea of {our,his} address, if different

	 * from our idea, only if the accept_{local,remote} flag is set.

	 */

	NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
	  if (go->accept_local && ciaddr1) { /* Do we know our address? */
		  try.ouraddr = ciaddr1;
		  IPCPDEBUG((LOG_INFO, "local IP address %s",
			     ip_ntoa(ciaddr1)));
	  }

	  if (go->accept_remote && ciaddr2) { /* Does he know his? */

		  try.hisaddr = ciaddr2;

		  IPCPDEBUG((LOG_INFO, "remote IP address %s",

			     ip_ntoa(ciaddr2)));

	  }

	);

	

	/*

	 * Accept the peer's value of maxslotindex provided that it

	 * is less than what we asked for.  Turn off slot-ID compression

	 * if the peer wants.  Send old-style compress-type option if

	 * the peer wants.

	 */

	NAKCIVJ(CI_COMPRESSTYPE, neg_vj,

		if (cilen == CILEN_VJ) {

			GETCHAR(cimaxslotindex, p);

			GETCHAR(cicflag, p);

			if (cishort == IPCP_VJ_COMP) {

				try.old_vj = 0;

				if (cimaxslotindex < go->maxslotindex)

					try.maxslotindex = cimaxslotindex;

				if (!cicflag)

					try.cflag = 0;

			} else {

				try.neg_vj = 0;

			}

		} else {

			if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {

				try.old_vj = 1;

				try.vj_protocol = cishort;

			} else {

				try.neg_vj = 0;

			}

		}

	);

	

	/*

	* There may be remaining CIs, if the peer is requesting negotiation

	* on an option that we didn't include in our request packet.

	* If they want to negotiate about IP addresses, we comply.

	* If they want us to ask for compression, we refuse.

	*/

	while (len > CILEN_VOID) {

		GETCHAR(citype, p);

		GETCHAR(cilen, p);

		if( (len -= cilen) < 0 )

			goto bad;

		next = p + cilen - 2;

		

		switch (citype) {

		case CI_COMPRESSTYPE:

			if (go->neg_vj || no.neg_vj ||

					(cilen != CILEN_VJ && cilen != CILEN_COMPRESS))

				goto bad;

			no.neg_vj = 1;

			break;

		case CI_ADDRS:

			if ((go->neg_addr && go->old_addrs) || no.old_addrs

					|| cilen != CILEN_ADDRS)

				goto bad;

			try.neg_addr = 1;

			try.old_addrs = 1;

			GETLONG(l, p);

			ciaddr1 = htonl(l);

			if (ciaddr1 && go->accept_local)

				try.ouraddr = ciaddr1;

			GETLONG(l, p);

			ciaddr2 = htonl(l);

			if (ciaddr2 && go->accept_remote)

				try.hisaddr = ciaddr2;

			no.old_addrs = 1;

			break;

		case CI_ADDR:

			if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)

				goto bad;

			try.old_addrs = 0;

			GETLONG(l, p);

			ciaddr1 = htonl(l);

			if (ciaddr1 && go->accept_local)

				try.ouraddr = ciaddr1;

			if (try.ouraddr != 0)

				try.neg_addr = 1;

			no.neg_addr = 1;

			break;

		}

		p = next;

	}

	

	/* If there is still anything left, this packet is bad. */

	if (len != 0)

		goto bad;

	

	/*

	 * OK, the Nak is good.  Now we can update state.

	 */

	if (f->state != OPENED)

		*go = try;

	

	return 1;

	

bad:

	IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!"));

	return 0;

}



/************************************************************************************************************/

/*

 * ipcp_rejci - Reject some of our CIs.

 */

static int ipcp_rejci(fsm *f, u_char *p, int len)

{

	ipcp_options *go = &ipcp_gotoptions[f->unit];

	u_char cimaxslotindex, ciflag, cilen;

	u_short cishort;

	u_int32_t cilong;

	ipcp_options try;		/* options to request next time */

	

	try = *go;

	/*

	 * Any Rejected 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 REJCIADDR(opt, neg, old, val1, val2) \
	if (go->neg && \
			len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
			p[1] == cilen && \
			p[0] == opt) { \
		u_int32_t l; \
		len -= cilen; \
		INCPTR(2, p); \
		GETLONG(l, p); \
		cilong = htonl(l); \
		/* Check rejected value. */ \
		if (cilong != val1) \
			goto bad; \
		if (old) { \
			GETLONG(l, p); \
			cilong = htonl(l); \
			/* Check rejected value. */ \
			if (cilong != val2) \
				goto bad; \
		} \
		try.neg = 0; \
	}

	

#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
	if (go->neg && \
			p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
			len >= p[1] && \
			p[0] == opt) { \
		len -= p[1]; \
		INCPTR(2, p); \
		GETSHORT(cishort, p); \
		/* Check rejected value. */  \
		if (cishort != val) \
			goto bad; \
		if (!old) { \
			GETCHAR(cimaxslotindex, p); \
			if (cimaxslotindex != maxslot) \
				goto bad; \
			GETCHAR(ciflag, p); \
			if (ciflag != cflag) \
				goto bad; \
		} \
		try.neg = 0; \
	}

	

	REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,

			  go->old_addrs, go->ouraddr, go->hisaddr);

	

	REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,

			go->maxslotindex, go->cflag);

	

	/*

	 * If there are any remaining CIs, then this packet is bad.

	 */

	if (len != 0)

		goto bad;

	/*

	 * Now we can update state.

	 */

	if (f->state != OPENED)

		*go = try;

	return 1;

	

bad:

	IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!"));

	return 0;

}



/*********************************************************************************************260***********/

/*

 * ipcp_reqci - Check the peer's requested CIs and send appropriate response.

 *

 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified

 * appropriately.  If reject_if_disagree is non-zero, doesn't return

 * CONFNAK; returns CONFREJ if it can't return CONFACK.

 */

static int ipcp_reqci(

	fsm *f,

	u_char *inp,		/* Requested CIs */

	int *len,			/* Length of requested CIs */

	int reject_if_disagree

)

{

	ipcp_options *wo = &ipcp_wantoptions[f->unit];

	ipcp_options *ho = &ipcp_hisoptions[f->unit];

	ipcp_options *ao = &ipcp_allowoptions[f->unit];

#ifdef OLD_CI_ADDRS

	ipcp_options *go = &ipcp_gotoptions[f->unit];

#endif

	u_char *cip, *next;				/* Pointer to current and next CIs */

	u_short cilen, citype;			/* Parsed len, type */

	u_short cishort;				/* Parsed short value */

	u_int32_t tl, ciaddr1;			/* Parsed address values */

#ifdef OLD_CI_ADDRS

	u_int32_t ciaddr2;				/* Parsed address values */

#endif

	int rc = CONFACK;				/* Final packet return code */

	int orc;						/* Individual option return code */

	u_char *p;						/* Pointer to next char to parse */

	u_char *ucp = inp;				/* Pointer to current output char */

	int l = *len;					/* Length left */

	u_char maxslotindex, cflag;

	int d;

	

	cis_received[f->unit] = 1;

	

	/*

	 * Reset all his options.

	 */

	BZERO(ho, sizeof(*ho));

	

	/*

	 * Process all his options.

	 */

	next = inp;

	while (l) {

		orc = CONFACK;				/* Assume success */

		cip = p = next;				/* Remember begining of CI */

		if (l < 2 ||				/* Not enough data for CI header or */

				p[1] < 2 ||			/*  CI length too small or */

				p[1] > l) {			/*  CI length too big? */

			IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!"));

			orc = CONFREJ;			/* Reject bad CI */

			cilen = l;				/* Reject till end of packet */

			l = 0;					/* Don't loop again */

			goto endswitch;

		}

		GETCHAR(citype, p);			/* Parse CI type */

		GETCHAR(cilen, p);			/* Parse CI length */

		l -= cilen;					/* Adjust remaining length */

		next += cilen;				/* Step to next CI */



		switch (citype) {			/* Check CI type */

#ifdef OLD_CI_ADDRS /* Need to save space... */

		case CI_ADDRS:

			IPCPDEBUG((LOG_INFO, "ipcp_reqci: received ADDRS "));

			if (!ao->neg_addr ||

					cilen != CILEN_ADDRS) {	/* Check CI length */

				orc = CONFREJ;		/* Reject CI */

				break;

			}

			

			/*

			 * If he has no address, or if we both have his address but

			 * disagree about it, then NAK it with our idea.

			 * In particular, if we don't know his address, but he does,

			 * then accept it.

			 */

			GETLONG(tl, p);		/* Parse source address (his) */

			ciaddr1 = htonl(tl);

			IPCPDEBUG((LOG_INFO, "his addr %s", ip_ntoa(ciaddr1)));

			if (ciaddr1 != wo->hisaddr

					&& (ciaddr1 == 0 || !wo->accept_remote)) {

				orc = CONFNAK;

				if (!reject_if_disagree) {

					DECPTR(sizeof(u_int32_t), p);

					tl = ntohl(wo->hisaddr);

					PUTLONG(tl, p);

				}

			} else if (ciaddr1 == 0 && wo->hisaddr == 0) {

				/*

				 * If neither we nor he knows his address, reject the option.

				 */

				orc = CONFREJ;

				wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */

				break;

			}

			

			/*

			 * If he doesn't know our address, or if we both have our address

			 * but disagree about it, then NAK it with our idea.

			 */

			GETLONG(tl, p);		/* Parse desination address (ours) */

			ciaddr2 = htonl(tl);

			IPCPDEBUG((LOG_INFO, "our addr %s", ip_ntoa(ciaddr2)));

			if (ciaddr2 != wo->ouraddr) {

				if (ciaddr2 == 0 || !wo->accept_local) {

					orc = CONFNAK;

					if (!reject_if_disagree) {

						DECPTR(sizeof(u_int32_t), p);

						tl = ntohl(wo->ouraddr);

						PUTLONG(tl, p);

					}

				} else {

					go->ouraddr = ciaddr2;	/* accept peer's idea */

				}

			}

			

			ho->neg_addr = 1;

			ho->old_addrs = 1;

			ho->hisaddr = ciaddr1;

			ho->ouraddr = ciaddr2;

			break;

#endif

/**********************************************************************************************************/		

		case CI_ADDR:

			if (!ao->neg_addr) {

				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed"));

				orc = CONFREJ;				/* Reject CI */

				break;

			} else if (cilen != CILEN_ADDR) {	/* Check CI length */

⌨️ 快捷键说明

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