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