/* * 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; } }
/* * Configure-Nak or Configure-Reject received. */ static void LcpRxConfNakRej(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; } /* * TODO: Process acked options. */ dcb->dcb_acked = 1; xcpo = nb->nb_ap.vp; xcpl = nb->nb_ap.sz; while (xcpl >= 2) { xcpl -= xcpo->xcpo_len; xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len); } NutNetBufFree(nb); switch (dcb->dcb_lcp_state) { case PPPS_CLOSED: case PPPS_STOPPED: /* * Go away, we're closed. */ NutLcpOutput(dev, XCP_TERMACK, id, 0); break; case PPPS_REQSENT: case PPPS_ACKSENT: /* They didn't agree to what we wanted - try another request */ LcpTxConfReq(dev, ++dcb->dcb_reqid, rejected); break; case PPPS_ACKRCVD: /* Got a Nak/reject when we had already had an Ack?? oh well... */ LcpTxConfReq(dev, ++dcb->dcb_reqid, 0); dcb->dcb_lcp_state = PPPS_REQSENT; break; case PPPS_OPENED: /* * Go down and restart negotiation. */ IpcpLowerDown(dev); LcpTxConfReq(dev, ++dcb->dcb_reqid, 0); dcb->dcb_lcp_state = PPPS_REQSENT; break; } }
void PapRxAuthNak(NUTDEVICE *dev, uint8_t id, NETBUF *nb) { PPPDCB *dcb = dev->dev_dcb; if(dcb->dcb_auth_state == PAPCS_AUTHREQ) { dcb->dcb_auth_state = PAPCS_BADAUTH; IpcpLowerDown(dev); } }
/* * \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); }
/* * Terminate-Ack received. */ static void IpcpRxTermAck(NUTDEVICE * dev, uint8_t id, NETBUF * nb) { PPPDCB *dcb = dev->dev_dcb; switch (dcb->dcb_ipcp_state) { case PPPS_CLOSING: dcb->dcb_ipcp_state = PPPS_CLOSED; break; case PPPS_STOPPING: dcb->dcb_ipcp_state = PPPS_STOPPED; break; case PPPS_ACKRCVD: dcb->dcb_ipcp_state = PPPS_REQSENT; break; case PPPS_OPENED: IpcpLowerDown(dev); IpcpTxConfReq(dev, ++dcb->dcb_reqid); break; } }
/* * Configure-Ack received. * Never called in INITIAL or STARTING phase. */ static void LcpRxConfAck(NUTDEVICE * dev, uint8_t id, NETBUF * nb) { PPPDCB *dcb = dev->dev_dcb; XCPOPT *xcpo; uint16_t xcpl; /* * Check if this is a valid ack. */ if (id == dcb->dcb_reqid && dcb->dcb_acked == 0) { dcb->dcb_acked = 1; xcpo = nb->nb_ap.vp; xcpl = nb->nb_ap.sz; while (xcpl >= 2) { switch (xcpo->xcpo_type) { case LCP_MRU: if (htons(xcpo->xcpo_.us) != 1500) dcb->dcb_acked = 0; break; case LCP_ASYNCMAP: //if(ntohl(xcpo->xcpo_.ul) != ) // dcb->dcb_acked = 0; break; case LCP_AUTHTYPE: if (htons(xcpo->xcpo_.us) != dcb->dcb_auth) dcb->dcb_acked = 0; break; case LCP_MAGICNUMBER: if (xcpo->xcpo_.ul == dcb->dcb_neg_magic) { dcb->dcb_loc_magic = dcb->dcb_neg_magic; } else { dcb->dcb_acked = 0; } break; case LCP_PCOMPRESSION: dcb->dcb_acked = 0; break; case LCP_ACCOMPRESSION: dcb->dcb_acked = 0; break; } xcpl -= xcpo->xcpo_len; xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len); } } /* * We don't need the NETBUF any more. */ NutNetBufFree(nb); /* * Ignore invalid acks. */ if (dcb->dcb_acked == 0) return; switch (dcb->dcb_lcp_state) { case PPPS_CLOSED: case PPPS_STOPPED: /* * Go away, we're closed. */ NutLcpOutput(dev, XCP_TERMACK, id, 0); break; case PPPS_REQSENT: dcb->dcb_lcp_state = PPPS_ACKRCVD; dcb->dcb_retries = 0; break; case PPPS_ACKRCVD: LcpTxConfReq(dev, ++dcb->dcb_reqid, 0); dcb->dcb_lcp_state = PPPS_REQSENT; break; case PPPS_ACKSENT: /* * ACK sent and ACK received. */ dcb->dcb_lcp_state = PPPS_OPENED; if (dcb->dcb_auth == PPP_PAP) PapTxAuthReq(dev, ++dcb->dcb_reqid); else IpcpLowerUp(dev); break; case PPPS_OPENED: /* * Go down and restart negotiation. */ IpcpLowerDown(dev); LcpTxConfReq(dev, ++dcb->dcb_reqid, 0); dcb->dcb_lcp_state = PPPS_REQSENT; break; } }
/* * Received Configure-Request. */ static void LcpRxConfReq(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; uint16_t sval; uint_fast8_t i; switch (dcb->dcb_lcp_state) { case PPPS_CLOSED: /* * Go away, we're closed. */ NutNetBufFree(nb); NutLcpOutput(dev, XCP_TERMACK, id, 0); return; case PPPS_CLOSING: case PPPS_STOPPING: /* * Silently ignore configuration requests while going down. */ NutNetBufFree(nb); return; case PPPS_OPENED: /* * Go down and restart negotiation. */ IpcpLowerDown(dev); LcpTxConfReq(dev, ++dcb->dcb_reqid, 0); break; case PPPS_STOPPED: /* * Negotiation started by our peer. */ LcpTxConfReq(dev, ++dcb->dcb_reqid, 0); dcb->dcb_lcp_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 LCP_MRU: if (xcpo->xcpo_len == 4) len = 0; break; case LCP_MAGICNUMBER: case LCP_ASYNCMAP: if (xcpo->xcpo_len == 6) len = 0; break; case LCP_AUTHTYPE: if (xcpo->xcpo_len >= 4) len = 0; break; case LCP_PCOMPRESSION: len = 0; break; case LCP_ACCOMPRESSION: 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++) /* bug fix by Michel Hendriks. Thanks! */ 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) { switch (xcpo->xcpo_type) { case LCP_MRU: if ((sval = htons(xcpo->xcpo_.us)) < MIN_LCPMRU) { len = 4; xcpr->xcpo_.us = ntohs(MIN_LCPMRU); } else dcb->dcb_rem_mru = sval; break; case LCP_ASYNCMAP: dcb->dcb_accm = ntohl(xcpo->xcpo_.ul); break; case LCP_AUTHTYPE: if (htons(xcpo->xcpo_.us) != PPP_PAP) { len = 4; xcpr->xcpo_.us = htons(PPP_PAP); } break; case LCP_MAGICNUMBER: if (xcpo->xcpo_.ul == dcb->dcb_loc_magic || xcpo->xcpo_.ul == dcb->dcb_neg_magic) { dcb->dcb_rem_magic = new_magic; len = 6; xcpr->xcpo_.ul = dcb->dcb_rem_magic; } break; case LCP_PCOMPRESSION: dcb->dcb_compr |= PPP_PFC; break; case LCP_ACCOMPRESSION: dcb->dcb_compr |= PPP_ACFC; break; } if (len) { if (xcpr != xcpo) { xcpr->xcpo_type = xcpo->xcpo_type; xcpr->xcpo_len = len; } 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; } } NutLcpOutput(dev, rc, id, nb); if (rc == XCP_CONFACK) { if (dcb->dcb_lcp_state == PPPS_ACKRCVD) { dcb->dcb_lcp_state = PPPS_OPENED; if (dcb->dcb_auth == PPP_PAP) PapTxAuthReq(dev, ++dcb->dcb_reqid); else IpcpLowerUp(dev); } else dcb->dcb_lcp_state = PPPS_ACKSENT; dcb->dcb_lcp_naks = 0; } else if (dcb->dcb_lcp_state != PPPS_ACKRCVD) dcb->dcb_lcp_state = PPPS_REQSENT; }
/* * 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); }