00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 #include <net/if_var.h>
00083 #include <dev/ppp.h>
00084 #include <sys/types.h>
00085 #include <netinet/if_ppp.h>
00086 #include <netinet/ppp_fsm.h>
00087 #include <netinet/in.h>
00088 #include <string.h>
00089 #include <dev/usart.h>
00090 #include <io.h>
00091 
00097 
00098 extern uint32_t new_magic;
00099 
00100 
00101 
00102 
00103 static INLINE void LcpRxConfReq(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00104 {
00105     PPPDCB *dcb = dev->dev_dcb;
00106     int rc = XCP_CONFACK;
00107     XCPOPT *xcpo;
00108     uint16_t xcpl;
00109     XCPOPT *xcpr;
00110     uint16_t xcps;
00111     uint16_t len = 0;
00112     uint16_t sval;
00113     uint_fast8_t i;
00114 
00115     switch (dcb->dcb_lcp_state) {
00116     case PPPS_CLOSED:
00117         
00118 
00119 
00120         NutNetBufFree(nb);
00121         NutLcpOutput(dev, XCP_TERMACK, id, 0);
00122         return;
00123 
00124     case PPPS_CLOSING:
00125     case PPPS_STOPPING:
00126         
00127 
00128 
00129         NutNetBufFree(nb);
00130         return;
00131 
00132     case PPPS_OPENED:
00133         
00134 
00135 
00136         IpcpLowerDown(dev);
00137         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00138         break;
00139 
00140     case PPPS_STOPPED:
00141         
00142 
00143 
00144         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00145         dcb->dcb_lcp_state = PPPS_REQSENT;
00146         break;
00147     }
00148 
00149     
00150 
00151 
00152     xcpo = nb->nb_ap.vp;
00153     xcpl = nb->nb_ap.sz;
00154     xcpr = nb->nb_ap.vp;
00155     xcps = 0;
00156     while (xcpl >= 2) {
00157         len = xcpo->xcpo_len;
00158         if (len > xcpl)
00159             len = xcpl;
00160         else {
00161             switch (xcpo->xcpo_type) {
00162             case LCP_MRU:
00163                 if (xcpo->xcpo_len == 4)
00164                     len = 0;
00165                 break;
00166             case LCP_MAGICNUMBER:
00167             case LCP_ASYNCMAP:
00168                 if (xcpo->xcpo_len == 6)
00169                     len = 0;
00170                 break;
00171             case LCP_AUTHTYPE:
00172                 if (xcpo->xcpo_len >= 4)
00173                     len = 0;
00174                 break;
00175             case LCP_PCOMPRESSION:
00176                 len = 0;
00177                 break;
00178             case LCP_ACCOMPRESSION:
00179                 len = 0;
00180                 break;
00181             }
00182         }
00183 
00184         if (len) {
00185             if (xcpr != xcpo) {
00186                 xcpr->xcpo_type = xcpo->xcpo_type;
00187                 xcpr->xcpo_len = len;
00188                 for (i = 0; i < len - 2; i++)
00189                     
00190                     xcpr->xcpo_.uc[i] = xcpo->xcpo_.uc[i];
00191             }
00192             xcpr = (XCPOPT *) ((char *) xcpr + len);
00193             xcps += len;
00194         }
00195         xcpl -= xcpo->xcpo_len;
00196         xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len);
00197     }
00198 
00199     if (xcps) {
00200         nb->nb_ap.sz = xcps;
00201         rc = XCP_CONFREJ;
00202     }
00203 
00204     
00205 
00206 
00207     else {
00208         xcpo = nb->nb_ap.vp;
00209         xcpl = nb->nb_ap.sz;
00210         xcpr = nb->nb_ap.vp;
00211         xcps = 0;
00212         len = 0;
00213         while (xcpl >= 2) {
00214             switch (xcpo->xcpo_type) {
00215             case LCP_MRU:
00216                 if ((sval = htons(xcpo->xcpo_.us)) < MIN_LCPMRU) {
00217                     len = 4;
00218                     xcpr->xcpo_.us = ntohs(MIN_LCPMRU);
00219                 } else
00220                     dcb->dcb_rem_mru = sval;
00221                 break;
00222             case LCP_ASYNCMAP:
00223                 dcb->dcb_accm = ntohl(xcpo->xcpo_.ul);
00224                 break;
00225             case LCP_AUTHTYPE:
00226                 if (htons(xcpo->xcpo_.us) != PPP_PAP) {
00227                     len = 4;
00228                     xcpr->xcpo_.us = htons(PPP_PAP);
00229                 }
00230                 break;
00231             case LCP_MAGICNUMBER:
00232                 if (xcpo->xcpo_.ul == dcb->dcb_loc_magic || xcpo->xcpo_.ul == dcb->dcb_neg_magic) {
00233                     dcb->dcb_rem_magic = new_magic;
00234                     len = 6;
00235                     xcpr->xcpo_.ul = dcb->dcb_rem_magic;
00236                 }
00237                 break;
00238             case LCP_PCOMPRESSION:
00239                 dcb->dcb_compr |= PPP_PFC;
00240                 break;
00241             case LCP_ACCOMPRESSION:
00242                 dcb->dcb_compr |= PPP_ACFC;
00243                 break;
00244             }
00245 
00246             if (len) {
00247                 if (xcpr != xcpo) {
00248                     xcpr->xcpo_type = xcpo->xcpo_type;
00249                     xcpr->xcpo_len = len;
00250                 }
00251                 xcpr = (XCPOPT *) ((char *) xcpr + len);
00252                 xcps += len;
00253                 len = 0;
00254             }
00255             xcpl -= xcpo->xcpo_len;
00256             xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len);
00257         }
00258         if (xcps) {
00259             nb->nb_ap.sz = xcps;
00260             rc = XCP_CONFNAK;
00261         }
00262     }
00263 
00264     NutLcpOutput(dev, rc, id, nb);
00265 
00266     if (rc == XCP_CONFACK) {
00267         if (dcb->dcb_lcp_state == PPPS_ACKRCVD) {
00268             dcb->dcb_lcp_state = PPPS_OPENED;
00269             _ioctl(dcb->dcb_fd, HDLC_SETTXACCM, &(dcb->dcb_accm) );
00270             if (dcb->dcb_auth == PPP_PAP)
00271                 PapTxAuthReq(dev, ++dcb->dcb_reqid);
00272             else
00273                 IpcpLowerUp(dev);
00274         } else
00275             dcb->dcb_lcp_state = PPPS_ACKSENT;
00276         dcb->dcb_lcp_naks = 0;
00277     } else if (dcb->dcb_lcp_state != PPPS_ACKRCVD)
00278         dcb->dcb_lcp_state = PPPS_REQSENT;
00279 }
00280 
00281 
00282 
00283 
00284 
00285 static INLINE void LcpRxConfAck(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00286 {
00287     PPPDCB *dcb = dev->dev_dcb;
00288     XCPOPT *xcpo;
00289     uint16_t xcpl;
00290 
00291     
00292 
00293 
00294     if (id == dcb->dcb_reqid && dcb->dcb_acked == 0) {
00295         dcb->dcb_acked = 1;
00296         xcpo = nb->nb_ap.vp;
00297         xcpl = nb->nb_ap.sz;
00298         while (xcpl >= 2) {
00299             switch (xcpo->xcpo_type) {
00300             case LCP_MRU:
00301                 if (htons(xcpo->xcpo_.us) != 1500)
00302                     dcb->dcb_acked = 0;
00303                 break;
00304             case LCP_ASYNCMAP:
00305                 
00306                 
00307                 break;
00308             case LCP_AUTHTYPE:
00309                 if (htons(xcpo->xcpo_.us) != dcb->dcb_auth)
00310                     dcb->dcb_acked = 0;
00311                 break;
00312             case LCP_MAGICNUMBER:
00313                 if (xcpo->xcpo_.ul == dcb->dcb_neg_magic) {
00314                     dcb->dcb_loc_magic = dcb->dcb_neg_magic;
00315                 } else {
00316                     dcb->dcb_acked = 0;
00317                 }
00318                 break;
00319             case LCP_PCOMPRESSION:
00320                 dcb->dcb_acked = 0;
00321                 break;
00322             case LCP_ACCOMPRESSION:
00323                 dcb->dcb_acked = 0;
00324                 break;
00325             }
00326             xcpl -= xcpo->xcpo_len;
00327             xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len);
00328         }
00329     }
00330 
00331     
00332 
00333 
00334     NutNetBufFree(nb);
00335 
00336     
00337 
00338 
00339     if (dcb->dcb_acked == 0)
00340         return;
00341 
00342     switch (dcb->dcb_lcp_state) {
00343     case PPPS_CLOSED:
00344     case PPPS_STOPPED:
00345         
00346 
00347 
00348         NutLcpOutput(dev, XCP_TERMACK, id, 0);
00349         break;
00350 
00351     case PPPS_REQSENT:
00352         dcb->dcb_lcp_state = PPPS_ACKRCVD;
00353         dcb->dcb_retries = 0;
00354         break;
00355 
00356     case PPPS_ACKRCVD:
00357         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00358         dcb->dcb_lcp_state = PPPS_REQSENT;
00359         break;
00360 
00361     case PPPS_ACKSENT:
00362         
00363 
00364 
00365         dcb->dcb_lcp_state = PPPS_OPENED;
00366         _ioctl(dcb->dcb_fd, HDLC_SETTXACCM, &(dcb->dcb_accm) );
00367 
00368         if (dcb->dcb_auth == PPP_PAP)
00369             PapTxAuthReq(dev, ++dcb->dcb_reqid);
00370         else
00371             IpcpLowerUp(dev);
00372         break;
00373 
00374     case PPPS_OPENED:
00375         
00376 
00377 
00378         IpcpLowerDown(dev);
00379         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00380         dcb->dcb_lcp_state = PPPS_REQSENT;
00381         break;
00382     }
00383 }
00384 
00385 
00386 
00387 
00388 static INLINE void LcpRxConfNakRej(NUTDEVICE * dev, uint8_t id, NETBUF * nb, uint8_t rejected)
00389 {
00390     PPPDCB *dcb = dev->dev_dcb;
00391 
00392     XCPOPT *xcpo;
00393     uint16_t xcpl;
00394 
00395     
00396 
00397 
00398     if (id != dcb->dcb_reqid || dcb->dcb_acked) {
00399         NutNetBufFree(nb);
00400         return;
00401     }
00402 
00403     
00404 
00405 
00406     dcb->dcb_acked = 1;
00407 
00408     xcpo = nb->nb_ap.vp;
00409     xcpl = nb->nb_ap.sz;
00410     while (xcpl >= 2) {
00411         xcpl -= xcpo->xcpo_len;
00412         xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len);
00413     }
00414 
00415     NutNetBufFree(nb);
00416 
00417     switch (dcb->dcb_lcp_state) {
00418     case PPPS_CLOSED:
00419     case PPPS_STOPPED:
00420         
00421 
00422 
00423         NutLcpOutput(dev, XCP_TERMACK, id, 0);
00424         break;
00425 
00426     case PPPS_REQSENT:
00427     case PPPS_ACKSENT:
00428         
00429         LcpTxConfReq(dev, ++dcb->dcb_reqid, rejected);
00430         break;
00431 
00432     case PPPS_ACKRCVD:
00433         
00434         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00435         dcb->dcb_lcp_state = PPPS_REQSENT;
00436         break;
00437 
00438     case PPPS_OPENED:
00439         
00440 
00441 
00442         IpcpLowerDown(dev);
00443         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00444         dcb->dcb_lcp_state = PPPS_REQSENT;
00445         break;
00446     }
00447 }
00448 
00449 
00450 
00451 
00452 static INLINE void LcpRxTermReq(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00453 {
00454     PPPDCB *dcb = dev->dev_dcb;
00455 
00456     NutNetBufFree(nb);
00457 
00458     switch (dcb->dcb_lcp_state) {
00459     case PPPS_ACKRCVD:
00460     case PPPS_ACKSENT:
00461         dcb->dcb_lcp_state = PPPS_REQSENT;      
00462         break;
00463 
00464     case PPPS_OPENED:
00465         IpcpLowerDown(dev);
00466         dcb->dcb_lcp_state = PPPS_STOPPING;
00467         break;
00468     }
00469     NutLcpOutput(dev, XCP_TERMACK, id, 0);
00470 }
00471 
00472 
00473 
00474 
00475 static INLINE void LcpRxTermAck(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00476 {
00477     PPPDCB *dcb = dev->dev_dcb;
00478 
00479     NutNetBufFree(nb);
00480 
00481     switch (dcb->dcb_lcp_state) {
00482     case PPPS_CLOSING:
00483         dcb->dcb_lcp_state = PPPS_CLOSED;
00484         break;
00485     case PPPS_STOPPING:
00486         dcb->dcb_lcp_state = PPPS_STOPPED;
00487         break;
00488 
00489     case PPPS_ACKRCVD:
00490         dcb->dcb_lcp_state = PPPS_REQSENT;
00491         break;
00492 
00493     case PPPS_OPENED:
00494         IpcpLowerDown(dev);
00495         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00496         break;
00497     }
00498 }
00499 
00500 
00501 
00502 
00503 
00504 
00505 void LcpRxProtRej(NUTDEVICE * dev)
00506 {
00507     PPPDCB *dcb = dev->dev_dcb;
00508 
00509     switch (dcb->dcb_lcp_state) {
00510     case PPPS_CLOSING:
00511     case PPPS_CLOSED:
00512         dcb->dcb_lcp_state = PPPS_CLOSED;
00513         break;
00514 
00515     case PPPS_STOPPING:
00516     case PPPS_REQSENT:
00517     case PPPS_ACKRCVD:
00518     case PPPS_ACKSENT:
00519     case PPPS_STOPPED:
00520         dcb->dcb_lcp_state = PPPS_STOPPED;
00521         break;
00522 
00523     case PPPS_OPENED:
00524         IpcpLowerDown(dev);
00525         NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00526         dcb->dcb_lcp_state = PPPS_STOPPING;
00527         break;
00528     }
00529 }
00530 
00531 
00532 
00533 
00534 static INLINE void LcpRxCodeRej(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00535 {
00536     PPPDCB *dcb = dev->dev_dcb;
00537 
00538     NutNetBufFree(nb);
00539 
00540     if (dcb->dcb_lcp_state == PPPS_ACKRCVD)
00541         dcb->dcb_lcp_state = PPPS_REQSENT;
00542 }
00543 
00544 
00545 
00546 
00547 static INLINE void LcpRxEchoReq(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00548 {
00549     PPPDCB *dcb = dev->dev_dcb;
00550 
00551     if (dcb->dcb_lcp_state != PPPS_OPENED) {
00552         NutNetBufFree(nb);
00553     } else {
00554         
00555         memcpy(nb->nb_ap.vp, &dcb->dcb_loc_magic, sizeof(uint32_t));
00556         NutLcpOutput(dev, LCP_ERP, id, nb);
00557     }
00558 }
00559 
00560 
00561 
00576 void NutLcpInput(NUTDEVICE * dev, NETBUF * nb)
00577 {
00578     XCPHDR *lcp;
00579     PPPDCB *dcb = dev->dev_dcb;
00580     uint16_t len;
00581 
00582     
00583 
00584 
00585     if (nb->nb_nw.sz < sizeof(XCPHDR)) {
00586         NutNetBufFree(nb);
00587         return;
00588     }
00589     lcp = (XCPHDR *) nb->nb_nw.vp;
00590     if ((len = htons(lcp->xch_len)) < sizeof(XCPHDR) || len > nb->nb_nw.sz) {
00591         NutNetBufFree(nb);
00592         return;
00593     }
00594 
00595     
00596 
00597 
00598     if (dcb->dcb_lcp_state == PPPS_INITIAL || dcb->dcb_lcp_state == PPPS_STARTING) {
00599         NutNetBufFree(nb);
00600         return;
00601     }
00602 
00603     
00604 
00605 
00606     nb->nb_ap.vp = lcp + 1;
00607     nb->nb_ap.sz = htons(lcp->xch_len) - sizeof(XCPHDR);
00608 
00609     
00610 
00611 
00612     switch (lcp->xch_code) {
00613     case XCP_CONFREQ:
00614         LcpRxConfReq(dev, lcp->xch_id, nb);
00615         break;
00616 
00617     case XCP_CONFACK:
00618         LcpRxConfAck(dev, lcp->xch_id, nb);
00619         break;
00620 
00621     case XCP_CONFNAK:
00622         LcpRxConfNakRej(dev, lcp->xch_id, nb, 0);
00623         break;
00624 
00625     case XCP_CONFREJ:
00626         LcpRxConfNakRej(dev, lcp->xch_id, nb, 1);
00627         break;
00628 
00629     case XCP_TERMREQ:
00630         LcpRxTermReq(dev, lcp->xch_id, nb);
00631         break;
00632 
00633     case XCP_TERMACK:
00634         LcpRxTermAck(dev, lcp->xch_id, nb);
00635         break;
00636 
00637     case XCP_CODEREJ:
00638         LcpRxCodeRej(dev, lcp->xch_id, nb);
00639         break;
00640 
00641     case LCP_ERQ:
00642         LcpRxEchoReq(dev, lcp->xch_id, nb);
00643         break;
00644 
00645     case LCP_ERP:
00646     case LCP_DRQ:
00647         
00648         NutNetBufFree(nb);
00649         break;
00650 
00651     default:
00652         
00653 
00654 
00655         NutNetBufFree(nb);
00656         break;
00657     }
00658 }
00659