diff --git a/src/include/netif/ppp_oe.h b/src/include/netif/ppp_oe.h index 8929a616..ada32934 100644 --- a/src/include/netif/ppp_oe.h +++ b/src/include/netif/ppp_oe.h @@ -145,7 +145,7 @@ struct pppoe_softc { struct pppoe_softc *next; struct netif *sc_ethif; /* ethernet interface we are using */ int sc_pd; /* ppp unit number */ - void (*sc_linkStatusCB)(int pd, int up); + void (*sc_link_status_cb)(int pd, int up); int sc_state; /* discovery phase or session connected */ struct eth_addr sc_dest; /* hardware address of concentrator */ @@ -168,7 +168,7 @@ struct pppoe_softc { #define pppoe_init() /* compatibility define, no initialization needed */ -err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr); +err_t pppoe_create(struct netif *ethif, int pd, void (*link_status_cb)(int pd, int up), struct pppoe_softc **scptr); err_t pppoe_destroy(struct netif *ifp); int pppoe_connect(struct pppoe_softc *sc); diff --git a/src/netif/ppp/ppp.c b/src/netif/ppp/ppp.c index bfd20a83..4400078a 100644 --- a/src/netif/ppp/ppp.c +++ b/src/netif/ppp/ppp.c @@ -380,6 +380,7 @@ int ppp_init(void) { memset(&ppp_settings, 0, sizeof(ppp_settings)); ppp_settings.usepeerdns = 1; + ppp_settings.persist = 1; ppp_set_auth(PPPAUTHTYPE_NONE, NULL, NULL); /* @@ -1835,39 +1836,46 @@ struct pbuf * ppp_singlebuf(struct pbuf *p) { #if PPPOE_SUPPORT static void ppp_over_ethernet_link_status_cb(int pd, int state) { - ppp_control *pc = &ppp_control_list[pd]; + int pppoe_err_code = PPPERR_NONE; + ppp_control *pc; switch(state) { + + /* PPPoE link is established, starting PPP negotiation */ case PPPOE_CB_STATE_UP: PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: UP, connecting\n", pd)); ppp_start(pd); - break; + return; - /* FIXME: here we can handle the PPPoE persist, in case of DOWN or FAILED, we just have to - * call pppoe_connect(sc); without setting pc->open_flag to 0. - */ + /* PPPoE link normally down (i.e. asked to do so) */ case PPPOE_CB_STATE_DOWN: PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: DOWN, disconnected\n", pd)); - ppp_hup(pd); - ppp_stop(pd); - pppoe_destroy(&pc->netif); - pc->open_flag = 0; - if(pc->link_status_cb) { - pc->link_status_cb(pc->link_status_ctx, pc->err_code ? pc->err_code : PPPERR_CONNECT, NULL); - } + pppoe_err_code = PPPERR_CONNECT; break; + /* PPPoE link failed to setup (i.e. PADI/PADO timeout */ case PPPOE_CB_STATE_FAILED: PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: FAILED, aborting\n", pd)); - ppp_hup(pd); - ppp_stop(pd); - pppoe_destroy(&pc->netif); - pc->open_flag = 0; - if(pc->link_status_cb) { - pc->link_status_cb(pc->link_status_ctx, pc->err_code ? pc->err_code : PPPERR_PROTOCOL, NULL); - } + pppoe_err_code = PPPERR_OPEN; break; } + + pc = &ppp_control_list[pd]; + + /* Reconnect if persist mode is enabled */ + if(ppp_settings.persist) { + if(pc->link_status_cb) + pc->link_status_cb(pc->link_status_ctx, pc->err_code ? pc->err_code : pppoe_err_code, NULL); + pppoe_connect(pc->pppoe_sc); + return; + } + + ppp_hup(pd); + ppp_stop(pd); + pppoe_destroy(&pc->netif); + pc->open_flag = 0; + if(pc->link_status_cb) + pc->link_status_cb(pc->link_status_ctx, pc->err_code ? pc->err_code : pppoe_err_code, NULL); } #endif /* PPPOE_SUPPORT */ diff --git a/src/netif/ppp/ppp_impl.h b/src/netif/ppp/ppp_impl.h index cfb4cd72..dfdacb64 100644 --- a/src/netif/ppp/ppp_impl.h +++ b/src/netif/ppp/ppp_impl.h @@ -437,6 +437,7 @@ struct ppp_settings { #endif /* EAP_SUPPORT */ u_int usehostname : 1; /* Use hostname for our_name */ u_int usepeerdns : 1; /* Ask peer for DNS adds */ + u_int persist : 1; /* Persist mode, always try to reopen the connection */ u_short idle_time_limit; /* Shut down link if idle for this long */ int maxconnect; /* Maximum connect time (seconds) */ diff --git a/src/netif/ppp/ppp_oe.c b/src/netif/ppp/ppp_oe.c index eef9e7a6..ab71d163 100644 --- a/src/netif/ppp/ppp_oe.c +++ b/src/netif/ppp/ppp_oe.c @@ -141,7 +141,7 @@ static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct n static struct pppoe_softc *pppoe_softc_list; err_t -pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr) +pppoe_create(struct netif *ethif, int pd, void (*link_status_cb)(int pd, int up), struct pppoe_softc **scptr) { struct pppoe_softc *sc; @@ -156,7 +156,7 @@ pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); sc->sc_pd = pd; - sc->sc_linkStatusCB = linkStatusCB; + sc->sc_link_status_cb = link_status_cb; sc->sc_ethif = ethif; /* put the new interface at the head of the list */ @@ -277,7 +277,7 @@ pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) static void pppoe_linkstatus_up(struct pppoe_softc *sc) { - sc->sc_linkStatusCB(sc->sc_pd, PPPOE_CB_STATE_UP); + sc->sc_link_status_cb(sc->sc_pd, PPPOE_CB_STATE_UP); } /* analyze and handle a single received packet while not in session state */ @@ -806,6 +806,12 @@ pppoe_connect(struct pppoe_softc *sc) return EBUSY; } + /* stop any timer */ + sys_untimeout(pppoe_timeout, sc); + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; + #ifdef PPPOE_SERVER /* wait PADI if IFF_PASSIVE */ if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { @@ -814,7 +820,6 @@ pppoe_connect(struct pppoe_softc *sc) #endif /* save state, in case we fail to send PADI */ sc->sc_state = PPPOE_STATE_PADI_SENT; - sc->sc_padr_retried = 0; if ((err = pppoe_send_padi(sc)) != 0) { 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)); } @@ -862,8 +867,10 @@ pppoe_do_disconnect(struct pppoe_softc *sc) sc->sc_hunique_len = 0; #endif sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; - sc->sc_linkStatusCB(sc->sc_pd, PPPOE_CB_STATE_DOWN); /* notify upper layers */ + sc->sc_link_status_cb(sc->sc_pd, PPPOE_CB_STATE_DOWN); /* notify upper layers */ return err; } @@ -872,13 +879,16 @@ static void pppoe_abort_connect(struct pppoe_softc *sc) { PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - sc->sc_state = PPPOE_STATE_CLOSING; - - sc->sc_linkStatusCB(sc->sc_pd, PPPOE_CB_STATE_FAILED); /* notify upper layers */ /* clear connection state */ - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); sc->sc_state = PPPOE_STATE_INITIAL; + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; + + sc->sc_link_status_cb(sc->sc_pd, PPPOE_CB_STATE_FAILED); /* notify upper layers */ } /* Send a PADR packet */ @@ -1112,17 +1122,17 @@ pppoe_clear_softc(struct pppoe_softc *sc, const char *message) /* stop timer */ sys_untimeout(pppoe_timeout, sc); 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)); - /* fix our state */ sc->sc_state = PPPOE_STATE_INITIAL; /* notify upper layers */ - sc->sc_linkStatusCB(sc->sc_pd, PPPOE_CB_STATE_DOWN); + sc->sc_link_status_cb(sc->sc_pd, PPPOE_CB_STATE_DOWN); /* clean up softc */ MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); sc->sc_ac_cookie_len = 0; sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; } - #endif /* PPP_SUPPORT && PPPOE_SUPPORT */