5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2006 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 * Created: Fri Jul 25 18:52:14 1997
26 /************************** Types and definitions ***************************/
29 struct SilcPacketEngineStruct {
30 SilcRng rng; /* RNG for engine */
31 SilcPacketCallbacks *callbacks; /* Packet callbacks */
32 void *callback_context; /* Context for callbacks */
33 SilcList streams; /* All streams in engine */
34 SilcList packet_pool; /* Free list for received packets */
35 SilcMutex lock; /* Engine lock */
36 SilcBool local_is_router;
39 /* Packet procesor context */
40 typedef struct SilcPacketProcessStruct {
41 SilcInt32 priority; /* Priority */
42 SilcPacketType *types; /* Packets to process */
43 SilcPacketCallbacks *callbacks; /* Callbacks or NULL */
44 void *callback_context;
48 struct SilcPacketStreamStruct {
49 struct SilcPacketStreamStruct *next;
50 SilcPacketEngine engine; /* Packet engine */
51 SilcStream stream; /* Underlaying stream */
52 SilcMutex lock; /* Stream lock */
53 SilcDList process; /* Packet processors, it set */
54 void *stream_context; /* Stream context */
55 SilcBufferStruct inbuf; /* In buffer */
56 SilcBufferStruct outbuf; /* Out buffer */
57 SilcUInt32 send_psn; /* Sending sequence */
58 SilcCipher send_key; /* Sending key */
59 SilcHmac send_hmac; /* Sending HMAC */
60 SilcUInt32 receive_psn; /* Receiving sequence */
61 SilcCipher receive_key; /* Receiving key */
62 SilcHmac receive_hmac; /* Receiving HMAC */
63 unsigned char *src_id; /* Source ID */
64 unsigned char *dst_id; /* Destination ID */
65 unsigned int src_id_len : 6;
66 unsigned int src_id_type : 2;
67 unsigned int dst_id_len : 6;
68 unsigned int dst_id_type : 2;
69 SilcUInt8 refcnt; /* Reference counter */
70 unsigned int is_router : 1; /* Set if router stream */
71 unsigned int destroyed : 1; /* Set if destroyed */
74 /* Initial size of stream buffers */
75 #define SILC_PACKET_DEFAULT_SIZE 1024
77 /* Header length without source and destination ID's. */
78 #define SILC_PACKET_HEADER_LEN 10
80 /* Minimum length of SILC Packet Header. This much is decrypted always
81 when packet is received to be able to get all the relevant data out
83 #define SILC_PACKET_MIN_HEADER_LEN 16
85 /* Maximum padding length */
86 #define SILC_PACKET_MAX_PADLEN 128
88 /* Default padding length */
89 #define SILC_PACKET_DEFAULT_PADLEN 16
91 /* Minimum packet length */
92 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
97 /* Returns true length of the packet. */
98 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
100 SILC_GET16_MSB((__ret_truelen), (__packetdata)); \
101 (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4]; \
104 /* Calculates the data length with given header length. This macro
105 can be used to check whether the data_len with header_len exceeds
106 SILC_PACKET_MAX_LEN. If it does, this returns the new data_len
107 so that the SILC_PACKET_MAX_LEN is not exceeded. If the data_len
108 plus header_len fits SILC_PACKET_MAX_LEN the returned data length
109 is the data_len given as argument. */
110 #define SILC_PACKET_DATALEN(data_len, header_len) \
111 ((data_len + header_len) > SILC_PACKET_MAX_LEN ? \
112 data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
114 /* Calculates the length of the padding in the packet. */
115 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen) \
117 __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) % \
118 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
120 __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
123 /* Returns the length of the padding up to the maximum length, which
125 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen) \
127 __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) % \
128 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
132 #define SILC_PACKET_CALLBACK_EOS(s) \
134 (s)->engine->callbacks->eos((s)->engine, s, \
135 (s)->engine->callback_context, \
136 (s)->stream_context); \
140 #define SILC_PACKET_CALLBACK_ERROR(s, err) \
142 (s)->engine->callbacks->error((s)->engine, s, err, \
143 (s)->engine->callback_context, \
144 (s)->stream_context); \
148 /************************ Static utility functions **************************/
150 static void silc_packet_read_process(SilcPacketStream stream);
152 /* Our stream IO notifier callback. */
154 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
157 SilcPacketStream ps = context;
160 silc_mutex_lock(ps->lock);
163 silc_mutex_unlock(ps->lock);
169 case SILC_STREAM_CAN_WRITE:
170 if (!silc_buffer_headlen(&ps->outbuf)) {
171 silc_mutex_unlock(ps->lock);
175 SILC_LOG_DEBUG(("Writing pending data to stream"));
177 /* Write pending data to stream */
178 while (silc_buffer_len(&ps->outbuf) > 0) {
179 ret = silc_stream_write(ps->stream, ps->outbuf.data,
180 silc_buffer_len(&ps->outbuf));
183 silc_buffer_reset(&ps->outbuf);
184 silc_mutex_unlock(ps->lock);
185 SILC_PACKET_CALLBACK_EOS(ps);
191 silc_buffer_reset(&ps->outbuf);
192 silc_mutex_unlock(ps->lock);
193 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
198 /* Cannot write now, write later. */
199 silc_mutex_unlock(ps->lock);
204 silc_buffer_pull(&ps->outbuf, ret);
207 silc_buffer_reset(&ps->outbuf);
209 silc_mutex_unlock(ps->lock);
212 case SILC_STREAM_CAN_READ:
213 SILC_LOG_DEBUG(("Reading data from stream"));
215 /* Make sure we have fair amount of free space in inbuf */
216 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
217 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
218 SILC_PACKET_DEFAULT_SIZE * 2)) {
219 silc_mutex_unlock(ps->lock);
223 /* Read data from stream */
224 ret = silc_stream_read(ps->stream, ps->inbuf.tail,
225 silc_buffer_taillen(&ps->inbuf));
229 silc_buffer_reset(&ps->inbuf);
230 silc_mutex_unlock(ps->lock);
231 SILC_PACKET_CALLBACK_EOS(ps);
237 silc_buffer_reset(&ps->inbuf);
238 silc_mutex_unlock(ps->lock);
239 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
244 /* Cannot read now, do it later. */
245 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
246 silc_mutex_unlock(ps->lock);
250 /* Now process the data */
251 silc_buffer_pull_tail(&ps->inbuf, ret);
252 silc_packet_read_process(ps);
254 silc_mutex_unlock(ps->lock);
258 silc_mutex_unlock(ps->lock);
263 /* Allocate packet */
265 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
269 SILC_LOG_DEBUG(("Packet pool count %d",
270 silc_list_count(engine->packet_pool)));
272 silc_mutex_lock(engine->lock);
274 /* Get packet from freelist or allocate new one. */
275 packet = silc_list_get(engine->packet_pool);
279 silc_mutex_unlock(engine->lock);
281 packet = silc_calloc(1, sizeof(*packet));
285 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
287 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
292 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
293 silc_buffer_reset(&packet->buffer);
298 SILC_LOG_DEBUG(("Get packet %p", packet));
300 /* Delete from freelist */
301 silc_list_del(engine->packet_pool, packet);
303 silc_mutex_unlock(engine->lock);
309 /******************************** Packet API ********************************/
311 /* Allocate new packet engine */
314 silc_packet_engine_start(SilcRng rng, SilcBool router,
315 SilcPacketCallbacks *callbacks,
316 void *callback_context)
318 SilcPacketEngine engine;
323 SILC_LOG_DEBUG(("Starting new packet engine"));
327 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
330 engine = silc_calloc(1, sizeof(*engine));
335 engine->local_is_router = router;
336 engine->callbacks = callbacks;
337 engine->callback_context = callback_context;
338 silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
339 silc_mutex_alloc(&engine->lock);
341 /* Allocate packet free list */
342 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
343 for (i = 0; i < 5; i++) {
344 packet = silc_calloc(1, sizeof(*packet));
348 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
351 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
352 silc_buffer_reset(&packet->buffer);
354 silc_list_add(engine->packet_pool, packet);
356 silc_list_start(engine->packet_pool);
361 /* Stop packet engine */
363 void silc_packet_engine_stop(SilcPacketEngine engine)
366 SILC_LOG_DEBUG(("Stopping packet engine"));
376 /* Create new packet stream */
378 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
379 SilcSchedule schedule,
385 SILC_LOG_DEBUG(("Creating new packet stream"));
387 if (!engine || !stream)
390 ps = silc_calloc(1, sizeof(*ps));
398 /* Allocate buffers */
399 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
402 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
403 silc_buffer_reset(&ps->inbuf);
404 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
407 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
408 silc_buffer_reset(&ps->outbuf);
410 /* Initialize packet procesors list */
411 ps->process = silc_dlist_init();
413 /* Set IO notifier callback */
414 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
416 silc_mutex_alloc(&ps->lock);
419 silc_mutex_lock(engine->lock);
420 silc_list_add(engine->streams, ps);
421 silc_mutex_unlock(engine->lock);
426 /* Destroy packet stream */
428 void silc_packet_stream_destroy(SilcPacketStream stream)
433 if (stream->refcnt > 1) {
434 stream->destroyed = TRUE;
438 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
440 /* Delete from engine */
441 silc_mutex_lock(stream->engine->lock);
442 silc_list_del(stream->engine->streams, stream);
443 silc_mutex_unlock(stream->engine->lock);
445 /* Clear and free buffers */
446 silc_buffer_clear(&stream->inbuf);
447 silc_buffer_clear(&stream->outbuf);
448 silc_buffer_purge(&stream->inbuf);
449 silc_buffer_purge(&stream->outbuf);
453 /* Destroy the underlaying stream */
454 silc_stream_destroy(stream->stream);
456 silc_dlist_uninit(stream->process);
457 silc_mutex_free(stream->lock);
461 /* Marks as router stream */
463 void silc_packet_stream_set_router(SilcPacketStream stream)
465 stream->is_router = TRUE;
469 /* Links `callbacks' to `stream' for specified packet types */
471 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
472 SilcPacketCallbacks *callbacks,
473 void *callback_context,
474 int priority, va_list ap)
476 SilcPacketProcess p, e;
477 SilcInt32 packet_type;
480 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
484 if (!callbacks->packet_receive)
487 p = silc_calloc(1, sizeof(*p));
491 p->priority = priority;
492 p->callbacks = callbacks;
493 p->callback_context = callback_context;
495 silc_mutex_lock(stream->lock);
497 if (!stream->process) {
498 stream->process = silc_dlist_init();
499 if (!stream->process) {
500 silc_mutex_unlock(stream->lock);
505 /* According to priority set the procesor to correct position. First
506 entry has the highest priority */
507 silc_dlist_start(stream->process);
508 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
509 if (p->priority > e->priority) {
510 silc_dlist_insert(stream->process, p);
515 silc_dlist_add(stream->process, p);
517 /* Get packet types to process */
520 packet_type = va_arg(ap, SilcInt32);
522 if (packet_type == SILC_PACKET_ANY)
525 if (packet_type == -1)
528 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
530 silc_mutex_unlock(stream->lock);
534 p->types[i - 1] = (SilcPacketType)packet_type;
540 silc_mutex_unlock(stream->lock);
542 silc_packet_stream_ref(stream);
547 /* Links `callbacks' to `stream' for specified packet types */
549 SilcBool silc_packet_stream_link(SilcPacketStream stream,
550 SilcPacketCallbacks *callbacks,
551 void *callback_context,
557 va_start(ap, priority);
558 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
565 /* Unlinks `callbacks' from `stream'. */
567 void silc_packet_stream_unlink(SilcPacketStream stream,
568 SilcPacketCallbacks *callbacks,
569 void *callback_context)
573 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
576 silc_mutex_lock(stream->lock);
578 silc_dlist_start(stream->process);
579 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
580 if (p->callbacks == callbacks &&
581 p->callback_context == callback_context) {
582 silc_dlist_del(stream->process, p);
587 if (!silc_dlist_count(stream->process)) {
588 silc_dlist_uninit(stream->process);
589 stream->process = NULL;
592 silc_mutex_unlock(stream->lock);
594 silc_packet_stream_unref(stream);
597 /* Reference packet stream */
599 void silc_packet_stream_ref(SilcPacketStream stream)
601 silc_mutex_lock(stream->lock);
603 silc_mutex_unlock(stream->lock);
606 /* Unreference packet stream */
608 void silc_packet_stream_unref(SilcPacketStream stream)
610 silc_mutex_lock(stream->lock);
612 silc_mutex_unlock(stream->lock);
613 if (stream->refcnt == 0)
614 silc_packet_stream_destroy(stream);
619 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
621 return stream->engine;
624 /* Set application context for packet stream */
626 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
628 silc_mutex_lock(stream->lock);
629 stream->stream_context = stream_context;
630 silc_mutex_unlock(stream->lock);
633 /* Return application context from packet stream */
635 void *silc_packet_get_context(SilcPacketStream stream)
638 silc_mutex_lock(stream->lock);
639 context = stream->stream_context;
640 silc_mutex_unlock(stream->lock);
644 /* Return underlaying stream */
646 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
648 return stream->stream;
651 /* Set ciphers for packet stream */
653 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
656 SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
657 silc_mutex_lock(stream->lock);
658 stream->send_key = send;
659 stream->receive_key = receive;
660 silc_mutex_unlock(stream->lock);
663 /* Return current ciphers from packet stream */
665 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
668 if (!stream->send_key && !stream->receive_key)
671 silc_mutex_lock(stream->lock);
674 *send = stream->send_key;
676 *receive = stream->receive_key;
678 silc_mutex_unlock(stream->lock);
683 /* Set HMACs for packet stream */
685 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
688 SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
689 silc_mutex_lock(stream->lock);
690 stream->send_hmac = send;
691 stream->receive_hmac = receive;
692 silc_mutex_unlock(stream->lock);
695 /* Return current HMACs from packet stream */
697 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
700 if (!stream->send_hmac && !stream->receive_hmac)
703 silc_mutex_lock(stream->lock);
706 *send = stream->send_hmac;
708 *receive = stream->receive_hmac;
710 silc_mutex_unlock(stream->lock);
715 /* Set SILC IDs to packet stream */
717 SilcBool silc_packet_set_ids(SilcPacketStream stream,
718 SilcIdType src_id_type, const void *src_id,
719 SilcIdType dst_id_type, const void *dst_id)
722 unsigned char tmp[32];
724 if (!src_id && !dst_id)
727 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
729 silc_mutex_lock(stream->lock);
732 silc_free(stream->src_id);
733 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
734 silc_mutex_unlock(stream->lock);
737 stream->src_id = silc_memdup(tmp, len);
738 if (!stream->src_id) {
739 silc_mutex_unlock(stream->lock);
742 stream->src_id_type = src_id_type;
743 stream->src_id_len = len;
747 silc_free(stream->dst_id);
748 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
749 silc_mutex_unlock(stream->lock);
752 stream->dst_id = silc_memdup(tmp, len);
753 if (!stream->dst_id) {
754 silc_mutex_unlock(stream->lock);
757 stream->dst_id_type = dst_id_type;
758 stream->dst_id_len = len;
761 silc_mutex_unlock(stream->lock);
768 void silc_packet_free(SilcPacket packet)
770 SilcPacketStream stream = packet->stream;
772 SILC_LOG_DEBUG(("Freeing packet %p", packet));
774 #if defined(SILC_DEBUG)
775 /* Check for double free */
776 assert(packet->stream != NULL);
777 #endif /* SILC_DEBUG */
779 silc_mutex_lock(stream->engine->lock);
781 packet->stream = NULL;
782 packet->src_id = packet->dst_id = NULL;
783 silc_buffer_reset(&packet->buffer);
785 /* Put the packet back to freelist */
786 silc_list_add(stream->engine->packet_pool, packet);
788 silc_mutex_unlock(stream->engine->lock);
791 /****************************** Packet Sending ******************************/
793 /* Prepare outgoing data buffer for packet sending. Returns the
794 pointer to that buffer into the `packet'. */
796 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
801 unsigned char *oldptr;
802 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
806 /* Allocate more space if needed */
807 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
808 if (!silc_buffer_realloc(&stream->outbuf,
809 silc_buffer_truelen(&stream->outbuf) + totlen))
813 /* Pull data area for the new packet, and return pointer to the start of
814 the data area and save the pointer in to the `packet'. MAC is pulled
815 later after it's computed. */
816 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
817 silc_buffer_set(packet, oldptr, totlen);
818 silc_buffer_push_tail(packet, mac_len);
823 /* Internal routine to send packet */
825 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
827 SilcPacketFlags flags,
828 SilcIdType src_id_type,
829 unsigned char *src_id,
830 SilcUInt32 src_id_len,
831 SilcIdType dst_id_type,
832 unsigned char *dst_id,
833 SilcUInt32 dst_id_len,
834 const unsigned char *data,
839 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
840 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
841 int i, enclen, truelen, padlen;
842 SilcBufferStruct packet;
844 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
845 "data len %d", silc_get_packet_name(type), stream->send_psn,
846 flags, src_id_type, dst_id_type, data_len));
848 /* Get the true length of the packet. This is saved as payload length
849 into the packet header. This does not include the length of the
851 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
852 src_id_len + dst_id_len));
853 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
854 src_id_len + dst_id_len);
856 /* We automatically figure out the packet structure from the packet
857 type and flags, and calculate correct length. Private messages with
858 private keys and channel messages are special packets as their
859 payload is encrypted already. */
860 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
861 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
862 type == SILC_PACKET_CHANNEL_MESSAGE) {
864 /* Padding is calculated from header + IDs */
865 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
867 dst_id_len), block_len, padlen);
869 /* Length to encrypt, header + IDs + padding. */
870 enclen = SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len + padlen;
873 /* Padding is calculated from true length of the packet */
874 if (flags & SILC_PACKET_FLAG_LONG_PAD)
875 SILC_PACKET_PADLEN_MAX(truelen, block_len, padlen);
877 SILC_PACKET_PADLEN(truelen, block_len, padlen);
882 /* Remove implementation specific flags */
883 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
885 /* Get random padding */
886 for (i = 0; i < padlen; i++) tmppad[i] =
887 silc_rng_get_byte_fast(stream->engine->rng);
889 silc_mutex_lock(stream->lock);
891 /* Get packet pointer from the outgoing buffer */
892 if (!silc_packet_send_prepare(stream, truelen + padlen, hmac, &packet)) {
893 silc_mutex_unlock(stream->lock);
897 /* Create the packet. This creates the SILC header, adds padding, and
898 the actual packet data. */
899 i = silc_buffer_format(&packet,
900 SILC_STR_UI_SHORT(truelen),
901 SILC_STR_UI_CHAR(flags),
902 SILC_STR_UI_CHAR(type),
903 SILC_STR_UI_CHAR(padlen),
905 SILC_STR_UI_CHAR(src_id_len),
906 SILC_STR_UI_CHAR(dst_id_len),
907 SILC_STR_UI_CHAR(src_id_type),
908 SILC_STR_UI_XNSTRING(src_id, src_id_len),
909 SILC_STR_UI_CHAR(dst_id_type),
910 SILC_STR_UI_XNSTRING(dst_id, dst_id_len),
911 SILC_STR_UI_XNSTRING(tmppad, padlen),
912 SILC_STR_UI_XNSTRING(data, data_len),
915 silc_mutex_unlock(stream->lock);
919 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
920 packet.data, silc_buffer_len(&packet));
922 /* Encrypt the packet */
924 SILC_LOG_DEBUG(("Encrypting packet"));
925 if (!silc_cipher_encrypt(cipher, packet.data, packet.data,
927 SILC_LOG_ERROR(("Packet encryption failed"));
928 silc_mutex_unlock(stream->lock);
935 unsigned char psn[4];
938 /* MAC is computed from the entire encrypted packet data, and put
939 to the end of the packet. */
940 silc_hmac_init(hmac);
941 SILC_PUT32_MSB(stream->send_psn, psn);
942 silc_hmac_update(hmac, psn, 4);
943 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
944 silc_hmac_final(hmac, packet.tail, &mac_len);
945 silc_buffer_pull_tail(&packet, mac_len);
949 /* Write the packet to the stream */
950 while (silc_buffer_len(&stream->outbuf) > 0) {
951 i = silc_stream_write(stream->stream, stream->outbuf.data,
952 silc_buffer_len(&stream->outbuf));
955 silc_buffer_reset(&stream->outbuf);
956 silc_mutex_unlock(stream->lock);
957 SILC_PACKET_CALLBACK_EOS(stream);
963 silc_buffer_reset(&stream->outbuf);
964 silc_mutex_unlock(stream->lock);
965 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_WRITE);
970 /* Cannot write now, write later. */
971 silc_mutex_unlock(stream->lock);
976 silc_buffer_pull(&stream->outbuf, i);
978 silc_buffer_reset(&stream->outbuf);
980 silc_mutex_unlock(stream->lock);
986 SilcBool silc_packet_send(SilcPacketStream stream,
987 SilcPacketType type, SilcPacketFlags flags,
988 const unsigned char *data, SilcUInt32 data_len)
990 return silc_packet_send_raw(stream, type, flags,
1002 /* Sends a packet, extended routine */
1004 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1005 SilcPacketType type, SilcPacketFlags flags,
1006 SilcIdType src_id_type, void *src_id,
1007 SilcIdType dst_id_type, void *dst_id,
1008 const unsigned char *data, SilcUInt32 data_len,
1009 SilcCipher cipher, SilcHmac hmac)
1011 unsigned char src_id_data[32], dst_id_data[32];
1012 SilcUInt32 src_id_len, dst_id_len;
1015 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1016 sizeof(src_id_data), &src_id_len))
1019 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1020 sizeof(dst_id_data), &dst_id_len))
1023 return silc_packet_send_raw(stream, type, flags,
1024 src_id ? src_id_type : stream->src_id_type,
1025 src_id ? src_id_data : stream->src_id,
1026 src_id ? src_id_len : stream->src_id_len,
1027 dst_id ? dst_id_type : stream->dst_id_type,
1028 dst_id ? dst_id_data : stream->dst_id,
1029 dst_id ? dst_id_len : stream->dst_id_len,
1031 cipher ? cipher : stream->send_key,
1032 hmac ? hmac : stream->send_hmac);
1036 /***************************** Packet Receiving *****************************/
1038 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1040 static SilcBool silc_packet_check_mac(SilcHmac hmac,
1041 const unsigned char *data,
1042 SilcUInt32 data_len,
1043 const unsigned char *packet_mac,
1044 SilcUInt32 sequence)
1048 unsigned char mac[32], psn[4];
1051 SILC_LOG_DEBUG(("Verifying MAC"));
1053 /* Compute HMAC of packet */
1054 silc_hmac_init(hmac);
1055 SILC_PUT32_MSB(sequence, psn);
1056 silc_hmac_update(hmac, psn, 4);
1057 silc_hmac_update(hmac, data, data_len);
1058 silc_hmac_final(hmac, mac, &mac_len);
1060 /* Compare the MAC's */
1061 if (memcmp(packet_mac, mac, mac_len)) {
1062 SILC_LOG_DEBUG(("MAC failed"));
1066 SILC_LOG_DEBUG(("MAC is Ok"));
1072 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1073 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1075 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1076 SilcUInt32 sequence, SilcBuffer buffer,
1079 if (normal == TRUE) {
1081 /* Decrypt rest of the packet */
1082 SILC_LOG_DEBUG(("Decrypting the packet"));
1083 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1084 silc_buffer_len(buffer), NULL))
1090 /* Decrypt rest of the header plus padding */
1093 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1095 SILC_LOG_DEBUG(("Decrypting the header"));
1097 /* Padding length + src id len + dst id len + header length - 16
1098 bytes already decrypted, gives the rest of the encrypted packet */
1099 silc_buffer_push(buffer, block_len);
1100 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1101 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1103 silc_buffer_pull(buffer, block_len);
1105 if (len > silc_buffer_len(buffer)) {
1106 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1110 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1119 /* Parses the packet. This is called when a whole packet is ready to be
1120 parsed. The buffer sent must be already decrypted before calling this
1123 static SilcBool silc_packet_parse(SilcPacket packet)
1125 SilcBuffer buffer = &packet->buffer;
1126 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1127 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1130 SILC_LOG_DEBUG(("Parsing incoming packet"));
1132 /* Parse the buffer. This parses the SILC header of the packet. */
1133 len = silc_buffer_unformat(buffer,
1135 SILC_STR_UI_CHAR(&src_id_len),
1136 SILC_STR_UI_CHAR(&dst_id_len),
1137 SILC_STR_UI_CHAR(&src_id_type),
1140 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1144 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1145 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1146 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1147 packet->src_id_len, packet->dst_id_len));
1151 ret = silc_buffer_unformat(buffer,
1152 SILC_STR_OFFSET(len),
1153 SILC_STR_UI_XNSTRING(&packet->src_id,
1155 SILC_STR_UI_CHAR(&dst_id_type),
1156 SILC_STR_UI_XNSTRING(&packet->dst_id,
1158 SILC_STR_OFFSET(padlen),
1161 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1165 if (src_id_type > SILC_ID_CHANNEL ||
1166 dst_id_type > SILC_ID_CHANNEL) {
1167 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1168 src_id_type, dst_id_type));
1172 packet->src_id_len = src_id_len;
1173 packet->dst_id_len = dst_id_len;
1174 packet->src_id_type = src_id_type;
1175 packet->dst_id_type = dst_id_type;
1177 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_len(buffer)),
1178 buffer->data, silc_buffer_len(buffer));
1180 /* Pull SILC header and padding from packet to get the data payload */
1181 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
1182 packet->src_id_len + packet->dst_id_len + padlen);
1184 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1185 silc_get_packet_name(packet->type)));
1190 /* Dispatch packet to application. Called with stream->lock locked. */
1192 static void silc_packet_dispatch(SilcPacket packet)
1194 SilcPacketStream stream = packet->stream;
1195 SilcPacketProcess p;
1196 SilcBool default_sent = FALSE;
1199 /* Parse the packet */
1200 if (!silc_packet_parse(packet)) {
1201 silc_mutex_unlock(packet->stream->lock);
1202 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1203 silc_mutex_lock(packet->stream->lock);
1204 silc_packet_free(packet);
1208 /* Dispatch packet to all packet processors that want it */
1210 if (!stream->process) {
1211 /* Send to default processor as no others exist */
1212 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1213 silc_mutex_unlock(packet->stream->lock);
1214 if (!stream->engine->callbacks->
1215 packet_receive(stream->engine, stream, packet,
1216 stream->engine->callback_context,
1217 stream->stream_context))
1218 silc_packet_free(packet);
1219 silc_mutex_lock(packet->stream->lock);
1223 silc_dlist_start(stream->process);
1224 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1226 /* If priority is 0 or less, we send to default processor first
1227 because default processor has 0 priority */
1228 if (!default_sent && p->priority <= 0) {
1229 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1230 default_sent = TRUE;
1231 silc_mutex_unlock(packet->stream->lock);
1232 if (stream->engine->callbacks->
1233 packet_receive(stream->engine, stream, packet,
1234 stream->engine->callback_context,
1235 stream->stream_context)) {
1236 silc_mutex_lock(packet->stream->lock);
1239 silc_mutex_lock(packet->stream->lock);
1242 /* Send to processor */
1244 /* Send all packet types */
1245 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1246 silc_mutex_unlock(packet->stream->lock);
1247 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1248 p->callback_context,
1249 stream->stream_context)) {
1250 silc_mutex_lock(packet->stream->lock);
1253 silc_mutex_lock(packet->stream->lock);
1255 /* Send specific types */
1256 for (pt = p->types; *pt; pt++) {
1257 if (*pt != packet->type)
1259 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1260 silc_mutex_unlock(packet->stream->lock);
1261 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1262 p->callback_context,
1263 stream->stream_context)) {
1264 silc_mutex_lock(packet->stream->lock);
1267 silc_mutex_lock(packet->stream->lock);
1273 if (!default_sent) {
1274 /* Send to default processor as it has not been sent yet */
1275 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1276 silc_mutex_unlock(packet->stream->lock);
1277 if (stream->engine->callbacks->
1278 packet_receive(stream->engine, stream, packet,
1279 stream->engine->callback_context,
1280 stream->stream_context)) {
1281 silc_mutex_lock(packet->stream->lock);
1284 silc_mutex_lock(packet->stream->lock);
1287 /* If we got here, no one wanted the packet, so drop it */
1288 silc_packet_free(packet);
1291 /* Process incoming data and parse packets. Called with stream->lock
1294 static void silc_packet_read_process(SilcPacketStream stream)
1297 SilcUInt16 packetlen;
1298 SilcUInt32 paddedlen, mac_len, block_len;
1299 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1300 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
1301 SilcBool normal = TRUE;
1304 /* Parse the packets from the data */
1305 while (silc_buffer_len(&stream->inbuf) > 0) {
1307 if (silc_buffer_len(&stream->inbuf) < SILC_PACKET_MIN_HEADER_LEN) {
1308 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1312 if (stream->receive_hmac)
1313 mac_len = silc_hmac_len(stream->receive_hmac);
1317 /* Decrypt first block of the packet to get the length field out */
1318 if (stream->receive_key) {
1319 block_len = silc_cipher_get_block_len(stream->receive_key);
1320 memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
1321 silc_cipher_decrypt(stream->receive_key, stream->inbuf.data,
1322 tmp, block_len, iv);
1325 block_len = SILC_PACKET_MIN_HEADER_LEN;
1326 header = stream->inbuf.data;
1329 /* Get packet length and full packet length with padding */
1330 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1333 if (packetlen < SILC_PACKET_MIN_LEN) {
1334 SILC_LOG_ERROR(("Received too short packet"));
1335 silc_mutex_unlock(stream->lock);
1336 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1337 silc_mutex_lock(stream->lock);
1338 memset(tmp, 0, sizeof(tmp));
1339 silc_buffer_reset(&stream->inbuf);
1343 if (silc_buffer_len(&stream->inbuf) < paddedlen + mac_len) {
1344 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1346 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1347 memset(tmp, 0, sizeof(tmp));
1351 /* Check MAC of the packet */
1352 if (!silc_packet_check_mac(stream->receive_hmac, stream->inbuf.data,
1353 paddedlen, stream->inbuf.data + paddedlen,
1354 stream->receive_psn)) {
1355 silc_mutex_unlock(stream->lock);
1356 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1357 silc_mutex_lock(stream->lock);
1358 memset(tmp, 0, sizeof(tmp));
1359 silc_buffer_reset(&stream->inbuf);
1364 packet = silc_packet_alloc(stream->engine);
1366 silc_mutex_unlock(stream->lock);
1367 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1368 silc_mutex_lock(stream->lock);
1369 memset(tmp, 0, sizeof(tmp));
1370 silc_buffer_reset(&stream->inbuf);
1374 /* Allocate more space to packet buffer, if needed */
1375 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1376 if (!silc_buffer_realloc(&packet->buffer,
1377 silc_buffer_truelen(&packet->buffer) +
1379 silc_buffer_truelen(&packet->buffer)))) {
1380 silc_mutex_unlock(stream->lock);
1381 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1382 silc_mutex_lock(stream->lock);
1383 silc_packet_free(packet);
1384 memset(tmp, 0, sizeof(tmp));
1385 silc_buffer_reset(&stream->inbuf);
1390 /* Parse packet header */
1391 packet->flags = (SilcPacketFlags)header[2];
1392 packet->type = (SilcPacketType)header[3];
1394 if (stream->engine->local_is_router) {
1395 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1396 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1398 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1399 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1400 stream->is_router == TRUE))
1403 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1404 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1406 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1410 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1411 stream->receive_psn, paddedlen + mac_len),
1412 stream->inbuf.data, paddedlen + mac_len);
1414 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1415 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1416 silc_buffer_put(&packet->buffer, header, block_len);
1417 silc_buffer_pull(&packet->buffer, block_len);
1418 silc_buffer_put(&packet->buffer, stream->inbuf.data + block_len,
1419 paddedlen - block_len);
1420 if (stream->receive_key) {
1421 silc_cipher_set_iv(stream->receive_key, iv);
1422 ret = silc_packet_decrypt(stream->receive_key, stream->receive_hmac,
1423 stream->receive_psn, &packet->buffer, normal);
1425 silc_mutex_unlock(stream->lock);
1426 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1427 silc_mutex_lock(stream->lock);
1428 silc_packet_free(packet);
1429 memset(tmp, 0, sizeof(tmp));
1433 stream->receive_psn++;
1435 silc_buffer_push(&packet->buffer, block_len);
1437 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1438 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1440 /* Dispatch the packet to application */
1441 packet->stream = stream;
1442 silc_packet_dispatch(packet);
1445 silc_buffer_reset(&stream->inbuf);
1449 /****************************** Packet Waiting ******************************/
1451 /* Packet wait receive callback */
1453 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1454 SilcPacketStream stream,
1456 void *callback_context,
1457 void *stream_context);
1459 /* Packet waiting callbacks */
1460 static SilcPacketCallbacks silc_packet_wait_cbs =
1462 silc_packet_wait_packet_receive, NULL, NULL
1465 /* Packet waiting context */
1467 SilcMutex wait_lock;
1469 SilcList packet_queue;
1470 unsigned int stopped : 1;
1473 /* Packet wait receive callback */
1476 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1477 SilcPacketStream stream,
1479 void *callback_context,
1480 void *stream_context)
1482 SilcPacketWait pw = callback_context;
1484 /* Signal the waiting thread for a new packet */
1485 silc_mutex_lock(pw->wait_lock);
1488 silc_mutex_unlock(pw->wait_lock);
1492 silc_list_add(pw->packet_queue, packet);
1493 silc_cond_broadcast(pw->wait_cond);
1495 silc_mutex_unlock(pw->wait_lock);
1500 /* Initialize packet waiting */
1502 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1508 pw = silc_calloc(1, sizeof(*pw));
1512 /* Allocate mutex and conditional variable */
1513 if (!silc_mutex_alloc(&pw->wait_lock)) {
1517 if (!silc_cond_alloc(&pw->wait_cond)) {
1518 silc_mutex_free(pw->wait_lock);
1523 /* Link to the packet stream for the requested packet types */
1524 va_start(ap, stream);
1525 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
1529 silc_cond_free(pw->wait_cond);
1530 silc_mutex_free(pw->wait_lock);
1535 /* Initialize packet queue */
1536 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
1541 /* Uninitialize packet waiting */
1543 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
1545 SilcPacketWait pw = waiter;
1548 /* Signal any threads to stop waiting */
1549 silc_mutex_lock(pw->wait_lock);
1551 silc_cond_broadcast(pw->wait_cond);
1552 silc_mutex_unlock(pw->wait_lock);
1554 /* Re-acquire lock and free resources */
1555 silc_mutex_lock(pw->wait_lock);
1556 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
1558 /* Free any remaining packets */
1559 silc_list_start(pw->packet_queue);
1560 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
1561 silc_packet_free(packet);
1563 silc_mutex_unlock(pw->wait_lock);
1564 silc_cond_free(pw->wait_cond);
1565 silc_mutex_free(pw->wait_lock);
1569 /* Blocks thread until a packet has been received. */
1571 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
1573 SilcPacketWait pw = waiter;
1574 SilcBool ret = FALSE;
1576 silc_mutex_lock(pw->wait_lock);
1578 /* Wait here until packet has arrived */
1579 while (silc_list_count(pw->packet_queue) == 0) {
1581 silc_mutex_unlock(pw->wait_lock);
1584 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
1588 silc_list_start(pw->packet_queue);
1589 *return_packet = silc_list_get(pw->packet_queue);
1590 silc_list_del(pw->packet_queue, *return_packet);
1592 silc_mutex_unlock(pw->wait_lock);
1594 return ret == TRUE ? 1 : 0;