/* * Peer doesn't speak this protocol. * * Treat this as a catastrophic error (RXJ-). */ void LcpRxProtRej(NUTDEVICE * dev) { PPPDCB *dcb = dev->dev_dcb; switch (dcb->dcb_lcp_state) { case PPPS_CLOSING: case PPPS_CLOSED: dcb->dcb_lcp_state = PPPS_CLOSED; break; case PPPS_STOPPING: case PPPS_REQSENT: case PPPS_ACKRCVD: case PPPS_ACKSENT: case PPPS_STOPPED: dcb->dcb_lcp_state = PPPS_STOPPED; break; case PPPS_OPENED: IpcpLowerDown(dev); NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0); dcb->dcb_lcp_state = PPPS_STOPPING; break; } }
/* * \brief Terminate request received. */ static void IpcpRxTermReq(NUTDEVICE * dev, uint8_t id, NETBUF * nb) { PPPDCB *dcb = dev->dev_dcb; NutNetBufFree(nb); switch (dcb->dcb_ipcp_state) { case PPPS_ACKRCVD: case PPPS_ACKSENT: dcb->dcb_ipcp_state = PPPS_REQSENT; break; case PPPS_OPENED: IpcpLowerDown(dev); dcb->dcb_ipcp_state = PPPS_STOPPING; break; } NutIpcpOutput(dev, XCP_TERMACK, id, 0); }
/* * Received Configure-Request. */ static void IpcpRxConfReq(NUTDEVICE * dev, uint8_t id, NETBUF * nb) { PPPDCB *dcb = dev->dev_dcb; int rc = XCP_CONFACK; XCPOPT *xcpo; uint16_t xcpl; XCPOPT *xcpr; uint16_t xcps; uint16_t len = 0; uint_fast8_t i; uint32_t ip; switch (dcb->dcb_ipcp_state) { case PPPS_CLOSED: /* * Go away, we're closed. */ NutNetBufFree(nb); NutIpcpOutput(dev, XCP_TERMACK, id, 0); return; case PPPS_CLOSING: case PPPS_STOPPING: /* * Ignore if we are going down. */ NutNetBufFree(nb); return; case PPPS_OPENED: /* * Go down and restart negotiation. */ IpcpLowerDown(dev); IpcpTxConfReq(dev, ++dcb->dcb_reqid); break; case PPPS_STOPPED: /* * Negotiation started by our peer. */ IpcpTxConfReq(dev, ++dcb->dcb_reqid); dcb->dcb_ipcp_state = PPPS_REQSENT; break; } /* * Check if there is anything to reject. */ xcpo = nb->nb_ap.vp; xcpl = nb->nb_ap.sz; xcpr = nb->nb_ap.vp; xcps = 0; while (xcpl >= 2) { len = xcpo->xcpo_len; if (len > xcpl) len = xcpl; else { switch (xcpo->xcpo_type) { case IPCP_MS_DNS1: if (xcpo->xcpo_.ul == 0 && dcb->dcb_ip_dns1 == 0) { break; } case IPCP_MS_DNS2: if (xcpo->xcpo_.ul == 0 && dcb->dcb_ip_dns2 == 0) { break; } case IPCP_ADDR: if (xcpo->xcpo_len == 6) len = 0; break; } } if (len) { if (xcpr != xcpo) { xcpr->xcpo_type = xcpo->xcpo_type; xcpr->xcpo_len = len; for (i = 0; i < len - 2; i++) xcpr->xcpo_.uc[i] = xcpo->xcpo_.uc[i]; } xcpr = (XCPOPT *) ((char *) xcpr + len); xcps += len; } xcpl -= xcpo->xcpo_len; xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len); } if (xcps) { nb->nb_ap.sz = xcps; rc = XCP_CONFREJ; } /* * Check if there is anything to negotiate. */ else { xcpo = nb->nb_ap.vp; xcpl = nb->nb_ap.sz; xcpr = nb->nb_ap.vp; xcps = 0; len = 0; while (xcpl >= 2) { ip = xcpo->xcpo_.ul; switch (xcpo->xcpo_type) { case IPCP_ADDR: len = IpcpValidateIpReq(&dcb->dcb_remote_ip, &ip); break; case IPCP_MS_DNS1: len = IpcpValidateIpReq(&dcb->dcb_ip_dns1, &ip); break; case IPCP_MS_DNS2: len = IpcpValidateIpReq(&dcb->dcb_ip_dns2, &ip); break; } if (len) { if (xcpr != xcpo) { xcpr->xcpo_type = xcpo->xcpo_type; xcpr->xcpo_len = len; } xcpr->xcpo_.ul = ip; xcpr = (XCPOPT *) ((char *) xcpr + len); xcps += len; len = 0; } xcpl -= xcpo->xcpo_len; xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len); } if (xcps) { nb->nb_ap.sz = xcps; rc = XCP_CONFNAK; } } NutIpcpOutput(dev, rc, id, nb); if (rc == XCP_CONFACK) { if (dcb->dcb_ipcp_state == PPPS_ACKRCVD) { dcb->dcb_ipcp_state = PPPS_OPENED; NutEventPost(&dcb->dcb_state_chg); } else dcb->dcb_ipcp_state = PPPS_ACKSENT; dcb->dcb_ipcp_naks = 0; } else if (dcb->dcb_ipcp_state != PPPS_ACKRCVD) dcb->dcb_ipcp_state = PPPS_REQSENT; }
/* * Configure-Nak or Configure-Reject received. */ static void IpcpRxConfNakRej(NUTDEVICE * dev, uint8_t id, NETBUF * nb, uint8_t rejected) { PPPDCB *dcb = dev->dev_dcb; XCPOPT *xcpo; uint16_t xcpl; /* * Ignore, if we are not expecting this id. */ if (id != dcb->dcb_reqid || dcb->dcb_acked) { NutNetBufFree(nb); return; } switch (dcb->dcb_ipcp_state) { case PPPS_CLOSED: case PPPS_STOPPED: /* * Go away, we're closed. */ NutNetBufFree(nb); NutIpcpOutput(dev, XCP_TERMACK, id, 0); return; case PPPS_REQSENT: case PPPS_ACKSENT: case PPPS_ACKRCVD: case PPPS_OPENED: break; default: NutNetBufFree(nb); return; } dcb->dcb_acked = 1; xcpo = nb->nb_ap.vp; xcpl = nb->nb_ap.sz; while (xcpl >= 2) { switch (xcpo->xcpo_type) { case IPCP_ADDR: if (xcpo->xcpo_.ul) dcb->dcb_local_ip = xcpo->xcpo_.ul; break; case IPCP_COMPRESSTYPE: break; case IPCP_MS_DNS1: if (rejected) dcb->dcb_rejects |= REJ_IPCP_DNS1; else if (xcpo->xcpo_.ul) dcb->dcb_ip_dns1 = xcpo->xcpo_.ul; break; case IPCP_MS_DNS2: if (rejected) dcb->dcb_rejects |= REJ_IPCP_DNS2; else if (xcpo->xcpo_.ul) dcb->dcb_ip_dns2 = xcpo->xcpo_.ul; break; } xcpl -= xcpo->xcpo_len; xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len); } NutNetBufFree(nb); switch (dcb->dcb_ipcp_state) { case PPPS_REQSENT: case PPPS_ACKSENT: /* They didn't agree to what we wanted - try another request */ IpcpTxConfReq(dev, ++dcb->dcb_reqid); break; case PPPS_ACKRCVD: /* Got a Nak/reject when we had already had an Ack?? oh well... */ IpcpTxConfReq(dev, ++dcb->dcb_reqid); dcb->dcb_ipcp_state = PPPS_REQSENT; break; case PPPS_OPENED: /* Go down and restart negotiation */ IpcpLowerDown(dev); IpcpTxConfReq(dev, ++dcb->dcb_reqid); dcb->dcb_ipcp_state = PPPS_REQSENT; break; } }
/* * Configure-Ack received. */ static void IpcpRxConfAck(NUTDEVICE * dev, uint8_t id, NETBUF * nb) { PPPDCB *dcb = dev->dev_dcb; XCPOPT *xcpo; uint16_t xcpl; /* * Ignore, if we are not expecting this id. */ if (id != dcb->dcb_reqid || dcb->dcb_acked) { return; } switch (dcb->dcb_ipcp_state) { case PPPS_CLOSED: case PPPS_STOPPED: /* * Go away, we're closed. */ NutNetBufFree(nb); NutIpcpOutput(dev, XCP_TERMACK, id, 0); return; case PPPS_REQSENT: dcb->dcb_ipcp_state = PPPS_ACKRCVD; dcb->dcb_retries = 0; break; case PPPS_ACKRCVD: /* Huh? an extra valid Ack? oh well... */ IpcpTxConfReq(dev, ++dcb->dcb_reqid); dcb->dcb_ipcp_state = PPPS_REQSENT; break; case PPPS_ACKSENT: dcb->dcb_ipcp_state = PPPS_OPENED; dcb->dcb_retries = 0; NutEventPost(&dcb->dcb_state_chg); break; case PPPS_OPENED: /* Go down and restart negotiation */ IpcpLowerDown(dev); IpcpTxConfReq(dev, ++dcb->dcb_reqid); dcb->dcb_ipcp_state = PPPS_REQSENT; break; } xcpo = nb->nb_ap.vp; xcpl = nb->nb_ap.sz; while (xcpl >= 2) { switch (xcpo->xcpo_type) { case IPCP_ADDR: if (xcpo->xcpo_.ul) dcb->dcb_local_ip = xcpo->xcpo_.ul; break; case IPCP_COMPRESSTYPE: break; case IPCP_MS_DNS1: if (xcpo->xcpo_.ul) dcb->dcb_ip_dns1 = xcpo->xcpo_.ul; break; case IPCP_MS_DNS2: /* Fixed secondary DNS bug, thanks to Tarmo Fimberg and Jelle Martijn Kok. */ if (xcpo->xcpo_.ul) dcb->dcb_ip_dns2 = xcpo->xcpo_.ul; break; } xcpl -= xcpo->xcpo_len; xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len); } dcb->dcb_acked = 1; NutNetBufFree(nb); }