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 #define IPCP_NUM_MY_OPTIONS 3
357 #define IPV6CP_NUM_MY_OPTIONS 1
358
359 enum ppp_flags {
360 PPP_CARRIER_UP,
361 };
362
363 /** @endcond */
364
365 /** Link control protocol options */
366 struct lcp_options {
367 /** Magic number */
368 uint32_t magic;
369
370 /** Async char map */
371 uint32_t async_map;
372
373 /** Maximum Receive Unit value */
374 uint16_t mru;
375
376 /** Which authentication protocol was negotiated (0 means none) */
377 uint16_t auth_proto;
378 };
379
380 #if defined(CONFIG_NET_L2_PPP_OPTION_MRU)
381 #define LCP_NUM_MY_OPTIONS 1
382 #endif
383
384 /** IPv4 control protocol options */
385 struct ipcp_options {
386 /** IPv4 address */
387 struct in_addr address;
388
389 /** Primary DNS server address */
390 struct in_addr dns1_address;
391
392 /** Secondary DNS server address */
393 struct in_addr dns2_address;
394 };
395
396 /** IPv6 control protocol options */
397 struct ipv6cp_options {
398 /** Interface identifier */
399 uint8_t iid[PPP_INTERFACE_IDENTIFIER_LEN];
400 };
401
402 /** PPP L2 context specific to certain network interface */
403 struct ppp_context {
404 /** Flags representing PPP state, which are accessed from multiple
405 * threads.
406 */
407 atomic_t flags;
408
409 /** PPP startup worker. */
410 struct k_work_delayable startup;
411
412 /** LCP options */
413 struct {
414 /** Finite state machine for LCP */
415 struct ppp_fsm fsm;
416
417 /** Options that we want to request */
418 struct lcp_options my_options;
419
420 /** Options that peer want to request */
421 struct lcp_options peer_options;
422
423 /** Magic-Number value */
424 uint32_t magic;
425 #if defined(CONFIG_NET_L2_PPP_OPTION_MRU)
426 struct ppp_my_option_data my_options_data[LCP_NUM_MY_OPTIONS];
427 #endif
428 } lcp;
429
430 #if defined(CONFIG_NET_IPV4)
431 /** ICMP options */
432 struct {
433 /** Finite state machine for IPCP */
434 struct ppp_fsm fsm;
435
436 /** Options that we want to request */
437 struct ipcp_options my_options;
438
439 /** Options that peer want to request */
440 struct ipcp_options peer_options;
441
442 /** My options runtime data */
443 struct ppp_my_option_data my_options_data[IPCP_NUM_MY_OPTIONS];
444 } ipcp;
445 #endif
446
447 #if defined(CONFIG_NET_IPV6)
448 /** IPV6CP options */
449 struct {
450 /** Finite state machine for IPV6CP */
451 struct ppp_fsm fsm;
452
453 /** Options that we want to request */
454 struct ipv6cp_options my_options;
455
456 /** Options that peer want to request */
457 struct ipv6cp_options peer_options;
458
459 /** My options runtime data */
460 struct ppp_my_option_data my_options_data[IPV6CP_NUM_MY_OPTIONS];
461 } ipv6cp;
462 #endif
463
464 #if defined(CONFIG_NET_L2_PPP_PAP)
465 /** PAP options */
466 struct {
467 /** Finite state machine for PAP */
468 struct ppp_fsm fsm;
469 } pap;
470 #endif
471
472 #if defined(CONFIG_NET_SHELL)
473 /** Network shell PPP command internal data */
474 struct {
475 /** Ping command internal data */
476 struct {
477 /** Callback to be called when Echo-Reply is received.
478 */
479 net_ppp_lcp_echo_reply_cb_t cb;
480
481 /** User specific data for the callback */
482 void *user_data;
483
484 /** User data length */
485 size_t user_data_len;
486 } echo_reply;
487
488 /** Used when waiting Echo-Reply */
489 struct k_sem wait_echo_reply;
490
491 /** Echo-Req data value */
492 uint32_t echo_req_data;
493
494 /** Echo-Reply data value */
495 uint32_t echo_reply_data;
496 } shell;
497 #endif
498
499 /** Network interface related to this PPP connection */
500 struct net_if *iface;
501
502 /** Network management callback structure */
503 struct net_mgmt_event_callback mgmt_evt_cb;
504
505 /** Current phase of PPP link */
506 enum ppp_phase phase;
507
508 /** Signal when PPP link is terminated */
509 struct k_sem wait_ppp_link_terminated;
510
511 /** Signal when PPP link is down */
512 struct k_sem wait_ppp_link_down;
513
514 /** This tells what features the PPP supports. */
515 enum net_l2_flags ppp_l2_flags;
516
517 /** This tells how many network protocols are open */
518 int network_protos_open;
519
520 /** This tells how many network protocols are up */
521 int network_protos_up;
522
523 /** Is PPP ready to receive packets */
524 uint16_t is_ready_to_serve : 1;
525
526 /** Is PPP L2 enabled or not */
527 uint16_t is_enabled : 1;
528
529 /** PPP enable pending */
530 uint16_t is_enable_done : 1;
531
532 /** IPCP status (up / down) */
533 uint16_t is_ipcp_up : 1;
534
535 /** IPCP open status (open / closed) */
536 uint16_t is_ipcp_open : 1;
537
538 /** IPV6CP status (up / down) */
539 uint16_t is_ipv6cp_up : 1;
540
541 /** IPV6CP open status (open / closed) */
542 uint16_t is_ipv6cp_open : 1;
543
544 /** PAP status (up / down) */
545 uint16_t is_pap_up : 1;
546
547 /** PAP open status (open / closed) */
548 uint16_t is_pap_open : 1;
549 };
550
551 /**
552 * @brief Initialize PPP L2 stack for a given interface
553 *
554 * @param iface A valid pointer to a network interface
555 */
556 void net_ppp_init(struct net_if *iface);
557
558 /* Management API for PPP */
559
560 /** @cond INTERNAL_HIDDEN */
561
562 #define PPP_L2_CTX_TYPE struct ppp_context
563
564 #define _NET_PPP_LAYER NET_MGMT_LAYER_L2
565 #define _NET_PPP_CODE 0x209
566 #define _NET_PPP_BASE (NET_MGMT_IFACE_BIT | \
567 NET_MGMT_LAYER(_NET_PPP_LAYER) | \
568 NET_MGMT_LAYER_CODE(_NET_PPP_CODE))
569 #define _NET_PPP_EVENT (_NET_PPP_BASE | NET_MGMT_EVENT_BIT)
570
571 enum net_event_ppp_cmd {
572 NET_EVENT_PPP_CMD_CARRIER_ON = 1,
573 NET_EVENT_PPP_CMD_CARRIER_OFF,
574 NET_EVENT_PPP_CMD_PHASE_RUNNING,
575 NET_EVENT_PPP_CMD_PHASE_DEAD,
576 };
577
578 struct net_if;
579
580 /** @endcond */
581
582 /** Event emitted when PPP carrier is on */
583 #define NET_EVENT_PPP_CARRIER_ON \
584 (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_ON)
585
586 /** Event emitted when PPP carrier is off */
587 #define NET_EVENT_PPP_CARRIER_OFF \
588 (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_OFF)
589
590 /** Event emitted when PPP goes into running phase */
591 #define NET_EVENT_PPP_PHASE_RUNNING \
592 (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_PHASE_RUNNING)
593
594 /** Event emitted when PPP goes into dead phase */
595 #define NET_EVENT_PPP_PHASE_DEAD \
596 (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_PHASE_DEAD)
597
598 /**
599 * @brief Raise CARRIER_ON event when PPP is connected.
600 *
601 * @param iface PPP network interface.
602 */
603 #if defined(CONFIG_NET_L2_PPP_MGMT)
604 void ppp_mgmt_raise_carrier_on_event(struct net_if *iface);
605 #else
ppp_mgmt_raise_carrier_on_event(struct net_if * iface)606 static inline void ppp_mgmt_raise_carrier_on_event(struct net_if *iface)
607 {
608 ARG_UNUSED(iface);
609 }
610 #endif
611
612 /**
613 * @brief Raise CARRIER_OFF event when PPP is disconnected.
614 *
615 * @param iface PPP network interface.
616 */
617 #if defined(CONFIG_NET_L2_PPP_MGMT)
618 void ppp_mgmt_raise_carrier_off_event(struct net_if *iface);
619 #else
ppp_mgmt_raise_carrier_off_event(struct net_if * iface)620 static inline void ppp_mgmt_raise_carrier_off_event(struct net_if *iface)
621 {
622 ARG_UNUSED(iface);
623 }
624 #endif
625
626 /**
627 * @brief Raise PHASE_RUNNING event when PPP reaching RUNNING phase
628 *
629 * @param iface PPP network interface.
630 */
631 #if defined(CONFIG_NET_L2_PPP_MGMT)
632 void ppp_mgmt_raise_phase_running_event(struct net_if *iface);
633 #else
ppp_mgmt_raise_phase_running_event(struct net_if * iface)634 static inline void ppp_mgmt_raise_phase_running_event(struct net_if *iface)
635 {
636 ARG_UNUSED(iface);
637 }
638 #endif
639
640 /**
641 * @brief Raise PHASE_DEAD event when PPP reaching DEAD phase
642 *
643 * @param iface PPP network interface.
644 */
645 #if defined(CONFIG_NET_L2_PPP_MGMT)
646 void ppp_mgmt_raise_phase_dead_event(struct net_if *iface);
647 #else
ppp_mgmt_raise_phase_dead_event(struct net_if * iface)648 static inline void ppp_mgmt_raise_phase_dead_event(struct net_if *iface)
649 {
650 ARG_UNUSED(iface);
651 }
652 #endif
653
654 /**
655 * @brief Send PPP Echo-Request to peer. We expect to receive Echo-Reply back.
656 *
657 * @param idx PPP network interface index
658 * @param timeout Amount of time to wait Echo-Reply. The value is in
659 * milliseconds.
660 *
661 * @return 0 if Echo-Reply was received, < 0 if there is a timeout or network
662 * index is not a valid PPP network index.
663 */
664 #if defined(CONFIG_NET_L2_PPP)
665 int net_ppp_ping(int idx, int32_t timeout);
666 #else
net_ppp_ping(int idx,int32_t timeout)667 static inline int net_ppp_ping(int idx, int32_t timeout)
668 {
669 ARG_UNUSED(idx);
670 ARG_UNUSED(timeout);
671
672 return -ENOTSUP;
673 }
674 #endif
675
676 /**
677 * @brief Get PPP context information. This is only used by net-shell to
678 * print information about PPP.
679 *
680 * @param idx PPP network interface index
681 *
682 * @return PPP context or NULL if idx is invalid.
683 */
684 #if defined(CONFIG_NET_L2_PPP) && defined(CONFIG_NET_SHELL)
685 struct ppp_context *net_ppp_context_get(int idx);
686 #else
net_ppp_context_get(int idx)687 static inline struct ppp_context *net_ppp_context_get(int idx)
688 {
689 ARG_UNUSED(idx);
690
691 return NULL;
692 }
693 #endif
694
695 #ifdef __cplusplus
696 }
697 #endif
698
699 /**
700 * @}
701 */
702
703 #endif /* ZEPHYR_INCLUDE_NET_PPP_H_ */
704