a542de46ac
This patch implements optional authentication phase, which is done between link establishment and network phases. It is part of LCP option negotiation to decide whether authentication is needed and which protocol will be used. For now we add only PAP support and try to negotiate it when some other protocol (e.g. CHAP or EAP) is proposed earlier. For simplicity reason we only add one way authentication support, which means that we try to authenticate to the other peer, but do not require authentication from it. This is an important step to make PPP work with cellular network modems, because most of them require to provide username and password within PPP authentication phase. Those credentials are used by modem to login to cellular network. In most cases however it is enough to provide dummy values, because they are not verified. For this reason and simplicity of this patch we hardcode PAP Peer-ID and Password now. Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
142 lines
2.9 KiB
C
142 lines
2.9 KiB
C
/*
|
|
* Copyright (c) 2019-2020 Grinn
|
|
*
|
|
* 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_pkt.h>
|
|
|
|
#include "ppp_internal.h"
|
|
|
|
static enum net_verdict pap_handle(struct ppp_context *ctx,
|
|
struct net_if *iface,
|
|
struct net_pkt *pkt)
|
|
{
|
|
return ppp_fsm_input(&ctx->pap.fsm, PPP_PAP, pkt);
|
|
}
|
|
|
|
static struct net_pkt *pap_config_info_add(struct ppp_fsm *fsm)
|
|
{
|
|
uint8_t payload[] = { 5, 'b', 'l', 'a', 'n', 'k',
|
|
5, 'b', 'l', 'a', 'n', 'k' };
|
|
struct net_pkt *pkt;
|
|
|
|
pkt = net_pkt_alloc_with_buffer(ppp_fsm_iface(fsm), sizeof(payload),
|
|
AF_UNSPEC, 0, PPP_BUF_ALLOC_TIMEOUT);
|
|
if (!pkt) {
|
|
return NULL;
|
|
}
|
|
|
|
(void)net_pkt_write(pkt, payload, sizeof(payload));
|
|
|
|
return pkt;
|
|
}
|
|
|
|
static int pap_config_info_ack(struct ppp_fsm *fsm,
|
|
struct net_pkt *pkt,
|
|
uint16_t length)
|
|
{
|
|
/*
|
|
* We only support one way negotiation for now, so move to ACK_SENT
|
|
* phase right away.
|
|
*/
|
|
if (fsm->state == PPP_REQUEST_SENT) {
|
|
ppp_change_state(fsm, PPP_ACK_SENT);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void pap_lower_down(struct ppp_context *ctx)
|
|
{
|
|
ppp_fsm_lower_down(&ctx->pap.fsm);
|
|
}
|
|
|
|
static void pap_lower_up(struct ppp_context *ctx)
|
|
{
|
|
ppp_fsm_lower_up(&ctx->pap.fsm);
|
|
}
|
|
|
|
static void pap_open(struct ppp_context *ctx)
|
|
{
|
|
ppp_fsm_open(&ctx->pap.fsm);
|
|
}
|
|
|
|
static void pap_close(struct ppp_context *ctx, const uint8_t *reason)
|
|
{
|
|
ppp_fsm_close(&ctx->pap.fsm, reason);
|
|
}
|
|
|
|
static void pap_up(struct ppp_fsm *fsm)
|
|
{
|
|
struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
|
|
pap.fsm);
|
|
|
|
if (ctx->is_pap_up) {
|
|
return;
|
|
}
|
|
|
|
ctx->is_pap_up = true;
|
|
|
|
NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
|
|
ppp_state_str(fsm->state), fsm->state);
|
|
|
|
ppp_link_authenticated(ctx);
|
|
}
|
|
|
|
static void pap_down(struct ppp_fsm *fsm)
|
|
{
|
|
struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
|
|
pap.fsm);
|
|
|
|
if (!ctx->is_pap_up) {
|
|
return;
|
|
}
|
|
|
|
ctx->is_pap_up = false;
|
|
}
|
|
|
|
static void pap_finished(struct ppp_fsm *fsm)
|
|
{
|
|
struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
|
|
pap.fsm);
|
|
|
|
if (!ctx->is_pap_open) {
|
|
return;
|
|
}
|
|
|
|
ctx->is_pap_open = false;
|
|
}
|
|
|
|
static void pap_proto_reject(struct ppp_fsm *fsm)
|
|
{
|
|
ppp_fsm_lower_down(fsm);
|
|
}
|
|
|
|
static void pap_init(struct ppp_context *ctx)
|
|
{
|
|
NET_DBG("proto %s (0x%04x) fsm %p", ppp_proto2str(PPP_PAP), PPP_PAP,
|
|
&ctx->pap.fsm);
|
|
|
|
memset(&ctx->pap.fsm, 0, sizeof(ctx->pap.fsm));
|
|
|
|
ppp_fsm_init(&ctx->pap.fsm, PPP_PAP);
|
|
|
|
ppp_fsm_name_set(&ctx->pap.fsm, ppp_proto2str(PPP_PAP));
|
|
|
|
ctx->pap.fsm.cb.up = pap_up;
|
|
ctx->pap.fsm.cb.down = pap_down;
|
|
ctx->pap.fsm.cb.finished = pap_finished;
|
|
ctx->pap.fsm.cb.proto_reject = pap_proto_reject;
|
|
ctx->pap.fsm.cb.config_info_add = pap_config_info_add;
|
|
ctx->pap.fsm.cb.config_info_ack = pap_config_info_ack;
|
|
}
|
|
|
|
PPP_PROTOCOL_REGISTER(PAP, PPP_PAP,
|
|
pap_init, pap_handle,
|
|
pap_lower_up, pap_lower_down,
|
|
pap_open, pap_close);
|