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