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