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