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 
00083 
00084 
00085 
00086 
00087 
00088 #include <sys/event.h>
00089 #include <sys/types.h>
00090 #include <net/if_var.h>
00091 #include <dev/ppp.h>
00092 
00093 #include <netinet/if_ppp.h>
00094 #include <netinet/ppp_fsm.h>
00095 #include <netinet/in.h>
00100 
00101 
00102 
00103 
00104 void IpcpRxConfReq(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00105 {
00106     PPPDCB *dcb = dev->dev_dcb;
00107     int rc = XCP_CONFACK;
00108     XCPOPT *xcpo;
00109     uint16_t xcpl;
00110     XCPOPT *xcpr;
00111     uint16_t xcps;
00112     uint16_t len = 0;
00113     uint_fast8_t i;
00114 
00115     switch (dcb->dcb_ipcp_state) {
00116     case PPPS_CLOSED:
00117         
00118 
00119 
00120         NutNetBufFree(nb);
00121         NutIpcpOutput(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         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00138         break;
00139 
00140     case PPPS_STOPPED:
00141         
00142 
00143 
00144         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00145         dcb->dcb_ipcp_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 IPCP_COMPRESSTYPE:
00163                 break;
00164             case IPCP_ADDR:
00165             case IPCP_MS_DNS1:
00166             case IPCP_MS_DNS2:
00167                 if (xcpo->xcpo_len == 6)
00168                     len = 0;
00169                 break;
00170             }
00171         }
00172 
00173         if (len) {
00174             if (xcpr != xcpo) {
00175                 xcpr->xcpo_type = xcpo->xcpo_type;
00176                 xcpr->xcpo_len = len;
00177                 for (i = 0; i < len - 2; i++)
00178                     
00179                     xcpr->xcpo_.uc[i] = xcpo->xcpo_.uc[i];
00180             }
00181             xcpr = (XCPOPT *) ((char *) xcpr + len);
00182             xcps += len;
00183         }
00184         xcpl -= xcpo->xcpo_len;
00185         xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len);
00186     }
00187 
00188     if (xcps) {
00189         nb->nb_ap.sz = xcps;
00190         rc = XCP_CONFREJ;
00191     }
00192 
00193     
00194 
00195 
00196     else {
00197         xcpo = nb->nb_ap.vp;
00198         xcpl = nb->nb_ap.sz;
00199         xcpr = nb->nb_ap.vp;
00200         xcps = 0;
00201         len = 0;
00202         while (xcpl >= 2) {
00203             switch (xcpo->xcpo_type) {
00204             case IPCP_ADDR:
00205                 if (xcpo->xcpo_.ul)
00206                     dcb->dcb_remote_ip = xcpo->xcpo_.ul;
00207                 else if (dcb->dcb_remote_ip == 0)
00208                     len = xcpo->xcpo_len;
00209                 break;
00210             case IPCP_COMPRESSTYPE:
00211                 len = 6;
00212                 xcpr->xcpo_.ul = 0;
00213                 break;
00214             case IPCP_MS_DNS1:
00215                 if (xcpo->xcpo_.ul)
00216                     dcb->dcb_ip_dns1 = xcpo->xcpo_.ul;
00217                 break;
00218             case IPCP_MS_DNS2:
00219                 if (xcpo->xcpo_.ul)
00220                     dcb->dcb_ip_dns2 = xcpo->xcpo_.ul;
00221                 break;
00222             }
00223 
00224             if (len) {
00225                 if (xcpr != xcpo) {
00226                     xcpr->xcpo_type = xcpo->xcpo_type;
00227                     xcpr->xcpo_len = len;
00228                 }
00229                 xcpr = (XCPOPT *) ((char *) xcpr + len);
00230                 xcps += len;
00231                 len = 0;
00232             }
00233             xcpl -= xcpo->xcpo_len;
00234             xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len);
00235         }
00236         if (xcps) {
00237             nb->nb_ap.sz = xcps;
00238             rc = XCP_CONFNAK;
00239         }
00240     }
00241 
00242     NutIpcpOutput(dev, rc, id, nb);
00243 
00244     if (rc == XCP_CONFACK) {
00245         if (dcb->dcb_ipcp_state == PPPS_ACKRCVD) {
00246             dcb->dcb_ipcp_state = PPPS_OPENED;
00247             NutEventPost(&dcb->dcb_state_chg);
00248         } else
00249             dcb->dcb_ipcp_state = PPPS_ACKSENT;
00250         dcb->dcb_ipcp_naks = 0;
00251     } else if (dcb->dcb_ipcp_state != PPPS_ACKRCVD)
00252         dcb->dcb_ipcp_state = PPPS_REQSENT;
00253 }
00254 
00255 
00256 
00257 
00258 void IpcpRxConfAck(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00259 {
00260     PPPDCB *dcb = dev->dev_dcb;
00261     XCPOPT *xcpo;
00262     uint16_t xcpl;
00263 
00264     
00265 
00266 
00267     if (id != dcb->dcb_reqid || dcb->dcb_acked) {
00268         return;
00269     }
00270 
00271     switch (dcb->dcb_ipcp_state) {
00272     case PPPS_CLOSED:
00273     case PPPS_STOPPED:
00274         
00275 
00276 
00277         NutNetBufFree(nb);
00278         NutIpcpOutput(dev, XCP_TERMACK, id, 0);
00279         return;
00280 
00281     case PPPS_REQSENT:
00282         dcb->dcb_ipcp_state = PPPS_ACKRCVD;
00283         dcb->dcb_retries = 0;
00284         break;
00285 
00286     case PPPS_ACKRCVD:
00287         
00288         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00289         dcb->dcb_ipcp_state = PPPS_REQSENT;
00290         break;
00291 
00292     case PPPS_ACKSENT:
00293         dcb->dcb_ipcp_state = PPPS_OPENED;
00294         dcb->dcb_retries = 0;
00295         NutEventPost(&dcb->dcb_state_chg);
00296         break;
00297 
00298     case PPPS_OPENED:
00299         
00300         IpcpLowerDown(dev);
00301         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00302         dcb->dcb_ipcp_state = PPPS_REQSENT;
00303         break;
00304     }
00305 
00306     xcpo = nb->nb_ap.vp;
00307     xcpl = nb->nb_ap.sz;
00308     while (xcpl >= 2) {
00309         switch (xcpo->xcpo_type) {
00310         case IPCP_ADDR:
00311             if (xcpo->xcpo_.ul)
00312                 dcb->dcb_local_ip = xcpo->xcpo_.ul;
00313             break;
00314         case IPCP_COMPRESSTYPE:
00315             break;
00316         case IPCP_MS_DNS1:
00317             if (xcpo->xcpo_.ul)
00318                 dcb->dcb_ip_dns1 = xcpo->xcpo_.ul;
00319             break;
00320         case IPCP_MS_DNS2:
00321             
00322 
00323             if (xcpo->xcpo_.ul)
00324                 dcb->dcb_ip_dns2 = xcpo->xcpo_.ul;
00325             break;
00326         }
00327         xcpl -= xcpo->xcpo_len;
00328         xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len);
00329     }
00330 
00331     dcb->dcb_acked = 1;
00332     NutNetBufFree(nb);
00333 }
00334 
00335 
00336 
00337 
00338 static void IpcpRxConfNakRej(NUTDEVICE * dev, uint8_t id, NETBUF * nb, uint8_t rejected)
00339 {
00340     PPPDCB *dcb = dev->dev_dcb;
00341     XCPOPT *xcpo;
00342     uint16_t xcpl;
00343 
00344     
00345 
00346 
00347     if (id != dcb->dcb_reqid || dcb->dcb_acked) {
00348         NutNetBufFree(nb);
00349         return;
00350     }
00351 
00352     switch (dcb->dcb_ipcp_state) {
00353     case PPPS_CLOSED:
00354     case PPPS_STOPPED:
00355         
00356 
00357 
00358         NutNetBufFree(nb);
00359         NutIpcpOutput(dev, XCP_TERMACK, id, 0);
00360         return;
00361 
00362     case PPPS_REQSENT:
00363     case PPPS_ACKSENT:
00364     case PPPS_ACKRCVD:
00365     case PPPS_OPENED:
00366         break;
00367 
00368     default:
00369         NutNetBufFree(nb);
00370         return;
00371     }
00372 
00373     dcb->dcb_acked = 1;
00374 
00375     xcpo = nb->nb_ap.vp;
00376     xcpl = nb->nb_ap.sz;
00377     while (xcpl >= 2) {
00378         switch (xcpo->xcpo_type) {
00379         case IPCP_ADDR:
00380             if (xcpo->xcpo_.ul)
00381                 dcb->dcb_local_ip = xcpo->xcpo_.ul;
00382             break;
00383         case IPCP_COMPRESSTYPE:
00384             break;
00385         case IPCP_MS_DNS1:
00386             if (rejected)
00387                 dcb->dcb_rejects |= REJ_IPCP_DNS1;
00388             else if (xcpo->xcpo_.ul)
00389                 dcb->dcb_ip_dns1 = xcpo->xcpo_.ul;
00390             break;
00391         case IPCP_MS_DNS2:
00392             if (rejected)
00393                 dcb->dcb_rejects |= REJ_IPCP_DNS2;
00394             else if (xcpo->xcpo_.ul)
00395                 dcb->dcb_ip_dns2 = xcpo->xcpo_.ul;
00396             break;
00397         }
00398         xcpl -= xcpo->xcpo_len;
00399         xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len);
00400     }
00401     NutNetBufFree(nb);
00402 
00403     switch (dcb->dcb_ipcp_state) {
00404 
00405     case PPPS_REQSENT:
00406     case PPPS_ACKSENT:
00407         
00408         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00409         break;
00410 
00411     case PPPS_ACKRCVD:
00412         
00413         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00414         dcb->dcb_ipcp_state = PPPS_REQSENT;
00415         break;
00416 
00417     case PPPS_OPENED:
00418         
00419         IpcpLowerDown(dev);
00420         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00421         dcb->dcb_ipcp_state = PPPS_REQSENT;
00422         break;
00423     }
00424 }
00425 
00426 
00427 
00428 
00429 void IpcpRxTermReq(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00430 {
00431     PPPDCB *dcb = dev->dev_dcb;
00432 
00433     NutNetBufFree(nb);
00434     switch (dcb->dcb_ipcp_state) {
00435     case PPPS_ACKRCVD:
00436     case PPPS_ACKSENT:
00437         dcb->dcb_ipcp_state = PPPS_REQSENT;
00438         break;
00439 
00440     case PPPS_OPENED:
00441         IpcpLowerDown(dev);
00442         dcb->dcb_ipcp_state = PPPS_STOPPING;
00443         break;
00444     }
00445     NutIpcpOutput(dev, XCP_TERMACK, id, 0);
00446 }
00447 
00448 
00449 
00450 
00451 void IpcpRxTermAck(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00452 {
00453     PPPDCB *dcb = dev->dev_dcb;
00454 
00455     switch (dcb->dcb_ipcp_state) {
00456     case PPPS_CLOSING:
00457         dcb->dcb_ipcp_state = PPPS_CLOSED;
00458         break;
00459     case PPPS_STOPPING:
00460         dcb->dcb_ipcp_state = PPPS_STOPPED;
00461         break;
00462 
00463     case PPPS_ACKRCVD:
00464         dcb->dcb_ipcp_state = PPPS_REQSENT;
00465         break;
00466 
00467     case PPPS_OPENED:
00468         IpcpLowerDown(dev);
00469         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00470         break;
00471     }
00472 }
00473 
00474 
00475 
00476 
00477 
00478 
00479 void IpcpRxProtRej(NUTDEVICE * dev)
00480 {
00481     PPPDCB *dcb = dev->dev_dcb;
00482 
00483     switch (dcb->dcb_ipcp_state) {
00484     case PPPS_CLOSING:
00485     case PPPS_CLOSED:
00486         dcb->dcb_ipcp_state = PPPS_CLOSED;
00487         break;
00488 
00489     case PPPS_STOPPING:
00490     case PPPS_REQSENT:
00491     case PPPS_ACKRCVD:
00492     case PPPS_ACKSENT:
00493     case PPPS_STOPPED:
00494         dcb->dcb_ipcp_state = PPPS_STOPPED;
00495         break;
00496 
00497     case PPPS_OPENED:
00498         IpcpLowerDown(dev);
00499         NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00500         dcb->dcb_ipcp_state = PPPS_STOPPING;
00501         break;
00502     }
00503 }
00504 
00505 
00506 
00507 
00508 static void IpcpRxCodeRej(NUTDEVICE * dev, uint8_t id, NETBUF * nb)
00509 {
00510     PPPDCB *dcb = dev->dev_dcb;
00511 
00512     NutNetBufFree(nb);
00513     if (dcb->dcb_ipcp_state == PPPS_ACKRCVD)
00514         dcb->dcb_ipcp_state = PPPS_REQSENT;
00515 }
00516 
00517 
00518 
00533 void NutIpcpInput(NUTDEVICE * dev, NETBUF * nb)
00534 {
00535     XCPHDR *xch;
00536     PPPDCB *dcb = dev->dev_dcb;
00537     uint16_t len;
00538 
00539     
00540 
00541 
00542     if (nb->nb_nw.sz < sizeof(XCPHDR)) {
00543         NutNetBufFree(nb);
00544         return;
00545     }
00546     xch = (XCPHDR *) nb->nb_nw.vp;
00547     if ((len = htons(xch->xch_len)) < sizeof(XCPHDR) || len > nb->nb_nw.sz) {
00548         NutNetBufFree(nb);
00549         return;
00550     }
00551 
00552     
00553 
00554 
00555     if (dcb->dcb_ipcp_state == PPPS_INITIAL || dcb->dcb_ipcp_state == PPPS_STARTING) {
00556         NutNetBufFree(nb);
00557         return;
00558     }
00559 
00560     
00561 
00562 
00563     nb->nb_ap.vp = xch + 1;
00564     nb->nb_ap.sz = htons(xch->xch_len) - sizeof(XCPHDR);
00565 
00566     
00567 
00568 
00569     switch (xch->xch_code) {
00570     case XCP_CONFREQ:
00571         IpcpRxConfReq(dev, xch->xch_id, nb);
00572         break;
00573 
00574     case XCP_CONFACK:
00575         IpcpRxConfAck(dev, xch->xch_id, nb);
00576         break;
00577 
00578     case XCP_CONFNAK:
00579         IpcpRxConfNakRej(dev, xch->xch_id, nb, 0);
00580         break;
00581 
00582     case XCP_CONFREJ:
00583         IpcpRxConfNakRej(dev, xch->xch_id, nb, 1);
00584         break;
00585 
00586     case XCP_TERMREQ:
00587         IpcpRxTermReq(dev, xch->xch_id, nb);
00588         break;
00589 
00590     case XCP_TERMACK:
00591         IpcpRxTermAck(dev, xch->xch_id, nb);
00592         break;
00593 
00594     case XCP_CODEREJ:
00595         IpcpRxCodeRej(dev, xch->xch_id, nb);
00596         break;
00597 
00598     default:
00599         
00600 
00601 
00602         NutNetBufFree(nb);
00603         break;
00604     }
00605 }
00606