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

📄 ipcp.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
		  (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 &&	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) {	/*	 * 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;	}    }}/* * 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 + pppifunit);	wo->accept_remote = 1;    }    if (wo->ouraddr == 0) {	/* make up an arbitrary address for us */	wo->ouraddr = htonl(0x0a404040 + pppifunit);	wo->accept_local = 1;	disable_defaultip = 1;	/* don't tell the peer this address */    }    if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))	return 0;    if (!sifup(u))	return 0;    if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))	return 0;    if (wo->default_route)	if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))	    default_route_set[u] = 1;    if (wo->proxy_arp)	if (sifproxyarp(u, wo->hisaddr))	    proxy_arp_set[u] = 1;    notice("local  IP address %I", wo->ouraddr);    notice("remote IP address %I", wo->hisaddr);    return 1;}/* * ipcp_up - IPCP has come UP. * * Configure the IP network interface appropriately and bring it up. */static voidipcp_up(f)    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];    IPCPDEBUG(("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) {	error("Could not determine remote IP address");	ipcp_close(f->unit, "Could not determine remote IP address");	return;    }    if (go->ouraddr == 0) {	error("Could not determine local IP address");	ipcp_close(f->unit, "Could not determine local IP address");	return;    }    if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {	create_resolv(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)) {	error("Peer is not authorized to use remote address %I", ho->hisaddr);	ipcp_close(f->unit, "Unauthorized remote IP address");	return;    }    /* set tcp compression */    sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);    /*     * If we are doing dial-on-demand, the interface is already     * configured, so we put out any saved-up packets, then set the     * interface to pass IP packets.     */    if (demand) {	if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {	    ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);	    if (go->ouraddr != wo->ouraddr) {		warn("Local IP address changed to %I", go->ouraddr);		wo->ouraddr = go->ouraddr;	    }	    if (ho->hisaddr != wo->hisaddr) {		warn("Remote IP address changed to %I", ho->hisaddr);		wo->hisaddr = ho->hisaddr;	    }	    /* Set the interface to the new addresses */	    mask = GetMask(go->ouraddr);	    if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {		if (debug)		    warn("Interface configuration failed");		ipcp_close(f->unit, "Interface configuration failed");		return;	    }	    /* 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;	    /* Make a proxy ARP entry if requested. */	    if (ipcp_wantoptions[f->unit].proxy_arp)		if (sifproxyarp(f->unit, ho->hisaddr))		    proxy_arp_set[f->unit] = 1;	}	demand_rexmit(PPP_IP);	sifnpmode(f->unit, PPP_IP, NPMODE_PASS);    } else {	/*	 * 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)) {	    if (debug)		warn("Interface configuration failed");	    ipcp_close(f->unit, "Interface configuration failed");	    return;	}#endif	/* bring the interface up for IP */	if (!sifup(f->unit)) {	    if (debug)		warn("Interface failed to come up");	    ipcp_close(f->unit, "Interface configuration failed");	    return;	}#if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {	    if (debug)		warn("Interface configuration 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;	/* Make a proxy ARP entry if requested. */	if (ipcp_wantoptions[f->unit].proxy_arp)	    if (sifproxyarp(f->unit, ho->hisaddr))		proxy_arp_set[f->unit] = 1;	ipcp_wantoptions[0].ouraddr = go->ouraddr;	notice("local  IP address %I", go->ouraddr);	notice("remote IP address %I", ho->hisaddr);	if (go->dnsaddr[0])	    notice("primary   DNS address %I", go->dnsaddr[0]);	if (go->dnsaddr[1])	    notice("secondary DNS address %I", go->dnsaddr[1]);    }    np_up(f->unit, PPP_IP);    ipcp_is_up = 1;    if (ip_up_hook)	ip_up_hook();}/* * ipcp_down - IPCP has gone DOWN. * * Take the IP network interface down, clear its addresses * and delete routes through it. */static voidipcp_down(f)    fsm *f;{    IPCPDEBUG(("ipcp: down"));    /* XXX a bit IPv4-centric here, we only need to get the stats     * before the interface is marked down. */    update_link_stats(f->unit);    if (ip_down_hook)	ip_down_hook();    if (ipcp_is_up) {	ipcp_is_up = 0;	np_down(f->unit, PPP_IP);    }    sifvjcomp(f->unit, 0, 0, 0);    /*     * If we are doing dial-on-demand, set the interface     * to queue up outgoing packets (for now).     */    if (demand) {	sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);    } else {	sifnpmode(f->unit, PPP_IP, NPMODE_DROP);	sifdown(f->unit);	ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,			 ipcp_hisoptions[f->unit].hisaddr);    }}/* * ipcp_clear_addrs() - clear the interface addresses, routes, * proxy arp entries, etc. */static voidipcp_clear_addrs(unit, ouraddr, hisaddr)    int unit;    u_int32_t ouraddr;  /* local address */    u_int32_t hisaddr;  /* remote address */{    if (proxy_arp_set[unit]) {	cifproxyarp(unit, hisaddr);	proxy_arp_set[unit] = 0;    }    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 voidipcp_finished(f)    fsm *f;{    np_finished(f->unit, PPP_IP);}/* * create_resolv - create the replacement resolv.conf file */static voidcreate_resolv(peerdns1, peerdns2)    u_int32_t peerdns1, peerdns2;{  extern int              rtems_bsdnet_nameserver_count;  extern struct in_addr   rtems_bsdnet_nameserver[];  /* initialize values */  rtems_bsdnet_nameserver_count = (int)0;  /* check to see if primary was specified */  if ( peerdns1 ) {    rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count].s_addr = peerdns1;    rtems_bsdnet_nameserver_count++;  }  /* check to see if secondary was specified */  if ( peerdns2 ) {    rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count].s_addr = peerdns2;    rtems_bsdnet_nameserver_count++;  }  /* initialize resolver */  __res_init();}/* * ipcp_printpkt - print the contents of an IPCP packet. */static char *ipcp_codenames[] = {    "ConfReq", "ConfAck", "ConfNak", "ConfRej",    "TermReq", "TermAck", "CodeRej"};static intipcp_printpkt(p, plen, printer, arg)    u_char *p;    int plen;    void (*printer) __P((void *, char *, ...));    void *arg;{    int code, id, len, olen;    u_char *pstart, *optend;    u_short cishort;    u_int32_t cilong;    if (plen < HEADERLEN)	return 0;    pstart = p;    GETCHAR(code, p);    GETCHAR(id, p);    GETSHORT(len, p);    if (len < HEADERLEN || len > plen)	return 0;    if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))	printer(arg, " %s", ipcp_codenames[code-1]);    else	printer(arg, " code=0x%x", code);    printer(arg, " id=0x%x", id);    len -= HEADERLEN;    switch (code) {    case CONFREQ:    case CONFACK:    case CONFNAK:    case CONFREJ:	/* print option list */	while (len >= 2) {	    GETCHAR(code, p);	    GETCHAR(olen, p);	    p -= 2;	    if (olen < 2 || olen > len) {		break;	    }	    printer(arg, " <");	    len -= olen;	    optend = p + olen;	    switch (code) {	    case CI_ADDRS:		if (olen == CILEN_ADDRS) {		    p += 2;		    GETLONG(cilong, p);		    printer(arg, "addrs %I", htonl(cilong));		    GETLONG(cilong, p);		    printer(arg, " %I", htonl(cilong));		}		break;	    case CI_COMPRESSTYPE:		if (olen >= CILEN_COMPRESS) {		    p += 2;		    GETSHORT(cishort, p);		    printer(arg, "compress ");		    switch (cishort) {		    case IPCP_VJ_COMP:			printer(arg, "VJ");			break;		    case IPCP_VJ_COMP_OLD:			printer(arg, "old-VJ");			break;		    default:			printer(arg, "0x%x", cishort);		    }		}		break;	    case CI_ADDR:		if (olen == CILEN_ADDR) {		    p += 2;		    GETLONG(cilong, p);		    printer(arg, "addr %I", htonl(cilong));		}		break;	    case CI_MS_DNS1:	    case CI_MS_DNS2:	        p += 2;		GETLONG(cilong, p);		printer(arg, "ms-dns%d %I", code - CI_MS_DNS1 + 1,			htonl(cilong));		break;	    case CI_MS_WINS1:	    case CI_MS_WINS2:	        p += 2;		GETLONG(cilong, p);		printer(arg, "ms-wins %I", htonl(cilong));		break;	    }	    while (p < optend) {		GETCHAR(code, p);		printer(arg, " %.2x", code);	    }	    printer(arg, ">");	}	break;    case TERMACK:    case TERMREQ:	if (len > 0 && *p >= ' ' && *p < 0x7f) {	    printer(arg, " ");	    print_string(p, len, printer, arg);	    p += len;	    len = 0;	}	break;    }    /* print the rest of the bytes in the packet */    for (; len > 0; --len) {	GETCHAR(code, p);	printer(arg, " %.2x", code);    }    return p - pstart;}/* * 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 intip_active_pkt(pkt, len)    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 + -