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

📄 netipcp.c

📁 ucos操作系统下TCPIP实现代码
💻 C
📖 第 1 页 / 共 3 页
字号:
					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 */
				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len"));
				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(u_int32_t), p);
					tl = ntohl(wo->hisaddr);
					PUTLONG(tl, p);
				}
				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s", ip_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", ip_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", ip_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 ", 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",
							d+1, ip_ntoa(tl)));
				DECPTR(sizeof(u_int32_t), p);
				tl = ntohl(ao->dnsaddr[d]);
				PUTLONG(tl, p);
				orc = CONFNAK;
			}
			IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request ", 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 ", 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(u_int32_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"));
				orc = CONFREJ;
				break;
			} else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
				IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d", 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", 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", 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", 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",
						ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));
			break;
			
		default:
			IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d", 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"));
				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"));
		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", CODENAME(rc)));
	return (rc);			/* Return final code */
}


/*
 * ip_check_options - check that any IP-related options are OK,
 * and assign appropriate defaults.
 */
static void ip_check_options(void)
{
	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 && !disable_defaultip) {
		wo->accept_local = 1;	/* don't insist on this default value */
		wo->ouraddr = htonl(localHost);
	}
}


/*
 * ipcp_up - IPCP has come UP.
 *
 * Configure the IP network interface appropriately and bring it up.
 */
static void ipcp_up(fsm *f)
{
	u_int32_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"));
	
	/*
	 * 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) {
		trace(LOG_ERR, "Could not determine remote IP address");
		ipcp_close(f->unit, "Could not determine remote IP address");
		return;
	}
	if (go->ouraddr == 0) {
		trace(LOG_ERR, "Could not determine local IP address");
		ipcp_close(f->unit, "Could not determine local IP address");
		return;
	}
	
	/*
	 * Check that the peer is allowed to use the IP address it wants.
	 */
	if (!auth_ip_addr(f->unit, ho->hisaddr)) {
		trace(LOG_ERR, "Peer is not authorized to use remote address %s",
				ip_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 !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
		IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
		ipcp_close(f->unit, "Interface configuration failed");
		return;
	}
#endif
	
	/* bring the interface up for IP */
	if (!sifup(f->unit)) {
		IPCPDEBUG((LOG_WARNING, "sifup failed"));
		ipcp_close(f->unit, "Interface configuration failed");
		return;
	}
	
#if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
		IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
		ipcp_close(f->unit, "Interface configuration failed");
		return;
	}
#endif
	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;
	
	trace(LOG_NOTICE, "local  IP address %s", ip_ntoa(go->ouraddr));
	trace(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr));
}


/*
 * 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"));
	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)
{
	u_int32_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);
}

#pragma argsused
static int ipcp_printpkt(
	u_char *p,
	int plen,
	void (*printer) __P((void *, char *, ...)),
	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;
}

⌨️ 快捷键说明

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