1 /*
2  *  Copyright (c) 2021, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * @brief
32  *   This file includes the platform abstraction for DNS Stateful Operations (DSO) transport.
33  */
34 
35 #ifndef OPENTHREAD_PLATFORM_DSO_TRANSPORT_H_
36 #define OPENTHREAD_PLATFORM_DSO_TRANSPORT_H_
37 
38 #include <stdint.h>
39 
40 #include <openthread/error.h>
41 #include <openthread/instance.h>
42 #include <openthread/ip6.h>
43 #include <openthread/message.h>
44 
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48 
49 /**
50  * Represents a DSO connection.
51  *
52  * It is an opaque struct (the platform implementation only deals with pointers to this struct).
53  */
54 typedef struct otPlatDsoConnection otPlatDsoConnection;
55 
56 /**
57  * Can be used by DSO platform implementation to get the the OpenThread instance associated with a
58  * connection instance.
59  *
60  * @param[in] aConnection   A pointer to the DSO connection.
61  *
62  * @returns A pointer to the `otInstance`.
63  */
64 extern otInstance *otPlatDsoGetInstance(otPlatDsoConnection *aConnection);
65 
66 /**
67  * Starts or stops listening for incoming connection requests on transport layer.
68  *
69  * For DNS-over-TLS, the transport layer MUST listen on port 853 and follow RFC 7858.
70  *
71  * While listening is enabled, if a connection request is received, the `otPlatDsoAccept()` callback MUST be called.
72  *
73  * @param[in] aInstance    The OpenThread instance.
74  * @param[in] aEnable      TRUE to start listening, FALSE to stop listening.
75  */
76 void otPlatDsoEnableListening(otInstance *aInstance, bool aEnable);
77 
78 /**
79  * Is a callback from the DSO platform to indicate an incoming connection request when listening is
80  * enabled.
81  *
82  * Determines whether or not to accept the connection request. It returns a non-null `otPlatDsoConnection`
83  * pointer if the request is to be accepted, or `NULL` if the request is to be rejected.
84  *
85  * If a non-null connection pointer is returned, the platform layer MUST continue establishing the connection with the
86  * peer. The platform reports the outcome by invoking `otPlatDsoHandleConnected()` callback on success or
87  * `otPlatDsoHandleDisconnected()` callback on failure.
88  *
89  * @param[in] aInstance      The OpenThread instance.
90  * @param[in] aPeerSockAddr  The socket address (IPv6 address and port number) of the peer requesting connection.
91  *
92  * @returns A pointer to the `otPlatDsoConnection` to use if to accept, or `NULL` if to reject.
93  */
94 extern otPlatDsoConnection *otPlatDsoAccept(otInstance *aInstance, const otSockAddr *aPeerSockAddr);
95 
96 /**
97  * Requests the platform layer to initiate establishing a connection with a peer.
98  *
99  * The platform reports the outcome by invoking `otPlatDsoHandleConnected()` callback on success or
100  * `otPlatDsoHandleDisconnected()` callback (on failure).
101  *
102  * @param[in] aConnection     The connection.
103  * @param[in] aPeerSockAddr   The socket address (IPv6 address and port number) of the peer to connect to.
104  */
105 void otPlatDsoConnect(otPlatDsoConnection *aConnection, const otSockAddr *aPeerSockAddr);
106 
107 /**
108  * Is a callback from the platform layer to indicate that a connection is successfully established.
109  *
110  * It MUST be called either after accepting an incoming connection (`otPlatDsoAccept`) or after a `otPlatDsoConnect()`
111  * call.
112  *
113  * Only after this callback, the connection can be used to send and receive messages.
114  *
115  * @param[in] aConnection     The connection.
116  */
117 extern void otPlatDsoHandleConnected(otPlatDsoConnection *aConnection);
118 
119 /**
120  * Sends a DSO message to the peer on a connection.
121  *
122  * Is used only after the connection is successfully established (after `otPlatDsoHandleConnected()`
123  * callback).
124  *
125  * Passes the ownership of the @p aMessage to the DSO platform layer, and the platform implementation is
126  * expected to free the message once it is no longer needed.
127  *
128  * The @p aMessage contains the DNS message (starting with DNS header). Note that it does not contain the the length
129  * field that is needed when sending over TLS/TCP transport. The platform layer MUST therefore include the length
130  * field when passing the message to TLS/TCP layer.
131  *
132  * @param[in] aConnection   The connection to send on.
133  * @param[in] aMessage      The message to send.
134  */
135 void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage);
136 
137 /**
138  * Is a callback from the platform layer to indicate that a DNS message was received over a connection.
139  *
140  * The platform MUST call this function only after the connection is successfully established (after callback
141  * `otPlatDsoHandleConnected()` is invoked).
142  *
143  * Passes the ownership of the @p aMessage from the DSO platform layer to OpenThread. OpenThread will
144  * free the message when no longer needed.
145  *
146  * The @p aMessage MUST contain the DNS message (starting with DNS header) and not include the length field that may
147  * be included in TCP/TLS exchange.
148  *
149  * @param[in] aConnection   The connection on which the message was received.
150  * @param[in] aMessage      The received message.
151  */
152 extern void otPlatDsoHandleReceive(otPlatDsoConnection *aConnection, otMessage *aMessage);
153 
154 /**
155  * Defines disconnect modes.
156  */
157 typedef enum
158 {
159     OT_PLAT_DSO_DISCONNECT_MODE_GRACEFULLY_CLOSE, ///< Gracefully close the connection.
160     OT_PLAT_DSO_DISCONNECT_MODE_FORCIBLY_ABORT,   ///< Forcibly abort the connection.
161 } otPlatDsoDisconnectMode;
162 
163 /**
164  * Requests a connection to be disconnected.
165  *
166  * After calling this function, the DSO platform implementation MUST NOT maintain `aConnection` pointer (platform
167  * MUST NOT call any callbacks using this `Connection` pointer anymore). In particular, calling `otPlatDsoDisconnect()`
168  * MUST NOT trigger the callback `otPlatDsoHandleDisconnected()`.
169  *
170  * @param[in] aConnection   The connection to disconnect
171  * @param[in] aMode         The disconnect mode (close gracefully or forcibly abort).
172  */
173 void otPlatDsoDisconnect(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode);
174 
175 /**
176  * Is a callback from the platform layer to indicate that peer closed/aborted the connection or the
177  * connection establishment failed (e.g., peer rejected a connection request).
178  *
179  * After calling this function, the DSO platform implementation MUST NOT maintain `aConnection` pointer (platform
180  * MUST NOT call any callbacks using this `Connection` pointer anymore).
181  *
182  * @param[in] aConnection   The connection which disconnected.
183  * @param[in] aMode         The disconnect mode (closed gracefully or forcibly aborted).
184  */
185 extern void otPlatDsoHandleDisconnected(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode);
186 
187 #ifdef __cplusplus
188 } // extern "C"
189 #endif
190 
191 #endif // OPENTHREAD_PLATFORM_DSO_TRANSPORT_H_
192