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

📄 ipcp.c

📁 轻量级TCP/IP协议栈最新版本
💻 C
📖 第 1 页 / 共 3 页
字号:
			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); \		u32_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; \		} \	}#define ACKCIDNS(opt, neg, addr) \	if (neg) { \		u32_t l; \		if ((len -= CILEN_ADDR) < 0) \			goto bad; \		GETCHAR(citype, p); \		GETCHAR(cilen, p); \		if (cilen != CILEN_ADDR || \				citype != opt) \			goto bad; \		GETLONG(l, p); \		cilong = htonl(l); \		if (addr != 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);		ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);	ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);	/*	 * 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!\n"));	return (0);}/* * 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. */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;	u32_t ciaddr1, ciaddr2, l, cidnsaddr;	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 \	}	#define NAKCIDNS(opt, neg, code) \	if (go->neg && \			((cilen = p[1]) == CILEN_ADDR) && \			len >= cilen && \			p[0] == opt) { \		len -= cilen; \		INCPTR(2, p); \		GETLONG(l, p); \		cidnsaddr = htonl(l); \		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\n",			     inet_ntoa(ciaddr1)));	  }	  if (go->accept_remote && ciaddr2) { /* Does he know his? */		  try.hisaddr = ciaddr2;		  IPCPDEBUG((LOG_INFO, "remote IP address %s\n",			     inet_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;			}		}	);		NAKCIDNS(CI_MS_DNS1, req_dns1,			try.dnsaddr[0] = cidnsaddr;		  	IPCPDEBUG((LOG_INFO, "primary DNS address %s\n", inet_ntoa(cidnsaddr)));			);	NAKCIDNS(CI_MS_DNS2, req_dns2,			try.dnsaddr[1] = cidnsaddr;		  	IPCPDEBUG((LOG_INFO, "secondary DNS address %s\n", inet_ntoa(cidnsaddr)));			);	/*	* 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!\n"));	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;	u32_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) { \		u32_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; \	}	#define REJCIDNS(opt, neg, dnsaddr) \	if (go->neg && \			((cilen = p[1]) == CILEN_ADDR) && \			len >= cilen && \			p[0] == opt) { \		u32_t l; \		len -= cilen; \		INCPTR(2, p); \		GETLONG(l, p); \		cilong = htonl(l); \		/* Check rejected value. */ \		if (cilong != dnsaddr) \			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);		REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);	REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);	/*	 * 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!\n"));	return 0;}/* * 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 */	u32_t tl, ciaddr1;			/* Parsed address values */#ifdef OLD_CI_ADDRS	u32_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!\n"));			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\n"));			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\n", inet_ntoa(ciaddr1)));			if (ciaddr1 != wo->hisaddr					&& (ciaddr1 == 0 || !wo->accept_remote)) {				orc = CONFNAK;

⌨️ 快捷键说明

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