1 /* secure-server -- A (broken) DTLS server example
3 * Copyright (C) 2011 Olaf Bergmann <bergmann@tzi.org>
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use, copy,
9 * modify, merge, publish, distribute, sublicense, and/or sell copies
10 * of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 #include <sys/select.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
42 #include <openssl/ssl.h>
43 #include <openssl/bio.h>
44 #include <openssl/err.h>
45 #include <openssl/rand.h>
48 #define SERVER_CERT_PEM "./server-cert.pem"
49 #define SERVER_KEY_PEM "./server-key.pem"
50 #define CA_CERT_PEM "./ca-cert.pem"
57 #endif /* HAVE_ASSERT_H */
61 /* SIGINT handler: set quit to 1 for graceful termination */
63 handle_sigint(int signum) {
68 check_connect(int sockfd, char *buf, int buflen,
69 struct sockaddr *src, int *ifindex) {
71 /* for some reason, the definition in netinet/in.h is not exported */
75 struct in6_addr ipi6_addr; /* src/dst IPv6 address */
76 unsigned int ipi6_ifindex; /* send/recv interface index */
82 struct iovec iov[1] = { {buf, buflen} };
83 char cmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
84 struct in6_pktinfo *p = NULL;
86 struct msghdr msg = { 0 };
90 msg.msg_namelen = sizeof(struct sockaddr_in6);
93 msg.msg_control = cmsgbuf;
94 msg.msg_controllen = sizeof(cmsgbuf);
96 bytes = recvmsg(sockfd, &msg, MSG_DONTWAIT | MSG_PEEK);
102 /* TODO: handle msg.msg_flags & MSG_TRUNC */
103 if (msg.msg_flags & MSG_CTRUNC) {
104 fprintf(stderr, "control was truncated!\n");
109 /* Here we try to retrieve the interface index where the packet was received */
111 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
112 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
114 if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
115 p = (struct in6_pktinfo *)(CMSG_DATA(cmsg));
116 *ifindex = p->ipi6_ifindex;
125 typedef enum { UNKNOWN=0, DTLS=1 } protocol_t;
128 demux_protocol(const char *buf, int len) {
134 PEER_ST_ESTABLISHED, PEER_ST_PENDING, PEER_ST_CLOSED
142 #define MAX_SSL_PENDING 2 /* must be less than MAX_SSL_PEERS */
143 #define MAX_SSL_PEERS 10 /* MAX_SSL_PENDING of these might be pending */
144 ssl_peer_t *ssl_peer_storage[MAX_SSL_PEERS];
145 static int pending = 0;
149 typedef struct bio_dgram_data_st
153 struct sockaddr_in sa_in;
154 struct sockaddr_in6 sa_in6;
156 unsigned int connected;
159 struct timeval next_timeout;
160 struct timeval socket_timeout;
163 struct sockaddr_in6 peer;
166 for (i = 0; i < MAX_SSL_PEERS; i++) {
167 if (ssl_peer_storage[i]) {
168 if (!ssl_peer_storage[i]->ssl)
169 fprintf(stderr, "invalid SSL object for peer %d!\n",i);
171 bio = SSL_get_rbio(ssl_peer_storage[i]->ssl);
173 (void) BIO_dgram_get_peer(bio, (struct sockaddr *)&peer);
174 if (peer.sin6_port && ssl_peer_storage[i]->h != ntohs(peer.sin6_port)) {
175 fprintf(stderr, " bio %p: port differs from hash: %d != %d! (%sconnected)\n", bio,
176 ssl_peer_storage[i]->h,
177 ntohs(((struct sockaddr_in6 *)&peer)->sin6_port),
178 ((bio_dgram_data *)bio->ptr)->connected ? "" : "not ");
187 /** Creates a hash value from the first num bytes of s, taking init as
188 * initialization value. */
189 static inline unsigned long
190 _hash(unsigned long init, const char *s, int num) {
194 while ( (c = *s++) ) {
195 init = ((init << 7) + init) + c;
201 static inline unsigned long
202 hash_peer(const struct sockaddr *peer, int ifindex) {
205 /* initialize hash value to interface index */
206 h = _hash(0, (char *)&ifindex, sizeof(int));
208 #define CAST(TYPE,VAR) ((TYPE)VAR)
211 switch (peer->sa_family) {
213 return ntohs(CAST(const struct sockaddr_in *, peer)->sin_port);
214 h = _hash(h, (char *) &CAST(const struct sockaddr_in *, peer)->sin_addr,
215 sizeof(struct in_addr));
216 h = _hash(h, (char *) &CAST(const struct sockaddr_in *, peer)->sin_port,
220 return ntohs(CAST(const struct sockaddr_in6 *, peer)->sin6_port);
222 (char *) &CAST(const struct sockaddr_in6 *, peer)->sin6_addr,
223 sizeof(struct in6_addr));
225 (char *) &CAST(const struct sockaddr_in6 *, peer)->sin6_port,
230 h = _hash(h, (char *)peer, sizeof(struct sockaddr));
237 /* Returns index of peer object for specified address/ifindex pair. */
239 get_index_of_peer(const struct sockaddr *peer, int ifindex) {
243 char addr[INET6_ADDRSTRLEN];
250 h = hash_peer(peer,ifindex);
252 for (idx = 0; idx < MAX_SSL_PEERS; idx++) {
253 if (ssl_peer_storage[idx] && ssl_peer_storage[idx]->h == h) {
255 getnameinfo((struct sockaddr *)peer, sizeof(struct sockaddr_in6),
256 addr, sizeof(addr), port, sizeof(port),
257 NI_NUMERICHOST | NI_NUMERICSERV);
259 fprintf(stderr, "get_index_of_peer: [%s]:%s => %lu\n",
269 get_ssl(SSL_CTX *ctx, int sockfd, struct sockaddr *src, int ifindex) {
274 struct sockaddr_storage peer;
275 char addr[INET6_ADDRSTRLEN];
280 idx = get_index_of_peer(src,ifindex);
282 fprintf(stderr,"found peer %d ",idx);
283 switch (ssl_peer_storage[idx]->state) {
284 case PEER_ST_ESTABLISHED: fprintf(stderr,"established\n"); break;
285 case PEER_ST_PENDING: fprintf(stderr,"pending\n"); break;
286 case PEER_ST_CLOSED: fprintf(stderr,"closed\n"); break;
292 memset(&peer, 0, sizeof(peer));
293 (void) BIO_dgram_get_peer(SSL_get_rbio(ssl_peer_storage[idx]->ssl), &peer);
295 getnameinfo((struct sockaddr *)&peer, sizeof(peer),
296 addr, sizeof(addr), port, sizeof(port),
297 NI_NUMERICHOST | NI_NUMERICSERV);
299 fprintf(stderr," [%s]:%s \n", addr, port);
301 return ssl_peer_storage[idx]->ssl;
304 /* none found, create new if sufficient space available */
305 if (pending < MAX_SSL_PENDING) {
306 for (idx = 0; idx < MAX_SSL_PEERS; idx++) {
307 if (ssl_peer_storage[idx] == NULL) { /* found space */
311 bio = BIO_new_dgram(sockfd, BIO_NOCLOSE);
317 SSL_set_bio(ssl, bio, bio);
318 SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
320 SSL_set_accept_state(ssl);
321 ssl_peer_storage[idx] = (ssl_peer_t *) malloc(sizeof(ssl_peer_t));
322 if (!ssl_peer_storage[idx]) {
326 ssl_peer_storage[idx]->state = PEER_ST_PENDING;
327 ssl_peer_storage[idx]->h = hash_peer(src,ifindex);
328 ssl_peer_storage[idx]->ssl = ssl;
333 "created new SSL peer %d for ssl object %p (storage: %p)\n",
334 idx, ssl, ssl_peer_storage[idx]);
336 if (getnameinfo((struct sockaddr *)&src, sizeof(src),
337 addr, sizeof(addr), port, sizeof(port),
338 NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
339 perror("getnameinfo");
340 fprintf(stderr, "port was %u\n", ntohs(((struct sockaddr_in6 *)src)->sin6_port));
342 fprintf(stderr," [%s]:%s \n", addr, port);
345 OPENSSL_assert(ssl_peer_storage[idx]->ssl == ssl);
346 fprintf(stderr,"%d objects pending\n", pending);
353 fprintf(stderr, "too many pending SSL objects\n");
357 fprintf(stderr, "too many peers\n");
361 /** Deletes peer stored at index idx and frees allocated memory. */
363 delete_peer(int idx) {
364 if (idx < 0 || !ssl_peer_storage[idx])
367 if (ssl_peer_storage[idx]->state == PEER_ST_PENDING)
370 OPENSSL_assert(ssl_peer_storage[idx]->ssl);
371 SSL_free(ssl_peer_storage[idx]->ssl);
373 free(ssl_peer_storage[idx]);
374 ssl_peer_storage[idx] = NULL;
376 printf("deleted peer %d\n",idx);
379 /** Deletes all closed objects from ssl_peer_storage. */
384 for (idx = 0; idx < MAX_SSL_PEERS; idx++)
385 if (ssl_peer_storage[idx]
386 && ssl_peer_storage[idx]->state == PEER_ST_CLOSED)
390 #define min(a,b) ((a) < (b) ? (a) : (b))
393 psk_server_callback(SSL *ssl, const char *identity,
394 unsigned char *psk, unsigned int max_psk_len) {
395 static char keybuf[] = "secretPSK";
397 printf("psk_server_callback: check identity of client %s\n", identity);
398 memcpy(psk, keybuf, min(strlen(keybuf), max_psk_len));
400 return min(strlen(keybuf), max_psk_len);
407 * This function tracks the status changes from libssl to manage local
411 info_callback(const SSL *ssl, int where, int ret) {
413 struct sockaddr_storage peer;
414 struct sockaddr_storage peer2;
415 char addr[INET6_ADDRSTRLEN];
418 if (where & SSL_CB_LOOP) /* do not care for intermediary states */
421 memset(&peer, 0, sizeof(peer));
422 (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
424 /* lookup SSL object */ /* FIXME: need to get the ifindex */
425 idx = get_index_of_peer((struct sockaddr *)&peer, 0);
428 fprintf(stderr, "info_callback: assert: %d < 0 || %p == %p (storage: %p)\n",
429 idx, ssl, ssl_peer_storage[idx]->ssl, ssl_peer_storage[idx]);
430 if (idx >= 0 && ssl != ssl_peer_storage[idx]->ssl) {
431 getnameinfo((struct sockaddr *)&peer, sizeof(peer),
432 addr, sizeof(addr), port, sizeof(port),
433 NI_NUMERICHOST | NI_NUMERICSERV);
435 fprintf(stderr," ssl: [%s]:%s ", addr, port);
437 (void) BIO_dgram_get_peer(SSL_get_rbio(ssl_peer_storage[idx]->ssl), &peer2);
438 getnameinfo((struct sockaddr *)&peer2, sizeof(peer2),
439 addr, sizeof(addr), port, sizeof(port),
440 NI_NUMERICHOST | NI_NUMERICSERV);
442 fprintf(stderr," ssl_peer_storage[idx]->ssl: [%s]:%s\n", addr, port);
444 fprintf(stderr, " hash:%lu h: %lu\n",
445 hash_peer((const struct sockaddr *)&peer, 0),
446 ssl_peer_storage[idx]->h);
448 for (i = 0; i < MAX_SSL_PEERS; i++) {
449 if (ssl_peer_storage[i]) {
450 fprintf(stderr, "%02d: %p ssl: %p ",
451 i, ssl_peer_storage[i] ,ssl_peer_storage[i]->ssl);
453 (void) BIO_dgram_get_peer(SSL_get_rbio(ssl_peer_storage[i]->ssl), &peer2);
454 getnameinfo((struct sockaddr *)&peer2, sizeof(peer2),
455 addr, sizeof(addr), port, sizeof(port),
456 NI_NUMERICHOST | NI_NUMERICSERV);
458 fprintf(stderr," peer: [%s]:%s h: %lu\n", addr, port, ssl_peer_storage[i]->h);
461 fprintf(stderr, "***** ASSERT FAILED ******\n");
463 memset(&peer, 0, sizeof(peer));
464 (void) BIO_dgram_get_peer(SSL_get_wbio(ssl), &peer);
466 idx = get_index_of_peer((struct sockaddr *)&peer, 0);
467 fprintf(stderr, " get_index_of_peer for wbio returns %d, type is %04x\n",
472 OPENSSL_assert((idx < 0) || (ssl == ssl_peer_storage[idx]->ssl));
475 if (where & SSL_CB_ALERT) {
478 fprintf(stderr,"%s:%s:%s\n", SSL_alert_type_string(ret),
479 SSL_alert_desc_string(ret), SSL_alert_desc_string_long(ret));
482 /* examine alert type */
483 switch (*SSL_alert_type_string(ret)) {
485 /* move SSL object from pending to close */
487 ssl_peer_storage[idx]->state = PEER_ST_CLOSED;
492 if ((ret & 0xff) == SSL_AD_CLOSE_NOTIFY) {
493 if (where == SSL_CB_WRITE_ALERT)
494 fprintf(stderr,"sent CLOSE_NOTIFY\n");
495 else /* received CN */
496 fprintf(stderr,"received CLOSE_NOTIFY\n");
499 default: /* handle unknown alert types */
501 printf("not handled!\n");
506 if (where & SSL_CB_HANDSHAKE_DONE) {
507 /* move SSL object from pending to established */
508 printf("HANDSHAKE_DONE ");
511 if (ssl_peer_storage[idx]->state == PEER_ST_PENDING) {
512 ssl_peer_storage[idx]->state = PEER_ST_ESTABLISHED;
514 printf("moved SSL object %d to ESTABLISHED\n", idx);
515 printf("%d objects pending\n", pending);
518 printf("huh, object %d was not pending? (%d)\n", idx,
519 ssl_peer_storage[idx]->state);
532 /* checks if ssl object was closed and can be removed */
534 check_close(SSL *ssl) {
536 struct sockaddr_storage peer;
538 memset(&peer, 0, sizeof(peer));
539 (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
542 if (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) {
543 printf("SSL_RECEIVED_SHUTDOWN\n");
544 res = SSL_shutdown(ssl);
546 printf("must call SSL_shutdown again\n");
547 res = SSL_shutdown(ssl);
550 err = SSL_get_error(ssl,res);
551 fprintf(stderr, "shutdown: SSL error %d: %s\n", err,
552 ERR_error_string(err, NULL));
555 /* we can close the SSL object anyway */
556 /* FIXME: need to get ifindex from somewhere */
557 idx = get_index_of_peer((struct sockaddr *)&peer, 0);
558 OPENSSL_assert(idx < 0 || ssl == ssl_peer_storage[idx]->ssl);
560 ssl_peer_storage[idx]->state = PEER_ST_CLOSED;
561 printf("moved SSL object %d to CLOSED\n",idx);
572 for (i = 0; i < MAX_SSL_PEERS; i++) {
573 if (ssl_peer_storage[i]) {
574 OPENSSL_assert(ssl_peer_storage[i]->ssl);
575 result = DTLSv1_handle_timeout(ssl_peer_storage[i]->ssl);
577 err = SSL_get_error(ssl_peer_storage[i]->ssl,result);
578 fprintf(stderr, "dtls1_handle_timeout (%d): %s\n",
579 err, ERR_error_string(err, NULL));
584 /* remove outdated obbjects? */
588 #endif /* WITH_DTLS */
591 _read(SSL_CTX *ctx, int sockfd) {
593 struct sockaddr_in6 src;
595 char addr[INET6_ADDRSTRLEN];
597 socklen_t sz = sizeof(struct sockaddr_in6);
603 /* Retrieve remote address and interface index as well as the first
604 few bytes of the message to demultiplex protocols. */
605 memset(&src, 0, sizeof(struct sockaddr_in6));
606 len = check_connect(sockfd, buf, 4, (struct sockaddr *)&src, &ifindex);
608 if (len < 0) /* error */
612 fprintf(stderr,"received packet");
614 if (getnameinfo((struct sockaddr *)&src, sizeof(src),
615 addr, sizeof(addr), port, sizeof(port),
616 NI_NUMERICHOST | NI_NUMERICSERV) == 0)
617 fprintf(stderr," from [%s]:%s", addr, port);
619 fprintf(stderr," on interface %d\n", ifindex);
622 switch (demux_protocol(buf, len)) {
625 ssl = get_ssl(ctx, sockfd, (struct sockaddr *)&src, ifindex);
627 fprintf(stderr, "cannot create new SSL object\n");
628 /* return recv(sockfd, buf, sizeof(buf), MSG_DONTWAIT);*/
629 len = recvfrom(sockfd, buf, sizeof(buf), MSG_DONTWAIT,
630 (struct sockaddr *)&src, &sz);
631 getnameinfo((struct sockaddr *)&src, sz,
632 addr, sizeof(addr), port, sizeof(port),
633 NI_NUMERICHOST | NI_NUMERICSERV);
634 printf("discarded %d bytes from [%s]:%s\n", len, addr, port);
637 len = SSL_read(ssl, buf, sizeof(buf));
642 len = recv(sockfd, buf, sizeof(buf), MSG_DONTWAIT);
646 printf("here is the data:\n");
647 for (i=0; i<len; i++)
649 } if (len == 0) { /* session closed? */
651 if (check_close(ssl) <= 0) {
652 fprintf(stderr, "not closed\n");
657 err = SSL_get_error(ssl,len);
659 case SSL_ERROR_WANT_READ:
660 fprintf(stderr, "SSL_ERROR_WANT_READ\n");
662 case SSL_ERROR_WANT_WRITE:
663 fprintf(stderr, "SSL_ERROR_WANT_WRITE\n");
666 fprintf(stderr, "read: SSL error %d: %s\n", err,
667 ERR_error_string(err, NULL));
679 _write(SSL_CTX *ctx, int sockfd) {
685 ssl = get_ssl(ctx, sockfd, NULL, 1);
687 fprintf(stderr, "no SSL object for writing");
690 res = SSL_write(ssl, NULL, 0);
693 if (SSL_want_write(ssl))
696 /* FIXME: check SSL_want_read(ssl) */
698 err = SSL_get_error(ssl,res);
699 fprintf(stderr,"SSL_write returned %d (%s)\n", err, ERR_error_string(err, NULL));
701 printf("SSL_write successful\n");
711 generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) {
712 /* FIXME: generate secure client-specific cookie */
713 #define DUMMYSTR "ABCDEFGHIJKLMNOP"
714 *cookie_len = strlen(DUMMYSTR);
715 memcpy(cookie, DUMMYSTR, *cookie_len);
721 verify_cookie(SSL *ssl, unsigned char *cookie, unsigned int cookie_len) {
726 enum { READ, WRITE };
729 main(int argc, char **argv) {
732 struct sockaddr_in6 listen_addr = { AF_INET6, htons(20220), 0, IN6ADDR_ANY_INIT, 0 };
733 size_t addr_size = sizeof(struct sockaddr_in6);
737 struct timeval timeout;
738 struct sigaction act, oact;
743 memset(ssl_peer_storage, 0, sizeof(ssl_peer_storage));
745 SSL_load_error_strings();
747 ctx = SSL_CTX_new(DTLSv1_server_method());
749 SSL_CTX_set_cipher_list(ctx, "ALL");
750 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
752 res = SSL_CTX_use_certificate_file(ctx, SERVER_CERT_PEM, SSL_FILETYPE_PEM);
754 fprintf(stderr, "cannot read server certificate from file '%s' (%s)\n",
755 SERVER_CERT_PEM, ERR_error_string(res,NULL));
759 res = SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY_PEM, SSL_FILETYPE_PEM);
761 fprintf(stderr, "cannot read server key from file '%s' (%s)\n",
762 SERVER_KEY_PEM, ERR_error_string(res,NULL));
766 res = SSL_CTX_check_private_key (ctx);
768 fprintf(stderr, "invalid private key\n");
772 res = SSL_CTX_load_verify_locations(ctx, CA_CERT_PEM, NULL);
774 fprintf(stderr, "cannot read ca file '%s'\n", CA_CERT_PEM);
778 /* Client has to authenticate */
780 /* Client has to authenticate */
781 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
783 SSL_CTX_set_read_ahead(ctx, 1); /* disable read-ahead */
784 SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie);
785 SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie);
787 SSL_CTX_use_psk_identity_hint(ctx, "Enter password for CoAP-Gateway");
788 SSL_CTX_set_psk_server_callback(ctx, psk_server_callback);
790 SSL_CTX_set_info_callback(ctx, info_callback);
793 sockfd = socket(listen_addr.sin6_family, SOCK_DGRAM, 0);
799 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0)
800 perror("setsockopt SO_REUSEADDR");
802 flags = fcntl(sockfd, F_GETFL, 0);
803 if (flags < 0 || fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
809 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on) ) < 0) {
810 perror("setsockopt IPV6_PKTINFO");
813 if (bind (sockfd, (const struct sockaddr *)&listen_addr, addr_size) < 0) {
819 act.sa_handler = handle_sigint;
820 sigemptyset(&act.sa_mask);
822 sigaction(SIGINT, &act, &oact);
826 FD_ZERO(&fds[WRITE]);
827 FD_SET(sockfd, &fds[READ]);
831 result = select( FD_SETSIZE, &fds[READ], &fds[WRITE], 0, &timeout);
833 if (result < 0) { /* error */
836 } else if (result > 0) { /* read from socket */
837 if ( FD_ISSET( sockfd, &fds[READ]) ) {
838 _read(ctx, sockfd); /* read received data */
839 } else if ( FD_ISSET( sockfd, &fds[WRITE]) ) { /* write to socket */
840 _write(ctx, sockfd); /* write data */
842 } else { /* timeout */
850 for (idx = 0; idx < MAX_SSL_PEERS; idx++) {
851 if (ssl_peer_storage[idx] && ssl_peer_storage[idx]->ssl) {
852 if (ssl_peer_storage[idx]->state == PEER_ST_ESTABLISHED)
853 SSL_shutdown(ssl_peer_storage[idx]->ssl);
854 SSL_free(ssl_peer_storage[idx]->ssl);
860 close(sockfd); /* don't care if we close stdin at this point */