1 /** @file
2  @brief PPP private header
3 
4  This is not to be included by the application.
5  */
6 
7 /*
8  * Copyright (c) 2019 Intel Corporation
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #include <zephyr/net/ppp.h>
14 #include <zephyr/sys/iterable_sections.h>
15 
16 /**
17  * FSM flags that control how it operates.
18  */
19 #define FSM_RESTART    BIT(0) /**< Treat 2nd OPEN as DOWN followed by UP    */
20 
21 /**
22  * PPP packet format.
23  */
24 struct ppp_packet {
25 	uint8_t code;
26 	uint8_t id;
27 	uint16_t length;
28 } __packed;
29 
30 /** Max Terminate-Request transmissions */
31 #define MAX_TERMINATE_REQ  CONFIG_NET_L2_PPP_MAX_TERMINATE_REQ_RETRANSMITS
32 
33 /** Max Configure-Request transmissions */
34 #define MAX_CONFIGURE_REQ CONFIG_NET_L2_PPP_MAX_CONFIGURE_REQ_RETRANSMITS
35 
36 #define PPP_BUF_ALLOC_TIMEOUT	K_MSEC(100)
37 
38 /** Protocol handler information. */
39 struct ppp_protocol_handler {
40 	/** Protocol init function */
41 	void (*init)(struct ppp_context *ctx);
42 
43 	/** Process a received packet */
44 	enum net_verdict (*handler)(struct ppp_context *ctx,
45 				    struct net_if *iface,
46 				    struct net_pkt *pkt);
47 
48 	/** Lower layer up */
49 	void (*lower_up)(struct ppp_context *ctx);
50 
51 	/** Lower layer down */
52 	void (*lower_down)(struct ppp_context *ctx);
53 
54 	/** Enable this protocol */
55 	void (*open)(struct ppp_context *ctx);
56 
57 	/** Disable this protocol */
58 	void (*close)(struct ppp_context *ctx, const uint8_t *reason);
59 
60 	/** PPP protocol number */
61 	uint16_t protocol;
62 };
63 
64 struct ppp_peer_option_info {
65 	uint8_t code;
66 	int (*parse)(struct ppp_fsm *fsm, struct net_pkt *pkt,
67 		     void *user_data);
68 	int (*nack)(struct ppp_fsm *fsm, struct net_pkt *ret_pkt,
69 		    void *user_data);
70 };
71 
72 #define PPP_PEER_OPTION(_code, _parse, _nack)	\
73 	{					\
74 		.code = _code,			\
75 		.parse = _parse,		\
76 		.nack = _nack,			\
77 	}
78 
79 int ppp_config_info_req(struct ppp_fsm *fsm,
80 			struct net_pkt *pkt,
81 			uint16_t length,
82 			struct net_pkt *ret_pkt,
83 			enum ppp_protocol_type protocol,
84 			const struct ppp_peer_option_info *options_info,
85 			size_t num_options_info,
86 			void *user_data);
87 
88 #define PPP_PROTO_GET_NAME(proto_name)		\
89 	_CONCAT(ppp_protocol_handler_, proto_name)
90 
91 #define PPP_PROTOCOL_REGISTER(name, proto, init_func, proto_handler,	\
92 			      proto_lower_up, proto_lower_down,		\
93 			      proto_open, proto_close)			\
94 	static const STRUCT_SECTION_ITERABLE(ppp_protocol_handler,	\
95 					PPP_PROTO_GET_NAME(name)) = {	\
96 		.protocol = proto,					\
97 		.init = init_func,					\
98 		.handler = proto_handler,				\
99 		.lower_up = proto_lower_up,				\
100 		.lower_down = proto_lower_down,				\
101 		.open = proto_open,					\
102 		.close = proto_close,					\
103 	}
104 
105 void ppp_queue_pkt(struct net_pkt *pkt);
106 const char *ppp_phase_str(enum ppp_phase phase);
107 const char *ppp_state_str(enum ppp_state state);
108 const char *ppp_proto2str(uint16_t proto);
109 const char *ppp_pkt_type2str(enum ppp_packet_type type);
110 const char *ppp_option2str(enum ppp_protocol_type protocol, int type);
111 void ppp_fsm_name_set(struct ppp_fsm *fsm, const char *name);
112 
113 #if CONFIG_NET_L2_PPP_LOG_LEVEL < LOG_LEVEL_DBG
114 void ppp_change_phase(struct ppp_context *ctx, enum ppp_phase new_phase);
115 void ppp_change_state(struct ppp_fsm *fsm, enum ppp_state new_state);
116 #else
117 void ppp_change_phase_debug(struct ppp_context *ctx,
118 			    enum ppp_phase new_phase,
119 			    const char *caller, int line);
120 
121 #define ppp_change_phase(ctx, state)				\
122 	ppp_change_phase_debug(ctx, state, __func__, __LINE__)
123 
124 #define ppp_change_state(fsm, state)				\
125 	ppp_change_state_debug(fsm, state, __func__, __LINE__)
126 
127 void ppp_change_state_debug(struct ppp_fsm *fsm, enum ppp_state new_state,
128 			    const char *caller, int line);
129 #endif
130 
131 struct ppp_context *ppp_fsm_ctx(struct ppp_fsm *fsm);
132 struct net_if *ppp_fsm_iface(struct ppp_fsm *fsm);
133 int ppp_send_pkt(struct ppp_fsm *fsm, struct net_if *iface,
134 		 enum ppp_packet_type type, uint8_t id,
135 		 void *data, uint32_t data_len);
136 void ppp_send_proto_rej(struct net_if *iface, struct net_pkt *pkt,
137 			uint16_t protocol);
138 
139 void ppp_fsm_init(struct ppp_fsm *fsm, uint16_t protocol);
140 void ppp_fsm_lower_up(struct ppp_fsm *fsm);
141 void ppp_fsm_lower_down(struct ppp_fsm *fsm);
142 void ppp_fsm_open(struct ppp_fsm *fsm);
143 void ppp_fsm_close(struct ppp_fsm *fsm, const uint8_t *reason);
144 void ppp_fsm_proto_reject(struct ppp_fsm *fsm);
145 enum net_verdict ppp_fsm_input(struct ppp_fsm *fsm, uint16_t proto,
146 			       struct net_pkt *pkt);
147 enum net_verdict ppp_fsm_recv_protocol_rej(struct ppp_fsm *fsm,
148 					   uint8_t id,
149 					   struct net_pkt *pkt);
150 enum net_verdict ppp_fsm_recv_echo_req(struct ppp_fsm *fsm,
151 				       uint8_t id,
152 				       struct net_pkt *pkt);
153 enum net_verdict ppp_fsm_recv_echo_reply(struct ppp_fsm *fsm,
154 					 uint8_t id,
155 					 struct net_pkt *pkt);
156 enum net_verdict ppp_fsm_recv_discard_req(struct ppp_fsm *fsm,
157 					  uint8_t id,
158 					  struct net_pkt *pkt);
159 
160 const struct ppp_protocol_handler *ppp_lcp_get(void);
161 int ppp_parse_options(struct ppp_fsm *fsm, struct net_pkt *pkt,
162 		      uint16_t length,
163 		      int (*parse)(struct net_pkt *pkt, uint8_t code,
164 				   uint8_t len, void *user_data),
165 		      void *user_data);
166 
167 void ppp_link_established(struct ppp_context *ctx, struct ppp_fsm *fsm);
168 void ppp_link_authenticated(struct ppp_context *ctx);
169 void ppp_link_terminated(struct ppp_context *ctx);
170 void ppp_link_down(struct ppp_context *ctx);
171 void ppp_link_needed(struct ppp_context *ctx);
172 
173 void ppp_network_up(struct ppp_context *ctx, int proto);
174 void ppp_network_down(struct ppp_context *ctx, int proto);
175 void ppp_network_done(struct ppp_context *ctx, int proto);
176 void ppp_network_all_down(struct ppp_context *ctx);
177 
178 struct ppp_my_option_info {
179 	uint8_t code;
180 	int (*conf_req_add)(struct ppp_context *ctx, struct net_pkt *pkt);
181 	int (*conf_ack_handle)(struct ppp_context *ctx, struct net_pkt *pkt,
182 			       uint8_t oplen);
183 	int (*conf_nak_handle)(struct ppp_context *ctx, struct net_pkt *pkt,
184 			       uint8_t oplen);
185 };
186 
187 #define PPP_MY_OPTION(_code, _req_add, _handle_ack, _handle_nak)	\
188 	{								\
189 		.code = _code,						\
190 		.conf_req_add = _req_add,				\
191 		.conf_ack_handle = _handle_ack,				\
192 		.conf_nak_handle = _handle_nak,				\
193 	}
194 
195 struct net_pkt *ppp_my_options_add(struct ppp_fsm *fsm, size_t packet_len);
196 
197 int ppp_my_options_parse_conf_ack(struct ppp_fsm *fsm,
198 				  struct net_pkt *pkt,
199 				  uint16_t length);
200 
201 int ppp_my_options_parse_conf_nak(struct ppp_fsm *fsm,
202 				  struct net_pkt *pkt,
203 				  uint16_t length);
204 
205 int ppp_my_options_parse_conf_rej(struct ppp_fsm *fsm,
206 				  struct net_pkt *pkt,
207 				  uint16_t length);
208 
209 uint32_t ppp_my_option_flags(struct ppp_fsm *fsm, uint8_t code);
210 
ppp_my_option_is_acked(struct ppp_fsm * fsm,uint8_t code)211 static inline bool ppp_my_option_is_acked(struct ppp_fsm *fsm,
212 					  uint8_t code)
213 {
214 	return ppp_my_option_flags(fsm, code) & PPP_MY_OPTION_ACKED;
215 }
216