1 /*
2  * Copyright (c) 2019-2020 Grinn
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
9 
10 #include <zephyr/net/net_pkt.h>
11 
12 #include "ppp_internal.h"
13 
pap_handle(struct ppp_context * ctx,struct net_if * iface,struct net_pkt * pkt)14 static enum net_verdict pap_handle(struct ppp_context *ctx,
15 				   struct net_if *iface,
16 				   struct net_pkt *pkt)
17 {
18 	return ppp_fsm_input(&ctx->pap.fsm, PPP_PAP, pkt);
19 }
20 
pap_config_info_add(struct ppp_fsm * fsm)21 static struct net_pkt *pap_config_info_add(struct ppp_fsm *fsm)
22 {
23 	uint8_t payload[] = { 5, 'b', 'l', 'a', 'n', 'k',
24 			      5, 'b', 'l', 'a', 'n', 'k' };
25 	struct net_pkt *pkt;
26 
27 	pkt = net_pkt_alloc_with_buffer(ppp_fsm_iface(fsm), sizeof(payload),
28 					AF_UNSPEC, 0, PPP_BUF_ALLOC_TIMEOUT);
29 	if (!pkt) {
30 		return NULL;
31 	}
32 
33 	(void)net_pkt_write(pkt, payload, sizeof(payload));
34 
35 	return pkt;
36 }
37 
pap_config_info_ack(struct ppp_fsm * fsm,struct net_pkt * pkt,uint16_t length)38 static int pap_config_info_ack(struct ppp_fsm *fsm,
39 			       struct net_pkt *pkt,
40 			       uint16_t length)
41 {
42 	/*
43 	 * We only support one way negotiation for now, so move to ACK_SENT
44 	 * phase right away.
45 	 */
46 	if (fsm->state == PPP_REQUEST_SENT) {
47 		ppp_change_state(fsm, PPP_ACK_SENT);
48 	}
49 
50 	return 0;
51 }
52 
pap_lower_down(struct ppp_context * ctx)53 static void pap_lower_down(struct ppp_context *ctx)
54 {
55 	ppp_fsm_lower_down(&ctx->pap.fsm);
56 }
57 
pap_lower_up(struct ppp_context * ctx)58 static void pap_lower_up(struct ppp_context *ctx)
59 {
60 	ppp_fsm_lower_up(&ctx->pap.fsm);
61 }
62 
pap_open(struct ppp_context * ctx)63 static void pap_open(struct ppp_context *ctx)
64 {
65 	ppp_fsm_open(&ctx->pap.fsm);
66 }
67 
pap_close(struct ppp_context * ctx,const uint8_t * reason)68 static void pap_close(struct ppp_context *ctx, const uint8_t *reason)
69 {
70 	ppp_fsm_close(&ctx->pap.fsm, reason);
71 }
72 
pap_up(struct ppp_fsm * fsm)73 static void pap_up(struct ppp_fsm *fsm)
74 {
75 	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
76 					       pap.fsm);
77 
78 	if (ctx->is_pap_up) {
79 		return;
80 	}
81 
82 	ctx->is_pap_up = true;
83 
84 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
85 		ppp_state_str(fsm->state), fsm->state);
86 
87 	ppp_link_authenticated(ctx);
88 }
89 
pap_down(struct ppp_fsm * fsm)90 static void pap_down(struct ppp_fsm *fsm)
91 {
92 	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
93 					       pap.fsm);
94 
95 	if (!ctx->is_pap_up) {
96 		return;
97 	}
98 
99 	ctx->is_pap_up = false;
100 }
101 
pap_finished(struct ppp_fsm * fsm)102 static void pap_finished(struct ppp_fsm *fsm)
103 {
104 	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
105 					       pap.fsm);
106 
107 	if (!ctx->is_pap_open) {
108 		return;
109 	}
110 
111 	ctx->is_pap_open = false;
112 }
113 
pap_proto_reject(struct ppp_fsm * fsm)114 static void pap_proto_reject(struct ppp_fsm *fsm)
115 {
116 	ppp_fsm_lower_down(fsm);
117 }
118 
pap_init(struct ppp_context * ctx)119 static void pap_init(struct ppp_context *ctx)
120 {
121 	NET_DBG("proto %s (0x%04x) fsm %p", ppp_proto2str(PPP_PAP), PPP_PAP,
122 		&ctx->pap.fsm);
123 
124 	memset(&ctx->pap.fsm, 0, sizeof(ctx->pap.fsm));
125 
126 	ppp_fsm_init(&ctx->pap.fsm, PPP_PAP);
127 
128 	ppp_fsm_name_set(&ctx->pap.fsm, ppp_proto2str(PPP_PAP));
129 
130 	ctx->pap.fsm.cb.up = pap_up;
131 	ctx->pap.fsm.cb.down = pap_down;
132 	ctx->pap.fsm.cb.finished = pap_finished;
133 	ctx->pap.fsm.cb.proto_reject = pap_proto_reject;
134 	ctx->pap.fsm.cb.config_info_add = pap_config_info_add;
135 	ctx->pap.fsm.cb.config_info_ack = pap_config_info_ack;
136 }
137 
138 PPP_PROTOCOL_REGISTER(PAP, PPP_PAP,
139 		      pap_init, pap_handle,
140 		      pap_lower_up, pap_lower_down,
141 		      pap_open, pap_close);
142