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