1 /*
2 * Copyright (c) 2019 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7
8 #ifndef ZEPHYR_INCLUDE_NET_PPP_H_
9 #define ZEPHYR_INCLUDE_NET_PPP_H_
10
11 #include <zephyr/net/net_if.h>
12 #include <zephyr/net/net_pkt.h>
13 #include <zephyr/net/net_stats.h>
14 #include <zephyr/net/net_mgmt.h>
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19
20 /**
21 * @brief Point-to-point (PPP) L2/driver support functions
22 * @defgroup ppp PPP L2/driver Support Functions
23 * @ingroup networking
24 * @{
25 */
26
27 /** PPP maximum receive unit (MRU) */
28 #define PPP_MRU CONFIG_NET_PPP_MTU_MRU
29
30 /** PPP maximum transfer unit (MTU) */
31 #define PPP_MTU PPP_MRU
32
33 /** Max length of terminate description string */
34 #define PPP_MAX_TERMINATE_REASON_LEN 32
35
36 /** Length of network interface identifier */
37 #define PPP_INTERFACE_IDENTIFIER_LEN 8
38
39 /** PPP L2 API */
40 struct ppp_api {
41 /**
42 * The net_if_api must be placed in first position in this
43 * struct so that we are compatible with network interface API.
44 */
45 struct net_if_api iface_api;
46
47 /** Start the device */
48 int (*start)(const struct device *dev);
49
50 /** Stop the device */
51 int (*stop)(const struct device *dev);
52
53 /** Send a network packet */
54 int (*send)(const struct device *dev, struct net_pkt *pkt);
55
56 #if defined(CONFIG_NET_STATISTICS_PPP)
57 /** Collect optional PPP specific statistics. This pointer
58 * should be set by driver if statistics needs to be collected
59 * for that driver.
60 */
61 struct net_stats_ppp *(*get_stats)(const struct device *dev);
62 #endif
63 };
64
65 /* Make sure that the network interface API is properly setup inside
66 * PPP API struct (it is the first one).
67 */
68 BUILD_ASSERT(offsetof(struct ppp_api, iface_api) == 0);
69
70 /**
71 * PPP protocol types.
72 * See https://www.iana.org/assignments/ppp-numbers/ppp-numbers.xhtml
73 * for details.
74 */
75 enum ppp_protocol_type {
76 PPP_IP = 0x0021, /**< RFC 1332 */
77 PPP_IPV6 = 0x0057, /**< RFC 5072 */
78 PPP_IPCP = 0x8021, /**< RFC 1332 */
79 PPP_ECP = 0x8053, /**< RFC 1968 */
80 PPP_IPV6CP = 0x8057, /**< RFC 5072 */
81 PPP_CCP = 0x80FD, /**< RFC 1962 */
82 PPP_LCP = 0xc021, /**< RFC 1661 */
83 PPP_PAP = 0xc023, /**< RFC 1334 */
84 PPP_CHAP = 0xc223, /**< RFC 1334 */
85 PPP_EAP = 0xc227, /**< RFC 2284 */
86 };
87
88 /**
89 * PPP phases
90 */
91 enum ppp_phase {
92 /** Physical-layer not ready */
93 PPP_DEAD,
94 /** Link is being established */
95 PPP_ESTABLISH,
96 /** Link authentication with peer */
97 PPP_AUTH,
98 /** Network connection establishment */
99 PPP_NETWORK,
100 /** Network running */
101 PPP_RUNNING,
102 /** Link termination */
103 PPP_TERMINATE,
104 };
105
106 /**
107 * PPP states, RFC 1661 ch. 4.2
108 */
109 enum ppp_state {
110 PPP_INITIAL,
111 PPP_STARTING,
112 PPP_CLOSED,
113 PPP_STOPPED,
114 PPP_CLOSING,
115 PPP_STOPPING,
116 PPP_REQUEST_SENT,
117 PPP_ACK_RECEIVED,
118 PPP_ACK_SENT,
119 PPP_OPENED
120 };
121
122 /**
123 * PPP protocol operations from RFC 1661
124 */
125 enum ppp_packet_type {
126 PPP_CONFIGURE_REQ = 1,
127 PPP_CONFIGURE_ACK = 2,
128 PPP_CONFIGURE_NACK = 3,
129 PPP_CONFIGURE_REJ = 4,
130 PPP_TERMINATE_REQ = 5,
131 PPP_TERMINATE_ACK = 6,
132 PPP_CODE_REJ = 7,
133 PPP_PROTOCOL_REJ = 8,
134 PPP_ECHO_REQ = 9,
135 PPP_ECHO_REPLY = 10,
136 PPP_DISCARD_REQ = 11
137 };
138
139 /**
140 * LCP option types from RFC 1661 ch. 6
141 */
142 enum lcp_option_type {
143 LCP_OPTION_RESERVED = 0,
144
145 /** Maximum-Receive-Unit */
146 LCP_OPTION_MRU = 1,
147
148 /** Async-Control-Character-Map */
149 LCP_OPTION_ASYNC_CTRL_CHAR_MAP = 2,
150
151 /** Authentication-Protocol */
152 LCP_OPTION_AUTH_PROTO = 3,
153
154 /** Quality-Protocol */
155 LCP_OPTION_QUALITY_PROTO = 4,
156
157 /** Magic-Number */
158 LCP_OPTION_MAGIC_NUMBER = 5,
159
160 /** Protocol-Field-Compression */
161 LCP_OPTION_PROTO_COMPRESS = 7,
162
163 /** Address-and-Control-Field-Compression */
164 LCP_OPTION_ADDR_CTRL_COMPRESS = 8
165 } __packed;
166
167 /**
168 * IPCP option types from RFC 1332
169 */
170 enum ipcp_option_type {
171 IPCP_OPTION_RESERVED = 0,
172
173 /** IP Addresses */
174 IPCP_OPTION_IP_ADDRESSES = 1,
175
176 /** IP Compression Protocol */
177 IPCP_OPTION_IP_COMP_PROTO = 2,
178
179 /** IP Address */
180 IPCP_OPTION_IP_ADDRESS = 3,
181
182 /* RFC 1877 */
183
184 /** Primary DNS Server Address */
185 IPCP_OPTION_DNS1 = 129,
186
187 /** Primary NBNS Server Address */
188 IPCP_OPTION_NBNS1 = 130,
189
190 /** Secondary DNS Server Address */
191 IPCP_OPTION_DNS2 = 131,
192
193 /** Secondary NBNS Server Address */
194 IPCP_OPTION_NBNS2 = 132,
195 } __packed;
196
197 /**
198 * IPV6CP option types from RFC 5072
199 */
200 enum ipv6cp_option_type {
201 IPV6CP_OPTION_RESERVED = 0,
202
203 /** Interface identifier */
204 IPV6CP_OPTION_INTERFACE_IDENTIFIER = 1,
205 } __packed;
206
207 /**
208 * @typedef net_ppp_lcp_echo_reply_cb_t
209 * @brief A callback function that can be called if a Echo-Reply needs to
210 * be received.
211 * @param user_data User settable data that is passed to the callback
212 * function.
213 * @param user_data_len Length of the user data.
214 */
215 typedef void (*net_ppp_lcp_echo_reply_cb_t)(void *user_data,
216 size_t user_data_len);
217
218 struct ppp_my_option_data;
219 struct ppp_my_option_info;
220
221 /**
222 * Generic PPP Finite State Machine
223 */
224 struct ppp_fsm {
225 /** Timeout timer */
226 struct k_work_delayable timer;
227
228 struct {
229 /** Acknowledge Configuration Information */
230 int (*config_info_ack)(struct ppp_fsm *fsm,
231 struct net_pkt *pkt,
232 uint16_t length);
233
234 /** Add Configuration Information */
235 struct net_pkt *(*config_info_add)(struct ppp_fsm *fsm);
236
237 /** Length of Configuration Information */
238 int (*config_info_len)(struct ppp_fsm *fsm);
239
240 /** Negative Acknowledge Configuration Information */
241 int (*config_info_nack)(struct ppp_fsm *fsm,
242 struct net_pkt *pkt,
243 uint16_t length,
244 bool rejected);
245
246 /** Request peer's Configuration Information */
247 int (*config_info_req)(struct ppp_fsm *fsm,
248 struct net_pkt *pkt,
249 uint16_t length,
250 struct net_pkt *ret_pkt);
251
252 /** Reject Configuration Information */
253 int (*config_info_rej)(struct ppp_fsm *fsm,
254 struct net_pkt *pkt,
255 uint16_t length);
256
257 /** Reset Configuration Information */
258 void (*config_info_reset)(struct ppp_fsm *fsm);
259
260 /** FSM goes to OPENED state */
261 void (*up)(struct ppp_fsm *fsm);
262
263 /** FSM leaves OPENED state */
264 void (*down)(struct ppp_fsm *fsm);
265
266 /** Starting this protocol */
267 void (*starting)(struct ppp_fsm *fsm);
268
269 /** Quitting this protocol */
270 void (*finished)(struct ppp_fsm *fsm);
271
272 /** We received Protocol-Reject */
273 void (*proto_reject)(struct ppp_fsm *fsm);
274
275 /** Retransmit */
276 void (*retransmit)(struct ppp_fsm *fsm);
277
278 /** Any code that is not understood by PPP is passed to
279 * this FSM for further processing.
280 */
281 enum net_verdict (*proto_extension)(struct ppp_fsm *fsm,
282 enum ppp_packet_type code,
283 uint8_t id,
284 struct net_pkt *pkt);
285 } cb;
286
287 struct {
288 /** Options information */
289 const struct ppp_my_option_info *info;
290
291 /** Options negotiation data */
292 struct ppp_my_option_data *data;
293
294 /** Number of negotiated options */
295 size_t count;
296 } my_options;
297
298 /** Option bits */
299 uint32_t flags;
300
301 /** Number of re-transmissions left */;
302 uint32_t retransmits;
303
304 /** Number of NACK loops since last ACK */
305 uint32_t nack_loops;
306
307 /** Number of NACKs received */
308 uint32_t recv_nack_loops;
309
310 /** Reason for closing protocol */
311 char terminate_reason[PPP_MAX_TERMINATE_REASON_LEN];
312
313 /** PPP protocol number for this FSM */
314 uint16_t protocol;
315
316 /** Current state of PPP link */
317 enum ppp_state state;
318
319 /** Protocol/layer name of this FSM (for debugging) */
320 const char *name;
321
322 /** Current id */
323 uint8_t id;
324
325 /** Current request id */
326 uint8_t req_id;
327
328 /** Have received valid Ack, Nack or Reject to a Request */
329 uint8_t ack_received : 1;
330 };
331
332 #define PPP_MY_OPTION_ACKED BIT(0)
333 #define PPP_MY_OPTION_REJECTED BIT(1)
334
335 struct ppp_my_option_data {
336 uint32_t flags;
337 };
338
339 struct lcp_options {
340 /** Magic number */
341 uint32_t magic;
342
343 /** Async char map */
344 uint32_t async_map;
345
346 /** Maximum Receive Unit value */
347 uint16_t mru;
348
349 /** Which authentication protocol was negotiated (0 means none) */
350 uint16_t auth_proto;
351 };
352
353 #if defined(CONFIG_NET_L2_PPP_OPTION_MRU)
354 #define LCP_NUM_MY_OPTIONS 1
355 #endif
356
357 struct ipcp_options {
358 /** IPv4 address */
359 struct in_addr address;
360 struct in_addr dns1_address;
361 struct in_addr dns2_address;
362 };
363
364 #define IPCP_NUM_MY_OPTIONS 3
365
366 struct ipv6cp_options {
367 /** Interface identifier */
368 uint8_t iid[PPP_INTERFACE_IDENTIFIER_LEN];
369 };
370
371 #define IPV6CP_NUM_MY_OPTIONS 1
372
373 enum ppp_flags {
374 PPP_CARRIER_UP,
375 };
376
377 /** PPP L2 context specific to certain network interface */
378 struct ppp_context {
379 /** Flags representing PPP state, which are accessed from multiple
380 * threads.
381 */
382 atomic_t flags;
383
384 /** PPP startup worker. */
385 struct k_work_delayable startup;
386
387 /** Carrier ON/OFF handler worker. This is used to create
388 * network interface UP/DOWN event when PPP L2 driver
389 * notices carrier ON/OFF situation. We must not create another
390 * network management event from inside management handler thus
391 * we use worker thread to trigger the UP/DOWN event.
392 */
393 struct k_work carrier_work;
394
395 struct {
396 /** Finite state machine for LCP */
397 struct ppp_fsm fsm;
398
399 /** Options that we want to request */
400 struct lcp_options my_options;
401
402 /** Options that peer want to request */
403 struct lcp_options peer_options;
404
405 /** Magic-Number value */
406 uint32_t magic;
407 #if defined(CONFIG_NET_L2_PPP_OPTION_MRU)
408 struct ppp_my_option_data my_options_data[LCP_NUM_MY_OPTIONS];
409 #endif
410 } lcp;
411
412 #if defined(CONFIG_NET_IPV4)
413 struct {
414 /** Finite state machine for IPCP */
415 struct ppp_fsm fsm;
416
417 /** Options that we want to request */
418 struct ipcp_options my_options;
419
420 /** Options that peer want to request */
421 struct ipcp_options peer_options;
422
423 /** My options runtime data */
424 struct ppp_my_option_data my_options_data[IPCP_NUM_MY_OPTIONS];
425 } ipcp;
426 #endif
427
428 #if defined(CONFIG_NET_IPV6)
429 struct {
430 /** Finite state machine for IPV6CP */
431 struct ppp_fsm fsm;
432
433 /** Options that we want to request */
434 struct ipv6cp_options my_options;
435
436 /** Options that peer want to request */
437 struct ipv6cp_options peer_options;
438
439 /** My options runtime data */
440 struct ppp_my_option_data my_options_data[IPV6CP_NUM_MY_OPTIONS];
441 } ipv6cp;
442 #endif
443
444 #if defined(CONFIG_NET_L2_PPP_PAP)
445 struct {
446 /** Finite state machine for PAP */
447 struct ppp_fsm fsm;
448 } pap;
449 #endif
450
451 #if defined(CONFIG_NET_SHELL)
452 struct {
453 struct {
454 /** Callback to be called when Echo-Reply is received.
455 */
456 net_ppp_lcp_echo_reply_cb_t cb;
457
458 /** User specific data for the callback */
459 void *user_data;
460
461 /** User data length */
462 size_t user_data_len;
463 } echo_reply;
464
465 /** Used when waiting Echo-Reply */
466 struct k_sem wait_echo_reply;
467
468 /** Echo-Req data value */
469 uint32_t echo_req_data;
470
471 /** Echo-Reply data value */
472 uint32_t echo_reply_data;
473 } shell;
474 #endif
475
476 /** Network interface related to this PPP connection */
477 struct net_if *iface;
478
479 /** Current phase of PPP link */
480 enum ppp_phase phase;
481
482 /** This tells what features the PPP supports. */
483 enum net_l2_flags ppp_l2_flags;
484
485 /** This tells how many network protocols are open */
486 int network_protos_open;
487
488 /** This tells how many network protocols are up */
489 int network_protos_up;
490
491 /** Is network carrier up */
492 uint16_t is_net_carrier_up : 1;
493
494 /** Is PPP ready to receive packets */
495 uint16_t is_ready_to_serve : 1;
496
497 /** Is PPP L2 enabled or not */
498 uint16_t is_enabled : 1;
499
500 /** PPP startup pending */
501 uint16_t is_startup_pending : 1;
502
503 /** PPP enable pending */
504 uint16_t is_enable_done : 1;
505
506 /** IPCP status (up / down) */
507 uint16_t is_ipcp_up : 1;
508
509 /** IPCP open status (open / closed) */
510 uint16_t is_ipcp_open : 1;
511
512 /** IPV6CP status (up / down) */
513 uint16_t is_ipv6cp_up : 1;
514
515 /** IPV6CP open status (open / closed) */
516 uint16_t is_ipv6cp_open : 1;
517
518 /** PAP status (up / down) */
519 uint16_t is_pap_up : 1;
520
521 /** PAP open status (open / closed) */
522 uint16_t is_pap_open : 1;
523 };
524
525 /**
526 * @brief Inform PPP L2 driver that carrier is detected.
527 * This happens when cable is connected etc.
528 *
529 * @param iface Network interface
530 */
531 void net_ppp_carrier_on(struct net_if *iface);
532
533 /**
534 * @brief Inform PPP L2 driver that carrier was lost.
535 * This happens when cable is disconnected etc.
536 *
537 * @param iface Network interface
538 */
539 void net_ppp_carrier_off(struct net_if *iface);
540
541 /**
542 * @brief Initialize PPP L2 stack for a given interface
543 *
544 * @param iface A valid pointer to a network interface
545 */
546 void net_ppp_init(struct net_if *iface);
547
548 /* Management API for PPP */
549
550 /** @cond INTERNAL_HIDDEN */
551
552 #define PPP_L2_CTX_TYPE struct ppp_context
553
554 #define _NET_PPP_LAYER NET_MGMT_LAYER_L2
555 #define _NET_PPP_CODE 0x209
556 #define _NET_PPP_BASE (NET_MGMT_IFACE_BIT | \
557 NET_MGMT_LAYER(_NET_PPP_LAYER) | \
558 NET_MGMT_LAYER_CODE(_NET_PPP_CODE))
559 #define _NET_PPP_EVENT (_NET_PPP_BASE | NET_MGMT_EVENT_BIT)
560
561 enum net_event_ppp_cmd {
562 NET_EVENT_PPP_CMD_CARRIER_ON = 1,
563 NET_EVENT_PPP_CMD_CARRIER_OFF,
564 NET_EVENT_PPP_CMD_PHASE_RUNNING,
565 NET_EVENT_PPP_CMD_PHASE_DEAD,
566 };
567
568 #define NET_EVENT_PPP_CARRIER_ON \
569 (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_ON)
570
571 #define NET_EVENT_PPP_CARRIER_OFF \
572 (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_OFF)
573
574 #define NET_EVENT_PPP_PHASE_RUNNING \
575 (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_PHASE_RUNNING)
576
577 #define NET_EVENT_PPP_PHASE_DEAD \
578 (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_PHASE_DEAD)
579
580 struct net_if;
581
582 /** @endcond */
583
584 /**
585 * @brief Raise CARRIER_ON event when PPP is connected.
586 *
587 * @param iface PPP network interface.
588 */
589 #if defined(CONFIG_NET_L2_PPP_MGMT)
590 void ppp_mgmt_raise_carrier_on_event(struct net_if *iface);
591 #else
ppp_mgmt_raise_carrier_on_event(struct net_if * iface)592 static inline void ppp_mgmt_raise_carrier_on_event(struct net_if *iface)
593 {
594 ARG_UNUSED(iface);
595 }
596 #endif
597
598 /**
599 * @brief Raise CARRIER_OFF event when PPP is disconnected.
600 *
601 * @param iface PPP network interface.
602 */
603 #if defined(CONFIG_NET_L2_PPP_MGMT)
604 void ppp_mgmt_raise_carrier_off_event(struct net_if *iface);
605 #else
ppp_mgmt_raise_carrier_off_event(struct net_if * iface)606 static inline void ppp_mgmt_raise_carrier_off_event(struct net_if *iface)
607 {
608 ARG_UNUSED(iface);
609 }
610 #endif
611
612 /**
613 * @brief Raise PHASE_RUNNING event when PPP reaching RUNNING phase
614 *
615 * @param iface PPP network interface.
616 */
617 #if defined(CONFIG_NET_L2_PPP_MGMT)
618 void ppp_mgmt_raise_phase_running_event(struct net_if *iface);
619 #else
ppp_mgmt_raise_phase_running_event(struct net_if * iface)620 static inline void ppp_mgmt_raise_phase_running_event(struct net_if *iface)
621 {
622 ARG_UNUSED(iface);
623 }
624 #endif
625
626 /**
627 * @brief Raise PHASE_DEAD event when PPP reaching DEAD phase
628 *
629 * @param iface PPP network interface.
630 */
631 #if defined(CONFIG_NET_L2_PPP_MGMT)
632 void ppp_mgmt_raise_phase_dead_event(struct net_if *iface);
633 #else
ppp_mgmt_raise_phase_dead_event(struct net_if * iface)634 static inline void ppp_mgmt_raise_phase_dead_event(struct net_if *iface)
635 {
636 ARG_UNUSED(iface);
637 }
638 #endif
639
640 /**
641 * @brief Send PPP Echo-Request to peer. We expect to receive Echo-Reply back.
642 *
643 * @param idx PPP network interface index
644 * @param timeout Amount of time to wait Echo-Reply. The value is in
645 * milliseconds.
646 *
647 * @return 0 if Echo-Reply was received, < 0 if there is a timeout or network
648 * index is not a valid PPP network index.
649 */
650 #if defined(CONFIG_NET_L2_PPP)
651 int net_ppp_ping(int idx, int32_t timeout);
652 #else
net_ppp_ping(int idx,int32_t timeout)653 static inline int net_ppp_ping(int idx, int32_t timeout)
654 {
655 ARG_UNUSED(idx);
656 ARG_UNUSED(timeout);
657
658 return -ENOTSUP;
659 }
660 #endif
661
662 /**
663 * @brief Get PPP context information. This is only used by net-shell to
664 * print information about PPP.
665 *
666 * @param idx PPP network interface index
667 *
668 * @return PPP context or NULL if idx is invalid.
669 */
670 #if defined(CONFIG_NET_L2_PPP) && defined(CONFIG_NET_SHELL)
671 struct ppp_context *net_ppp_context_get(int idx);
672 #else
net_ppp_context_get(int idx)673 static inline struct ppp_context *net_ppp_context_get(int idx)
674 {
675 ARG_UNUSED(idx);
676
677 return NULL;
678 }
679 #endif
680
681 #ifdef __cplusplus
682 }
683 #endif
684
685 /**
686 * @}
687 */
688
689 #endif /* ZEPHYR_INCLUDE_NET_PPP_H_ */
690