Merge branch 'master' into windows-port
[platform/upstream/iotivity.git] / extlibs / tinydtls / tests / dtls-server.c
1
2 /* This is needed for apple */
3 #define __APPLE_USE_RFC_3542
4
5 #include <assert.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <errno.h>
9 #ifdef HAVE_UNISTD_H
10 #include <unistd.h>
11 #endif
12 #ifdef HAVE_NETINET_IN_H
13 #include <netinet/in.h>
14 #endif
15 #include <sys/types.h>
16 #ifdef HAVE_SYS_SOCKET_H
17 #include <sys/socket.h>
18 #endif
19 #ifdef HAVE_SYS_TIME_H
20 #include <sys/time.h>
21 #endif
22 #ifdef HAVE_NETDB_H
23 #include <netdb.h>
24 #endif
25 #include <signal.h>
26 #include <getopt.h>
27 #include "platform_features.h"
28
29 #include "tinydtls.h"
30 #include "dtls.h"
31 #include "debug.h"
32
33 #ifdef DTLS_X509
34 #define DTLS_PRIVATE_KEY_SIZE        (32)
35 #define DTLS_PUBLIC_KEY_SIZE         (64)
36 #endif
37
38 #define DEFAULT_PORT 20220
39
40 /**
41  * @struct byte_array
42  *
43  * General purpose byte array structure.
44  *
45  * Contains pointer to array of bytes and it's length.
46  */
47
48 typedef struct
49 {
50     uint8_t *data;    /**< Pointer to the byte array */
51     size_t len;      /**< Data size */
52 } byte_array;
53
54
55 /**@def BYTE_ARRAY_INITIALIZER
56  *
57  * Initializes of existing byte array pointer to \a NULL.
58  */
59 #undef BYTE_ARRAY_INITIALIZER
60 #define BYTE_ARRAY_INITIALIZER {NULL, 0}
61
62 #ifdef DTLS_X509
63 #define X509_OPTIONS         "x:r:u:"
64 #define SERVER_CRT_LEN 295
65 static const unsigned char g_server_certificate[SERVER_CRT_LEN] = {
66         0x00, 0x01, 0x24,
67         0x30, 0x82, 0x01, 0x20, 0x30, 0x81, 0xc4, 0xa0,
68         0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x37,
69         0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
70         0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x17,
71         0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04,
72         0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c,
73         0x20, 0x49, 0x53, 0x53, 0x55, 0x45, 0x52, 0x30,
74         0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x31, 0x30,
75         0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
76         0x17, 0x0d, 0x34, 0x39, 0x30, 0x31, 0x30, 0x31,
77         0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
78         0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55,
79         0x04, 0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61,
80         0x6c, 0x20, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52,
81         0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
82         0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
83         0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
84         0x42, 0x00, 0x04, 0x07, 0x88, 0x10, 0xdc, 0x62,
85         0xd7, 0xe6, 0x9b, 0x7c, 0xad, 0x6e, 0x78, 0xb0,
86         0x5f, 0x9a, 0x00, 0x11, 0x74, 0x2c, 0x8b, 0xaf,
87         0x09, 0x65, 0x7c, 0x86, 0x8e, 0x55, 0xcb, 0x39,
88         0x55, 0x72, 0xc6, 0x65, 0x71, 0xcd, 0x03, 0xdc,
89         0x2a, 0x4f, 0x46, 0x5b, 0x14, 0xc8, 0x27, 0x74,
90         0xab, 0xf4, 0x1f, 0xc1, 0x35, 0x0d, 0x42, 0xbc,
91         0xc2, 0x9f, 0xb5, 0xc1, 0x79, 0xb6, 0x8b, 0xca,
92         0xdb, 0xff, 0x82, 0x30, 0x0c, 0x06, 0x08, 0x2a,
93         0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05,
94         0x00, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21,
95         0x00, 0xb1, 0x81, 0x81, 0x92, 0x0e, 0x76, 0x7c,
96         0xeb, 0xf5, 0x37, 0xde, 0x27, 0xc4, 0x01, 0xc8,
97         0x96, 0xc3, 0xe5, 0x9f, 0x47, 0x7e, 0x25, 0x92,
98         0xa4, 0xba, 0x22, 0x25, 0xa3, 0x81, 0x19, 0xcf,
99         0x0d, 0x02, 0x21, 0x00, 0xca, 0x92, 0xbe, 0x79,
100         0xc7, 0x82, 0x84, 0x64, 0xc4, 0xc4, 0xf4, 0x3d,
101         0x69, 0x79, 0x68, 0xc0, 0xf1, 0xba, 0xaf, 0x6c,
102         0xbb, 0xdd, 0x54, 0x7d, 0x07, 0xe7, 0x53, 0x3b,
103         0xc3, 0x1b, 0x87, 0x04};
104
105 //default server's key pair
106 static const unsigned char x509_priv_key[] = {
107         0xaa, 0xa3, 0x46, 0xf1, 0x3c, 0x56, 0x5d, 0x08,
108         0x5e, 0x59, 0xba, 0x7f, 0xd2, 0x21, 0x62, 0xc6,
109         0xcc, 0x5d, 0xfa, 0x3f, 0xb5, 0x25, 0xa9, 0x89,
110         0x4f, 0x32, 0xe8, 0x2a, 0xe0, 0xee, 0x9b, 0x4c};
111
112 static const unsigned char x509_pub_key_x[] = {
113         0x07, 0x88, 0x10, 0xdc, 0x62, 0xd7, 0xe6, 0x9b,
114         0x7c, 0xad, 0x6e, 0x78, 0xb0, 0x5f, 0x9a, 0x00,
115         0x11, 0x74, 0x2c, 0x8b, 0xaf, 0x09, 0x65, 0x7c,
116         0x86, 0x8e, 0x55, 0xcb, 0x39, 0x55, 0x72, 0xc6};
117
118 static const unsigned char x509_pub_key_y[] = {
119         0x65, 0x71, 0xcd, 0x03, 0xdc, 0x2a, 0x4f, 0x46,
120         0x5b, 0x14, 0xc8, 0x27, 0x74, 0xab, 0xf4, 0x1f,
121         0xc1, 0x35, 0x0d, 0x42, 0xbc, 0xc2, 0x9f, 0xb5,
122         0xc1, 0x79, 0xb6, 0x8b, 0xca, 0xdb, 0xff, 0x82};
123
124 //default CA pub key
125 static const unsigned char x509_ca_pub_x[] = {
126         0x57, 0x94, 0x7f, 0x98, 0x7a, 0x02, 0x67, 0x09,
127         0x25, 0xc1, 0xcb, 0x5a, 0xf5, 0x46, 0xfb, 0xad,
128         0xf7, 0x68, 0x94, 0x8c, 0xa7, 0xe3, 0xf0, 0x5b,
129         0xc3, 0x6b, 0x5c, 0x9b, 0xd3, 0x7d, 0x74, 0x12
130 };
131
132 static const unsigned char x509_ca_pub_y[] = {
133         0xce, 0x68, 0xbc, 0x55, 0xf5, 0xf8, 0x1b, 0x3d,
134         0xef, 0xed, 0x1f, 0x2b, 0xd2, 0x69, 0x5d, 0xcf,
135         0x79, 0x16, 0xa6, 0xbd, 0x97, 0x96, 0x27, 0x60,
136         0x5d, 0xd1, 0xb7, 0x93, 0xa2, 0x4a, 0x62, 0x4d
137 };
138
139 static const unsigned char client_pub_key_x[] = {
140         0xe3, 0xd1, 0x67, 0x1e, 0xdc, 0x46, 0xf4, 0x19,
141         0x50, 0x15, 0x2e, 0x3a, 0x2f, 0xd8, 0x68, 0x6b,
142         0x37, 0x32, 0x84, 0x9e, 0x83, 0x81, 0xbf, 0x25,
143         0x5d, 0xbb, 0x18, 0x07, 0x3c, 0xbd, 0xf3, 0xab};
144
145 static const unsigned char client_pub_key_y[] = {
146         0xd3, 0xbf, 0x53, 0x59, 0xc9, 0x1e, 0xce, 0x5b,
147         0x39, 0x6a, 0xe5, 0x60, 0xf3, 0x70, 0xdb, 0x66,
148         0xb6, 0x80, 0xcb, 0x65, 0x0b, 0x35, 0x2a, 0x62,
149         0x44, 0x89, 0x63, 0x64, 0x6f, 0x6f, 0xbd, 0xf0};
150
151 static unsigned char x509_server_cert[DTLS_MAX_CERT_SIZE];
152 static size_t x509_server_cert_len = 0;
153 static unsigned char x509_server_priv[DTLS_PRIVATE_KEY_SIZE+1];
154 static size_t x509_server_priv_is_set = 0;
155 static unsigned char x509_ca_pub[DTLS_PUBLIC_KEY_SIZE+1];
156 static size_t x509_ca_pub_is_set = 0;
157
158 static int x509_info_from_file = 0;
159 #endif /*DTLS_X509*/
160 #ifdef DTLS_ECC
161 static const unsigned char ecdsa_priv_key[] = {
162                         0xD9, 0xE2, 0x70, 0x7A, 0x72, 0xDA, 0x6A, 0x05,
163                         0x04, 0x99, 0x5C, 0x86, 0xED, 0xDB, 0xE3, 0xEF,
164                         0xC7, 0xF1, 0xCD, 0x74, 0x83, 0x8F, 0x75, 0x70,
165                         0xC8, 0x07, 0x2D, 0x0A, 0x76, 0x26, 0x1B, 0xD4};
166
167 static const unsigned char ecdsa_pub_key_x[] = {
168                         0xD0, 0x55, 0xEE, 0x14, 0x08, 0x4D, 0x6E, 0x06,
169                         0x15, 0x59, 0x9D, 0xB5, 0x83, 0x91, 0x3E, 0x4A,
170                         0x3E, 0x45, 0x26, 0xA2, 0x70, 0x4D, 0x61, 0xF2,
171                         0x7A, 0x4C, 0xCF, 0xBA, 0x97, 0x58, 0xEF, 0x9A};
172
173 static const unsigned char ecdsa_pub_key_y[] = {
174                         0xB4, 0x18, 0xB6, 0x4A, 0xFE, 0x80, 0x30, 0xDA,
175                         0x1D, 0xDC, 0xF4, 0xF4, 0x2E, 0x2F, 0x26, 0x31,
176                         0xD0, 0x43, 0xB1, 0xFB, 0x03, 0xE2, 0x2F, 0x4D,
177                         0x17, 0xDE, 0x43, 0xF9, 0xF9, 0xAD, 0xEE, 0x70};
178 #endif /*DTLS_ECC*/
179 #if 0
180 /* SIGINT handler: set quit to 1 for graceful termination */
181 void
182 handle_sigint(int signum) {
183   dsrv_stop(dsrv_get_context());
184 }
185 #endif
186
187 #ifdef DTLS_X509
188 ssize_t
189 read_from_file(char *arg, unsigned char *buf, size_t max_buf_len) {
190   FILE *f;
191   ssize_t result = 0;
192
193   f = fopen(arg, "r");
194   if (f == NULL)
195     return -1;
196
197   while (!feof(f)) {
198     size_t bytes_read;
199     bytes_read = fread(buf, 1, max_buf_len, f);
200     if (ferror(f)) {
201       result = -1;
202       break;
203     }
204
205     buf += bytes_read;
206     result += bytes_read;
207     max_buf_len -= bytes_read;
208   }
209
210   fclose(f);
211   return result;
212 }
213 #endif /*DTLS_X509*/
214
215 #ifdef DTLS_PSK
216
217 #define PSK_SERVER_HINT  "Server_identity"
218
219 /* This function is the "key store" for tinyDTLS. It is called to
220  * retrieve a key for the given identity within this particular
221  * session. */
222 static int
223 get_psk_info(struct dtls_context_t *ctx, const session_t *session,
224              dtls_credentials_type_t type,
225              const unsigned char *id, size_t id_len,
226              unsigned char *result, size_t result_length) {
227
228   (void)ctx;
229   (void)session;
230   struct keymap_t {
231     unsigned char *id;
232     size_t id_length;
233     unsigned char *key;
234     size_t key_length;
235   } psk[3] = {
236     { (unsigned char *)"Client_identity", 15,
237       (unsigned char *)"secretPSK", 9 },
238     { (unsigned char *)"default identity", 16,
239       (unsigned char *)"\x11\x22\x33", 3 },
240     { (unsigned char *)"\0", 2,
241       (unsigned char *)"", 1 }
242   };
243
244   switch (type) {
245   case DTLS_PSK_HINT:
246     if (result_length < strlen(PSK_SERVER_HINT)) {
247       dtls_warn("cannot set psk_hint -- buffer too small\n");
248       return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
249     }
250
251     memcpy(result, PSK_SERVER_HINT, strlen(PSK_SERVER_HINT));
252     return strlen(PSK_SERVER_HINT);
253
254   case DTLS_PSK_KEY:
255     if (id) {
256       int i;
257       for (i = 0; i < (int)(sizeof(psk)/sizeof(struct keymap_t)); i++) {
258         if (id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) {
259           if (result_length < psk[i].key_length) {
260             dtls_warn("buffer too small for PSK");
261             return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
262           }
263
264           memcpy(result, psk[i].key, psk[i].key_length);
265           return psk[i].key_length;
266         }
267       }
268     }
269     break;
270
271   default:
272     dtls_warn("unsupported request type: %d\n", type);
273   }
274
275   return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR);
276 }
277
278 #endif /* DTLS_PSK */
279
280 #ifdef DTLS_ECC
281 static int
282 get_ecdsa_key(struct dtls_context_t *ctx,
283               const session_t *session,
284               const dtls_ecc_key_t **result) {
285     (void)ctx;
286     (void)session;
287   static const dtls_ecc_key_t ecdsa_key = {
288     .curve = DTLS_ECDH_CURVE_SECP256R1,
289     .priv_key = ecdsa_priv_key,
290     .pub_key_x = ecdsa_pub_key_x,
291     .pub_key_y = ecdsa_pub_key_y
292   };
293
294   *result = &ecdsa_key;
295   return 0;
296 }
297
298 static int
299 verify_ecdsa_key(struct dtls_context_t *ctx,
300                  const session_t *session,
301                  const unsigned char *other_pub_x,
302                  const unsigned char *other_pub_y,
303                  size_t key_size) {
304   (void)ctx;
305   (void)session;
306   (void)other_pub_x;
307   (void)other_pub_y;
308   (void)key_size;
309   return 0;
310 }
311 #endif /* DTLS_ECC */
312
313 #ifdef DTLS_X509
314 static int
315 get_x509_key(struct dtls_context_t *ctx,
316           const session_t *session,
317           const dtls_ecc_key_t **result) {
318     (void)ctx;
319     (void)session;
320   static dtls_ecc_key_t ecdsa_key = {
321     .curve = DTLS_ECDH_CURVE_SECP256R1,
322     .priv_key = x509_priv_key,
323     .pub_key_x = x509_pub_key_x,
324     .pub_key_y = x509_pub_key_y
325   };
326   if (x509_info_from_file)
327       ecdsa_key.priv_key = x509_server_priv;
328
329   *result = &ecdsa_key;
330   return 0;
331 }
332
333 static int
334 get_x509_cert(struct dtls_context_t *ctx,
335                 const session_t *session,
336                 const unsigned char **cert,
337                 size_t *cert_size)
338 {
339     (void)ctx;
340     (void)session;
341     if (x509_info_from_file)
342     {
343         *cert = x509_server_cert;
344         *cert_size = x509_server_cert_len;
345     }
346     else
347     {
348         *cert = g_server_certificate;
349         *cert_size = SERVER_CRT_LEN;
350     }
351
352     return 0;
353 }
354
355 static int check_certificate(byte_array cert_der_code, byte_array ca_public_key)
356 {
357     (void)cert_der_code;
358     (void)ca_public_key;
359     return 0;
360 }
361
362 static int verify_x509_cert(struct dtls_context_t *ctx, const session_t *session,
363                                   const unsigned char *cert, size_t cert_size,
364                                   unsigned char *x,
365                                   size_t x_size,
366                                   unsigned char *y,
367                                   size_t y_size)
368 {
369     int ret;
370     const unsigned char *ca_pub_x;
371     const unsigned char *ca_pub_y;
372     byte_array cert_der_code = BYTE_ARRAY_INITIALIZER;
373     byte_array ca_public_key = BYTE_ARRAY_INITIALIZER;
374     unsigned char ca_pub_key[DTLS_PUBLIC_KEY_SIZE];
375     (void)ctx;
376     (void)session;
377
378     if (x509_info_from_file)
379     {
380         ca_pub_x = x509_ca_pub;
381         ca_pub_y = x509_ca_pub + DTLS_PUBLIC_KEY_SIZE/2;
382     }
383     else
384     {
385         ca_pub_x = x509_ca_pub_x;
386         ca_pub_y = x509_ca_pub_y;
387     }
388
389     cert_der_code.data = (uint8_t *)cert;
390     cert_der_code.len = cert_size;
391
392     ca_public_key.len = DTLS_PUBLIC_KEY_SIZE;
393     ca_public_key.data = ca_pub_key;
394     memcpy(ca_public_key.data, ca_pub_x, DTLS_PUBLIC_KEY_SIZE/2);
395     memcpy(ca_public_key.data + DTLS_PUBLIC_KEY_SIZE/2, ca_pub_y, DTLS_PUBLIC_KEY_SIZE/2);
396
397     memcpy(x, client_pub_key_x, x_size);
398     memcpy(y, client_pub_key_y, y_size);
399
400     ret = (int) check_certificate(cert_der_code, ca_public_key);
401
402   return -ret;
403 }
404
405 static int is_x509_active(struct dtls_context_t *ctx)
406 {
407     (void)ctx;
408     return 0;
409 }
410 #endif /* DTLS_X509 */
411
412
413 #define DTLS_SERVER_CMD_CLOSE "server:close"
414 #define DTLS_SERVER_CMD_RENEGOTIATE "server:renegotiate"
415
416 static int
417 read_from_peer(struct dtls_context_t *ctx,
418                session_t *session, uint8 *data, size_t len) {
419   size_t i;
420   for (i = 0; i < len; i++)
421     printf("%c", data[i]);
422   if (len >= strlen(DTLS_SERVER_CMD_CLOSE) &&
423       !memcmp(data, DTLS_SERVER_CMD_CLOSE, strlen(DTLS_SERVER_CMD_CLOSE))) {
424     printf("server: closing connection\n");
425     dtls_close(ctx, session);
426     return len;
427   } else if (len >= strlen(DTLS_SERVER_CMD_RENEGOTIATE) &&
428       !memcmp(data, DTLS_SERVER_CMD_RENEGOTIATE, strlen(DTLS_SERVER_CMD_RENEGOTIATE))) {
429     printf("server: renegotiate connection\n");
430     dtls_renegotiate(ctx, session);
431     return len;
432   }
433
434   return dtls_write(ctx, session, data, len);
435 }
436
437 static int
438 send_to_peer(struct dtls_context_t *ctx, 
439              session_t *session, uint8 *data, size_t len) {
440
441   int fd = *(int *)dtls_get_app_data(ctx);
442   return sendto(fd, data, len, MSG_DONTWAIT,
443                 &session->addr.sa, session->size);
444 }
445
446 static int
447 dtls_handle_read(struct dtls_context_t *ctx) {
448   int *fd;
449   session_t session;
450   static uint8 buf[DTLS_MAX_BUF];
451   int len;
452
453   fd = dtls_get_app_data(ctx);
454
455   assert(fd);
456
457   memset(&session, 0, sizeof(session_t));
458   session.size = sizeof(session.addr);
459   len = recvfrom(*fd, buf, sizeof(buf), MSG_TRUNC,
460                  &session.addr.sa, &session.size);
461
462   if (len < 0) {
463     perror("recvfrom");
464     return -1;
465   } else {
466     dtls_debug("got %d bytes from port %d\n", len, 
467              ntohs(session.addr.sin6.sin6_port));
468     if ((int)(sizeof(buf)) < len) {
469       dtls_warn("packet was truncated (%d bytes lost)\n", len - sizeof(buf));
470     }
471   }
472
473   return dtls_handle_message(ctx, &session, buf, len);
474 }    
475
476 static int
477 resolve_address(const char *server, struct sockaddr *dst) {
478   
479   struct addrinfo *res, *ainfo;
480   struct addrinfo hints;
481   static char addrstr[256];
482   int error;
483
484   memset(addrstr, 0, sizeof(addrstr));
485   if (server && strlen(server) > 0)
486     memcpy(addrstr, server, strlen(server));
487   else
488     memcpy(addrstr, "localhost", 9);
489
490   memset ((char *)&hints, 0, sizeof(hints));
491   hints.ai_socktype = SOCK_DGRAM;
492   hints.ai_family = AF_UNSPEC;
493
494   error = getaddrinfo(addrstr, "", &hints, &res);
495
496   if (error != 0) {
497     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
498     return error;
499   }
500
501   for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
502
503     switch (ainfo->ai_family) {
504     case AF_INET6:
505
506       memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen);
507       return ainfo->ai_addrlen;
508     default:
509       ;
510     }
511   }
512
513   freeaddrinfo(res);
514   return -1;
515 }
516
517 static void
518 usage(const char *program, const char *version) {
519   const char *p;
520
521   p = strrchr( program, '/' );
522   if ( p )
523     program = ++p;
524
525   fprintf(stderr, "%s v%s -- DTLS server implementation\n"
526           "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
527           "usage: %s [-A address] [-p port] [-v num] [-a enable|disable]\n"
528 #ifdef DTLS_X509
529       " [-x file] [-r file] [-u file]"
530 #endif /* DTLS_X509 */
531           "\t-A address\t\tlisten on specified address (default is ::)\n"
532           "\t-p port\t\tlisten on specified port (default is %d)\n"
533           "\t-v num\t\tverbosity level (default: 3)\n"
534           "\t-a enable|disable\t(default: disable)\n"
535           "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
536           "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
537 #ifdef DTLS_X509
538       "\t-x file\tread Server certificate from file\n"
539       "\t-r file\tread Server private key from file\n"
540       "\t-u file\tread CA public key from file\n"
541 #endif /* DTLS_X509 */
542       ,program, version, program, DEFAULT_PORT);
543 }
544
545 static dtls_handler_t cb = {
546   .write = send_to_peer,
547   .read  = read_from_peer,
548   .event = NULL,
549 #ifdef DTLS_PSK
550   .get_psk_info = get_psk_info,
551 #endif /* DTLS_PSK */
552 #ifdef DTLS_ECC
553   .get_ecdsa_key = get_ecdsa_key,
554   .verify_ecdsa_key = verify_ecdsa_key,
555 #endif /* DTLS_ECC */
556 #ifdef DTLS_X509
557   .get_x509_key = get_x509_key,
558   .verify_x509_cert = verify_x509_cert,
559   .get_x509_cert = get_x509_cert,
560   .is_x509_active = is_x509_active,
561 #endif
562
563 };
564
565 int
566 main(int argc, char **argv) {
567   dtls_context_t *the_context = NULL;
568   log_t log_level = DTLS_LOG_WARN;
569   fd_set rfds, wfds;
570   struct timeval timeout;
571   int fd, opt, result;
572   int on = 1;
573   dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
574   struct sockaddr_in6 listen_addr;
575
576   memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
577
578   /* fill extra field for 4.4BSD-based systems (see RFC 3493, section 3.4) */
579 #if defined(SIN6_LEN) || defined(HAVE_SOCKADDR_IN6_SIN6_LEN)
580   listen_addr.sin6_len = sizeof(struct sockaddr_in6);
581 #endif
582
583   listen_addr.sin6_family = AF_INET6;
584   listen_addr.sin6_port = htons(DEFAULT_PORT);
585   listen_addr.sin6_addr = in6addr_any;
586
587   while ((opt = getopt(argc, argv, "A:p:v:a:")) != -1) {
588     switch (opt) {
589     case 'A' :
590       if (resolve_address(optarg, (struct sockaddr *)&listen_addr) < 0) {
591         fprintf(stderr, "cannot resolve address\n");
592         exit(-1);
593       }
594       break;
595     case 'p' :
596       listen_addr.sin6_port = htons(atoi(optarg));
597       break;
598     case 'v' :
599       log_level = strtol(optarg, NULL, 10);
600       break;
601     case 'a':
602       if( strcmp(optarg, "enable") == 0)
603           ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
604       break;
605 #ifdef DTLS_X509
606     case 'x' :
607     {
608       ssize_t result = read_from_file(optarg, x509_server_cert, DTLS_MAX_CERT_SIZE);
609       if (result < 0)
610       {
611           dtls_warn("Cannot read Server certificate. Using default\n");
612       }
613       else
614       {
615           x509_server_cert_len = result;
616       }
617       break;
618     }
619     case 'r' :
620     {
621       ssize_t result = read_from_file(optarg, x509_server_priv, DTLS_PRIVATE_KEY_SIZE+1);
622       if (result < 0)
623       {
624           dtls_warn("Cannot read Server private key. Using default\n");
625       }
626       else
627       {
628           x509_server_priv_is_set = result;
629       }
630       break;
631     }
632     case 'u' :
633     {
634       ssize_t result = read_from_file(optarg, x509_ca_pub, DTLS_PUBLIC_KEY_SIZE+1);
635       if (result < 0)
636       {
637           dtls_warn("Cannot read CA public key. Using default\n");
638       }
639       else
640       {
641           x509_ca_pub_is_set = result;
642       }
643       break;
644     }
645 #endif /* DTLS_X509 */
646     default:
647       usage(argv[0], dtls_package_version());
648       exit(1);
649     }
650   }
651
652   dtls_set_log_level(log_level);
653
654 #ifdef DTLS_X509
655   if (x509_server_cert_len && x509_server_priv_is_set && x509_ca_pub_is_set)
656   {
657       x509_info_from_file = 1;
658   }
659   else if(!(x509_server_cert_len || x509_server_priv_is_set || x509_ca_pub_is_set))
660   {
661       x509_info_from_file = 0;
662   }
663   else
664   {
665       fprintf(stderr,"please set -x, -r, -u options simultaneously");
666       usage(argv[0], dtls_package_version());
667       exit(1);
668   }
669 #endif /* DTLS_X509 */
670
671   /* init socket and set it to non-blocking */
672   fd = socket(listen_addr.sin6_family, SOCK_DGRAM, 0);
673
674   if (fd < 0) {
675     dtls_alert("socket: %s\n", strerror(errno));
676     return 0;
677   }
678
679   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on) ) < 0) {
680     dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno));
681   }
682 #if 0
683   flags = fcntl(fd, F_GETFL, 0);
684   if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
685     dtls_alert("fcntl: %s\n", strerror(errno));
686     goto error;
687   }
688 #endif
689   on = 1;
690 #ifdef IPV6_RECVPKTINFO
691   if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) {
692 #else /* IPV6_RECVPKTINFO */
693   if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) {
694 #endif /* IPV6_RECVPKTINFO */
695     dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno));
696   }
697
698   if (bind(fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) {
699     dtls_alert("bind: %s\n", strerror(errno));
700     goto error;
701   }
702
703   dtls_init();
704
705   the_context = dtls_new_context(&fd);
706
707   /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
708   dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
709
710   dtls_set_handler(the_context, &cb);
711
712   while (1) {
713     FD_ZERO(&rfds);
714     FD_ZERO(&wfds);
715
716     FD_SET(fd, &rfds);
717     /* FD_SET(fd, &wfds); */
718     
719     timeout.tv_sec = 5;
720     timeout.tv_usec = 0;
721     
722     result = select( fd+1, &rfds, &wfds, 0, &timeout);
723     
724     if (result < 0) {           /* error */
725       if (errno != EINTR)
726         perror("select");
727     } else if (result == 0) {   /* timeout */
728     } else {                    /* ok */
729       if (FD_ISSET(fd, &wfds))
730         ;
731       else if (FD_ISSET(fd, &rfds)) {
732         dtls_handle_read(the_context);
733       }
734     }
735   }
736   
737  error:
738   dtls_free_context(the_context);
739   exit(0);
740 }