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 "lwip/opt.h"
00083
00084 #if PPP_SUPPORT
00085
00086 #include "ppp_impl.h"
00087 #include "lwip/ip.h"
00088
00089 #include "pppdebug.h"
00090
00091 #include "randm.h"
00092 #include "fsm.h"
00093 #if PAP_SUPPORT
00094 #include "pap.h"
00095 #endif
00096 #if CHAP_SUPPORT
00097 #include "chap.h"
00098 #endif
00099 #include "ipcp.h"
00100 #include "lcp.h"
00101 #include "magic.h"
00102 #include "auth.h"
00103 #if VJ_SUPPORT
00104 #include "vj.h"
00105 #endif
00106 #if PPPOE_SUPPORT
00107 #include "netif/ppp_oe.h"
00108 #endif
00109
00110 #include "lwip/tcpip.h"
00111 #include "lwip/api.h"
00112 #include "lwip/snmp.h"
00113
00114 #include <string.h>
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 #ifndef PPP_INPROC_MULTITHREADED
00125 #define PPP_INPROC_MULTITHREADED (NO_SYS==0)
00126 #endif
00127
00128
00129
00130
00131 #ifndef PPP_INPROC_OWNTHREAD
00132 #define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED
00133 #endif
00134
00135 #if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED
00136 #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1"
00137 #endif
00138
00139
00140
00141
00142 #define PPP_ADDRESS(p) (((u_char *)(p))[0])
00143 #define PPP_CONTROL(p) (((u_char *)(p))[1])
00144 #define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
00145
00146
00147
00148 typedef enum {
00149 PDIDLE = 0,
00150 PDSTART,
00151 PDADDRESS,
00152 PDCONTROL,
00153 PDPROTOCOL1,
00154 PDPROTOCOL2,
00155 PDDATA
00156 } PPPDevStates;
00157
00158 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
00159
00160
00161
00162
00163
00164
00165 #ifndef PPPOS_RX_BUFSIZE
00166 #define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN)
00167 #endif
00168
00169 typedef struct PPPControlRx_s {
00170
00171 int pd;
00172
00173 sio_fd_t fd;
00174
00175 #if PPP_INPROC_OWNTHREAD
00176 u_char rxbuf[PPPOS_RX_BUFSIZE];
00177 #endif
00178
00179
00180 struct pbuf *inHead, *inTail;
00181
00182 #if PPPOS_SUPPORT
00183 u16_t inProtocol;
00184 u16_t inFCS;
00185 #endif
00186 PPPDevStates inState;
00187 char inEscaped;
00188 ext_accm inACCM;
00189 } PPPControlRx;
00190
00191
00192
00193
00194 typedef struct PPPControl_s {
00195 PPPControlRx rx;
00196 char openFlag;
00197 #if PPPOE_SUPPORT
00198 struct netif *ethif;
00199 struct pppoe_softc *pppoe_sc;
00200 #endif
00201 int if_up;
00202 int errCode;
00203 #if PPPOS_SUPPORT
00204 sio_fd_t fd;
00205 #endif
00206 u16_t mtu;
00207 int pcomp;
00208 int accomp;
00209 u_long lastXMit;
00210 ext_accm outACCM;
00211 #if PPPOS_SUPPORT && VJ_SUPPORT
00212 int vjEnabled;
00213 struct vjcompress vjComp;
00214 #endif
00215
00216 struct netif netif;
00217
00218 struct ppp_addrs addrs;
00219
00220 void (*linkStatusCB)(void *ctx, int errCode, void *arg);
00221 void *linkStatusCtx;
00222
00223 } PPPControl;
00224
00225
00226
00227
00228
00229
00230 struct npioctl {
00231 int protocol;
00232 enum NPmode mode;
00233 };
00234
00235
00236
00237
00238
00239
00240 #if PPPOS_SUPPORT
00241 #if PPP_INPROC_OWNTHREAD
00242 static void pppInputThread(void *arg);
00243 #endif
00244 static void pppDrop(PPPControlRx *pcrx);
00245 static void pppInProc(PPPControlRx *pcrx, u_char *s, int l);
00246 static void pppFreeCurrentInputPacket(PPPControlRx *pcrx);
00247 #endif
00248
00249
00250
00251
00252
00253 u_long subnetMask;
00254
00255 static PPPControl pppControl[NUM_PPP];
00256
00257
00258
00259
00260
00261
00262 struct protent *ppp_protocols[] = {
00263 &lcp_protent,
00264 #if PAP_SUPPORT
00265 &pap_protent,
00266 #endif
00267 #if CHAP_SUPPORT
00268 &chap_protent,
00269 #endif
00270 #if CBCP_SUPPORT
00271 &cbcp_protent,
00272 #endif
00273 &ipcp_protent,
00274 #if CCP_SUPPORT
00275 &ccp_protent,
00276 #endif
00277 NULL
00278 };
00279
00280
00281
00282
00283
00284
00285 u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
00286
00287
00288
00289
00290
00291
00292 #if PPPOS_SUPPORT
00293
00294
00295
00296
00297 static const u_short fcstab[256] = {
00298 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
00299 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
00300 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
00301 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
00302 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
00303 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
00304 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
00305 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
00306 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
00307 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
00308 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
00309 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
00310 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
00311 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
00312 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
00313 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
00314 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
00315 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
00316 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
00317 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
00318 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
00319 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
00320 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
00321 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
00322 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
00323 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
00324 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
00325 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
00326 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
00327 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
00328 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
00329 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
00330 };
00331
00332
00333
00334 static u_char pppACCMMask[] = {
00335 0x01,
00336 0x02,
00337 0x04,
00338 0x08,
00339 0x10,
00340 0x20,
00341 0x40,
00342 0x80
00343 };
00344
00345 #if PPP_INPROC_OWNTHREAD
00346
00347 static void
00348 pppRecvWakeup(int pd)
00349 {
00350 PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd));
00351 if (pppControl[pd].openFlag != 0) {
00352 sio_read_abort(pppControl[pd].fd);
00353 }
00354 }
00355 #endif
00356 #endif
00357
00358 void
00359 pppLinkTerminated(int pd)
00360 {
00361 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd));
00362
00363 #if PPPOE_SUPPORT
00364 if (pppControl[pd].ethif) {
00365 pppoe_disconnect(pppControl[pd].pppoe_sc);
00366 } else
00367 #endif
00368 {
00369 #if PPPOS_SUPPORT
00370 PPPControl* pc;
00371 #if PPP_INPROC_OWNTHREAD
00372 pppRecvWakeup(pd);
00373 #endif
00374 pc = &pppControl[pd];
00375
00376 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
00377 if (pc->linkStatusCB) {
00378 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
00379 }
00380
00381 pc->openFlag = 0;
00382 #endif
00383 }
00384 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n"));
00385 }
00386
00387 void
00388 pppLinkDown(int pd)
00389 {
00390 PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd));
00391
00392 #if PPPOE_SUPPORT
00393 if (pppControl[pd].ethif) {
00394 pppoe_disconnect(pppControl[pd].pppoe_sc);
00395 } else
00396 #endif
00397 {
00398 #if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD
00399 pppRecvWakeup(pd);
00400 #endif
00401 }
00402 }
00403
00404
00405 static void
00406 pppStart(int pd)
00407 {
00408 PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd));
00409 lcp_lowerup(pd);
00410 lcp_open(pd);
00411 PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n"));
00412 }
00413
00414
00415 static void
00416 pppStop(int pd)
00417 {
00418 PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd));
00419 lcp_close(pd, "User request");
00420 }
00421
00422
00423 static void
00424 pppHup(int pd)
00425 {
00426 PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd));
00427 lcp_lowerdown(pd);
00428 link_terminated(pd);
00429 }
00430
00431
00432
00433
00434
00435
00436 struct ppp_settings ppp_settings;
00437
00438 void
00439 pppInit(void)
00440 {
00441 struct protent *protp;
00442 int i, j;
00443
00444 memset(&ppp_settings, 0, sizeof(ppp_settings));
00445 ppp_settings.usepeerdns = 1;
00446 pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
00447
00448 magicInit();
00449
00450 subnetMask = PP_HTONL(0xffffff00UL);
00451
00452 for (i = 0; i < NUM_PPP; i++) {
00453
00454 for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) {
00455 (*protp->init)(i);
00456 }
00457 }
00458 }
00459
00460 void
00461 pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
00462 {
00463 switch(authType) {
00464 case PPPAUTHTYPE_NONE:
00465 default:
00466 #ifdef LWIP_PPP_STRICT_PAP_REJECT
00467 ppp_settings.refuse_pap = 1;
00468 #else
00469
00470 ppp_settings.refuse_pap = 0;
00471 #endif
00472 ppp_settings.refuse_chap = 1;
00473 break;
00474
00475 case PPPAUTHTYPE_ANY:
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 ppp_settings.refuse_pap = 0;
00496 ppp_settings.refuse_chap = 0;
00497 break;
00498
00499 case PPPAUTHTYPE_PAP:
00500 ppp_settings.refuse_pap = 0;
00501 ppp_settings.refuse_chap = 1;
00502 break;
00503
00504 case PPPAUTHTYPE_CHAP:
00505 ppp_settings.refuse_pap = 1;
00506 ppp_settings.refuse_chap = 0;
00507 break;
00508 }
00509
00510 if(user) {
00511 strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
00512 ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
00513 } else {
00514 ppp_settings.user[0] = '\0';
00515 }
00516
00517 if(passwd) {
00518 strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
00519 ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
00520 } else {
00521 ppp_settings.passwd[0] = '\0';
00522 }
00523 }
00524
00525 #if PPPOS_SUPPORT
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 int
00537 pppOverSerialOpen(sio_fd_t fd, pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx)
00538 {
00539 PPPControl *pc;
00540 int pd;
00541
00542 if (linkStatusCB == NULL) {
00543
00544
00545 return PPPERR_PARAM;
00546 }
00547
00548
00549 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
00550
00551 if (pd >= NUM_PPP) {
00552 pd = PPPERR_OPEN;
00553 } else {
00554 pc = &pppControl[pd];
00555
00556 pppFreeCurrentInputPacket(&pc->rx);
00557
00558 memset(pc, 0, sizeof(PPPControl));
00559 pc->rx.pd = pd;
00560 pc->rx.fd = fd;
00561
00562 pc->openFlag = 1;
00563 pc->fd = fd;
00564
00565 #if VJ_SUPPORT
00566 vj_compress_init(&pc->vjComp);
00567 #endif
00568
00569
00570
00571
00572
00573 pc->rx.inACCM[15] = 0x60;
00574 pc->outACCM[15] = 0x60;
00575
00576 pc->linkStatusCB = linkStatusCB;
00577 pc->linkStatusCtx = linkStatusCtx;
00578
00579
00580
00581
00582 PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd));
00583 pppStart(pd);
00584 #if PPP_INPROC_OWNTHREAD
00585 sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO);
00586 #endif
00587 }
00588
00589 return pd;
00590 }
00591 #endif
00592
00593 #if PPPOE_SUPPORT
00594 static void pppOverEthernetLinkStatusCB(int pd, int up);
00595
00596 void
00597 pppOverEthernetClose(int pd)
00598 {
00599 PPPControl* pc = &pppControl[pd];
00600
00601
00602 lcp_close(pd, NULL);
00603
00604 pppoe_destroy(&pc->netif);
00605 }
00606
00607 int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name,
00608 pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx)
00609 {
00610 PPPControl *pc;
00611 int pd;
00612
00613 LWIP_UNUSED_ARG(service_name);
00614 LWIP_UNUSED_ARG(concentrator_name);
00615
00616 if (linkStatusCB == NULL) {
00617
00618
00619 return PPPERR_PARAM;
00620 }
00621
00622
00623 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
00624 if (pd >= NUM_PPP) {
00625 pd = PPPERR_OPEN;
00626 } else {
00627 pc = &pppControl[pd];
00628 memset(pc, 0, sizeof(PPPControl));
00629 pc->openFlag = 1;
00630 pc->ethif = ethif;
00631
00632 pc->linkStatusCB = linkStatusCB;
00633 pc->linkStatusCtx = linkStatusCtx;
00634
00635 lcp_wantoptions[pd].mru = PPPOE_MAXMTU;
00636 lcp_wantoptions[pd].neg_asyncmap = 0;
00637 lcp_wantoptions[pd].neg_pcompression = 0;
00638 lcp_wantoptions[pd].neg_accompression = 0;
00639
00640 lcp_allowoptions[pd].mru = PPPOE_MAXMTU;
00641 lcp_allowoptions[pd].neg_asyncmap = 0;
00642 lcp_allowoptions[pd].neg_pcompression = 0;
00643 lcp_allowoptions[pd].neg_accompression = 0;
00644
00645 if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) {
00646 pc->openFlag = 0;
00647 return PPPERR_OPEN;
00648 }
00649
00650 pppoe_connect(pc->pppoe_sc);
00651 }
00652
00653 return pd;
00654 }
00655 #endif
00656
00657
00658
00659
00660
00661 int
00662 pppClose(int pd)
00663 {
00664 PPPControl *pc = &pppControl[pd];
00665 int st = 0;
00666
00667 PPPDEBUG(LOG_DEBUG, ("pppClose() called\n"));
00668
00669
00670 #if PPPOE_SUPPORT
00671 if(pc->ethif) {
00672 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd));
00673 pc->errCode = PPPERR_USER;
00674
00675 pppStop(pd);
00676 } else
00677 #endif
00678 {
00679 #if PPPOS_SUPPORT
00680 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd));
00681 pc->errCode = PPPERR_USER;
00682
00683 pppStop(pd);
00684 #if PPP_INPROC_OWNTHREAD
00685 pppRecvWakeup(pd);
00686 #endif
00687 #endif
00688 }
00689
00690 return st;
00691 }
00692
00693
00694 void
00695 pppSigHUP(int pd)
00696 {
00697 PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
00698 pppHup(pd);
00699 }
00700
00701 #if PPPOS_SUPPORT
00702 static void
00703 nPut(PPPControl *pc, struct pbuf *nb)
00704 {
00705 struct pbuf *b;
00706 int c;
00707
00708 for(b = nb; b != NULL; b = b->next) {
00709 if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
00710 PPPDEBUG(LOG_WARNING,
00711 ("PPP nPut: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c));
00712 LINK_STATS_INC(link.err);
00713 pc->lastXMit = 0;
00714 snmp_inc_ifoutdiscards(&pc->netif);
00715 pbuf_free(nb);
00716 return;
00717 }
00718 }
00719
00720 snmp_add_ifoutoctets(&pc->netif, nb->tot_len);
00721 snmp_inc_ifoutucastpkts(&pc->netif);
00722 pbuf_free(nb);
00723 LINK_STATS_INC(link.xmit);
00724 }
00725
00726
00727
00728
00729
00730
00731
00732 static struct pbuf *
00733 pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
00734 {
00735 struct pbuf *tb = nb;
00736
00737
00738
00739
00740
00741 if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
00742 tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
00743 if (tb) {
00744 nb->next = tb;
00745 } else {
00746 LINK_STATS_INC(link.memerr);
00747 }
00748 nb = tb;
00749 }
00750
00751 if (nb) {
00752 if (outACCM && ESCAPE_P(*outACCM, c)) {
00753 *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE;
00754 *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS;
00755 } else {
00756 *((u_char*)nb->payload + nb->len++) = c;
00757 }
00758 }
00759
00760 return tb;
00761 }
00762 #endif
00763
00764 #if PPPOE_SUPPORT
00765 static err_t
00766 pppifOutputOverEthernet(int pd, struct pbuf *p)
00767 {
00768 PPPControl *pc = &pppControl[pd];
00769 struct pbuf *pb;
00770 u_short protocol = PPP_IP;
00771 int i=0;
00772 u16_t tot_len;
00773
00774
00775 pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM);
00776 if(!pb) {
00777 LINK_STATS_INC(link.memerr);
00778 LINK_STATS_INC(link.proterr);
00779 snmp_inc_ifoutdiscards(&pc->netif);
00780 return ERR_MEM;
00781 }
00782
00783 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN);
00784
00785 pc->lastXMit = sys_jiffies();
00786
00787 if (!pc->pcomp || protocol > 0xFF) {
00788 *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF;
00789 }
00790 *((u_char*)pb->payload + i) = protocol & 0xFF;
00791
00792 pbuf_chain(pb, p);
00793 tot_len = pb->tot_len;
00794
00795 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
00796 LINK_STATS_INC(link.err);
00797 snmp_inc_ifoutdiscards(&pc->netif);
00798 return PPPERR_DEVICE;
00799 }
00800
00801 snmp_add_ifoutoctets(&pc->netif, tot_len);
00802 snmp_inc_ifoutucastpkts(&pc->netif);
00803 LINK_STATS_INC(link.xmit);
00804 return ERR_OK;
00805 }
00806 #endif
00807
00808
00809 static err_t
00810 pppifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr)
00811 {
00812 int pd = (int)(size_t)netif->state;
00813 PPPControl *pc = &pppControl[pd];
00814 #if PPPOS_SUPPORT
00815 u_short protocol = PPP_IP;
00816 u_int fcsOut = PPP_INITFCS;
00817 struct pbuf *headMB = NULL, *tailMB = NULL, *p;
00818 u_char c;
00819 #endif
00820
00821 LWIP_UNUSED_ARG(ipaddr);
00822
00823
00824
00825
00826 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
00827 PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n",
00828 pd, PPP_IP, pb));
00829 LINK_STATS_INC(link.opterr);
00830 LINK_STATS_INC(link.drop);
00831 snmp_inc_ifoutdiscards(netif);
00832 return ERR_ARG;
00833 }
00834
00835
00836 if (lcp_phase[pd] == PHASE_DEAD) {
00837 PPPDEBUG(LOG_ERR, ("pppifOutput[%d]: link not up\n", pd));
00838 LINK_STATS_INC(link.rterr);
00839 LINK_STATS_INC(link.drop);
00840 snmp_inc_ifoutdiscards(netif);
00841 return ERR_RTE;
00842 }
00843
00844 #if PPPOE_SUPPORT
00845 if(pc->ethif) {
00846 return pppifOutputOverEthernet(pd, pb);
00847 }
00848 #endif
00849
00850 #if PPPOS_SUPPORT
00851
00852 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
00853 if (headMB == NULL) {
00854 PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: first alloc fail\n", pd));
00855 LINK_STATS_INC(link.memerr);
00856 LINK_STATS_INC(link.drop);
00857 snmp_inc_ifoutdiscards(netif);
00858 return ERR_MEM;
00859 }
00860
00861 #if VJ_SUPPORT
00862
00863
00864
00865
00866 if (protocol == PPP_IP && pc->vjEnabled) {
00867 switch (vj_compress_tcp(&pc->vjComp, pb)) {
00868 case TYPE_IP:
00869
00870
00871 break;
00872 case TYPE_COMPRESSED_TCP:
00873 protocol = PPP_VJC_COMP;
00874 break;
00875 case TYPE_UNCOMPRESSED_TCP:
00876 protocol = PPP_VJC_UNCOMP;
00877 break;
00878 default:
00879 PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad IP packet\n", pd));
00880 LINK_STATS_INC(link.proterr);
00881 LINK_STATS_INC(link.drop);
00882 snmp_inc_ifoutdiscards(netif);
00883 pbuf_free(headMB);
00884 return ERR_VAL;
00885 }
00886 }
00887 #endif
00888
00889 tailMB = headMB;
00890
00891
00892 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
00893 tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
00894 }
00895
00896 pc->lastXMit = sys_jiffies();
00897 if (!pc->accomp) {
00898 fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
00899 tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM);
00900 fcsOut = PPP_FCS(fcsOut, PPP_UI);
00901 tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM);
00902 }
00903 if (!pc->pcomp || protocol > 0xFF) {
00904 c = (protocol >> 8) & 0xFF;
00905 fcsOut = PPP_FCS(fcsOut, c);
00906 tailMB = pppAppend(c, tailMB, &pc->outACCM);
00907 }
00908 c = protocol & 0xFF;
00909 fcsOut = PPP_FCS(fcsOut, c);
00910 tailMB = pppAppend(c, tailMB, &pc->outACCM);
00911
00912
00913 for(p = pb; p; p = p->next) {
00914 int n;
00915 u_char *sPtr;
00916
00917 sPtr = (u_char*)p->payload;
00918 n = p->len;
00919 while (n-- > 0) {
00920 c = *sPtr++;
00921
00922
00923 fcsOut = PPP_FCS(fcsOut, c);
00924
00925
00926 tailMB = pppAppend(c, tailMB, &pc->outACCM);
00927 }
00928 }
00929
00930
00931 c = ~fcsOut & 0xFF;
00932 tailMB = pppAppend(c, tailMB, &pc->outACCM);
00933 c = (~fcsOut >> 8) & 0xFF;
00934 tailMB = pppAppend(c, tailMB, &pc->outACCM);
00935 tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
00936
00937
00938 if (!tailMB) {
00939 PPPDEBUG(LOG_WARNING,
00940 ("pppifOutput[%d]: Alloc err - dropping proto=%d\n",
00941 pd, protocol));
00942 pbuf_free(headMB);
00943 LINK_STATS_INC(link.memerr);
00944 LINK_STATS_INC(link.drop);
00945 snmp_inc_ifoutdiscards(netif);
00946 return ERR_MEM;
00947 }
00948
00949
00950 PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol));
00951
00952 nPut(pc, headMB);
00953 #endif
00954
00955 return ERR_OK;
00956 }
00957
00958
00959
00960 int
00961 pppIOCtl(int pd, int cmd, void *arg)
00962 {
00963 PPPControl *pc = &pppControl[pd];
00964 int st = 0;
00965
00966 if (pd < 0 || pd >= NUM_PPP) {
00967 st = PPPERR_PARAM;
00968 } else {
00969 switch(cmd) {
00970 case PPPCTLG_UPSTATUS:
00971 if (arg) {
00972 *(int *)arg = (int)(pc->if_up);
00973 } else {
00974 st = PPPERR_PARAM;
00975 }
00976 break;
00977 case PPPCTLS_ERRCODE:
00978 if (arg) {
00979 pc->errCode = *(int *)arg;
00980 } else {
00981 st = PPPERR_PARAM;
00982 }
00983 break;
00984 case PPPCTLG_ERRCODE:
00985 if (arg) {
00986 *(int *)arg = (int)(pc->errCode);
00987 } else {
00988 st = PPPERR_PARAM;
00989 }
00990 break;
00991 #if PPPOS_SUPPORT
00992 case PPPCTLG_FD:
00993 if (arg) {
00994 *(sio_fd_t *)arg = pc->fd;
00995 } else {
00996 st = PPPERR_PARAM;
00997 }
00998 break;
00999 #endif
01000 default:
01001 st = PPPERR_PARAM;
01002 break;
01003 }
01004 }
01005
01006 return st;
01007 }
01008
01009
01010
01011
01012 u_short
01013 pppMTU(int pd)
01014 {
01015 PPPControl *pc = &pppControl[pd];
01016 u_short st;
01017
01018
01019 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
01020 st = 0;
01021 } else {
01022 st = pc->mtu;
01023 }
01024
01025 return st;
01026 }
01027
01028 #if PPPOE_SUPPORT
01029 int
01030 pppWriteOverEthernet(int pd, const u_char *s, int n)
01031 {
01032 PPPControl *pc = &pppControl[pd];
01033 struct pbuf *pb;
01034
01035
01036 s += 2;
01037 n -= 2;
01038
01039 LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff);
01040 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM);
01041 if(!pb) {
01042 LINK_STATS_INC(link.memerr);
01043 LINK_STATS_INC(link.proterr);
01044 snmp_inc_ifoutdiscards(&pc->netif);
01045 return PPPERR_ALLOC;
01046 }
01047
01048 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN);
01049
01050 pc->lastXMit = sys_jiffies();
01051
01052 MEMCPY(pb->payload, s, n);
01053
01054 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
01055 LINK_STATS_INC(link.err);
01056 snmp_inc_ifoutdiscards(&pc->netif);
01057 return PPPERR_DEVICE;
01058 }
01059
01060 snmp_add_ifoutoctets(&pc->netif, (u16_t)n);
01061 snmp_inc_ifoutucastpkts(&pc->netif);
01062 LINK_STATS_INC(link.xmit);
01063 return PPPERR_NONE;
01064 }
01065 #endif
01066
01067
01068
01069
01070
01071
01072 int
01073 pppWrite(int pd, const u_char *s, int n)
01074 {
01075 PPPControl *pc = &pppControl[pd];
01076 #if PPPOS_SUPPORT
01077 u_char c;
01078 u_int fcsOut;
01079 struct pbuf *headMB, *tailMB;
01080 #endif
01081
01082 #if PPPOE_SUPPORT
01083 if(pc->ethif) {
01084 return pppWriteOverEthernet(pd, s, n);
01085 }
01086 #endif
01087
01088 #if PPPOS_SUPPORT
01089 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
01090 if (headMB == NULL) {
01091 LINK_STATS_INC(link.memerr);
01092 LINK_STATS_INC(link.proterr);
01093 snmp_inc_ifoutdiscards(&pc->netif);
01094 return PPPERR_ALLOC;
01095 }
01096
01097 tailMB = headMB;
01098
01099
01100
01101 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
01102 tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
01103 }
01104 pc->lastXMit = sys_jiffies();
01105
01106 fcsOut = PPP_INITFCS;
01107
01108 while (n-- > 0) {
01109 c = *s++;
01110
01111
01112 fcsOut = PPP_FCS(fcsOut, c);
01113
01114
01115 tailMB = pppAppend(c, tailMB, &pc->outACCM);
01116 }
01117
01118
01119 c = ~fcsOut & 0xFF;
01120 tailMB = pppAppend(c, tailMB, &pc->outACCM);
01121 c = (~fcsOut >> 8) & 0xFF;
01122 tailMB = pppAppend(c, tailMB, &pc->outACCM);
01123 tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
01124
01125
01126
01127 if (!tailMB) {
01128 PPPDEBUG(LOG_WARNING,
01129 ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
01130
01131 pbuf_free(headMB);
01132 LINK_STATS_INC(link.memerr);
01133 LINK_STATS_INC(link.proterr);
01134 snmp_inc_ifoutdiscards(&pc->netif);
01135 return PPPERR_ALLOC;
01136 }
01137
01138 PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len));
01139
01140 nPut(pc, headMB);
01141 #endif
01142
01143 return PPPERR_NONE;
01144 }
01145
01146
01147
01148
01149
01150 void
01151 ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp)
01152 {
01153 PPPControl *pc = &pppControl[unit];
01154 int i;
01155
01156 pc->mtu = mtu;
01157 pc->pcomp = pcomp;
01158 pc->accomp = accomp;
01159
01160
01161 for (i = 0; i < 32/8; i++) {
01162 pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF);
01163 }
01164 PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n",
01165 unit,
01166 pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
01167 }
01168
01169
01170
01171
01172
01173 void
01174 ppp_set_xaccm(int unit, ext_accm *accm)
01175 {
01176 SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm));
01177 PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
01178 unit,
01179 pppControl[unit].outACCM[0],
01180 pppControl[unit].outACCM[1],
01181 pppControl[unit].outACCM[2],
01182 pppControl[unit].outACCM[3]));
01183 }
01184
01185
01186
01187
01188
01189
01190 void
01191 ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp)
01192 {
01193 PPPControl *pc = &pppControl[unit];
01194 int i;
01195 SYS_ARCH_DECL_PROTECT(lev);
01196
01197 LWIP_UNUSED_ARG(accomp);
01198 LWIP_UNUSED_ARG(pcomp);
01199 LWIP_UNUSED_ARG(mru);
01200
01201
01202 SYS_ARCH_PROTECT(lev);
01203 for (i = 0; i < 32 / 8; i++) {
01204
01205 pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8));
01206 }
01207 SYS_ARCH_UNPROTECT(lev);
01208 PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
01209 unit,
01210 pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3]));
01211 }
01212
01213 #if 0
01214
01215
01216
01217
01218
01219
01220 int
01221 ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr)
01222 {
01223 return 0;
01224 }
01225
01226
01227
01228
01229 void
01230 ccp_flags_set(int unit, int isopen, int isup)
01231 {
01232
01233 }
01234
01235
01236
01237
01238
01239
01240 int
01241 ccp_fatal_error(int unit)
01242 {
01243
01244 return 0;
01245 }
01246 #endif
01247
01248
01249
01250
01251 int
01252 get_idle_time(int u, struct ppp_idle *ip)
01253 {
01254
01255 LWIP_UNUSED_ARG(u);
01256 LWIP_UNUSED_ARG(ip);
01257
01258 return 0;
01259 }
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 u32_t
01271 GetMask(u32_t addr)
01272 {
01273 u32_t mask, nmask;
01274
01275 addr = htonl(addr);
01276 if (IP_CLASSA(addr)) {
01277 nmask = IP_CLASSA_NET;
01278 } else if (IP_CLASSB(addr)) {
01279 nmask = IP_CLASSB_NET;
01280 } else {
01281 nmask = IP_CLASSC_NET;
01282 }
01283
01284
01285 mask = subnetMask | htonl(nmask);
01286
01287
01288
01289
01290
01291
01292 return mask;
01293 }
01294
01295
01296
01297
01298 int
01299 sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid)
01300 {
01301 #if PPPOS_SUPPORT && VJ_SUPPORT
01302 PPPControl *pc = &pppControl[pd];
01303
01304 pc->vjEnabled = vjcomp;
01305 pc->vjComp.compressSlot = cidcomp;
01306 pc->vjComp.maxSlotIndex = maxcid;
01307 PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
01308 vjcomp, cidcomp, maxcid));
01309 #else
01310 LWIP_UNUSED_ARG(pd);
01311 LWIP_UNUSED_ARG(vjcomp);
01312 LWIP_UNUSED_ARG(cidcomp);
01313 LWIP_UNUSED_ARG(maxcid);
01314 #endif
01315
01316 return 0;
01317 }
01318
01319
01320
01321
01322 static err_t
01323 pppifNetifInit(struct netif *netif)
01324 {
01325 netif->name[0] = 'p';
01326 netif->name[1] = 'p';
01327 netif->output = pppifOutput;
01328 netif->mtu = pppMTU((int)(size_t)netif->state);
01329 netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP;
01330 #if LWIP_NETIF_HOSTNAME
01331
01332
01333 #endif
01334 return ERR_OK;
01335 }
01336
01337
01338
01339
01340
01341 int
01342 sifup(int pd)
01343 {
01344 PPPControl *pc = &pppControl[pd];
01345 int st = 1;
01346
01347 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
01348 st = 0;
01349 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
01350 } else {
01351 netif_remove(&pc->netif);
01352 if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask,
01353 &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppifNetifInit, ip_input)) {
01354 netif_set_up(&pc->netif);
01355 pc->if_up = 1;
01356 pc->errCode = PPPERR_NONE;
01357
01358 PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
01359 if (pc->linkStatusCB) {
01360 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
01361 }
01362 } else {
01363 st = 0;
01364 PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd));
01365 }
01366 }
01367
01368 return st;
01369 }
01370
01371
01372
01373
01374 int
01375 sifnpmode(int u, int proto, enum NPmode mode)
01376 {
01377 LWIP_UNUSED_ARG(u);
01378 LWIP_UNUSED_ARG(proto);
01379 LWIP_UNUSED_ARG(mode);
01380 return 0;
01381 }
01382
01383
01384
01385
01386 int
01387 sifdown(int pd)
01388 {
01389 PPPControl *pc = &pppControl[pd];
01390 int st = 1;
01391
01392 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
01393 st = 0;
01394 PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd));
01395 } else {
01396 pc->if_up = 0;
01397
01398 netif_set_down(&pc->netif);
01399 netif_remove(&pc->netif);
01400 PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
01401 if (pc->linkStatusCB) {
01402 pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
01403 }
01404 }
01405 return st;
01406 }
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417 int
01418 sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2)
01419 {
01420 PPPControl *pc = &pppControl[pd];
01421 int st = 1;
01422
01423 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
01424 st = 0;
01425 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
01426 } else {
01427 SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o));
01428 SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h));
01429 SMEMCPY(&pc->addrs.netmask, &m, sizeof(m));
01430 SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1));
01431 SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2));
01432 }
01433 return st;
01434 }
01435
01436
01437
01438
01439
01440
01441
01442
01443 int
01444 cifaddr( int pd, u32_t o, u32_t h)
01445 {
01446 PPPControl *pc = &pppControl[pd];
01447 int st = 1;
01448
01449 LWIP_UNUSED_ARG(o);
01450 LWIP_UNUSED_ARG(h);
01451 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
01452 st = 0;
01453 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
01454 } else {
01455 IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
01456 IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
01457 IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
01458 IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
01459 IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
01460 }
01461 return st;
01462 }
01463
01464
01465
01466
01467 int
01468 sifdefaultroute(int pd, u32_t l, u32_t g)
01469 {
01470 PPPControl *pc = &pppControl[pd];
01471 int st = 1;
01472
01473 LWIP_UNUSED_ARG(l);
01474 LWIP_UNUSED_ARG(g);
01475
01476 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
01477 st = 0;
01478 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
01479 } else {
01480 netif_set_default(&pc->netif);
01481 }
01482
01483
01484
01485 return st;
01486 }
01487
01488
01489
01490
01491 int
01492 cifdefaultroute(int pd, u32_t l, u32_t g)
01493 {
01494 PPPControl *pc = &pppControl[pd];
01495 int st = 1;
01496
01497 LWIP_UNUSED_ARG(l);
01498 LWIP_UNUSED_ARG(g);
01499
01500 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
01501 st = 0;
01502 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
01503 } else {
01504 netif_set_default(NULL);
01505 }
01506
01507 return st;
01508 }
01509
01510
01511
01512
01513
01514 #if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD
01515
01516
01517 static void
01518 pppInputThread(void *arg)
01519 {
01520 int count;
01521 PPPControlRx *pcrx = arg;
01522
01523 while (lcp_phase[pcrx->pd] != PHASE_DEAD) {
01524 count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE);
01525 if(count > 0) {
01526 pppInProc(pcrx, pcrx->rxbuf, count);
01527 } else {
01528
01529 sys_msleep(1);
01530 }
01531 }
01532 }
01533 #endif
01534
01535 #if PPPOE_SUPPORT
01536
01537 void
01538 pppOverEthernetInitFailed(int pd)
01539 {
01540 PPPControl* pc;
01541
01542 pppHup(pd);
01543 pppStop(pd);
01544
01545 pc = &pppControl[pd];
01546 pppoe_destroy(&pc->netif);
01547 pc->openFlag = 0;
01548
01549 if(pc->linkStatusCB) {
01550 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
01551 }
01552 }
01553
01554 static void
01555 pppOverEthernetLinkStatusCB(int pd, int up)
01556 {
01557 if(up) {
01558 PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd));
01559 pppStart(pd);
01560 } else {
01561 pppOverEthernetInitFailed(pd);
01562 }
01563 }
01564 #endif
01565
01566 struct pbuf *
01567 pppSingleBuf(struct pbuf *p)
01568 {
01569 struct pbuf *q, *b;
01570 u_char *pl;
01571
01572 if(p->tot_len == p->len) {
01573 return p;
01574 }
01575
01576 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
01577 if(!q) {
01578 PPPDEBUG(LOG_ERR,
01579 ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len));
01580 return p;
01581 }
01582
01583 for(b = p, pl = q->payload; b != NULL; b = b->next) {
01584 MEMCPY(pl, b->payload, b->len);
01585 pl += b->len;
01586 }
01587
01588 pbuf_free(p);
01589
01590 return q;
01591 }
01592
01593 struct pppInputHeader {
01594 int unit;
01595 u16_t proto;
01596 };
01597
01598
01599
01600
01601
01602 static void
01603 pppInput(void *arg)
01604 {
01605 struct pbuf *nb = (struct pbuf *)arg;
01606 u16_t protocol;
01607 int pd;
01608
01609 pd = ((struct pppInputHeader *)nb->payload)->unit;
01610 protocol = ((struct pppInputHeader *)nb->payload)->proto;
01611
01612 if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) {
01613 LWIP_ASSERT("pbuf_header failed\n", 0);
01614 goto drop;
01615 }
01616
01617 LINK_STATS_INC(link.recv);
01618 snmp_inc_ifinucastpkts(&pppControl[pd].netif);
01619 snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len);
01620
01621
01622
01623
01624
01625
01626 if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) {
01627 if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) ||
01628 (lcp_phase[pd] != PHASE_AUTHENTICATE)) {
01629 PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd]));
01630 goto drop;
01631 }
01632 }
01633
01634 switch(protocol) {
01635 case PPP_VJC_COMP:
01636 #if PPPOS_SUPPORT && VJ_SUPPORT
01637 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
01638
01639
01640
01641
01642 if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) {
01643 pppControl[pd].netif.input(nb, &pppControl[pd].netif);
01644 return;
01645 }
01646
01647 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd));
01648 #else
01649
01650 PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
01651 #endif
01652 break;
01653
01654 case PPP_VJC_UNCOMP:
01655 #if PPPOS_SUPPORT && VJ_SUPPORT
01656 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
01657
01658
01659
01660
01661 if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) {
01662 pppControl[pd].netif.input(nb, &pppControl[pd].netif);
01663 return;
01664 }
01665
01666 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd));
01667 #else
01668
01669 PPPDEBUG(LOG_INFO,
01670 ("pppInput[%d]: drop VJ UnComp in %d:.*H\n",
01671 pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
01672 #endif
01673 break;
01674
01675 case PPP_IP:
01676 PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
01677 if (pppControl[pd].netif.input) {
01678 pppControl[pd].netif.input(nb, &pppControl[pd].netif);
01679 return;
01680 }
01681 break;
01682
01683 default: {
01684 struct protent *protp;
01685 int i;
01686
01687
01688
01689
01690 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
01691 if (protp->protocol == protocol && protp->enabled_flag) {
01692 PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
01693 nb = pppSingleBuf(nb);
01694 (*protp->input)(pd, nb->payload, nb->len);
01695 PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd));
01696 goto out;
01697 }
01698 }
01699
01700
01701 PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len));
01702 if (pbuf_header(nb, sizeof(protocol))) {
01703 LWIP_ASSERT("pbuf_header failed\n", 0);
01704 goto drop;
01705 }
01706 #if BYTE_ORDER == LITTLE_ENDIAN
01707 protocol = htons(protocol);
01708 #endif
01709 SMEMCPY(nb->payload, &protocol, sizeof(protocol));
01710 lcp_sprotrej(pd, nb->payload, nb->len);
01711 }
01712 break;
01713 }
01714
01715 drop:
01716 LINK_STATS_INC(link.drop);
01717 snmp_inc_ifindiscards(&pppControl[pd].netif);
01718
01719 out:
01720 pbuf_free(nb);
01721 return;
01722 }
01723
01724 #if PPPOS_SUPPORT
01725
01726
01727
01728 static void
01729 pppFreeCurrentInputPacket(PPPControlRx *pcrx)
01730 {
01731 if (pcrx->inHead != NULL) {
01732 if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) {
01733 pbuf_free(pcrx->inTail);
01734 }
01735 pbuf_free(pcrx->inHead);
01736 pcrx->inHead = NULL;
01737 }
01738 pcrx->inTail = NULL;
01739 }
01740
01741
01742
01743
01744 static void
01745 pppDrop(PPPControlRx *pcrx)
01746 {
01747 if (pcrx->inHead != NULL) {
01748 #if 0
01749 PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload));
01750 #endif
01751 PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead));
01752 }
01753 pppFreeCurrentInputPacket(pcrx);
01754 #if VJ_SUPPORT
01755 vj_uncompress_err(&pppControl[pcrx->pd].vjComp);
01756 #endif
01757
01758 LINK_STATS_INC(link.drop);
01759 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
01760 }
01761
01762 #if !PPP_INPROC_OWNTHREAD
01763
01764
01765
01766
01767
01768
01769
01770 void
01771 pppos_input(int pd, u_char* data, int len)
01772 {
01773 pppInProc(&pppControl[pd].rx, data, len);
01774 }
01775 #endif
01776
01777
01778
01779
01780 static void
01781 pppInProc(PPPControlRx *pcrx, u_char *s, int l)
01782 {
01783 struct pbuf *nextNBuf;
01784 u_char curChar;
01785 u_char escaped;
01786 SYS_ARCH_DECL_PROTECT(lev);
01787
01788 PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l));
01789 while (l-- > 0) {
01790 curChar = *s++;
01791
01792 SYS_ARCH_PROTECT(lev);
01793 escaped = ESCAPE_P(pcrx->inACCM, curChar);
01794 SYS_ARCH_UNPROTECT(lev);
01795
01796 if (escaped) {
01797
01798
01799
01800
01801
01802 if (curChar == PPP_ESCAPE) {
01803 pcrx->inEscaped = 1;
01804
01805 } else if (curChar == PPP_FLAG) {
01806
01807 if (pcrx->inState <= PDADDRESS) {
01808 ;
01809
01810 } else if (pcrx->inState < PDDATA) {
01811 PPPDEBUG(LOG_WARNING,
01812 ("pppInProc[%d]: Dropping incomplete packet %d\n",
01813 pcrx->pd, pcrx->inState));
01814 LINK_STATS_INC(link.lenerr);
01815 pppDrop(pcrx);
01816
01817 } else if (pcrx->inFCS != PPP_GOODFCS) {
01818 PPPDEBUG(LOG_INFO,
01819 ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n",
01820 pcrx->pd, pcrx->inFCS, pcrx->inProtocol));
01821
01822 LINK_STATS_INC(link.chkerr);
01823 pppDrop(pcrx);
01824
01825 } else {
01826 struct pbuf *inp;
01827
01828 if(pcrx->inTail->len >= 2) {
01829 pcrx->inTail->len -= 2;
01830
01831 pcrx->inTail->tot_len = pcrx->inTail->len;
01832 if (pcrx->inTail != pcrx->inHead) {
01833 pbuf_cat(pcrx->inHead, pcrx->inTail);
01834 }
01835 } else {
01836 pcrx->inTail->tot_len = pcrx->inTail->len;
01837 if (pcrx->inTail != pcrx->inHead) {
01838 pbuf_cat(pcrx->inHead, pcrx->inTail);
01839 }
01840
01841 pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2);
01842 }
01843
01844
01845 inp = pcrx->inHead;
01846
01847 pcrx->inHead = NULL;
01848 pcrx->inTail = NULL;
01849 #if PPP_INPROC_MULTITHREADED
01850 if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) {
01851 PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd));
01852 pbuf_free(inp);
01853 LINK_STATS_INC(link.drop);
01854 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
01855 }
01856 #else
01857 pppInput(inp);
01858 #endif
01859 }
01860
01861
01862 pcrx->inFCS = PPP_INITFCS;
01863 pcrx->inState = PDADDRESS;
01864 pcrx->inEscaped = 0;
01865
01866
01867 } else {
01868 PPPDEBUG(LOG_WARNING,
01869 ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar));
01870 }
01871
01872 } else {
01873
01874 if (pcrx->inEscaped) {
01875 pcrx->inEscaped = 0;
01876 curChar ^= PPP_TRANS;
01877 }
01878
01879
01880 switch(pcrx->inState) {
01881 case PDIDLE:
01882
01883
01884 if (curChar != PPP_ALLSTATIONS) {
01885 break;
01886 }
01887
01888
01889 case PDSTART:
01890
01891 pcrx->inFCS = PPP_INITFCS;
01892
01893
01894 case PDADDRESS:
01895 if (curChar == PPP_ALLSTATIONS) {
01896 pcrx->inState = PDCONTROL;
01897 break;
01898 }
01899
01900
01901 case PDCONTROL:
01902
01903 if (curChar == PPP_UI) {
01904 pcrx->inState = PDPROTOCOL1;
01905 break;
01906 }
01907 #if 0
01908 else {
01909 PPPDEBUG(LOG_WARNING,
01910 ("pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar));
01911 pcrx->inState = PDSTART;
01912 }
01913 #endif
01914 case PDPROTOCOL1:
01915
01916
01917 if (curChar & 1) {
01918 pcrx->inProtocol = curChar;
01919 pcrx->inState = PDDATA;
01920 } else {
01921 pcrx->inProtocol = (u_int)curChar << 8;
01922 pcrx->inState = PDPROTOCOL2;
01923 }
01924 break;
01925 case PDPROTOCOL2:
01926 pcrx->inProtocol |= curChar;
01927 pcrx->inState = PDDATA;
01928 break;
01929 case PDDATA:
01930
01931 if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) {
01932 if (pcrx->inTail != NULL) {
01933 pcrx->inTail->tot_len = pcrx->inTail->len;
01934 if (pcrx->inTail != pcrx->inHead) {
01935 pbuf_cat(pcrx->inHead, pcrx->inTail);
01936
01937 pcrx->inTail = NULL;
01938 }
01939 }
01940
01941 nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
01942 if (nextNBuf == NULL) {
01943
01944
01945
01946 PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd));
01947 LINK_STATS_INC(link.memerr);
01948 pppDrop(pcrx);
01949 pcrx->inState = PDSTART;
01950 break;
01951 }
01952 if (pcrx->inHead == NULL) {
01953 struct pppInputHeader *pih = nextNBuf->payload;
01954
01955 pih->unit = pcrx->pd;
01956 pih->proto = pcrx->inProtocol;
01957
01958 nextNBuf->len += sizeof(*pih);
01959
01960 pcrx->inHead = nextNBuf;
01961 }
01962 pcrx->inTail = nextNBuf;
01963 }
01964
01965 ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar;
01966 break;
01967 }
01968
01969
01970 pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar);
01971 }
01972 }
01973
01974 avRandomize();
01975 }
01976 #endif
01977
01978 #if PPPOE_SUPPORT
01979 void
01980 pppInProcOverEthernet(int pd, struct pbuf *pb)
01981 {
01982 struct pppInputHeader *pih;
01983 u16_t inProtocol;
01984
01985 if(pb->len < sizeof(inProtocol)) {
01986 PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n"));
01987 goto drop;
01988 }
01989
01990 inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1];
01991
01992
01993 if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) {
01994 PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n"));
01995 goto drop;
01996 }
01997
01998 pih = pb->payload;
01999
02000 pih->unit = pd;
02001 pih->proto = inProtocol;
02002
02003
02004 pppInput(pb);
02005 return;
02006
02007 drop:
02008 LINK_STATS_INC(link.drop);
02009 snmp_inc_ifindiscards(&pppControl[pd].netif);
02010 pbuf_free(pb);
02011 return;
02012 }
02013 #endif
02014
02015 #if LWIP_NETIF_STATUS_CALLBACK
02016
02017
02018
02019
02020
02021
02022
02023 void
02024 ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback)
02025 {
02026 netif_set_status_callback(&pppControl[pd].netif, status_callback);
02027 }
02028 #endif
02029
02030 #if LWIP_NETIF_LINK_CALLBACK
02031
02032
02033
02034
02035
02036
02037
02038 void
02039 ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback)
02040 {
02041 netif_set_link_callback(&pppControl[pd].netif, link_callback);
02042 }
02043 #endif
02044
02045 #endif