GNUnet 0.26.0
 
Loading...
Searching...
No Matches
gnunet-communicator-tcp.c File Reference

Transport plugin using TCP. More...

Include dependency graph for gnunet-communicator-tcp.c:

Go to the source code of this file.

Data Structures

struct  TcpHandshakeSignature
 Signature we use to verify that the ephemeral key was really chosen by the specified sender. More...
 
struct  TcpHandshakeAckSignature
 Signature we use to verify that the ack from the receiver of the ephemeral key was really send by the specified sender. More...
 
struct  TCPConfirmation
 Encrypted continuation of TCP initial handshake. More...
 
struct  TCPConfirmationAck
 Ack for the encrypted continuation of TCP initial handshake. More...
 
struct  TCPBox
 TCP message box. More...
 
struct  TCPRekey
 TCP rekey message box. More...
 
struct  TcpRekeySignature
 Signature we use to verify that the ephemeral key was really chosen by the specified sender. More...
 
struct  TCPFinish
 TCP finish. More...
 
struct  TCPNATProbeMessage
 Basically a WELCOME message, but with the purpose of giving the waiting peer a client handle to use. More...
 
struct  PendingReversal
 Struct for pending nat reversals. More...
 
struct  ListenTask
 Struct to use as closure. More...
 
struct  Queue
 Handle for a queue. More...
 
struct  ProtoQueue
 Handle for an incoming connection where we do not yet have enough information to setup a full queue. More...
 
struct  PortOnlyIpv4Ipv6
 In case of port only configuration we like to bind to ipv4 and ipv6 addresses. More...
 
struct  Addresses
 DLL to store the addresses we like to register at NAT service. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "communicator-tcp", __VA_ARGS__)
 
#define NAT_TIMEOUT   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
 How long until we give up on establishing an NAT connection? Must be > 4 RTT.
 
#define ADDRESS_VALIDITY_PERIOD    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
 How long do we believe our addresses to remain up (before the other peer should revalidate).
 
#define DEFAULT_MAX_QUEUE_LENGTH   8
 How many messages do we keep at most in the queue to the transport service before we start to drop (default, can be changed via the configuration file).
 
#define BUF_SIZE   (2 * 64 * 1024 + sizeof(struct TCPBox))
 Size of our IO buffers for ciphertext data.
 
#define DEFAULT_REKEY_INTERVAL   GNUNET_TIME_UNIT_DAYS
 How often do we rekey based on time (at least)
 
#define PROTO_QUEUE_TIMEOUT   GNUNET_TIME_UNIT_MINUTES
 How long do we wait until we must have received the initial KX?
 
#define REKEY_MAX_BYTES   (1024LLU * 1024 * 400)
 How often do we rekey based on number of bytes transmitted? (additionally randomized).
 
#define INITIAL_KX_SIZE
 Size of the initial key exchange message sent first in both directions.
 
#define INITIAL_CORE_KX_SIZE
 Size of the initial core key exchange messages.
 
#define COMMUNICATOR_ADDRESS_PREFIX   "tcp"
 Address prefix used by the communicator.
 
#define COMMUNICATOR_CONFIG_SECTION   "communicator-tcp"
 Configuration section used by the communicator.
 

Functions

static void listen_cb (void *cls)
 We have been notified that our listen socket has something to read.
 
static void eddsa_priv_to_hpke_key (struct GNUNET_CRYPTO_EddsaPrivateKey *edpk, struct GNUNET_CRYPTO_HpkePrivateKey *pk)
 
static void eddsa_pub_to_hpke_key (struct GNUNET_CRYPTO_EddsaPublicKey *edpk, struct GNUNET_CRYPTO_HpkePublicKey *pk)
 
static void queue_destroy (struct Queue *queue)
 Functions with this signature are called whenever we need to close a queue due to a disconnect or failure to establish a connection.
 
static void calculate_hmac (struct GNUNET_HashCode *hmac_secret, const void *buf, size_t buf_size, struct GNUNET_ShortHashCode *smac)
 Compute mac over buf, and ratched the hmac_secret.
 
static void queue_finish (struct Queue *queue)
 Append a 'finish' message to the outgoing transmission.
 
static void queue_read (void *cls)
 Queue read task.
 
static void core_read_finished_cb (void *cls, int success)
 Core tells us it is done processing a message that transport received on a queue with status success.
 
static void pass_plaintext_to_core (struct Queue *queue, const void *plaintext, size_t plaintext_len)
 We received plaintext_len bytes of plaintext on queue.
 
static void setup_cipher (const struct GNUNET_ShortHashCode *prk, const struct GNUNET_PeerIdentity *pid, gcry_cipher_hd_t *cipher, struct GNUNET_HashCode *hmac_key)
 Setup cipher based on shared secret dh and decrypting peer pid.
 
static void rekey_monotime_store_cb (void *cls, int success)
 Callback called when peerstore store operation for rekey monotime value is finished.
 
static void rekey_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY where found.
 
static void setup_in_cipher_elligator (const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct Queue *queue)
 Setup cipher of queue for decryption from an elligator representative.
 
static void setup_in_cipher (const struct GNUNET_CRYPTO_HpkeEncapsulation *ephemeral, struct Queue *queue)
 Setup cipher of queue for decryption.
 
static void do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
 Handle rekey message on queue.
 
static void handshake_ack_monotime_store_cb (void *cls, int success)
 Callback called when peerstore store operation for handshake ack monotime value is finished.
 
static void handshake_ack_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK where found.
 
static void send_challenge (struct GNUNET_CRYPTO_ChallengeNonceP challenge, struct Queue *queue)
 Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
 
static void setup_out_cipher (struct Queue *queue, struct GNUNET_ShortHashCode *dh)
 Setup cipher for outgoing data stream based on target and our ephemeral private key.
 
static void inject_rekey (struct Queue *queue)
 Inject a struct TCPRekey message into the queue's plaintext buffer.
 
static int pending_reversals_delete_it (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static void check_and_remove_pending_reversal (struct sockaddr *in, sa_family_t sa_family, struct GNUNET_PeerIdentity *sender)
 
static void free_proto_queue (struct ProtoQueue *pq)
 Closes socket and frees memory associated with pq.
 
static void proto_queue_write (void *cls)
 We have been notified that our socket is ready to write.
 
static void queue_write (void *cls)
 We have been notified that our socket is ready to write.
 
static size_t try_handle_plaintext (struct Queue *queue)
 Test if we have received a full message in plaintext.
 
static struct sockaddr * tcp_address_to_sockaddr_numeric_v6 (socklen_t *sock_len, struct sockaddr_in6 v6, unsigned int port)
 Convert a struct sockaddr_in6 to astruct sockaddr *`.
 
static struct sockaddr * tcp_address_to_sockaddr_numeric_v4 (socklen_t *sock_len, struct sockaddr_in v4, unsigned int port)
 Convert a struct sockaddr_in4 to astruct sockaddr *`.
 
static struct PortOnlyIpv4Ipv6tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port)
 Convert TCP bind specification to a struct PortOnlyIpv4Ipv6 *
 
static char * extract_address (const char *bindto)
 This Method extracts the address part of the BINDTO string.
 
static unsigned int extract_port (const char *addr_and_port)
 This Method extracts the port part of the BINDTO string.
 
static struct sockaddr * tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
 Convert TCP bind specification to a struct sockaddr *
 
static void mq_send (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
 Signature of functions implementing the sending functionality of a message queue.
 
static void mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Signature of functions implementing the destruction of a message queue.
 
static void mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Implementation function that cancels the currently sent message.
 
static void mq_error (void *cls, enum GNUNET_MQ_Error error)
 Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.
 
static void boot_queue (struct Queue *queue)
 Add the given queue to our internal data structure.
 
static void transmit_kx (struct Queue *queue, const struct GNUNET_CRYPTO_HpkeEncapsulation *c)
 Generate and transmit our ephemeral key and the signature for the initial KX with the other peer.
 
static void start_initial_kx_out (struct Queue *queue)
 Initialize our key material for outgoing transmissions and inform the other peer about it.
 
static void handshake_monotime_store_cb (void *cls, int success)
 Callback called when peerstore store operation for handshake monotime is finished.
 
static void handshake_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE where found.
 
static int decrypt_and_check_tc (struct Queue *queue, struct TCPConfirmation *tc, char *ibuf)
 We have received the first bytes from the other side on a queue.
 
static void queue_read_kx (void *cls)
 Read from the socket of the queue until we have enough data to initialize the decryption logic and can switch to regular reading.
 
static void proto_read_kx (void *cls)
 Read from the socket of the proto queue until we have enough data to upgrade to full queue.
 
static struct ProtoQueuecreate_proto_queue (struct GNUNET_NETWORK_Handle *sock, struct sockaddr *in, socklen_t addrlen)
 
static void try_connection_reversal (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 
static void pending_reversal_timeout (void *cls)
 
static int mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
 Function called by the transport service to initialize a message queue given address information about another peer.
 
static int get_lt_delete_it (void *cls, const struct GNUNET_HashCode *key, void *value)
 Iterator over all ListenTasks to clean up.
 
static int get_queue_delete_it (void *cls, const struct GNUNET_HashCode *target, void *value)
 Iterator over all message queues to clean up.
 
static void do_shutdown (void *cls)
 Shutdown the UNIX communicator.
 
static void enc_notify_cb (void *cls, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg)
 Function called when the transport service has received an acknowledgement for this communicator (!) via a different return path.
 
static void nat_address_cb (void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
 Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of 'valid' addresses changes.
 
static void add_addr (struct sockaddr *in, socklen_t in_len)
 This method adds addresses to the DLL, that are later register at the NAT service.
 
static void load_ikm ()
 Get the initial secret key for generating the peer id.
 
static int init_socket (struct sockaddr *addr, socklen_t in_len)
 This method launch network interactions for each address we like to bind to.
 
static void nat_register ()
 This method reads from the DLL addrs_head to register them at the NAT service.
 
static void init_socket_resolv (void *cls, const struct sockaddr *addr, socklen_t in_len)
 This method is the callback called by the resolver API, and wraps method init_socket.
 
void pid_change_cb (void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *addr_hash)
 
static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
 Setup communicator and launch network interactions.
 
int main (int argc, char *const *argv)
 The main function for the UNIX communicator.
 

Variables

static unsigned long long max_queue_length
 Maximum queue length before we stop reading towards the transport service.
 
static struct GNUNET_PILS_Handlepils
 For PILS.
 
static struct GNUNET_STATISTICS_Handlestats
 For logging statistics.
 
static struct GNUNET_TRANSPORT_CommunicatorHandlech
 Our environment.
 
static struct GNUNET_CONTAINER_MultiHashMapqueue_map
 Queues (map from peer identity to struct Queue)
 
static struct GNUNET_CONTAINER_MultiHashMaplt_map
 ListenTasks (map from socket to struct ListenTask)
 
static struct GNUNET_PeerIdentity my_identity
 Our public key.
 
static unsigned long long rekey_max_bytes
 The rekey byte maximum.
 
static struct GNUNET_TIME_Relative rekey_interval
 The rekey interval.
 
static struct GNUNET_CRYPTO_EddsaPrivateKeymy_private_key
 Our private key.
 
static struct GNUNET_CRYPTO_HpkePrivateKey my_x25519_private_key
 Our private key.
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Our configuration.
 
static struct GNUNET_NT_InterfaceScanneris
 Network scanner to determine network types.
 
static struct GNUNET_NAT_Handlenat
 Connection to NAT service.
 
static struct ProtoQueueproto_head
 Protoqueues DLL head.
 
static struct ProtoQueueproto_tail
 Protoqueues DLL tail.
 
struct GNUNET_RESOLVER_RequestHandleresolve_request_handle
 Handle for DNS lookup of bindto address.
 
static struct Addressesaddrs_head
 Head of DLL with addresses we like to register at NAT service.
 
static struct Addressesaddrs_tail
 Head of DLL with addresses we like to register at NAT service.
 
static int addrs_lens
 Number of addresses in the DLL for register at NAT service.
 
static struct GNUNET_PEERSTORE_Handlepeerstore
 Database for peer's HELLOs.
 
static int shutdown_running = GNUNET_NO
 A flag indicating we are already doing a shutdown.
 
static int disable_v6
 IPv6 disabled.
 
static unsigned int bind_port
 The port the communicator should be assigned to.
 
static struct GNUNET_CONTAINER_MultiHashMappending_reversals
 Map of pending reversals.
 
static unsigned char ikm [256/8]
 The initial key material for the peer.
 

Detailed Description

Transport plugin using TCP.

Author
Christian Grothoff

TODO:

  • support NAT connection reversal method (#5529)
  • support other TCP-specific NAT traversal methods (#5531)

Definition in file gnunet-communicator-tcp.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "communicator-tcp", __VA_ARGS__)

Definition at line 45 of file gnunet-communicator-tcp.c.

◆ NAT_TIMEOUT

How long until we give up on establishing an NAT connection? Must be > 4 RTT.

Definition at line 52 of file gnunet-communicator-tcp.c.

◆ ADDRESS_VALIDITY_PERIOD

#define ADDRESS_VALIDITY_PERIOD    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)

How long do we believe our addresses to remain up (before the other peer should revalidate).

Definition at line 58 of file gnunet-communicator-tcp.c.

126{
131
135 struct GNUNET_PeerIdentity sender;
136
141
145 struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral;
146
151 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
152
156 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
157};
158
164{
169
174
179
185
190};
191
195struct TCPConfirmation
196{
201
206
212
217
218};
219
224{
225
226
231
236
241
247
252
253};
254
258struct TCPBox
259{
267
277
278 /* followed by as may bytes of payload as indicated in @e header,
279 excluding the TCPBox itself! */
280};
281
282
287struct TCPRekey
288{
293
303
308
313
319};
320
326{
331
336
341
346
352};
353
359struct TCPFinish
360{
365
375};
376
382{
387
392};
393
395
399struct PendingReversal
400{
401 /*
402 * Timeout task.
403 */
405
410
414 struct sockaddr *in;
415};
416
420struct ListenTask
421{
426
431};
432
436struct Queue
437{
442
447
452
457
461 gcry_cipher_hd_t in_cipher;
462
466 gcry_cipher_hd_t out_cipher;
467
471 struct GNUNET_HashCode key;
472
477
483
488
493
497 struct sockaddr *address;
498
503 uint64_t rekey_left_bytes;
504
510
514 socklen_t address_len;
515
519 struct GNUNET_MQ_Handle *mq;
520
525
529 unsigned long long bytes_in_queue;
530
534 char cread_buf[BUF_SIZE];
535
539 char cwrite_buf[BUF_SIZE];
540
544 char pread_buf[UINT16_MAX + 1 + sizeof(struct TCPBox)];
545
549 char pwrite_buf[UINT16_MAX + 1 + sizeof(struct TCPBox)];
550
555 size_t cread_off;
556
561 size_t cwrite_off;
562
567 size_t pread_off;
568
573 size_t pwrite_off;
574
579
587 unsigned int backpressure;
588
593
598
603
607 int finishing;
608
615 int destroyed;
616
621 int rekeyed;
622
627
632
637
642
647
652
657
662
667
672
677
681 // TODO remove?
682 size_t unverified_size;
683
688};
689
690
695struct ProtoQueue
696{
700 struct ProtoQueue *next;
701
705 struct ProtoQueue *prev;
706
711
716
721
725 char write_buf[sizeof (struct TCPNATProbeMessage)];
726
730 size_t write_off;
731
736
740 struct sockaddr *address;
741
745 socklen_t address_len;
746
751
756 char ibuf[INITIAL_KX_SIZE];
757
761 size_t ibuf_off;
762};
763
767struct PortOnlyIpv4Ipv6
768{
772 struct sockaddr *addr_ipv4;
773
777 socklen_t addr_len_ipv4;
778
782 struct sockaddr *addr_ipv6;
783
787 socklen_t addr_len_ipv6;
788
789};
790
794struct Addresses
795{
799 struct Addresses *next;
800
804 struct Addresses *prev;
805
809 struct sockaddr *addr;
810
814 socklen_t addr_len;
815
816};
817
818
822static unsigned long long max_queue_length;
823
827static struct GNUNET_PILS_Handle *pils;
828
832static struct GNUNET_STATISTICS_Handle *stats;
833
838
843
848
852static struct GNUNET_PeerIdentity my_identity;
853
857static unsigned long long rekey_max_bytes;
858
863
868
873
877static const struct GNUNET_CONFIGURATION_Handle *cfg;
878
882static struct GNUNET_NT_InterfaceScanner *is;
883
887static struct GNUNET_NAT_Handle *nat;
888
892static struct ProtoQueue *proto_head;
893
897static struct ProtoQueue *proto_tail;
898
903
907static struct Addresses *addrs_head;
908
912static struct Addresses *addrs_tail;
913
917static int addrs_lens;
918
923
927static int shutdown_running = GNUNET_NO;
928
932static int disable_v6;
933
937static unsigned int bind_port;
938
943
947static unsigned char ikm[256 / 8];
948
956static void
957listen_cb (void *cls);
958
959static void
962{
964 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
965 key.eddsa_key = *edpk;
967 pk);
968}
969
970
971static void
974{
976 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
977 key.eddsa_key = *edpk;
979}
980
981
989static void
990queue_destroy (struct Queue *queue)
991{
992 struct ListenTask *lt = NULL;
993 struct GNUNET_HashCode h_sock;
994 int sockfd;
995
996 if (NULL != queue->listen_sock)
997 {
998 sockfd = GNUNET_NETWORK_get_fd (queue->listen_sock);
999 GNUNET_CRYPTO_hash (&sockfd,
1000 sizeof(int),
1001 &h_sock);
1002
1004 }
1005
1007 "Disconnecting queue for peer `%s'\n",
1008 GNUNET_i2s (&queue->target));
1009 if (NULL != queue->rekey_monotime_sc)
1010 {
1011 GNUNET_PEERSTORE_store_cancel (queue->rekey_monotime_sc);
1012 queue->rekey_monotime_sc = NULL;
1013 }
1014 if (NULL != queue->handshake_monotime_sc)
1015 {
1016 GNUNET_PEERSTORE_store_cancel (queue->handshake_monotime_sc);
1017 queue->handshake_monotime_sc = NULL;
1018 }
1019 if (NULL != queue->handshake_ack_monotime_sc)
1020 {
1021 GNUNET_PEERSTORE_store_cancel (queue->handshake_ack_monotime_sc);
1022 queue->handshake_ack_monotime_sc = NULL;
1023 }
1024 if (NULL != queue->rekey_monotime_get)
1025 {
1026 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1027 queue->rekey_monotime_get = NULL;
1028 }
1029 if (NULL != queue->handshake_monotime_get)
1030 {
1031 GNUNET_PEERSTORE_iteration_stop (queue->handshake_monotime_get);
1032 queue->handshake_monotime_get = NULL;
1033 }
1034 if (NULL != queue->handshake_ack_monotime_get)
1035 {
1036 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1037 queue->handshake_ack_monotime_get = NULL;
1038 }
1039 if (NULL != queue->qh)
1040 {
1042 queue->qh = NULL;
1043 }
1045 GNUNET_YES ==
1048 "# queues active",
1050 GNUNET_NO);
1051 if (NULL != queue->read_task)
1052 {
1053 GNUNET_SCHEDULER_cancel (queue->read_task);
1054 queue->read_task = NULL;
1055 }
1056 if (NULL != queue->write_task)
1057 {
1058 GNUNET_SCHEDULER_cancel (queue->write_task);
1059 queue->write_task = NULL;
1060 }
1062 {
1064 "closing socket failed\n");
1065 }
1066 gcry_cipher_close (queue->in_cipher);
1067 gcry_cipher_close (queue->out_cipher);
1068 GNUNET_free (queue->address);
1069 if (0 != queue->backpressure)
1070 queue->destroyed = GNUNET_YES;
1071 else
1073
1074 if (NULL == lt)
1075 return;
1076
1077 if ((! shutdown_running) && (NULL == lt->listen_task))
1078 {
1080 "add read net listen\n");
1083 lt->listen_sock,
1084 &listen_cb,
1085 lt);
1086 }
1087 else
1088 GNUNET_free (lt);
1089}
1090
1091
1100static void
1101calculate_hmac (struct GNUNET_HashCode *hmac_secret,
1102 const void *buf,
1103 size_t buf_size,
1104 struct GNUNET_ShortHashCode *smac)
1105{
1106 struct GNUNET_HashCode mac;
1107
1108 GNUNET_CRYPTO_hmac_raw (hmac_secret,
1109 sizeof(struct GNUNET_HashCode),
1110 buf,
1111 buf_size,
1112 &mac);
1113 /* truncate to `struct GNUNET_ShortHashCode` */
1114 memcpy (smac, &mac, sizeof(struct GNUNET_ShortHashCode));
1115 /* ratchet hmac key */
1116 GNUNET_CRYPTO_hash (hmac_secret,
1117 sizeof(struct GNUNET_HashCode),
1118 hmac_secret);
1119}
1120
1121
1128static void
1129queue_finish (struct Queue *queue)
1130{
1131 struct TCPFinish fin;
1132
1133 memset (&fin, 0, sizeof(fin));
1134 fin.header.size = htons (sizeof(fin));
1135 fin.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH);
1136 calculate_hmac (&queue->out_hmac, &fin, sizeof(fin), &fin.hmac);
1137 /* if there is any message left in pwrite_buf, we
1138 overwrite it (possibly dropping the last message
1139 from CORE hard here) */
1140 memcpy (queue->pwrite_buf, &fin, sizeof(fin));
1141 queue->pwrite_off = sizeof(fin);
1142 /* This flag will ensure that #queue_write() no longer
1143 notifies CORE about the possibility of sending
1144 more data, and that #queue_write() will call
1145 #queue_destroy() once the @c fin was fully written. */
1146 queue->finishing = GNUNET_YES;
1147}
1148
1149
1155static void
1156queue_read (void *cls);
1157
1158
1166static void
1167core_read_finished_cb (void *cls, int success)
1168{
1169 struct Queue *queue = cls;
1170 if (GNUNET_OK != success)
1172 "# messages lost in communicator API towards CORE",
1173 1,
1174 GNUNET_NO);
1175 if (NULL == queue)
1176 return;
1177
1179 "backpressure %u\n",
1180 queue->backpressure);
1181
1182 queue->backpressure--;
1183 /* handle deferred queue destruction */
1184 if ((queue->destroyed) && (0 == queue->backpressure))
1185 {
1187 return;
1188 }
1189 else if (GNUNET_YES != queue->destroyed)
1190 {
1191 queue->timeout =
1193 );
1194 /* possibly unchoke reading, now that CORE made progress */
1195 if (NULL == queue->read_task)
1196 queue->read_task =
1198 queue->timeout),
1199 queue->sock,
1200 &queue_read,
1201 queue);
1202 }
1203}
1204
1205
1215static void
1217 const void *plaintext,
1218 size_t plaintext_len)
1219{
1220 const struct GNUNET_MessageHeader *hdr = plaintext;
1221 int ret;
1222
1224 "pass message from %s to core\n",
1225 GNUNET_i2s (&queue->target));
1226
1227 if (ntohs (hdr->size) != plaintext_len)
1228 {
1229 /* NOTE: If we ever allow multiple CORE messages in one
1230 BOX, this will have to change! */
1231 GNUNET_break (0);
1232 return;
1233 }
1235 &queue->target,
1236 hdr,
1239 queue);
1241 "passed to core\n");
1242 if (GNUNET_OK == ret)
1243 queue->backpressure++;
1244 GNUNET_break (GNUNET_NO != ret); /* backpressure not working!? */
1245 if (GNUNET_SYSERR == ret)
1247 "# bytes lost due to CORE not running",
1248 plaintext_len,
1249 GNUNET_NO);
1250}
1251
1252
1262static void
1263setup_cipher (const struct GNUNET_ShortHashCode *prk,
1264 const struct GNUNET_PeerIdentity *pid,
1265 gcry_cipher_hd_t *cipher,
1266 struct GNUNET_HashCode *hmac_key)
1267{
1268 char key[256 / 8];
1269 char ctr[128 / 8];
1270
1271 GNUNET_assert (0 == gcry_cipher_open (cipher,
1272 GCRY_CIPHER_AES256 /* low level: go for speed */
1273 ,
1274 GCRY_CIPHER_MODE_CTR,
1275 0 /* flags */));
1278 sizeof(key),
1279 prk,
1280 "gnunet-communicator-tcp-key",
1281 strlen (
1282 "gnunet-communicator-tcp-key"),
1283 NULL,
1284 0));
1285 GNUNET_assert (0 == gcry_cipher_setkey (*cipher, key, sizeof(key)));
1288 sizeof(ctr),
1289 prk,
1290 "gnunet-communicator-tcp-ctr",
1291 strlen (
1292 "gnunet-communicator-tcp-ctr"),
1293 NULL,
1294 0));
1295 gcry_cipher_setctr (*cipher, ctr, sizeof(ctr));
1297 GNUNET_CRYPTO_hkdf_expand (hmac_key,
1298 sizeof(struct GNUNET_HashCode),
1299 prk,
1300 "gnunet-communicator-hmac",
1301 strlen ("gnunet-communicator-hmac"),
1302 NULL,
1303 0));
1304}
1305
1306
1312static void
1313rekey_monotime_store_cb (void *cls, int success)
1314{
1315 struct Queue *queue = cls;
1316 if (GNUNET_OK != success)
1317 {
1319 "Failed to store rekey monotonic time in PEERSTORE!\n");
1320 }
1321 queue->rekey_monotime_sc = NULL;
1322 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1323}
1324
1325
1333static void
1334rekey_monotime_cb (void *cls,
1335 const struct GNUNET_PEERSTORE_Record *record,
1336 const char *emsg)
1337{
1338 struct Queue *queue = cls;
1339 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1340 struct GNUNET_TIME_Absolute mt;
1341 const struct GNUNET_PeerIdentity *pid;
1342 struct GNUNET_TIME_AbsoluteNBO *rekey_monotonic_time;
1343
1344 (void) emsg;
1345
1346 rekey_monotonic_time = &queue->rekey_monotonic_time;
1347 pid = &queue->target;
1348 if (NULL == record)
1349 {
1350 queue->rekey_monotime_get = NULL;
1351 return;
1352 }
1353 if (sizeof(*mtbe) != record->value_size)
1354 {
1355 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1356 GNUNET_break (0);
1357 return;
1358 }
1359 mtbe = record->value;
1360 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1361 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1362 queue->rekey_monotonic_time).abs_value_us)
1363 {
1365 "Queue from %s dropped, rekey monotime in the past\n",
1366 GNUNET_i2s (&queue->target));
1367 GNUNET_break (0);
1368 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1369 queue->rekey_monotime_get = NULL;
1370 // FIXME: Why should we try to gracefully finish here??
1372 return;
1373 }
1374 queue->rekey_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
1375 "transport_tcp_communicator",
1376 pid,
1378 rekey_monotonic_time,
1379 sizeof(*
1380 rekey_monotonic_time),
1384 queue);
1385}
1386
1387
1394static void
1396 const struct GNUNET_CRYPTO_HpkeEncapsulation *c,
1397 struct Queue *queue)
1398{
1399 struct GNUNET_ShortHashCode k;
1400
1402 c,
1403 &k);
1404 setup_cipher (&k, &my_identity, &queue->in_cipher, &queue->in_hmac);
1405}
1406
1407
1414static void
1415setup_in_cipher (const struct GNUNET_CRYPTO_HpkeEncapsulation *ephemeral,
1416 struct Queue *queue)
1417{
1418 struct GNUNET_ShortHashCode k;
1419
1421 setup_cipher (&k, &my_identity, &queue->in_cipher, &queue->in_hmac);
1422}
1423
1424
1433static void
1434do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
1435{
1436 struct TcpRekeySignature thp;
1437
1439 thp.purpose.size = htonl (sizeof(thp));
1441 "do_rekey size %u\n",
1442 thp.purpose.size);
1443 thp.sender = queue->target;
1445 "sender %s\n",
1446 GNUNET_p2s (&thp.sender.public_key));
1448 "sender %s\n",
1449 GNUNET_p2s (&queue->target.public_key));
1450 thp.receiver = my_identity;
1452 "receiver %s\n",
1453 GNUNET_p2s (&thp.receiver.public_key));
1454 thp.ephemeral = rekey->ephemeral;
1456 "ephemeral %s\n",
1457 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
1458 );
1459 thp.monotonic_time = rekey->monotonic_time;
1461 "time %s\n",
1463 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1464 GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp)));
1465 if (GNUNET_OK !=
1468 &thp,
1469 &rekey->sender_sig,
1470 &queue->target.public_key))
1471 {
1472 GNUNET_break (0);
1473 // FIXME Why should we try to gracefully finish here?
1475 return;
1476 }
1477 queue->rekey_monotonic_time = rekey->monotonic_time;
1478 queue->rekey_monotime_get = GNUNET_PEERSTORE_iteration_start (peerstore,
1479 "transport_tcp_communicator",
1480 &queue->target,
1482 &
1484 queue);
1485 gcry_cipher_close (queue->in_cipher);
1486 queue->rekeyed = GNUNET_YES;
1487 setup_in_cipher (&rekey->ephemeral, queue);
1488}
1489
1490
1496static void
1497handshake_ack_monotime_store_cb (void *cls, int success)
1498{
1499 struct Queue *queue = cls;
1500
1501 if (GNUNET_OK != success)
1502 {
1504 "Failed to store handshake ack monotonic time in PEERSTORE!\n");
1505 }
1506 queue->handshake_ack_monotime_sc = NULL;
1507 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1508}
1509
1510
1518static void
1519handshake_ack_monotime_cb (void *cls,
1520 const struct GNUNET_PEERSTORE_Record *record,
1521 const char *emsg)
1522{
1523 struct Queue *queue = cls;
1524 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1525 struct GNUNET_TIME_Absolute mt;
1526 const struct GNUNET_PeerIdentity *pid;
1527 struct GNUNET_TIME_AbsoluteNBO *handshake_ack_monotonic_time;
1528
1529 (void) emsg;
1530
1531 handshake_ack_monotonic_time = &queue->handshake_ack_monotonic_time;
1532 pid = &queue->target;
1533 if (NULL == record)
1534 {
1535 queue->handshake_ack_monotime_get = NULL;
1536 return;
1537 }
1538 if (sizeof(*mtbe) != record->value_size)
1539 {
1540 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1541 GNUNET_break (0);
1542 return;
1543 }
1544 mtbe = record->value;
1545 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1546 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1547 queue->handshake_ack_monotonic_time).abs_value_us)
1548 {
1550 "Queue from %s dropped, handshake ack monotime in the past\n",
1551 GNUNET_i2s (&queue->target));
1552 GNUNET_break (0);
1553 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1554 queue->handshake_ack_monotime_get = NULL;
1555 // FIXME: Why should we try to gracefully finish here?
1557 return;
1558 }
1559 queue->handshake_ack_monotime_sc =
1561 "transport_tcp_communicator",
1562 pid,
1564 handshake_ack_monotonic_time,
1565 sizeof(*handshake_ack_monotonic_time),
1569 queue);
1570}
1571
1572
1579static void
1581 struct Queue *queue)
1582{
1583 struct TCPConfirmationAck tca;
1584 struct TcpHandshakeAckSignature thas;
1585
1587 "sending challenge\n");
1588
1589 tca.header.type = ntohs (
1591 tca.header.size = ntohs (sizeof(tca));
1592 tca.challenge = challenge;
1593 tca.sender = my_identity;
1594 tca.monotonic_time =
1596 thas.purpose.purpose = htonl (
1598 thas.purpose.size = htonl (sizeof(thas));
1599 thas.sender = my_identity;
1600 thas.receiver = queue->target;
1601 thas.monotonic_time = tca.monotonic_time;
1602 thas.challenge = tca.challenge;
1604 &thas,
1605 &tca.sender_sig);
1606 GNUNET_assert (0 ==
1607 gcry_cipher_encrypt (queue->out_cipher,
1608 &queue->cwrite_buf[queue->cwrite_off],
1609 sizeof(tca),
1610 &tca,
1611 sizeof(tca)));
1612 queue->cwrite_off += sizeof(tca);
1614 "sending challenge done\n");
1615}
1616
1617
1624static void
1626{
1627 setup_cipher (dh, &queue->target, &queue->out_cipher, &queue->out_hmac);
1629 queue->rekey_left_bytes =
1631}
1632
1633
1640static void
1641inject_rekey (struct Queue *queue)
1642{
1643 struct TCPRekey rekey;
1644 struct TcpRekeySignature thp;
1645 struct GNUNET_ShortHashCode k;
1646
1647 GNUNET_assert (0 == queue->pwrite_off);
1648 memset (&rekey, 0, sizeof(rekey));
1649 GNUNET_CRYPTO_eddsa_kem_encaps (&queue->target.public_key, &rekey.ephemeral,
1650 &k);
1652 rekey.header.size = ntohs (sizeof(rekey));
1653 rekey.monotonic_time =
1655 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1656 thp.purpose.size = htonl (sizeof(thp));
1658 "inject_rekey size %u\n",
1659 thp.purpose.size);
1660 thp.sender = my_identity;
1662 "sender %s\n",
1663 GNUNET_p2s (&thp.sender.public_key));
1664 thp.receiver = queue->target;
1666 "receiver %s\n",
1667 GNUNET_p2s (&thp.receiver.public_key));
1668 thp.ephemeral = rekey.ephemeral;
1670 "ephemeral %s\n",
1671 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
1672 );
1673 thp.monotonic_time = rekey.monotonic_time;
1675 "time %s\n",
1677 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1679 &thp,
1680 &rekey.sender_sig);
1681 calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac);
1682 /* Encrypt rekey message with 'old' cipher */
1683 GNUNET_assert (0 ==
1684 gcry_cipher_encrypt (queue->out_cipher,
1685 &queue->cwrite_buf[queue->cwrite_off],
1686 sizeof(rekey),
1687 &rekey,
1688 sizeof(rekey)));
1689 queue->cwrite_off += sizeof(rekey);
1690 /* Setup new cipher for successive messages */
1691 gcry_cipher_close (queue->out_cipher);
1692 setup_out_cipher (queue, &k);
1693}
1694
1695
1696static int
1698 const struct GNUNET_HashCode *key,
1699 void *value)
1700{
1701 struct PendingReversal *pending_reversal = value;
1702 (void) cls;
1703
1704 if (NULL != pending_reversal->timeout_task)
1705 {
1706 GNUNET_SCHEDULER_cancel (pending_reversal->timeout_task);
1707 pending_reversal->timeout_task = NULL;
1708 }
1711 key,
1712 pending_reversal));
1713 GNUNET_free (pending_reversal->in);
1714 GNUNET_free (pending_reversal);
1715 return GNUNET_OK;
1716}
1717
1718
1719static void
1720check_and_remove_pending_reversal (struct sockaddr *in, sa_family_t sa_family,
1721 struct GNUNET_PeerIdentity *sender)
1722{
1723 if (AF_INET == sa_family)
1724 {
1725 struct PendingReversal *pending_reversal;
1726 struct GNUNET_HashCode key;
1727 struct sockaddr_in *natted_address;
1728
1729 natted_address = GNUNET_memdup (in, sizeof (struct sockaddr));
1730 natted_address->sin_port = 0;
1731 GNUNET_CRYPTO_hash (natted_address,
1732 sizeof(struct sockaddr),
1733 &key);
1734
1736 &key);
1737 if (NULL != pending_reversal && (NULL == sender ||
1738 0 != memcmp (sender,
1739 &pending_reversal->target,
1740 sizeof(struct
1742 {
1744 "Removing invalid pending reversal for `%s'at `%s'\n",
1745 GNUNET_i2s (&pending_reversal->target),
1746 GNUNET_a2s (in, sizeof (struct sockaddr)));
1747 pending_reversals_delete_it (NULL, &key, pending_reversal);
1748 }
1749 GNUNET_free (natted_address);
1750 }
1751}
1752
1753
1759static void
1760free_proto_queue (struct ProtoQueue *pq)
1761{
1762 if (NULL != pq->listen_sock)
1763 {
1765 pq->listen_sock = NULL;
1766 }
1767 if (NULL != pq->read_task)
1768 {
1770 pq->read_task = NULL;
1771 }
1772 if (NULL != pq->write_task)
1773 {
1775 pq->write_task = NULL;
1776 }
1777 check_and_remove_pending_reversal (pq->address, pq->address->sa_family, NULL);
1779 GNUNET_free (pq->address);
1781 GNUNET_free (pq);
1782}
1783
1784
1791static void
1792proto_queue_write (void *cls)
1793{
1794 struct ProtoQueue *pq = cls;
1795 ssize_t sent;
1796 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In proto queue write\n");
1797 pq->write_task = NULL;
1798 if (0 != pq->write_off)
1799 {
1800 sent = GNUNET_NETWORK_socket_send (pq->sock,
1801 pq->write_buf,
1802 pq->write_off);
1804 "Sent %lu bytes to TCP queue\n", sent);
1805 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1806 {
1808 free_proto_queue (pq);
1809 return;
1810 }
1811 if (sent > 0)
1812 {
1813 size_t usent = (size_t) sent;
1814 pq->write_off -= usent;
1815 memmove (pq->write_buf,
1816 &pq->write_buf[usent],
1817 pq->write_off);
1818 }
1819 }
1820 /* do we care to write more? */
1821 if ((0 < pq->write_off))
1822 pq->write_task =
1824 pq->sock,
1826 pq);
1827}
1828
1829
1836static void
1837queue_write (void *cls)
1838{
1839 struct Queue *queue = cls;
1840 ssize_t sent;
1841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n");
1842 queue->write_task = NULL;
1843 if (0 != queue->cwrite_off)
1844 {
1845 sent = GNUNET_NETWORK_socket_send (queue->sock,
1846 queue->cwrite_buf,
1847 queue->cwrite_off);
1849 "Sent %lu bytes to TCP queue\n", sent);
1850 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1851 {
1854 return;
1855 }
1856 if (sent > 0)
1857 {
1858 size_t usent = (size_t) sent;
1859 queue->cwrite_off -= usent;
1860 memmove (queue->cwrite_buf,
1861 &queue->cwrite_buf[usent],
1862 queue->cwrite_off);
1863 queue->timeout =
1866 }
1867 }
1868 {
1869 /* can we encrypt more? (always encrypt full messages, needed
1870 such that #mq_cancel() can work!) */
1871 unsigned int we_do_not_need_to_rekey = (0 < queue->rekey_left_bytes
1872 - (queue->cwrite_off
1873 + queue->pwrite_off
1874 + sizeof (struct TCPRekey)));
1875 if (we_do_not_need_to_rekey &&
1876 (queue->pwrite_off > 0) &&
1877 (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE))
1878 {
1880 "Encrypting %lu bytes\n", queue->pwrite_off);
1881 GNUNET_assert (0 ==
1882 gcry_cipher_encrypt (queue->out_cipher,
1883 &queue->cwrite_buf[queue->cwrite_off],
1884 queue->pwrite_off,
1885 queue->pwrite_buf,
1886 queue->pwrite_off));
1887 if (queue->rekey_left_bytes > queue->pwrite_off)
1888 queue->rekey_left_bytes -= queue->pwrite_off;
1889 else
1890 queue->rekey_left_bytes = 0;
1891 queue->cwrite_off += queue->pwrite_off;
1892 queue->pwrite_off = 0;
1893 }
1894 // if ((-1 != unverified_size)&& ((0 == queue->pwrite_off) &&
1895 if (((0 == queue->rekey_left_bytes) ||
1897 queue->rekey_time).rel_value_us)) &&
1898 (((0 == queue->pwrite_off) || ! we_do_not_need_to_rekey) &&
1899 (queue->cwrite_off + sizeof (struct TCPRekey) <= BUF_SIZE)))
1900 {
1902 }
1903 }
1904 if ((0 == queue->pwrite_off) && (! queue->finishing) &&
1905 (GNUNET_YES == queue->mq_awaits_continue))
1906 {
1907 queue->mq_awaits_continue = GNUNET_NO;
1909 }
1910 /* did we just finish writing 'finish'? */
1911 if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing))
1912 {
1914 "Finishing queue\n");
1916 return;
1917 }
1918 /* do we care to write more? */
1919 if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off))
1920 queue->write_task =
1922 queue->sock,
1923 &queue_write,
1924 queue);
1925}
1926
1927
1935static size_t
1937{
1938 const struct GNUNET_MessageHeader *hdr;
1939 const struct TCPConfirmationAck *tca;
1940 const struct TCPBox *box;
1941 const struct TCPRekey *rekey;
1942 const struct TCPFinish *fin;
1943 struct TCPRekey rekeyz;
1944 struct TCPFinish finz;
1945 struct GNUNET_ShortHashCode tmac;
1946 uint16_t type;
1947 size_t size = 0;
1948 struct TcpHandshakeAckSignature thas;
1949 const struct GNUNET_CRYPTO_ChallengeNonceP challenge = queue->challenge;
1950
1952 "try handle plaintext!\n");
1953
1954 hdr = (const struct GNUNET_MessageHeader *) queue->pread_buf;
1955 if ((sizeof(*hdr) > queue->pread_off))
1956 {
1958 "Handling plaintext, not even a header!\n");
1959 return 0; /* not even a header */
1960 }
1961
1962 if ((GNUNET_YES != queue->initial_core_kx_done) && (queue->unverified_size >
1964 {
1966 "Already received data of size %lu bigger than KX size %lu!\n",
1967 queue->unverified_size,
1969 GNUNET_break_op (0);
1971 return 0;
1972 }
1973
1974 type = ntohs (hdr->type);
1975 switch (type)
1976 {
1978 tca = (const struct TCPConfirmationAck *) queue->pread_buf;
1980 "start processing ack\n");
1981 if (sizeof(*tca) > queue->pread_off)
1982 {
1984 "Handling plaintext size of tca greater than pread offset.\n")
1985 ;
1986 return 0;
1987 }
1988 if (ntohs (hdr->size) != sizeof(*tca))
1989 {
1991 "Handling plaintext size does not match message type.\n");
1992 GNUNET_break_op (0);
1994 return 0;
1995 }
1996
1997 thas.purpose.purpose = htonl (
1999 thas.purpose.size = htonl (sizeof(thas));
2000 thas.sender = tca->sender;
2001 thas.receiver = my_identity;
2002 thas.monotonic_time = tca->monotonic_time;
2003 thas.challenge = tca->challenge;
2004
2007 &thas,
2008 &tca->sender_sig,
2009 &tca->sender.public_key))
2010 {
2012 "Verification of signature failed!\n");
2013 GNUNET_break (0);
2015 return 0;
2016 }
2017 if (0 != GNUNET_memcmp (&tca->challenge, &challenge))
2018 {
2020 "Challenge in TCPConfirmationAck not correct!\n");
2021 GNUNET_break (0);
2023 return 0;
2024 }
2025
2026 queue->handshake_ack_monotime_get = GNUNET_PEERSTORE_iteration_start (
2027 peerstore,
2028 "transport_tcp_communicator",
2029 &queue->target,
2032 queue);
2033
2035 "Handling plaintext, ack processed!\n");
2036
2038 {
2039 send_challenge (queue->challenge_received, queue);
2040 queue->write_task =
2042 queue->sock,
2043 &queue_write,
2044 queue);
2045 }
2046 else if (GNUNET_TRANSPORT_CS_OUTBOUND == queue->cs)
2047 {
2049 queue->address->sa_family, NULL);
2050 }
2051
2056 queue->initial_core_kx_done = GNUNET_YES;
2057
2058 {
2059 char *foreign_addr;
2060
2061 switch (queue->address->sa_family)
2062 {
2063 case AF_INET:
2064 GNUNET_asprintf (&foreign_addr,
2065 "%s-%s",
2067 GNUNET_a2s (queue->address, queue->address_len));
2068 break;
2069
2070 case AF_INET6:
2071 GNUNET_asprintf (&foreign_addr,
2072 "%s-%s",
2074 GNUNET_a2s (queue->address, queue->address_len));
2075 break;
2076
2077 default:
2078 GNUNET_assert (0);
2079 }
2081 &queue->target,
2082 foreign_addr,
2083 UINT16_MAX, /* no MTU */
2085 0, /* Priority */
2086 queue->nt,
2087 queue->cs,
2088 queue->mq);
2089
2090 GNUNET_free (foreign_addr);
2091 }
2092
2093 size = ntohs (hdr->size);
2094 break;
2096 /* Special case: header size excludes box itself! */
2097 box = (const struct TCPBox *) queue->pread_buf;
2098 if (ntohs (hdr->size) + sizeof(struct TCPBox) > queue->pread_off)
2099 return 0;
2100 calculate_hmac (&queue->in_hmac, &box[1], ntohs (hdr->size), &tmac);
2101 if (0 != memcmp (&tmac, &box->hmac, sizeof(tmac)))
2102 {
2103 GNUNET_break_op (0);
2105 return 0;
2106 }
2107 pass_plaintext_to_core (queue, (const void *) &box[1], ntohs (hdr->size));
2108 size = ntohs (hdr->size) + sizeof(*box);
2110 "Handling plaintext, box processed!\n");
2112 "# bytes decrypted with BOX",
2113 size,
2114 GNUNET_NO);
2116 "# messages decrypted with BOX",
2117 1,
2118 GNUNET_NO);
2119 break;
2120
2122 rekey = (const struct TCPRekey *) queue->pread_buf;
2123 if (sizeof(*rekey) > queue->pread_off)
2124 return 0;
2125 if (ntohs (hdr->size) != sizeof(*rekey))
2126 {
2127 GNUNET_break_op (0);
2129 return 0;
2130 }
2131 rekeyz = *rekey;
2132 memset (&rekeyz.hmac, 0, sizeof(rekeyz.hmac));
2133 calculate_hmac (&queue->in_hmac, &rekeyz, sizeof(rekeyz), &tmac);
2134 if (0 != memcmp (&tmac, &rekey->hmac, sizeof(tmac)))
2135 {
2136 GNUNET_break_op (0);
2138 return 0;
2139 }
2140 do_rekey (queue, rekey);
2141 size = ntohs (hdr->size);
2143 "Handling plaintext, rekey processed!\n");
2145 "# rekeying successful",
2146 1,
2147 GNUNET_NO);
2148 break;
2149
2151 fin = (const struct TCPFinish *) queue->pread_buf;
2152 if (sizeof(*fin) > queue->pread_off)
2153 return 0;
2154 if (ntohs (hdr->size) != sizeof(*fin))
2155 {
2156 GNUNET_break_op (0);
2158 return 0;
2159 }
2160 finz = *fin;
2161 memset (&finz.hmac, 0, sizeof(finz.hmac));
2162 calculate_hmac (&queue->in_hmac, &finz, sizeof(finz), &tmac);
2163 if (0 != memcmp (&tmac, &fin->hmac, sizeof(tmac)))
2164 {
2165 GNUNET_break_op (0);
2167 return 0;
2168 }
2169 /* handle FINISH by destroying queue */
2172 "Handling plaintext, finish processed!\n");
2173 break;
2174
2175 default:
2177 "Handling plaintext, nothing processed!\n");
2178 GNUNET_break_op (0);
2180 return 0;
2181 }
2182 GNUNET_assert (0 != size);
2183 if (-1 != queue->unverified_size)
2184 queue->unverified_size += size;
2185 return size;
2186}
2187
2188
2194static void
2195queue_read (void *cls)
2196{
2197 struct Queue *queue = cls;
2198 struct GNUNET_TIME_Relative left;
2199 ssize_t rcvd;
2200
2201 queue->read_task = NULL;
2202 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2203 &queue->cread_buf[queue->cread_off],
2204 BUF_SIZE - queue->cread_off);
2206 "Received %zd bytes from TCP queue\n", rcvd);
2207 if (-1 == rcvd)
2208 {
2209 if ((EAGAIN != errno) && (EINTR != errno))
2210 {
2213 return;
2214 }
2215 /* try again */
2216 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2217 if (0 != left.rel_value_us)
2218 {
2219 queue->read_task =
2221 return;
2222 }
2224 "Queue %p was idle for %s, disconnecting\n",
2225 queue,
2228 GNUNET_YES));
2230 return;
2231 }
2232 if (0 == rcvd)
2233 {
2234 /* Orderly shutdown of connection */
2236 "Socket for queue %p seems to have been closed\n", queue);
2238 return;
2239 }
2240 queue->timeout =
2242 queue->cread_off += rcvd;
2243 while ((queue->pread_off < sizeof(queue->pread_buf)) &&
2244 (queue->cread_off > 0))
2245 {
2246 size_t max = GNUNET_MIN (sizeof(queue->pread_buf) - queue->pread_off,
2247 queue->cread_off);
2248 size_t done;
2249 size_t total;
2250 size_t old_pread_off = queue->pread_off;
2251
2252 GNUNET_assert (0 ==
2253 gcry_cipher_decrypt (queue->in_cipher,
2254 &queue->pread_buf[queue->pread_off],
2255 max,
2256 queue->cread_buf,
2257 max));
2258 queue->pread_off += max;
2259 total = 0;
2260 while (0 != (done = try_handle_plaintext (queue)))
2261 {
2262 /* 'done' bytes of plaintext were used, shift buffer */
2263 GNUNET_assert (done <= queue->pread_off);
2264 /* NOTE: this memmove() could possibly sometimes be
2265 avoided if we pass 'total' into try_handle_plaintext()
2266 and use it at an offset into the buffer there! */
2267 memmove (queue->pread_buf,
2268 &queue->pread_buf[done],
2269 queue->pread_off - done);
2270 queue->pread_off -= done;
2271 total += done;
2272 /* The last plaintext was a rekey, abort for now */
2273 if (GNUNET_YES == queue->rekeyed)
2274 break;
2275 }
2276 /* when we encounter a rekey message, the decryption above uses the
2277 wrong key for everything after the rekey; in that case, we have
2278 to re-do the decryption at 'total' instead of at 'max'.
2279 However, we have to take into account that the plaintext buffer may have
2280 already contained data and not jumped too far ahead in the ciphertext.
2281 If there is no rekey and the last message is incomplete (max > total),
2282 it is safe to keep the decryption so we shift by 'max' */
2283 if (GNUNET_YES == queue->rekeyed)
2284 {
2285 max = total - old_pread_off;
2286 queue->rekeyed = GNUNET_NO;
2287 queue->pread_off = 0;
2288 }
2289 memmove (queue->cread_buf, &queue->cread_buf[max], queue->cread_off - max);
2290 queue->cread_off -= max;
2291 }
2292 if (BUF_SIZE == queue->cread_off)
2293 return; /* buffer full, suspend reading */
2294 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2295 if (0 != left.rel_value_us)
2296 {
2297 if (max_queue_length > queue->backpressure)
2298 {
2299 /* continue reading */
2300 queue->read_task =
2302 }
2303 return;
2304 }
2306 "Queue %p was idle for %s, disconnecting\n",
2307 queue,
2310 GNUNET_YES));
2312}
2313
2314
2322static struct sockaddr *
2323tcp_address_to_sockaddr_numeric_v6 (socklen_t *sock_len,
2324 struct sockaddr_in6 v6,
2325 unsigned int port)
2326{
2327 struct sockaddr *in;
2328
2329 v6.sin6_family = AF_INET6;
2330 v6.sin6_port = htons ((uint16_t) port);
2331#if HAVE_SOCKADDR_IN_SIN_LEN
2332 v6.sin6_len = sizeof(struct sockaddr_in6);
2333#endif
2334 v6.sin6_flowinfo = 0;
2335 v6.sin6_scope_id = 0;
2336 in = GNUNET_memdup (&v6, sizeof(v6));
2337 *sock_len = sizeof(struct sockaddr_in6);
2338
2339 return in;
2340}
2341
2342
2350static struct sockaddr *
2351tcp_address_to_sockaddr_numeric_v4 (socklen_t *sock_len,
2352 struct sockaddr_in v4,
2353 unsigned int port)
2354{
2355 struct sockaddr *in;
2356
2357 v4.sin_family = AF_INET;
2358 v4.sin_port = htons ((uint16_t) port);
2359#if HAVE_SOCKADDR_IN_SIN_LEN
2360 v4.sin_len = sizeof(struct sockaddr_in);
2361#endif
2362 in = GNUNET_memdup (&v4, sizeof(v4));
2363 *sock_len = sizeof(struct sockaddr_in);
2364 return in;
2365}
2366
2367
2374static struct PortOnlyIpv4Ipv6 *
2375tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port)
2376{
2377 struct PortOnlyIpv4Ipv6 *po;
2378 struct sockaddr_in *i4;
2379 struct sockaddr_in6 *i6;
2380 socklen_t sock_len_ipv4;
2381 socklen_t sock_len_ipv6;
2382
2383 /* interpreting value as just a PORT number */
2384 if (*port > UINT16_MAX)
2385 {
2387 "BINDTO specification `%s' invalid: value too large for port\n",
2388 bindto);
2389 return NULL;
2390 }
2391
2392 po = GNUNET_new (struct PortOnlyIpv4Ipv6);
2393
2394 if (GNUNET_YES == disable_v6)
2395 {
2396 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2397 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2398 *port);
2399 po->addr_len_ipv4 = sock_len_ipv4;
2400 }
2401 else
2402 {
2403
2404 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2405 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2406 *port);
2407 po->addr_len_ipv4 = sock_len_ipv4;
2408
2409 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
2410 po->addr_ipv6 = tcp_address_to_sockaddr_numeric_v6 (&sock_len_ipv6, *i6,
2411 *port);
2412
2413 po->addr_len_ipv6 = sock_len_ipv6;
2414
2415 GNUNET_free (i6);
2416 }
2417
2418 GNUNET_free (i4);
2419
2420 return po;
2421}
2422
2423
2430static char *
2431extract_address (const char *bindto)
2432{
2433 char *addr;
2434 char *start;
2435 char *token;
2436 char *cp;
2437 char *rest = NULL;
2438
2440 "extract address with bindto %s\n",
2441 bindto);
2442
2443 if (NULL == bindto)
2445 "bindto is NULL\n");
2446
2447 cp = GNUNET_strdup (bindto);
2448
2450 "extract address 2\n");
2451
2452 start = cp;
2453 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
2454 {
2455 start++; /* skip over '['*/
2456 cp[strlen (cp) - 1] = '\0'; /* eat ']'*/
2457 addr = GNUNET_strdup (start);
2458 }
2459 else
2460 {
2461 token = strtok_r (cp, "]", &rest);
2462 if (strlen (bindto) == strlen (token))
2463 {
2464 token = strtok_r (cp, ":", &rest);
2465 addr = GNUNET_strdup (token);
2466 }
2467 else
2468 {
2469 token++;
2470 addr = GNUNET_strdup (token);
2471 }
2472 }
2473
2475 "tcp address: %s\n",
2476 addr);
2477 GNUNET_free (cp);
2478 return addr;
2479}
2480
2481
2488static unsigned int
2489extract_port (const char *addr_and_port)
2490{
2491 unsigned int port;
2492 char dummy[2];
2493 char *token;
2494 char *addr;
2495 char *colon;
2496 char *cp;
2497 char *rest = NULL;
2498
2499 if (NULL != addr_and_port)
2500 {
2501 cp = GNUNET_strdup (addr_and_port);
2502 token = strtok_r (cp, "]", &rest);
2503 if (strlen (addr_and_port) == strlen (token))
2504 {
2505 colon = strrchr (cp, ':');
2506 if (NULL == colon)
2507 {
2508 GNUNET_free (cp);
2509 return 0;
2510 }
2511 addr = colon;
2512 addr++;
2513 }
2514 else
2515 {
2516 token = strtok_r (NULL, "]", &rest);
2517 if (NULL == token)
2518 {
2519 GNUNET_free (cp);
2520 return 0;
2521 }
2522 else
2523 {
2524 addr = token;
2525 addr++;
2526 }
2527 }
2528
2529
2530 if (1 == sscanf (addr, "%u%1s", &port, dummy))
2531 {
2532 /* interpreting value as just a PORT number */
2533 if (port > UINT16_MAX)
2534 {
2536 "Port `%u' invalid: value too large for port\n",
2537 port);
2538 GNUNET_free (cp);
2539 return 0;
2540 }
2541 }
2542 else
2543 {
2545 "BINDTO specification invalid: last ':' not followed by number\n");
2546 GNUNET_free (cp);
2547 return 0;
2548 }
2549 GNUNET_free (cp);
2550 }
2551 else
2552 {
2554 "return 0\n");
2555 /* interpret missing port as 0, aka pick any free one */
2556 port = 0;
2557 }
2558
2559 return port;
2560}
2561
2562
2570static struct sockaddr *
2571tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
2572{
2573 struct sockaddr *in;
2574 unsigned int port;
2575 struct sockaddr_in v4;
2576 struct sockaddr_in6 v6;
2577 char *start;
2578
2579 memset (&v4, 0, sizeof(v4));
2580 start = extract_address (bindto);
2581 GNUNET_assert (NULL != start);
2583 "start %s\n",
2584 start);
2585
2587 "!bindto %s\n",
2588 bindto);
2589
2590
2591 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
2592 {
2593 port = extract_port (bindto);
2594
2596 "port %u\n",
2597 port);
2598
2599 in = tcp_address_to_sockaddr_numeric_v4 (sock_len, v4, port);
2600 }
2601 else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
2602 {
2603 port = extract_port (bindto);
2604 in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port);
2605 }
2606 else
2607 {
2608 GNUNET_assert (0);
2609 }
2610
2612 return in;
2613}
2614
2615
2624static void
2625mq_send (struct GNUNET_MQ_Handle *mq,
2626 const struct GNUNET_MessageHeader *msg,
2627 void *impl_state)
2628{
2629 struct Queue *queue = impl_state;
2630 uint16_t msize = ntohs (msg->size);
2631 struct TCPBox box;
2633 "In MQ send. Queue finishing: %s; write task running: %s\n",
2634 (GNUNET_YES == queue->finishing) ? "yes" : "no",
2635 (NULL == queue->write_task) ? "yes" : "no");
2636 GNUNET_assert (mq == queue->mq);
2637 queue->mq_awaits_continue = GNUNET_YES;
2638 if (GNUNET_YES == queue->finishing)
2639 return; /* this queue is dying, drop msg */
2640 GNUNET_assert (0 == queue->pwrite_off);
2641 box.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX);
2642 box.header.size = htons (msize);
2643 calculate_hmac (&queue->out_hmac, msg, msize, &box.hmac);
2644 memcpy (&queue->pwrite_buf[queue->pwrite_off], &box, sizeof(box));
2645 queue->pwrite_off += sizeof(box);
2646 memcpy (&queue->pwrite_buf[queue->pwrite_off], msg, msize);
2647 queue->pwrite_off += msize;
2649 "%lu bytes of plaintext to send\n", queue->pwrite_off);
2650 GNUNET_assert (NULL != queue->sock);
2651 if (NULL == queue->write_task)
2652 queue->write_task =
2654 queue->sock,
2655 &queue_write,
2656 queue);
2657}
2658
2659
2668static void
2669mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state)
2670{
2671 struct Queue *queue = impl_state;
2672
2673 if (mq == queue->mq)
2674 {
2675 queue->mq = NULL;
2677 }
2678}
2679
2680
2687static void
2688mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
2689{
2690 struct Queue *queue = impl_state;
2691
2692 GNUNET_assert (0 != queue->pwrite_off);
2693 queue->pwrite_off = 0;
2694}
2695
2696
2706static void
2707mq_error (void *cls, enum GNUNET_MQ_Error error)
2708{
2709 struct Queue *queue = cls;
2710
2712 "MQ error in queue to %s: %d\n",
2713 GNUNET_i2s (&queue->target),
2714 (int) error);
2716}
2717
2718
2726static void
2727boot_queue (struct Queue *queue)
2728{
2729 queue->nt =
2730 GNUNET_NT_scanner_get_type (is, queue->address, queue->address_len);
2732 queue_map,
2733 &queue->key,
2734 queue,
2737 "# queues active",
2739 GNUNET_NO);
2740 queue->timeout =
2743 &mq_destroy,
2744 &mq_cancel,
2745 queue,
2746 NULL,
2747 &mq_error,
2748 queue);
2749}
2750
2751
2762static void
2763transmit_kx (struct Queue *queue,
2764 const struct GNUNET_CRYPTO_HpkeEncapsulation *c)
2765{
2766 struct TcpHandshakeSignature ths;
2767 struct TCPConfirmation tc;
2768
2769 memcpy (queue->cwrite_buf, c, sizeof(*c));
2770 queue->cwrite_off = sizeof(*c);
2771 /* compute 'tc' and append in encrypted format to cwrite_buf */
2772 tc.sender = my_identity;
2773 tc.monotonic_time =
2776 &tc.challenge,
2777 sizeof(tc.challenge));
2778 ths.purpose.purpose = htonl (
2780 ths.purpose.size = htonl (sizeof(ths));
2781 ths.sender = my_identity;
2782 ths.receiver = queue->target;
2783 ths.ephemeral = *c;
2784 ths.monotonic_time = tc.monotonic_time;
2785 ths.challenge = tc.challenge;
2787 &ths,
2788 &tc.sender_sig);
2789 GNUNET_assert (0 ==
2790 gcry_cipher_encrypt (queue->out_cipher,
2791 &queue->cwrite_buf[queue->cwrite_off],
2792 sizeof(tc),
2793 &tc,
2794 sizeof(tc)));
2795 queue->challenge = tc.challenge;
2796 queue->cwrite_off += sizeof(tc);
2797
2799 "handshake written\n");
2800}
2801
2802
2810static void
2812{
2814 struct GNUNET_ShortHashCode k;
2815
2817 &c, &k);
2818 setup_out_cipher (queue, &k);
2819 transmit_kx (queue, &c);
2820}
2821
2822
2828static void
2829handshake_monotime_store_cb (void *cls, int success)
2830{
2831 struct Queue *queue = cls;
2832 if (GNUNET_OK != success)
2833 {
2835 "Failed to store handshake monotonic time in PEERSTORE!\n");
2836 }
2837 queue->handshake_monotime_sc = NULL;
2838 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
2839}
2840
2841
2849static void
2850handshake_monotime_cb (void *cls,
2851 const struct GNUNET_PEERSTORE_Record *record,
2852 const char *emsg)
2853{
2854 struct Queue *queue = cls;
2855 struct GNUNET_TIME_AbsoluteNBO *mtbe;
2856 struct GNUNET_TIME_Absolute mt;
2857 const struct GNUNET_PeerIdentity *pid;
2858 struct GNUNET_TIME_AbsoluteNBO *handshake_monotonic_time;
2859
2860 (void) emsg;
2861
2862 handshake_monotonic_time = &queue->handshake_monotonic_time;
2863 pid = &queue->target;
2865 "tcp handshake with us %s\n",
2867 if (NULL == record)
2868 {
2869 queue->handshake_monotime_get = NULL;
2870 return;
2871 }
2873 "tcp handshake from peer %s\n",
2874 GNUNET_i2s (pid));
2875 if (sizeof(*mtbe) != record->value_size)
2876 {
2877 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
2878 GNUNET_break (0);
2879 return;
2880 }
2881 mtbe = record->value;
2882 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
2883 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
2884 queue->handshake_monotonic_time).abs_value_us)
2885 {
2887 "Queue from %s dropped, handshake monotime in the past\n",
2888 GNUNET_i2s (&queue->target));
2889 GNUNET_break (0);
2890 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
2891 queue->handshake_ack_monotime_get = NULL;
2893 return;
2894 }
2895 queue->handshake_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
2896 "transport_tcp_communicator",
2897 pid,
2899 handshake_monotonic_time,
2900 sizeof(*
2901 handshake_monotonic_time),
2904 &
2906 queue);
2907}
2908
2909
2921static int
2923 struct TCPConfirmation *tc,
2924 char *ibuf)
2925{
2926 struct TcpHandshakeSignature ths;
2928
2930 0 ==
2931 gcry_cipher_decrypt (queue->in_cipher,
2932 tc,
2933 sizeof(*tc),
2934 &ibuf[sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)],
2935 sizeof(*tc)));
2936 ths.purpose.purpose = htonl (
2938 ths.purpose.size = htonl (sizeof(ths));
2939 ths.sender = tc->sender;
2940 ths.receiver = my_identity;
2941 memcpy (&ths.ephemeral, ibuf, sizeof(struct GNUNET_CRYPTO_EcdhePublicKey));
2942 ths.monotonic_time = tc->monotonic_time;
2943 ths.challenge = tc->challenge;
2946 &ths,
2947 &tc->sender_sig,
2948 &tc->sender.public_key);
2949 if (GNUNET_YES == ret)
2950 queue->handshake_monotime_get =
2952 "transport_tcp_communicator",
2953 &queue->target,
2956 queue);
2957 return ret;
2958}
2959
2960
2968static void
2969queue_read_kx (void *cls)
2970{
2971 struct Queue *queue = cls;
2972 ssize_t rcvd;
2973 struct GNUNET_TIME_Relative left;
2974 struct TCPConfirmation tc;
2975
2976 queue->read_task = NULL;
2977 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2978 if (0 == left.rel_value_us)
2979 {
2981 return;
2982 }
2983 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2984 &queue->cread_buf[queue->cread_off],
2985 BUF_SIZE - queue->cread_off);
2987 "Received %lu bytes to write in buffer of size %lu for KX from queue %p (expires in %"
2988 PRIu64 ")\n",
2989 rcvd, BUF_SIZE - queue->cread_off, queue, left.rel_value_us);
2990 if (-1 == rcvd)
2991 {
2992 if ((EAGAIN != errno) && (EINTR != errno))
2993 {
2996 return;
2997 }
2998 queue->read_task =
3000 return;
3001 }
3002 if (0 == rcvd)
3003 {
3004 /* Orderly shutdown of connection */
3006 "Socket for queue %p seems to have been closed\n", queue);
3008 return;
3009 }
3010 queue->cread_off += rcvd;
3011 if (queue->cread_off < INITIAL_KX_SIZE)
3012 {
3013 /* read more */
3015 "%lu/%lu bytes of KX read. Rescheduling...\n",
3016 queue->cread_off, INITIAL_KX_SIZE);
3017 queue->read_task =
3019 return;
3020 }
3021 /* we got all the data, let's find out who we are talking to! */
3023 (const struct GNUNET_CRYPTO_HpkeEncapsulation*)
3024 queue->cread_buf,
3025 queue);
3026 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
3027 {
3029 "Invalid TCP KX received from %s\n",
3030 GNUNET_a2s (queue->address, queue->address_len));
3032 return;
3033 }
3034 if (0 !=
3035 memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
3036 {
3038 "Invalid sender in TCP KX received from %s\n",
3039 GNUNET_a2s (queue->address, queue->address_len));
3041 return;
3042 }
3043 send_challenge (tc.challenge, queue);
3044 queue->write_task =
3046 queue->sock,
3047 &queue_write,
3048 queue);
3049
3050 /* update queue timeout */
3051 queue->timeout =
3053 /* prepare to continue with regular read task immediately */
3054 memmove (queue->cread_buf,
3055 &queue->cread_buf[INITIAL_KX_SIZE],
3056 queue->cread_off - (INITIAL_KX_SIZE));
3058 "cread_off is %lu bytes before adjusting\n",
3059 queue->cread_off);
3060 queue->cread_off -= INITIAL_KX_SIZE;
3062 "cread_off set to %lu bytes\n",
3063 queue->cread_off);
3065}
3066
3067
3074static void
3075proto_read_kx (void *cls)
3076{
3077 struct ProtoQueue *pq = cls;
3078 ssize_t rcvd;
3079 struct GNUNET_TIME_Relative left;
3080 struct Queue *queue;
3081 struct TCPConfirmation tc;
3083
3084 pq->read_task = NULL;
3086 if (0 == left.rel_value_us)
3087 {
3088 free_proto_queue (pq);
3089 return;
3090 }
3091 rcvd = GNUNET_NETWORK_socket_recv (pq->sock,
3092 &pq->ibuf[pq->ibuf_off],
3093 sizeof(pq->ibuf) - pq->ibuf_off);
3095 "Proto received %lu bytes for KX\n", rcvd);
3096 if (-1 == rcvd)
3097 {
3098 if ((EAGAIN != errno) && (EINTR != errno))
3099 {
3101 free_proto_queue (pq);
3102 return;
3103 }
3104 /* try again */
3105 pq->read_task =
3107 return;
3108 }
3109 if (0 == rcvd)
3110 {
3111 /* Orderly shutdown of connection */
3113 "Socket for proto queue %p seems to have been closed\n", pq);
3114 free_proto_queue (pq);
3115 return;
3116 }
3117 pq->ibuf_off += rcvd;
3118 if (sizeof (struct TCPNATProbeMessage) == pq->ibuf_off)
3119 {
3120 struct TCPNATProbeMessage *pm = (struct TCPNATProbeMessage *) pq->ibuf;
3121
3123 &pm->clientIdentity);
3124
3125 queue = GNUNET_new (struct Queue);
3126 queue->target = pm->clientIdentity;
3127 eddsa_pub_to_hpke_key (&queue->target.public_key,
3128 &queue->target_hpke_key);
3131 }
3132 else if (pq->ibuf_off > sizeof(pq->ibuf))
3133 {
3134 /* read more */
3135 pq->read_task =
3137 return;
3138 }
3139 else
3140 {
3141 /* we got all the data, let's find out who we are talking to! */
3142 queue = GNUNET_new (struct Queue);
3144 (const struct GNUNET_CRYPTO_HpkeEncapsulation *) pq->
3145 ibuf,
3146 queue);
3147 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
3148 {
3150 "Invalid TCP KX received from %s\n",
3151 GNUNET_a2s (pq->address, pq->address_len));
3152 gcry_cipher_close (queue->in_cipher);
3154 free_proto_queue (pq);
3155 return;
3156 }
3157 queue->target = tc.sender;
3158 eddsa_pub_to_hpke_key (&queue->target.public_key,
3159 &queue->target_hpke_key);
3162 }
3163 queue->address = pq->address; /* steals reference */
3164 queue->address_len = pq->address_len;
3165 queue->listen_sock = pq->listen_sock;
3166 queue->sock = pq->sock;
3167
3169 "created queue with target %s\n",
3170 GNUNET_i2s (&queue->target));
3171
3173 "start kx proto\n");
3174
3176 boot_queue (queue);
3177 queue->read_task =
3179 queue->sock,
3180 read_task,
3181 queue);
3182 queue->write_task =
3184 queue->sock,
3185 &queue_write,
3186 queue);
3187 // TODO To early! Move it somewhere else.
3188 // send_challenge (tc.challenge, queue);
3189 queue->challenge_received = tc.challenge;
3190
3192 GNUNET_free (pq);
3193}
3194
3195
3196static struct ProtoQueue *
3198 struct sockaddr *in,
3199 socklen_t addrlen)
3200{
3201 struct ProtoQueue *pq = GNUNET_new (struct ProtoQueue);
3202
3203 if (NULL == sock)
3204 {
3205 // sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
3206 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 0);
3207 if (NULL == sock)
3208 {
3210 "socket(%d) failed: %s",
3211 in->sa_family,
3212 strerror (errno));
3213 GNUNET_free (in);
3214 GNUNET_free (pq);
3215 return NULL;
3216 }
3217 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, addrlen)) &&
3218 (errno != EINPROGRESS))
3219 {
3221 "connect to `%s' failed: %s",
3222 GNUNET_a2s (in, addrlen),
3223 strerror (errno));
3225 GNUNET_free (in);
3226 GNUNET_free (pq);
3227 return NULL;
3228 }
3229 }
3230 pq->address_len = addrlen;
3231 pq->address = in;
3233 pq->sock = sock;
3235 pq->sock,
3237 pq);
3239
3240 return pq;
3241}
3242
3243
3251static void
3252listen_cb (void *cls)
3253{
3254 struct sockaddr_storage in;
3255 socklen_t addrlen;
3256 struct GNUNET_NETWORK_Handle *sock;
3257 struct ListenTask *lt;
3258 struct sockaddr *in_addr;
3259
3261 "listen_cb\n");
3262
3263 lt = cls;
3264
3265 lt->listen_task = NULL;
3266 GNUNET_assert (NULL != lt->listen_sock);
3267 addrlen = sizeof(in);
3268 memset (&in, 0, sizeof(in));
3270 (struct sockaddr*) &in,
3271 &addrlen);
3272 if ((NULL == sock) && ((EMFILE == errno) || (ENFILE == errno)))
3273 return; /* system limit reached, wait until connection goes down */
3275 lt->listen_sock,
3276 &listen_cb,
3277 lt);
3278 if ((NULL == sock) && ((EAGAIN == errno) || (ENOBUFS == errno)))
3279 return;
3280 if (NULL == sock)
3281 {
3283 return;
3284 }
3285 in_addr = GNUNET_memdup (&in, addrlen);
3286 create_proto_queue (sock, in_addr, addrlen);
3287}
3288
3289
3290static void
3291try_connection_reversal (void *cls,
3292 const struct sockaddr *addr,
3293 socklen_t addrlen)
3294{
3295 struct TCPNATProbeMessage pm;
3296 struct ProtoQueue *pq;
3297 struct sockaddr *in_addr;
3298 (void) cls;
3299
3301 "addr->sa_family %d\n",
3302 addr->sa_family);
3304 "Try to connect back\n");
3305 in_addr = GNUNET_memdup (addr, addrlen);
3307 "in_addr->sa_family %d\n",
3308 in_addr->sa_family);
3309 pq = create_proto_queue (NULL, in_addr, addrlen);
3310 if (NULL != pq)
3311 {
3312 pm.header.size = htons (sizeof(struct TCPNATProbeMessage));
3313 pm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
3314 pm.clientIdentity = my_identity;
3315 memcpy (pq->write_buf, &pm, sizeof(struct TCPNATProbeMessage));
3316 pq->write_off = sizeof(struct TCPNATProbeMessage);
3318 pq->sock,
3320 pq);
3321 }
3322 else
3323 {
3325 "Couldn't create ProtoQueue for sending TCPNATProbeMessage\n");
3326 }
3327}
3328
3329
3330static void
3331pending_reversal_timeout (void *cls)
3332{
3333 struct sockaddr *in = cls;
3334 struct PendingReversal *pending_reversal;
3335 struct GNUNET_HashCode key;
3336
3338 sizeof(struct sockaddr),
3339 &key);
3341 &key);
3342
3343 GNUNET_assert (NULL != pending_reversal);
3344
3346 &key,
3347 pending_reversal))
3349 "No pending reversal found for address %s\n",
3350 GNUNET_a2s (in, sizeof (struct sockaddr)));
3351 GNUNET_free (pending_reversal->in);
3352 GNUNET_free (pending_reversal);
3353}
3354
3355
3374static int
3375mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
3376{
3377 struct sockaddr *in;
3378 socklen_t in_len = 0;
3379 const char *path;
3380 struct sockaddr_in *v4;
3381 struct sockaddr_in6 *v6;
3382 unsigned int is_natd = GNUNET_NO;
3383 struct GNUNET_HashCode key;
3384 struct GNUNET_HashCode queue_map_key;
3385 struct GNUNET_HashContext *hsh;
3386 struct Queue *queue;
3387
3389 "Connecting to %s at %s\n",
3390 GNUNET_i2s (peer),
3391 address);
3392 if (0 != strncmp (address,
3394 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
3395 {
3396 GNUNET_break_op (0);
3397 return GNUNET_SYSERR;
3398 }
3399 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
3400 in = tcp_address_to_sockaddr (path, &in_len);
3401
3402 if (NULL == in)
3403 {
3405 "Failed to setup TCP socket address\n");
3406 return GNUNET_SYSERR;
3407 }
3408
3410 "in %s\n",
3411 GNUNET_a2s (in, in_len));
3412
3415 GNUNET_CRYPTO_hash_context_read (hsh, peer, sizeof (*peer));
3416 GNUNET_CRYPTO_hash_context_finish (hsh, &queue_map_key);
3418
3419 if (NULL != queue)
3420 {
3422 "Queue for %s already exists or is in construction\n", address);
3423 GNUNET_free (in);
3424 return GNUNET_NO;
3425 }
3426 switch (in->sa_family)
3427 {
3428 case AF_INET:
3429 v4 = (struct sockaddr_in *) in;
3430 if (0 == v4->sin_port)
3431 {
3432 is_natd = GNUNET_YES;
3434 sizeof(struct sockaddr),
3435 &key);
3438 &key))
3439 {
3441 "There is already a request reversal for `%s'at `%s'\n",
3442 GNUNET_i2s (peer),
3443 address);
3444 GNUNET_free (in);
3445 return GNUNET_SYSERR;
3446 }
3447 }
3448 break;
3449
3450 case AF_INET6:
3451 if (GNUNET_YES == disable_v6)
3452 {
3454 "IPv6 disabled, skipping %s\n", address);
3455 GNUNET_free (in);
3456 return GNUNET_SYSERR;
3457 }
3458 v6 = (struct sockaddr_in6 *) in;
3459 if (0 == v6->sin6_port)
3460 {
3462 "Request reversal for `%s' at `%s' not possible for an IPv6 address\n",
3463 GNUNET_i2s (peer),
3464 address);
3465 GNUNET_free (in);
3466 return GNUNET_SYSERR;
3467 }
3468 break;
3469
3470 default:
3471 GNUNET_assert (0);
3472 }
3473
3474 if (GNUNET_YES == is_natd)
3475 {
3476 struct sockaddr_in local_sa;
3477 struct PendingReversal *pending_reversal;
3478
3479 memset (&local_sa, 0, sizeof(local_sa));
3480 local_sa.sin_family = AF_INET;
3481 local_sa.sin_port = htons (bind_port);
3482 /* We leave sin_address at 0, let the kernel figure it out,
3483 even if our bind() is more specific. (May want to reconsider
3484 later.) */
3485 if (GNUNET_OK != GNUNET_NAT_request_reversal (nat, &local_sa, v4))
3486 {
3488 "request reversal for `%s' at `%s' failed\n",
3489 GNUNET_i2s (peer),
3490 address);
3491 GNUNET_free (in);
3492 return GNUNET_SYSERR;
3493 }
3494 pending_reversal = GNUNET_new (struct PendingReversal);
3495 pending_reversal->in = in;
3498 &key,
3499 pending_reversal,
3501 pending_reversal->target = *peer;
3503 &
3505 in);
3507 "Created NAT WAIT connection to `%s' at `%s'\n",
3508 GNUNET_i2s (peer),
3509 GNUNET_a2s (in, sizeof (struct sockaddr)));
3510 }
3511 else
3512 {
3513 struct GNUNET_NETWORK_Handle *sock;
3514
3515 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM,
3516 IPPROTO_TCP);
3517 if (NULL == sock)
3518 {
3520 "socket(%d) failed: %s",
3521 in->sa_family,
3522 strerror (errno));
3523 GNUNET_free (in);
3524 return GNUNET_SYSERR;
3525 }
3526 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
3527 (errno != EINPROGRESS))
3528 {
3530 "connect to `%s' failed: %s",
3531 address,
3532 strerror (errno));
3534 GNUNET_free (in);
3535 return GNUNET_SYSERR;
3536 }
3537
3538 queue = GNUNET_new (struct Queue);
3539 queue->target = *peer;
3540 eddsa_pub_to_hpke_key (&queue->target.public_key, &queue->target_hpke_key);
3541 queue->key = queue_map_key;
3542 queue->address = in;
3543 queue->address_len = in_len;
3544 queue->sock = sock;
3546 boot_queue (queue);
3548 "booted queue with target %s\n",
3549 GNUNET_i2s (&queue->target));
3550 // queue->mq_awaits_continue = GNUNET_YES;
3551 queue->read_task =
3553 queue->sock,
3555 queue);
3556
3557
3559 "start kx mq_init\n");
3560
3562 queue->write_task =
3564 queue->sock,
3565 &queue_write,
3566 queue);
3567 }
3568
3569 return GNUNET_OK;
3570}
3571
3572
3581static int
3582get_lt_delete_it (void *cls,
3583 const struct GNUNET_HashCode *key,
3584 void *value)
3585{
3586 struct ListenTask *lt = value;
3587
3588 (void) cls;
3589 (void) key;
3590 if (NULL != lt->listen_task)
3591 {
3593 lt->listen_task = NULL;
3594 }
3595 if (NULL != lt->listen_sock)
3596 {
3598 lt->listen_sock = NULL;
3599 }
3600 GNUNET_free (lt);
3601 return GNUNET_OK;
3602}
3603
3604
3613static int
3614get_queue_delete_it (void *cls,
3615 const struct GNUNET_HashCode *target,
3616 void *value)
3617{
3618 struct Queue *queue = value;
3619
3620 (void) cls;
3621 (void) target;
3623 return GNUNET_OK;
3624}
3625
3626
3632static void
3633do_shutdown (void *cls)
3634{
3636 "Shutdown %s!\n",
3637 shutdown_running ? "running" : "not running");
3638
3640 return;
3641 else
3643
3644 while (NULL != proto_head)
3646 if (NULL != nat)
3647 {
3649 nat = NULL;
3650 }
3658 if (NULL != ch)
3659 {
3662 ch = NULL;
3663 }
3664 if (NULL != stats)
3665 {
3667 stats = NULL;
3668 }
3669 if (NULL != my_private_key)
3670 {
3672 my_private_key = NULL;
3673 }
3674 if (NULL != is)
3675 {
3677 is = NULL;
3678 }
3679 if (NULL != pils)
3680 {
3682 pils = NULL;
3683 }
3684 if (NULL != peerstore)
3685 {
3687 peerstore = NULL;
3688 }
3689 if (NULL != resolve_request_handle)
3690 {
3693 }
3695 "Shutdown done!\n");
3696}
3697
3698
3710static void
3711enc_notify_cb (void *cls,
3712 const struct GNUNET_PeerIdentity *sender,
3713 const struct GNUNET_MessageHeader *msg)
3714{
3715 (void) cls;
3716 (void) sender;
3717 (void) msg;
3718 GNUNET_break_op (0);
3719}
3720
3721
3735static void
3736nat_address_cb (void *cls,
3737 void **app_ctx,
3738 int add_remove,
3740 const struct sockaddr *addr,
3741 socklen_t addrlen)
3742{
3743 char *my_addr;
3745
3747 "nat address cb %s %s\n",
3748 add_remove ? "add" : "remove",
3749 GNUNET_a2s (addr, addrlen));
3750
3751 if (GNUNET_YES == add_remove)
3752 {
3754
3755 GNUNET_asprintf (&my_addr,
3756 "%s-%s",
3758 GNUNET_a2s (addr, addrlen));
3759 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3760 ai =
3762 my_addr,
3763 nt,
3765 GNUNET_free (my_addr);
3766 *app_ctx = ai;
3767 }
3768 else
3769 {
3770 ai = *app_ctx;
3772 *app_ctx = NULL;
3773 }
3774}
3775
3776
3780static void
3781add_addr (struct sockaddr *in, socklen_t in_len)
3782{
3783
3784 struct Addresses *saddrs;
3785
3787 "add address %s\n",
3788 GNUNET_a2s (in, in_len));
3789
3790 saddrs = GNUNET_new (struct Addresses);
3791 saddrs->addr = in;
3792 saddrs->addr_len = in_len;
3794
3796 "after add address %s\n",
3797 GNUNET_a2s (in, in_len));
3798
3800 "add address %s\n",
3801 GNUNET_a2s (saddrs->addr, saddrs->addr_len));
3802
3803 addrs_lens++;
3804}
3805
3806
3817static void
3818load_ikm ()
3819{
3820 char *keyfile;
3822
3823 if (GNUNET_OK !=
3825 "PEER",
3826 "PRIVATE_KEY",
3827 &keyfile))
3828 {
3830 "PEER",
3831 "PRIVATE_KEY");
3833 return;
3834 }
3835 if (GNUNET_SYSERR ==
3837 GNUNET_YES,
3838 &key))
3839 {
3841 "Failed to setup peer's private key\n");
3842 GNUNET_free (keyfile);
3844 return;
3845 }
3846 GNUNET_free (keyfile);
3847 GNUNET_assert (sizeof ikm == sizeof key.d);
3848 memcpy (ikm, key.d, sizeof ikm);
3849}
3850
3851
3859static int
3860init_socket (struct sockaddr *addr,
3861 socklen_t in_len)
3862{
3863 struct sockaddr_storage in_sto;
3864 socklen_t sto_len;
3865 struct GNUNET_NETWORK_Handle *listen_sock;
3866 struct ListenTask *lt;
3867 int sockfd;
3868 struct GNUNET_HashCode h_sock;
3869
3870 if (NULL == addr)
3871 {
3873 "Address is NULL.\n");
3874 return GNUNET_SYSERR;
3875 }
3876
3878 "address %s\n",
3879 GNUNET_a2s (addr, in_len));
3880
3881 listen_sock =
3882 GNUNET_NETWORK_socket_create (addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
3883 if (NULL == listen_sock)
3884 {
3886 return GNUNET_SYSERR;
3887 }
3888
3889 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, addr, in_len))
3890 {
3892 GNUNET_NETWORK_socket_close (listen_sock);
3893 listen_sock = NULL;
3894 return GNUNET_SYSERR;
3895 }
3896
3897 if (GNUNET_OK !=
3898 GNUNET_NETWORK_socket_listen (listen_sock,
3899 5))
3900 {
3902 "listen");
3903 GNUNET_NETWORK_socket_close (listen_sock);
3904 listen_sock = NULL;
3905 return GNUNET_SYSERR;
3906 }
3907
3908 /* We might have bound to port 0, allowing the OS to figure it out;
3909 thus, get the real IN-address from the socket */
3910 sto_len = sizeof(in_sto);
3911
3912 if (0 != getsockname (GNUNET_NETWORK_get_fd (listen_sock),
3913 (struct sockaddr *) &in_sto,
3914 &sto_len))
3915 {
3916 memcpy (&in_sto, addr, in_len);
3917 sto_len = in_len;
3918 }
3919
3920 // addr = (struct sockaddr *) &in_sto;
3921 in_len = sto_len;
3923 "Bound to `%s'\n",
3924 GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len));
3925 if (NULL == stats)
3926 stats = GNUNET_STATISTICS_create ("communicator-tcp", cfg);
3927
3928 if (NULL == is)
3930
3931 /* start listening */
3932
3933 lt = GNUNET_new (struct ListenTask);
3934 lt->listen_sock = listen_sock;
3935
3937 listen_sock,
3938 &listen_cb,
3939 lt);
3940
3942 "creating hash\n");
3943 sockfd = GNUNET_NETWORK_get_fd (lt->listen_sock);
3944 GNUNET_CRYPTO_hash (&sockfd,
3945 sizeof(int),
3946 &h_sock);
3947
3949 "creating map\n");
3950 if (NULL == lt_map)
3952
3954 "creating map entry\n");
3957 &h_sock,
3958 lt,
3960
3962 "map entry created\n");
3963
3964 if (NULL == queue_map)
3966
3967 if (NULL == ch)
3972 &mq_init,
3973 NULL,
3975 NULL,
3976 NULL);
3977
3978 if (NULL == ch)
3979 {
3980 GNUNET_break (0);
3981 if (NULL != resolve_request_handle)
3984 return GNUNET_SYSERR;
3985 }
3986
3987 add_addr (addr, in_len);
3988 return GNUNET_OK;
3989
3990}
3991
3992
3996static void
3997nat_register ()
3998{
3999 struct sockaddr **saddrs;
4000 socklen_t *saddr_lens;
4001 int i;
4002 size_t len;
4003
4005 "starting nat register!\n");
4006 len = 0;
4007 i = 0;
4008 saddrs = GNUNET_malloc ((addrs_lens) * sizeof(struct sockaddr *));
4009 saddr_lens = GNUNET_malloc ((addrs_lens) * sizeof(socklen_t));
4010 for (struct Addresses *pos = addrs_head; NULL != pos; pos = pos->next)
4011 {
4013 "registering address %s\n",
4014 GNUNET_a2s (pos->addr, pos->addr_len));
4015
4016 saddr_lens[i] = pos->addr_len;
4017 len += saddr_lens[i];
4018 saddrs[i] = GNUNET_memdup (pos->addr, saddr_lens[i]);
4019 i++;
4020 }
4021
4023 "registering addresses %lu %lu %lu %lu\n",
4024 (addrs_lens) * sizeof(struct sockaddr *),
4025 (addrs_lens) * sizeof(socklen_t),
4026 len,
4030 IPPROTO_TCP,
4031 addrs_lens,
4032 (const struct sockaddr **) saddrs,
4033 saddr_lens,
4036 NULL /* closure */);
4037 for (i = addrs_lens - 1; i >= 0; i--)
4038 GNUNET_free (saddrs[i]);
4039 GNUNET_free (saddrs);
4040 GNUNET_free (saddr_lens);
4041
4042 if (NULL == nat)
4043 {
4044 GNUNET_break (0);
4045 if (NULL != resolve_request_handle)
4048 }
4049}
4050
4051
4059static void
4060init_socket_resolv (void *cls,
4061 const struct sockaddr *addr,
4062 socklen_t in_len)
4063{
4064 struct sockaddr_in *v4;
4065 struct sockaddr_in6 *v6;
4066 struct sockaddr *in;
4067
4068 (void) cls;
4069 if (NULL != addr)
4070 {
4071 if (AF_INET == addr->sa_family)
4072 {
4073 v4 = (struct sockaddr_in *) addr;
4074 in = tcp_address_to_sockaddr_numeric_v4 (&in_len, *v4, bind_port);// _global);
4075 }
4076 else if (AF_INET6 == addr->sa_family)
4077 {
4078 v6 = (struct sockaddr_in6 *) addr;
4079 in = tcp_address_to_sockaddr_numeric_v6 (&in_len, *v6, bind_port);// _global);
4080 }
4081 else
4082 {
4084 "Address family %u not suitable (not AF_INET %u nor AF_INET6 %u \n",
4085 addr->sa_family,
4086 AF_INET,
4087 AF_INET6);
4088 return;
4089 }
4090 init_socket (in, in_len);
4091 }
4092 else
4093 {
4095 "Address is NULL. This might be an error or the resolver finished resolving.\n");
4096 if (NULL == addrs_head)
4097 {
4099 "Resolver finished resolving, but we do not listen to an address!.\n");
4100 return;
4101 }
4102 nat_register ();
4103 }
4104}
4105
4106
4107void
4108pid_change_cb (void *cls,
4109 const struct GNUNET_HELLO_Parser *parser,
4110 const struct GNUNET_HashCode *addr_hash)
4111{
4113 "Got PID to derive from `%s':\n",
4114 GNUNET_h2s (addr_hash));
4115 if (NULL == my_private_key)
4117
4119 (uint8_t*) ikm,
4120 addr_hash,
4126}
4127
4128
4137static void
4138run (void *cls,
4139 char *const *args,
4140 const char *cfgfile,
4141 const struct GNUNET_CONFIGURATION_Handle *c)
4142{
4143 char *bindto;
4144 struct sockaddr *in;
4145 socklen_t in_len;
4146 struct sockaddr_in v4;
4147 struct sockaddr_in6 v6;
4148 char *start;
4149 unsigned int port;
4150 char dummy[2];
4151 char *rest = NULL;
4152 struct PortOnlyIpv4Ipv6 *po;
4153 socklen_t addr_len_ipv4;
4154 socklen_t addr_len_ipv6;
4155
4156 (void) cls;
4157
4159 memset (&v4,0,sizeof(struct sockaddr_in));
4160 memset (&v6,0,sizeof(struct sockaddr_in6));
4161 cfg = c;
4162 if (GNUNET_OK !=
4165 "BINDTO",
4166 &bindto))
4167 {
4170 "BINDTO");
4171 return;
4172 }
4173 if (GNUNET_OK !=
4176 "MAX_QUEUE_LENGTH",
4178 {
4180 }
4181 if (GNUNET_OK !=
4184 "REKEY_INTERVAL",
4186 {
4188 }
4189 if (GNUNET_OK !=
4192 "REKEY_MAX_BYTES",
4194 {
4196 }
4198 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
4199 (GNUNET_YES ==
4202 "DISABLE_V6")))
4203 {
4205 }
4206 load_ikm ();
4208 GNUNET_assert (NULL != pils);
4210 if (NULL == peerstore)
4211 {
4212 GNUNET_free (bindto);
4213 GNUNET_break (0);
4215 return;
4216 }
4217
4219
4220 if (1 == sscanf (bindto, "%u%1s", &bind_port, dummy))
4221 {
4225 "address po %s\n",
4227 if (NULL != po->addr_ipv4)
4228 {
4230 }
4231 if (NULL != po->addr_ipv6)
4232 {
4235 }
4236 GNUNET_free (po);
4237 nat_register ();
4238 GNUNET_free (bindto);
4239 return;
4240 }
4241
4242 start = extract_address (bindto);
4243 // FIXME: check for NULL == start...
4244 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
4245 {
4246 bind_port = extract_port (bindto);
4247
4249 init_socket (in, in_len);
4250 nat_register ();
4252 GNUNET_free (bindto);
4253 return;
4254 }
4255
4256 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
4257 {
4258 bind_port = extract_port (bindto);
4260 init_socket (in, in_len);
4261 nat_register ();
4263 GNUNET_free (bindto);
4264 return;
4265 }
4266
4267 bind_port = extract_port (bindto);
4269 ":",
4270 &rest),
4271 AF_UNSPEC,
4274 &port);
4275
4276 GNUNET_free (bindto);
4278}
4279
4280
4288int
4289main (int argc, char *const *argv)
4290{
4291 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4293 };
4294 int ret;
4295
4297 "Starting tcp communicator\n");
4298
4299 ret = (GNUNET_OK ==
4301 argc,
4302 argv,
4303 "gnunet-communicator-tcp",
4304 _ ("GNUnet TCP communicator"),
4305 options,
4306 &run,
4307 NULL))
4308 ? 0
4309 : 1;
4310 return ret;
4311}
4312
4313
4314/* end of gnunet-communicator-tcp.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MessageHeader * msg
Definition 005.c:2
int main()
Program to simulate results from GCP_get_desirability_of_path() for various plausible inputs.
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
void pid_change_cb(void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *addr_hash)
static void calculate_hmac(struct GNUNET_HashCode *hmac_secret, const void *buf, size_t buf_size, struct GNUNET_ShortHashCode *smac)
Compute mac over buf, and ratched the hmac_secret.
static void queue_finish(struct Queue *queue)
Append a 'finish' message to the outgoing transmission.
static void transmit_kx(struct Queue *queue, const struct GNUNET_CRYPTO_HpkeEncapsulation *c)
Generate and transmit our ephemeral key and the signature for the initial KX with the other peer.
static void boot_queue(struct Queue *queue)
Add the given queue to our internal data structure.
static unsigned int bind_port
The port the communicator should be assigned to.
static size_t try_handle_plaintext(struct Queue *queue)
Test if we have received a full message in plaintext.
static void pass_plaintext_to_core(struct Queue *queue, const void *plaintext, size_t plaintext_len)
We received plaintext_len bytes of plaintext on queue.
static struct sockaddr * tcp_address_to_sockaddr_numeric_v6(socklen_t *sock_len, struct sockaddr_in6 v6, unsigned int port)
Convert a struct sockaddr_in6 to astruct sockaddr *`.
static struct GNUNET_PeerIdentity my_identity
Our public key.
#define COMMUNICATOR_ADDRESS_PREFIX
Address prefix used by the communicator.
static unsigned char ikm[256/8]
The initial key material for the peer.
static void mq_destroy(struct GNUNET_MQ_Handle *mq, void *impl_state)
Signature of functions implementing the destruction of a message queue.
#define ADDRESS_VALIDITY_PERIOD
How long do we believe our addresses to remain up (before the other peer should revalidate).
static struct PortOnlyIpv4Ipv6 * tcp_address_to_sockaddr_port_only(const char *bindto, unsigned int *port)
Convert TCP bind specification to a struct PortOnlyIpv4Ipv6 *
static void setup_in_cipher(const struct GNUNET_CRYPTO_HpkeEncapsulation *ephemeral, struct Queue *queue)
Setup cipher of queue for decryption.
#define INITIAL_CORE_KX_SIZE
Size of the initial core key exchange messages.
static void do_rekey(struct Queue *queue, const struct TCPRekey *rekey)
Handle rekey message on queue.
static struct ProtoQueue * create_proto_queue(struct GNUNET_NETWORK_Handle *sock, struct sockaddr *in, socklen_t addrlen)
static int init_socket(struct sockaddr *addr, socklen_t in_len)
This method launch network interactions for each address we like to bind to.
static void try_connection_reversal(void *cls, const struct sockaddr *addr, socklen_t addrlen)
static struct GNUNET_NT_InterfaceScanner * is
Network scanner to determine network types.
static void listen_cb(void *cls)
We have been notified that our listen socket has something to read.
static void rekey_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY where...
static int disable_v6
IPv6 disabled.
static struct GNUNET_CONTAINER_MultiHashMap * pending_reversals
Map of pending reversals.
static struct GNUNET_STATISTICS_Handle * stats
For logging statistics.
static void queue_destroy(struct Queue *queue)
Functions with this signature are called whenever we need to close a queue due to a disconnect or fai...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static void enc_notify_cb(void *cls, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg)
Function called when the transport service has received an acknowledgement for this communicator (!...
static void handshake_ack_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for handshake ack monotime value is finished.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static int pending_reversals_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
static struct ProtoQueue * proto_tail
Protoqueues DLL tail.
static void queue_read_kx(void *cls)
Read from the socket of the queue until we have enough data to initialize the decryption logic and ca...
static int get_lt_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over all ListenTasks to clean up.
static void inject_rekey(struct Queue *queue)
Inject a struct TCPRekey message into the queue's plaintext buffer.
static struct GNUNET_TIME_Relative rekey_interval
The rekey interval.
#define NAT_TIMEOUT
How long until we give up on establishing an NAT connection? Must be > 4 RTT.
#define BUF_SIZE
Size of our IO buffers for ciphertext data.
#define COMMUNICATOR_CONFIG_SECTION
Configuration section used by the communicator.
static struct GNUNET_CONTAINER_MultiHashMap * queue_map
Queues (map from peer identity to struct Queue)
static void proto_read_kx(void *cls)
Read from the socket of the proto queue until we have enough data to upgrade to full queue.
static void nat_address_cb(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of ...
static struct sockaddr * tcp_address_to_sockaddr_numeric_v4(socklen_t *sock_len, struct sockaddr_in v4, unsigned int port)
Convert a struct sockaddr_in4 to astruct sockaddr *`.
static void check_and_remove_pending_reversal(struct sockaddr *in, sa_family_t sa_family, struct GNUNET_PeerIdentity *sender)
static void init_socket_resolv(void *cls, const struct sockaddr *addr, socklen_t in_len)
This method is the callback called by the resolver API, and wraps method init_socket.
static struct GNUNET_TRANSPORT_CommunicatorHandle * ch
Our environment.
static unsigned long long max_queue_length
Maximum queue length before we stop reading towards the transport service.
static void setup_cipher(const struct GNUNET_ShortHashCode *prk, const struct GNUNET_PeerIdentity *pid, gcry_cipher_hd_t *cipher, struct GNUNET_HashCode *hmac_key)
Setup cipher based on shared secret dh and decrypting peer pid.
struct GNUNET_RESOLVER_RequestHandle * resolve_request_handle
Handle for DNS lookup of bindto address.
static void nat_register()
This method reads from the DLL addrs_head to register them at the NAT service.
static void setup_out_cipher(struct Queue *queue, struct GNUNET_ShortHashCode *dh)
Setup cipher for outgoing data stream based on target and our ephemeral private key.
static int addrs_lens
Number of addresses in the DLL for register at NAT service.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Setup communicator and launch network interactions.
static struct GNUNET_CRYPTO_HpkePrivateKey my_x25519_private_key
Our private key.
static struct GNUNET_NAT_Handle * nat
Connection to NAT service.
static void pending_reversal_timeout(void *cls)
static void load_ikm()
Get the initial secret key for generating the peer id.
#define PROTO_QUEUE_TIMEOUT
How long do we wait until we must have received the initial KX?
static void queue_read(void *cls)
Queue read task.
#define REKEY_MAX_BYTES
How often do we rekey based on number of bytes transmitted? (additionally randomized).
static int get_queue_delete_it(void *cls, const struct GNUNET_HashCode *target, void *value)
Iterator over all message queues to clean up.
static void mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
#define INITIAL_KX_SIZE
Size of the initial key exchange message sent first in both directions.
static void handshake_ack_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_A...
static void eddsa_pub_to_hpke_key(struct GNUNET_CRYPTO_EddsaPublicKey *edpk, struct GNUNET_CRYPTO_HpkePublicKey *pk)
static int mq_init(void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
Function called by the transport service to initialize a message queue given address information abou...
static void proto_queue_write(void *cls)
We have been notified that our socket is ready to write.
static void eddsa_priv_to_hpke_key(struct GNUNET_CRYPTO_EddsaPrivateKey *edpk, struct GNUNET_CRYPTO_HpkePrivateKey *pk)
static void handshake_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for handshake monotime is finished.
static void send_challenge(struct GNUNET_CRYPTO_ChallengeNonceP challenge, struct Queue *queue)
Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
static void rekey_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for rekey monotime value is finished.
static char * extract_address(const char *bindto)
This Method extracts the address part of the BINDTO string.
static struct ProtoQueue * proto_head
Protoqueues DLL head.
static int shutdown_running
A flag indicating we are already doing a shutdown.
static int decrypt_and_check_tc(struct Queue *queue, struct TCPConfirmation *tc, char *ibuf)
We have received the first bytes from the other side on a queue.
#define LOG(kind,...)
#define DEFAULT_REKEY_INTERVAL
How often do we rekey based on time (at least)
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_private_key
Our private key.
static void queue_write(void *cls)
We have been notified that our socket is ready to write.
static void add_addr(struct sockaddr *in, socklen_t in_len)
This method adds addresses to the DLL, that are later register at the NAT service.
static void handshake_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE w...
static struct Addresses * addrs_head
Head of DLL with addresses we like to register at NAT service.
static struct sockaddr * tcp_address_to_sockaddr(const char *bindto, socklen_t *sock_len)
Convert TCP bind specification to a struct sockaddr *
static struct Addresses * addrs_tail
Head of DLL with addresses we like to register at NAT service.
static void setup_in_cipher_elligator(const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct Queue *queue)
Setup cipher of queue for decryption from an elligator representative.
#define DEFAULT_MAX_QUEUE_LENGTH
How many messages do we keep at most in the queue to the transport service before we start to drop (d...
static void mq_error(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
static unsigned int extract_port(const char *addr_and_port)
This Method extracts the port part of the BINDTO string.
static void mq_send(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue.
static struct GNUNET_PILS_Handle * pils
For PILS.
static void start_initial_kx_out(struct Queue *queue)
Initialize our key material for outgoing transmissions and inform the other peer about it.
static void free_proto_queue(struct ProtoQueue *pq)
Closes socket and frees memory associated with pq.
static struct GNUNET_CONTAINER_MultiHashMap * lt_map
ListenTasks (map from socket to struct ListenTask)
static unsigned long long rekey_max_bytes
The rekey byte maximum.
static void core_read_finished_cb(void *cls, int success)
Core tells us it is done processing a message that transport received on a queue with status success.
static struct GNUNET_SCHEDULER_Task * write_task
ID of write task.
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * address
GNS address for this phone.
struct GNUNET_HashCode key
The key used in the DHT.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
struct GNUNET_CRYPTO_BlindablePrivateKey pk
Private key from command line option, or NULL.
struct GNUNET_SCHEDULER_Task * read_task
static void queue(const char *label, uint32_t rd_count, struct GNUNET_GNSRECORD_Data *rd, const struct Zone *zone)
Add hostname to the list of requests to be made.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:367
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:390
void GNUNET_PILS_derive_pid(size_t seed_key_bytes, const uint8_t seed_key[seed_key_bytes], const struct GNUNET_HashCode *addrs_hash, struct GNUNET_CRYPTO_EddsaPrivateKey *outkey)
Generate the peer id from the addresses hash and the initial secret key.
Definition pils_api.c:507
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK
Signature by a peer sending back the nonce received at initial handshake.
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY
Signature used by TCP communicator rekey.
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE
Signature used by TCP communicator handshake.
void GNUNET_TRANSPORT_communicator_address_remove(struct GNUNET_TRANSPORT_AddressIdentifier *ai)
Notify transport service about an address that this communicator no longer provides for this peer.
int GNUNET_TRANSPORT_communicator_receive(struct GNUNET_TRANSPORT_CommunicatorHandle *handle, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative expected_addr_validity, GNUNET_TRANSPORT_MessageCompletedCallback cb, void *cb_cls)
Notify transport service that the communicator has received a message.
void GNUNET_TRANSPORT_communicator_mq_del(struct GNUNET_TRANSPORT_QueueHandle *qh)
Notify transport service that an MQ became unavailable due to a disconnect or timeout.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
struct GNUNET_TRANSPORT_QueueHandle * GNUNET_TRANSPORT_communicator_mq_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const struct GNUNET_PeerIdentity *peer, const char *address, uint32_t mtu, uint64_t q_len, uint32_t priority, enum GNUNET_NetworkType nt, enum GNUNET_TRANSPORT_ConnectionStatus cs, struct GNUNET_MQ_Handle *mq)
Notify transport service that a MQ became available due to an "inbound" connection or because the com...
void GNUNET_TRANSPORT_communicator_disconnect(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Disconnect from the transport service.
GNUNET_TRANSPORT_ConnectionStatus
Possible states of a connection.
struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section_name, const char *addr_prefix, enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls, GNUNET_TRANSPORT_CommunicatorNotify notify_cb, void *notify_cb_cls, GNUNET_TRANSPORT_StartBurstNotify sb)
Connect to the transport service.
struct GNUNET_TRANSPORT_AddressIdentifier * GNUNET_TRANSPORT_communicator_address_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const char *address, enum GNUNET_NetworkType nt, struct GNUNET_TIME_Relative expiration)
Notify transport service about an address that this communicator provides for this peer.
void GNUNET_TRANSPORT_communicator_address_remove_all(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Notify transport service that this communicator no longer provides all its addresses for this peer.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
@ GNUNET_TRANSPORT_CS_INBOUND
this is an inbound connection (communicator initiated)
@ GNUNET_TRANSPORT_CS_OUTBOUND
this is an outbound connection (transport initiated)
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private EdDSA key.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_elligator_kem_encaps(const struct GNUNET_CRYPTO_HpkePublicKey *pkR, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *shared_secret)
Carries out ecdh encapsulation with given public key and the private key from a freshly created ephem...
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_key_from_file(const char *filename, int do_create, struct GNUNET_CRYPTO_EddsaPrivateKey *pkey)
Create a new private key by reading it from a file.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition crypto_ecc.c:201
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_elligator_kem_decaps(const struct GNUNET_CRYPTO_HpkePrivateKey *skR, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *shared_secret)
Carries out ecdh decapsulation with own private key and the representative of the received public key...
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
#define GNUNET_CRYPTO_eddsa_sign(priv, ps, sig)
EdDSA sign a given block.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_GETOPT_OPTION_END
Marker for the end of the list of options.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hkdf_expand(void *result, size_t out_len, const struct GNUNET_ShortHashCode *prk,...)
HKDF-Expand using SHA256.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_sk_to_x25519(const struct GNUNET_CRYPTO_BlindablePrivateKey *sk, struct GNUNET_CRYPTO_HpkePrivateKey *sk_enc)
Convert a GNUnet identity key to a key sutiable for HPKE (X25519)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
GNUNET_GenericReturnValue
Named constants for return values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_pk_to_x25519(const struct GNUNET_CRYPTO_BlindablePublicKey *pk, struct GNUNET_CRYPTO_HpkePublicKey *pk_enc)
Convert a GNUnet identity key to a key sutiable for HPKE (X25519)
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
void GNUNET_CRYPTO_hmac_raw(const void *key, size_t key_len, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104) TODO: Shouldn't this be the standard hmac function and the abo...
@ GNUNET_PUBLIC_KEY_TYPE_EDDSA
EDDSA identity.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * GNUNET_e2s(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
const char * GNUNET_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition mq.c:482
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition mq.c:437
int GNUNET_NAT_request_reversal(struct GNUNET_NAT_Handle *nh, const struct sockaddr_in *local_sa, const struct sockaddr_in *remote_sa)
We learned about a peer (possibly behind NAT) so run the gnunet-nat-client to send dummy ICMP respons...
Definition nat_api.c:675
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
Definition network.c:392
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition network.c:508
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition network.c:1001
ssize_t GNUNET_NETWORK_socket_recv(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length)
Read data from a connected socket (always non-blocking).
Definition network.c:717
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:833
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_connect(const struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Connect a socket to some remote address.
Definition network.c:602
ssize_t GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc, const void *buffer, size_t length)
Send data (always non-blocking).
Definition network.c:738
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition network.c:79
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition network.c:439
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition network.c:652
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
void GNUNET_NT_scanner_done(struct GNUNET_NT_InterfaceScanner *is)
Terminate interface scanner.
Definition nt.c:428
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init(void)
Initialize the address characterization client handle.
Definition nt.c:407
enum GNUNET_NetworkType GNUNET_NT_scanner_get_type(struct GNUNET_NT_InterfaceScanner *is, const struct sockaddr *addr, socklen_t addrlen)
Returns where the address is located: loopback, LAN or WAN.
Definition nt.c:309
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE
Key used to store sender's monotonic time from handshake message.
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK
Key used to store sender's monotonic time from handshake ack message.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY
Key used to store sender's monotonic time from rekey message.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition program.c:407
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK
TCP communicator confirmation ack.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE
TCP NAT probe message, send from NAT'd peer to other peer to establish bi-directional communication.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH
TCP communicator end of stream.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX
TCP communicator payload box.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY
TCP communicator rekey message.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1511
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1582
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1304
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1277
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:599
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_monotonic(const struct GNUNET_CONFIGURATION_Handle *cfg)
Obtain the current time and make sure it is monotonically increasing.
Definition time.c:860
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:660
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define max(x, y)
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:431
void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition socks.c:330
DLL to store the addresses we like to register at NAT service.
struct Addresses * next
Kept in a DLL.
struct Addresses * prev
Kept in a DLL.
struct sockaddr * addr
Address we like to register at NAT service.
socklen_t addr_len
Length of address we like to register at NAT service.
Internal representation of the hash map.
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
Type of a nonce used for challenges.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
Private ECC key encoded for transmission.
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
A public key used for decryption.
A public key used for encryption.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
Definition of a command line option.
Context for parsing HELLOs.
Definition hello-uri.c:232
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Header for all communications.
Handle for active NAT registrations.
Definition nat_api.c:72
handle to a socket
Definition network.c:53
Handle to the interface scanner.
Definition nt.c:104
Handle to the PEERSTORE service.
Context for a iterate request.
Context for a store request.
A handle for the PILS service.
Definition pils_api.c:82
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Handle to a request given to the resolver.
Entry in list of pending tasks.
Definition scheduler.c:136
Handle for the service.
A 256-bit hashcode.
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Internal representation of an address a communicator is currently providing for the transport service...
Opaque handle to the transport service for communicators.
struct GNUNET_MQ_Handle * mq
Queue to talk to the transport service.
Handle returned to identify the internal data structure the transport API has created to manage a mes...
Struct to use as closure.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
struct GNUNET_SCHEDULER_Task * listen_task
ID of listen task.
Struct for pending nat reversals.
struct sockaddr * in
Address the reversal was send to.
struct GNUNET_SCHEDULER_Task * timeout_task
struct GNUNET_PeerIdentity target
To whom are we like to talk to.
In case of port only configuration we like to bind to ipv4 and ipv6 addresses.
struct sockaddr * addr_ipv4
Ipv4 address we like to bind to.
struct sockaddr * addr_ipv6
Ipv6 address we like to bind to.
socklen_t addr_len_ipv6
Length of ipv6 address.
socklen_t addr_len_ipv4
Length of ipv4 address.
Handle for an incoming connection where we do not yet have enough information to setup a full queue.
socklen_t address_len
Length of the address.
struct GNUNET_SCHEDULER_Task * write_task
ID of write task for this connection.
char write_buf[sizeof(struct TCPNATProbeMessage)]
buffer for writing struct TCPNATProbeMessage to network.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
size_t ibuf_off
Current offset for reading into ibuf.
struct GNUNET_TIME_Absolute timeout
Timeout for this protoqueue.
struct GNUNET_NETWORK_Handle * sock
socket that we transmit all data with on this queue
struct sockaddr * address
Address of the other peer.
struct ProtoQueue * prev
Kept in a DLL.
char ibuf[(sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)+sizeof(struct TCPConfirmation))]
Buffer for reading all the information we need to upgrade from protoqueue to queue.
size_t write_off
Offset of the buffer?
struct GNUNET_SCHEDULER_Task * read_task
ID of read task for this connection.
struct ProtoQueue * next
Kept in a DLL.
Handle for a queue.
unsigned int backpressure
How may messages did we pass from this queue to CORE for which we have yet to receive an acknowledgem...
struct GNUNET_NETWORK_Handle * sock
socket that we transmit all data with on this queue
struct GNUNET_PEERSTORE_IterateContext * handshake_ack_monotime_get
Iteration Context for retrieving the monotonic time send with the handshake ack.
int rekeyed
GNUNET_YES if we just rekeyed and must thus possibly re-decrypt ciphertext.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
size_t unverified_size
Size of data received without KX challenge played back.
struct GNUNET_TRANSPORT_QueueHandle * qh
handle for this queue with the ch.
struct GNUNET_HashCode out_hmac
Shared secret for HMAC generation on outgoing data, ratcheted after each operation.
int finishing
Did we enqueue a finish message and are closing down the queue?
int initial_core_kx_done
Has the initial (core) handshake already happened?
struct GNUNET_HashCode key
Key in hash map.
socklen_t address_len
Length of the address.
struct GNUNET_MQ_Handle * mq
Message queue we are providing for the ch.
unsigned long long bytes_in_queue
Number of bytes we currently have in our write queue.
char pread_buf[UINT16_MAX+1+sizeof(struct TCPBox)]
Plaintext buffer for decrypted plaintext.
int destroyed
Did we technically destroy this queue, but kept the allocation around because of backpressure not bei...
struct GNUNET_PEERSTORE_StoreContext * rekey_monotime_sc
Store Context for retrieving the monotonic time send with key for rekeying.
size_t cwrite_off
At which offset in the ciphertext write buffer should we append more ciphertext from reading next?
struct GNUNET_PEERSTORE_IterateContext * rekey_monotime_get
Iteration Context for retrieving the monotonic time send with key for rekeying.
char cread_buf[(2 *64 *1024+sizeof(struct TCPBox))]
Buffer for reading ciphertext from network into.
struct GNUNET_CRYPTO_HpkePublicKey target_hpke_key
To whom are we talking to.
enum GNUNET_NetworkType nt
Which network type does this queue use?
struct GNUNET_CRYPTO_ChallengeNonceP challenge_received
Challenge value received.
uint64_t rekey_left_bytes
How many more bytes may we sent with the current out_cipher before we should rekey?
int mq_awaits_continue
Is MQ awaiting a GNUNET_MQ_impl_send_continue() call?
gcry_cipher_hd_t in_cipher
cipher for decryption of incoming data.
struct GNUNET_PEERSTORE_StoreContext * handshake_ack_monotime_sc
Store Context for retrieving the monotonic time send with the handshake ack.
struct GNUNET_SCHEDULER_Task * write_task
ID of write task for this connection.
size_t pwrite_off
At which offset in the plaintext output buffer should we append more plaintext for encryption next?
struct GNUNET_TIME_Absolute timeout
Timeout for this queue.
size_t cread_off
At which offset in the ciphertext read buffer should we append more ciphertext for transmission next?
struct GNUNET_TIME_Absolute rekey_time
Until what time may we sent with the current out_cipher before we should rekey?
struct GNUNET_PeerIdentity target
To whom are we talking to.
char cwrite_buf[(2 *64 *1024+sizeof(struct TCPBox))]
buffer for writing ciphertext to network.
struct GNUNET_PEERSTORE_StoreContext * handshake_monotime_sc
Store Context for retrieving the monotonic time send with the handshake.
size_t pread_off
At which offset in the plaintext input buffer should we append more plaintext from decryption next?
struct GNUNET_SCHEDULER_Task * read_task
ID of read task for this connection.
enum GNUNET_TRANSPORT_ConnectionStatus cs
The connection status of this queue.
gcry_cipher_hd_t out_cipher
cipher for encryption of outgoing data.
char pwrite_buf[UINT16_MAX+1+sizeof(struct TCPBox)]
Plaintext buffer for messages to be encrypted.
struct GNUNET_HashCode in_hmac
Shared secret for HMAC verification on incoming data.
struct GNUNET_PEERSTORE_IterateContext * handshake_monotime_get
Iteration Context for retrieving the monotonic time send with the handshake.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
struct sockaddr * address
Address of the other peer.
struct GNUNET_TIME_AbsoluteNBO handshake_ack_monotonic_time
Monotonic time value for handshake ack message.
struct GNUNET_TIME_AbsoluteNBO rekey_monotonic_time
Monotonic time value for rekey message.
struct GNUNET_TIME_AbsoluteNBO handshake_monotonic_time
Monotonic time value for handshake message.
TCP message box.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX.
struct GNUNET_ShortHashCode hmac
HMAC for the following encrypted message.
Ack for the encrypted continuation of TCP initial handshake.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Sender's signature of type GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK.
struct GNUNET_PeerIdentity sender
Sender's identity.
Encrypted continuation of TCP initial handshake.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Sender's signature of type GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE.
struct GNUNET_PeerIdentity sender
Sender's identity.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH.
struct GNUNET_ShortHashCode hmac
HMAC for the following encrypted message.
Basically a WELCOME message, but with the purpose of giving the waiting peer a client handle to use.
struct GNUNET_PeerIdentity clientIdentity
Identity of the sender of the message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
TCP rekey message box.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Sender's signature of type GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral
New ephemeral key.
struct GNUNET_ShortHashCode hmac
HMAC for the following encrypted message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY.
Signature we use to verify that the ack from the receiver of the ephemeral key was really send by the...
struct GNUNET_PeerIdentity sender
Identity of the inititor of the TCP connection (TCP client).
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_PeerIdentity receiver
Presumed identity of the target of the TCP connection (TCP server)
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
Signature we use to verify that the ephemeral key was really chosen by the specified sender.
Signature we use to verify that the ephemeral key was really chosen by the specified sender.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral
Ephemeral key used by the sender.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY.
struct GNUNET_PeerIdentity sender
Identity of the inititor of the TCP connection (TCP client).
struct GNUNET_PeerIdentity receiver
Presumed identity of the target of the TCP connection (TCP server)
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...

◆ DEFAULT_MAX_QUEUE_LENGTH

#define DEFAULT_MAX_QUEUE_LENGTH   8

How many messages do we keep at most in the queue to the transport service before we start to drop (default, can be changed via the configuration file).

Should be below the level of the communicator API, as otherwise we may read messages just to have them dropped by the communicator API.

Definition at line 69 of file gnunet-communicator-tcp.c.

◆ BUF_SIZE

#define BUF_SIZE   (2 * 64 * 1024 + sizeof(struct TCPBox))

Size of our IO buffers for ciphertext data.

Must be at least UINT_MAX + sizeof (struct TCPBox).

Definition at line 75 of file gnunet-communicator-tcp.c.

◆ DEFAULT_REKEY_INTERVAL

#define DEFAULT_REKEY_INTERVAL   GNUNET_TIME_UNIT_DAYS

How often do we rekey based on time (at least)

Definition at line 80 of file gnunet-communicator-tcp.c.

◆ PROTO_QUEUE_TIMEOUT

#define PROTO_QUEUE_TIMEOUT   GNUNET_TIME_UNIT_MINUTES

How long do we wait until we must have received the initial KX?

Definition at line 85 of file gnunet-communicator-tcp.c.

◆ REKEY_MAX_BYTES

#define REKEY_MAX_BYTES   (1024LLU * 1024 * 400)

How often do we rekey based on number of bytes transmitted? (additionally randomized).

Currently 400 MB

Definition at line 91 of file gnunet-communicator-tcp.c.

◆ INITIAL_KX_SIZE

#define INITIAL_KX_SIZE
Value:
(sizeof(struct GNUNET_CRYPTO_EcdhePublicKey) \
+ sizeof(struct TCPConfirmation))

Size of the initial key exchange message sent first in both directions.

Definition at line 97 of file gnunet-communicator-tcp.c.

◆ INITIAL_CORE_KX_SIZE

#define INITIAL_CORE_KX_SIZE
Value:
(sizeof(struct EphemeralKeyMessage) \
+ sizeof(struct PingMessage) \
+ sizeof(struct PongMessage))
Message transmitted with the signed ephemeral key of a peer.
We're sending an (encrypted) PING to the other peer to check if it can decrypt.
Response to a PING.

Size of the initial core key exchange messages.

Definition at line 104 of file gnunet-communicator-tcp.c.

◆ COMMUNICATOR_ADDRESS_PREFIX

#define COMMUNICATOR_ADDRESS_PREFIX   "tcp"

Address prefix used by the communicator.

Definition at line 112 of file gnunet-communicator-tcp.c.

◆ COMMUNICATOR_CONFIG_SECTION

#define COMMUNICATOR_CONFIG_SECTION   "communicator-tcp"

Configuration section used by the communicator.

Definition at line 117 of file gnunet-communicator-tcp.c.

Function Documentation

◆ listen_cb()

static void listen_cb ( void *  cls)
static

We have been notified that our listen socket has something to read.

Do the read and reschedule this function to be called again once more is available.

Parameters
clsNULL

Do the read and reschedule this function to be called again once more is available.

Parameters
clsListenTask with listening socket and task

Definition at line 3253 of file gnunet-communicator-tcp.c.

3254{
3255 struct sockaddr_storage in;
3256 socklen_t addrlen;
3257 struct GNUNET_NETWORK_Handle *sock;
3258 struct ListenTask *lt;
3259 struct sockaddr *in_addr;
3260
3262 "listen_cb\n");
3263
3264 lt = cls;
3265
3266 lt->listen_task = NULL;
3267 GNUNET_assert (NULL != lt->listen_sock);
3268 addrlen = sizeof(in);
3269 memset (&in, 0, sizeof(in));
3271 (struct sockaddr*) &in,
3272 &addrlen);
3273 if ((NULL == sock) && ((EMFILE == errno) || (ENFILE == errno)))
3274 return; /* system limit reached, wait until connection goes down */
3276 lt->listen_sock,
3277 &listen_cb,
3278 lt);
3279 if ((NULL == sock) && ((EAGAIN == errno) || (ENOBUFS == errno)))
3280 return;
3281 if (NULL == sock)
3282 {
3284 return;
3285 }
3286 in_addr = GNUNET_memdup (&in, addrlen);
3287 create_proto_queue (sock, in_addr, addrlen);
3288}

References create_proto_queue(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror, GNUNET_memdup, GNUNET_NETWORK_socket_accept(), GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, listen_cb(), ListenTask::listen_sock, and ListenTask::listen_task.

Referenced by init_socket(), listen_cb(), and queue_destroy().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ eddsa_priv_to_hpke_key()

static void eddsa_priv_to_hpke_key ( struct GNUNET_CRYPTO_EddsaPrivateKey edpk,
struct GNUNET_CRYPTO_HpkePrivateKey pk 
)
static

Definition at line 961 of file gnunet-communicator-tcp.c.

963{
965 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
966 key.eddsa_key = *edpk;
968 pk);
969}

References GNUNET_CRYPTO_hpke_sk_to_x25519(), GNUNET_PUBLIC_KEY_TYPE_EDDSA, key, and pk.

Referenced by pid_change_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ eddsa_pub_to_hpke_key()

static void eddsa_pub_to_hpke_key ( struct GNUNET_CRYPTO_EddsaPublicKey edpk,
struct GNUNET_CRYPTO_HpkePublicKey pk 
)
static

Definition at line 973 of file gnunet-communicator-tcp.c.

975{
977 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
978 key.eddsa_key = *edpk;
980}

References GNUNET_CRYPTO_hpke_pk_to_x25519(), GNUNET_PUBLIC_KEY_TYPE_EDDSA, key, and pk.

Referenced by mq_init(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_destroy()

static void queue_destroy ( struct Queue queue)
static

Functions with this signature are called whenever we need to close a queue due to a disconnect or failure to establish a connection.

Parameters
queuequeue to close down

Definition at line 991 of file gnunet-communicator-tcp.c.

992{
993 struct ListenTask *lt = NULL;
994 struct GNUNET_HashCode h_sock;
995 int sockfd;
996
997 if (NULL != queue->listen_sock)
998 {
999 sockfd = GNUNET_NETWORK_get_fd (queue->listen_sock);
1000 GNUNET_CRYPTO_hash (&sockfd,
1001 sizeof(int),
1002 &h_sock);
1003
1005 }
1006
1008 "Disconnecting queue for peer `%s'\n",
1009 GNUNET_i2s (&queue->target));
1010 if (NULL != queue->rekey_monotime_sc)
1011 {
1012 GNUNET_PEERSTORE_store_cancel (queue->rekey_monotime_sc);
1013 queue->rekey_monotime_sc = NULL;
1014 }
1015 if (NULL != queue->handshake_monotime_sc)
1016 {
1017 GNUNET_PEERSTORE_store_cancel (queue->handshake_monotime_sc);
1018 queue->handshake_monotime_sc = NULL;
1019 }
1020 if (NULL != queue->handshake_ack_monotime_sc)
1021 {
1022 GNUNET_PEERSTORE_store_cancel (queue->handshake_ack_monotime_sc);
1023 queue->handshake_ack_monotime_sc = NULL;
1024 }
1025 if (NULL != queue->rekey_monotime_get)
1026 {
1027 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1028 queue->rekey_monotime_get = NULL;
1029 }
1030 if (NULL != queue->handshake_monotime_get)
1031 {
1032 GNUNET_PEERSTORE_iteration_stop (queue->handshake_monotime_get);
1033 queue->handshake_monotime_get = NULL;
1034 }
1035 if (NULL != queue->handshake_ack_monotime_get)
1036 {
1037 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1038 queue->handshake_ack_monotime_get = NULL;
1039 }
1040 if (NULL != queue->qh)
1041 {
1043 queue->qh = NULL;
1044 }
1046 GNUNET_YES ==
1049 "# queues active",
1051 GNUNET_NO);
1052 if (NULL != queue->read_task)
1053 {
1054 GNUNET_SCHEDULER_cancel (queue->read_task);
1055 queue->read_task = NULL;
1056 }
1057 if (NULL != queue->write_task)
1058 {
1059 GNUNET_SCHEDULER_cancel (queue->write_task);
1060 queue->write_task = NULL;
1061 }
1063 {
1065 "closing socket failed\n");
1066 }
1067 gcry_cipher_close (queue->in_cipher);
1068 gcry_cipher_close (queue->out_cipher);
1069 GNUNET_free (queue->address);
1070 if (0 != queue->backpressure)
1071 queue->destroyed = GNUNET_YES;
1072 else
1074
1075 if (NULL == lt)
1076 return;
1077
1078 if ((! shutdown_running) && (NULL == lt->listen_task))
1079 {
1081 "add read net listen\n");
1084 lt->listen_sock,
1085 &listen_cb,
1086 lt);
1087 }
1088 else
1089 GNUNET_free (lt);
1090}

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_NETWORK_get_fd(), GNUNET_NETWORK_socket_close(), GNUNET_NO, GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store_cancel(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_set(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_communicator_mq_del(), GNUNET_YES, listen_cb(), ListenTask::listen_sock, ListenTask::listen_task, lt_map, queue(), queue_map, shutdown_running, and stats.

Referenced by get_queue_delete_it(), queue_read(), queue_read_kx(), queue_write(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_hmac()

static void calculate_hmac ( struct GNUNET_HashCode hmac_secret,
const void *  buf,
size_t  buf_size,
struct GNUNET_ShortHashCode smac 
)
static

Compute mac over buf, and ratched the hmac_secret.

Parameters
[in,out]hmac_secretsecret for HMAC calculation
bufbuffer to MAC
buf_sizenumber of bytes in buf
[out]smacwhere to write the HMAC

Definition at line 1102 of file gnunet-communicator-tcp.c.

1106{
1107 struct GNUNET_HashCode mac;
1108
1109 GNUNET_CRYPTO_hmac_raw (hmac_secret,
1110 sizeof(struct GNUNET_HashCode),
1111 buf,
1112 buf_size,
1113 &mac);
1114 /* truncate to `struct GNUNET_ShortHashCode` */
1115 memcpy (smac, &mac, sizeof(struct GNUNET_ShortHashCode));
1116 /* ratchet hmac key */
1117 GNUNET_CRYPTO_hash (hmac_secret,
1118 sizeof(struct GNUNET_HashCode),
1119 hmac_secret);
1120}

References GNUNET_CRYPTO_hash(), and GNUNET_CRYPTO_hmac_raw().

Referenced by inject_rekey(), mq_send(), queue_finish(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_finish()

static void queue_finish ( struct Queue queue)
static

Append a 'finish' message to the outgoing transmission.

Once the finish has been transmitted, destroy the queue.

Parameters
queuequeue to shut down nicely

Definition at line 1130 of file gnunet-communicator-tcp.c.

1131{
1132 struct TCPFinish fin;
1133
1134 memset (&fin, 0, sizeof(fin));
1135 fin.header.size = htons (sizeof(fin));
1136 fin.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH);
1137 calculate_hmac (&queue->out_hmac, &fin, sizeof(fin), &fin.hmac);
1138 /* if there is any message left in pwrite_buf, we
1139 overwrite it (possibly dropping the last message
1140 from CORE hard here) */
1141 memcpy (queue->pwrite_buf, &fin, sizeof(fin));
1142 queue->pwrite_off = sizeof(fin);
1143 /* This flag will ensure that #queue_write() no longer
1144 notifies CORE about the possibility of sending
1145 more data, and that #queue_write() will call
1146 #queue_destroy() once the @c fin was fully written. */
1147 queue->finishing = GNUNET_YES;
1148}

References calculate_hmac(), GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH, GNUNET_YES, TCPFinish::header, TCPFinish::hmac, queue(), GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by do_rekey(), handshake_ack_monotime_cb(), handshake_monotime_cb(), mq_destroy(), mq_error(), rekey_monotime_cb(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_read()

static void queue_read ( void *  cls)
static

Queue read task.

If we hit the timeout, disconnect it

Parameters
clsthe struct Queue * to disconnect

Definition at line 2196 of file gnunet-communicator-tcp.c.

2197{
2198 struct Queue *queue = cls;
2199 struct GNUNET_TIME_Relative left;
2200 ssize_t rcvd;
2201
2202 queue->read_task = NULL;
2203 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2204 &queue->cread_buf[queue->cread_off],
2205 BUF_SIZE - queue->cread_off);
2207 "Received %zd bytes from TCP queue\n", rcvd);
2208 if (-1 == rcvd)
2209 {
2210 if ((EAGAIN != errno) && (EINTR != errno))
2211 {
2214 return;
2215 }
2216 /* try again */
2217 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2218 if (0 != left.rel_value_us)
2219 {
2220 queue->read_task =
2222 return;
2223 }
2225 "Queue %p was idle for %s, disconnecting\n",
2226 queue,
2229 GNUNET_YES));
2231 return;
2232 }
2233 if (0 == rcvd)
2234 {
2235 /* Orderly shutdown of connection */
2237 "Socket for queue %p seems to have been closed\n", queue);
2239 return;
2240 }
2241 queue->timeout =
2243 queue->cread_off += rcvd;
2244 while ((queue->pread_off < sizeof(queue->pread_buf)) &&
2245 (queue->cread_off > 0))
2246 {
2247 size_t max = GNUNET_MIN (sizeof(queue->pread_buf) - queue->pread_off,
2248 queue->cread_off);
2249 size_t done;
2250 size_t total;
2251 size_t old_pread_off = queue->pread_off;
2252
2253 GNUNET_assert (0 ==
2254 gcry_cipher_decrypt (queue->in_cipher,
2255 &queue->pread_buf[queue->pread_off],
2256 max,
2257 queue->cread_buf,
2258 max));
2259 queue->pread_off += max;
2260 total = 0;
2261 while (0 != (done = try_handle_plaintext (queue)))
2262 {
2263 /* 'done' bytes of plaintext were used, shift buffer */
2264 GNUNET_assert (done <= queue->pread_off);
2265 /* NOTE: this memmove() could possibly sometimes be
2266 avoided if we pass 'total' into try_handle_plaintext()
2267 and use it at an offset into the buffer there! */
2268 memmove (queue->pread_buf,
2269 &queue->pread_buf[done],
2270 queue->pread_off - done);
2271 queue->pread_off -= done;
2272 total += done;
2273 /* The last plaintext was a rekey, abort for now */
2274 if (GNUNET_YES == queue->rekeyed)
2275 break;
2276 }
2277 /* when we encounter a rekey message, the decryption above uses the
2278 wrong key for everything after the rekey; in that case, we have
2279 to re-do the decryption at 'total' instead of at 'max'.
2280 However, we have to take into account that the plaintext buffer may have
2281 already contained data and not jumped too far ahead in the ciphertext.
2282 If there is no rekey and the last message is incomplete (max > total),
2283 it is safe to keep the decryption so we shift by 'max' */
2284 if (GNUNET_YES == queue->rekeyed)
2285 {
2286 max = total - old_pread_off;
2287 queue->rekeyed = GNUNET_NO;
2288 queue->pread_off = 0;
2289 }
2290 memmove (queue->cread_buf, &queue->cread_buf[max], queue->cread_off - max);
2291 queue->cread_off -= max;
2292 }
2293 if (BUF_SIZE == queue->cread_off)
2294 return; /* buffer full, suspend reading */
2295 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2296 if (0 != left.rel_value_us)
2297 {
2298 if (max_queue_length > queue->backpressure)
2299 {
2300 /* continue reading */
2301 queue->read_task =
2303 }
2304 return;
2305 }
2307 "Queue %p was idle for %s, disconnecting\n",
2308 queue,
2311 GNUNET_YES));
2313}

References BUF_SIZE, GNUNET_assert, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_log_strerror, GNUNET_MIN, GNUNET_NETWORK_socket_recv(), GNUNET_NO, GNUNET_SCHEDULER_add_read_net(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, max, max_queue_length, queue(), queue_destroy(), queue_read(), GNUNET_TIME_Relative::rel_value_us, and try_handle_plaintext().

Referenced by core_read_finished_cb(), proto_read_kx(), queue_read(), and queue_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ core_read_finished_cb()

static void core_read_finished_cb ( void *  cls,
int  success 
)
static

Core tells us it is done processing a message that transport received on a queue with status success.

Parameters
clsa struct Queue * where the message originally came from
successGNUNET_OK on success

Definition at line 1168 of file gnunet-communicator-tcp.c.

1169{
1170 struct Queue *queue = cls;
1171 if (GNUNET_OK != success)
1173 "# messages lost in communicator API towards CORE",
1174 1,
1175 GNUNET_NO);
1176 if (NULL == queue)
1177 return;
1178
1180 "backpressure %u\n",
1181 queue->backpressure);
1182
1183 queue->backpressure--;
1184 /* handle deferred queue destruction */
1185 if ((queue->destroyed) && (0 == queue->backpressure))
1186 {
1188 return;
1189 }
1190 else if (GNUNET_YES != queue->destroyed)
1191 {
1192 queue->timeout =
1194 );
1195 /* possibly unchoke reading, now that CORE made progress */
1196 if (NULL == queue->read_task)
1197 queue->read_task =
1199 queue->timeout),
1200 queue->sock,
1201 &queue_read,
1202 queue);
1203 }
1204}

References GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, queue(), queue_read(), and stats.

Referenced by pass_plaintext_to_core().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pass_plaintext_to_core()

static void pass_plaintext_to_core ( struct Queue queue,
const void *  plaintext,
size_t  plaintext_len 
)
static

We received plaintext_len bytes of plaintext on queue.

Pass it on to CORE. If transmission is actually happening, increase backpressure counter.

Parameters
queuethe queue that received the plaintext
plaintextthe plaintext that was received
plaintext_lennumber of bytes of plaintext received

Definition at line 1217 of file gnunet-communicator-tcp.c.

1220{
1221 const struct GNUNET_MessageHeader *hdr = plaintext;
1222 int ret;
1223
1225 "pass message from %s to core\n",
1226 GNUNET_i2s (&queue->target));
1227
1228 if (ntohs (hdr->size) != plaintext_len)
1229 {
1230 /* NOTE: If we ever allow multiple CORE messages in one
1231 BOX, this will have to change! */
1232 GNUNET_break (0);
1233 return;
1234 }
1236 &queue->target,
1237 hdr,
1240 queue);
1242 "passed to core\n");
1243 if (GNUNET_OK == ret)
1244 queue->backpressure++;
1245 GNUNET_break (GNUNET_NO != ret); /* backpressure not working!? */
1246 if (GNUNET_SYSERR == ret)
1248 "# bytes lost due to CORE not running",
1249 plaintext_len,
1250 GNUNET_NO);
1251}

References ADDRESS_VALIDITY_PERIOD, ch, core_read_finished_cb(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TRANSPORT_communicator_receive(), queue(), ret, GNUNET_MessageHeader::size, and stats.

Referenced by try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_cipher()

static void setup_cipher ( const struct GNUNET_ShortHashCode prk,
const struct GNUNET_PeerIdentity pid,
gcry_cipher_hd_t *  cipher,
struct GNUNET_HashCode hmac_key 
)
static

Setup cipher based on shared secret dh and decrypting peer pid.

Parameters
dhshared secret
piddecrypting peer's identity
[out]ciphercipher to initialize
[out]hmac_keyHMAC key to initialize

Definition at line 1264 of file gnunet-communicator-tcp.c.

1268{
1269 char key[256 / 8];
1270 char ctr[128 / 8];
1271
1272 GNUNET_assert (0 == gcry_cipher_open (cipher,
1273 GCRY_CIPHER_AES256 /* low level: go for speed */
1274 ,
1275 GCRY_CIPHER_MODE_CTR,
1276 0 /* flags */));
1279 sizeof(key),
1280 prk,
1281 "gnunet-communicator-tcp-key",
1282 strlen (
1283 "gnunet-communicator-tcp-key"),
1284 NULL,
1285 0));
1286 GNUNET_assert (0 == gcry_cipher_setkey (*cipher, key, sizeof(key)));
1289 sizeof(ctr),
1290 prk,
1291 "gnunet-communicator-tcp-ctr",
1292 strlen (
1293 "gnunet-communicator-tcp-ctr"),
1294 NULL,
1295 0));
1296 gcry_cipher_setctr (*cipher, ctr, sizeof(ctr));
1298 GNUNET_CRYPTO_hkdf_expand (hmac_key,
1299 sizeof(struct GNUNET_HashCode),
1300 prk,
1301 "gnunet-communicator-hmac",
1302 strlen ("gnunet-communicator-hmac"),
1303 NULL,
1304 0));
1305}

References GNUNET_assert, GNUNET_CRYPTO_hkdf_expand(), GNUNET_YES, and key.

Referenced by setup_in_cipher(), setup_in_cipher_elligator(), and setup_out_cipher().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ rekey_monotime_store_cb()

static void rekey_monotime_store_cb ( void *  cls,
int  success 
)
static

Callback called when peerstore store operation for rekey monotime value is finished.

Parameters
clsQueue context the store operation was executed.
successStore operation was successful (GNUNET_OK) or not.

Definition at line 1314 of file gnunet-communicator-tcp.c.

1315{
1316 struct Queue *queue = cls;
1317 if (GNUNET_OK != success)
1318 {
1320 "Failed to store rekey monotonic time in PEERSTORE!\n");
1321 }
1322 queue->rekey_monotime_sc = NULL;
1323 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1324}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_PEERSTORE_iteration_next(), and queue().

Referenced by rekey_monotime_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ rekey_monotime_cb()

static void rekey_monotime_cb ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY where found.

Parameters
clsQueue context the store operation was executed.
recordThe record found or NULL if there is no record left.
emsgMessage from peerstore.

Definition at line 1335 of file gnunet-communicator-tcp.c.

1338{
1339 struct Queue *queue = cls;
1340 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1341 struct GNUNET_TIME_Absolute mt;
1342 const struct GNUNET_PeerIdentity *pid;
1343 struct GNUNET_TIME_AbsoluteNBO *rekey_monotonic_time;
1344
1345 (void) emsg;
1346
1347 rekey_monotonic_time = &queue->rekey_monotonic_time;
1348 pid = &queue->target;
1349 if (NULL == record)
1350 {
1351 queue->rekey_monotime_get = NULL;
1352 return;
1353 }
1354 if (sizeof(*mtbe) != record->value_size)
1355 {
1356 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1357 GNUNET_break (0);
1358 return;
1359 }
1360 mtbe = record->value;
1361 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1362 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1363 queue->rekey_monotonic_time).abs_value_us)
1364 {
1366 "Queue from %s dropped, rekey monotime in the past\n",
1367 GNUNET_i2s (&queue->target));
1368 GNUNET_break (0);
1369 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1370 queue->rekey_monotime_get = NULL;
1371 // FIXME: Why should we try to gracefully finish here??
1373 return;
1374 }
1375 queue->rekey_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
1376 "transport_tcp_communicator",
1377 pid,
1379 rekey_monotonic_time,
1380 sizeof(*
1381 rekey_monotonic_time),
1385 queue);
1386}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_log, GNUNET_PEERSTORE_iteration_next(), GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_REPLACE, GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY, GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_UNIT_FOREVER_ABS, peerstore, pid, queue(), queue_finish(), record(), and rekey_monotime_store_cb().

Referenced by do_rekey().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_in_cipher_elligator()

static void setup_in_cipher_elligator ( const struct GNUNET_CRYPTO_HpkeEncapsulation c,
struct Queue queue 
)
static

Setup cipher of queue for decryption from an elligator representative.

Parameters
ephemeralephemeral key we received from the other peer (elligator representative)
[in,out]queuequeue to initialize decryption cipher for

Definition at line 1396 of file gnunet-communicator-tcp.c.

1399{
1400 struct GNUNET_ShortHashCode k;
1401
1403 c,
1404 &k);
1405 setup_cipher (&k, &my_identity, &queue->in_cipher, &queue->in_hmac);
1406}

References GNUNET_CRYPTO_hpke_elligator_kem_decaps(), my_identity, my_x25519_private_key, queue(), and setup_cipher().

Referenced by proto_read_kx(), and queue_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_in_cipher()

static void setup_in_cipher ( const struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral,
struct Queue queue 
)
static

Setup cipher of queue for decryption.

Parameters
ephemeralephemeral key we received from the other peer
[in,out]queuequeue to initialize decryption cipher for

Definition at line 1416 of file gnunet-communicator-tcp.c.

1418{
1419 struct GNUNET_ShortHashCode k;
1420
1422 setup_cipher (&k, &my_identity, &queue->in_cipher, &queue->in_hmac);
1423}

References GNUNET_CRYPTO_eddsa_kem_decaps(), my_identity, my_private_key, queue(), and setup_cipher().

Referenced by do_rekey().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_rekey()

static void do_rekey ( struct Queue queue,
const struct TCPRekey rekey 
)
static

Handle rekey message on queue.

The message was already HMAC'ed, but we should additionally still check the signature. Then we need to stop the old cipher and start afresh.

Parameters
queuethe queue rekey was received on
rekeythe rekey message

Definition at line 1435 of file gnunet-communicator-tcp.c.

1436{
1437 struct TcpRekeySignature thp;
1438
1440 thp.purpose.size = htonl (sizeof(thp));
1442 "do_rekey size %u\n",
1443 thp.purpose.size);
1444 thp.sender = queue->target;
1446 "sender %s\n",
1447 GNUNET_p2s (&thp.sender.public_key));
1449 "sender %s\n",
1450 GNUNET_p2s (&queue->target.public_key));
1451 thp.receiver = my_identity;
1453 "receiver %s\n",
1454 GNUNET_p2s (&thp.receiver.public_key));
1455 thp.ephemeral = rekey->ephemeral;
1457 "ephemeral %s\n",
1458 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
1459 );
1460 thp.monotonic_time = rekey->monotonic_time;
1462 "time %s\n",
1464 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1465 GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp)));
1466 if (GNUNET_OK !=
1469 &thp,
1470 &rekey->sender_sig,
1471 &queue->target.public_key))
1472 {
1473 GNUNET_break (0);
1474 // FIXME Why should we try to gracefully finish here?
1476 return;
1477 }
1478 queue->rekey_monotonic_time = rekey->monotonic_time;
1479 queue->rekey_monotime_get = GNUNET_PEERSTORE_iteration_start (peerstore,
1480 "transport_tcp_communicator",
1481 &queue->target,
1483 &
1485 queue);
1486 gcry_cipher_close (queue->in_cipher);
1487 queue->rekeyed = GNUNET_YES;
1488 setup_in_cipher (&rekey->ephemeral, queue);
1489}

References TCPRekey::ephemeral, TcpRekeySignature::ephemeral, GNUNET_assert, GNUNET_break, GNUNET_CRYPTO_eddsa_verify, GNUNET_e2s(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_OK, GNUNET_p2s(), GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY, GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY, GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_absolute_ntoh(), GNUNET_YES, TCPRekey::monotonic_time, TcpRekeySignature::monotonic_time, my_identity, peerstore, GNUNET_PeerIdentity::public_key, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpRekeySignature::purpose, queue(), queue_finish(), TcpRekeySignature::receiver, rekey_monotime_cb(), TcpRekeySignature::sender, TCPRekey::sender_sig, setup_in_cipher(), and GNUNET_CRYPTO_SignaturePurpose::size.

Referenced by try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handshake_ack_monotime_store_cb()

static void handshake_ack_monotime_store_cb ( void *  cls,
int  success 
)
static

Callback called when peerstore store operation for handshake ack monotime value is finished.

Parameters
clsQueue context the store operation was executed.
successStore operation was successful (GNUNET_OK) or not.

Definition at line 1498 of file gnunet-communicator-tcp.c.

1499{
1500 struct Queue *queue = cls;
1501
1502 if (GNUNET_OK != success)
1503 {
1505 "Failed to store handshake ack monotonic time in PEERSTORE!\n");
1506 }
1507 queue->handshake_ack_monotime_sc = NULL;
1508 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1509}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_PEERSTORE_iteration_next(), and queue().

Referenced by handshake_ack_monotime_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handshake_ack_monotime_cb()

static void handshake_ack_monotime_cb ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK where found.

Parameters
clsQueue context the store operation was executed.
recordThe record found or NULL if there is no record left.
emsgMessage from peerstore.

Definition at line 1520 of file gnunet-communicator-tcp.c.

1523{
1524 struct Queue *queue = cls;
1525 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1526 struct GNUNET_TIME_Absolute mt;
1527 const struct GNUNET_PeerIdentity *pid;
1528 struct GNUNET_TIME_AbsoluteNBO *handshake_ack_monotonic_time;
1529
1530 (void) emsg;
1531
1532 handshake_ack_monotonic_time = &queue->handshake_ack_monotonic_time;
1533 pid = &queue->target;
1534 if (NULL == record)
1535 {
1536 queue->handshake_ack_monotime_get = NULL;
1537 return;
1538 }
1539 if (sizeof(*mtbe) != record->value_size)
1540 {
1541 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1542 GNUNET_break (0);
1543 return;
1544 }
1545 mtbe = record->value;
1546 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1547 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1548 queue->handshake_ack_monotonic_time).abs_value_us)
1549 {
1551 "Queue from %s dropped, handshake ack monotime in the past\n",
1552 GNUNET_i2s (&queue->target));
1553 GNUNET_break (0);
1554 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1555 queue->handshake_ack_monotime_get = NULL;
1556 // FIXME: Why should we try to gracefully finish here?
1558 return;
1559 }
1560 queue->handshake_ack_monotime_sc =
1562 "transport_tcp_communicator",
1563 pid,
1565 handshake_ack_monotonic_time,
1566 sizeof(*handshake_ack_monotonic_time),
1570 queue);
1571}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_log, GNUNET_PEERSTORE_iteration_next(), GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_REPLACE, GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK, GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_UNIT_FOREVER_ABS, handshake_ack_monotime_store_cb(), peerstore, pid, queue(), queue_finish(), and record().

Referenced by try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_challenge()

static void send_challenge ( struct GNUNET_CRYPTO_ChallengeNonceP  challenge,
struct Queue queue 
)
static

Sending challenge with TcpConfirmationAck back to sender of ephemeral key.

Parameters
tcThe TCPConfirmation originally send.
queueThe queue context.

Definition at line 1581 of file gnunet-communicator-tcp.c.

1583{
1584 struct TCPConfirmationAck tca;
1585 struct TcpHandshakeAckSignature thas;
1586
1588 "sending challenge\n");
1589
1590 tca.header.type = ntohs (
1592 tca.header.size = ntohs (sizeof(tca));
1593 tca.challenge = challenge;
1594 tca.sender = my_identity;
1595 tca.monotonic_time =
1597 thas.purpose.purpose = htonl (
1599 thas.purpose.size = htonl (sizeof(thas));
1600 thas.sender = my_identity;
1601 thas.receiver = queue->target;
1602 thas.monotonic_time = tca.monotonic_time;
1603 thas.challenge = tca.challenge;
1605 &thas,
1606 &tca.sender_sig);
1607 GNUNET_assert (0 ==
1608 gcry_cipher_encrypt (queue->out_cipher,
1609 &queue->cwrite_buf[queue->cwrite_off],
1610 sizeof(tca),
1611 &tca,
1612 sizeof(tca)));
1613 queue->cwrite_off += sizeof(tca);
1615 "sending challenge done\n");
1616}

References cfg, TcpHandshakeAckSignature::challenge, TCPConfirmationAck::challenge, GNUNET_assert, GNUNET_CRYPTO_eddsa_sign, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK, GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK, GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), TCPConfirmationAck::header, TcpHandshakeAckSignature::monotonic_time, TCPConfirmationAck::monotonic_time, my_identity, my_private_key, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpHandshakeAckSignature::purpose, queue(), TcpHandshakeAckSignature::receiver, TcpHandshakeAckSignature::sender, TCPConfirmationAck::sender, TCPConfirmationAck::sender_sig, GNUNET_MessageHeader::size, GNUNET_CRYPTO_SignaturePurpose::size, and GNUNET_MessageHeader::type.

Referenced by queue_read_kx(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_out_cipher()

static void setup_out_cipher ( struct Queue queue,
struct GNUNET_ShortHashCode dh 
)
static

Setup cipher for outgoing data stream based on target and our ephemeral private key.

Parameters
queuequeue to setup outgoing (encryption) cipher for

Definition at line 1626 of file gnunet-communicator-tcp.c.

1627{
1628 setup_cipher (dh, &queue->target, &queue->out_cipher, &queue->out_hmac);
1630 queue->rekey_left_bytes =
1632}

References GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_TIME_relative_to_absolute(), queue(), rekey_interval, rekey_max_bytes, and setup_cipher().

Referenced by inject_rekey(), and start_initial_kx_out().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ inject_rekey()

static void inject_rekey ( struct Queue queue)
static

Inject a struct TCPRekey message into the queue's plaintext buffer.

Parameters
queuequeue to perform rekeying on

Definition at line 1642 of file gnunet-communicator-tcp.c.

1643{
1644 struct TCPRekey rekey;
1645 struct TcpRekeySignature thp;
1646 struct GNUNET_ShortHashCode k;
1647
1648 GNUNET_assert (0 == queue->pwrite_off);
1649 memset (&rekey, 0, sizeof(rekey));
1650 GNUNET_CRYPTO_eddsa_kem_encaps (&queue->target.public_key, &rekey.ephemeral,
1651 &k);
1652 rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY);
1653 rekey.header.size = ntohs (sizeof(rekey));
1654 rekey.monotonic_time =
1656 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1657 thp.purpose.size = htonl (sizeof(thp));
1659 "inject_rekey size %u\n",
1660 thp.purpose.size);
1661 thp.sender = my_identity;
1663 "sender %s\n",
1664 GNUNET_p2s (&thp.sender.public_key));
1665 thp.receiver = queue->target;
1667 "receiver %s\n",
1668 GNUNET_p2s (&thp.receiver.public_key));
1669 thp.ephemeral = rekey.ephemeral;
1671 "ephemeral %s\n",
1672 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
1673 );
1674 thp.monotonic_time = rekey.monotonic_time;
1676 "time %s\n",
1678 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1680 &thp,
1681 &rekey.sender_sig);
1682 calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac);
1683 /* Encrypt rekey message with 'old' cipher */
1684 GNUNET_assert (0 ==
1685 gcry_cipher_encrypt (queue->out_cipher,
1686 &queue->cwrite_buf[queue->cwrite_off],
1687 sizeof(rekey),
1688 &rekey,
1689 sizeof(rekey)));
1690 queue->cwrite_off += sizeof(rekey);
1691 /* Setup new cipher for successive messages */
1692 gcry_cipher_close (queue->out_cipher);
1693 setup_out_cipher (queue, &k);
1694}

References calculate_hmac(), cfg, TCPRekey::ephemeral, TcpRekeySignature::ephemeral, GNUNET_assert, GNUNET_CRYPTO_eddsa_kem_encaps(), GNUNET_CRYPTO_eddsa_sign, GNUNET_e2s(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY, GNUNET_p2s(), GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY, GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_absolute_ntoh(), TCPRekey::header, TCPRekey::hmac, TCPRekey::monotonic_time, TcpRekeySignature::monotonic_time, my_identity, my_private_key, GNUNET_PeerIdentity::public_key, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpRekeySignature::purpose, queue(), TcpRekeySignature::receiver, TcpRekeySignature::sender, TCPRekey::sender_sig, setup_out_cipher(), GNUNET_MessageHeader::size, GNUNET_CRYPTO_SignaturePurpose::size, and GNUNET_MessageHeader::type.

Referenced by queue_write().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pending_reversals_delete_it()

static int pending_reversals_delete_it ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 1698 of file gnunet-communicator-tcp.c.

1701{
1702 struct PendingReversal *pending_reversal = value;
1703 (void) cls;
1704
1705 if (NULL != pending_reversal->timeout_task)
1706 {
1707 GNUNET_SCHEDULER_cancel (pending_reversal->timeout_task);
1708 pending_reversal->timeout_task = NULL;
1709 }
1712 key,
1713 pending_reversal));
1714 GNUNET_free (pending_reversal->in);
1715 GNUNET_free (pending_reversal);
1716 return GNUNET_OK;
1717}

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_remove(), GNUNET_free, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_YES, PendingReversal::in, key, pending_reversals, PendingReversal::timeout_task, and value.

Referenced by check_and_remove_pending_reversal(), and do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_and_remove_pending_reversal()

static void check_and_remove_pending_reversal ( struct sockaddr *  in,
sa_family_t  sa_family,
struct GNUNET_PeerIdentity sender 
)
static

Definition at line 1721 of file gnunet-communicator-tcp.c.

1723{
1724 if (AF_INET == sa_family)
1725 {
1726 struct PendingReversal *pending_reversal;
1727 struct GNUNET_HashCode key;
1728 struct sockaddr_in *natted_address;
1729
1730 natted_address = GNUNET_memdup (in, sizeof (struct sockaddr));
1731 natted_address->sin_port = 0;
1732 GNUNET_CRYPTO_hash (natted_address,
1733 sizeof(struct sockaddr),
1734 &key);
1735
1737 &key);
1738 if (NULL != pending_reversal && (NULL == sender ||
1739 0 != memcmp (sender,
1740 &pending_reversal->target,
1741 sizeof(struct
1743 {
1745 "Removing invalid pending reversal for `%s'at `%s'\n",
1746 GNUNET_i2s (&pending_reversal->target),
1747 GNUNET_a2s (in, sizeof (struct sockaddr)));
1748 pending_reversals_delete_it (NULL, &key, pending_reversal);
1749 }
1750 GNUNET_free (natted_address);
1751 }
1752}

References GNUNET_a2s(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memdup, key, pending_reversals, pending_reversals_delete_it(), and PendingReversal::target.

Referenced by free_proto_queue(), proto_read_kx(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_proto_queue()

static void free_proto_queue ( struct ProtoQueue pq)
static

Closes socket and frees memory associated with pq.

Parameters
pqproto queue to free

Definition at line 1761 of file gnunet-communicator-tcp.c.

1762{
1763 if (NULL != pq->listen_sock)
1764 {
1766 pq->listen_sock = NULL;
1767 }
1768 if (NULL != pq->read_task)
1769 {
1771 pq->read_task = NULL;
1772 }
1773 if (NULL != pq->write_task)
1774 {
1776 pq->write_task = NULL;
1777 }
1778 check_and_remove_pending_reversal (pq->address, pq->address->sa_family, NULL);
1780 GNUNET_free (pq->address);
1782 GNUNET_free (pq);
1783}

References ProtoQueue::address, check_and_remove_pending_reversal(), GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_SCHEDULER_cancel(), ProtoQueue::listen_sock, proto_head, proto_tail, ProtoQueue::read_task, ProtoQueue::sock, and ProtoQueue::write_task.

Referenced by do_shutdown(), proto_queue_write(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ proto_queue_write()

static void proto_queue_write ( void *  cls)
static

We have been notified that our socket is ready to write.

Then reschedule this function to be called again once more is available.

Parameters
clsa struct ProtoQueue

Definition at line 1793 of file gnunet-communicator-tcp.c.

1794{
1795 struct ProtoQueue *pq = cls;
1796 ssize_t sent;
1797 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In proto queue write\n");
1798 pq->write_task = NULL;
1799 if (0 != pq->write_off)
1800 {
1801 sent = GNUNET_NETWORK_socket_send (pq->sock,
1802 pq->write_buf,
1803 pq->write_off);
1805 "Sent %lu bytes to TCP queue\n", sent);
1806 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1807 {
1809 free_proto_queue (pq);
1810 return;
1811 }
1812 if (sent > 0)
1813 {
1814 size_t usent = (size_t) sent;
1815 pq->write_off -= usent;
1816 memmove (pq->write_buf,
1817 &pq->write_buf[usent],
1818 pq->write_off);
1819 }
1820 }
1821 /* do we care to write more? */
1822 if ((0 < pq->write_off))
1823 pq->write_task =
1825 pq->sock,
1827 pq);
1828}

References free_proto_queue(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_send(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, proto_queue_write(), ProtoQueue::sock, ProtoQueue::write_buf, ProtoQueue::write_off, and ProtoQueue::write_task.

Referenced by proto_queue_write(), and try_connection_reversal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_write()

static void queue_write ( void *  cls)
static

We have been notified that our socket is ready to write.

Then reschedule this function to be called again once more is available.

Parameters
clsa struct Queue

Definition at line 1838 of file gnunet-communicator-tcp.c.

1839{
1840 struct Queue *queue = cls;
1841 ssize_t sent;
1842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n");
1843 queue->write_task = NULL;
1844 if (0 != queue->cwrite_off)
1845 {
1846 sent = GNUNET_NETWORK_socket_send (queue->sock,
1847 queue->cwrite_buf,
1848 queue->cwrite_off);
1850 "Sent %lu bytes to TCP queue\n", sent);
1851 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1852 {
1855 return;
1856 }
1857 if (sent > 0)
1858 {
1859 size_t usent = (size_t) sent;
1860 queue->cwrite_off -= usent;
1861 memmove (queue->cwrite_buf,
1862 &queue->cwrite_buf[usent],
1863 queue->cwrite_off);
1864 queue->timeout =
1867 }
1868 }
1869 {
1870 /* can we encrypt more? (always encrypt full messages, needed
1871 such that #mq_cancel() can work!) */
1872 unsigned int we_do_not_need_to_rekey = (0 < queue->rekey_left_bytes
1873 - (queue->cwrite_off
1874 + queue->pwrite_off
1875 + sizeof (struct TCPRekey)));
1876 if (we_do_not_need_to_rekey &&
1877 (queue->pwrite_off > 0) &&
1878 (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE))
1879 {
1881 "Encrypting %lu bytes\n", queue->pwrite_off);
1882 GNUNET_assert (0 ==
1883 gcry_cipher_encrypt (queue->out_cipher,
1884 &queue->cwrite_buf[queue->cwrite_off],
1885 queue->pwrite_off,
1886 queue->pwrite_buf,
1887 queue->pwrite_off));
1888 if (queue->rekey_left_bytes > queue->pwrite_off)
1889 queue->rekey_left_bytes -= queue->pwrite_off;
1890 else
1891 queue->rekey_left_bytes = 0;
1892 queue->cwrite_off += queue->pwrite_off;
1893 queue->pwrite_off = 0;
1894 }
1895 // if ((-1 != unverified_size)&& ((0 == queue->pwrite_off) &&
1896 if (((0 == queue->rekey_left_bytes) ||
1898 queue->rekey_time).rel_value_us)) &&
1899 (((0 == queue->pwrite_off) || ! we_do_not_need_to_rekey) &&
1900 (queue->cwrite_off + sizeof (struct TCPRekey) <= BUF_SIZE)))
1901 {
1903 }
1904 }
1905 if ((0 == queue->pwrite_off) && (! queue->finishing) &&
1906 (GNUNET_YES == queue->mq_awaits_continue))
1907 {
1908 queue->mq_awaits_continue = GNUNET_NO;
1910 }
1911 /* did we just finish writing 'finish'? */
1912 if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing))
1913 {
1915 "Finishing queue\n");
1917 return;
1918 }
1919 /* do we care to write more? */
1920 if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off))
1921 queue->write_task =
1923 queue->sock,
1924 &queue_write,
1925 queue);
1926}

References BUF_SIZE, GNUNET_assert, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror, GNUNET_MQ_impl_send_continue(), GNUNET_NETWORK_socket_send(), GNUNET_NO, GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, inject_rekey(), queue(), queue_destroy(), queue_write(), and GNUNET_TIME_Relative::rel_value_us.

Referenced by mq_init(), mq_send(), proto_read_kx(), queue_read_kx(), queue_write(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_handle_plaintext()

static size_t try_handle_plaintext ( struct Queue queue)
static

Test if we have received a full message in plaintext.

If so, handle it.

Parameters
queuequeue to process inbound plaintext for
Returns
number of bytes of plaintext handled, 0 for none

Once we received this ack, we consider this a verified connection. FIXME: I am not sure this logic is sane here.

Definition at line 1937 of file gnunet-communicator-tcp.c.

1938{
1939 const struct GNUNET_MessageHeader *hdr;
1940 const struct TCPConfirmationAck *tca;
1941 const struct TCPBox *box;
1942 const struct TCPRekey *rekey;
1943 const struct TCPFinish *fin;
1944 struct TCPRekey rekeyz;
1945 struct TCPFinish finz;
1946 struct GNUNET_ShortHashCode tmac;
1947 uint16_t type;
1948 size_t size = 0;
1949 struct TcpHandshakeAckSignature thas;
1950 const struct GNUNET_CRYPTO_ChallengeNonceP challenge = queue->challenge;
1951
1953 "try handle plaintext!\n");
1954
1955 hdr = (const struct GNUNET_MessageHeader *) queue->pread_buf;
1956 if ((sizeof(*hdr) > queue->pread_off))
1957 {
1959 "Handling plaintext, not even a header!\n");
1960 return 0; /* not even a header */
1961 }
1962
1963 if ((GNUNET_YES != queue->initial_core_kx_done) && (queue->unverified_size >
1965 {
1967 "Already received data of size %lu bigger than KX size %lu!\n",
1968 queue->unverified_size,
1970 GNUNET_break_op (0);
1972 return 0;
1973 }
1974
1975 type = ntohs (hdr->type);
1976 switch (type)
1977 {
1979 tca = (const struct TCPConfirmationAck *) queue->pread_buf;
1981 "start processing ack\n");
1982 if (sizeof(*tca) > queue->pread_off)
1983 {
1985 "Handling plaintext size of tca greater than pread offset.\n")
1986 ;
1987 return 0;
1988 }
1989 if (ntohs (hdr->size) != sizeof(*tca))
1990 {
1992 "Handling plaintext size does not match message type.\n");
1993 GNUNET_break_op (0);
1995 return 0;
1996 }
1997
1998 thas.purpose.purpose = htonl (
2000 thas.purpose.size = htonl (sizeof(thas));
2001 thas.sender = tca->sender;
2002 thas.receiver = my_identity;
2003 thas.monotonic_time = tca->monotonic_time;
2004 thas.challenge = tca->challenge;
2005
2008 &thas,
2009 &tca->sender_sig,
2010 &tca->sender.public_key))
2011 {
2013 "Verification of signature failed!\n");
2014 GNUNET_break (0);
2016 return 0;
2017 }
2018 if (0 != GNUNET_memcmp (&tca->challenge, &challenge))
2019 {
2021 "Challenge in TCPConfirmationAck not correct!\n");
2022 GNUNET_break (0);
2024 return 0;
2025 }
2026
2027 queue->handshake_ack_monotime_get = GNUNET_PEERSTORE_iteration_start (
2028 peerstore,
2029 "transport_tcp_communicator",
2030 &queue->target,
2033 queue);
2034
2036 "Handling plaintext, ack processed!\n");
2037
2039 {
2040 send_challenge (queue->challenge_received, queue);
2041 queue->write_task =
2043 queue->sock,
2044 &queue_write,
2045 queue);
2046 }
2047 else if (GNUNET_TRANSPORT_CS_OUTBOUND == queue->cs)
2048 {
2050 queue->address->sa_family, NULL);
2051 }
2052
2057 queue->initial_core_kx_done = GNUNET_YES;
2058
2059 {
2060 char *foreign_addr;
2061
2062 switch (queue->address->sa_family)
2063 {
2064 case AF_INET:
2065 GNUNET_asprintf (&foreign_addr,
2066 "%s-%s",
2068 GNUNET_a2s (queue->address, queue->address_len));
2069 break;
2070
2071 case AF_INET6:
2072 GNUNET_asprintf (&foreign_addr,
2073 "%s-%s",
2075 GNUNET_a2s (queue->address, queue->address_len));
2076 break;
2077
2078 default:
2079 GNUNET_assert (0);
2080 }
2082 &queue->target,
2083 foreign_addr,
2084 UINT16_MAX, /* no MTU */
2086 0, /* Priority */
2087 queue->nt,
2088 queue->cs,
2089 queue->mq);
2090
2091 GNUNET_free (foreign_addr);
2092 }
2093
2094 size = ntohs (hdr->size);
2095 break;
2097 /* Special case: header size excludes box itself! */
2098 box = (const struct TCPBox *) queue->pread_buf;
2099 if (ntohs (hdr->size) + sizeof(struct TCPBox) > queue->pread_off)
2100 return 0;
2101 calculate_hmac (&queue->in_hmac, &box[1], ntohs (hdr->size), &tmac);
2102 if (0 != memcmp (&tmac, &box->hmac, sizeof(tmac)))
2103 {
2104 GNUNET_break_op (0);
2106 return 0;
2107 }
2108 pass_plaintext_to_core (queue, (const void *) &box[1], ntohs (hdr->size));
2109 size = ntohs (hdr->size) + sizeof(*box);
2111 "Handling plaintext, box processed!\n");
2113 "# bytes decrypted with BOX",
2114 size,
2115 GNUNET_NO);
2117 "# messages decrypted with BOX",
2118 1,
2119 GNUNET_NO);
2120 break;
2121
2123 rekey = (const struct TCPRekey *) queue->pread_buf;
2124 if (sizeof(*rekey) > queue->pread_off)
2125 return 0;
2126 if (ntohs (hdr->size) != sizeof(*rekey))
2127 {
2128 GNUNET_break_op (0);
2130 return 0;
2131 }
2132 rekeyz = *rekey;
2133 memset (&rekeyz.hmac, 0, sizeof(rekeyz.hmac));
2134 calculate_hmac (&queue->in_hmac, &rekeyz, sizeof(rekeyz), &tmac);
2135 if (0 != memcmp (&tmac, &rekey->hmac, sizeof(tmac)))
2136 {
2137 GNUNET_break_op (0);
2139 return 0;
2140 }
2141 do_rekey (queue, rekey);
2142 size = ntohs (hdr->size);
2144 "Handling plaintext, rekey processed!\n");
2146 "# rekeying successful",
2147 1,
2148 GNUNET_NO);
2149 break;
2150
2152 fin = (const struct TCPFinish *) queue->pread_buf;
2153 if (sizeof(*fin) > queue->pread_off)
2154 return 0;
2155 if (ntohs (hdr->size) != sizeof(*fin))
2156 {
2157 GNUNET_break_op (0);
2159 return 0;
2160 }
2161 finz = *fin;
2162 memset (&finz.hmac, 0, sizeof(finz.hmac));
2163 calculate_hmac (&queue->in_hmac, &finz, sizeof(finz), &tmac);
2164 if (0 != memcmp (&tmac, &fin->hmac, sizeof(tmac)))
2165 {
2166 GNUNET_break_op (0);
2168 return 0;
2169 }
2170 /* handle FINISH by destroying queue */
2173 "Handling plaintext, finish processed!\n");
2174 break;
2175
2176 default:
2178 "Handling plaintext, nothing processed!\n");
2179 GNUNET_break_op (0);
2181 return 0;
2182 }
2183 GNUNET_assert (0 != size);
2184 if (-1 != queue->unverified_size)
2185 queue->unverified_size += size;
2186 return size;
2187}

References calculate_hmac(), ch, TcpHandshakeAckSignature::challenge, TCPConfirmationAck::challenge, check_and_remove_pending_reversal(), COMMUNICATOR_ADDRESS_PREFIX, do_rekey(), GNUNET_a2s(), GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CRYPTO_eddsa_verify, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_memcmp, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY, GNUNET_NO, GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK, GNUNET_SCHEDULER_add_write_net(), GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_communicator_mq_add(), GNUNET_TRANSPORT_CS_INBOUND, GNUNET_TRANSPORT_CS_OUTBOUND, GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, GNUNET_YES, handshake_ack_monotime_cb(), TCPBox::hmac, TCPRekey::hmac, TCPFinish::hmac, INITIAL_CORE_KX_SIZE, TcpHandshakeAckSignature::monotonic_time, TCPConfirmationAck::monotonic_time, GNUNET_TRANSPORT_CommunicatorHandle::mq, my_identity, pass_plaintext_to_core(), peerstore, GNUNET_PeerIdentity::public_key, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpHandshakeAckSignature::purpose, queue(), queue_destroy(), queue_finish(), queue_write(), TcpHandshakeAckSignature::receiver, send_challenge(), TcpHandshakeAckSignature::sender, TCPConfirmationAck::sender, TCPConfirmationAck::sender_sig, GNUNET_MessageHeader::size, GNUNET_CRYPTO_SignaturePurpose::size, size, stats, type, and GNUNET_MessageHeader::type.

Referenced by queue_read().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ tcp_address_to_sockaddr_numeric_v6()

static struct sockaddr * tcp_address_to_sockaddr_numeric_v6 ( socklen_t *  sock_len,
struct sockaddr_in6  v6,
unsigned int  port 
)
static

Convert a struct sockaddr_in6 to astruct sockaddr *`.

Parameters
[out]sock_lenset to the length of the address.
v6The sockaddr_in6 to be converted.
Returns
The struct sockaddr *.

Definition at line 2324 of file gnunet-communicator-tcp.c.

2327{
2328 struct sockaddr *in;
2329
2330 v6.sin6_family = AF_INET6;
2331 v6.sin6_port = htons ((uint16_t) port);
2332#if HAVE_SOCKADDR_IN_SIN_LEN
2333 v6.sin6_len = sizeof(struct sockaddr_in6);
2334#endif
2335 v6.sin6_flowinfo = 0;
2336 v6.sin6_scope_id = 0;
2337 in = GNUNET_memdup (&v6, sizeof(v6));
2338 *sock_len = sizeof(struct sockaddr_in6);
2339
2340 return in;
2341}

References GNUNET_memdup, and port.

Referenced by init_socket_resolv(), run(), tcp_address_to_sockaddr(), and tcp_address_to_sockaddr_port_only().

Here is the caller graph for this function:

◆ tcp_address_to_sockaddr_numeric_v4()

static struct sockaddr * tcp_address_to_sockaddr_numeric_v4 ( socklen_t *  sock_len,
struct sockaddr_in  v4,
unsigned int  port 
)
static

Convert a struct sockaddr_in4 to astruct sockaddr *`.

Parameters
[out]sock_lenset to the length of the address.
v4The sockaddr_in4 to be converted.
Returns
The struct sockaddr *.

Definition at line 2352 of file gnunet-communicator-tcp.c.

2355{
2356 struct sockaddr *in;
2357
2358 v4.sin_family = AF_INET;
2359 v4.sin_port = htons ((uint16_t) port);
2360#if HAVE_SOCKADDR_IN_SIN_LEN
2361 v4.sin_len = sizeof(struct sockaddr_in);
2362#endif
2363 in = GNUNET_memdup (&v4, sizeof(v4));
2364 *sock_len = sizeof(struct sockaddr_in);
2365 return in;
2366}

References GNUNET_memdup, and port.

Referenced by init_socket_resolv(), run(), tcp_address_to_sockaddr(), and tcp_address_to_sockaddr_port_only().

Here is the caller graph for this function:

◆ tcp_address_to_sockaddr_port_only()

static struct PortOnlyIpv4Ipv6 * tcp_address_to_sockaddr_port_only ( const char *  bindto,
unsigned int *  port 
)
static

Convert TCP bind specification to a struct PortOnlyIpv4Ipv6 *

Parameters
bindtobind specification to convert.
Returns
The converted bindto specification.

Definition at line 2376 of file gnunet-communicator-tcp.c.

2377{
2378 struct PortOnlyIpv4Ipv6 *po;
2379 struct sockaddr_in *i4;
2380 struct sockaddr_in6 *i6;
2381 socklen_t sock_len_ipv4;
2382 socklen_t sock_len_ipv6;
2383
2384 /* interpreting value as just a PORT number */
2385 if (*port > UINT16_MAX)
2386 {
2388 "BINDTO specification `%s' invalid: value too large for port\n",
2389 bindto);
2390 return NULL;
2391 }
2392
2393 po = GNUNET_new (struct PortOnlyIpv4Ipv6);
2394
2395 if (GNUNET_YES == disable_v6)
2396 {
2397 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2398 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2399 *port);
2400 po->addr_len_ipv4 = sock_len_ipv4;
2401 }
2402 else
2403 {
2404
2405 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2406 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2407 *port);
2408 po->addr_len_ipv4 = sock_len_ipv4;
2409
2410 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
2411 po->addr_ipv6 = tcp_address_to_sockaddr_numeric_v6 (&sock_len_ipv6, *i6,
2412 *port);
2413
2414 po->addr_len_ipv6 = sock_len_ipv6;
2415
2416 GNUNET_free (i6);
2417 }
2418
2419 GNUNET_free (i4);
2420
2421 return po;
2422}

References PortOnlyIpv4Ipv6::addr_ipv4, PortOnlyIpv4Ipv6::addr_ipv6, PortOnlyIpv4Ipv6::addr_len_ipv4, PortOnlyIpv4Ipv6::addr_len_ipv6, disable_v6, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_new, GNUNET_YES, port, tcp_address_to_sockaddr_numeric_v4(), and tcp_address_to_sockaddr_numeric_v6().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ extract_address()

static char * extract_address ( const char *  bindto)
static

This Method extracts the address part of the BINDTO string.

Parameters
bindtoString we extract the address part from.
Returns
The extracted address string.

Definition at line 2432 of file gnunet-communicator-tcp.c.

2433{
2434 char *addr;
2435 char *start;
2436 char *token;
2437 char *cp;
2438 char *rest = NULL;
2439
2441 "extract address with bindto %s\n",
2442 bindto);
2443
2444 if (NULL == bindto)
2446 "bindto is NULL\n");
2447
2448 cp = GNUNET_strdup (bindto);
2449
2451 "extract address 2\n");
2452
2453 start = cp;
2454 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
2455 {
2456 start++; /* skip over '['*/
2457 cp[strlen (cp) - 1] = '\0'; /* eat ']'*/
2458 addr = GNUNET_strdup (start);
2459 }
2460 else
2461 {
2462 token = strtok_r (cp, "]", &rest);
2463 if (strlen (bindto) == strlen (token))
2464 {
2465 token = strtok_r (cp, ":", &rest);
2466 addr = GNUNET_strdup (token);
2467 }
2468 else
2469 {
2470 token++;
2471 addr = GNUNET_strdup (token);
2472 }
2473 }
2474
2476 "tcp address: %s\n",
2477 addr);
2478 GNUNET_free (cp);
2479 return addr;
2480}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_strdup, and start.

Referenced by run(), and tcp_address_to_sockaddr().

Here is the caller graph for this function:

◆ extract_port()

static unsigned int extract_port ( const char *  addr_and_port)
static

This Method extracts the port part of the BINDTO string.

Parameters
addr_and_portString we extract the port from.
Returns
The extracted port as unsigned int.

Definition at line 2490 of file gnunet-communicator-tcp.c.

2491{
2492 unsigned int port;
2493 char dummy[2];
2494 char *token;
2495 char *addr;
2496 char *colon;
2497 char *cp;
2498 char *rest = NULL;
2499
2500 if (NULL != addr_and_port)
2501 {
2502 cp = GNUNET_strdup (addr_and_port);
2503 token = strtok_r (cp, "]", &rest);
2504 if (strlen (addr_and_port) == strlen (token))
2505 {
2506 colon = strrchr (cp, ':');
2507 if (NULL == colon)
2508 {
2509 GNUNET_free (cp);
2510 return 0;
2511 }
2512 addr = colon;
2513 addr++;
2514 }
2515 else
2516 {
2517 token = strtok_r (NULL, "]", &rest);
2518 if (NULL == token)
2519 {
2520 GNUNET_free (cp);
2521 return 0;
2522 }
2523 else
2524 {
2525 addr = token;
2526 addr++;
2527 }
2528 }
2529
2530
2531 if (1 == sscanf (addr, "%u%1s", &port, dummy))
2532 {
2533 /* interpreting value as just a PORT number */
2534 if (port > UINT16_MAX)
2535 {
2537 "Port `%u' invalid: value too large for port\n",
2538 port);
2539 GNUNET_free (cp);
2540 return 0;
2541 }
2542 }
2543 else
2544 {
2546 "BINDTO specification invalid: last ':' not followed by number\n");
2547 GNUNET_free (cp);
2548 return 0;
2549 }
2550 GNUNET_free (cp);
2551 }
2552 else
2553 {
2555 "return 0\n");
2556 /* interpret missing port as 0, aka pick any free one */
2557 port = 0;
2558 }
2559
2560 return port;
2561}

References dummy, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_strdup, and port.

Referenced by run(), and tcp_address_to_sockaddr().

Here is the caller graph for this function:

◆ tcp_address_to_sockaddr()

static struct sockaddr * tcp_address_to_sockaddr ( const char *  bindto,
socklen_t *  sock_len 
)
static

Convert TCP bind specification to a struct sockaddr *

Parameters
bindtobind specification to convert
[out]sock_lenset to the length of the address
Returns
converted bindto specification

Definition at line 2572 of file gnunet-communicator-tcp.c.

2573{
2574 struct sockaddr *in;
2575 unsigned int port;
2576 struct sockaddr_in v4;
2577 struct sockaddr_in6 v6;
2578 char *start;
2579
2580 memset (&v4, 0, sizeof(v4));
2581 start = extract_address (bindto);
2582 GNUNET_assert (NULL != start);
2584 "start %s\n",
2585 start);
2586
2588 "!bindto %s\n",
2589 bindto);
2590
2591
2592 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
2593 {
2594 port = extract_port (bindto);
2595
2597 "port %u\n",
2598 port);
2599
2600 in = tcp_address_to_sockaddr_numeric_v4 (sock_len, v4, port);
2601 }
2602 else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
2603 {
2604 port = extract_port (bindto);
2605 in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port);
2606 }
2607 else
2608 {
2609 GNUNET_assert (0);
2610 }
2611
2613 return in;
2614}

References extract_address(), extract_port(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, port, start, tcp_address_to_sockaddr_numeric_v4(), and tcp_address_to_sockaddr_numeric_v6().

Referenced by mq_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_send()

static void mq_send ( struct GNUNET_MQ_Handle mq,
const struct GNUNET_MessageHeader msg,
void *  impl_state 
)
static

Signature of functions implementing the sending functionality of a message queue.

Parameters
mqthe message queue
msgthe message to send
impl_stateour struct Queue

Definition at line 2626 of file gnunet-communicator-tcp.c.

2629{
2630 struct Queue *queue = impl_state;
2631 uint16_t msize = ntohs (msg->size);
2632 struct TCPBox box;
2634 "In MQ send. Queue finishing: %s; write task running: %s\n",
2635 (GNUNET_YES == queue->finishing) ? "yes" : "no",
2636 (NULL == queue->write_task) ? "yes" : "no");
2637 GNUNET_assert (mq == queue->mq);
2638 queue->mq_awaits_continue = GNUNET_YES;
2639 if (GNUNET_YES == queue->finishing)
2640 return; /* this queue is dying, drop msg */
2641 GNUNET_assert (0 == queue->pwrite_off);
2642 box.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX);
2643 box.header.size = htons (msize);
2644 calculate_hmac (&queue->out_hmac, msg, msize, &box.hmac);
2645 memcpy (&queue->pwrite_buf[queue->pwrite_off], &box, sizeof(box));
2646 queue->pwrite_off += sizeof(box);
2647 memcpy (&queue->pwrite_buf[queue->pwrite_off], msg, msize);
2648 queue->pwrite_off += msize;
2650 "%lu bytes of plaintext to send\n", queue->pwrite_off);
2651 GNUNET_assert (NULL != queue->sock);
2652 if (NULL == queue->write_task)
2653 queue->write_task =
2655 queue->sock,
2656 &queue_write,
2657 queue);
2658}

References calculate_hmac(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX, GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, TCPBox::header, TCPBox::hmac, mq, msg, queue(), queue_write(), GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by boot_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_destroy()

static void mq_destroy ( struct GNUNET_MQ_Handle mq,
void *  impl_state 
)
static

Signature of functions implementing the destruction of a message queue.

Implementations must not free mq, but should take care of impl_state.

Parameters
mqthe message queue to destroy
impl_stateour struct Queue

Definition at line 2670 of file gnunet-communicator-tcp.c.

2671{
2672 struct Queue *queue = impl_state;
2673
2674 if (mq == queue->mq)
2675 {
2676 queue->mq = NULL;
2678 }
2679}

References mq, Queue::mq, queue(), and queue_finish().

Referenced by boot_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_cancel()

static void mq_cancel ( struct GNUNET_MQ_Handle mq,
void *  impl_state 
)
static

Implementation function that cancels the currently sent message.

Parameters
mqmessage queue
impl_stateour struct Queue

Definition at line 2689 of file gnunet-communicator-tcp.c.

2690{
2691 struct Queue *queue = impl_state;
2692
2693 GNUNET_assert (0 != queue->pwrite_off);
2694 queue->pwrite_off = 0;
2695}

References GNUNET_assert, and queue().

Referenced by boot_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_error()

static void mq_error ( void *  cls,
enum GNUNET_MQ_Error  error 
)
static

Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.

Not every message queue implementation supports an error handler.

Parameters
clsour struct Queue
errorerror code

Definition at line 2708 of file gnunet-communicator-tcp.c.

2709{
2710 struct Queue *queue = cls;
2711
2713 "MQ error in queue to %s: %d\n",
2714 GNUNET_i2s (&queue->target),
2715 (int) error);
2717}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_log, queue(), and queue_finish().

Referenced by boot_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ boot_queue()

static void boot_queue ( struct Queue queue)
static

Add the given queue to our internal data structure.

Setup the MQ processing and inform transport that the queue is ready. Must be called after the KX for outgoing messages has been bootstrapped.

Parameters
queuequeue to boot

Definition at line 2728 of file gnunet-communicator-tcp.c.

2729{
2730 queue->nt =
2731 GNUNET_NT_scanner_get_type (is, queue->address, queue->address_len);
2733 queue_map,
2734 &queue->key,
2735 queue,
2738 "# queues active",
2740 GNUNET_NO);
2741 queue->timeout =
2744 &mq_destroy,
2745 &mq_cancel,
2746 queue,
2747 NULL,
2748 &mq_error,
2749 queue);
2750}

References GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_MQ_queue_for_callbacks(), GNUNET_NO, GNUNET_NT_scanner_get_type(), GNUNET_STATISTICS_set(), GNUNET_TIME_relative_to_absolute(), is, mq_cancel(), mq_destroy(), mq_error(), mq_send(), queue(), queue_map, and stats.

Referenced by mq_init(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transmit_kx()

static void transmit_kx ( struct Queue queue,
const struct GNUNET_CRYPTO_HpkeEncapsulation c 
)
static

Generate and transmit our ephemeral key and the signature for the initial KX with the other peer.

Must be called first, before any other bytes are ever written to the output buffer. Note that our cipher must already be initialized when calling this function. Helper function for start_initial_kx_out().

Parameters
queuequeue to do KX for
epubour public key for the KX

Definition at line 2764 of file gnunet-communicator-tcp.c.

2766{
2767 struct TcpHandshakeSignature ths;
2768 struct TCPConfirmation tc;
2769
2770 memcpy (queue->cwrite_buf, c, sizeof(*c));
2771 queue->cwrite_off = sizeof(*c);
2772 /* compute 'tc' and append in encrypted format to cwrite_buf */
2773 tc.sender = my_identity;
2774 tc.monotonic_time =
2777 &tc.challenge,
2778 sizeof(tc.challenge));
2779 ths.purpose.purpose = htonl (
2781 ths.purpose.size = htonl (sizeof(ths));
2782 ths.sender = my_identity;
2783 ths.receiver = queue->target;
2784 ths.ephemeral = *c;
2785 ths.monotonic_time = tc.monotonic_time;
2786 ths.challenge = tc.challenge;
2788 &ths,
2789 &tc.sender_sig);
2790 GNUNET_assert (0 ==
2791 gcry_cipher_encrypt (queue->out_cipher,
2792 &queue->cwrite_buf[queue->cwrite_off],
2793 sizeof(tc),
2794 &tc,
2795 sizeof(tc)));
2796 queue->challenge = tc.challenge;
2797 queue->cwrite_off += sizeof(tc);
2798
2800 "handshake written\n");
2801}

References cfg, TcpHandshakeSignature::challenge, TcpHandshakeSignature::ephemeral, GNUNET_assert, GNUNET_CRYPTO_eddsa_sign, GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE, GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), TcpHandshakeSignature::monotonic_time, my_identity, my_private_key, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpHandshakeSignature::purpose, queue(), TcpHandshakeSignature::receiver, TcpHandshakeSignature::sender, GNUNET_CRYPTO_SignaturePurpose::size, and tc.

Referenced by start_initial_kx_out().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_initial_kx_out()

static void start_initial_kx_out ( struct Queue queue)
static

Initialize our key material for outgoing transmissions and inform the other peer about it.

Must be called first before any data is sent.

Parameters
queuethe queue to setup

Definition at line 2812 of file gnunet-communicator-tcp.c.

2813{
2815 struct GNUNET_ShortHashCode k;
2816
2818 &c, &k);
2819 setup_out_cipher (queue, &k);
2820 transmit_kx (queue, &c);
2821}

References GNUNET_CRYPTO_hpke_elligator_kem_encaps(), queue(), setup_out_cipher(), and transmit_kx().

Referenced by mq_init(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handshake_monotime_store_cb()

static void handshake_monotime_store_cb ( void *  cls,
int  success 
)
static

Callback called when peerstore store operation for handshake monotime is finished.

Parameters
clsQueue context the store operation was executed.
successStore operation was successful (GNUNET_OK) or not.

Definition at line 2830 of file gnunet-communicator-tcp.c.

2831{
2832 struct Queue *queue = cls;
2833 if (GNUNET_OK != success)
2834 {
2836 "Failed to store handshake monotonic time in PEERSTORE!\n");
2837 }
2838 queue->handshake_monotime_sc = NULL;
2839 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
2840}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_PEERSTORE_iteration_next(), and queue().

Referenced by handshake_monotime_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handshake_monotime_cb()

static void handshake_monotime_cb ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE where found.

Parameters
clsQueue context the store operation was executed.
recordThe record found or NULL if there is no record left.
emsgMessage from peerstore.

Definition at line 2851 of file gnunet-communicator-tcp.c.

2854{
2855 struct Queue *queue = cls;
2856 struct GNUNET_TIME_AbsoluteNBO *mtbe;
2857 struct GNUNET_TIME_Absolute mt;
2858 const struct GNUNET_PeerIdentity *pid;
2859 struct GNUNET_TIME_AbsoluteNBO *handshake_monotonic_time;
2860
2861 (void) emsg;
2862
2863 handshake_monotonic_time = &queue->handshake_monotonic_time;
2864 pid = &queue->target;
2866 "tcp handshake with us %s\n",
2868 if (NULL == record)
2869 {
2870 queue->handshake_monotime_get = NULL;
2871 return;
2872 }
2874 "tcp handshake from peer %s\n",
2875 GNUNET_i2s (pid));
2876 if (sizeof(*mtbe) != record->value_size)
2877 {
2878 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
2879 GNUNET_break (0);
2880 return;
2881 }
2882 mtbe = record->value;
2883 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
2884 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
2885 queue->handshake_monotonic_time).abs_value_us)
2886 {
2888 "Queue from %s dropped, handshake monotime in the past\n",
2889 GNUNET_i2s (&queue->target));
2890 GNUNET_break (0);
2891 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
2892 queue->handshake_ack_monotime_get = NULL;
2894 return;
2895 }
2896 queue->handshake_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
2897 "transport_tcp_communicator",
2898 pid,
2900 handshake_monotonic_time,
2901 sizeof(*
2902 handshake_monotonic_time),
2905 &
2907 queue);
2908}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_log, GNUNET_PEERSTORE_iteration_next(), GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_REPLACE, GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE, GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_UNIT_FOREVER_ABS, handshake_monotime_store_cb(), my_identity, peerstore, pid, queue(), queue_finish(), and record().

Referenced by decrypt_and_check_tc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ decrypt_and_check_tc()

static int decrypt_and_check_tc ( struct Queue queue,
struct TCPConfirmation tc,
char *  ibuf 
)
static

We have received the first bytes from the other side on a queue.

Decrypt the tc contained in ibuf and check the signature. Note that setup_in_cipher() must have already been called.

Parameters
queuequeue to decrypt initial bytes from other peer for
[out]tcwhere to store the result
ibufincoming data, of size INITIAL_KX_SIZE
Returns
GNUNET_OK if the signature was OK, GNUNET_SYSERR if not

Definition at line 2923 of file gnunet-communicator-tcp.c.

2926{
2927 struct TcpHandshakeSignature ths;
2929
2931 0 ==
2932 gcry_cipher_decrypt (queue->in_cipher,
2933 tc,
2934 sizeof(*tc),
2935 &ibuf[sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)],
2936 sizeof(*tc)));
2937 ths.purpose.purpose = htonl (
2939 ths.purpose.size = htonl (sizeof(ths));
2940 ths.sender = tc->sender;
2941 ths.receiver = my_identity;
2942 memcpy (&ths.ephemeral, ibuf, sizeof(struct GNUNET_CRYPTO_EcdhePublicKey));
2943 ths.monotonic_time = tc->monotonic_time;
2944 ths.challenge = tc->challenge;
2947 &ths,
2948 &tc->sender_sig,
2949 &tc->sender.public_key);
2950 if (GNUNET_YES == ret)
2951 queue->handshake_monotime_get =
2953 "transport_tcp_communicator",
2954 &queue->target,
2957 queue);
2958 return ret;
2959}

References TcpHandshakeSignature::challenge, TcpHandshakeSignature::ephemeral, GNUNET_assert, GNUNET_CRYPTO_eddsa_verify, GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE, GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE, GNUNET_YES, handshake_monotime_cb(), TcpHandshakeSignature::monotonic_time, my_identity, peerstore, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpHandshakeSignature::purpose, queue(), TcpHandshakeSignature::receiver, ret, TcpHandshakeSignature::sender, GNUNET_CRYPTO_SignaturePurpose::size, and tc.

Referenced by proto_read_kx(), and queue_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_read_kx()

static void queue_read_kx ( void *  cls)
static

Read from the socket of the queue until we have enough data to initialize the decryption logic and can switch to regular reading.

Parameters
clsa struct Queue

Definition at line 2970 of file gnunet-communicator-tcp.c.

2971{
2972 struct Queue *queue = cls;
2973 ssize_t rcvd;
2974 struct GNUNET_TIME_Relative left;
2975 struct TCPConfirmation tc;
2976
2977 queue->read_task = NULL;
2978 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2979 if (0 == left.rel_value_us)
2980 {
2982 return;
2983 }
2984 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2985 &queue->cread_buf[queue->cread_off],
2986 BUF_SIZE - queue->cread_off);
2988 "Received %lu bytes to write in buffer of size %lu for KX from queue %p (expires in %"
2989 PRIu64 ")\n",
2990 rcvd, BUF_SIZE - queue->cread_off, queue, left.rel_value_us);
2991 if (-1 == rcvd)
2992 {
2993 if ((EAGAIN != errno) && (EINTR != errno))
2994 {
2997 return;
2998 }
2999 queue->read_task =
3001 return;
3002 }
3003 if (0 == rcvd)
3004 {
3005 /* Orderly shutdown of connection */
3007 "Socket for queue %p seems to have been closed\n", queue);
3009 return;
3010 }
3011 queue->cread_off += rcvd;
3012 if (queue->cread_off < INITIAL_KX_SIZE)
3013 {
3014 /* read more */
3016 "%lu/%lu bytes of KX read. Rescheduling...\n",
3017 queue->cread_off, INITIAL_KX_SIZE);
3018 queue->read_task =
3020 return;
3021 }
3022 /* we got all the data, let's find out who we are talking to! */
3024 (const struct GNUNET_CRYPTO_HpkeEncapsulation*)
3025 queue->cread_buf,
3026 queue);
3027 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
3028 {
3030 "Invalid TCP KX received from %s\n",
3031 GNUNET_a2s (queue->address, queue->address_len));
3033 return;
3034 }
3035 if (0 !=
3036 memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
3037 {
3039 "Invalid sender in TCP KX received from %s\n",
3040 GNUNET_a2s (queue->address, queue->address_len));
3042 return;
3043 }
3044 send_challenge (tc.challenge, queue);
3045 queue->write_task =
3047 queue->sock,
3048 &queue_write,
3049 queue);
3050
3051 /* update queue timeout */
3052 queue->timeout =
3054 /* prepare to continue with regular read task immediately */
3055 memmove (queue->cread_buf,
3056 &queue->cread_buf[INITIAL_KX_SIZE],
3057 queue->cread_off - (INITIAL_KX_SIZE));
3059 "cread_off is %lu bytes before adjusting\n",
3060 queue->cread_off);
3061 queue->cread_off -= INITIAL_KX_SIZE;
3063 "cread_off set to %lu bytes\n",
3064 queue->cread_off);
3066}

References BUF_SIZE, decrypt_and_check_tc(), GNUNET_a2s(), GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_recv(), GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_FOREVER_REL, INITIAL_KX_SIZE, queue(), queue_destroy(), queue_read(), queue_read_kx(), queue_write(), GNUNET_TIME_Relative::rel_value_us, send_challenge(), setup_in_cipher_elligator(), and tc.

Referenced by mq_init(), proto_read_kx(), and queue_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ proto_read_kx()

static void proto_read_kx ( void *  cls)
static

Read from the socket of the proto queue until we have enough data to upgrade to full queue.

Parameters
clsa struct ProtoQueue

Definition at line 3076 of file gnunet-communicator-tcp.c.

3077{
3078 struct ProtoQueue *pq = cls;
3079 ssize_t rcvd;
3080 struct GNUNET_TIME_Relative left;
3081 struct Queue *queue;
3082 struct TCPConfirmation tc;
3084
3085 pq->read_task = NULL;
3087 if (0 == left.rel_value_us)
3088 {
3089 free_proto_queue (pq);
3090 return;
3091 }
3092 rcvd = GNUNET_NETWORK_socket_recv (pq->sock,
3093 &pq->ibuf[pq->ibuf_off],
3094 sizeof(pq->ibuf) - pq->ibuf_off);
3096 "Proto received %lu bytes for KX\n", rcvd);
3097 if (-1 == rcvd)
3098 {
3099 if ((EAGAIN != errno) && (EINTR != errno))
3100 {
3102 free_proto_queue (pq);
3103 return;
3104 }
3105 /* try again */
3106 pq->read_task =
3108 return;
3109 }
3110 if (0 == rcvd)
3111 {
3112 /* Orderly shutdown of connection */
3114 "Socket for proto queue %p seems to have been closed\n", pq);
3115 free_proto_queue (pq);
3116 return;
3117 }
3118 pq->ibuf_off += rcvd;
3119 if (sizeof (struct TCPNATProbeMessage) == pq->ibuf_off)
3120 {
3121 struct TCPNATProbeMessage *pm = (struct TCPNATProbeMessage *) pq->ibuf;
3122
3124 &pm->clientIdentity);
3125
3126 queue = GNUNET_new (struct Queue);
3127 queue->target = pm->clientIdentity;
3128 eddsa_pub_to_hpke_key (&queue->target.public_key,
3129 &queue->target_hpke_key);
3132 }
3133 else if (pq->ibuf_off > sizeof(pq->ibuf))
3134 {
3135 /* read more */
3136 pq->read_task =
3138 return;
3139 }
3140 else
3141 {
3142 /* we got all the data, let's find out who we are talking to! */
3143 queue = GNUNET_new (struct Queue);
3145 (const struct GNUNET_CRYPTO_HpkeEncapsulation *) pq->
3146 ibuf,
3147 queue);
3148 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
3149 {
3151 "Invalid TCP KX received from %s\n",
3152 GNUNET_a2s (pq->address, pq->address_len));
3153 gcry_cipher_close (queue->in_cipher);
3155 free_proto_queue (pq);
3156 return;
3157 }
3158 queue->target = tc.sender;
3159 eddsa_pub_to_hpke_key (&queue->target.public_key,
3160 &queue->target_hpke_key);
3163 }
3164 queue->address = pq->address; /* steals reference */
3165 queue->address_len = pq->address_len;
3166 queue->listen_sock = pq->listen_sock;
3167 queue->sock = pq->sock;
3168
3170 "created queue with target %s\n",
3171 GNUNET_i2s (&queue->target));
3172
3174 "start kx proto\n");
3175
3177 boot_queue (queue);
3178 queue->read_task =
3180 queue->sock,
3181 read_task,
3182 queue);
3183 queue->write_task =
3185 queue->sock,
3186 &queue_write,
3187 queue);
3188 // TODO To early! Move it somewhere else.
3189 // send_challenge (tc.challenge, queue);
3190 queue->challenge_received = tc.challenge;
3191
3193 GNUNET_free (pq);
3194}

References ProtoQueue::address, ProtoQueue::address_len, boot_queue(), check_and_remove_pending_reversal(), decrypt_and_check_tc(), eddsa_pub_to_hpke_key(), free_proto_queue(), GNUNET_a2s(), GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_recv(), GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_CS_INBOUND, GNUNET_TRANSPORT_CS_OUTBOUND, ProtoQueue::ibuf, ProtoQueue::ibuf_off, ProtoQueue::listen_sock, pm, proto_head, proto_read_kx(), proto_tail, queue(), queue_read(), queue_read_kx(), queue_write(), read_task, ProtoQueue::read_task, GNUNET_TIME_Relative::rel_value_us, setup_in_cipher_elligator(), ProtoQueue::sock, start_initial_kx_out(), tc, and ProtoQueue::timeout.

Referenced by create_proto_queue(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_proto_queue()

static struct ProtoQueue * create_proto_queue ( struct GNUNET_NETWORK_Handle sock,
struct sockaddr *  in,
socklen_t  addrlen 
)
static

Definition at line 3198 of file gnunet-communicator-tcp.c.

3201{
3202 struct ProtoQueue *pq = GNUNET_new (struct ProtoQueue);
3203
3204 if (NULL == sock)
3205 {
3206 // sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
3207 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 0);
3208 if (NULL == sock)
3209 {
3211 "socket(%d) failed: %s",
3212 in->sa_family,
3213 strerror (errno));
3214 GNUNET_free (in);
3215 GNUNET_free (pq);
3216 return NULL;
3217 }
3218 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, addrlen)) &&
3219 (errno != EINPROGRESS))
3220 {
3222 "connect to `%s' failed: %s",
3223 GNUNET_a2s (in, addrlen),
3224 strerror (errno));
3226 GNUNET_free (in);
3227 GNUNET_free (pq);
3228 return NULL;
3229 }
3230 }
3231 pq->address_len = addrlen;
3232 pq->address = in;
3234 pq->sock = sock;
3236 pq->sock,
3238 pq);
3240
3241 return pq;
3242}

References ProtoQueue::address, ProtoQueue::address_len, GNUNET_a2s(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_connect(), GNUNET_NETWORK_socket_create(), GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_relative_to_absolute(), proto_head, PROTO_QUEUE_TIMEOUT, proto_read_kx(), proto_tail, ProtoQueue::read_task, ProtoQueue::sock, and ProtoQueue::timeout.

Referenced by listen_cb(), and try_connection_reversal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_connection_reversal()

static void try_connection_reversal ( void *  cls,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Definition at line 3292 of file gnunet-communicator-tcp.c.

3295{
3296 struct TCPNATProbeMessage pm;
3297 struct ProtoQueue *pq;
3298 struct sockaddr *in_addr;
3299 (void) cls;
3300
3302 "addr->sa_family %d\n",
3303 addr->sa_family);
3305 "Try to connect back\n");
3306 in_addr = GNUNET_memdup (addr, addrlen);
3308 "in_addr->sa_family %d\n",
3309 in_addr->sa_family);
3310 pq = create_proto_queue (NULL, in_addr, addrlen);
3311 if (NULL != pq)
3312 {
3313 pm.header.size = htons (sizeof(struct TCPNATProbeMessage));
3314 pm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
3315 pm.clientIdentity = my_identity;
3316 memcpy (pq->write_buf, &pm, sizeof(struct TCPNATProbeMessage));
3317 pq->write_off = sizeof(struct TCPNATProbeMessage);
3319 pq->sock,
3321 pq);
3322 }
3323 else
3324 {
3326 "Couldn't create ProtoQueue for sending TCPNATProbeMessage\n");
3327 }
3328}

References create_proto_queue(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_memdup, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE, GNUNET_SCHEDULER_add_write_net(), my_identity, pm, PROTO_QUEUE_TIMEOUT, proto_queue_write(), ProtoQueue::sock, ProtoQueue::write_buf, ProtoQueue::write_off, and ProtoQueue::write_task.

Referenced by nat_register().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pending_reversal_timeout()

static void pending_reversal_timeout ( void *  cls)
static

Definition at line 3332 of file gnunet-communicator-tcp.c.

3333{
3334 struct sockaddr *in = cls;
3335 struct PendingReversal *pending_reversal;
3336 struct GNUNET_HashCode key;
3337
3339 sizeof(struct sockaddr),
3340 &key);
3342 &key);
3343
3344 GNUNET_assert (NULL != pending_reversal);
3345
3347 &key,
3348 pending_reversal))
3350 "No pending reversal found for address %s\n",
3351 GNUNET_a2s (in, sizeof (struct sockaddr)));
3352 GNUNET_free (pending_reversal->in);
3353 GNUNET_free (pending_reversal);
3354}

References GNUNET_a2s(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_NO, PendingReversal::in, key, and pending_reversals.

Referenced by mq_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_init()

static int mq_init ( void *  cls,
const struct GNUNET_PeerIdentity peer,
const char *  address 
)
static

Function called by the transport service to initialize a message queue given address information about another peer.

If and when the communication channel is established, the communicator must call GNUNET_TRANSPORT_communicator_mq_add() to notify the service that the channel is now up. It is the responsibility of the communicator to manage sane retries and timeouts for any peer/address combination provided by the transport service. Timeouts and retries do not need to be signalled to the transport service.

Parameters
clsclosure
peeridentity of the other peer
addresswhere to send the message, human-readable communicator-specific format, 0-terminated, UTF-8
Returns
GNUNET_OK on success, GNUNET_SYSERR if the provided address is invalid

Definition at line 3376 of file gnunet-communicator-tcp.c.

3377{
3378 struct sockaddr *in;
3379 socklen_t in_len = 0;
3380 const char *path;
3381 struct sockaddr_in *v4;
3382 struct sockaddr_in6 *v6;
3383 unsigned int is_natd = GNUNET_NO;
3384 struct GNUNET_HashCode key;
3385 struct GNUNET_HashCode queue_map_key;
3386 struct GNUNET_HashContext *hsh;
3387 struct Queue *queue;
3388
3390 "Connecting to %s at %s\n",
3391 GNUNET_i2s (peer),
3392 address);
3393 if (0 != strncmp (address,
3395 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
3396 {
3397 GNUNET_break_op (0);
3398 return GNUNET_SYSERR;
3399 }
3400 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
3401 in = tcp_address_to_sockaddr (path, &in_len);
3402
3403 if (NULL == in)
3404 {
3406 "Failed to setup TCP socket address\n");
3407 return GNUNET_SYSERR;
3408 }
3409
3411 "in %s\n",
3412 GNUNET_a2s (in, in_len));
3413
3416 GNUNET_CRYPTO_hash_context_read (hsh, peer, sizeof (*peer));
3417 GNUNET_CRYPTO_hash_context_finish (hsh, &queue_map_key);
3419
3420 if (NULL != queue)
3421 {
3423 "Queue for %s already exists or is in construction\n", address);
3424 GNUNET_free (in);
3425 return GNUNET_NO;
3426 }
3427 switch (in->sa_family)
3428 {
3429 case AF_INET:
3430 v4 = (struct sockaddr_in *) in;
3431 if (0 == v4->sin_port)
3432 {
3433 is_natd = GNUNET_YES;
3435 sizeof(struct sockaddr),
3436 &key);
3439 &key))
3440 {
3442 "There is already a request reversal for `%s'at `%s'\n",
3443 GNUNET_i2s (peer),
3444 address);
3445 GNUNET_free (in);
3446 return GNUNET_SYSERR;
3447 }
3448 }
3449 break;
3450
3451 case AF_INET6:
3452 if (GNUNET_YES == disable_v6)
3453 {
3455 "IPv6 disabled, skipping %s\n", address);
3456 GNUNET_free (in);
3457 return GNUNET_SYSERR;
3458 }
3459 v6 = (struct sockaddr_in6 *) in;
3460 if (0 == v6->sin6_port)
3461 {
3463 "Request reversal for `%s' at `%s' not possible for an IPv6 address\n",
3464 GNUNET_i2s (peer),
3465 address);
3466 GNUNET_free (in);
3467 return GNUNET_SYSERR;
3468 }
3469 break;
3470
3471 default:
3472 GNUNET_assert (0);
3473 }
3474
3475 if (GNUNET_YES == is_natd)
3476 {
3477 struct sockaddr_in local_sa;
3478 struct PendingReversal *pending_reversal;
3479
3480 memset (&local_sa, 0, sizeof(local_sa));
3481 local_sa.sin_family = AF_INET;
3482 local_sa.sin_port = htons (bind_port);
3483 /* We leave sin_address at 0, let the kernel figure it out,
3484 even if our bind() is more specific. (May want to reconsider
3485 later.) */
3486 if (GNUNET_OK != GNUNET_NAT_request_reversal (nat, &local_sa, v4))
3487 {
3489 "request reversal for `%s' at `%s' failed\n",
3490 GNUNET_i2s (peer),
3491 address);
3492 GNUNET_free (in);
3493 return GNUNET_SYSERR;
3494 }
3495 pending_reversal = GNUNET_new (struct PendingReversal);
3496 pending_reversal->in = in;
3499 &key,
3500 pending_reversal,
3502 pending_reversal->target = *peer;
3504 &
3506 in);
3508 "Created NAT WAIT connection to `%s' at `%s'\n",
3509 GNUNET_i2s (peer),
3510 GNUNET_a2s (in, sizeof (struct sockaddr)));
3511 }
3512 else
3513 {
3514 struct GNUNET_NETWORK_Handle *sock;
3515
3516 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM,
3517 IPPROTO_TCP);
3518 if (NULL == sock)
3519 {
3521 "socket(%d) failed: %s",
3522 in->sa_family,
3523 strerror (errno));
3524 GNUNET_free (in);
3525 return GNUNET_SYSERR;
3526 }
3527 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
3528 (errno != EINPROGRESS))
3529 {
3531 "connect to `%s' failed: %s",
3532 address,
3533 strerror (errno));
3535 GNUNET_free (in);
3536 return GNUNET_SYSERR;
3537 }
3538
3539 queue = GNUNET_new (struct Queue);
3540 queue->target = *peer;
3541 eddsa_pub_to_hpke_key (&queue->target.public_key, &queue->target_hpke_key);
3542 queue->key = queue_map_key;
3543 queue->address = in;
3544 queue->address_len = in_len;
3545 queue->sock = sock;
3547 boot_queue (queue);
3549 "booted queue with target %s\n",
3550 GNUNET_i2s (&queue->target));
3551 // queue->mq_awaits_continue = GNUNET_YES;
3552 queue->read_task =
3554 queue->sock,
3556 queue);
3557
3558
3560 "start kx mq_init\n");
3561
3563 queue->write_task =
3565 queue->sock,
3566 &queue_write,
3567 queue);
3568 }
3569
3570 return GNUNET_OK;
3571}

References address, bind_port, boot_queue(), COMMUNICATOR_ADDRESS_PREFIX, disable_v6, eddsa_pub_to_hpke_key(), GNUNET_a2s(), GNUNET_assert, GNUNET_break_op, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_hash_context_finish(), GNUNET_CRYPTO_hash_context_read(), GNUNET_CRYPTO_hash_context_start(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_NAT_request_reversal(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_connect(), GNUNET_NETWORK_socket_create(), GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_write_net(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_CS_OUTBOUND, GNUNET_YES, PendingReversal::in, key, nat, NAT_TIMEOUT, pending_reversal_timeout(), pending_reversals, queue(), queue_map, queue_read_kx(), queue_write(), start_initial_kx_out(), PendingReversal::target, tcp_address_to_sockaddr(), and PendingReversal::timeout_task.

Referenced by init_socket().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_lt_delete_it()

static int get_lt_delete_it ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Iterator over all ListenTasks to clean up.

Parameters
clsNULL
keyunused
valuethe ListenTask to cancel.
Returns
GNUNET_OK to continue to iterate

Definition at line 3583 of file gnunet-communicator-tcp.c.

3586{
3587 struct ListenTask *lt = value;
3588
3589 (void) cls;
3590 (void) key;
3591 if (NULL != lt->listen_task)
3592 {
3594 lt->listen_task = NULL;
3595 }
3596 if (NULL != lt->listen_sock)
3597 {
3599 lt->listen_sock = NULL;
3600 }
3601 GNUNET_free (lt);
3602 return GNUNET_OK;
3603}

References GNUNET_break, GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_SCHEDULER_cancel(), key, ListenTask::listen_sock, ListenTask::listen_task, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_queue_delete_it()

static int get_queue_delete_it ( void *  cls,
const struct GNUNET_HashCode target,
void *  value 
)
static

Iterator over all message queues to clean up.

Parameters
clsNULL
targetunused
valuethe queue to destroy
Returns
GNUNET_OK to continue to iterate

Definition at line 3615 of file gnunet-communicator-tcp.c.

3618{
3619 struct Queue *queue = value;
3620
3621 (void) cls;
3622 (void) target;
3624 return GNUNET_OK;
3625}

References GNUNET_OK, queue(), queue_destroy(), Queue::target, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_shutdown()

static void do_shutdown ( void *  cls)
static

Shutdown the UNIX communicator.

Parameters
clsNULL (always)

Definition at line 3634 of file gnunet-communicator-tcp.c.

3635{
3637 "Shutdown %s!\n",
3638 shutdown_running ? "running" : "not running");
3639
3641 return;
3642 else
3644
3645 while (NULL != proto_head)
3647 if (NULL != nat)
3648 {
3650 nat = NULL;
3651 }
3659 if (NULL != ch)
3660 {
3663 ch = NULL;
3664 }
3665 if (NULL != stats)
3666 {
3668 stats = NULL;
3669 }
3670 if (NULL != my_private_key)
3671 {
3673 my_private_key = NULL;
3674 }
3675 if (NULL != is)
3676 {
3678 is = NULL;
3679 }
3680 if (NULL != pils)
3681 {
3683 pils = NULL;
3684 }
3685 if (NULL != peerstore)
3686 {
3688 peerstore = NULL;
3689 }
3690 if (NULL != resolve_request_handle)
3691 {
3694 }
3696 "Shutdown done!\n");
3697}

References ch, free_proto_queue(), get_lt_delete_it(), get_queue_delete_it(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NAT_unregister(), GNUNET_NT_scanner_done(), GNUNET_PEERSTORE_disconnect(), GNUNET_PILS_disconnect(), GNUNET_RESOLVER_request_cancel(), GNUNET_STATISTICS_destroy(), GNUNET_TRANSPORT_communicator_address_remove_all(), GNUNET_TRANSPORT_communicator_disconnect(), GNUNET_YES, is, lt_map, my_private_key, nat, peerstore, pending_reversals, pending_reversals_delete_it(), pils, proto_head, queue_map, resolve_request_handle, shutdown_running, and stats.

Here is the call graph for this function:

◆ enc_notify_cb()

static void enc_notify_cb ( void *  cls,
const struct GNUNET_PeerIdentity sender,
const struct GNUNET_MessageHeader msg 
)
static

Function called when the transport service has received an acknowledgement for this communicator (!) via a different return path.

Not applicable for TCP.

Parameters
clsclosure
senderwhich peer sent the notification
msgpayload

Definition at line 3712 of file gnunet-communicator-tcp.c.

3715{
3716 (void) cls;
3717 (void) sender;
3718 (void) msg;
3719 GNUNET_break_op (0);
3720}

References GNUNET_break_op, and msg.

Referenced by init_socket().

Here is the caller graph for this function:

◆ nat_address_cb()

static void nat_address_cb ( void *  cls,
void **  app_ctx,
int  add_remove,
enum GNUNET_NAT_AddressClass  ac,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of 'valid' addresses changes.

Parameters
clsclosure
[in,out]app_ctxlocation where the app can store stuff on add and retrieve it on remove
add_removeGNUNET_YES to add a new public IP address, GNUNET_NO to remove a previous (now invalid) one
acaddress class the address belongs to
addreither the previous or the new public IP address
addrlenactual length of the addr

Definition at line 3737 of file gnunet-communicator-tcp.c.

3743{
3744 char *my_addr;
3746
3748 "nat address cb %s %s\n",
3749 add_remove ? "add" : "remove",
3750 GNUNET_a2s (addr, addrlen));
3751
3752 if (GNUNET_YES == add_remove)
3753 {
3755
3756 GNUNET_asprintf (&my_addr,
3757 "%s-%s",
3759 GNUNET_a2s (addr, addrlen));
3760 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3761 ai =
3763 my_addr,
3764 nt,
3766 GNUNET_free (my_addr);
3767 *app_ctx = ai;
3768 }
3769 else
3770 {
3771 ai = *app_ctx;
3773 *app_ctx = NULL;
3774 }
3775}

References ai, ch, COMMUNICATOR_ADDRESS_PREFIX, GNUNET_a2s(), GNUNET_asprintf(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NT_scanner_get_type(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_communicator_address_add(), GNUNET_TRANSPORT_communicator_address_remove(), GNUNET_YES, is, and nt.

Referenced by nat_register().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_addr()

static void add_addr ( struct sockaddr *  in,
socklen_t  in_len 
)
static

This method adds addresses to the DLL, that are later register at the NAT service.

Definition at line 3782 of file gnunet-communicator-tcp.c.

3783{
3784
3785 struct Addresses *saddrs;
3786
3788 "add address %s\n",
3789 GNUNET_a2s (in, in_len));
3790
3791 saddrs = GNUNET_new (struct Addresses);
3792 saddrs->addr = in;
3793 saddrs->addr_len = in_len;
3795
3797 "after add address %s\n",
3798 GNUNET_a2s (in, in_len));
3799
3801 "add address %s\n",
3802 GNUNET_a2s (saddrs->addr, saddrs->addr_len));
3803
3804 addrs_lens++;
3805}

References Addresses::addr, Addresses::addr_len, addrs_head, addrs_lens, addrs_tail, GNUNET_a2s(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and GNUNET_new.

Referenced by init_socket().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_ikm()

static void load_ikm ( )
static

Get the initial secret key for generating the peer id.

This is supposed to be generated at random once in the lifetime of a peer, so all generated peer ids use the same initial secret key to obtain the same peer id per set of addresses.

First check whether there's already a initial secret key. If so: return it. If no initial secret key exists yet, generate at random and store it where it will be found.

Parameters
initialsecret key the memory the initial secret key can be written to.

Definition at line 3819 of file gnunet-communicator-tcp.c.

3820{
3821 char *keyfile;
3823
3824 if (GNUNET_OK !=
3826 "PEER",
3827 "PRIVATE_KEY",
3828 &keyfile))
3829 {
3831 "PEER",
3832 "PRIVATE_KEY");
3834 return;
3835 }
3836 if (GNUNET_SYSERR ==
3838 GNUNET_YES,
3839 &key))
3840 {
3842 "Failed to setup peer's private key\n");
3843 GNUNET_free (keyfile);
3845 return;
3846 }
3847 GNUNET_free (keyfile);
3848 GNUNET_assert (sizeof ikm == sizeof key.d);
3849 memcpy (ikm, key.d, sizeof ikm);
3850}

References cfg, GNUNET_assert, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CRYPTO_eddsa_key_from_file(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_log_config_missing(), GNUNET_OK, GNUNET_SCHEDULER_shutdown(), GNUNET_SYSERR, GNUNET_YES, ikm, and key.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_socket()

static int init_socket ( struct sockaddr *  addr,
socklen_t  in_len 
)
static

This method launch network interactions for each address we like to bind to.

Parameters
addrThe address we will listen to.
in_lenThe length of the address we will listen to.
Returns
GNUNET_SYSERR in case of error. GNUNET_OK in case we are successfully listen to the address.

Definition at line 3861 of file gnunet-communicator-tcp.c.

3863{
3864 struct sockaddr_storage in_sto;
3865 socklen_t sto_len;
3866 struct GNUNET_NETWORK_Handle *listen_sock;
3867 struct ListenTask *lt;
3868 int sockfd;
3869 struct GNUNET_HashCode h_sock;
3870
3871 if (NULL == addr)
3872 {
3874 "Address is NULL.\n");
3875 return GNUNET_SYSERR;
3876 }
3877
3879 "address %s\n",
3880 GNUNET_a2s (addr, in_len));
3881
3882 listen_sock =
3883 GNUNET_NETWORK_socket_create (addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
3884 if (NULL == listen_sock)
3885 {
3887 return GNUNET_SYSERR;
3888 }
3889
3890 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, addr, in_len))
3891 {
3893 GNUNET_NETWORK_socket_close (listen_sock);
3894 listen_sock = NULL;
3895 return GNUNET_SYSERR;
3896 }
3897
3898 if (GNUNET_OK !=
3899 GNUNET_NETWORK_socket_listen (listen_sock,
3900 5))
3901 {
3903 "listen");
3904 GNUNET_NETWORK_socket_close (listen_sock);
3905 listen_sock = NULL;
3906 return GNUNET_SYSERR;
3907 }
3908
3909 /* We might have bound to port 0, allowing the OS to figure it out;
3910 thus, get the real IN-address from the socket */
3911 sto_len = sizeof(in_sto);
3912
3913 if (0 != getsockname (GNUNET_NETWORK_get_fd (listen_sock),
3914 (struct sockaddr *) &in_sto,
3915 &sto_len))
3916 {
3917 memcpy (&in_sto, addr, in_len);
3918 sto_len = in_len;
3919 }
3920
3921 // addr = (struct sockaddr *) &in_sto;
3922 in_len = sto_len;
3924 "Bound to `%s'\n",
3925 GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len));
3926 if (NULL == stats)
3927 stats = GNUNET_STATISTICS_create ("communicator-tcp", cfg);
3928
3929 if (NULL == is)
3931
3932 /* start listening */
3933
3934 lt = GNUNET_new (struct ListenTask);
3935 lt->listen_sock = listen_sock;
3936
3938 listen_sock,
3939 &listen_cb,
3940 lt);
3941
3943 "creating hash\n");
3944 sockfd = GNUNET_NETWORK_get_fd (lt->listen_sock);
3945 GNUNET_CRYPTO_hash (&sockfd,
3946 sizeof(int),
3947 &h_sock);
3948
3950 "creating map\n");
3951 if (NULL == lt_map)
3953
3955 "creating map entry\n");
3958 &h_sock,
3959 lt,
3961
3963 "map entry created\n");
3964
3965 if (NULL == queue_map)
3967
3968 if (NULL == ch)
3973 &mq_init,
3974 NULL,
3976 NULL,
3977 NULL);
3978
3979 if (NULL == ch)
3980 {
3981 GNUNET_break (0);
3982 if (NULL != resolve_request_handle)
3985 return GNUNET_SYSERR;
3986 }
3987
3988 add_addr (addr, in_len);
3989 return GNUNET_OK;
3990
3991}

References add_addr(), cfg, ch, COMMUNICATOR_ADDRESS_PREFIX, COMMUNICATOR_CONFIG_SECTION, enc_notify_cb(), GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_get_fd(), GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_NETWORK_socket_listen(), GNUNET_new, GNUNET_NO, GNUNET_NT_scanner_init(), GNUNET_OK, GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_create(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_CC_RELIABLE, GNUNET_TRANSPORT_communicator_connect(), is, listen_cb(), ListenTask::listen_sock, ListenTask::listen_task, lt_map, mq_init(), queue_map, resolve_request_handle, and stats.

Referenced by init_socket_resolv(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ nat_register()

static void nat_register ( )
static

This method reads from the DLL addrs_head to register them at the NAT service.

Definition at line 3998 of file gnunet-communicator-tcp.c.

3999{
4000 struct sockaddr **saddrs;
4001 socklen_t *saddr_lens;
4002 int i;
4003 size_t len;
4004
4006 "starting nat register!\n");
4007 len = 0;
4008 i = 0;
4009 saddrs = GNUNET_malloc ((addrs_lens) * sizeof(struct sockaddr *));
4010 saddr_lens = GNUNET_malloc ((addrs_lens) * sizeof(socklen_t));
4011 for (struct Addresses *pos = addrs_head; NULL != pos; pos = pos->next)
4012 {
4014 "registering address %s\n",
4015 GNUNET_a2s (pos->addr, pos->addr_len));
4016
4017 saddr_lens[i] = pos->addr_len;
4018 len += saddr_lens[i];
4019 saddrs[i] = GNUNET_memdup (pos->addr, saddr_lens[i]);
4020 i++;
4021 }
4022
4024 "registering addresses %lu %lu %lu %lu\n",
4025 (addrs_lens) * sizeof(struct sockaddr *),
4026 (addrs_lens) * sizeof(socklen_t),
4027 len,
4031 IPPROTO_TCP,
4032 addrs_lens,
4033 (const struct sockaddr **) saddrs,
4034 saddr_lens,
4037 NULL /* closure */);
4038 for (i = addrs_lens - 1; i >= 0; i--)
4039 GNUNET_free (saddrs[i]);
4040 GNUNET_free (saddrs);
4041 GNUNET_free (saddr_lens);
4042
4043 if (NULL == nat)
4044 {
4045 GNUNET_break (0);
4046 if (NULL != resolve_request_handle)
4049 }
4050}

References addrs_head, addrs_lens, cfg, COMMUNICATOR_CONFIG_SECTION, GNUNET_a2s(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_memdup, GNUNET_NAT_register(), GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_shutdown(), nat, nat_address_cb(), Addresses::next, resolve_request_handle, and try_connection_reversal().

Referenced by init_socket_resolv(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_socket_resolv()

static void init_socket_resolv ( void *  cls,
const struct sockaddr *  addr,
socklen_t  in_len 
)
static

This method is the callback called by the resolver API, and wraps method init_socket.

Parameters
clsThe port we will bind to.
addrThe address we will bind to.
in_lenThe length of the address we will bind to.

Definition at line 4061 of file gnunet-communicator-tcp.c.

4064{
4065 struct sockaddr_in *v4;
4066 struct sockaddr_in6 *v6;
4067 struct sockaddr *in;
4068
4069 (void) cls;
4070 if (NULL != addr)
4071 {
4072 if (AF_INET == addr->sa_family)
4073 {
4074 v4 = (struct sockaddr_in *) addr;
4075 in = tcp_address_to_sockaddr_numeric_v4 (&in_len, *v4, bind_port);// _global);
4076 }
4077 else if (AF_INET6 == addr->sa_family)
4078 {
4079 v6 = (struct sockaddr_in6 *) addr;
4080 in = tcp_address_to_sockaddr_numeric_v6 (&in_len, *v6, bind_port);// _global);
4081 }
4082 else
4083 {
4085 "Address family %u not suitable (not AF_INET %u nor AF_INET6 %u \n",
4086 addr->sa_family,
4087 AF_INET,
4088 AF_INET6);
4089 return;
4090 }
4091 init_socket (in, in_len);
4092 }
4093 else
4094 {
4096 "Address is NULL. This might be an error or the resolver finished resolving.\n");
4097 if (NULL == addrs_head)
4098 {
4100 "Resolver finished resolving, but we do not listen to an address!.\n");
4101 return;
4102 }
4103 nat_register ();
4104 }
4105}

References addrs_head, bind_port, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, init_socket(), nat_register(), tcp_address_to_sockaddr_numeric_v4(), and tcp_address_to_sockaddr_numeric_v6().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pid_change_cb()

void pid_change_cb ( void *  cls,
const struct GNUNET_HELLO_Parser parser,
const struct GNUNET_HashCode addr_hash 
)

Definition at line 4109 of file gnunet-communicator-tcp.c.

4112{
4114 "Got PID to derive from `%s':\n",
4115 GNUNET_h2s (addr_hash));
4116 if (NULL == my_private_key)
4118
4120 (uint8_t*) ikm,
4121 addr_hash,
4127}

References eddsa_priv_to_hpke_key(), GNUNET_CRYPTO_eddsa_key_get_public(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_new, GNUNET_PILS_derive_pid(), ikm, LOG, my_identity, my_private_key, my_x25519_private_key, and GNUNET_PeerIdentity::public_key.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
char *const *  args,
const char *  cfgfile,
const struct GNUNET_CONFIGURATION_Handle c 
)
static

Setup communicator and launch network interactions.

Parameters
clsNULL (always)
argsremaining command-line arguments
cfgfilename of the configuration file used (for saving, can be NULL!)
cconfiguration

Definition at line 4139 of file gnunet-communicator-tcp.c.

4143{
4144 char *bindto;
4145 struct sockaddr *in;
4146 socklen_t in_len;
4147 struct sockaddr_in v4;
4148 struct sockaddr_in6 v6;
4149 char *start;
4150 unsigned int port;
4151 char dummy[2];
4152 char *rest = NULL;
4153 struct PortOnlyIpv4Ipv6 *po;
4154 socklen_t addr_len_ipv4;
4155 socklen_t addr_len_ipv6;
4156
4157 (void) cls;
4158
4160 memset (&v4,0,sizeof(struct sockaddr_in));
4161 memset (&v6,0,sizeof(struct sockaddr_in6));
4162 cfg = c;
4163 if (GNUNET_OK !=
4166 "BINDTO",
4167 &bindto))
4168 {
4171 "BINDTO");
4172 return;
4173 }
4174 if (GNUNET_OK !=
4177 "MAX_QUEUE_LENGTH",
4179 {
4181 }
4182 if (GNUNET_OK !=
4185 "REKEY_INTERVAL",
4187 {
4189 }
4190 if (GNUNET_OK !=
4193 "REKEY_MAX_BYTES",
4195 {
4197 }
4199 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
4200 (GNUNET_YES ==
4203 "DISABLE_V6")))
4204 {
4206 }
4207 load_ikm ();
4209 GNUNET_assert (NULL != pils);
4211 if (NULL == peerstore)
4212 {
4213 GNUNET_free (bindto);
4214 GNUNET_break (0);
4216 return;
4217 }
4218
4220
4221 if (1 == sscanf (bindto, "%u%1s", &bind_port, dummy))
4222 {
4226 "address po %s\n",
4228 if (NULL != po->addr_ipv4)
4229 {
4231 }
4232 if (NULL != po->addr_ipv6)
4233 {
4236 }
4237 GNUNET_free (po);
4238 nat_register ();
4239 GNUNET_free (bindto);
4240 return;
4241 }
4242
4243 start = extract_address (bindto);
4244 // FIXME: check for NULL == start...
4245 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
4246 {
4247 bind_port = extract_port (bindto);
4248
4250 init_socket (in, in_len);
4251 nat_register ();
4253 GNUNET_free (bindto);
4254 return;
4255 }
4256
4257 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
4258 {
4259 bind_port = extract_port (bindto);
4261 init_socket (in, in_len);
4262 nat_register ();
4264 GNUNET_free (bindto);
4265 return;
4266 }
4267
4268 bind_port = extract_port (bindto);
4270 ":",
4271 &rest),
4272 AF_UNSPEC,
4275 &port);
4276
4277 GNUNET_free (bindto);
4279}

References PortOnlyIpv4Ipv6::addr_ipv4, PortOnlyIpv4Ipv6::addr_ipv6, PortOnlyIpv4Ipv6::addr_len_ipv4, PortOnlyIpv4Ipv6::addr_len_ipv6, bind_port, cfg, COMMUNICATOR_CONFIG_SECTION, DEFAULT_MAX_QUEUE_LENGTH, DEFAULT_REKEY_INTERVAL, disable_v6, do_shutdown, dummy, extract_address(), extract_port(), GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_time(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONTAINER_multihashmap_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_log_config_missing(), GNUNET_NETWORK_test_pf(), GNUNET_NO, GNUNET_OK, GNUNET_PEERSTORE_connect(), GNUNET_PILS_connect(), GNUNET_RESOLVER_ip_get(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_TIME_UNIT_MINUTES, GNUNET_YES, init_socket(), init_socket_resolv(), load_ikm(), max_queue_length, nat_register(), peerstore, pending_reversals, pid_change_cb(), pils, port, rekey_interval, REKEY_MAX_BYTES, rekey_max_bytes, resolve_request_handle, start, tcp_address_to_sockaddr_numeric_v4(), tcp_address_to_sockaddr_numeric_v6(), and tcp_address_to_sockaddr_port_only().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *const *  argv 
)

The main function for the UNIX communicator.

Parameters
argcnumber of arguments from the command line
argvcommand line arguments
Returns
0 ok, 1 on error

Definition at line 4290 of file gnunet-communicator-tcp.c.

4291{
4292 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4294 };
4295 int ret;
4296
4298 "Starting tcp communicator\n");
4299
4300 ret = (GNUNET_OK ==
4302 argc,
4303 argv,
4304 "gnunet-communicator-tcp",
4305 _ ("GNUnet TCP communicator"),
4306 options,
4307 &run,
4308 NULL))
4309 ? 0
4310 : 1;
4311 return ret;
4312}

References _, GNUNET_ERROR_TYPE_DEBUG, GNUNET_GETOPT_OPTION_END, GNUNET_log, GNUNET_OK, GNUNET_OS_project_data_gnunet(), GNUNET_PROGRAM_run(), options, ret, and run().

Here is the call graph for this function:

Variable Documentation

◆ max_queue_length

unsigned long long max_queue_length
static

Maximum queue length before we stop reading towards the transport service.

Definition at line 823 of file gnunet-communicator-tcp.c.

Referenced by queue_read(), queue_read(), and run().

◆ pils

struct GNUNET_PILS_Handle* pils
static

For PILS.

Definition at line 828 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), and run().

◆ stats

◆ ch

◆ queue_map

struct GNUNET_CONTAINER_MultiHashMap* queue_map
static

Queues (map from peer identity to struct Queue)

Definition at line 843 of file gnunet-communicator-tcp.c.

Referenced by boot_queue(), do_shutdown(), init_socket(), mq_init(), and queue_destroy().

◆ lt_map

struct GNUNET_CONTAINER_MultiHashMap* lt_map
static

ListenTasks (map from socket to struct ListenTask)

Definition at line 848 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), init_socket(), and queue_destroy().

◆ my_identity

◆ rekey_max_bytes

unsigned long long rekey_max_bytes
static

The rekey byte maximum.

Definition at line 858 of file gnunet-communicator-tcp.c.

Referenced by run(), setup_out_cipher(), and setup_out_cipher().

◆ rekey_interval

struct GNUNET_TIME_Relative rekey_interval
static

The rekey interval.

Definition at line 863 of file gnunet-communicator-tcp.c.

Referenced by run(), run(), setup_out_cipher(), and setup_out_cipher().

◆ my_private_key

struct GNUNET_CRYPTO_EddsaPrivateKey* my_private_key
static

Our private key.

Definition at line 868 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), inject_rekey(), pid_change_cb(), send_challenge(), setup_in_cipher(), and transmit_kx().

◆ my_x25519_private_key

struct GNUNET_CRYPTO_HpkePrivateKey my_x25519_private_key
static

Our private key.

Definition at line 873 of file gnunet-communicator-tcp.c.

Referenced by pid_change_cb(), and setup_in_cipher_elligator().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

Definition at line 878 of file gnunet-communicator-tcp.c.

Referenced by init_socket(), inject_rekey(), load_ikm(), nat_register(), run(), send_challenge(), and transmit_kx().

◆ is

struct GNUNET_NT_InterfaceScanner* is
static

Network scanner to determine network types.

Definition at line 883 of file gnunet-communicator-tcp.c.

Referenced by boot_queue(), do_shutdown(), init_socket(), and nat_address_cb().

◆ nat

struct GNUNET_NAT_Handle* nat
static

Connection to NAT service.

Definition at line 888 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), mq_init(), and nat_register().

◆ proto_head

struct ProtoQueue* proto_head
static

◆ proto_tail

struct ProtoQueue* proto_tail
static

◆ resolve_request_handle

struct GNUNET_RESOLVER_RequestHandle* resolve_request_handle

Handle for DNS lookup of bindto address.

Definition at line 903 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), do_shutdown(), init_socket(), init_socket(), nat_register(), and run().

◆ addrs_head

struct Addresses* addrs_head
static

Head of DLL with addresses we like to register at NAT service.

Definition at line 908 of file gnunet-communicator-tcp.c.

Referenced by add_addr(), init_socket_resolv(), and nat_register().

◆ addrs_tail

struct Addresses* addrs_tail
static

Head of DLL with addresses we like to register at NAT service.

Definition at line 913 of file gnunet-communicator-tcp.c.

Referenced by add_addr().

◆ addrs_lens

int addrs_lens
static

Number of addresses in the DLL for register at NAT service.

Definition at line 918 of file gnunet-communicator-tcp.c.

Referenced by add_addr(), add_addr(), and nat_register().

◆ peerstore

◆ shutdown_running

int shutdown_running = GNUNET_NO
static

A flag indicating we are already doing a shutdown.

Definition at line 928 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), and queue_destroy().

◆ disable_v6

int disable_v6
static

IPv6 disabled.

Definition at line 933 of file gnunet-communicator-tcp.c.

Referenced by mq_init(), run(), and tcp_address_to_sockaddr_port_only().

◆ bind_port

unsigned int bind_port
static

The port the communicator should be assigned to.

Definition at line 938 of file gnunet-communicator-tcp.c.

Referenced by init_socket_resolv(), mq_init(), mq_init(), run(), and run().

◆ pending_reversals

◆ ikm

unsigned char ikm[256/8]
static

The initial key material for the peer.

Definition at line 948 of file gnunet-communicator-tcp.c.

Referenced by load_ikm(), and pid_change_cb().