PPP Phase Diagram [1] allows only one way phase change. In current implementation there is an additional RUNNING phase, which is entered just after NETWORK phase. Prevent going back from RUNNING to NETWORK phase when Term-Req was received, as this is meaningless for overall PPP operation and violates PPP Phase Diagram property of having one way direction change. This change also improves Adminitrative Close handling (calling lcp_close()). This request results in moving into TERMINATE phase. Then LCP is put down (by calling lcp_down()) and then ppp_link_down() is called, which so far (before this patch) resulted in moving back to NETWORK and then to DEAD. Right now (after this patch) we move directly from TERMINATE to DEAD phase, which is exactly how [1] specifies it. [1] https://tools.ietf.org/html/rfc1661#section-3.2 Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
143 lines
2.6 KiB
C
143 lines
2.6 KiB
C
/*
|
|
* Copyright (c) 2019 Intel Corporation.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <logging/log.h>
|
|
LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
|
|
|
|
#include <net/net_core.h>
|
|
#include <net/net_pkt.h>
|
|
|
|
#include <net/ppp.h>
|
|
|
|
#include "net_private.h"
|
|
|
|
#include "ppp_internal.h"
|
|
|
|
static void lcp_up(struct ppp_context *ctx)
|
|
{
|
|
Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
|
|
if (proto->protocol == PPP_LCP) {
|
|
continue;
|
|
}
|
|
|
|
if (proto->lower_up) {
|
|
proto->lower_up(ctx);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void do_network(struct ppp_context *ctx)
|
|
{
|
|
ppp_change_phase(ctx, PPP_NETWORK);
|
|
|
|
Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
|
|
if (proto->protocol == PPP_CCP || proto->protocol == PPP_ECP) {
|
|
if (proto->open) {
|
|
proto->open(ctx);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Do the other network protocols if encryption is not needed for
|
|
* them.
|
|
*/
|
|
/* TODO possible encryption stuff here*/
|
|
|
|
Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
|
|
if (proto->protocol == PPP_CCP || proto->protocol == PPP_ECP ||
|
|
proto->protocol >= 0xC000) {
|
|
continue;
|
|
}
|
|
|
|
if (proto->open) {
|
|
ctx->network_protos_open++;
|
|
proto->open(ctx);
|
|
}
|
|
}
|
|
|
|
if (ctx->network_protos_open == 0) {
|
|
const struct ppp_protocol_handler *proto = ppp_lcp_get();
|
|
|
|
if (proto) {
|
|
proto->close(ctx, "No network protocols open");
|
|
}
|
|
}
|
|
}
|
|
|
|
static void do_auth(struct ppp_context *ctx)
|
|
{
|
|
uint16_t auth_proto = 0;
|
|
|
|
ppp_change_phase(ctx, PPP_AUTH);
|
|
|
|
if (IS_ENABLED(CONFIG_NET_L2_PPP_AUTH_SUPPORT)) {
|
|
auth_proto = ctx->lcp.peer_options.auth_proto;
|
|
}
|
|
|
|
/* If no authentication is need, then we are done */
|
|
if (!auth_proto) {
|
|
ppp_link_authenticated(ctx);
|
|
return;
|
|
}
|
|
|
|
Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
|
|
if (proto->protocol == auth_proto) {
|
|
if (proto->open) {
|
|
proto->open(ctx);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ppp_link_established(struct ppp_context *ctx, struct ppp_fsm *fsm)
|
|
{
|
|
NET_DBG("[%p] Link established", ctx);
|
|
|
|
ppp_change_phase(ctx, PPP_ESTABLISH);
|
|
|
|
do_auth(ctx);
|
|
|
|
lcp_up(ctx);
|
|
}
|
|
|
|
void ppp_link_authenticated(struct ppp_context *ctx)
|
|
{
|
|
NET_DBG("[%p] Link authenticated", ctx);
|
|
|
|
do_network(ctx);
|
|
}
|
|
|
|
void ppp_link_terminated(struct ppp_context *ctx)
|
|
{
|
|
if (ctx->phase == PPP_DEAD) {
|
|
return;
|
|
}
|
|
|
|
/* TODO: cleanup things etc here if needed */
|
|
|
|
ppp_change_phase(ctx, PPP_DEAD);
|
|
|
|
NET_DBG("[%p] Link terminated", ctx);
|
|
}
|
|
|
|
void ppp_link_down(struct ppp_context *ctx)
|
|
{
|
|
if (ctx->phase == PPP_DEAD) {
|
|
return;
|
|
}
|
|
|
|
ppp_network_all_down(ctx);
|
|
|
|
ppp_change_phase(ctx, PPP_DEAD);
|
|
}
|
|
|
|
void ppp_link_needed(struct ppp_context *ctx)
|
|
{
|
|
/* TODO: Try to create link if needed. */
|
|
}
|