mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-01-30 12:32:37 +00:00
PPP, L2TP, added link-level IPv6 support
This commit is contained in:
parent
684bef066f
commit
3ce6dd166c
@ -232,6 +232,52 @@ pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipad
|
||||
TCPIP_PPPAPI(&msg);
|
||||
return msg.msg.ppp;
|
||||
}
|
||||
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Call pppol2tp_create_ip6() inside the tcpip_thread context.
|
||||
*/
|
||||
static void
|
||||
pppapi_do_pppol2tp_create_ip6(struct pppapi_msg_msg *msg)
|
||||
{
|
||||
msg->ppp = pppol2tp_create_ip6(msg->msg.l2tpcreateip6.pppif,
|
||||
msg->msg.l2tpcreateip6.netif, msg->msg.l2tpcreateip6.ip6addr, msg->msg.l2tpcreateip6.port,
|
||||
#if PPPOL2TP_AUTH_SUPPORT
|
||||
msg->msg.l2tpcreateip6.secret,
|
||||
msg->msg.l2tpcreateip6.secret_len,
|
||||
#else /* PPPOL2TP_AUTH_SUPPORT */
|
||||
NULL,
|
||||
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
||||
msg->msg.l2tpcreateip6.link_status_cb, msg->msg.l2tpcreateip6.ctx_cb);
|
||||
TCPIP_PPPAPI_ACK(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call pppol2tp_create_ip6() in a thread-safe way by running that function inside the
|
||||
* tcpip_thread context.
|
||||
*/
|
||||
ppp_pcb*
|
||||
pppapi_pppol2tp_create_ip6(struct netif *pppif, struct netif *netif, ip6_addr_t *ip6addr, u16_t port,
|
||||
u8_t *secret, u8_t secret_len,
|
||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb)
|
||||
{
|
||||
struct pppapi_msg msg;
|
||||
msg.function = pppapi_do_pppol2tp_create_ip6;
|
||||
msg.msg.msg.l2tpcreateip6.pppif = pppif;
|
||||
msg.msg.msg.l2tpcreateip6.netif = netif;
|
||||
msg.msg.msg.l2tpcreateip6.ip6addr = ip6addr;
|
||||
msg.msg.msg.l2tpcreateip6.port = port;
|
||||
#if PPPOL2TP_AUTH_SUPPORT
|
||||
msg.msg.msg.l2tpcreateip6.secret = secret;
|
||||
msg.msg.msg.l2tpcreateip6.secret_len = secret_len;
|
||||
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
||||
msg.msg.msg.l2tpcreateip6.link_status_cb = link_status_cb;
|
||||
msg.msg.msg.l2tpcreateip6.ctx_cb = ctx_cb;
|
||||
TCPIP_PPPAPI(&msg);
|
||||
return msg.msg.ppp;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
#endif /* PPPOL2TP_SUPPORT */
|
||||
|
||||
|
||||
|
@ -88,6 +88,20 @@ struct pppapi_msg_msg {
|
||||
ppp_link_status_cb_fn link_status_cb;
|
||||
void *ctx_cb;
|
||||
} l2tpcreate;
|
||||
#if LWIP_IPV6
|
||||
struct {
|
||||
struct netif *pppif;
|
||||
struct netif *netif;
|
||||
ip6_addr_t *ip6addr;
|
||||
u16_t port;
|
||||
#if PPPOL2TP_AUTH_SUPPORT
|
||||
u8_t *secret;
|
||||
u8_t secret_len;
|
||||
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
||||
ppp_link_status_cb_fn link_status_cb;
|
||||
void *ctx_cb;
|
||||
} l2tpcreateip6;
|
||||
#endif /* LWIP_IPV6 */
|
||||
#endif /* PPPOL2TP_SUPPORT */
|
||||
struct {
|
||||
u16_t holdoff;
|
||||
@ -130,6 +144,11 @@ ppp_pcb *pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const cha
|
||||
ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port,
|
||||
u8_t *secret, u8_t secret_len,
|
||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
|
||||
#if LWIP_IPV6
|
||||
ppp_pcb *pppapi_pppol2tp_create_ip6(struct netif *pppif, struct netif *netif, ip6_addr_t *ip6addr, u16_t port,
|
||||
u8_t *secret, u8_t secret_len,
|
||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
|
||||
#endif /* LWIP_IPV6 */
|
||||
#endif /* PPPOL2TP_SUPPORT */
|
||||
err_t pppapi_connect(ppp_pcb *pcb, u16_t holdoff);
|
||||
#if PPP_SERVER
|
||||
|
@ -166,7 +166,7 @@ struct pppol2tp_pcb_s {
|
||||
u8_t phase; /* L2TP phase */
|
||||
struct udp_pcb *udp; /* UDP L2TP Socket */
|
||||
struct netif *netif; /* Output interface, used as a default route */
|
||||
ip_addr_t remote_ip; /* LNS IP Address */
|
||||
ipX_addr_t remote_ip; /* LNS IP Address */
|
||||
u16_t remote_port; /* LNS port */
|
||||
#if PPPOL2TP_AUTH_SUPPORT
|
||||
u8_t *secret; /* Secret string */
|
||||
@ -191,11 +191,19 @@ struct pppol2tp_pcb_s {
|
||||
};
|
||||
|
||||
|
||||
/* Create a new L2TP session. */
|
||||
/* Create a new L2TP session over IPv4. */
|
||||
ppp_pcb *pppol2tp_create(struct netif *pppif,
|
||||
struct netif *netif, ip_addr_t *ipaddr, u16_t port,
|
||||
u8_t *secret, u8_t secret_len,
|
||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
|
||||
|
||||
#if LWIP_IPV6
|
||||
/* Create a new L2TP session over IPv6. */
|
||||
ppp_pcb *pppol2tp_create_ip6(struct netif *pppif,
|
||||
struct netif *netif, ip6_addr_t *ip6addr, u16_t port,
|
||||
u8_t *secret, u8_t secret_len,
|
||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#endif /* PPPOL2TP_H_ */
|
||||
#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */
|
||||
|
@ -82,9 +82,12 @@ static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect
|
||||
static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx); /* Disconnect */
|
||||
|
||||
/* Prototypes for procedures local to this file. */
|
||||
static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const struct ip_addr *addr, u16_t port);
|
||||
static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, const struct ip_addr *addr, u16_t port,
|
||||
struct pbuf *p, u16_t len, u16_t tunnel_id, u16_t session_id, u16_t ns, u16_t nr);
|
||||
static void pppol2tp_input_ip4(void *arg, struct udp_pcb *pcb, struct pbuf *p, const struct ip_addr *addr, u16_t port);
|
||||
#if LWIP_IPV6
|
||||
static void pppol2tp_input_ip6(void *arg, struct udp_pcb *pcb, struct pbuf *p, const struct ip6_addr *addr, u16_t port);
|
||||
#endif /* LWIP_IPV6 */
|
||||
static void pppol2tp_input(pppol2tp_pcb *l2tp, struct pbuf *p, u16_t port);
|
||||
static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr);
|
||||
static void pppol2tp_timeout(void *arg);
|
||||
static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp);
|
||||
static void pppol2tp_clear(pppol2tp_pcb *l2tp);
|
||||
@ -143,14 +146,14 @@ ppp_pcb *pppol2tp_create(struct netif *pppif,
|
||||
ppp_free(ppp);
|
||||
return NULL;
|
||||
}
|
||||
udp_recv(udp, pppol2tp_input, l2tp);
|
||||
udp_recv(udp, pppol2tp_input_ip4, l2tp);
|
||||
|
||||
memset(l2tp, 0, sizeof(pppol2tp_pcb));
|
||||
l2tp->phase = PPPOL2TP_STATE_INITIAL;
|
||||
l2tp->ppp = ppp;
|
||||
l2tp->udp = udp;
|
||||
l2tp->netif = netif;
|
||||
ip_addr_set(&l2tp->remote_ip, ipaddr);
|
||||
ip_addr_set(&l2tp->remote_ip.ip4, ipaddr);
|
||||
l2tp->remote_port = port;
|
||||
#if PPPOL2TP_AUTH_SUPPORT
|
||||
l2tp->secret = secret;
|
||||
@ -161,6 +164,52 @@ ppp_pcb *pppol2tp_create(struct netif *pppif,
|
||||
return ppp;
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/* Create a new L2TP session over IPv6. */
|
||||
ppp_pcb *pppol2tp_create_ip6(struct netif *pppif,
|
||||
struct netif *netif, ip6_addr_t *ip6addr, u16_t port,
|
||||
u8_t *secret, u8_t secret_len,
|
||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb) {
|
||||
ppp_pcb *ppp;
|
||||
pppol2tp_pcb *l2tp;
|
||||
struct udp_pcb *udp;
|
||||
|
||||
ppp = ppp_new(pppif, link_status_cb, ctx_cb);
|
||||
if (ppp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l2tp = (pppol2tp_pcb *)memp_malloc(MEMP_PPPOL2TP_PCB);
|
||||
if (l2tp == NULL) {
|
||||
ppp_free(ppp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udp = udp_new_ip6();
|
||||
if (udp == NULL) {
|
||||
memp_free(MEMP_PPPOL2TP_PCB, l2tp);
|
||||
ppp_free(ppp);
|
||||
return NULL;
|
||||
}
|
||||
udp_recv_ip6(udp, pppol2tp_input_ip6, l2tp);
|
||||
|
||||
memset(l2tp, 0, sizeof(pppol2tp_pcb));
|
||||
l2tp->phase = PPPOL2TP_STATE_INITIAL;
|
||||
l2tp->ppp = ppp;
|
||||
l2tp->udp = udp;
|
||||
l2tp->netif = netif;
|
||||
ip6_addr_set(&l2tp->remote_ip.ip6, ip6addr);
|
||||
l2tp->remote_port = port;
|
||||
#if PPPOL2TP_AUTH_SUPPORT
|
||||
l2tp->secret = secret;
|
||||
l2tp->secret_len = secret_len;
|
||||
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
||||
|
||||
ppp_link_set_callbacks(ppp, &pppol2tp_callbacks, l2tp);
|
||||
return ppp;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/* Called by PPP core */
|
||||
static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) {
|
||||
pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx;
|
||||
@ -302,6 +351,11 @@ static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
|
||||
/* Listen to a random source port, we need to do that instead of using udp_connect()
|
||||
* because the L2TP LNS might answer with its own random source port (!= 1701)
|
||||
*/
|
||||
#if LWIP_IPV6
|
||||
if (PCB_ISIPV6(l2tp->udp)) {
|
||||
udp_bind_ip6(l2tp->udp, IP6_ADDR_ANY, 0);
|
||||
} else
|
||||
#endif /* LWIP_IPV6 */
|
||||
udp_bind(l2tp->udp, IP_ADDR_ANY, 0);
|
||||
|
||||
#if PPPOL2TP_AUTH_SUPPORT
|
||||
@ -339,21 +393,52 @@ static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx) {
|
||||
ppp_link_end(ppp); /* notify upper layers */
|
||||
}
|
||||
|
||||
/* UDP Callback for incoming L2TP frames */
|
||||
static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const struct ip_addr *addr, u16_t port) {
|
||||
/* UDP Callback for incoming IPv4 L2TP frames */
|
||||
static void pppol2tp_input_ip4(void *arg, struct udp_pcb *pcb, struct pbuf *p, const struct ip_addr *addr, u16_t port) {
|
||||
pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg;
|
||||
u16_t hflags, hlen, len=0, tunnel_id=0, session_id=0, ns=0, nr=0, offset=0;
|
||||
u8_t *inp;
|
||||
LWIP_UNUSED_ARG(pcb);
|
||||
|
||||
if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) {
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
if (!ip_addr_cmp(&l2tp->remote_ip, addr)) {
|
||||
if (!ip_addr_cmp(&l2tp->remote_ip.ip4, addr)) {
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
pppol2tp_input(l2tp, p, port);
|
||||
return;
|
||||
|
||||
free_and_return:
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/* UDP Callback for incoming IPv6 L2TP frames */
|
||||
static void pppol2tp_input_ip6(void *arg, struct udp_pcb *pcb, struct pbuf *p, const struct ip6_addr *addr, u16_t port) {
|
||||
pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg;
|
||||
LWIP_UNUSED_ARG(pcb);
|
||||
|
||||
if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) {
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
if (!ip6_addr_cmp(&l2tp->remote_ip.ip6, addr)) {
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
pppol2tp_input(l2tp, p, port);
|
||||
return;
|
||||
|
||||
free_and_return:
|
||||
pbuf_free(p);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
static void pppol2tp_input(pppol2tp_pcb *l2tp, struct pbuf *p, u16_t port) {
|
||||
u16_t hflags, hlen, len=0, tunnel_id=0, session_id=0, ns=0, nr=0, offset=0;
|
||||
u8_t *inp;
|
||||
|
||||
/* discard packet if port mismatch, but only if we received a SCCRP */
|
||||
if (l2tp->phase > PPPOL2TP_STATE_SCCRQ_SENT && l2tp->tunnel_port != port) {
|
||||
goto free_and_return;
|
||||
@ -442,7 +527,7 @@ static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const
|
||||
|
||||
/* Control packet */
|
||||
if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) {
|
||||
pppol2tp_dispatch_control_packet(l2tp, addr, port, p, len, tunnel_id, session_id, ns, nr);
|
||||
pppol2tp_dispatch_control_packet(l2tp, port, p, ns, nr);
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
@ -479,8 +564,7 @@ free_and_return:
|
||||
}
|
||||
|
||||
/* L2TP Control packet entry point */
|
||||
static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, const struct ip_addr *addr, u16_t port,
|
||||
struct pbuf *p, u16_t len, u16_t tunnel_id, u16_t session_id, u16_t ns, u16_t nr) {
|
||||
static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr) {
|
||||
u8_t *inp;
|
||||
u16_t avplen, avpflags, vendorid, attributetype, messagetype=0;
|
||||
err_t err;
|
||||
@ -489,10 +573,6 @@ static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, const struct ip
|
||||
u8_t md5_hash[16];
|
||||
u8_t challenge_id = 0;
|
||||
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
||||
LWIP_UNUSED_ARG(addr);
|
||||
LWIP_UNUSED_ARG(len);
|
||||
LWIP_UNUSED_ARG(tunnel_id);
|
||||
LWIP_UNUSED_ARG(session_id);
|
||||
|
||||
l2tp->peer_nr = nr;
|
||||
l2tp->peer_ns = ns;
|
||||
@ -1137,10 +1217,19 @@ static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb) {
|
||||
|
||||
static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb) {
|
||||
err_t err;
|
||||
#if LWIP_IPV6
|
||||
if (PCB_ISIPV6(l2tp->udp)) {
|
||||
if (l2tp->netif) {
|
||||
err = udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port, l2tp->netif);
|
||||
udp_sendto_if_ip6(l2tp->udp, pb, &l2tp->remote_ip.ip6, l2tp->tunnel_port, l2tp->netif);
|
||||
} else {
|
||||
err = udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port);
|
||||
udp_sendto_ip6(l2tp->udp, pb, &l2tp->remote_ip.ip6, l2tp->tunnel_port);
|
||||
}
|
||||
} else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (l2tp->netif) {
|
||||
err = udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip.ip4, l2tp->tunnel_port, l2tp->netif);
|
||||
} else {
|
||||
err = udp_sendto(l2tp->udp, pb, &l2tp->remote_ip.ip4, l2tp->tunnel_port);
|
||||
}
|
||||
pbuf_free(pb);
|
||||
return err;
|
||||
|
Loading…
x
Reference in New Issue
Block a user