📄 ipcp.c
字号:
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 + -