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 #include "lwip/opt.h"
00072
00073 #if PPPOE_SUPPORT
00074
00075 #include "ppp.h"
00076 #include "pppdebug.h"
00077
00078 #include "lwip/sys.h"
00079
00080 #include "netif/ppp_oe.h"
00081 #include "netif/etharp.h"
00082
00083 #include <string.h>
00084 #include <stdio.h>
00085
00086
00087 #ifndef _SYS_QUEUE_H_
00088 #define _SYS_QUEUE_H_
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 #define LIST_HEAD(name, type) \
00105 struct name { \
00106 struct type *lh_first; \
00107 }
00108
00109 #define LIST_HEAD_INITIALIZER(head) \
00110 { NULL }
00111
00112 #define LIST_ENTRY(type) \
00113 struct { \
00114 struct type *le_next; \
00115 struct type **le_prev; \
00116 }
00117
00118
00119
00120
00121
00122 #define LIST_EMPTY(head) ((head)->lh_first == NULL)
00123
00124 #define LIST_FIRST(head) ((head)->lh_first)
00125
00126 #define LIST_FOREACH(var, head, field) \
00127 for ((var) = LIST_FIRST((head)); \
00128 (var); \
00129 (var) = LIST_NEXT((var), field))
00130
00131 #define LIST_INIT(head) do { \
00132 LIST_FIRST((head)) = NULL; \
00133 } while (0)
00134
00135 #define LIST_INSERT_AFTER(listelm, elm, field) do { \
00136 if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL) \
00137 LIST_NEXT((listelm), field)->field.le_prev = \
00138 &LIST_NEXT((elm), field); \
00139 LIST_NEXT((listelm), field) = (elm); \
00140 (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
00141 } while (0)
00142
00143 #define LIST_INSERT_BEFORE(listelm, elm, field) do { \
00144 (elm)->field.le_prev = (listelm)->field.le_prev; \
00145 LIST_NEXT((elm), field) = (listelm); \
00146 *(listelm)->field.le_prev = (elm); \
00147 (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
00148 } while (0)
00149
00150 #define LIST_INSERT_HEAD(head, elm, field) do { \
00151 if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
00152 LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field); \
00153 LIST_FIRST((head)) = (elm); \
00154 (elm)->field.le_prev = &LIST_FIRST((head)); \
00155 } while (0)
00156
00157 #define LIST_NEXT(elm, field) ((elm)->field.le_next)
00158
00159 #define LIST_REMOVE(elm, field) do { \
00160 if (LIST_NEXT((elm), field) != NULL) \
00161 LIST_NEXT((elm), field)->field.le_prev = \
00162 (elm)->field.le_prev; \
00163 *(elm)->field.le_prev = LIST_NEXT((elm), field); \
00164 } while (0)
00165
00166 #endif
00167
00168
00169
00170 #define PPPOE_ADD_16(PTR, VAL) \
00171 *(PTR)++ = (VAL) / 256; \
00172 *(PTR)++ = (VAL) % 256
00173
00174
00175 #define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \
00176 *(PTR)++ = PPPOE_VERTYPE; \
00177 *(PTR)++ = (CODE); \
00178 PPPOE_ADD_16(PTR, SESS); \
00179 PPPOE_ADD_16(PTR, LEN)
00180
00181 #define PPPOE_DISC_TIMEOUT (5*1000)
00182 #define PPPOE_SLOW_RETRY (60*1000)
00183 #define PPPOE_DISC_MAXPADI 4
00184 #define PPPOE_DISC_MAXPADR 2
00185
00186 #ifdef PPPOE_SERVER
00187
00188 #define IFF_PASSIVE IFF_LINK0
00189 #endif
00190
00191 struct pppoe_softc {
00192 LIST_ENTRY(pppoe_softc) sc_list;
00193 struct netif *sc_ethif;
00194 int sc_pd;
00195 void (*sc_linkStatusCB)(int pd, int up);
00196
00197 int sc_state;
00198 struct eth_addr sc_dest;
00199 u16_t sc_session;
00200
00201 char *sc_service_name;
00202 char *sc_concentrator_name;
00203 u8_t *sc_ac_cookie;
00204 size_t sc_ac_cookie_len;
00205 #ifdef PPPOE_SERVER
00206 u8_t *sc_hunique;
00207 size_t sc_hunique_len;
00208 #endif
00209 int sc_padi_retried;
00210 int sc_padr_retried;
00211 };
00212
00213
00214 static void pppoe_dispatch_disc_pkt(struct netif *, struct pbuf *);
00215
00216
00217 static int pppoe_do_disconnect(struct pppoe_softc *);
00218 static void pppoe_abort_connect(struct pppoe_softc *);
00219 static void pppoe_clear_softc(struct pppoe_softc *, const char *);
00220
00221
00222 static void pppoe_timeout(void *);
00223
00224
00225 static err_t pppoe_send_padi(struct pppoe_softc *);
00226 static err_t pppoe_send_padr(struct pppoe_softc *);
00227 #ifdef PPPOE_SERVER
00228 static err_t pppoe_send_pado(struct pppoe_softc *);
00229 static err_t pppoe_send_pads(struct pppoe_softc *);
00230 #endif
00231 static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *);
00232
00233
00234 static struct pppoe_softc * pppoe_find_softc_by_session(u_int, struct netif *);
00235 static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct netif *);
00236
00237 static LIST_HEAD(pppoe_softc_head, pppoe_softc) pppoe_softc_list;
00238
00239 int pppoe_hdrlen;
00240
00241 void
00242 pppoe_init(void)
00243 {
00244 pppoe_hdrlen = sizeof(struct eth_hdr) + PPPOE_HEADERLEN;
00245 LIST_INIT(&pppoe_softc_list);
00246 }
00247
00248 err_t
00249 pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr)
00250 {
00251 struct pppoe_softc *sc;
00252
00253 sc = mem_malloc(sizeof(struct pppoe_softc));
00254 if(!sc) {
00255 *scptr = NULL;
00256 return ERR_MEM;
00257 }
00258 memset(sc, 0, sizeof(struct pppoe_softc));
00259
00260
00261 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
00262
00263 sc->sc_pd = pd;
00264 sc->sc_linkStatusCB = linkStatusCB;
00265 sc->sc_ethif = ethif;
00266
00267 LIST_INSERT_HEAD(&pppoe_softc_list, sc, sc_list);
00268
00269 *scptr = sc;
00270
00271 return ERR_OK;
00272 }
00273
00274 err_t
00275 pppoe_destroy(struct netif *ifp)
00276 {
00277 struct pppoe_softc * sc;
00278
00279 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
00280 if (sc->sc_ethif == ifp) {
00281 break;
00282 }
00283 }
00284
00285 if(!(sc && (sc->sc_ethif == ifp))) {
00286 return ERR_IF;
00287 }
00288
00289 tcpip_untimeout(pppoe_timeout, sc);
00290 LIST_REMOVE(sc, sc_list);
00291
00292 if (sc->sc_concentrator_name) {
00293 mem_free(sc->sc_concentrator_name);
00294 }
00295 if (sc->sc_service_name) {
00296 mem_free(sc->sc_service_name);
00297 }
00298 if (sc->sc_ac_cookie) {
00299 mem_free(sc->sc_ac_cookie);
00300 }
00301 mem_free(sc);
00302
00303 return ERR_OK;
00304 }
00305
00306
00307
00308
00309
00310
00311
00312 static struct pppoe_softc *
00313 pppoe_find_softc_by_session(u_int session, struct netif *rcvif)
00314 {
00315 struct pppoe_softc *sc;
00316
00317 if (session == 0) {
00318 return NULL;
00319 }
00320
00321 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
00322 if (sc->sc_state == PPPOE_STATE_SESSION
00323 && sc->sc_session == session) {
00324 if (sc->sc_ethif == rcvif) {
00325 return sc;
00326 } else {
00327 return NULL;
00328 }
00329 }
00330 }
00331 return NULL;
00332 }
00333
00334
00335
00336 static struct pppoe_softc *
00337 pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif)
00338 {
00339 struct pppoe_softc *sc, *t;
00340
00341 if (LIST_EMPTY(&pppoe_softc_list)) {
00342 return NULL;
00343 }
00344
00345 if (len != sizeof sc) {
00346 return NULL;
00347 }
00348 MEMCPY(&t, token, len);
00349
00350 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
00351 if (sc == t) {
00352 break;
00353 }
00354 }
00355
00356 if (sc == NULL) {
00357 PPPDEBUG((LOG_DEBUG, "pppoe: alien host unique tag, no session found\n"));
00358 return NULL;
00359 }
00360
00361
00362 if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) {
00363 printf("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n",
00364 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state);
00365 return NULL;
00366 }
00367 if (sc->sc_ethif != rcvif) {
00368 printf("%c%c%"U16_F": wrong interface, not accepting host unique\n",
00369 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
00370 return NULL;
00371 }
00372 return sc;
00373 }
00374
00375 static void
00376 pppoe_linkstatus_up(void *arg)
00377 {
00378 struct pppoe_softc *sc = (struct pppoe_softc*)arg;
00379
00380 sc->sc_linkStatusCB(sc->sc_pd, 1);
00381 }
00382
00383
00384 static void
00385 pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
00386 {
00387 u16_t tag, len;
00388 u16_t session, plen;
00389 struct pppoe_softc *sc;
00390 const char *err_msg;
00391 char devname[6];
00392 char *error;
00393 u8_t *ac_cookie;
00394 size_t ac_cookie_len;
00395 #ifdef PPPOE_SERVER
00396 u8_t *hunique;
00397 size_t hunique_len;
00398 #endif
00399 struct pppoehdr *ph;
00400 struct pppoetag pt;
00401 int off, err, errortag;
00402 struct eth_hdr *ethhdr;
00403
00404 pb = pppSingleBuf(pb);
00405
00406 strcpy(devname, "pppoe");
00407 err_msg = NULL;
00408 errortag = 0;
00409 if (pb->len < sizeof(*ethhdr)) {
00410 goto done;
00411 }
00412 ethhdr = (struct eth_hdr *)pb->payload;
00413 off = sizeof(*ethhdr);
00414
00415 ac_cookie = NULL;
00416 ac_cookie_len = 0;
00417 #ifdef PPPOE_SERVER
00418 hunique = NULL;
00419 hunique_len = 0;
00420 #endif
00421 session = 0;
00422 if (pb->len - off < PPPOE_HEADERLEN) {
00423 printf("pppoe: packet too short: %d\n", pb->len);
00424 goto done;
00425 }
00426
00427 ph = (struct pppoehdr *) (ethhdr + 1);
00428 if (ph->vertype != PPPOE_VERTYPE) {
00429 printf("pppoe: unknown version/type packet: 0x%x\n", ph->vertype);
00430 goto done;
00431 }
00432 session = ntohs(ph->session);
00433 plen = ntohs(ph->plen);
00434 off += sizeof(*ph);
00435
00436 if (plen + off > pb->len) {
00437 printf("pppoe: packet content does not fit: data available = %d, packet size = %u\n",
00438 pb->len - off, plen);
00439 goto done;
00440 }
00441 if(pb->tot_len == pb->len) {
00442 pb->tot_len = pb->len = off + plen;
00443 }
00444 tag = 0;
00445 len = 0;
00446 sc = NULL;
00447 while (off + sizeof(pt) <= pb->len) {
00448 MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt));
00449 tag = ntohs(pt.tag);
00450 len = ntohs(pt.len);
00451 if (off + sizeof(pt) + len > pb->len) {
00452 printf("pppoe: tag 0x%x len 0x%x is too long\n", tag, len);
00453 goto done;
00454 }
00455 switch (tag) {
00456 case PPPOE_TAG_EOL:
00457 goto breakbreak;
00458 case PPPOE_TAG_SNAME:
00459 break;
00460 case PPPOE_TAG_ACNAME:
00461 break;
00462 case PPPOE_TAG_HUNIQUE:
00463 if (sc != NULL) {
00464 break;
00465 }
00466 #ifdef PPPOE_SERVER
00467 hunique = (u8_t*)pb->payload + off + sizeof(pt);
00468 hunique_len = len;
00469 #endif
00470 sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif);
00471 if (sc != NULL) {
00472 snprintf(devname, sizeof(devname), "%c%c%"U16_F, sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
00473 }
00474 break;
00475 case PPPOE_TAG_ACCOOKIE:
00476 if (ac_cookie == NULL) {
00477 ac_cookie = (u8_t*)pb->payload + off + sizeof(pt);
00478 ac_cookie_len = len;
00479 }
00480 break;
00481 case PPPOE_TAG_SNAME_ERR:
00482 err_msg = "SERVICE NAME ERROR";
00483 errortag = 1;
00484 break;
00485 case PPPOE_TAG_ACSYS_ERR:
00486 err_msg = "AC SYSTEM ERROR";
00487 errortag = 1;
00488 break;
00489 case PPPOE_TAG_GENERIC_ERR:
00490 err_msg = "GENERIC ERROR";
00491 errortag = 1;
00492 break;
00493 }
00494 if (err_msg) {
00495 error = NULL;
00496 if (errortag && len) {
00497 error = mem_malloc(len+1);
00498 if (error) {
00499 strncpy(error, (char*)pb->payload + off + sizeof(pt), len);
00500 error[len-1] = '\0';
00501 }
00502 }
00503 if (error) {
00504 printf("%s: %s: %s\n", devname, err_msg, error);
00505 mem_free(error);
00506 } else {
00507 printf("%s: %s\n", devname, err_msg);
00508 }
00509 if (errortag) {
00510 goto done;
00511 }
00512 }
00513 off += sizeof(pt) + len;
00514 }
00515
00516 breakbreak:;
00517 switch (ph->code) {
00518 case PPPOE_CODE_PADI:
00519 #ifdef PPPOE_SERVER
00520
00521
00522
00523
00524 if (LIST_EMPTY(&pppoe_softc_list)) {
00525 goto done;
00526 }
00527 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
00528 if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) {
00529 continue;
00530 }
00531 if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) {
00532 continue;
00533 }
00534 if (sc->sc_state == PPPOE_STATE_INITIAL) {
00535 break;
00536 }
00537 }
00538 if (sc == NULL) {
00539
00540 goto done;
00541 }
00542 if (hunique) {
00543 if (sc->sc_hunique) {
00544 mem_free(sc->sc_hunique);
00545 }
00546 sc->sc_hunique = mem_malloc(hunique_len);
00547 if (sc->sc_hunique == NULL) {
00548 goto done;
00549 }
00550 sc->sc_hunique_len = hunique_len;
00551 MEMCPY(sc->sc_hunique, hunique, hunique_len);
00552 }
00553 MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest);
00554 sc->sc_state = PPPOE_STATE_PADO_SENT;
00555 pppoe_send_pado(sc);
00556 break;
00557 #endif
00558 case PPPOE_CODE_PADR:
00559 #ifdef PPPOE_SERVER
00560
00561
00562
00563 if (ac_cookie == NULL) {
00564
00565 printf("pppoe: received PADR but not includes ac_cookie\n");
00566 goto done;
00567 }
00568 sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif);
00569 if (sc == NULL) {
00570
00571 if (!LIST_EMPTY(&pppoe_softc_list)) {
00572 printf("pppoe: received PADR but could not find request for it\n");
00573 }
00574 goto done;
00575 }
00576 if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
00577 printf("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
00578 goto done;
00579 }
00580 if (hunique) {
00581 if (sc->sc_hunique) {
00582 mem_free(sc->sc_hunique);
00583 }
00584 sc->sc_hunique = mem_malloc(hunique_len);
00585 if (sc->sc_hunique == NULL) {
00586 goto done;
00587 }
00588 sc->sc_hunique_len = hunique_len;
00589 MEMCPY(sc->sc_hunique, hunique, hunique_len);
00590 }
00591 pppoe_send_pads(sc);
00592 sc->sc_state = PPPOE_STATE_SESSION;
00593 tcpip_timeout (100, pppoe_linkstatus_up, sc);
00594 break;
00595 #else
00596
00597 goto done;
00598 #endif
00599 case PPPOE_CODE_PADO:
00600 if (sc == NULL) {
00601
00602 if (!LIST_EMPTY(&pppoe_softc_list)) {
00603 printf("pppoe: received PADO but could not find request for it\n");
00604 }
00605 goto done;
00606 }
00607 if (sc->sc_state != PPPOE_STATE_PADI_SENT) {
00608 printf("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
00609 goto done;
00610 }
00611 if (ac_cookie) {
00612 if (sc->sc_ac_cookie) {
00613 mem_free(sc->sc_ac_cookie);
00614 }
00615 sc->sc_ac_cookie = mem_malloc(ac_cookie_len);
00616 if (sc->sc_ac_cookie == NULL) {
00617 goto done;
00618 }
00619 sc->sc_ac_cookie_len = ac_cookie_len;
00620 MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len);
00621 }
00622 MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr));
00623 tcpip_untimeout(pppoe_timeout, sc);
00624 sc->sc_padr_retried = 0;
00625 sc->sc_state = PPPOE_STATE_PADR_SENT;
00626 if ((err = pppoe_send_padr(sc)) != 0) {
00627 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
00628 }
00629 tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
00630 break;
00631 case PPPOE_CODE_PADS:
00632 if (sc == NULL) {
00633 goto done;
00634 }
00635 sc->sc_session = session;
00636 tcpip_untimeout(pppoe_timeout, sc);
00637 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session));
00638 sc->sc_state = PPPOE_STATE_SESSION;
00639 tcpip_timeout (100, pppoe_linkstatus_up, sc);
00640 break;
00641 case PPPOE_CODE_PADT:
00642 if (sc == NULL) {
00643 goto done;
00644 }
00645 pppoe_clear_softc(sc, "received PADT");
00646 break;
00647 default:
00648 if(sc) {
00649 printf("%c%c%"U16_F": unknown code (0x%04x) session = 0x%04x\n",
00650 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
00651 ph->code, session);
00652 } else {
00653 printf("pppoe: unknown code (0x%04x) session = 0x%04x\n", ph->code, session);
00654 }
00655 break;
00656 }
00657
00658 done:
00659 pbuf_free(pb);
00660 return;
00661 }
00662
00663 void
00664 pppoe_disc_input(struct netif *netif, struct pbuf *p)
00665 {
00666
00667 if (!LIST_EMPTY(&pppoe_softc_list)) {
00668 pppoe_dispatch_disc_pkt(netif, p);
00669 } else {
00670 pbuf_free(p);
00671 }
00672 }
00673
00674 void
00675 pppoe_data_input(struct netif *netif, struct pbuf *pb)
00676 {
00677 u16_t session, plen;
00678 struct pppoe_softc *sc;
00679 struct pppoehdr *ph;
00680 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS
00681 u8_t shost[ETHER_ADDR_LEN];
00682 #endif
00683
00684 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS
00685 MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost));
00686 #endif
00687 if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) {
00688
00689 PPPDEBUG((LOG_ERR, "pppoe_data_input: pbuf_header failed\n"));
00690 LINK_STATS_INC(link.lenerr);
00691 goto drop;
00692 }
00693
00694 pb = pppSingleBuf (pb);
00695
00696 if (pb->len <= PPPOE_HEADERLEN) {
00697 printf("pppoe (data): dropping too short packet: %d bytes\n", pb->len);
00698 goto drop;
00699 }
00700
00701 if (pb->len < sizeof(*ph)) {
00702 printf("pppoe_data_input: could not get PPPoE header\n");
00703 goto drop;
00704 }
00705 ph = (struct pppoehdr *)pb->payload;
00706
00707 if (ph->vertype != PPPOE_VERTYPE) {
00708 printf("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype);
00709 goto drop;
00710 }
00711 if (ph->code != 0) {
00712 goto drop;
00713 }
00714
00715 session = ntohs(ph->session);
00716 sc = pppoe_find_softc_by_session(session, netif);
00717 if (sc == NULL) {
00718 #ifdef PPPOE_TERM_UNKNOWN_SESSIONS
00719 printf("pppoe: input for unknown session 0x%x, sending PADT\n", session);
00720 pppoe_send_padt(netif, session, shost);
00721 #endif
00722 goto drop;
00723 }
00724
00725 plen = ntohs(ph->plen);
00726
00727 if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) {
00728
00729 PPPDEBUG((LOG_ERR, "pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n"));
00730 LINK_STATS_INC(link.lenerr);
00731 goto drop;
00732 }
00733
00734 PPPDEBUG((LOG_DEBUG, "pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n",
00735 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
00736 pb->len, plen));
00737
00738 if (pb->len < plen) {
00739 goto drop;
00740 }
00741
00742 pppInProcOverEthernet(sc->sc_pd, pb);
00743
00744 return;
00745
00746 drop:
00747 pbuf_free(pb);
00748 }
00749
00750 static err_t
00751 pppoe_output(struct pppoe_softc *sc, struct pbuf *pb)
00752 {
00753 struct eth_hdr *ethhdr;
00754 u16_t etype;
00755 err_t res;
00756
00757 if (!sc->sc_ethif) {
00758 pbuf_free(pb);
00759 return ERR_IF;
00760 }
00761
00762 ethhdr = (struct eth_hdr *)pb->payload;
00763 etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC;
00764 ethhdr->type = htons(etype);
00765 MEMCPY(ethhdr->dest.addr, sc->sc_dest.addr, sizeof(ethhdr->dest.addr));
00766 MEMCPY(ethhdr->src.addr, ((struct eth_addr *)sc->sc_ethif->hwaddr)->addr, sizeof(ethhdr->src.addr));
00767
00768 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n",
00769 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype,
00770 sc->sc_state, sc->sc_session,
00771 sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5],
00772 pb->tot_len));
00773
00774 res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb);
00775
00776 pbuf_free(pb);
00777
00778 return res;
00779 }
00780
00781 static err_t
00782 pppoe_send_padi(struct pppoe_softc *sc)
00783 {
00784 struct pbuf *pb;
00785 u8_t *p;
00786 int len, l1 = 0, l2 = 0;
00787
00788 if (sc->sc_state >PPPOE_STATE_PADI_SENT) {
00789 PPPDEBUG((LOG_ERR, "ERROR: pppoe_send_padi in state %d", sc->sc_state));
00790 }
00791
00792
00793 len = 2 + 2 + 2 + 2 + sizeof sc;
00794 if (sc->sc_service_name != NULL) {
00795 l1 = strlen(sc->sc_service_name);
00796 len += l1;
00797 }
00798 if (sc->sc_concentrator_name != NULL) {
00799 l2 = strlen(sc->sc_concentrator_name);
00800 len += 2 + 2 + l2;
00801 }
00802
00803
00804 pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
00805 if (!pb) {
00806 return ERR_MEM;
00807 }
00808
00809 p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
00810
00811 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, len);
00812 PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
00813 if (sc->sc_service_name != NULL) {
00814 PPPOE_ADD_16(p, l1);
00815 MEMCPY(p, sc->sc_service_name, l1);
00816 p += l1;
00817 } else {
00818 PPPOE_ADD_16(p, 0);
00819 }
00820 if (sc->sc_concentrator_name != NULL) {
00821 PPPOE_ADD_16(p, PPPOE_TAG_ACNAME);
00822 PPPOE_ADD_16(p, l2);
00823 MEMCPY(p, sc->sc_concentrator_name, l2);
00824 p += l2;
00825 }
00826 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
00827 PPPOE_ADD_16(p, sizeof(sc));
00828 MEMCPY(p, &sc, sizeof sc);
00829
00830
00831 return pppoe_output(sc, pb);
00832 }
00833
00834 static void
00835 pppoe_timeout(void *arg)
00836 {
00837 int retry_wait, err;
00838 struct pppoe_softc *sc = (struct pppoe_softc*)arg;
00839
00840 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
00841
00842 switch (sc->sc_state) {
00843 case PPPOE_STATE_PADI_SENT:
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 retry_wait = PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried);
00856
00857 sc->sc_padi_retried++;
00858 if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) {
00859 #if 0
00860 if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) {
00861
00862 retry_wait = PPPOE_SLOW_RETRY;
00863 } else
00864 #endif
00865 {
00866 pppoe_abort_connect(sc);
00867 return;
00868 }
00869 }
00870 if ((err = pppoe_send_padi(sc)) != 0) {
00871 sc->sc_padi_retried--;
00872 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
00873 }
00874 tcpip_timeout(retry_wait, pppoe_timeout, sc);
00875 break;
00876
00877 case PPPOE_STATE_PADR_SENT:
00878 sc->sc_padr_retried++;
00879 if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) {
00880 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
00881 sc->sc_state = PPPOE_STATE_PADI_SENT;
00882 sc->sc_padr_retried = 0;
00883 if ((err = pppoe_send_padi(sc)) != 0) {
00884 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
00885 }
00886 tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc);
00887 return;
00888 }
00889 if ((err = pppoe_send_padr(sc)) != 0) {
00890 sc->sc_padr_retried--;
00891 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
00892 }
00893 tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
00894 break;
00895 case PPPOE_STATE_CLOSING:
00896 pppoe_do_disconnect(sc);
00897 break;
00898 default:
00899 return;
00900 }
00901 }
00902
00903
00904 int
00905 pppoe_connect(struct pppoe_softc *sc)
00906 {
00907 int err;
00908
00909 if (sc->sc_state != PPPOE_STATE_INITIAL) {
00910 return EBUSY;
00911 }
00912
00913 #ifdef PPPOE_SERVER
00914
00915 if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) {
00916 return 0;
00917 }
00918 #endif
00919
00920 sc->sc_state = PPPOE_STATE_PADI_SENT;
00921 sc->sc_padr_retried = 0;
00922 err = pppoe_send_padi(sc);
00923 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
00924 tcpip_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
00925 return err;
00926 }
00927
00928
00929 void
00930 pppoe_disconnect(struct pppoe_softc *sc)
00931 {
00932 if (sc->sc_state < PPPOE_STATE_SESSION) {
00933 return;
00934 }
00935
00936
00937
00938
00939
00940 sc->sc_state = PPPOE_STATE_CLOSING;
00941 tcpip_timeout(20, pppoe_timeout, sc);
00942 }
00943
00944 static int
00945 pppoe_do_disconnect(struct pppoe_softc *sc)
00946 {
00947 int err;
00948
00949 if (sc->sc_state < PPPOE_STATE_SESSION) {
00950 err = EBUSY;
00951 } else {
00952 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
00953 err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest);
00954 }
00955
00956
00957 sc->sc_state = PPPOE_STATE_INITIAL;
00958 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
00959 if (sc->sc_ac_cookie) {
00960 mem_free(sc->sc_ac_cookie);
00961 sc->sc_ac_cookie = NULL;
00962 }
00963 sc->sc_ac_cookie_len = 0;
00964 #ifdef PPPOE_SERVER
00965 if (sc->sc_hunique) {
00966 mem_free(sc->sc_hunique);
00967 sc->sc_hunique = NULL;
00968 }
00969 sc->sc_hunique_len = 0;
00970 #endif
00971 sc->sc_session = 0;
00972
00973 sc->sc_linkStatusCB(sc->sc_pd, 0);
00974
00975 return err;
00976 }
00977
00978
00979 static void
00980 pppoe_abort_connect(struct pppoe_softc *sc)
00981 {
00982 printf("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
00983 sc->sc_state = PPPOE_STATE_CLOSING;
00984
00985 sc->sc_linkStatusCB(sc->sc_pd, 0);
00986
00987
00988 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
00989 sc->sc_state = PPPOE_STATE_INITIAL;
00990 }
00991
00992
00993 static err_t
00994 pppoe_send_padr(struct pppoe_softc *sc)
00995 {
00996 struct pbuf *pb;
00997 u8_t *p;
00998 size_t len, l1 = 0;
00999
01000 if (sc->sc_state != PPPOE_STATE_PADR_SENT) {
01001 return ERR_CONN;
01002 }
01003
01004 len = 2 + 2 + 2 + 2 + sizeof(sc);
01005 if (sc->sc_service_name != NULL) {
01006 l1 = strlen(sc->sc_service_name);
01007 len += l1;
01008 }
01009 if (sc->sc_ac_cookie_len > 0) {
01010 len += 2 + 2 + sc->sc_ac_cookie_len;
01011 }
01012 pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
01013 if (!pb) {
01014 return ERR_MEM;
01015 }
01016 p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
01017 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len);
01018 PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
01019 if (sc->sc_service_name != NULL) {
01020 PPPOE_ADD_16(p, l1);
01021 MEMCPY(p, sc->sc_service_name, l1);
01022 p += l1;
01023 } else {
01024 PPPOE_ADD_16(p, 0);
01025 }
01026 if (sc->sc_ac_cookie_len > 0) {
01027 PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
01028 PPPOE_ADD_16(p, sc->sc_ac_cookie_len);
01029 MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len);
01030 p += sc->sc_ac_cookie_len;
01031 }
01032 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
01033 PPPOE_ADD_16(p, sizeof(sc));
01034 MEMCPY(p, &sc, sizeof sc);
01035
01036 return pppoe_output(sc, pb);
01037 }
01038
01039
01040 static err_t
01041 pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest)
01042 {
01043 struct pbuf *pb;
01044 struct eth_hdr *ethhdr;
01045 err_t res;
01046 u8_t *p;
01047
01048 pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN, PBUF_RAM);
01049 if (!pb) {
01050 return ERR_MEM;
01051 }
01052
01053 ethhdr = (struct eth_hdr *)pb->payload;
01054 ethhdr->type = htons(ETHTYPE_PPPOEDISC);
01055 MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr));
01056 MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr));
01057
01058 p = (u8_t*)(ethhdr + 1);
01059 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0);
01060
01061 res = outgoing_if->linkoutput(outgoing_if, pb);
01062
01063 pbuf_free(pb);
01064
01065 return res;
01066 }
01067
01068 #ifdef PPPOE_SERVER
01069 static err_t
01070 pppoe_send_pado(struct pppoe_softc *sc)
01071 {
01072 struct pbuf *pb;
01073 u8_t *p;
01074 size_t len;
01075
01076 if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
01077 return ERR_CONN;
01078 }
01079
01080
01081 len = 0;
01082
01083 len += 2 + 2 + sizeof(sc);
01084
01085 len += 2 + 2 + sc->sc_hunique_len;
01086 pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
01087 if (!pb) {
01088 return ERR_MEM;
01089 }
01090 p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
01091 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len);
01092 PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
01093 PPPOE_ADD_16(p, sizeof(sc));
01094 MEMCPY(p, &sc, sizeof(sc));
01095 p += sizeof(sc);
01096 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
01097 PPPOE_ADD_16(p, sc->sc_hunique_len);
01098 MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len);
01099 return pppoe_output(sc, pb);
01100 }
01101
01102 static err_t
01103 pppoe_send_pads(struct pppoe_softc *sc)
01104 {
01105 struct pbuf *pb;
01106 u8_t *p;
01107 size_t len, l1 = 0;
01108
01109 if (sc->sc_state != PPPOE_STATE_PADO_SENT) {
01110 return ERR_CONN;
01111 }
01112
01113 sc->sc_session = mono_time.tv_sec % 0xff + 1;
01114
01115 len = 0;
01116
01117 len += 2 + 2 + 2 + 2 + sc->sc_hunique_len;
01118 if (sc->sc_service_name != NULL) {
01119 l1 = strlen(sc->sc_service_name);
01120 len += l1;
01121 }
01122 pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
01123 if (!pb) {
01124 return ERR_MEM;
01125 }
01126 p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
01127 PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len);
01128 PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
01129 if (sc->sc_service_name != NULL) {
01130 PPPOE_ADD_16(p, l1);
01131 MEMCPY(p, sc->sc_service_name, l1);
01132 p += l1;
01133 } else {
01134 PPPOE_ADD_16(p, 0);
01135 }
01136 PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
01137 PPPOE_ADD_16(p, sc->sc_hunique_len);
01138 MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len);
01139 return pppoe_output(sc, pb);
01140 }
01141 #endif
01142
01143 err_t
01144 pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb)
01145 {
01146 u8_t *p;
01147 size_t len;
01148
01149
01150 if (sc->sc_state < PPPOE_STATE_SESSION) {
01151
01152 pbuf_free(pb);
01153 return ERR_CONN;
01154 }
01155
01156 len = pb->tot_len;
01157
01158
01159 if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) {
01160
01161 PPPDEBUG((LOG_ERR, "pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
01162 LINK_STATS_INC(link.lenerr);
01163 pbuf_free(pb);
01164 return ERR_BUF;
01165 }
01166
01167 p = (u8_t*)pb->payload + sizeof(struct eth_hdr);
01168 PPPOE_ADD_HEADER(p, 0, sc->sc_session, len);
01169
01170 return pppoe_output(sc, pb);
01171 }
01172
01173 #if 0
01174 static int
01175 pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir)
01176 {
01177 struct pppoe_softc *sc;
01178 int s;
01179
01180 if (mp != (struct pbuf **)PFIL_IFNET_DETACH) {
01181 return 0;
01182 }
01183
01184 LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
01185 if (sc->sc_ethif != ifp) {
01186 continue;
01187 }
01188 if (sc->sc_sppp.pp_if.if_flags & IFF_UP) {
01189 sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
01190 printf("%c%c%"U16_F": ethernet interface detached, going down\n",
01191 sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num);
01192 }
01193 sc->sc_ethif = NULL;
01194 pppoe_clear_softc(sc, "ethernet interface detached");
01195 }
01196
01197 return 0;
01198 }
01199 #endif
01200
01201 static void
01202 pppoe_clear_softc(struct pppoe_softc *sc, const char *message)
01203 {
01204 LWIP_UNUSED_ARG(message);
01205
01206
01207 tcpip_untimeout(pppoe_timeout, sc);
01208 PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message));
01209
01210
01211 sc->sc_state = PPPOE_STATE_INITIAL;
01212
01213
01214 sc->sc_linkStatusCB(sc->sc_pd, 0);
01215
01216
01217 MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
01218 if (sc->sc_ac_cookie) {
01219 mem_free(sc->sc_ac_cookie);
01220 sc->sc_ac_cookie = NULL;
01221 }
01222 sc->sc_ac_cookie_len = 0;
01223 sc->sc_session = 0;
01224 }
01225
01226 #endif
01227