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