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);
790 if (silc_list_count(stream->engine->packet_pool) == 1)
791 silc_list_start(stream->engine->packet_pool);
793 silc_mutex_unlock(stream->engine->lock);
796 /****************************** Packet Sending ******************************/
798 /* Prepare outgoing data buffer for packet sending. Returns the
799 pointer to that buffer into the `packet'. */
801 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
806 unsigned char *oldptr;
807 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
811 /* Allocate more space if needed */
812 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
813 if (!silc_buffer_realloc(&stream->outbuf,
814 silc_buffer_truelen(&stream->outbuf) + totlen))
818 /* Pull data area for the new packet, and return pointer to the start of
819 the data area and save the pointer in to the `packet'. MAC is pulled
820 later after it's computed. */
821 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
822 silc_buffer_set(packet, oldptr, totlen);
823 silc_buffer_push_tail(packet, mac_len);
828 /* Internal routine to send packet */
830 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
832 SilcPacketFlags flags,
833 SilcIdType src_id_type,
834 unsigned char *src_id,
835 SilcUInt32 src_id_len,
836 SilcIdType dst_id_type,
837 unsigned char *dst_id,
838 SilcUInt32 dst_id_len,
839 const unsigned char *data,
844 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[32], psn[4];
845 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
846 int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
847 SilcBufferStruct packet;
849 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
850 "data len %d", silc_get_packet_name(type), stream->send_psn,
851 flags, src_id_type, dst_id_type, data_len));
853 /* Get the true length of the packet. This is saved as payload length
854 into the packet header. This does not include the length of the
856 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
857 src_id_len + dst_id_len));
858 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
859 src_id_len + dst_id_len);
861 /* If IV is included, the IV and sequence number is added to packet */
862 if (stream->iv_included && cipher) {
864 psnlen = sizeof(psn);
865 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
868 /* We automatically figure out the packet structure from the packet
869 type and flags, and calculate correct length. Private messages with
870 private keys and channel messages are special packets as their
871 payload is encrypted already. */
872 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
873 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
874 type == SILC_PACKET_CHANNEL_MESSAGE) {
876 /* Padding is calculated from header + IDs */
877 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
878 psnlen), block_len, padlen);
880 /* Length to encrypt, header + IDs + padding. */
881 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
885 /* Padding is calculated from true length of the packet */
886 if (flags & SILC_PACKET_FLAG_LONG_PAD)
887 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
889 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
891 enclen += padlen + psnlen;
894 /* Remove implementation specific flags */
895 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
897 /* Get random padding */
898 for (i = 0; i < padlen; i++) tmppad[i] =
899 silc_rng_get_byte_fast(stream->engine->rng);
901 silc_mutex_lock(stream->lock);
903 /* Get packet pointer from the outgoing buffer */
904 if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
906 silc_mutex_unlock(stream->lock);
910 SILC_PUT32_MSB(stream->send_psn, psn);
912 /* Create the packet. This creates the SILC header, adds padding, and
913 the actual packet data. */
914 i = silc_buffer_format(&packet,
915 SILC_STR_UI_XNSTRING(iv, ivlen),
916 SILC_STR_UI_XNSTRING(psn, psnlen),
917 SILC_STR_UI_SHORT(truelen),
918 SILC_STR_UI_CHAR(flags),
919 SILC_STR_UI_CHAR(type),
920 SILC_STR_UI_CHAR(padlen),
922 SILC_STR_UI_CHAR(src_id_len),
923 SILC_STR_UI_CHAR(dst_id_len),
924 SILC_STR_UI_CHAR(src_id_type),
925 SILC_STR_UI_XNSTRING(src_id, src_id_len),
926 SILC_STR_UI_CHAR(dst_id_type),
927 SILC_STR_UI_XNSTRING(dst_id, dst_id_len),
928 SILC_STR_UI_XNSTRING(tmppad, padlen),
929 SILC_STR_UI_XNSTRING(data, data_len),
932 silc_mutex_unlock(stream->lock);
936 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
937 silc_buffer_data(&packet), silc_buffer_len(&packet));
939 /* Encrypt the packet */
941 SILC_LOG_DEBUG(("Encrypting packet"));
942 if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
943 packet.data + ivlen, enclen, NULL)) {
944 SILC_LOG_ERROR(("Packet encryption failed"));
945 silc_mutex_unlock(stream->lock);
954 /* MAC is computed from the entire encrypted packet data, and put
955 to the end of the packet. */
956 silc_hmac_init(hmac);
957 silc_hmac_update(hmac, psn, sizeof(psn));
958 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
959 silc_hmac_final(hmac, packet.tail, &mac_len);
960 silc_buffer_pull_tail(&packet, mac_len);
964 /* Write the packet to the stream */
965 while (silc_buffer_len(&stream->outbuf) > 0) {
966 i = silc_stream_write(stream->stream, stream->outbuf.data,
967 silc_buffer_len(&stream->outbuf));
970 silc_buffer_reset(&stream->outbuf);
971 silc_mutex_unlock(stream->lock);
972 SILC_PACKET_CALLBACK_EOS(stream);
978 silc_buffer_reset(&stream->outbuf);
979 silc_mutex_unlock(stream->lock);
980 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_WRITE);
985 /* Cannot write now, write later. */
986 silc_mutex_unlock(stream->lock);
991 silc_buffer_pull(&stream->outbuf, i);
993 silc_buffer_reset(&stream->outbuf);
995 silc_mutex_unlock(stream->lock);
1001 SilcBool silc_packet_send(SilcPacketStream stream,
1002 SilcPacketType type, SilcPacketFlags flags,
1003 const unsigned char *data, SilcUInt32 data_len)
1005 return silc_packet_send_raw(stream, type, flags,
1006 stream->src_id_type,
1009 stream->dst_id_type,
1017 /* Sends a packet, extended routine */
1019 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1020 SilcPacketType type, SilcPacketFlags flags,
1021 SilcIdType src_id_type, void *src_id,
1022 SilcIdType dst_id_type, void *dst_id,
1023 const unsigned char *data, SilcUInt32 data_len,
1024 SilcCipher cipher, SilcHmac hmac)
1026 unsigned char src_id_data[32], dst_id_data[32];
1027 SilcUInt32 src_id_len, dst_id_len;
1030 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1031 sizeof(src_id_data), &src_id_len))
1034 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1035 sizeof(dst_id_data), &dst_id_len))
1038 return silc_packet_send_raw(stream, type, flags,
1039 src_id ? src_id_type : stream->src_id_type,
1040 src_id ? src_id_data : stream->src_id,
1041 src_id ? src_id_len : stream->src_id_len,
1042 dst_id ? dst_id_type : stream->dst_id_type,
1043 dst_id ? dst_id_data : stream->dst_id,
1044 dst_id ? dst_id_len : stream->dst_id_len,
1046 cipher ? cipher : stream->send_key,
1047 hmac ? hmac : stream->send_hmac);
1051 /***************************** Packet Receiving *****************************/
1053 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1055 static SilcBool silc_packet_check_mac(SilcHmac hmac,
1056 const unsigned char *data,
1057 SilcUInt32 data_len,
1058 const unsigned char *packet_mac,
1059 const unsigned char *packet_seq,
1060 SilcUInt32 sequence)
1064 unsigned char mac[32], psn[4];
1067 SILC_LOG_DEBUG(("Verifying MAC"));
1069 /* Compute HMAC of packet */
1070 silc_hmac_init(hmac);
1073 SILC_PUT32_MSB(sequence, psn);
1074 silc_hmac_update(hmac, psn, 4);
1076 silc_hmac_update(hmac, packet_seq, 4);
1078 silc_hmac_update(hmac, data, data_len);
1079 silc_hmac_final(hmac, mac, &mac_len);
1081 /* Compare the MAC's */
1082 if (memcmp(packet_mac, mac, mac_len)) {
1083 SILC_LOG_DEBUG(("MAC failed"));
1087 SILC_LOG_DEBUG(("MAC is Ok"));
1093 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1094 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1096 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1097 SilcUInt32 sequence, SilcBuffer buffer,
1100 if (normal == TRUE) {
1102 /* Decrypt rest of the packet */
1103 SILC_LOG_DEBUG(("Decrypting the packet"));
1104 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1105 silc_buffer_len(buffer), NULL))
1111 /* Decrypt rest of the header plus padding */
1114 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1116 SILC_LOG_DEBUG(("Decrypting the header"));
1118 /* Padding length + src id len + dst id len + header length - 16
1119 bytes already decrypted, gives the rest of the encrypted packet */
1120 silc_buffer_push(buffer, block_len);
1121 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1122 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1124 silc_buffer_pull(buffer, block_len);
1126 if (len > silc_buffer_len(buffer)) {
1127 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1131 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1140 /* Parses the packet. This is called when a whole packet is ready to be
1141 parsed. The buffer sent must be already decrypted before calling this
1144 static SilcBool silc_packet_parse(SilcPacket packet)
1146 SilcBuffer buffer = &packet->buffer;
1147 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1148 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1151 SILC_LOG_DEBUG(("Parsing incoming packet"));
1153 /* Parse the buffer. This parses the SILC header of the packet. */
1154 len = silc_buffer_unformat(buffer,
1156 SILC_STR_UI_CHAR(&src_id_len),
1157 SILC_STR_UI_CHAR(&dst_id_len),
1158 SILC_STR_UI_CHAR(&src_id_type),
1161 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1165 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1166 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1167 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1168 packet->src_id_len, packet->dst_id_len));
1172 ret = silc_buffer_unformat(buffer,
1173 SILC_STR_OFFSET(len),
1174 SILC_STR_UI_XNSTRING(&packet->src_id,
1176 SILC_STR_UI_CHAR(&dst_id_type),
1177 SILC_STR_UI_XNSTRING(&packet->dst_id,
1179 SILC_STR_OFFSET(padlen),
1182 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1186 if (src_id_type > SILC_ID_CHANNEL ||
1187 dst_id_type > SILC_ID_CHANNEL) {
1188 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1189 src_id_type, dst_id_type));
1193 packet->src_id_len = src_id_len;
1194 packet->dst_id_len = dst_id_len;
1195 packet->src_id_type = src_id_type;
1196 packet->dst_id_type = dst_id_type;
1198 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_len(buffer)),
1199 buffer->data, silc_buffer_len(buffer));
1201 /* Pull SILC header and padding from packet to get the data payload */
1202 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
1203 packet->src_id_len + packet->dst_id_len + padlen);
1205 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1206 silc_get_packet_name(packet->type)));
1211 /* Dispatch packet to application. Called with stream->lock locked. */
1213 static void silc_packet_dispatch(SilcPacket packet)
1215 SilcPacketStream stream = packet->stream;
1216 SilcPacketProcess p;
1217 SilcBool default_sent = FALSE;
1220 /* Parse the packet */
1221 if (!silc_packet_parse(packet)) {
1222 silc_mutex_unlock(packet->stream->lock);
1223 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1224 silc_mutex_lock(packet->stream->lock);
1225 silc_packet_free(packet);
1229 /* Dispatch packet to all packet processors that want it */
1231 if (!stream->process) {
1232 /* Send to default processor as no others exist */
1233 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1234 silc_mutex_unlock(packet->stream->lock);
1235 if (!stream->engine->callbacks->
1236 packet_receive(stream->engine, stream, packet,
1237 stream->engine->callback_context,
1238 stream->stream_context))
1239 silc_packet_free(packet);
1240 silc_mutex_lock(packet->stream->lock);
1244 silc_dlist_start(stream->process);
1245 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1247 /* If priority is 0 or less, we send to default processor first
1248 because default processor has 0 priority */
1249 if (!default_sent && p->priority <= 0) {
1250 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1251 default_sent = TRUE;
1252 silc_mutex_unlock(packet->stream->lock);
1253 if (stream->engine->callbacks->
1254 packet_receive(stream->engine, stream, packet,
1255 stream->engine->callback_context,
1256 stream->stream_context)) {
1257 silc_mutex_lock(packet->stream->lock);
1260 silc_mutex_lock(packet->stream->lock);
1263 /* Send to processor */
1265 /* Send all packet types */
1266 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1267 silc_mutex_unlock(packet->stream->lock);
1268 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1269 p->callback_context,
1270 stream->stream_context)) {
1271 silc_mutex_lock(packet->stream->lock);
1274 silc_mutex_lock(packet->stream->lock);
1276 /* Send specific types */
1277 for (pt = p->types; *pt; pt++) {
1278 if (*pt != packet->type)
1280 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1281 silc_mutex_unlock(packet->stream->lock);
1282 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1283 p->callback_context,
1284 stream->stream_context)) {
1285 silc_mutex_lock(packet->stream->lock);
1288 silc_mutex_lock(packet->stream->lock);
1294 if (!default_sent) {
1295 /* Send to default processor as it has not been sent yet */
1296 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1297 silc_mutex_unlock(packet->stream->lock);
1298 if (stream->engine->callbacks->
1299 packet_receive(stream->engine, stream, packet,
1300 stream->engine->callback_context,
1301 stream->stream_context)) {
1302 silc_mutex_lock(packet->stream->lock);
1305 silc_mutex_lock(packet->stream->lock);
1308 /* If we got here, no one wanted the packet, so drop it */
1309 silc_packet_free(packet);
1312 /* Process incoming data and parse packets. Called with stream->lock
1315 static void silc_packet_read_process(SilcPacketStream stream)
1318 SilcUInt16 packetlen;
1319 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1320 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1321 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1322 SilcBool normal = TRUE;
1325 /* Parse the packets from the data */
1326 while (silc_buffer_len(&stream->inbuf) > 0) {
1329 if (silc_buffer_len(&stream->inbuf) <
1330 stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1331 SILC_PACKET_MIN_HEADER_LEN) {
1332 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1336 if (stream->receive_hmac)
1337 mac_len = silc_hmac_len(stream->receive_hmac);
1341 /* Decrypt first block of the packet to get the length field out */
1342 if (stream->receive_key) {
1343 block_len = silc_cipher_get_block_len(stream->receive_key);
1345 if (stream->iv_included) {
1346 /* IV is included in the ciphertext */
1347 memcpy(iv, stream->inbuf.data, block_len);
1351 memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
1353 silc_cipher_decrypt(stream->receive_key, stream->inbuf.data + ivlen,
1354 tmp, block_len, iv);
1357 if (stream->iv_included) {
1358 /* Take sequence number from packet */
1359 packet_seq = header;
1363 block_len = SILC_PACKET_MIN_HEADER_LEN;
1364 header = stream->inbuf.data;
1367 /* Get packet length and full packet length with padding */
1368 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1371 if (packetlen < SILC_PACKET_MIN_LEN) {
1372 SILC_LOG_ERROR(("Received too short packet"));
1373 silc_mutex_unlock(stream->lock);
1374 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1375 silc_mutex_lock(stream->lock);
1376 memset(tmp, 0, sizeof(tmp));
1377 silc_buffer_reset(&stream->inbuf);
1381 if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1382 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1384 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1385 memset(tmp, 0, sizeof(tmp));
1389 /* Check MAC of the packet */
1390 if (!silc_packet_check_mac(stream->receive_hmac, stream->inbuf.data,
1392 stream->inbuf.data + ivlen + paddedlen,
1393 packet_seq, stream->receive_psn)) {
1394 silc_mutex_unlock(stream->lock);
1395 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1396 silc_mutex_lock(stream->lock);
1397 memset(tmp, 0, sizeof(tmp));
1398 silc_buffer_reset(&stream->inbuf);
1403 packet = silc_packet_alloc(stream->engine);
1405 silc_mutex_unlock(stream->lock);
1406 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1407 silc_mutex_lock(stream->lock);
1408 memset(tmp, 0, sizeof(tmp));
1409 silc_buffer_reset(&stream->inbuf);
1413 /* Allocate more space to packet buffer, if needed */
1414 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1415 if (!silc_buffer_realloc(&packet->buffer,
1416 silc_buffer_truelen(&packet->buffer) +
1418 silc_buffer_truelen(&packet->buffer)))) {
1419 silc_mutex_unlock(stream->lock);
1420 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1421 silc_mutex_lock(stream->lock);
1422 silc_packet_free(packet);
1423 memset(tmp, 0, sizeof(tmp));
1424 silc_buffer_reset(&stream->inbuf);
1429 /* Parse packet header */
1430 packet->flags = (SilcPacketFlags)header[2];
1431 packet->type = (SilcPacketType)header[3];
1433 if (stream->engine->local_is_router) {
1434 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1435 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1437 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1438 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1439 stream->is_router == TRUE))
1442 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1443 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1445 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1449 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1450 stream->receive_psn, paddedlen + ivlen + mac_len),
1451 stream->inbuf.data, paddedlen + ivlen + mac_len);
1453 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1454 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1455 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1456 silc_buffer_pull(&packet->buffer, block_len - psnlen);
1457 silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1458 psnlen + (block_len - psnlen)),
1459 paddedlen - ivlen - psnlen - (block_len - psnlen));
1460 if (stream->receive_key) {
1461 silc_cipher_set_iv(stream->receive_key, iv);
1462 ret = silc_packet_decrypt(stream->receive_key, stream->receive_hmac,
1463 stream->receive_psn, &packet->buffer, normal);
1465 silc_mutex_unlock(stream->lock);
1466 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1467 silc_mutex_lock(stream->lock);
1468 silc_packet_free(packet);
1469 memset(tmp, 0, sizeof(tmp));
1473 stream->receive_psn++;
1475 silc_buffer_push(&packet->buffer, block_len);
1477 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1478 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1480 /* Dispatch the packet to application */
1481 packet->stream = stream;
1482 silc_packet_dispatch(packet);
1485 silc_buffer_reset(&stream->inbuf);
1489 /****************************** Packet Waiting ******************************/
1491 /* Packet wait receive callback */
1493 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1494 SilcPacketStream stream,
1496 void *callback_context,
1497 void *stream_context);
1499 /* Packet waiting callbacks */
1500 static SilcPacketCallbacks silc_packet_wait_cbs =
1502 silc_packet_wait_packet_receive, NULL, NULL
1505 /* Packet waiting context */
1507 SilcMutex wait_lock;
1509 SilcList packet_queue;
1510 unsigned int stopped : 1;
1513 /* Packet wait receive callback */
1516 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1517 SilcPacketStream stream,
1519 void *callback_context,
1520 void *stream_context)
1522 SilcPacketWait pw = callback_context;
1524 /* Signal the waiting thread for a new packet */
1525 silc_mutex_lock(pw->wait_lock);
1528 silc_mutex_unlock(pw->wait_lock);
1532 silc_list_add(pw->packet_queue, packet);
1533 silc_cond_broadcast(pw->wait_cond);
1535 silc_mutex_unlock(pw->wait_lock);
1540 /* Initialize packet waiting */
1542 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1548 pw = silc_calloc(1, sizeof(*pw));
1552 /* Allocate mutex and conditional variable */
1553 if (!silc_mutex_alloc(&pw->wait_lock)) {
1557 if (!silc_cond_alloc(&pw->wait_cond)) {
1558 silc_mutex_free(pw->wait_lock);
1563 /* Link to the packet stream for the requested packet types */
1564 va_start(ap, stream);
1565 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
1569 silc_cond_free(pw->wait_cond);
1570 silc_mutex_free(pw->wait_lock);
1575 /* Initialize packet queue */
1576 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
1581 /* Uninitialize packet waiting */
1583 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
1585 SilcPacketWait pw = waiter;
1588 /* Signal any threads to stop waiting */
1589 silc_mutex_lock(pw->wait_lock);
1591 silc_cond_broadcast(pw->wait_cond);
1592 silc_mutex_unlock(pw->wait_lock);
1594 /* Re-acquire lock and free resources */
1595 silc_mutex_lock(pw->wait_lock);
1596 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
1598 /* Free any remaining packets */
1599 silc_list_start(pw->packet_queue);
1600 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
1601 silc_packet_free(packet);
1603 silc_mutex_unlock(pw->wait_lock);
1604 silc_cond_free(pw->wait_cond);
1605 silc_mutex_free(pw->wait_lock);
1609 /* Blocks thread until a packet has been received. */
1611 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
1613 SilcPacketWait pw = waiter;
1614 SilcBool ret = FALSE;
1616 silc_mutex_lock(pw->wait_lock);
1618 /* Wait here until packet has arrived */
1619 while (silc_list_count(pw->packet_queue) == 0) {
1621 silc_mutex_unlock(pw->wait_lock);
1624 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
1628 silc_list_start(pw->packet_queue);
1629 *return_packet = silc_list_get(pw->packet_queue);
1630 silc_list_del(pw->packet_queue, *return_packet);
1632 silc_mutex_unlock(pw->wait_lock);
1634 return ret == TRUE ? 1 : 0;