mbed port of tinydtls

Committer:
ashleymills
Date:
Fri Oct 11 08:46:21 2013 +0000
Revision:
1:bc8a649bad13
Parent:
0:04990d454f45
Cleaned up all the debug stuff I added finding the hash table bug.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:04990d454f45 1 /* dtls -- a very basic DTLS implementation
ashleymills 0:04990d454f45 2 *
ashleymills 0:04990d454f45 3 * Copyright (C) 2011--2013 Olaf Bergmann <bergmann@tzi.org>
ashleymills 0:04990d454f45 4 *
ashleymills 0:04990d454f45 5 * Permission is hereby granted, free of charge, to any person
ashleymills 0:04990d454f45 6 * obtaining a copy of this software and associated documentation
ashleymills 0:04990d454f45 7 * files (the "Software"), to deal in the Software without
ashleymills 0:04990d454f45 8 * restriction, including without limitation the rights to use, copy,
ashleymills 0:04990d454f45 9 * modify, merge, publish, distribute, sublicense, and/or sell copies
ashleymills 0:04990d454f45 10 * of the Software, and to permit persons to whom the Software is
ashleymills 0:04990d454f45 11 * furnished to do so, subject to the following conditions:
ashleymills 0:04990d454f45 12 *
ashleymills 0:04990d454f45 13 * The above copyright notice and this permission notice shall be
ashleymills 0:04990d454f45 14 * included in all copies or substantial portions of the Software.
ashleymills 0:04990d454f45 15 *
ashleymills 0:04990d454f45 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
ashleymills 0:04990d454f45 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
ashleymills 0:04990d454f45 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ashleymills 0:04990d454f45 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
ashleymills 0:04990d454f45 20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ashleymills 0:04990d454f45 21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
ashleymills 0:04990d454f45 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
ashleymills 0:04990d454f45 23 * SOFTWARE.
ashleymills 0:04990d454f45 24 */
ashleymills 0:04990d454f45 25
ashleymills 0:04990d454f45 26 /**
ashleymills 0:04990d454f45 27 * @file dtls.h
ashleymills 0:04990d454f45 28 * @brief High level DTLS API and visible structures.
ashleymills 0:04990d454f45 29 */
ashleymills 0:04990d454f45 30
ashleymills 0:04990d454f45 31 #ifndef _DTLS_H_
ashleymills 0:04990d454f45 32 #define _DTLS_H_
ashleymills 0:04990d454f45 33
ashleymills 0:04990d454f45 34 #include <stdint.h>
ashleymills 0:04990d454f45 35
ashleymills 0:04990d454f45 36 #include "t_list.h"
ashleymills 0:04990d454f45 37 #include "state.h"
ashleymills 0:04990d454f45 38 #include "peer.h"
ashleymills 0:04990d454f45 39
ashleymills 0:04990d454f45 40 #ifndef WITH_CONTIKI
ashleymills 0:04990d454f45 41 #include "uthash.h"
ashleymills 0:04990d454f45 42 #endif /* WITH_CONTIKI */
ashleymills 0:04990d454f45 43
ashleymills 0:04990d454f45 44 #include "alert.h"
ashleymills 0:04990d454f45 45 #include "crypto.h"
ashleymills 0:04990d454f45 46 #include "hmac.h"
ashleymills 0:04990d454f45 47
ashleymills 0:04990d454f45 48 #include "config.h"
ashleymills 0:04990d454f45 49 #include "global.h"
ashleymills 0:04990d454f45 50 #include "dtls_time.h"
ashleymills 0:04990d454f45 51
ashleymills 0:04990d454f45 52 #ifndef DTLSv12
ashleymills 0:04990d454f45 53 #define DTLS_VERSION 0xfeff /* DTLS v1.1 */
ashleymills 0:04990d454f45 54 #else
ashleymills 0:04990d454f45 55 #define DTLS_VERSION 0xfefd /* DTLS v1.2 */
ashleymills 0:04990d454f45 56 #endif
ashleymills 0:04990d454f45 57
ashleymills 0:04990d454f45 58 /** Known compression methods
ashleymills 0:04990d454f45 59 *
ashleymills 0:04990d454f45 60 * \hideinitializer
ashleymills 0:04990d454f45 61 */
ashleymills 0:04990d454f45 62 #define TLS_COMP_NULL 0x00 /* NULL compression */
ashleymills 0:04990d454f45 63
ashleymills 0:04990d454f45 64 typedef enum {
ashleymills 0:04990d454f45 65 DTLS_KEY_INVALID=0, DTLS_KEY_PSK=1, DTLS_KEY_RPK=2
ashleymills 0:04990d454f45 66 } dtls_key_type_t;
ashleymills 0:04990d454f45 67
ashleymills 0:04990d454f45 68 typedef struct dtls_key_t {
ashleymills 0:04990d454f45 69 dtls_key_type_t type;
ashleymills 0:04990d454f45 70 union {
ashleymills 0:04990d454f45 71 struct dtls_psk_t {
ashleymills 0:04990d454f45 72 unsigned char *id; /**< psk identity */
ashleymills 0:04990d454f45 73 size_t id_length; /**< length of psk identity */
ashleymills 0:04990d454f45 74 unsigned char *key; /**< key data */
ashleymills 0:04990d454f45 75 size_t key_length; /**< length of key */
ashleymills 0:04990d454f45 76 } psk;
ashleymills 0:04990d454f45 77 } key;
ashleymills 0:04990d454f45 78 } dtls_key_t;
ashleymills 0:04990d454f45 79
ashleymills 0:04990d454f45 80 /** Length of the secret that is used for generating Hello Verify cookies. */
ashleymills 0:04990d454f45 81 #define DTLS_COOKIE_SECRET_LENGTH 12
ashleymills 0:04990d454f45 82
ashleymills 0:04990d454f45 83 struct dtls_context_t;
ashleymills 0:04990d454f45 84
ashleymills 0:04990d454f45 85 #ifdef __cplusplus
ashleymills 0:04990d454f45 86 extern "C" {
ashleymills 0:04990d454f45 87 #endif
ashleymills 0:04990d454f45 88
ashleymills 0:04990d454f45 89 /**
ashleymills 0:04990d454f45 90 * This structure contains callback functions used by tinydtls to
ashleymills 0:04990d454f45 91 * communicate with the application. At least the write function must
ashleymills 0:04990d454f45 92 * be provided. It is called by the DTLS state machine to send packets
ashleymills 0:04990d454f45 93 * over the network. The read function is invoked to deliver decrypted
ashleymills 0:04990d454f45 94 * and verfified application data. The third callback is an event
ashleymills 0:04990d454f45 95 * handler function that is called when alert messages are encountered
ashleymills 0:04990d454f45 96 * or events generated by the library have occured.
ashleymills 0:04990d454f45 97 */
ashleymills 0:04990d454f45 98 typedef struct {
ashleymills 0:04990d454f45 99 /**
ashleymills 0:04990d454f45 100 * Called from dtls_handle_message() to send DTLS packets over the
ashleymills 0:04990d454f45 101 * network. The callback function must use the network interface
ashleymills 0:04990d454f45 102 * denoted by session->ifindex to send the data.
ashleymills 0:04990d454f45 103 *
ashleymills 0:04990d454f45 104 * @param ctx The current DTLS context.
ashleymills 0:04990d454f45 105 * @param session The session object, including the address of the
ashleymills 0:04990d454f45 106 * remote peer where the data shall be sent.
ashleymills 0:04990d454f45 107 * @param buf The data to send.
ashleymills 0:04990d454f45 108 * @param len The actual length of @p buf.
ashleymills 0:04990d454f45 109 * @return The callback function must return the number of bytes
ashleymills 0:04990d454f45 110 * that were sent, or a value less than zero to indicate an
ashleymills 0:04990d454f45 111 * error.
ashleymills 0:04990d454f45 112 */
ashleymills 0:04990d454f45 113 int (*write)(struct dtls_context_t *ctx,
ashleymills 0:04990d454f45 114 session_t *session, uint8 *buf, size_t len);
ashleymills 0:04990d454f45 115
ashleymills 0:04990d454f45 116 /**
ashleymills 0:04990d454f45 117 * Called from dtls_handle_message() deliver application data that was
ashleymills 0:04990d454f45 118 * received on the given session. The data is delivered only after
ashleymills 0:04990d454f45 119 * decryption and verification have succeeded.
ashleymills 0:04990d454f45 120 *
ashleymills 0:04990d454f45 121 * @param ctx The current DTLS context.
ashleymills 0:04990d454f45 122 * @param session The session object, including the address of the
ashleymills 0:04990d454f45 123 * data's origin.
ashleymills 0:04990d454f45 124 * @param buf The received data packet.
ashleymills 0:04990d454f45 125 * @param len The actual length of @p buf.
ashleymills 0:04990d454f45 126 * @return ignored
ashleymills 0:04990d454f45 127 */
ashleymills 0:04990d454f45 128 int (*read)(struct dtls_context_t *ctx,
ashleymills 0:04990d454f45 129 session_t *session, uint8 *buf, size_t len);
ashleymills 0:04990d454f45 130
ashleymills 0:04990d454f45 131 /**
ashleymills 0:04990d454f45 132 * The event handler is called when a message from the alert
ashleymills 0:04990d454f45 133 * protocol is received or the state of the DTLS session changes.
ashleymills 0:04990d454f45 134 *
ashleymills 0:04990d454f45 135 * @param ctx The current dtls context.
ashleymills 0:04990d454f45 136 * @param session The session object that was affected.
ashleymills 0:04990d454f45 137 * @param level The alert level or @c 0 when an event ocurred that
ashleymills 0:04990d454f45 138 * is not an alert.
ashleymills 0:04990d454f45 139 * @param code Values less than @c 256 indicate alerts, while
ashleymills 0:04990d454f45 140 * @c 256 or greater indicate internal DTLS session changes.
ashleymills 0:04990d454f45 141 * @return ignored
ashleymills 0:04990d454f45 142 */
ashleymills 0:04990d454f45 143 int (*event)(struct dtls_context_t *ctx, session_t *session,
ashleymills 0:04990d454f45 144 dtls_alert_level_t level, unsigned short code);
ashleymills 0:04990d454f45 145
ashleymills 0:04990d454f45 146 /**
ashleymills 0:04990d454f45 147 * Called during handshake to lookup the key for @p id in @p
ashleymills 0:04990d454f45 148 * session. If found, the key must be stored in @p result and
ashleymills 0:04990d454f45 149 * the return value must be @c 0. If not found, @p result is
ashleymills 0:04990d454f45 150 * undefined and the return value must be less than zero.
ashleymills 0:04990d454f45 151 *
ashleymills 0:04990d454f45 152 * @param ctx The current dtls context.
ashleymills 0:04990d454f45 153 * @param session The session where the key will be used.
ashleymills 0:04990d454f45 154 * @param id The identity of the communicating peer. This value is
ashleymills 0:04990d454f45 155 * @c NULL when the DTLS engine requests the local
ashleymills 0:04990d454f45 156 * id/key pair to use for session setup.
ashleymills 0:04990d454f45 157 * @param id_len The actual length of @p id
ashleymills 0:04990d454f45 158 * @param result Must be set to the key object to use.for the given
ashleymills 0:04990d454f45 159 * session.
ashleymills 0:04990d454f45 160 * @return @c 0 if result is set, or less than zero on error.
ashleymills 0:04990d454f45 161 */
ashleymills 0:04990d454f45 162 int (*get_key)(struct dtls_context_t *ctx,
ashleymills 0:04990d454f45 163 const session_t *session,
ashleymills 0:04990d454f45 164 const unsigned char *id, size_t id_len,
ashleymills 0:04990d454f45 165 const dtls_key_t **result);
ashleymills 0:04990d454f45 166 } dtls_handler_t;
ashleymills 0:04990d454f45 167
ashleymills 0:04990d454f45 168 /** Holds global information of the DTLS engine. */
ashleymills 0:04990d454f45 169 typedef struct dtls_context_t {
ashleymills 0:04990d454f45 170 unsigned char cookie_secret[DTLS_COOKIE_SECRET_LENGTH];
ashleymills 0:04990d454f45 171 clock_time_t cookie_secret_age; /**< the time the secret has been generated */
ashleymills 0:04990d454f45 172
ashleymills 0:04990d454f45 173 #ifndef WITH_CONTIKI
ashleymills 0:04990d454f45 174 dtls_peer_t *peers; /**< peer hash map */
ashleymills 0:04990d454f45 175 #else /* WITH_CONTIKI */
ashleymills 0:04990d454f45 176 LIST_STRUCT(peers);
ashleymills 0:04990d454f45 177
ashleymills 0:04990d454f45 178 struct etimer retransmit_timer; /**< fires when the next packet must be sent */
ashleymills 0:04990d454f45 179 #endif /* WITH_CONTIKI */
ashleymills 0:04990d454f45 180
ashleymills 0:04990d454f45 181 LIST_STRUCT(sendqueue); /**< the packets to send */
ashleymills 0:04990d454f45 182
ashleymills 0:04990d454f45 183 void *app; /**< application-specific data */
ashleymills 0:04990d454f45 184
ashleymills 0:04990d454f45 185 dtls_handler_t *h; /**< callback handlers */
ashleymills 0:04990d454f45 186
ashleymills 0:04990d454f45 187 unsigned char readbuf[DTLS_MAX_BUF];
ashleymills 0:04990d454f45 188 unsigned char sendbuf[DTLS_MAX_BUF];
ashleymills 0:04990d454f45 189 } dtls_context_t;
ashleymills 0:04990d454f45 190
ashleymills 0:04990d454f45 191 /**
ashleymills 0:04990d454f45 192 * This function initializes the tinyDTLS memory management and must
ashleymills 0:04990d454f45 193 * be called first.
ashleymills 0:04990d454f45 194 */
ashleymills 0:04990d454f45 195 void dtls_init();
ashleymills 0:04990d454f45 196
ashleymills 0:04990d454f45 197 /**
ashleymills 0:04990d454f45 198 * Creates a new context object. The storage allocated for the new
ashleymills 0:04990d454f45 199 * object must be released with dtls_free_context(). */
ashleymills 0:04990d454f45 200 dtls_context_t *dtls_new_context(void *app_data);
ashleymills 0:04990d454f45 201
ashleymills 0:04990d454f45 202 /** Releases any storage that has been allocated for \p ctx. */
ashleymills 0:04990d454f45 203 void dtls_free_context(dtls_context_t *ctx);
ashleymills 0:04990d454f45 204
ashleymills 0:04990d454f45 205 #define dtls_set_app_data(CTX,DATA) ((CTX)->app = (DATA))
ashleymills 0:04990d454f45 206 #define dtls_get_app_data(CTX) ((CTX)->app)
ashleymills 0:04990d454f45 207
ashleymills 0:04990d454f45 208 /** Sets the callback handler object for @p ctx to @p h. */
ashleymills 0:04990d454f45 209 static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
ashleymills 0:04990d454f45 210 ctx->h = h;
ashleymills 0:04990d454f45 211 }
ashleymills 0:04990d454f45 212
ashleymills 0:04990d454f45 213 /**
ashleymills 0:04990d454f45 214 * Establishes a DTLS channel with the specified remote peer @p dst.
ashleymills 0:04990d454f45 215 * This function returns @c 0 if that channel already exists, a value
ashleymills 0:04990d454f45 216 * greater than zero when a new ClientHello message was sent, and
ashleymills 0:04990d454f45 217 * a value less than zero on error.
ashleymills 0:04990d454f45 218 *
ashleymills 0:04990d454f45 219 * @param ctx The DTLS context to use.
ashleymills 0:04990d454f45 220 * @param dst The remote party to connect to.
ashleymills 0:04990d454f45 221 * @return A value less than zero on error, greater or equal otherwise.
ashleymills 0:04990d454f45 222 */
ashleymills 0:04990d454f45 223 int dtls_connect(dtls_context_t *ctx, const session_t *dst);
ashleymills 0:04990d454f45 224
ashleymills 0:04990d454f45 225 /**
ashleymills 0:04990d454f45 226 * Establishes a DTLS channel with the specified remote peer.
ashleymills 0:04990d454f45 227 * This function returns @c 0 if that channel already exists, a value
ashleymills 0:04990d454f45 228 * greater than zero when a new ClientHello message was sent, and
ashleymills 0:04990d454f45 229 * a value less than zero on error.
ashleymills 0:04990d454f45 230 *
ashleymills 0:04990d454f45 231 * @param ctx The DTLS context to use.
ashleymills 0:04990d454f45 232 * @param peer The peer object that describes the session.
ashleymills 0:04990d454f45 233 * @return A value less than zero on error, greater or equal otherwise.
ashleymills 0:04990d454f45 234 */
ashleymills 0:04990d454f45 235 int dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer);
ashleymills 0:04990d454f45 236
ashleymills 0:04990d454f45 237 /**
ashleymills 0:04990d454f45 238 * Closes the DTLS connection associated with @p remote. This function
ashleymills 0:04990d454f45 239 * returns zero on success, and a value less than zero on error.
ashleymills 0:04990d454f45 240 */
ashleymills 0:04990d454f45 241 int dtls_close(dtls_context_t *ctx, const session_t *remote);
ashleymills 0:04990d454f45 242
ashleymills 0:04990d454f45 243 /**
ashleymills 0:04990d454f45 244 * Writes the application data given in @p buf to the peer specified
ashleymills 0:04990d454f45 245 * by @p session.
ashleymills 0:04990d454f45 246 *
ashleymills 0:04990d454f45 247 * @param ctx The DTLS context to use.
ashleymills 0:04990d454f45 248 * @param session The remote transport address and local interface.
ashleymills 0:04990d454f45 249 * @param buf The data to write.
ashleymills 0:04990d454f45 250 * @param len The actual length of @p data.
ashleymills 0:04990d454f45 251 *
ashleymills 0:04990d454f45 252 * @return The number of bytes written or @c -1 on error.
ashleymills 0:04990d454f45 253 */
ashleymills 0:04990d454f45 254 int dtls_write(struct dtls_context_t *ctx, session_t *session,
ashleymills 0:04990d454f45 255 uint8 *buf, size_t len);
ashleymills 0:04990d454f45 256
ashleymills 0:04990d454f45 257 /**
ashleymills 0:04990d454f45 258 * Checks sendqueue of given DTLS context object for any outstanding
ashleymills 0:04990d454f45 259 * packets to be transmitted.
ashleymills 0:04990d454f45 260 *
ashleymills 0:04990d454f45 261 * @param context The DTLS context object to use.
ashleymills 0:04990d454f45 262 * @param next If not NULL, @p next is filled with the timestamp
ashleymills 0:04990d454f45 263 * of the next scheduled retransmission, or @c 0 when no packets are
ashleymills 0:04990d454f45 264 * waiting.
ashleymills 0:04990d454f45 265 */
ashleymills 0:04990d454f45 266 void dtls_check_retransmit(dtls_context_t *context, clock_time_t *next);
ashleymills 0:04990d454f45 267
ashleymills 0:04990d454f45 268 #define DTLS_COOKIE_LENGTH 16
ashleymills 0:04990d454f45 269
ashleymills 0:04990d454f45 270 #define DTLS_CT_CHANGE_CIPHER_SPEC 20
ashleymills 0:04990d454f45 271 #define DTLS_CT_ALERT 21
ashleymills 0:04990d454f45 272 #define DTLS_CT_HANDSHAKE 22
ashleymills 0:04990d454f45 273 #define DTLS_CT_APPLICATION_DATA 23
ashleymills 0:04990d454f45 274
ashleymills 0:04990d454f45 275 /** Generic header structure of the DTLS record layer. */
ashleymills 0:04990d454f45 276 typedef struct {
ashleymills 0:04990d454f45 277 uint8 content_type; /**< content type of the included message */
ashleymills 0:04990d454f45 278 uint16 version; /**< Protocol version */
ashleymills 0:04990d454f45 279 uint16 epoch; /**< counter for cipher state changes */
ashleymills 0:04990d454f45 280 uint48 sequence_number; /**< sequence number */
ashleymills 0:04990d454f45 281 uint16 length; /**< length of the following fragment */
ashleymills 0:04990d454f45 282 /* fragment */
ashleymills 0:04990d454f45 283 } dtls_record_header_t;
ashleymills 0:04990d454f45 284
ashleymills 0:04990d454f45 285 /* Handshake types */
ashleymills 0:04990d454f45 286
ashleymills 0:04990d454f45 287 #define DTLS_HT_HELLO_REQUEST 0
ashleymills 0:04990d454f45 288 #define DTLS_HT_CLIENT_HELLO 1
ashleymills 0:04990d454f45 289 #define DTLS_HT_SERVER_HELLO 2
ashleymills 0:04990d454f45 290 #define DTLS_HT_HELLO_VERIFY_REQUEST 3
ashleymills 0:04990d454f45 291 #define DTLS_HT_CERTIFICATE 11
ashleymills 0:04990d454f45 292 #define DTLS_HT_SERVER_KEY_EXCHANGE 12
ashleymills 0:04990d454f45 293 #define DTLS_HT_CERTIFICATE_REQUEST 13
ashleymills 0:04990d454f45 294 #define DTLS_HT_SERVER_HELLO_DONE 14
ashleymills 0:04990d454f45 295 #define DTLS_HT_CERTIFICATE_VERIFY 15
ashleymills 0:04990d454f45 296 #define DTLS_HT_CLIENT_KEY_EXCHANGE 16
ashleymills 0:04990d454f45 297 #define DTLS_HT_FINISHED 20
ashleymills 0:04990d454f45 298
ashleymills 0:04990d454f45 299 /** Header structure for the DTLS handshake protocol. */
ashleymills 0:04990d454f45 300 typedef struct {
ashleymills 0:04990d454f45 301 uint8 msg_type; /**< Type of handshake message (one of DTLS_HT_) */
ashleymills 0:04990d454f45 302 uint24 length; /**< length of this message */
ashleymills 0:04990d454f45 303 uint16 message_seq; /**< Message sequence number */
ashleymills 0:04990d454f45 304 uint24 fragment_offset; /**< Fragment offset. */
ashleymills 0:04990d454f45 305 uint24 fragment_length; /**< Fragment length. */
ashleymills 0:04990d454f45 306 /* body */
ashleymills 0:04990d454f45 307 } dtls_handshake_header_t;
ashleymills 0:04990d454f45 308
ashleymills 0:04990d454f45 309 /** Structure of the Client Hello message. */
ashleymills 0:04990d454f45 310 typedef struct {
ashleymills 0:04990d454f45 311 uint16 version; /**< Client version */
ashleymills 0:04990d454f45 312 uint32 gmt_random; /**< GMT time of the random byte creation */
ashleymills 0:04990d454f45 313 unsigned char random[28]; /**< Client random bytes */
ashleymills 0:04990d454f45 314 /* session id (up to 32 bytes) */
ashleymills 0:04990d454f45 315 /* cookie (up to 32 bytes) */
ashleymills 0:04990d454f45 316 /* cipher suite (2 to 2^16 -1 bytes) */
ashleymills 0:04990d454f45 317 /* compression method */
ashleymills 0:04990d454f45 318 } dtls_client_hello_t;
ashleymills 0:04990d454f45 319
ashleymills 0:04990d454f45 320 /** Structure of the Hello Verify Request. */
ashleymills 0:04990d454f45 321 typedef struct {
ashleymills 0:04990d454f45 322 uint16 version; /**< Server version */
ashleymills 0:04990d454f45 323 uint8 cookie_length; /**< Length of the included cookie */
ashleymills 0:04990d454f45 324 uint8 cookie[]; /**< up to 32 bytes making up the cookie */
ashleymills 0:04990d454f45 325 } dtls_hello_verify_t;
ashleymills 0:04990d454f45 326
ashleymills 0:04990d454f45 327 #if 0
ashleymills 0:04990d454f45 328 /**
ashleymills 0:04990d454f45 329 * Checks a received DTLS record for consistency and eventually decrypt,
ashleymills 0:04990d454f45 330 * verify, decompress and reassemble the contained fragment for
ashleymills 0:04990d454f45 331 * delivery to high-lever clients.
ashleymills 0:04990d454f45 332 *
ashleymills 0:04990d454f45 333 * \param state The DTLS record state for the current session.
ashleymills 0:04990d454f45 334 * \param
ashleymills 0:04990d454f45 335 */
ashleymills 0:04990d454f45 336 int dtls_record_read(dtls_state_t *state, uint8 *msg, int msglen);
ashleymills 0:04990d454f45 337 #endif
ashleymills 0:04990d454f45 338
ashleymills 0:04990d454f45 339 /**
ashleymills 0:04990d454f45 340 * Retrieves a pointer to the cookie contained in a Client Hello message.
ashleymills 0:04990d454f45 341 *
ashleymills 0:04990d454f45 342 * \param hello_msg Points to the received Client Hello message
ashleymills 0:04990d454f45 343 * \param msglen Length of \p hello_msg
ashleymills 0:04990d454f45 344 * \param cookie Is set to the beginning of the cookie in the message if
ashleymills 0:04990d454f45 345 * found. Undefined if this function returns \c 0.
ashleymills 0:04990d454f45 346 * \return \c 0 if no cookie was found, < 0 on error. On success, the return
ashleymills 0:04990d454f45 347 * value reflects the cookie's length.
ashleymills 0:04990d454f45 348 */
ashleymills 0:04990d454f45 349 int dtls_get_cookie(uint8 *hello_msg, int msglen, uint8 **cookie);
ashleymills 0:04990d454f45 350
ashleymills 0:04990d454f45 351 /**
ashleymills 0:04990d454f45 352 * Handles incoming data as DTLS message from given peer.
ashleymills 0:04990d454f45 353 *
ashleymills 0:04990d454f45 354 * @param ctx The dtls context to use.
ashleymills 0:04990d454f45 355 * @param session The current session
ashleymills 0:04990d454f45 356 * @param msg The received data
ashleymills 0:04990d454f45 357 * @param msglen The actual length of @p msg.
ashleymills 0:04990d454f45 358 * @return A value less than zero on error, zero on success.
ashleymills 0:04990d454f45 359 */
ashleymills 0:04990d454f45 360 int dtls_handle_message(dtls_context_t *ctx, session_t *session,
ashleymills 0:04990d454f45 361 uint8 *msg, int msglen);
ashleymills 0:04990d454f45 362
ashleymills 0:04990d454f45 363 /**
ashleymills 0:04990d454f45 364 * Check if @p session is associated with a peer object in @p context.
ashleymills 0:04990d454f45 365 * This function returns a pointer to the peer if found, NULL otherwise.
ashleymills 0:04990d454f45 366 *
ashleymills 0:04990d454f45 367 * @param context The DTLS context to search.
ashleymills 0:04990d454f45 368 * @param session The remote address and local interface
ashleymills 0:04990d454f45 369 * @return A pointer to the peer associated with @p session or NULL if
ashleymills 0:04990d454f45 370 * none exists.
ashleymills 0:04990d454f45 371 */
ashleymills 0:04990d454f45 372 dtls_peer_t *dtls_get_peer(const dtls_context_t *context,
ashleymills 0:04990d454f45 373 const session_t *session);
ashleymills 0:04990d454f45 374
ashleymills 0:04990d454f45 375
ashleymills 0:04990d454f45 376 #endif /* _DTLS_H_ */
ashleymills 0:04990d454f45 377
ashleymills 0:04990d454f45 378 /**
ashleymills 0:04990d454f45 379 * @mainpage
ashleymills 0:04990d454f45 380 *
ashleymills 0:04990d454f45 381 * @author Olaf Bergmann, TZI Uni Bremen
ashleymills 0:04990d454f45 382 *
ashleymills 0:04990d454f45 383 * This library provides a very simple datagram server with DTLS
ashleymills 0:04990d454f45 384 * support. It is designed to support session multiplexing in
ashleymills 0:04990d454f45 385 * single-threaded applications and thus targets specifically on
ashleymills 0:04990d454f45 386 * embedded systems.
ashleymills 0:04990d454f45 387 *
ashleymills 0:04990d454f45 388 * @section license License
ashleymills 0:04990d454f45 389 *
ashleymills 0:04990d454f45 390 * This software is under the <a
ashleymills 0:04990d454f45 391 * href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>.
ashleymills 0:04990d454f45 392 *
ashleymills 0:04990d454f45 393 * @subsection uthash UTHash
ashleymills 0:04990d454f45 394 *
ashleymills 0:04990d454f45 395 * This library uses <a href="http://uthash.sourceforge.net/">uthash</a> to manage
ashleymills 0:04990d454f45 396 * its peers (not used for Contiki). @b uthash uses the <b>BSD revised license</b>, see
ashleymills 0:04990d454f45 397 * <a href="http://uthash.sourceforge.net/license.html">http://uthash.sourceforge.net/license.html</a>.
ashleymills 0:04990d454f45 398 *
ashleymills 0:04990d454f45 399 * @subsection sha256 Aaron D. Gifford's SHA256 Implementation
ashleymills 0:04990d454f45 400 *
ashleymills 0:04990d454f45 401 * tinyDTLS provides HMAC-SHA256 with BSD-licensed code from Aaron D. Gifford,
ashleymills 0:04990d454f45 402 * see <a href="http://www.aarongifford.com/">www.aarongifford.com</a>.
ashleymills 0:04990d454f45 403 *
ashleymills 0:04990d454f45 404 * @subsection aes Rijndael Implementation From OpenBSD
ashleymills 0:04990d454f45 405 *
ashleymills 0:04990d454f45 406 * The AES implementation is taken from rijndael.{c,h} contained in the crypto
ashleymills 0:04990d454f45 407 * sub-system of the OpenBSD operating system. It is copyright by Vincent Rijmen, *
ashleymills 0:04990d454f45 408 * Antoon Bosselaers and Paulo Barreto. See <a
ashleymills 0:04990d454f45 409 * href="http://www.openbsd.org/cgi-bin/cvsweb/src/sys/crypto/rijndael.c">rijndael.c</a>
ashleymills 0:04990d454f45 410 * for License info.
ashleymills 0:04990d454f45 411 *
ashleymills 0:04990d454f45 412 * @section download Getting the Files
ashleymills 0:04990d454f45 413 *
ashleymills 0:04990d454f45 414 * You can get the sources either from the <a
ashleymills 0:04990d454f45 415 * href="http://sourceforge.net/projects/tinydtls/files">downloads</a> section or
ashleymills 0:04990d454f45 416 * through git from the <a
ashleymills 0:04990d454f45 417 * href="http://sourceforge.net/projects/tinydtls/develop">project develop page</a>.
ashleymills 0:04990d454f45 418 *
ashleymills 0:04990d454f45 419 * @section config Configuration
ashleymills 0:04990d454f45 420 *
ashleymills 0:04990d454f45 421 * Use @c configure to set up everything for a successful build. For Contiki, use the
ashleymills 0:04990d454f45 422 * option @c --with-contiki.
ashleymills 0:04990d454f45 423 *
ashleymills 0:04990d454f45 424 * @section build Building
ashleymills 0:04990d454f45 425 *
ashleymills 0:04990d454f45 426 * After configuration, just type
ashleymills 0:04990d454f45 427 * @code
ashleymills 0:04990d454f45 428 make
ashleymills 0:04990d454f45 429 * @endcode
ashleymills 0:04990d454f45 430 * optionally followed by
ashleymills 0:04990d454f45 431 * @code
ashleymills 0:04990d454f45 432 make install
ashleymills 0:04990d454f45 433 * @endcode
ashleymills 0:04990d454f45 434 * The Contiki version is integrated with the Contiki build system, hence you do not
ashleymills 0:04990d454f45 435 * need to invoke @c make explicitely. Just add @c tinydtls to the variable @c APPS
ashleymills 0:04990d454f45 436 * in your @c Makefile.
ashleymills 0:04990d454f45 437 *
ashleymills 0:04990d454f45 438 * @addtogroup dtls_usage DTLS Usage
ashleymills 0:04990d454f45 439 *
ashleymills 0:04990d454f45 440 * @section dtls_server_example DTLS Server Example
ashleymills 0:04990d454f45 441 *
ashleymills 0:04990d454f45 442 * This section shows how to use the DTLS library functions to setup a
ashleymills 0:04990d454f45 443 * simple secure UDP echo server. The application is responsible for the
ashleymills 0:04990d454f45 444 * entire network communication and thus will look like a usual UDP
ashleymills 0:04990d454f45 445 * server with socket creation and binding and a typical select-loop as
ashleymills 0:04990d454f45 446 * shown below. The minimum configuration required for DTLS is the
ashleymills 0:04990d454f45 447 * creation of the dtls_context_t using dtls_new_context(), and a callback
ashleymills 0:04990d454f45 448 * for sending data. Received packets are read by the application and
ashleymills 0:04990d454f45 449 * passed to dtls_handle_message() as shown in @ref dtls_read_cb.
ashleymills 0:04990d454f45 450 * For any useful communication to happen, read and write call backs
ashleymills 0:04990d454f45 451 * and a key management function should be registered as well.
ashleymills 0:04990d454f45 452 *
ashleymills 0:04990d454f45 453 * @code
ashleymills 0:04990d454f45 454 dtls_context_t *the_context = NULL;
ashleymills 0:04990d454f45 455 int fd, result;
ashleymills 0:04990d454f45 456
ashleymills 0:04990d454f45 457 static dtls_handler_t cb = {
ashleymills 0:04990d454f45 458 .write = send_to_peer,
ashleymills 0:04990d454f45 459 .read = read_from_peer,
ashleymills 0:04990d454f45 460 .event = NULL,
ashleymills 0:04990d454f45 461 .get_key = get_key
ashleymills 0:04990d454f45 462 };
ashleymills 0:04990d454f45 463
ashleymills 0:04990d454f45 464 fd = socket(...);
ashleymills 0:04990d454f45 465 if (fd < 0 || bind(fd, ...) < 0)
ashleymills 0:04990d454f45 466 exit(-1);
ashleymills 0:04990d454f45 467
ashleymills 0:04990d454f45 468 the_context = dtls_new_context(&fd);
ashleymills 0:04990d454f45 469 dtls_set_handler(the_context, &cb);
ashleymills 0:04990d454f45 470
ashleymills 0:04990d454f45 471 while (1) {
ashleymills 0:04990d454f45 472 ...initialize fd_set rfds and timeout ...
ashleymills 0:04990d454f45 473 result = select(fd+1, &rfds, NULL, 0, NULL);
ashleymills 0:04990d454f45 474
ashleymills 0:04990d454f45 475 if (FD_ISSET(fd, &rfds))
ashleymills 0:04990d454f45 476 dtls_handle_read(the_context);
ashleymills 0:04990d454f45 477 }
ashleymills 0:04990d454f45 478
ashleymills 0:04990d454f45 479 dtls_free_context(the_context);
ashleymills 0:04990d454f45 480 * @endcode
ashleymills 0:04990d454f45 481 *
ashleymills 0:04990d454f45 482 * @subsection dtls_read_cb The Read Callback
ashleymills 0:04990d454f45 483 *
ashleymills 0:04990d454f45 484 * The DTLS library expects received raw data to be passed to
ashleymills 0:04990d454f45 485 * dtls_handle_message(). The application is responsible for
ashleymills 0:04990d454f45 486 * filling a session_t structure with the address data of the
ashleymills 0:04990d454f45 487 * remote peer as illustrated by the following example:
ashleymills 0:04990d454f45 488 *
ashleymills 0:04990d454f45 489 * @code
ashleymills 0:04990d454f45 490 int dtls_handle_read(struct dtls_context_t *ctx) {
ashleymills 0:04990d454f45 491 int *fd;
ashleymills 0:04990d454f45 492 session_t session;
ashleymills 0:04990d454f45 493 static uint8 buf[DTLS_MAX_BUF];
ashleymills 0:04990d454f45 494 int len;
ashleymills 0:04990d454f45 495
ashleymills 0:04990d454f45 496 fd = dtls_get_app_data(ctx);
ashleymills 0:04990d454f45 497
ashleymills 0:04990d454f45 498 assert(fd);
ashleymills 0:04990d454f45 499
ashleymills 0:04990d454f45 500 session.size = sizeof(session.addr);
ashleymills 0:04990d454f45 501 len = recvfrom(*fd, buf, sizeof(buf), 0, &session.addr.sa, &session.size);
ashleymills 0:04990d454f45 502
ashleymills 0:04990d454f45 503 return len < 0 ? len : dtls_handle_message(ctx, &session, buf, len);
ashleymills 0:04990d454f45 504 }
ashleymills 0:04990d454f45 505 * @endcode
ashleymills 0:04990d454f45 506 *
ashleymills 0:04990d454f45 507 * Once a new DTLS session was established and DTLS ApplicationData has been
ashleymills 0:04990d454f45 508 * received, the DTLS server invokes the read callback with the MAC-verified
ashleymills 0:04990d454f45 509 * cleartext data as its argument. A read callback for a simple echo server
ashleymills 0:04990d454f45 510 * could look like this:
ashleymills 0:04990d454f45 511 * @code
ashleymills 0:04990d454f45 512 int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
ashleymills 0:04990d454f45 513 return dtls_write(ctx, session, data, len);
ashleymills 0:04990d454f45 514 }
ashleymills 0:04990d454f45 515 * @endcode
ashleymills 0:04990d454f45 516 *
ashleymills 0:04990d454f45 517 * @subsection dtls_send_cb The Send Callback
ashleymills 0:04990d454f45 518 *
ashleymills 0:04990d454f45 519 * The callback function send_to_peer() is called whenever data must be
ashleymills 0:04990d454f45 520 * sent over the network. Here, the sendto() system call is used to
ashleymills 0:04990d454f45 521 * transmit data within the given session. The socket descriptor required
ashleymills 0:04990d454f45 522 * by sendto() has been registered as application data when the DTLS context
ashleymills 0:04990d454f45 523 * was created with dtls_new_context().
ashleymills 0:04990d454f45 524 * Note that it is on the application to buffer the data when it cannot be
ashleymills 0:04990d454f45 525 * sent at the time this callback is invoked. The following example thus
ashleymills 0:04990d454f45 526 * is incomplete as it would have to deal with EAGAIN somehow.
ashleymills 0:04990d454f45 527 * @code
ashleymills 0:04990d454f45 528 int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
ashleymills 0:04990d454f45 529 int fd = *(int *)dtls_get_app_data(ctx);
ashleymills 0:04990d454f45 530 return sendto(fd, data, len, MSG_DONTWAIT, &session->addr.sa, session->size);
ashleymills 0:04990d454f45 531 }
ashleymills 0:04990d454f45 532 * @endcode
ashleymills 0:04990d454f45 533 *
ashleymills 0:04990d454f45 534 * @subsection dtls_get_key The Key Storage
ashleymills 0:04990d454f45 535 *
ashleymills 0:04990d454f45 536 * When a new DTLS session is created, the library must ask the application
ashleymills 0:04990d454f45 537 * for keying material. To do so, it invokes the registered call-back function
ashleymills 0:04990d454f45 538 * get_key() with the current context and session information as parameter.
ashleymills 0:04990d454f45 539 * When the function is called with the @p id parameter set, the result must
ashleymills 0:04990d454f45 540 * point to a dtls_key_t structure for the given identity. When @p id is
ashleymills 0:04990d454f45 541 * @c NULL, the function must pick a suitable identity and return a pointer to
ashleymills 0:04990d454f45 542 * the corresponding dtls_key_t structure. The following example shows a
ashleymills 0:04990d454f45 543 * simple key storage for a pre-shared key for @c Client_identity:
ashleymills 0:04990d454f45 544 *
ashleymills 0:04990d454f45 545 * @code
ashleymills 0:04990d454f45 546 int get_key(struct dtls_context_t *ctx,
ashleymills 0:04990d454f45 547 const session_t *session,
ashleymills 0:04990d454f45 548 const unsigned char *id, size_t id_len,
ashleymills 0:04990d454f45 549 const dtls_key_t **result) {
ashleymills 0:04990d454f45 550
ashleymills 0:04990d454f45 551 static const dtls_key_t psk = {
ashleymills 0:04990d454f45 552 .type = DTLS_KEY_PSK,
ashleymills 0:04990d454f45 553 .key.psk.id = (unsigned char *)"my identity",
ashleymills 0:04990d454f45 554 .key.psk.id_length = 11,
ashleymills 0:04990d454f45 555 .key.psk.key = (unsigned char *)"secret",
ashleymills 0:04990d454f45 556 .key.psk.key_length = 6
ashleymills 0:04990d454f45 557 };
ashleymills 0:04990d454f45 558
ashleymills 0:04990d454f45 559 *result = &psk;
ashleymills 0:04990d454f45 560 return 0;
ashleymills 0:04990d454f45 561 }
ashleymills 0:04990d454f45 562 * @endcode
ashleymills 0:04990d454f45 563 *
ashleymills 0:04990d454f45 564 * @subsection dtls_events The Event Notifier
ashleymills 0:04990d454f45 565 *
ashleymills 0:04990d454f45 566 * Applications that want to be notified whenever the status of a DTLS session
ashleymills 0:04990d454f45 567 * has changed can register an event handling function with the field @c event
ashleymills 0:04990d454f45 568 * in the dtls_handler_t structure (see \ref dtls_server_example). The call-back
ashleymills 0:04990d454f45 569 * function is called for alert messages and internal state changes. For alert
ashleymills 0:04990d454f45 570 * messages, the argument @p level will be set to a value greate than zero, and
ashleymills 0:04990d454f45 571 * @p code will indicate the notification code. For internal events, @p level
ashleymills 0:04990d454f45 572 * is @c 0, and @p code a value greater than @c 255.
ashleymills 0:04990d454f45 573 *
ashleymills 0:04990d454f45 574 * Currently, the only defined internal event is @c DTLS_EVENT_CONNECTED. It
ashleymills 0:04990d454f45 575 * indicates successful establishment of a new DTLS channel.
ashleymills 0:04990d454f45 576 *
ashleymills 0:04990d454f45 577 * @code
ashleymills 0:04990d454f45 578 int handle_event(struct dtls_context_t *ctx, session_t *session,
ashleymills 0:04990d454f45 579 dtls_alert_level_t level, unsigned short code) {
ashleymills 0:04990d454f45 580 ... do something with event ...
ashleymills 0:04990d454f45 581 return 0;
ashleymills 0:04990d454f45 582 }
ashleymills 0:04990d454f45 583 * @endcode
ashleymills 0:04990d454f45 584 *
ashleymills 0:04990d454f45 585 * @section dtls_client_example DTLS Client Example
ashleymills 0:04990d454f45 586 *
ashleymills 0:04990d454f45 587 * A DTLS client is constructed like a server but needs to actively setup
ashleymills 0:04990d454f45 588 * a new session by calling dtls_connect() at some point. As this function
ashleymills 0:04990d454f45 589 * usually returns before the new DTLS channel is established, the application
ashleymills 0:04990d454f45 590 * must register an event handler and wait for @c DTLS_EVENT_CONNECT before
ashleymills 0:04990d454f45 591 * it can send data over the DTLS channel.
ashleymills 0:04990d454f45 592 *
ashleymills 0:04990d454f45 593 */
ashleymills 0:04990d454f45 594
ashleymills 0:04990d454f45 595 /**
ashleymills 0:04990d454f45 596 * @addtogroup contiki Contiki
ashleymills 0:04990d454f45 597 *
ashleymills 0:04990d454f45 598 * To use tinyDTLS as Contiki application, place the source code in the directory
ashleymills 0:04990d454f45 599 * @c apps/tinydtls in the Contiki source tree and invoke configure with the option
ashleymills 0:04990d454f45 600 * @c --with-contiki. This will create the tinydtls Makefile and config.h from the
ashleymills 0:04990d454f45 601 * templates @c Makefile.contiki and @c config.h.contiki instead of the usual
ashleymills 0:04990d454f45 602 * templates ending in @c .in.
ashleymills 0:04990d454f45 603 *
ashleymills 0:04990d454f45 604 * Then, create a Contiki project with @c APPS += tinydtls in its Makefile. A sample
ashleymills 0:04990d454f45 605 * server could look like this (with read_from_peer() and get_key() as shown above).
ashleymills 0:04990d454f45 606 *
ashleymills 0:04990d454f45 607 * @code
ashleymills 0:04990d454f45 608 #include "contiki.h"
ashleymills 0:04990d454f45 609
ashleymills 0:04990d454f45 610 #include "config.h"
ashleymills 0:04990d454f45 611 #include "dtls.h"
ashleymills 0:04990d454f45 612
ashleymills 0:04990d454f45 613 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
ashleymills 0:04990d454f45 614 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
ashleymills 0:04990d454f45 615
ashleymills 0:04990d454f45 616 int send_to_peer(struct dtls_context_t *, session_t *, uint8 *, size_t);
ashleymills 0:04990d454f45 617
ashleymills 0:04990d454f45 618 static struct uip_udp_conn *server_conn;
ashleymills 0:04990d454f45 619 static dtls_context_t *dtls_context;
ashleymills 0:04990d454f45 620
ashleymills 0:04990d454f45 621 static dtls_handler_t cb = {
ashleymills 0:04990d454f45 622 .write = send_to_peer,
ashleymills 0:04990d454f45 623 .read = read_from_peer,
ashleymills 0:04990d454f45 624 .event = NULL,
ashleymills 0:04990d454f45 625 .get_key = get_key
ashleymills 0:04990d454f45 626 };
ashleymills 0:04990d454f45 627
ashleymills 0:04990d454f45 628 PROCESS(server_process, "DTLS server process");
ashleymills 0:04990d454f45 629 AUTOSTART_PROCESSES(&server_process);
ashleymills 0:04990d454f45 630
ashleymills 0:04990d454f45 631 PROCESS_THREAD(server_process, ev, data)
ashleymills 0:04990d454f45 632 {
ashleymills 0:04990d454f45 633 PROCESS_BEGIN();
ashleymills 0:04990d454f45 634
ashleymills 0:04990d454f45 635 dtls_init();
ashleymills 0:04990d454f45 636
ashleymills 0:04990d454f45 637 server_conn = udp_new(NULL, 0, NULL);
ashleymills 0:04990d454f45 638 udp_bind(server_conn, UIP_HTONS(5684));
ashleymills 0:04990d454f45 639
ashleymills 0:04990d454f45 640 dtls_context = dtls_new_context(server_conn);
ashleymills 0:04990d454f45 641 if (!dtls_context) {
ashleymills 0:04990d454f45 642 dsrv_log(LOG_EMERG, "cannot create context\n");
ashleymills 0:04990d454f45 643 PROCESS_EXIT();
ashleymills 0:04990d454f45 644 }
ashleymills 0:04990d454f45 645
ashleymills 0:04990d454f45 646 dtls_set_handler(dtls_context, &cb);
ashleymills 0:04990d454f45 647
ashleymills 0:04990d454f45 648 while(1) {
ashleymills 0:04990d454f45 649 PROCESS_WAIT_EVENT();
ashleymills 0:04990d454f45 650 if(ev == tcpip_event && uip_newdata()) {
ashleymills 0:04990d454f45 651 session_t session;
ashleymills 0:04990d454f45 652
ashleymills 0:04990d454f45 653 uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr);
ashleymills 0:04990d454f45 654 session.port = UIP_UDP_BUF->srcport;
ashleymills 0:04990d454f45 655 session.size = sizeof(session.addr) + sizeof(session.port);
ashleymills 0:04990d454f45 656
ashleymills 0:04990d454f45 657 dtls_handle_message(ctx, &session, uip_appdata, uip_datalen());
ashleymills 0:04990d454f45 658 }
ashleymills 0:04990d454f45 659 }
ashleymills 0:04990d454f45 660
ashleymills 0:04990d454f45 661 PROCESS_END();
ashleymills 0:04990d454f45 662 }
ashleymills 0:04990d454f45 663
ashleymills 0:04990d454f45 664 int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
ashleymills 0:04990d454f45 665 struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx);
ashleymills 0:04990d454f45 666
ashleymills 0:04990d454f45 667 uip_ipaddr_copy(&conn->ripaddr, &session->addr);
ashleymills 0:04990d454f45 668 conn->rport = session->port;
ashleymills 0:04990d454f45 669
ashleymills 0:04990d454f45 670 uip_udp_packet_send(conn, data, len);
ashleymills 0:04990d454f45 671
ashleymills 0:04990d454f45 672 memset(&conn->ripaddr, 0, sizeof(server_conn->ripaddr));
ashleymills 0:04990d454f45 673 memset(&conn->rport, 0, sizeof(conn->rport));
ashleymills 0:04990d454f45 674
ashleymills 0:04990d454f45 675 return len;
ashleymills 0:04990d454f45 676 }
ashleymills 0:04990d454f45 677 * @endcode
ashleymills 0:04990d454f45 678 */
ashleymills 0:04990d454f45 679
ashleymills 0:04990d454f45 680 #ifdef __cplusplus
ashleymills 0:04990d454f45 681 }
ashleymills 0:04990d454f45 682 #endif