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