diff --git a/src/api/pppapi.c b/src/api/pppapi.c index 1c112a52..a11145b1 100644 --- a/src/api/pppapi.c +++ b/src/api/pppapi.c @@ -261,6 +261,34 @@ pppapi_open(ppp_pcb *pcb, u16_t holdoff) } +#if PPP_SERVER +/** + * Call ppp_listen() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_listen(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_listen(msg->ppp, msg->msg.listen.addrs); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_listen() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_listen; + msg.msg.ppp = pcb; + msg.msg.msg.listen.addrs = addrs; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} +#endif /* PPP_SERVER */ + + /** * Call ppp_close() inside the tcpip_thread context. */ diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index d190906f..cc5d5d9e 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -2049,7 +2049,9 @@ #endif /** - * PPP_SERVER==1: Enable PPP server support (waiting for incoming PPP session). CURRENTLY NOT SUPPORTED! DO NOT SET! + * PPP_SERVER==1: Enable PPP server support (waiting for incoming PPP session). + * + * Currently only supported for PPPoS. */ #ifndef PPP_SERVER #define PPP_SERVER 0 diff --git a/src/include/lwip/pppapi.h b/src/include/lwip/pppapi.h index f963da7e..65ff6c63 100644 --- a/src/include/lwip/pppapi.h +++ b/src/include/lwip/pppapi.h @@ -92,6 +92,11 @@ struct pppapi_msg_msg { struct { u16_t holdoff; } open; +#if PPP_SERVER + struct { + struct ppp_addrs *addrs; + } listen; +#endif /* PPP_SERVER */ struct { u8_t nocarrier; } close; @@ -127,6 +132,9 @@ ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_add ppp_link_status_cb_fn link_status_cb, void *ctx_cb); #endif /* PPPOL2TP_SUPPORT */ err_t pppapi_open(ppp_pcb *pcb, u16_t holdoff); +#if PPP_SERVER +err_t pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs); +#endif /* PPP_SERVER */ err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier); err_t pppapi_free(ppp_pcb *pcb); err_t pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); diff --git a/src/include/netif/ppp/ppp.h b/src/include/netif/ppp/ppp.h index 843f42f4..212c4c59 100644 --- a/src/include/netif/ppp/ppp.h +++ b/src/include/netif/ppp/ppp.h @@ -463,6 +463,21 @@ void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_p */ err_t ppp_open(ppp_pcb *pcb, u16_t holdoff); +#if PPP_SERVER +/* + * Listen for an incoming PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Local and remote interface IP addresses, as well as DNS are + * provided through a previously filled struct ppp_addrs. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_listen(ppp_pcb *pcb, struct ppp_addrs *addrs); +#endif /* PPP_SERVER */ + /* * Initiate the end of a PPP connection. * Any outstanding packets in the queues are dropped. diff --git a/src/include/netif/ppp/ppp_impl.h b/src/include/netif/ppp/ppp_impl.h index 07362ea6..a887d5c1 100644 --- a/src/include/netif/ppp/ppp_impl.h +++ b/src/include/netif/ppp/ppp_impl.h @@ -143,6 +143,10 @@ struct link_callbacks { /* Start a connection (e.g. Initiate discovery phase) */ err_t (*connect) (ppp_pcb *pcb, void *ctx); +#if PPP_SERVER + /* Listen for an incoming connection (Passive mode) */ + err_t (*listen) (ppp_pcb *pcb, void *ctx, struct ppp_addrs *addrs); +#endif /* PPP_SERVER */ /* End a connection (i.e. initiate disconnect phase) */ void (*disconnect) (ppp_pcb *pcb, void *ctx); /* Free lower protocol control block */ diff --git a/src/netif/ppp/ppp.c b/src/netif/ppp/ppp.c index 8a1df4aa..b863ec7a 100644 --- a/src/netif/ppp/ppp.c +++ b/src/netif/ppp/ppp.c @@ -247,6 +247,32 @@ err_t ppp_open(ppp_pcb *pcb, u16_t holdoff) { return ERR_OK; } +#if PPP_SERVER +/* + * Listen for an incoming PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Local and remote interface IP addresses, as well as DNS are + * provided through a previously filled struct ppp_addrs. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_listen(ppp_pcb *pcb, struct ppp_addrs *addrs) { + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_ALREADY; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_listen() called\n")); + + if (pcb->link_cb->listen) { + return pcb->link_cb->listen(pcb, pcb->link_ctx_cb, addrs); + } + return ERR_IF; +} +#endif /* PPP_SERVER */ + /* * Initiate the end of a PPP connection. * Any outstanding packets in the queues are dropped. diff --git a/src/netif/ppp/pppoe.c b/src/netif/ppp/pppoe.c index b974d415..1eeddcfc 100644 --- a/src/netif/ppp/pppoe.c +++ b/src/netif/ppp/pppoe.c @@ -150,6 +150,9 @@ static struct pppoe_softc *pppoe_softc_list; /* Callbacks structure for PPP core */ static const struct link_callbacks pppoe_callbacks = { pppoe_connect, +#if PPP_SERVER + NULL, +#endif /* PPP_SERVER */ pppoe_disconnect, pppoe_destroy, pppoe_write, diff --git a/src/netif/ppp/pppol2tp.c b/src/netif/ppp/pppol2tp.c index 8debc213..b9fd8ec7 100644 --- a/src/netif/ppp/pppol2tp.c +++ b/src/netif/ppp/pppol2tp.c @@ -99,6 +99,9 @@ static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb); /* Callbacks structure for PPP core */ static const struct link_callbacks pppol2tp_callbacks = { pppol2tp_connect, +#if PPP_SERVER + NULL, +#endif /* PPP_SERVER */ pppol2tp_disconnect, pppol2tp_destroy, pppol2tp_write, diff --git a/src/netif/ppp/pppos.c b/src/netif/ppp/pppos.c index f41002f3..23dd75b9 100644 --- a/src/netif/ppp/pppos.c +++ b/src/netif/ppp/pppos.c @@ -54,6 +54,9 @@ static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u_short protocol); static err_t pppos_connect(ppp_pcb *ppp, void *ctx); +#if PPP_SERVER +static err_t pppos_listen(ppp_pcb *ppp, void *ctx, struct ppp_addrs *addrs); +#endif /* PPP_SERVER */ static void pppos_disconnect(ppp_pcb *ppp, void *ctx); static err_t pppos_destroy(ppp_pcb *ppp, void *ctx); static void pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm); @@ -76,6 +79,9 @@ static void pppos_drop(pppos_pcb *pppos); /* Callbacks structure for PPP core */ static const struct link_callbacks pppos_callbacks = { pppos_connect, +#if PPP_SERVER + pppos_listen, +#endif /* PPP_SERVER */ pppos_disconnect, pppos_destroy, pppos_write, @@ -418,6 +424,76 @@ pppos_connect(ppp_pcb *ppp, void *ctx) return ERR_OK; } +#if PPP_SERVER +static err_t +pppos_listen(ppp_pcb *ppp, void *ctx, struct ppp_addrs *addrs) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; +#if PPP_IPV4_SUPPORT + ipcp_options *ipcp_wo; +#if !VJ_SUPPORT + ipcp_options *ipcp_ao; +#endif /* !VJ_SUPPORT */ +#endif /* PPP_IPV4_SUPPORT */ + lcp_options *lcp_wo; + + /* input pbuf left over from last session? */ + pppos_free_current_input_packet(pppos); + + ppp_clear(ppp); + /* reset PPPoS control block to its initial state */ + memset(&pppos->out_accm, 0, sizeof(pppos_pcb) - ( (char*)&((pppos_pcb*)0)->out_accm - (char*)0 ) ); + + /* Wait passively */ + lcp_wo = &ppp->lcp_wantoptions; + lcp_wo->silent = 1; + +#if PPP_AUTH_SUPPORT + if (ppp->settings.user && ppp->settings.passwd) { + ppp->settings.auth_required = 1; + } +#endif /* PPP_AUTH_SUPPORT */ + +#if PPP_IPV4_SUPPORT + ipcp_wo = &ppp->ipcp_wantoptions; + ipcp_wo->ouraddr = ip4_addr_get_u32(&addrs->our_ipaddr); + ipcp_wo->hisaddr = ip4_addr_get_u32(&addrs->his_ipaddr); + ipcp_wo->dnsaddr[0] = ip4_addr_get_u32(&addrs->dns1); + ipcp_wo->dnsaddr[1] = ip4_addr_get_u32(&addrs->dns2); + +#if VJ_SUPPORT + vj_compress_init(&pppos->vj_comp); +#else /* VJ_SUPPORT */ + /* Don't even try to negotiate VJ if VJ is disabled */ + ipcp_wo = &ppp->ipcp_wantoptions; + ipcp_wo->neg_vj = 0; + ipcp_wo->old_vj = 0; + + ipcp_ao = &ppp->ipcp_allowoptions; + ipcp_ao->neg_vj = 0; + ipcp_ao->old_vj = 0; +#endif /* VJ_SUPPORT */ + +#else /* PPP_IPV4_SUPPORT */ + LWIP_UNUSED_ARG(addrs); +#endif /* PPP_IPV4_SUPPORT */ + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ + pppos->out_accm[15] = 0x60; + + /* + * Wait for something to happen. + */ + PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num)); + ppp_start(ppp); /* notify upper layers */ + return ERR_OK; +} +#endif /* PPP_SERVER */ + static void pppos_disconnect(ppp_pcb *ppp, void *ctx) {