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 */
72 unsigned int iv_included : 1; /* Set if IV included */
75 /* Initial size of stream buffers */
76 #define SILC_PACKET_DEFAULT_SIZE 1024
78 /* Header length without source and destination ID's. */
79 #define SILC_PACKET_HEADER_LEN 10
81 /* Minimum length of SILC Packet Header. */
82 #define SILC_PACKET_MIN_HEADER_LEN 16
83 #define SILC_PACKET_MIN_HEADER_LEN_IV 32
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)
94 /* Returns true length of the packet. */
95 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
97 SILC_GET16_MSB((__ret_truelen), (__packetdata)); \
98 (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4]; \
101 /* Calculates the data length with given header length. This macro
102 can be used to check whether the data_len with header_len exceeds
103 SILC_PACKET_MAX_LEN. If it does, this returns the new data_len
104 so that the SILC_PACKET_MAX_LEN is not exceeded. If the data_len
105 plus header_len fits SILC_PACKET_MAX_LEN the returned data length
106 is the data_len given as argument. */
107 #define SILC_PACKET_DATALEN(data_len, header_len) \
108 ((data_len + header_len) > SILC_PACKET_MAX_LEN ? \
109 data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
111 /* Calculates the length of the padding in the packet. */
112 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen) \
114 __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) % \
115 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
117 __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
120 /* Returns the length of the padding up to the maximum length, which
122 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen) \
124 __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) % \
125 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
129 #define SILC_PACKET_CALLBACK_EOS(s) \
131 (s)->engine->callbacks->eos((s)->engine, s, \
132 (s)->engine->callback_context, \
133 (s)->stream_context); \
137 #define SILC_PACKET_CALLBACK_ERROR(s, err) \
139 (s)->engine->callbacks->error((s)->engine, s, err, \
140 (s)->engine->callback_context, \
141 (s)->stream_context); \
145 /************************ Static utility functions **************************/
147 static void silc_packet_read_process(SilcPacketStream stream);
149 /* Our stream IO notifier callback. */
151 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
154 SilcPacketStream ps = context;
157 silc_mutex_lock(ps->lock);
160 silc_mutex_unlock(ps->lock);
166 case SILC_STREAM_CAN_WRITE:
167 if (!silc_buffer_headlen(&ps->outbuf)) {
168 silc_mutex_unlock(ps->lock);
172 SILC_LOG_DEBUG(("Writing pending data to stream"));
174 /* Write pending data to stream */
175 while (silc_buffer_len(&ps->outbuf) > 0) {
176 ret = silc_stream_write(ps->stream, ps->outbuf.data,
177 silc_buffer_len(&ps->outbuf));
180 silc_buffer_reset(&ps->outbuf);
181 silc_mutex_unlock(ps->lock);
182 SILC_PACKET_CALLBACK_EOS(ps);
188 silc_buffer_reset(&ps->outbuf);
189 silc_mutex_unlock(ps->lock);
190 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
195 /* Cannot write now, write later. */
196 silc_mutex_unlock(ps->lock);
201 silc_buffer_pull(&ps->outbuf, ret);
204 silc_buffer_reset(&ps->outbuf);
206 silc_mutex_unlock(ps->lock);
209 case SILC_STREAM_CAN_READ:
210 SILC_LOG_DEBUG(("Reading data from stream"));
212 /* Make sure we have fair amount of free space in inbuf */
213 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
214 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
215 SILC_PACKET_DEFAULT_SIZE * 2)) {
216 silc_mutex_unlock(ps->lock);
220 /* Read data from stream */
221 ret = silc_stream_read(ps->stream, ps->inbuf.tail,
222 silc_buffer_taillen(&ps->inbuf));
226 silc_buffer_reset(&ps->inbuf);
227 silc_mutex_unlock(ps->lock);
228 SILC_PACKET_CALLBACK_EOS(ps);
234 silc_buffer_reset(&ps->inbuf);
235 silc_mutex_unlock(ps->lock);
236 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
241 /* Cannot read now, do it later. */
242 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
243 silc_mutex_unlock(ps->lock);
247 /* Now process the data */
248 silc_buffer_pull_tail(&ps->inbuf, ret);
249 silc_packet_read_process(ps);
251 silc_mutex_unlock(ps->lock);
255 silc_mutex_unlock(ps->lock);
260 /* Allocate packet */
262 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
266 SILC_LOG_DEBUG(("Packet pool count %d",
267 silc_list_count(engine->packet_pool)));
269 silc_mutex_lock(engine->lock);
271 /* Get packet from freelist or allocate new one. */
272 packet = silc_list_get(engine->packet_pool);
276 silc_mutex_unlock(engine->lock);
278 packet = silc_calloc(1, sizeof(*packet));
282 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
284 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
289 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
290 silc_buffer_reset(&packet->buffer);
295 SILC_LOG_DEBUG(("Get packet %p", packet));
297 /* Delete from freelist */
298 silc_list_del(engine->packet_pool, packet);
300 silc_mutex_unlock(engine->lock);
306 /******************************** Packet API ********************************/
308 /* Allocate new packet engine */
311 silc_packet_engine_start(SilcRng rng, SilcBool router,
312 SilcPacketCallbacks *callbacks,
313 void *callback_context)
315 SilcPacketEngine engine;
320 SILC_LOG_DEBUG(("Starting new packet engine"));
324 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
327 engine = silc_calloc(1, sizeof(*engine));
332 engine->local_is_router = router;
333 engine->callbacks = callbacks;
334 engine->callback_context = callback_context;
335 silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
336 silc_mutex_alloc(&engine->lock);
338 /* Allocate packet free list */
339 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
340 for (i = 0; i < 5; i++) {
341 packet = silc_calloc(1, sizeof(*packet));
345 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
348 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
349 silc_buffer_reset(&packet->buffer);
351 silc_list_add(engine->packet_pool, packet);
353 silc_list_start(engine->packet_pool);
358 /* Stop packet engine */
360 void silc_packet_engine_stop(SilcPacketEngine engine)
363 SILC_LOG_DEBUG(("Stopping packet engine"));
373 /* Create new packet stream */
375 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
376 SilcSchedule schedule,
382 SILC_LOG_DEBUG(("Creating new packet stream"));
384 if (!engine || !stream)
387 ps = silc_calloc(1, sizeof(*ps));
395 /* Allocate buffers */
396 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
399 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
400 silc_buffer_reset(&ps->inbuf);
401 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
404 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
405 silc_buffer_reset(&ps->outbuf);
407 /* Initialize packet procesors list */
408 ps->process = silc_dlist_init();
410 /* Set IO notifier callback */
411 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
413 silc_mutex_alloc(&ps->lock);
416 silc_mutex_lock(engine->lock);
417 silc_list_add(engine->streams, ps);
418 silc_mutex_unlock(engine->lock);
423 /* Destroy packet stream */
425 void silc_packet_stream_destroy(SilcPacketStream stream)
430 if (stream->refcnt > 1) {
431 stream->destroyed = TRUE;
435 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
437 /* Delete from engine */
438 silc_mutex_lock(stream->engine->lock);
439 silc_list_del(stream->engine->streams, stream);
440 silc_mutex_unlock(stream->engine->lock);
442 /* Clear and free buffers */
443 silc_buffer_clear(&stream->inbuf);
444 silc_buffer_clear(&stream->outbuf);
445 silc_buffer_purge(&stream->inbuf);
446 silc_buffer_purge(&stream->outbuf);
450 /* Destroy the underlaying stream */
451 silc_stream_destroy(stream->stream);
453 silc_dlist_uninit(stream->process);
454 silc_mutex_free(stream->lock);
458 /* Marks as router stream */
460 void silc_packet_stream_set_router(SilcPacketStream stream)
462 stream->is_router = TRUE;
465 /* Mark to include IV in ciphertext */
467 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
469 stream->iv_included = TRUE;
472 /* Links `callbacks' to `stream' for specified packet types */
474 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
475 SilcPacketCallbacks *callbacks,
476 void *callback_context,
477 int priority, va_list ap)
479 SilcPacketProcess p, e;
480 SilcInt32 packet_type;
483 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
487 if (!callbacks->packet_receive)
490 p = silc_calloc(1, sizeof(*p));
494 p->priority = priority;
495 p->callbacks = callbacks;
496 p->callback_context = callback_context;
498 silc_mutex_lock(stream->lock);
500 if (!stream->process) {
501 stream->process = silc_dlist_init();
502 if (!stream->process) {
503 silc_mutex_unlock(stream->lock);
508 /* According to priority set the procesor to correct position. First
509 entry has the highest priority */
510 silc_dlist_start(stream->process);
511 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
512 if (p->priority > e->priority) {
513 silc_dlist_insert(stream->process, p);
518 silc_dlist_add(stream->process, p);
520 /* Get packet types to process */
523 packet_type = va_arg(ap, SilcInt32);
525 if (packet_type == SILC_PACKET_ANY)
528 if (packet_type == -1)
531 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
533 silc_mutex_unlock(stream->lock);
537 p->types[i - 1] = (SilcPacketType)packet_type;
543 silc_mutex_unlock(stream->lock);
545 silc_packet_stream_ref(stream);
550 /* Links `callbacks' to `stream' for specified packet types */
552 SilcBool silc_packet_stream_link(SilcPacketStream stream,
553 SilcPacketCallbacks *callbacks,
554 void *callback_context,
560 va_start(ap, priority);
561 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
568 /* Unlinks `callbacks' from `stream'. */
570 void silc_packet_stream_unlink(SilcPacketStream stream,
571 SilcPacketCallbacks *callbacks,
572 void *callback_context)
576 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
579 silc_mutex_lock(stream->lock);
581 silc_dlist_start(stream->process);
582 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
583 if (p->callbacks == callbacks &&
584 p->callback_context == callback_context) {
585 silc_dlist_del(stream->process, p);
590 if (!silc_dlist_count(stream->process)) {
591 silc_dlist_uninit(stream->process);
592 stream->process = NULL;
595 silc_mutex_unlock(stream->lock);
597 silc_packet_stream_unref(stream);
600 /* Reference packet stream */
602 void silc_packet_stream_ref(SilcPacketStream stream)
604 silc_mutex_lock(stream->lock);
606 silc_mutex_unlock(stream->lock);
609 /* Unreference packet stream */
611 void silc_packet_stream_unref(SilcPacketStream stream)
613 silc_mutex_lock(stream->lock);
615 silc_mutex_unlock(stream->lock);
616 if (stream->refcnt == 0)
617 silc_packet_stream_destroy(stream);
622 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
624 return stream->engine;
627 /* Set application context for packet stream */
629 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
631 silc_mutex_lock(stream->lock);
632 stream->stream_context = stream_context;
633 silc_mutex_unlock(stream->lock);
636 /* Return application context from packet stream */
638 void *silc_packet_get_context(SilcPacketStream stream)
641 silc_mutex_lock(stream->lock);
642 context = stream->stream_context;
643 silc_mutex_unlock(stream->lock);
647 /* Return underlaying stream */
649 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
651 return stream->stream;
654 /* Set ciphers for packet stream */
656 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
659 SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
660 silc_mutex_lock(stream->lock);
661 stream->send_key = send;
662 stream->receive_key = receive;
663 silc_mutex_unlock(stream->lock);
666 /* Return current ciphers from packet stream */
668 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
671 if (!stream->send_key && !stream->receive_key)
674 silc_mutex_lock(stream->lock);
677 *send = stream->send_key;
679 *receive = stream->receive_key;
681 silc_mutex_unlock(stream->lock);
686 /* Set HMACs for packet stream */
688 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
691 SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
692 silc_mutex_lock(stream->lock);
693 stream->send_hmac = send;
694 stream->receive_hmac = receive;
695 silc_mutex_unlock(stream->lock);
698 /* Return current HMACs from packet stream */
700 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
703 if (!stream->send_hmac && !stream->receive_hmac)
706 silc_mutex_lock(stream->lock);
709 *send = stream->send_hmac;
711 *receive = stream->receive_hmac;
713 silc_mutex_unlock(stream->lock);
718 /* Set SILC IDs to packet stream */
720 SilcBool silc_packet_set_ids(SilcPacketStream stream,
721 SilcIdType src_id_type, const void *src_id,
722 SilcIdType dst_id_type, const void *dst_id)
725 unsigned char tmp[32];
727 if (!src_id && !dst_id)
730 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
732 silc_mutex_lock(stream->lock);
735 silc_free(stream->src_id);
736 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
737 silc_mutex_unlock(stream->lock);
740 stream->src_id = silc_memdup(tmp, len);
741 if (!stream->src_id) {
742 silc_mutex_unlock(stream->lock);
745 stream->src_id_type = src_id_type;
746 stream->src_id_len = len;
750 silc_free(stream->dst_id);
751 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
752 silc_mutex_unlock(stream->lock);
755 stream->dst_id = silc_memdup(tmp, len);
756 if (!stream->dst_id) {
757 silc_mutex_unlock(stream->lock);
760 stream->dst_id_type = dst_id_type;
761 stream->dst_id_len = len;
764 silc_mutex_unlock(stream->lock);
771 void silc_packet_free(SilcPacket packet)
773 SilcPacketStream stream = packet->stream;
775 SILC_LOG_DEBUG(("Freeing packet %p", packet));
777 #if defined(SILC_DEBUG)
778 /* Check for double free */
779 assert(packet->stream != NULL);
780 #endif /* SILC_DEBUG */
782 silc_mutex_lock(stream->engine->lock);
784 packet->stream = NULL;
785 packet->src_id = packet->dst_id = NULL;
786 silc_buffer_reset(&packet->buffer);
788 /* Put the packet back to freelist */
789 silc_list_add(stream->engine->packet_pool, packet);
791 silc_mutex_unlock(stream->engine->lock);
794 /****************************** Packet Sending ******************************/
796 /* Prepare outgoing data buffer for packet sending. Returns the
797 pointer to that buffer into the `packet'. */
799 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
804 unsigned char *oldptr;
805 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
809 /* Allocate more space if needed */
810 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
811 if (!silc_buffer_realloc(&stream->outbuf,
812 silc_buffer_truelen(&stream->outbuf) + totlen))
816 /* Pull data area for the new packet, and return pointer to the start of
817 the data area and save the pointer in to the `packet'. MAC is pulled
818 later after it's computed. */
819 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
820 silc_buffer_set(packet, oldptr, totlen);
821 silc_buffer_push_tail(packet, mac_len);
826 /* Internal routine to send packet */
828 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
830 SilcPacketFlags flags,
831 SilcIdType src_id_type,
832 unsigned char *src_id,
833 SilcUInt32 src_id_len,
834 SilcIdType dst_id_type,
835 unsigned char *dst_id,
836 SilcUInt32 dst_id_len,
837 const unsigned char *data,
842 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[32], psn[4];
843 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
844 int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
845 SilcBufferStruct packet;
847 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
848 "data len %d", silc_get_packet_name(type), stream->send_psn,
849 flags, src_id_type, dst_id_type, data_len));
851 /* Get the true length of the packet. This is saved as payload length
852 into the packet header. This does not include the length of the
854 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
855 src_id_len + dst_id_len));
856 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
857 src_id_len + dst_id_len);
859 /* If IV is included, the IV and sequence number is added to packet */
860 if (stream->iv_included && cipher) {
862 psnlen = sizeof(psn);
863 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
866 /* We automatically figure out the packet structure from the packet
867 type and flags, and calculate correct length. Private messages with
868 private keys and channel messages are special packets as their
869 payload is encrypted already. */
870 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
871 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
872 type == SILC_PACKET_CHANNEL_MESSAGE) {
874 /* Padding is calculated from header + IDs */
875 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
876 psnlen), block_len, padlen);
878 /* Length to encrypt, header + IDs + padding. */
879 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
883 /* Padding is calculated from true length of the packet */
884 if (flags & SILC_PACKET_FLAG_LONG_PAD)
885 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
887 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
889 enclen += padlen + psnlen;
892 /* Remove implementation specific flags */
893 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
895 /* Get random padding */
896 for (i = 0; i < padlen; i++) tmppad[i] =
897 silc_rng_get_byte_fast(stream->engine->rng);
899 silc_mutex_lock(stream->lock);
901 /* Get packet pointer from the outgoing buffer */
902 if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
904 silc_mutex_unlock(stream->lock);
908 SILC_PUT32_MSB(stream->send_psn, psn);
910 /* Create the packet. This creates the SILC header, adds padding, and
911 the actual packet data. */
912 i = silc_buffer_format(&packet,
913 SILC_STR_UI_XNSTRING(iv, ivlen),
914 SILC_STR_UI_XNSTRING(psn, psnlen),
915 SILC_STR_UI_SHORT(truelen),
916 SILC_STR_UI_CHAR(flags),
917 SILC_STR_UI_CHAR(type),
918 SILC_STR_UI_CHAR(padlen),
920 SILC_STR_UI_CHAR(src_id_len),
921 SILC_STR_UI_CHAR(dst_id_len),
922 SILC_STR_UI_CHAR(src_id_type),
923 SILC_STR_UI_XNSTRING(src_id, src_id_len),
924 SILC_STR_UI_CHAR(dst_id_type),
925 SILC_STR_UI_XNSTRING(dst_id, dst_id_len),
926 SILC_STR_UI_XNSTRING(tmppad, padlen),
927 SILC_STR_UI_XNSTRING(data, data_len),
930 silc_mutex_unlock(stream->lock);
934 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
935 silc_buffer_data(&packet), silc_buffer_len(&packet));
937 /* Encrypt the packet */
939 SILC_LOG_DEBUG(("Encrypting packet"));
940 if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
941 packet.data + ivlen, enclen, NULL)) {
942 SILC_LOG_ERROR(("Packet encryption failed"));
943 silc_mutex_unlock(stream->lock);
952 /* MAC is computed from the entire encrypted packet data, and put
953 to the end of the packet. */
954 silc_hmac_init(hmac);
955 silc_hmac_update(hmac, psn, sizeof(psn));
956 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
957 silc_hmac_final(hmac, packet.tail, &mac_len);
958 silc_buffer_pull_tail(&packet, mac_len);
962 /* Write the packet to the stream */
963 while (silc_buffer_len(&stream->outbuf) > 0) {
964 i = silc_stream_write(stream->stream, stream->outbuf.data,
965 silc_buffer_len(&stream->outbuf));
968 silc_buffer_reset(&stream->outbuf);
969 silc_mutex_unlock(stream->lock);
970 SILC_PACKET_CALLBACK_EOS(stream);
976 silc_buffer_reset(&stream->outbuf);
977 silc_mutex_unlock(stream->lock);
978 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_WRITE);
983 /* Cannot write now, write later. */
984 silc_mutex_unlock(stream->lock);
989 silc_buffer_pull(&stream->outbuf, i);
991 silc_buffer_reset(&stream->outbuf);
993 silc_mutex_unlock(stream->lock);
999 SilcBool silc_packet_send(SilcPacketStream stream,
1000 SilcPacketType type, SilcPacketFlags flags,
1001 const unsigned char *data, SilcUInt32 data_len)
1003 return silc_packet_send_raw(stream, type, flags,
1004 stream->src_id_type,
1007 stream->dst_id_type,
1015 /* Sends a packet, extended routine */
1017 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1018 SilcPacketType type, SilcPacketFlags flags,
1019 SilcIdType src_id_type, void *src_id,
1020 SilcIdType dst_id_type, void *dst_id,
1021 const unsigned char *data, SilcUInt32 data_len,
1022 SilcCipher cipher, SilcHmac hmac)
1024 unsigned char src_id_data[32], dst_id_data[32];
1025 SilcUInt32 src_id_len, dst_id_len;
1028 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1029 sizeof(src_id_data), &src_id_len))
1032 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1033 sizeof(dst_id_data), &dst_id_len))
1036 return silc_packet_send_raw(stream, type, flags,
1037 src_id ? src_id_type : stream->src_id_type,
1038 src_id ? src_id_data : stream->src_id,
1039 src_id ? src_id_len : stream->src_id_len,
1040 dst_id ? dst_id_type : stream->dst_id_type,
1041 dst_id ? dst_id_data : stream->dst_id,
1042 dst_id ? dst_id_len : stream->dst_id_len,
1044 cipher ? cipher : stream->send_key,
1045 hmac ? hmac : stream->send_hmac);
1049 /***************************** Packet Receiving *****************************/
1051 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1053 static SilcBool silc_packet_check_mac(SilcHmac hmac,
1054 const unsigned char *data,
1055 SilcUInt32 data_len,
1056 const unsigned char *packet_mac,
1057 const unsigned char *packet_seq,
1058 SilcUInt32 sequence)
1062 unsigned char mac[32], psn[4];
1065 SILC_LOG_DEBUG(("Verifying MAC"));
1067 /* Compute HMAC of packet */
1068 silc_hmac_init(hmac);
1071 SILC_PUT32_MSB(sequence, psn);
1072 silc_hmac_update(hmac, psn, 4);
1074 silc_hmac_update(hmac, packet_seq, 4);
1076 silc_hmac_update(hmac, data, data_len);
1077 silc_hmac_final(hmac, mac, &mac_len);
1079 /* Compare the MAC's */
1080 if (memcmp(packet_mac, mac, mac_len)) {
1081 SILC_LOG_DEBUG(("MAC failed"));
1085 SILC_LOG_DEBUG(("MAC is Ok"));
1091 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1092 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1094 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1095 SilcUInt32 sequence, SilcBuffer buffer,
1098 if (normal == TRUE) {
1100 /* Decrypt rest of the packet */
1101 SILC_LOG_DEBUG(("Decrypting the packet"));
1102 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1103 silc_buffer_len(buffer), NULL))
1109 /* Decrypt rest of the header plus padding */
1112 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1114 SILC_LOG_DEBUG(("Decrypting the header"));
1116 /* Padding length + src id len + dst id len + header length - 16
1117 bytes already decrypted, gives the rest of the encrypted packet */
1118 silc_buffer_push(buffer, block_len);
1119 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1120 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1122 silc_buffer_pull(buffer, block_len);
1124 if (len > silc_buffer_len(buffer)) {
1125 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1129 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1138 /* Parses the packet. This is called when a whole packet is ready to be
1139 parsed. The buffer sent must be already decrypted before calling this
1142 static SilcBool silc_packet_parse(SilcPacket packet)
1144 SilcBuffer buffer = &packet->buffer;
1145 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1146 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1149 SILC_LOG_DEBUG(("Parsing incoming packet"));
1151 /* Parse the buffer. This parses the SILC header of the packet. */
1152 len = silc_buffer_unformat(buffer,
1154 SILC_STR_UI_CHAR(&src_id_len),
1155 SILC_STR_UI_CHAR(&dst_id_len),
1156 SILC_STR_UI_CHAR(&src_id_type),
1159 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1163 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1164 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1165 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1166 packet->src_id_len, packet->dst_id_len));
1170 ret = silc_buffer_unformat(buffer,
1171 SILC_STR_OFFSET(len),
1172 SILC_STR_UI_XNSTRING(&packet->src_id,
1174 SILC_STR_UI_CHAR(&dst_id_type),
1175 SILC_STR_UI_XNSTRING(&packet->dst_id,
1177 SILC_STR_OFFSET(padlen),
1180 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1184 if (src_id_type > SILC_ID_CHANNEL ||
1185 dst_id_type > SILC_ID_CHANNEL) {
1186 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1187 src_id_type, dst_id_type));
1191 packet->src_id_len = src_id_len;
1192 packet->dst_id_len = dst_id_len;
1193 packet->src_id_type = src_id_type;
1194 packet->dst_id_type = dst_id_type;
1196 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_len(buffer)),
1197 buffer->data, silc_buffer_len(buffer));
1199 /* Pull SILC header and padding from packet to get the data payload */
1200 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
1201 packet->src_id_len + packet->dst_id_len + padlen);
1203 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1204 silc_get_packet_name(packet->type)));
1209 /* Dispatch packet to application. Called with stream->lock locked. */
1211 static void silc_packet_dispatch(SilcPacket packet)
1213 SilcPacketStream stream = packet->stream;
1214 SilcPacketProcess p;
1215 SilcBool default_sent = FALSE;
1218 /* Parse the packet */
1219 if (!silc_packet_parse(packet)) {
1220 silc_mutex_unlock(packet->stream->lock);
1221 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1222 silc_mutex_lock(packet->stream->lock);
1223 silc_packet_free(packet);
1227 /* Dispatch packet to all packet processors that want it */
1229 if (!stream->process) {
1230 /* Send to default processor as no others exist */
1231 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1232 silc_mutex_unlock(packet->stream->lock);
1233 if (!stream->engine->callbacks->
1234 packet_receive(stream->engine, stream, packet,
1235 stream->engine->callback_context,
1236 stream->stream_context))
1237 silc_packet_free(packet);
1238 silc_mutex_lock(packet->stream->lock);
1242 silc_dlist_start(stream->process);
1243 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1245 /* If priority is 0 or less, we send to default processor first
1246 because default processor has 0 priority */
1247 if (!default_sent && p->priority <= 0) {
1248 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1249 default_sent = TRUE;
1250 silc_mutex_unlock(packet->stream->lock);
1251 if (stream->engine->callbacks->
1252 packet_receive(stream->engine, stream, packet,
1253 stream->engine->callback_context,
1254 stream->stream_context)) {
1255 silc_mutex_lock(packet->stream->lock);
1258 silc_mutex_lock(packet->stream->lock);
1261 /* Send to processor */
1263 /* Send all packet types */
1264 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1265 silc_mutex_unlock(packet->stream->lock);
1266 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1267 p->callback_context,
1268 stream->stream_context)) {
1269 silc_mutex_lock(packet->stream->lock);
1272 silc_mutex_lock(packet->stream->lock);
1274 /* Send specific types */
1275 for (pt = p->types; *pt; pt++) {
1276 if (*pt != packet->type)
1278 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1279 silc_mutex_unlock(packet->stream->lock);
1280 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1281 p->callback_context,
1282 stream->stream_context)) {
1283 silc_mutex_lock(packet->stream->lock);
1286 silc_mutex_lock(packet->stream->lock);
1292 if (!default_sent) {
1293 /* Send to default processor as it has not been sent yet */
1294 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1295 silc_mutex_unlock(packet->stream->lock);
1296 if (stream->engine->callbacks->
1297 packet_receive(stream->engine, stream, packet,
1298 stream->engine->callback_context,
1299 stream->stream_context)) {
1300 silc_mutex_lock(packet->stream->lock);
1303 silc_mutex_lock(packet->stream->lock);
1306 /* If we got here, no one wanted the packet, so drop it */
1307 silc_packet_free(packet);
1310 /* Process incoming data and parse packets. Called with stream->lock
1313 static void silc_packet_read_process(SilcPacketStream stream)
1316 SilcUInt16 packetlen;
1317 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1318 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1319 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1320 SilcBool normal = TRUE;
1323 /* Parse the packets from the data */
1324 while (silc_buffer_len(&stream->inbuf) > 0) {
1327 if (silc_buffer_len(&stream->inbuf) <
1328 stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN :
1329 SILC_PACKET_MIN_HEADER_LEN_IV) {
1330 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1334 if (stream->receive_hmac)
1335 mac_len = silc_hmac_len(stream->receive_hmac);
1339 /* Decrypt first block of the packet to get the length field out */
1340 if (stream->receive_key) {
1341 block_len = silc_cipher_get_block_len(stream->receive_key);
1343 if (stream->iv_included) {
1344 /* IV is included in the ciphertext */
1345 memcpy(iv, stream->inbuf.data, block_len);
1349 memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
1351 silc_cipher_decrypt(stream->receive_key, stream->inbuf.data + ivlen,
1352 tmp, block_len, iv);
1355 if (stream->iv_included) {
1356 /* Take sequence number from packet */
1357 packet_seq = header;
1361 block_len = SILC_PACKET_MIN_HEADER_LEN;
1362 header = stream->inbuf.data;
1365 /* Get packet length and full packet length with padding */
1366 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1369 if (packetlen < SILC_PACKET_MIN_LEN) {
1370 SILC_LOG_ERROR(("Received too short packet"));
1371 silc_mutex_unlock(stream->lock);
1372 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1373 silc_mutex_lock(stream->lock);
1374 memset(tmp, 0, sizeof(tmp));
1375 silc_buffer_reset(&stream->inbuf);
1379 if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1380 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1382 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1383 memset(tmp, 0, sizeof(tmp));
1387 /* Check MAC of the packet */
1388 if (!silc_packet_check_mac(stream->receive_hmac, stream->inbuf.data,
1390 stream->inbuf.data + ivlen + paddedlen,
1391 packet_seq, stream->receive_psn)) {
1392 silc_mutex_unlock(stream->lock);
1393 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1394 silc_mutex_lock(stream->lock);
1395 memset(tmp, 0, sizeof(tmp));
1396 silc_buffer_reset(&stream->inbuf);
1401 packet = silc_packet_alloc(stream->engine);
1403 silc_mutex_unlock(stream->lock);
1404 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1405 silc_mutex_lock(stream->lock);
1406 memset(tmp, 0, sizeof(tmp));
1407 silc_buffer_reset(&stream->inbuf);
1411 /* Allocate more space to packet buffer, if needed */
1412 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1413 if (!silc_buffer_realloc(&packet->buffer,
1414 silc_buffer_truelen(&packet->buffer) +
1416 silc_buffer_truelen(&packet->buffer)))) {
1417 silc_mutex_unlock(stream->lock);
1418 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1419 silc_mutex_lock(stream->lock);
1420 silc_packet_free(packet);
1421 memset(tmp, 0, sizeof(tmp));
1422 silc_buffer_reset(&stream->inbuf);
1427 /* Parse packet header */
1428 packet->flags = (SilcPacketFlags)header[2];
1429 packet->type = (SilcPacketType)header[3];
1431 if (stream->engine->local_is_router) {
1432 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1433 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1435 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1436 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1437 stream->is_router == TRUE))
1440 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1441 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1443 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1447 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1448 stream->receive_psn, paddedlen + ivlen + mac_len),
1449 stream->inbuf.data, paddedlen + ivlen + mac_len);
1451 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1452 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1453 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1454 silc_buffer_pull(&packet->buffer, block_len - psnlen);
1455 silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1456 psnlen + (block_len - psnlen)),
1457 paddedlen - ivlen - psnlen - (block_len - psnlen));
1458 if (stream->receive_key) {
1459 silc_cipher_set_iv(stream->receive_key, iv);
1460 ret = silc_packet_decrypt(stream->receive_key, stream->receive_hmac,
1461 stream->receive_psn, &packet->buffer, normal);
1463 silc_mutex_unlock(stream->lock);
1464 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1465 silc_mutex_lock(stream->lock);
1466 silc_packet_free(packet);
1467 memset(tmp, 0, sizeof(tmp));
1471 stream->receive_psn++;
1473 silc_buffer_push(&packet->buffer, block_len);
1475 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1476 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1478 /* Dispatch the packet to application */
1479 packet->stream = stream;
1480 silc_packet_dispatch(packet);
1483 silc_buffer_reset(&stream->inbuf);
1487 /****************************** Packet Waiting ******************************/
1489 /* Packet wait receive callback */
1491 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1492 SilcPacketStream stream,
1494 void *callback_context,
1495 void *stream_context);
1497 /* Packet waiting callbacks */
1498 static SilcPacketCallbacks silc_packet_wait_cbs =
1500 silc_packet_wait_packet_receive, NULL, NULL
1503 /* Packet waiting context */
1505 SilcMutex wait_lock;
1507 SilcList packet_queue;
1508 unsigned int stopped : 1;
1511 /* Packet wait receive callback */
1514 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1515 SilcPacketStream stream,
1517 void *callback_context,
1518 void *stream_context)
1520 SilcPacketWait pw = callback_context;
1522 /* Signal the waiting thread for a new packet */
1523 silc_mutex_lock(pw->wait_lock);
1526 silc_mutex_unlock(pw->wait_lock);
1530 silc_list_add(pw->packet_queue, packet);
1531 silc_cond_broadcast(pw->wait_cond);
1533 silc_mutex_unlock(pw->wait_lock);
1538 /* Initialize packet waiting */
1540 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1546 pw = silc_calloc(1, sizeof(*pw));
1550 /* Allocate mutex and conditional variable */
1551 if (!silc_mutex_alloc(&pw->wait_lock)) {
1555 if (!silc_cond_alloc(&pw->wait_cond)) {
1556 silc_mutex_free(pw->wait_lock);
1561 /* Link to the packet stream for the requested packet types */
1562 va_start(ap, stream);
1563 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
1567 silc_cond_free(pw->wait_cond);
1568 silc_mutex_free(pw->wait_lock);
1573 /* Initialize packet queue */
1574 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
1579 /* Uninitialize packet waiting */
1581 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
1583 SilcPacketWait pw = waiter;
1586 /* Signal any threads to stop waiting */
1587 silc_mutex_lock(pw->wait_lock);
1589 silc_cond_broadcast(pw->wait_cond);
1590 silc_mutex_unlock(pw->wait_lock);
1592 /* Re-acquire lock and free resources */
1593 silc_mutex_lock(pw->wait_lock);
1594 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
1596 /* Free any remaining packets */
1597 silc_list_start(pw->packet_queue);
1598 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
1599 silc_packet_free(packet);
1601 silc_mutex_unlock(pw->wait_lock);
1602 silc_cond_free(pw->wait_cond);
1603 silc_mutex_free(pw->wait_lock);
1607 /* Blocks thread until a packet has been received. */
1609 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
1611 SilcPacketWait pw = waiter;
1612 SilcBool ret = FALSE;
1614 silc_mutex_lock(pw->wait_lock);
1616 /* Wait here until packet has arrived */
1617 while (silc_list_count(pw->packet_queue) == 0) {
1619 silc_mutex_unlock(pw->wait_lock);
1622 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
1626 silc_list_start(pw->packet_queue);
1627 *return_packet = silc_list_get(pw->packet_queue);
1628 silc_list_del(pw->packet_queue, *return_packet);
1630 silc_mutex_unlock(pw->wait_lock);
1632 return ret == TRUE ? 1 : 0;