/* * ipcp_ackci - Ack our CIs. * Called by fsm_rconfack, Receive Configure ACK. * * Returns: * 0 - Ack was bad. * 1 - Ack was good. */ static int ipcp_ackci( fsm *f, u_char *p, int len) { ipcp_options *go = &ipcp_gotoptions[f->unit]; u_short cilen, citype, cishort; uint32_t cilong; u_char cimaxslotindex, cicflag; /* * 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 ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ if (neg) { \ int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ if ((len -= vjlen) < 0) \ goto bad; \ GETCHAR(citype, p); \ GETCHAR(cilen, p); \ if (cilen != vjlen || \ citype != opt) \ goto bad; \ GETSHORT(cishort, p); \ if (cishort != val) \ goto bad; \ if (!old) { \ GETCHAR(cimaxslotindex, p); \ if (cimaxslotindex != maxslotindex) \ goto bad; \ GETCHAR(cicflag, p); \ if (cicflag != cflag) \ goto bad; \ } \ } #define ACKCIADDR(opt, neg, old, val1, val2) \ if (neg) { \ int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ uint32_t l; \ if ((len -= addrlen) < 0) \ goto bad; \ GETCHAR(citype, p); \ GETCHAR(cilen, p); \ if (cilen != addrlen || \ citype != opt) \ goto bad; \ GETLONG(l, p); \ cilong = htonl(l); \ if (val1 != cilong) \ goto bad; \ if (old) { \ GETLONG(l, p); \ cilong = htonl(l); \ if (val2 != cilong) \ goto bad; \ } \ } #define ACKCIDNS(opt, neg, addr) \ if (neg) { \ uint32_t l; \ if ((len -= CILEN_ADDR) < 0) \ goto bad; \ GETCHAR(citype, p); \ GETCHAR(cilen, p); \ if (cilen != CILEN_ADDR || citype != opt) \ goto bad; \ GETLONG(l, p); \ cilong = htonl(l); \ if (addr != cilong) \ goto bad; \ } ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, go->old_addrs, go->ouraddr, go->hisaddr); ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, go->maxslotindex, go->cflag); ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); /* * If there are any remaining CIs, then this packet is bad. */ if (len != 0) goto bad; return (1); bad: IPCPDEBUG(("ipcp_ackci: received bad Ack!")); return (0); }
//****************************************************************************** // Parse DNS address from ipconfig options //****************************************************************************** Boolean Capi2ReadDnsSrv( PCHProtConfig_t *ipcnfg, u_long* primaryDns1, u_long* secDns1, u_long* primaryDns2, u_long* secDns2) { u_char *input; u_char code, id, len_pid; u_short protocol; int len, t_len; int i=0; int type, templ; u_long DNSsrvr; u_long l; *primaryDns1 = 0; *secDns1 = 0; *primaryDns2 = 0; *secDns2 = 0; IPCPDEBUG(("ReadDnsSrv, read dns_servers")); /* if option length == 2, no option data */ if (ipcnfg->length == 0) { IPCPDEBUG(("Network ignored protocol options")); /* (Not an error, network does not want to bother) */ return TRUE; } len = 0; if (( ipcnfg->options[len++] & 0x83 ) == 0x81) { IPCPDEBUG(("Bad protocol config option")); return FALSE; } t_len = len; while ( t_len < (ipcnfg->length) ) { input = (u_char *) &ipcnfg->options[t_len]; GETSHORT(protocol, input); GETCHAR(len_pid, input); GETCHAR(code, input); GETCHAR(id, input); GETSHORT(len, input); switch (protocol) { /* Check LCP option from the Network */ case PPP_LCP: break; /* Check IPCP option from the Network */ case PPP_IPCP: if ( code == CONFREQ ) { IPCPDEBUG((" ReadOptions: CONFREQ")); i=0; while (i<(len-4)) { GETCHAR(type, input); //RFC 1661, this is option type GETCHAR(templ, input); //RFC 1661, next byte is length GETLONG(l, input); //read but don't use i += templ; } } else if ( code == CONFACK || code == CONFNAK ) { IPCPDEBUG((" ReadOptions: CONFACK or CONFNAK")); i=0; while (i<(len-4)) { GETCHAR(type, input); //RFC 1661, this is option type GETCHAR(templ, input); //RFC 1661, next byte is length switch (type) { case CI_ADDR: GETLONG(l, input); IPCPDEBUG(("CI_ADDR")); break; case CI_DNSADDR_PRI: GETLONG(l, input); DNSsrvr = htonl(l); *primaryDns1 = DNSsrvr; IPCPDEBUG(("CI_DNSADDR_PRI =%x", DNSsrvr)); break; case (CI_DNSADDR_PRI+1): GETLONG(l, input); DNSsrvr = htonl(l); *primaryDns2 = DNSsrvr; IPCPDEBUG(("CI_DNSADDR_PRI =%x", DNSsrvr)); break; case CI_DNSADDR_SEC: GETLONG(l, input); DNSsrvr = htonl(l); *secDns1 = DNSsrvr; IPCPDEBUG(("CI_DNSADDR_SEC")); break; case (CI_DNSADDR_SEC+1): GETLONG(l, input); DNSsrvr = htonl(l); *secDns2 = DNSsrvr; IPCPDEBUG(("CI_DNSADDR_SEC")); break; default: break; } i += templ; } } else /* Network had rejected */ { while(i<(len-4)) { GETCHAR(type, input); GETCHAR(templ, input); switch (type) { case CI_DNSADDR_PRI: IPCPDEBUG(("CI_DNSADDR_PRI rejected")); break; case (CI_DNSADDR_PRI+1): IPCPDEBUG(("CI_DNSADDR_PRI+1 rejected")); break; case CI_DNSADDR_SEC: IPCPDEBUG(("CI_DNSADDR_SEC rejected")); break; case (CI_DNSADDR_SEC+1): // Not supported IPCPDEBUG(("CI_DNSADDR_SEC+1 rejected")); break; default: break; } i += templ; } IPCPDEBUG((" ReadOptions: IPCP REJed")); } break; default: break; } t_len += (len + 3); } return TRUE; }
/* * ipcp_nakci - Peer has sent a NAK for some of our CIs. * This should not modify any state if the Nak is bad * or if IPCP is in the OPENED state. * * Returns: * 0 - Nak was bad. * 1 - Nak was good. */ static int ipcp_nakci(fsm *f, u_char *p, int len) { ipcp_options *go = &ipcp_gotoptions[f->unit]; u_char cimaxslotindex, cicflag; u_char citype, cilen, *next; u_short cishort; u32_t ciaddr1, ciaddr2, l, cidnsaddr; ipcp_options no; /* options we've seen Naks for */ ipcp_options try; /* options to request next time */ BZERO(&no, sizeof(no)); try = *go; /* * Any Nak'd 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 NAKCIADDR(opt, neg, old, code) \ if (go->neg && \ len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ p[1] == cilen && \ p[0] == opt) { \ len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ ciaddr1 = htonl(l); \ if (old) { \ GETLONG(l, p); \ ciaddr2 = htonl(l); \ no.old_addrs = 1; \ } else \ ciaddr2 = 0; \ no.neg = 1; \ code \ } #define NAKCIVJ(opt, neg, code) \ if (go->neg && \ ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ len >= cilen && \ p[0] == opt) { \ len -= cilen; \ INCPTR(2, p); \ GETSHORT(cishort, p); \ no.neg = 1; \ code \ } #define NAKCIDNS(opt, neg, code) \ if (go->neg && \ ((cilen = p[1]) == CILEN_ADDR) && \ len >= cilen && \ p[0] == opt) { \ len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ cidnsaddr = htonl(l); \ no.neg = 1; \ code \ } /* * Accept the peer's idea of {our,his} address, if different * from our idea, only if the accept_{local,remote} flag is set. */ NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, if (go->accept_local && ciaddr1) { /* Do we know our address? */ try.ouraddr = ciaddr1; IPCPDEBUG((LOG_INFO, "local IP address %s\n", inet_ntoa(ciaddr1))); } if (go->accept_remote && ciaddr2) { /* Does he know his? */ try.hisaddr = ciaddr2; IPCPDEBUG((LOG_INFO, "remote IP address %s\n", inet_ntoa(ciaddr2))); } ); /* * Accept the peer's value of maxslotindex provided that it * is less than what we asked for. Turn off slot-ID compression * if the peer wants. Send old-style compress-type option if * the peer wants. */ NAKCIVJ(CI_COMPRESSTYPE, neg_vj, if (cilen == CILEN_VJ) { GETCHAR(cimaxslotindex, p); GETCHAR(cicflag, p); if (cishort == IPCP_VJ_COMP) { try.old_vj = 0; if (cimaxslotindex < go->maxslotindex) try.maxslotindex = cimaxslotindex; if (!cicflag) try.cflag = 0; } else { try.neg_vj = 0;
//****************************************************************************** // BuildIpConfigOptions //****************************************************************************** void BuildIpConfigOptions(PCHProtConfig_t *ip_cnfg, IPConfigAuthType_t authType, CHAP_ChallengeOptions_t *cc, CHAP_ResponseOptions_t *cr, PAP_CnfgOptions_t *po) { int len, i, tlen; u_char *outp, *lenp, *len_pid; u_long dnsaddr_pri; u_long dnsaddr_sec; u_short IPCP_prot = PPP_IPCP; u_short UPAP_prot = PPP_UPAP; u_short CHAP_prot = PPP_CHAP; u_long ipaddr = 0; u_long l; len = 0; //start at the top dnsaddr_pri = 0; dnsaddr_sec = 0; ip_cnfg->options[len++] = 0x80; /* octet2, Protocol Config Option, PPP for use with */ /** build Protocol Identifier, CHAP authentication (RFC 1994)*/ if(authType == REQUIRE_CHAP) { /* Send CHAP challenge packet here */ if ( cc->flag ) /* Request the network for CHAP authentication? */ { outp = (u_char *)&ip_cnfg->options[len]; PUTSHORT(CHAP_prot, outp); /* CHAP protocol */ len += 2; ip_cnfg->options[len++] = cc->len; /* Protocol ID length */ IPCPDEBUG(("Build Option: chap cc len=%d total=%d\n",cc->len,len)); for (i = 0; i < cc->len; i++) /* octet27, send PAP data */ ip_cnfg->options[len++] = cc->content[i]; /* octetm */ cc->flag = 0; /* Clear Request flag. We only do this once per request */ } /* Send CHAP response packet here */ if ( cr->flag ) /* Request the network for PAP authentication? */ { outp = (u_char *)&ip_cnfg->options[len]; PUTSHORT(CHAP_prot, outp); /* CHAP protocol */ len += 2; ip_cnfg->options[len++] = cr->len; /* Protocol ID length */ IPCPDEBUG(("Build Option: chap resp len=%d total=%d\n",cr->len,len)); for (i = 0; i < cr->len; i++) /* send PAP data */ ip_cnfg->options[len++] = cr->content[i]; cr->flag = 0; /* Clear Request flag. We only do this once per request */ } }/** done CHAP */ /** build Protocol Identifier, PAP authentication (RFC 1334)*/ if(authType == REQUIRE_PAP) { if ( po->flag ) /* Request the network for PAP authentication? */ { outp = (u_char *)&ip_cnfg->options[len]; PUTSHORT(UPAP_prot, outp); /* UPAP protocol */ len += 2; ip_cnfg->options[len++] = po->len; /* Protocol ID length */ IPCPDEBUG(("Build Option: pap len=%d total=%d\n",po->len,len)); for (i = 0; i < po->len; i++) /* send PAP data */ ip_cnfg->options[len++] = po->content[i]; po->flag = 0; /* Clear Request flag. We only do this once per request */ } /** done PAP */ } /** build Protocol Identifier, IPCP */ outp = (u_char *)&ip_cnfg->options[len++]; PUTSHORT(IPCP_prot, outp); /* IPCP protocol */ len += 1; len_pid = (u_char *)&ip_cnfg->options[len++]; /* Protocol ID length */ tlen = len; /* build code, id, length */ ip_cnfg->options[len++] = 1; /* configure-req */ ip_cnfg->options[len++] = 1; /* id */ lenp = (u_char *)&ip_cnfg->options[len++]; len++; /** build IPCP options 129 (RFC 1877)**/ IPCPDEBUG(("Build Option: PDNS")); ip_cnfg->options[len++] = CI_DNSADDR_PRI; ip_cnfg->options[len++] = 6; outp = (u_char *)&ip_cnfg->options[len]; l = ntohl(dnsaddr_pri); PUTLONG(l, outp); /* allow network to NAK and give us primary DNS server addr */ len += 4; /** build IPCP options 130 (RFC 1877)**/ IPCPDEBUG(("Build Option: SDNS")); ip_cnfg->options[len++] = CI_DNSADDR_SEC; ip_cnfg->options[len++] = 6; outp = (u_char *)&ip_cnfg->options[len]; l = ntohl(dnsaddr_sec); PUTLONG(ipaddr, outp); /* allow network to NAK and give us secondary DNS server addr*/ len += 4; tlen = len - tlen; PUTCHAR(tlen, len_pid); /* store Protocol ID length */ PUTSHORT(tlen, lenp); /* store IPCP length */ if (len > 1) ip_cnfg->length = len; /* Protocol Config Option length Config protocol octet */ else ip_cnfg->length = 0; /* If no options, length is zero as per discussion with Iulia */ /* --- DEBUG print --- */ /*---------------------------------------------------------------*/ IPCPDEBUG(("\r\nIP config options: %x", ip_cnfg->length)); for (i = 0; i < len; i++) IPCPDEBUG(("%x ",ip_cnfg->options[i])); /*---------------------------------------------------------------*/ }