We now negotiate DNS servers in the IPCP configuration. This has been observed to speed up the connection setup. The received DNS servers are used by the DNS resolver library, but we leave it optional since the static server list might be preferable. Increase MAX_IPCP_OPTIONS to 4 so that we can nack all RFC 1877 options. Signed-off-by: Göran Weinholt <goran.weinholt@endian.se>
364 lines
7.8 KiB
C
364 lines
7.8 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"
|
|
|
|
const char *ppp_phase_str(enum ppp_phase phase)
|
|
{
|
|
#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
|
|
switch (phase) {
|
|
case PPP_DEAD:
|
|
return "DEAD";
|
|
case PPP_ESTABLISH:
|
|
return "ESTABLISH";
|
|
case PPP_AUTH:
|
|
return "AUTH";
|
|
case PPP_NETWORK:
|
|
return "NETWORK";
|
|
case PPP_RUNNING:
|
|
return "RUNNING";
|
|
case PPP_TERMINATE:
|
|
return "TERMINATE";
|
|
}
|
|
#else
|
|
ARG_UNUSED(phase);
|
|
#endif
|
|
|
|
return "";
|
|
}
|
|
|
|
#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
static void validate_phase_transition(enum ppp_phase current,
|
|
enum ppp_phase new)
|
|
{
|
|
static const u8_t valid_transitions[] = {
|
|
[PPP_DEAD] = 1 << PPP_ESTABLISH,
|
|
[PPP_ESTABLISH] = 1 << PPP_DEAD |
|
|
1 << PPP_AUTH |
|
|
1 << PPP_TERMINATE,
|
|
[PPP_AUTH] = 1 << PPP_TERMINATE |
|
|
1 << PPP_NETWORK,
|
|
[PPP_NETWORK] = 1 << PPP_TERMINATE |
|
|
1 << PPP_RUNNING,
|
|
[PPP_RUNNING] = 1 << PPP_TERMINATE |
|
|
1 << PPP_NETWORK,
|
|
[PPP_TERMINATE] = 1 << PPP_DEAD,
|
|
};
|
|
|
|
if (!(valid_transitions[current] & 1 << new)) {
|
|
NET_DBG("Invalid phase transition: %s (%d) => %s (%d)",
|
|
ppp_phase_str(current), current,
|
|
ppp_phase_str(new), new);
|
|
}
|
|
}
|
|
#else
|
|
static inline void validate_phase_transition(enum ppp_phase current,
|
|
enum ppp_phase new)
|
|
{
|
|
ARG_UNUSED(current);
|
|
ARG_UNUSED(new);
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
void ppp_change_phase_debug(struct ppp_context *ctx, enum ppp_phase new_phase,
|
|
const char *caller, int line)
|
|
#else
|
|
void ppp_change_phase(struct ppp_context *ctx, enum ppp_phase new_phase)
|
|
#endif
|
|
{
|
|
NET_ASSERT(ctx);
|
|
|
|
if (ctx->phase == new_phase) {
|
|
return;
|
|
}
|
|
|
|
NET_ASSERT(new_phase >= PPP_DEAD &&
|
|
new_phase <= PPP_TERMINATE);
|
|
|
|
#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
NET_DBG("[%p] phase %s (%d) => %s (%d) (%s():%d)",
|
|
ctx, ppp_phase_str(ctx->phase), ctx->phase,
|
|
ppp_phase_str(new_phase), new_phase, caller, line);
|
|
#endif
|
|
|
|
validate_phase_transition(ctx->phase, new_phase);
|
|
|
|
ctx->phase = new_phase;
|
|
}
|
|
|
|
const char *ppp_state_str(enum ppp_state state)
|
|
{
|
|
#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
|
|
switch (state) {
|
|
case PPP_INITIAL:
|
|
return "INITIAL";
|
|
case PPP_STARTING:
|
|
return "STARTING";
|
|
case PPP_CLOSED:
|
|
return "CLOSED";
|
|
case PPP_STOPPED:
|
|
return "STOPPED";
|
|
case PPP_CLOSING:
|
|
return "CLOSING";
|
|
case PPP_STOPPING:
|
|
return "STOPPING";
|
|
case PPP_REQUEST_SENT:
|
|
return "REQUEST_SENT";
|
|
case PPP_ACK_RECEIVED:
|
|
return "ACK_RECEIVED";
|
|
case PPP_ACK_SENT:
|
|
return "ACK_SENT";
|
|
case PPP_OPENED:
|
|
return "OPENED";
|
|
}
|
|
#else
|
|
ARG_UNUSED(state);
|
|
#endif
|
|
|
|
return "";
|
|
}
|
|
|
|
const char *ppp_pkt_type2str(enum ppp_packet_type type)
|
|
{
|
|
#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
|
|
switch (type) {
|
|
case PPP_CONFIGURE_REQ:
|
|
return "Configure-Req";
|
|
case PPP_CONFIGURE_ACK:
|
|
return "Configure-Ack";
|
|
case PPP_CONFIGURE_NACK:
|
|
return "Configure-Nack";
|
|
case PPP_CONFIGURE_REJ:
|
|
return "Configure-Rej";
|
|
case PPP_TERMINATE_REQ:
|
|
return "Terminate-Req";
|
|
case PPP_TERMINATE_ACK:
|
|
return "Terminate-Ack";
|
|
case PPP_CODE_REJ:
|
|
return "Code-Rej";
|
|
case PPP_PROTOCOL_REJ:
|
|
return "Protocol-Rej";
|
|
case PPP_ECHO_REQ:
|
|
return "Echo-Req";
|
|
case PPP_ECHO_REPLY:
|
|
return "Echo-Reply";
|
|
case PPP_DISCARD_REQ:
|
|
return "Discard-Req";
|
|
}
|
|
#else
|
|
ARG_UNUSED(type);
|
|
#endif
|
|
|
|
return "";
|
|
}
|
|
|
|
const char *ppp_proto2str(u16_t proto)
|
|
{
|
|
#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG)
|
|
switch (proto) {
|
|
case PPP_IP:
|
|
return "IPv4";
|
|
case PPP_IPV6:
|
|
return "IPv6";
|
|
case PPP_ECP:
|
|
return "ECP";
|
|
case PPP_CCP:
|
|
return "CCP";
|
|
case PPP_LCP:
|
|
return "LCP";
|
|
case PPP_IPCP:
|
|
return "IPCP";
|
|
case PPP_IPV6CP:
|
|
return "IPV6CP";
|
|
}
|
|
#else
|
|
ARG_UNUSED(proto);
|
|
#endif
|
|
|
|
return "";
|
|
}
|
|
|
|
#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
static void validate_state_transition(enum ppp_state current,
|
|
enum ppp_state new)
|
|
{
|
|
/* See RFC 1661 ch. 4.1 */
|
|
static const u16_t valid_transitions[] = {
|
|
[PPP_INITIAL] = 1 << PPP_CLOSED |
|
|
1 << PPP_STARTING,
|
|
[PPP_STARTING] = 1 << PPP_INITIAL |
|
|
1 << PPP_REQUEST_SENT,
|
|
[PPP_CLOSED] = 1 << PPP_INITIAL |
|
|
1 << PPP_REQUEST_SENT,
|
|
[PPP_STOPPED] = 1 << PPP_STARTING |
|
|
1 << PPP_CLOSED |
|
|
1 << PPP_ACK_RECEIVED |
|
|
1 << PPP_REQUEST_SENT,
|
|
[PPP_CLOSING] = 1 << PPP_INITIAL |
|
|
1 << PPP_STOPPING |
|
|
1 << PPP_CLOSED,
|
|
[PPP_STOPPING] = 1 << PPP_STARTING |
|
|
1 << PPP_CLOSING |
|
|
1 << PPP_STOPPED,
|
|
[PPP_REQUEST_SENT] = 1 << PPP_STARTING |
|
|
1 << PPP_CLOSING |
|
|
1 << PPP_STOPPED |
|
|
1 << PPP_ACK_SENT |
|
|
1 << PPP_ACK_RECEIVED,
|
|
[PPP_ACK_RECEIVED] = 1 << PPP_STARTING |
|
|
1 << PPP_CLOSING |
|
|
1 << PPP_OPENED |
|
|
1 << PPP_REQUEST_SENT |
|
|
1 << PPP_STOPPED,
|
|
[PPP_ACK_SENT] = 1 << PPP_STARTING |
|
|
1 << PPP_CLOSING |
|
|
1 << PPP_STOPPED |
|
|
1 << PPP_REQUEST_SENT |
|
|
1 << PPP_OPENED,
|
|
[PPP_OPENED] = 1 << PPP_STARTING |
|
|
1 << PPP_CLOSING |
|
|
1 << PPP_ACK_SENT |
|
|
1 << PPP_REQUEST_SENT |
|
|
1 << PPP_CLOSING |
|
|
1 << PPP_STOPPING,
|
|
};
|
|
|
|
if (!(valid_transitions[current] & 1 << new)) {
|
|
NET_DBG("Invalid state transition: %s (%d) => %s (%d)",
|
|
ppp_state_str(current), current,
|
|
ppp_state_str(new), new);
|
|
}
|
|
}
|
|
#else
|
|
static inline void validate_state_transition(enum ppp_state current,
|
|
enum ppp_state new)
|
|
{
|
|
ARG_UNUSED(current);
|
|
ARG_UNUSED(new);
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
void ppp_change_state_debug(struct ppp_fsm *fsm, enum ppp_state new_state,
|
|
const char *caller, int line)
|
|
#else
|
|
void ppp_change_state(struct ppp_fsm *fsm, enum ppp_state new_state)
|
|
#endif
|
|
{
|
|
NET_ASSERT(fsm);
|
|
|
|
if (fsm->state == new_state) {
|
|
return;
|
|
}
|
|
|
|
NET_ASSERT(new_state >= PPP_INITIAL &&
|
|
new_state <= PPP_OPENED);
|
|
|
|
#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
NET_DBG("[%s/%p] state %s (%d) => %s (%d) (%s():%d)",
|
|
fsm->name, fsm, ppp_state_str(fsm->state), fsm->state,
|
|
ppp_state_str(new_state), new_state, caller, line);
|
|
#endif
|
|
|
|
validate_state_transition(fsm->state, new_state);
|
|
|
|
fsm->state = new_state;
|
|
}
|
|
|
|
const char *ppp_option2str(enum ppp_protocol_type protocol,
|
|
int type)
|
|
{
|
|
#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
|
|
switch (protocol) {
|
|
case PPP_LCP:
|
|
switch (type) {
|
|
case LCP_OPTION_RESERVED:
|
|
return "RESERVED";
|
|
case LCP_OPTION_MRU:
|
|
return "MRU";
|
|
case LCP_OPTION_ASYNC_CTRL_CHAR_MAP:
|
|
return "ASYNC_CTRL_CHAR_MAP";
|
|
case LCP_OPTION_AUTH_PROTO:
|
|
return "AUTH_PROTO";
|
|
case LCP_OPTION_QUALITY_PROTO:
|
|
return "QUALITY_PROTO";
|
|
case LCP_OPTION_MAGIC_NUMBER:
|
|
return "MAGIC_NUMBER";
|
|
case LCP_OPTION_PROTO_COMPRESS:
|
|
return "PROTO_COMPRESS";
|
|
case LCP_OPTION_ADDR_CTRL_COMPRESS:
|
|
return "ADDR_CTRL_COMPRESS";
|
|
}
|
|
|
|
break;
|
|
|
|
#if defined(CONFIG_NET_IPV4)
|
|
case PPP_IPCP:
|
|
switch (type) {
|
|
case IPCP_OPTION_RESERVED:
|
|
return "RESERVED";
|
|
case IPCP_OPTION_IP_ADDRESSES:
|
|
return "IP_ADDRESSES";
|
|
case IPCP_OPTION_IP_COMP_PROTO:
|
|
return "IP_COMPRESSION_PROTOCOL";
|
|
case IPCP_OPTION_IP_ADDRESS:
|
|
return "IP_ADDRESS";
|
|
case IPCP_OPTION_DNS1:
|
|
return "DNS1";
|
|
case IPCP_OPTION_NBNS1:
|
|
return "NBNS1";
|
|
case IPCP_OPTION_DNS2:
|
|
return "DNS2";
|
|
case IPCP_OPTION_NBNS2:
|
|
return "NBNS2";
|
|
}
|
|
|
|
break;
|
|
#endif
|
|
|
|
#if defined(CONFIG_NET_IPV6)
|
|
case PPP_IPV6CP:
|
|
switch (type) {
|
|
case IPV6CP_OPTION_RESERVED:
|
|
return "RESERVED";
|
|
case IPV6CP_OPTION_INTERFACE_IDENTIFIER:
|
|
return "INTERFACE_IDENTIFIER";
|
|
}
|
|
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
break;
|
|
}
|
|
#else
|
|
ARG_UNUSED(type);
|
|
#endif
|
|
|
|
return "";
|
|
}
|
|
|
|
void ppp_fsm_name_set(struct ppp_fsm *fsm, const char *name)
|
|
{
|
|
#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
fsm->name = name;
|
|
#else
|
|
ARG_UNUSED(fsm);
|
|
ARG_UNUSED(name);
|
|
#endif
|
|
}
|