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

📄 ipcp.c

📁 轻量级TCP/IP协议栈最新版本
💻 C
📖 第 1 页 / 共 3 页
字号:
				if (!reject_if_disagree) {					DECPTR(sizeof(u32_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\n", inet_ntoa(ciaddr2)));			if (ciaddr2 != wo->ouraddr) {				if (ciaddr2 == 0 || !wo->accept_local) {					orc = CONFNAK;					if (!reject_if_disagree) {						DECPTR(sizeof(u32_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\n"));				orc = CONFREJ;				/* Reject CI */				break;			} else if (cilen != CILEN_ADDR) {	/* Check CI length */				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len\n"));				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);			if (ciaddr1 != wo->hisaddr					&& (ciaddr1 == 0 || !wo->accept_remote)) {				orc = CONFNAK;				if (!reject_if_disagree) {					DECPTR(sizeof(u32_t), p);					tl = ntohl(wo->hisaddr);					PUTLONG(tl, p);				}				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));			} else if (ciaddr1 == 0 && wo->hisaddr == 0) {				/*				 * Don't ACK an address of 0.0.0.0 - reject it instead.				 */				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));				orc = CONFREJ;				wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */				break;			}						ho->neg_addr = 1;			ho->hisaddr = ciaddr1;			IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));			break;				case CI_MS_DNS1:		case CI_MS_DNS2:			/* Microsoft primary or secondary DNS request */			d = citype == CI_MS_DNS2;						/* If we do not have a DNS address then we cannot send it */			if (ao->dnsaddr[d] == 0 ||					cilen != CILEN_ADDR) {	/* Check CI length */				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request\n", d+1));				orc = CONFREJ;				/* Reject CI */				break;			}			GETLONG(tl, p);			if (htonl(tl) != ao->dnsaddr[d]) {				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d\n",							d+1, inet_ntoa(tl)));				DECPTR(sizeof(u32_t), p);				tl = ntohl(ao->dnsaddr[d]);				PUTLONG(tl, p);				orc = CONFNAK;			}			IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request\n", d+1));			break;				case CI_MS_WINS1:		case CI_MS_WINS2:			/* Microsoft primary or secondary WINS request */			d = citype == CI_MS_WINS2;			IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request\n", d+1));						/* If we do not have a DNS address then we cannot send it */			if (ao->winsaddr[d] == 0 ||				cilen != CILEN_ADDR) {	/* Check CI length */				orc = CONFREJ;			/* Reject CI */				break;			}			GETLONG(tl, p);			if (htonl(tl) != ao->winsaddr[d]) {				DECPTR(sizeof(u32_t), p);				tl = ntohl(ao->winsaddr[d]);				PUTLONG(tl, p);				orc = CONFNAK;			}			break;				case CI_COMPRESSTYPE:			if (!ao->neg_vj) {				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));				orc = CONFREJ;				break;			} else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));				orc = CONFREJ;				break;			}			GETSHORT(cishort, p);						if (!(cishort == IPCP_VJ_COMP ||					(cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));				orc = CONFREJ;				break;			}						ho->neg_vj = 1;			ho->vj_protocol = cishort;			if (cilen == CILEN_VJ) {				GETCHAR(maxslotindex, p);				if (maxslotindex > ao->maxslotindex) { 					IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));					orc = CONFNAK;					if (!reject_if_disagree){						DECPTR(1, p);						PUTCHAR(ao->maxslotindex, p);					}				}				GETCHAR(cflag, p);				if (cflag && !ao->cflag) {					IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d\n", cflag));					orc = CONFNAK;					if (!reject_if_disagree){						DECPTR(1, p);						PUTCHAR(wo->cflag, p);					}				}				ho->maxslotindex = maxslotindex;				ho->cflag = cflag;			} else {				ho->old_vj = 1;				ho->maxslotindex = MAX_SLOTS - 1;				ho->cflag = 1;			}			IPCPDEBUG((LOG_INFO, 						"ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n",						ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));			break;					default:			IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d\n", citype));			orc = CONFREJ;			break;		}		endswitch:		if (orc == CONFACK &&		/* Good CI */				rc != CONFACK)		/*  but prior CI wasnt? */			continue;				/* Don't send this one */				if (orc == CONFNAK) {		/* Nak this CI? */			if (reject_if_disagree) {	/* Getting fed up with sending NAKs? */				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks\n"));				orc = CONFREJ;		/* Get tough if so */			} else {				if (rc == CONFREJ)	/* Rejecting prior CI? */					continue;		/* Don't send this one */				if (rc == CONFACK) {	/* Ack'd all prior CIs? */					rc = CONFNAK;	/* Not anymore... */					ucp = inp;		/* Backup */				}			}		}				if (orc == CONFREJ &&		/* Reject this CI */				rc != CONFREJ) {	/*  but no prior ones? */			rc = CONFREJ;			ucp = inp;				/* Backup */		}				/* Need to move CI? */		if (ucp != cip)			BCOPY(cip, ucp, cilen);	/* Move it */				/* Update output pointer */		INCPTR(cilen, ucp);	}		/*	 * If we aren't rejecting this packet, and we want to negotiate	 * their address, and they didn't send their address, then we	 * send a NAK with a CI_ADDR option appended.  We assume the	 * input buffer is long enough that we can append the extra	 * option safely.	 */	if (rc != CONFREJ && !ho->neg_addr &&			wo->req_addr && !reject_if_disagree) {		IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address\n"));		if (rc == CONFACK) {			rc = CONFNAK;			ucp = inp;				/* reset pointer */			wo->req_addr = 0;		/* don't ask again */		}		PUTCHAR(CI_ADDR, ucp);		PUTCHAR(CILEN_ADDR, ucp);		tl = ntohl(wo->hisaddr);		PUTLONG(tl, ucp);	}		*len = (int)(ucp - inp);		/* Compute output length */	IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));	return (rc);			/* Return final code */}#if 0/* * ip_check_options - check that any IP-related options are OK, * and assign appropriate defaults. */static void ip_check_options(u_long localAddr){	ipcp_options *wo = &ipcp_wantoptions[0];	/*	 * Load our default IP address but allow the remote host to give us	 * a new address.	 */	if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) {		wo->accept_local = 1;	/* don't insist on this default value */		wo->ouraddr = htonl(localAddr);	}}#endif/* * ipcp_up - IPCP has come UP. * * Configure the IP network interface appropriately and bring it up. */static void ipcp_up(fsm *f){	u32_t mask;	ipcp_options *ho = &ipcp_hisoptions[f->unit];	ipcp_options *go = &ipcp_gotoptions[f->unit];	ipcp_options *wo = &ipcp_wantoptions[f->unit];		np_up(f->unit, PPP_IP);	IPCPDEBUG((LOG_INFO, "ipcp: up\n"));		/*	 * We must have a non-zero IP address for both ends of the link.	 */	if (!ho->neg_addr)		ho->hisaddr = wo->hisaddr;		if (ho->hisaddr == 0) {		IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n"));		ipcp_close(f->unit, "Could not determine remote IP address");		return;	}	if (go->ouraddr == 0) {		IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n"));		ipcp_close(f->unit, "Could not determine local IP address");		return;	}		if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {		/*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/	}	/*	 * Check that the peer is allowed to use the IP address it wants.	 */	if (!auth_ip_addr(f->unit, ho->hisaddr)) {		IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n",				inet_ntoa(ho->hisaddr)));		ipcp_close(f->unit, "Unauthorized remote IP address");		return;	}		/* set tcp compression */	sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);		/*	 * Set IP addresses and (if specified) netmask.	 */	mask = GetMask(go->ouraddr);		if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) {		IPCPDEBUG((LOG_WARNING, "sifaddr failed\n"));		ipcp_close(f->unit, "Interface configuration failed");		return;	}		/* bring the interface up for IP */	if (!sifup(f->unit)) {		IPCPDEBUG((LOG_WARNING, "sifup failed\n"));		ipcp_close(f->unit, "Interface configuration failed");		return;	}		sifnpmode(f->unit, PPP_IP, NPMODE_PASS);		/* assign a default route through the interface if required */	if (ipcp_wantoptions[f->unit].default_route) 		if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))			default_route_set[f->unit] = 1;		IPCPDEBUG((LOG_NOTICE, "local  IP address %s\n", inet_ntoa(go->ouraddr)));	IPCPDEBUG((LOG_NOTICE, "remote IP address %s\n", inet_ntoa(ho->hisaddr)));	if (go->dnsaddr[0]) {		IPCPDEBUG((LOG_NOTICE, "primary   DNS address %s\n", inet_ntoa(go->dnsaddr[0])));	}	if (go->dnsaddr[1]) {		IPCPDEBUG((LOG_NOTICE, "secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));	}}/* * ipcp_down - IPCP has gone DOWN. * * Take the IP network interface down, clear its addresses * and delete routes through it. */static void ipcp_down(fsm *f){	IPCPDEBUG((LOG_INFO, "ipcp: down\n"));	np_down(f->unit, PPP_IP);	sifvjcomp(f->unit, 0, 0, 0);		sifdown(f->unit);	ipcp_clear_addrs(f->unit);}/* * ipcp_clear_addrs() - clear the interface addresses, routes, etc. */static void ipcp_clear_addrs(int unit){	u32_t ouraddr, hisaddr;		ouraddr = ipcp_gotoptions[unit].ouraddr;	hisaddr = ipcp_hisoptions[unit].hisaddr;	if (default_route_set[unit]) {		cifdefaultroute(unit, ouraddr, hisaddr);		default_route_set[unit] = 0;	}	cifaddr(unit, ouraddr, hisaddr);}/* * ipcp_finished - possibly shut down the lower layers. */static void ipcp_finished(fsm *f){	np_finished(f->unit, PPP_IP);}#if 0static int ipcp_printpkt(	u_char *p,	int plen,	void (*printer) (void *, char *, ...),	void *arg){	(void)p;	(void)plen;	(void)printer;	(void)arg;	return 0;}/* * ip_active_pkt - see if this IP packet is worth bringing the link up for. * We don't bring the link up for IP fragments or for TCP FIN packets * with no data. */#define IP_HDRLEN	20	/* bytes */#define IP_OFFMASK	0x1fff#define IPPROTO_TCP	6#define TCP_HDRLEN	20#define TH_FIN		0x01/* * We use these macros because the IP header may be at an odd address, * and some compilers might use word loads to get th_off or ip_hl. */#define net_short(x)	(((x)[0] << 8) + (x)[1])#define get_iphl(x)	(((unsigned char *)(x))[0] & 0xF)#define get_ipoff(x)	net_short((unsigned char *)(x) + 6)#define get_ipproto(x)	(((unsigned char *)(x))[9])#define get_tcpoff(x)	(((unsigned char *)(x))[12] >> 4)#define get_tcpflags(x)	(((unsigned char *)(x))[13])static int ip_active_pkt(u_char *pkt, int len){	u_char *tcp;	int hlen;		len -= PPP_HDRLEN;	pkt += PPP_HDRLEN;	if (len < IP_HDRLEN)		return 0;	if ((get_ipoff(pkt) & IP_OFFMASK) != 0)		return 0;	if (get_ipproto(pkt) != IPPROTO_TCP)		return 1;	hlen = get_iphl(pkt) * 4;	if (len < hlen + TCP_HDRLEN)		return 0;	tcp = pkt + hlen;	if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)		return 0;	return 1;}#endif#endif /* PPP_SUPPORT */

⌨️ 快捷键说明

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