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

📄 ipcp.c

📁 自己精简过的PPPD代码。在嵌入中应用可以更好的发挥。比原先的小了很多
💻 C
📖 第 1 页 / 共 4 页
字号:
		 try.dnsaddr[0] = cidnsaddr;	     }	     );    NAKCIDNS(CI_MS_DNS2, req_dns2,	     if (treat_as_reject) {		 try.req_dns2 = 0;	     } else {		 try.dnsaddr[1] = 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 ( cilen < CILEN_VOID || (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 = 0;	    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;    }    /*     * OK, the Nak is good.  Now we can update state.     * If there are any remaining options, we ignore them.     */    if (f->state != OPENED)	*go = try;    return 1;bad:    IPCPDEBUG(("ipcp_nakci: received bad Nak!"));    return 0;}/* * ipcp_rejci - Reject some of our CIs. * Callback from fsm_rconfnakrej. */static intipcp_rejci(f, p, len)    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 REJCIADDRS(opt, neg, val1, val2) \    if ((neg) && \	(cilen = p[1]) == CILEN_ADDRS && \	len >= 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; \	GETLONG(l, p); \	cilong = htonl(l); \	/* Check rejected value. */ \	if (cilong != val2) \	    goto bad; \	try.old_addrs = 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 REJCIADDR(opt, neg, val) \    if (go->neg && \	(cilen = p[1]) == CILEN_ADDR && \	len >= cilen && \	p[0] == opt) { \	u_int32_t l; \	len -= cilen; \	INCPTR(2, p); \	GETLONG(l, p); \	cilong = htonl(l); \	/* Check rejected value. */ \	if (cilong != val) \	    goto bad; \	try.neg = 0; \    }#define REJCIDNS(opt, neg, dnsaddr) \    if (go->neg && \	((cilen = p[1]) == CILEN_ADDR) && \	len >= cilen && \	p[0] == opt) { \	u_int32_t l; \	len -= cilen; \	INCPTR(2, p); \	GETLONG(l, p); \	cilong = htonl(l); \	/* Check rejected value. */ \	if (cilong != dnsaddr) \	    goto bad; \	try.neg = 0; \    }    REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,	       go->ouraddr, go->hisaddr);    REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,	    go->maxslotindex, go->cflag);    REJCIADDR(CI_ADDR, neg_addr, go->ouraddr);    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(("ipcp_rejci: received bad Reject!"));    return 0;}/* * ipcp_reqci - Check the peer's requested CIs and send appropriate response. * Callback from fsm_rconfreq, Receive Configure Request * * 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 intipcp_reqci(f, inp, len, reject_if_disagree)    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];    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, ciaddr2;/* Parsed address values */    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;    /*     * 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(("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 */	case CI_ADDRS:	    if (!ao->old_addrs || ho->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);	    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);	    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 {		    wo->ouraddr = ciaddr2;	/* accept peer's idea */		}	    }	    ho->old_addrs = 1;	    ho->hisaddr = ciaddr1;	    ho->ouraddr = ciaddr2;	    break;	case CI_ADDR:	    if (!ao->neg_addr || ho->old_addrs ||		cilen != CILEN_ADDR) {	/* 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);	    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) {		/*		 * Don't ACK an address of 0.0.0.0 - reject it instead.		 */		orc = CONFREJ;		wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */		break;	    }		    ho->neg_addr = 1;	    ho->hisaddr = 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 */		orc = CONFREJ;		/* Reject CI */		break;	    }	    GETLONG(tl, p);	    if (htonl(tl) != ao->dnsaddr[d]) {                DECPTR(sizeof(u_int32_t), p);		tl = ntohl(ao->dnsaddr[d]);		PUTLONG(tl, p);		orc = CONFNAK;            }            break;	case CI_MS_WINS1:	case CI_MS_WINS2:	    /* Microsoft primary or secondary WINS request */	    d = citype == CI_MS_WINS2;	    /* 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 ||		(cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {		orc = CONFREJ;		break;	    }	    GETSHORT(cishort, p);	    if (!(cishort == IPCP_VJ_COMP ||		  (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {		orc = CONFREJ;		break;	    }	    ho->neg_vj = 1;	    ho->vj_protocol = cishort;	    if (cilen == CILEN_VJ) {		GETCHAR(maxslotindex, p);		if (maxslotindex > ao->maxslotindex) { 		    orc = CONFNAK;		    if (!reject_if_disagree){			DECPTR(1, p);			PUTCHAR(ao->maxslotindex, p);		    }		}		GETCHAR(cflag, p);		if (cflag && !ao->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_STATES - 1;		ho->cflag = 1;	    }	    break;	default:	    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? */		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 && !ho->old_addrs &&	wo->req_addr && !reject_if_disagree) {	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 = ucp - inp;			/* Compute output length */    IPCPDEBUG(("ipcp: 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 voidip_check_options(){    struct hostent *hp;    u_int32_t local;    ipcp_options *wo = &ipcp_wantoptions[0];    /*     * Default our local IP address based on our hostname.     * If local IP address already given, don't bother.     */    if (wo->ouraddr == 0 && !disable_defaultip) {	/*	 * Look up our hostname (possibly with domain name appended)	 * and take the first IP address as our local IP address.	 * If there isn't an IP address for our hostname, too bad.	 */	wo->accept_local = 1;	/* don't insist on this default value */	if ((hp = gethostbyname(hostname)) != NULL) {	    local = *(u_int32_t *)hp->h_addr;	    if (local != 0 && !bad_ip_adrs(local))		wo->ouraddr = local;	}    }    ask_for_local = wo->ouraddr != 0 || !disable_defaultip;}/* * ip_demand_conf - configure the interface as though * IPCP were up, for use with dial-on-demand. */static intip_demand_conf(u)    int u;{    ipcp_options *wo = &ipcp_wantoptions[u];    if (wo->hisaddr == 0) {	/* make up an arbitrary address for the peer */	wo->hisaddr = htonl(0x0a707070 + ifunit);	wo->accept_remote = 1;    }    if (wo->ouraddr == 0) {	/* make up an arbitrary address for us */	wo->ouraddr = htonl(0x0a404040 + ifunit);	wo->accept_local = 1;	ask_for_local = 0;	/* don't tell the peer this address */    }

⌨️ 快捷键说明

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