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 SilcHashTable streamers; /* Valid if streamers exist */
55 void *stream_context; /* Stream context */
56 SilcBufferStruct inbuf; /* In buffer */
57 SilcBufferStruct outbuf; /* Out buffer */
58 SilcUInt32 send_psn; /* Sending sequence */
59 SilcCipher send_key; /* Sending key */
60 SilcHmac send_hmac; /* Sending HMAC */
61 SilcUInt32 receive_psn; /* Receiving sequence */
62 SilcCipher receive_key; /* Receiving key */
63 SilcHmac receive_hmac; /* Receiving HMAC */
64 unsigned char *src_id; /* Source ID */
65 unsigned char *dst_id; /* Destination ID */
66 unsigned int src_id_len : 6;
67 unsigned int src_id_type : 2;
68 unsigned int dst_id_len : 6;
69 unsigned int dst_id_type : 2;
70 SilcUInt8 refcnt; /* Reference counter */
71 unsigned int is_router : 1; /* Set if router stream */
72 unsigned int destroyed : 1; /* Set if destroyed */
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. This much is decrypted always
82 when packet is received to be able to get all the relevant data out
84 #define SILC_PACKET_MIN_HEADER_LEN 16
86 /* Maximum padding length */
87 #define SILC_PACKET_MAX_PADLEN 128
89 /* Default padding length */
90 #define SILC_PACKET_DEFAULT_PADLEN 16
92 /* Minimum packet length */
93 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
98 /* Returns true length of the packet. */
99 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
101 SILC_GET16_MSB((__ret_truelen), (__packetdata)); \
102 (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4]; \
105 /* Calculates the data length with given header length. This macro
106 can be used to check whether the data_len with header_len exceeds
107 SILC_PACKET_MAX_LEN. If it does, this returns the new data_len
108 so that the SILC_PACKET_MAX_LEN is not exceeded. If the data_len
109 plus header_len fits SILC_PACKET_MAX_LEN the returned data length
110 is the data_len given as argument. */
111 #define SILC_PACKET_DATALEN(data_len, header_len) \
112 ((data_len + header_len) > SILC_PACKET_MAX_LEN ? \
113 data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
115 /* Calculates the length of the padding in the packet. */
116 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen) \
118 __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) % \
119 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
121 __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
124 /* Returns the length of the padding up to the maximum length, which
126 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen) \
128 __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) % \
129 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
133 #define SILC_PACKET_CALLBACK_EOS(s) \
135 (s)->engine->callbacks->eos((s)->engine, s, \
136 (s)->engine->callback_context, \
137 (s)->stream_context); \
141 #define SILC_PACKET_CALLBACK_ERROR(s, err) \
143 (s)->engine->callbacks->error((s)->engine, s, err, \
144 (s)->engine->callback_context, \
145 (s)->stream_context); \
149 /************************ Static utility functions **************************/
151 static void silc_packet_read_process(SilcPacketStream stream);
153 /* Our stream IO notifier callback. */
155 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
158 SilcPacketStream ps = context;
161 silc_mutex_lock(ps->lock);
164 silc_mutex_unlock(ps->lock);
170 case SILC_STREAM_CAN_WRITE:
171 if (!silc_buffer_headlen(&ps->outbuf)) {
172 silc_mutex_unlock(ps->lock);
176 SILC_LOG_DEBUG(("Writing pending data to stream"));
178 /* Write pending data to stream */
179 while (silc_buffer_len(&ps->outbuf) > 0) {
180 ret = silc_stream_write(ps->stream, ps->outbuf.data,
181 silc_buffer_len(&ps->outbuf));
184 silc_buffer_reset(&ps->outbuf);
185 silc_mutex_unlock(ps->lock);
186 SILC_PACKET_CALLBACK_EOS(ps);
192 silc_buffer_reset(&ps->outbuf);
193 silc_mutex_unlock(ps->lock);
194 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
199 /* Cannot write now, write later. */
200 silc_mutex_unlock(ps->lock);
205 silc_buffer_pull(&ps->outbuf, ret);
208 silc_buffer_reset(&ps->outbuf);
210 silc_mutex_unlock(ps->lock);
213 case SILC_STREAM_CAN_READ:
214 SILC_LOG_DEBUG(("Reading data from stream"));
216 /* Make sure we have fair amount of free space in inbuf */
217 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
218 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
219 SILC_PACKET_DEFAULT_SIZE * 2)) {
220 silc_mutex_unlock(ps->lock);
224 /* Read data from stream */
225 ret = silc_stream_read(ps->stream, ps->inbuf.tail,
226 silc_buffer_taillen(&ps->inbuf));
230 silc_buffer_reset(&ps->inbuf);
231 silc_mutex_unlock(ps->lock);
232 SILC_PACKET_CALLBACK_EOS(ps);
238 silc_buffer_reset(&ps->inbuf);
239 silc_mutex_unlock(ps->lock);
240 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
245 /* Cannot read now, do it later. */
246 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
247 silc_mutex_unlock(ps->lock);
251 /* Now process the data */
252 silc_buffer_pull_tail(&ps->inbuf, ret);
253 silc_packet_read_process(ps);
255 silc_mutex_unlock(ps->lock);
259 silc_mutex_unlock(ps->lock);
264 /* Allocate packet */
266 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
270 SILC_LOG_DEBUG(("Packet pool count %d",
271 silc_list_count(engine->packet_pool)));
273 silc_mutex_lock(engine->lock);
275 /* Get packet from freelist or allocate new one. */
276 packet = silc_list_get(engine->packet_pool);
280 silc_mutex_unlock(engine->lock);
282 packet = silc_calloc(1, sizeof(*packet));
286 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
288 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
293 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
294 silc_buffer_reset(&packet->buffer);
299 SILC_LOG_DEBUG(("Get packet %p", packet));
301 /* Delete from freelist */
302 silc_list_del(engine->packet_pool, packet);
304 silc_mutex_unlock(engine->lock);
310 /******************************** Packet API ********************************/
312 /* Allocate new packet engine */
315 silc_packet_engine_start(SilcRng rng, SilcBool router,
316 SilcPacketCallbacks *callbacks,
317 void *callback_context)
319 SilcPacketEngine engine;
324 SILC_LOG_DEBUG(("Starting new packet engine"));
328 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
331 engine = silc_calloc(1, sizeof(*engine));
336 engine->local_is_router = router;
337 engine->callbacks = callbacks;
338 engine->callback_context = callback_context;
339 silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
340 silc_mutex_alloc(&engine->lock);
342 /* Allocate packet free list */
343 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
344 for (i = 0; i < 5; i++) {
345 packet = silc_calloc(1, sizeof(*packet));
349 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
352 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
353 silc_buffer_reset(&packet->buffer);
355 silc_list_add(engine->packet_pool, packet);
357 silc_list_start(engine->packet_pool);
362 /* Stop packet engine */
364 void silc_packet_engine_stop(SilcPacketEngine engine)
367 SILC_LOG_DEBUG(("Stopping packet engine"));
377 /* Create new packet stream */
379 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
380 SilcSchedule schedule,
386 SILC_LOG_DEBUG(("Creating new packet stream"));
388 if (!engine || !stream)
391 ps = silc_calloc(1, sizeof(*ps));
399 /* Allocate buffers */
400 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
403 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
404 silc_buffer_reset(&ps->inbuf);
405 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
408 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
409 silc_buffer_reset(&ps->outbuf);
411 /* Initialize packet procesors list */
412 ps->process = silc_dlist_init();
414 /* Set IO notifier callback */
415 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
417 silc_mutex_alloc(&ps->lock);
420 silc_mutex_lock(engine->lock);
421 silc_list_add(engine->streams, ps);
422 silc_mutex_unlock(engine->lock);
427 /* Destroy packet stream */
429 void silc_packet_stream_destroy(SilcPacketStream stream)
434 if (stream->refcnt > 1) {
435 stream->destroyed = TRUE;
439 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
441 /* Delete from engine */
442 silc_mutex_lock(stream->engine->lock);
443 silc_list_del(stream->engine->streams, stream);
444 silc_mutex_unlock(stream->engine->lock);
446 /* Clear and free buffers */
447 silc_buffer_clear(&stream->inbuf);
448 silc_buffer_clear(&stream->outbuf);
449 silc_buffer_purge(&stream->inbuf);
450 silc_buffer_purge(&stream->outbuf);
454 /* Destroy the underlaying stream */
455 silc_stream_destroy(stream->stream);
457 silc_dlist_uninit(stream->process);
458 silc_mutex_free(stream->lock);
462 /* Marks as router stream */
464 void silc_packet_stream_set_router(SilcPacketStream stream)
466 stream->is_router = TRUE;
470 /* Links `callbacks' to `stream' for specified packet types */
472 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
473 SilcPacketCallbacks *callbacks,
474 void *callback_context,
475 int priority, va_list ap)
477 SilcPacketProcess p, e;
478 SilcInt32 packet_type;
481 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
485 if (!callbacks->packet_receive)
488 p = silc_calloc(1, sizeof(*p));
492 p->priority = priority;
493 p->callbacks = callbacks;
494 p->callback_context = callback_context;
496 silc_mutex_lock(stream->lock);
498 if (!stream->process) {
499 stream->process = silc_dlist_init();
500 if (!stream->process)
504 /* According to priority set the procesor to correct position. First
505 entry has the highest priority */
506 silc_dlist_start(stream->process);
507 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
508 if (p->priority > e->priority) {
509 silc_dlist_insert(stream->process, p);
514 silc_dlist_add(stream->process, p);
516 /* Get packet types to process */
519 packet_type = va_arg(ap, SilcInt32);
521 if (packet_type == SILC_PACKET_ANY)
524 if (packet_type == -1)
527 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
529 silc_mutex_unlock(stream->lock);
533 p->types[i - 1] = (SilcPacketType)packet_type;
539 silc_mutex_unlock(stream->lock);
541 silc_packet_stream_ref(stream);
546 /* Links `callbacks' to `stream' for specified packet types */
548 SilcBool silc_packet_stream_link(SilcPacketStream stream,
549 SilcPacketCallbacks *callbacks,
550 void *callback_context,
556 va_start(ap, priority);
557 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
564 /* Unlinks `callbacks' from `stream'. */
566 void silc_packet_stream_unlink(SilcPacketStream stream,
567 SilcPacketCallbacks *callbacks,
568 void *callback_context)
572 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
575 silc_mutex_lock(stream->lock);
577 silc_dlist_start(stream->process);
578 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
579 if (p->callbacks == callbacks &&
580 p->callback_context == callback_context) {
581 silc_dlist_del(stream->process, p);
586 if (!silc_dlist_count(stream->process)) {
587 silc_dlist_uninit(stream->process);
588 stream->process = NULL;
591 silc_mutex_unlock(stream->lock);
593 silc_packet_stream_unref(stream);
596 /* Reference packet stream */
598 void silc_packet_stream_ref(SilcPacketStream stream)
600 silc_mutex_lock(stream->lock);
602 silc_mutex_unlock(stream->lock);
605 /* Unreference packet stream */
607 void silc_packet_stream_unref(SilcPacketStream stream)
609 silc_mutex_lock(stream->lock);
611 silc_mutex_unlock(stream->lock);
612 if (stream->refcnt == 0)
613 silc_packet_stream_destroy(stream);
618 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
620 return stream->engine;
623 /* Set application context for packet stream */
625 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
627 silc_mutex_lock(stream->lock);
628 stream->stream_context = stream_context;
629 silc_mutex_unlock(stream->lock);
632 /* Return application context from packet stream */
634 void *silc_packet_get_context(SilcPacketStream stream)
637 silc_mutex_lock(stream->lock);
638 context = stream->stream_context;
639 silc_mutex_unlock(stream->lock);
643 /* Return underlaying stream */
645 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
647 return stream->stream;
650 /* Set ciphers for packet stream */
652 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
655 SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
656 silc_mutex_lock(stream->lock);
657 stream->send_key = send;
658 stream->receive_key = receive;
659 silc_mutex_unlock(stream->lock);
662 /* Return current ciphers from packet stream */
664 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
667 if (!stream->send_key && !stream->receive_key)
670 silc_mutex_lock(stream->lock);
673 *send = stream->send_key;
675 *receive = stream->receive_key;
677 silc_mutex_unlock(stream->lock);
682 /* Set HMACs for packet stream */
684 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
687 SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
688 silc_mutex_lock(stream->lock);
689 stream->send_hmac = send;
690 stream->receive_hmac = receive;
691 silc_mutex_unlock(stream->lock);
694 /* Return current HMACs from packet stream */
696 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
699 if (!stream->send_hmac && !stream->receive_hmac)
702 silc_mutex_lock(stream->lock);
705 *send = stream->send_hmac;
707 *receive = stream->receive_hmac;
709 silc_mutex_unlock(stream->lock);
714 /* Set SILC IDs to packet stream */
716 SilcBool silc_packet_set_ids(SilcPacketStream stream,
717 SilcIdType src_id_type, const void *src_id,
718 SilcIdType dst_id_type, const void *dst_id)
721 unsigned char tmp[32];
723 if (!src_id && !dst_id)
726 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
728 silc_mutex_lock(stream->lock);
731 silc_free(stream->src_id);
732 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
733 silc_mutex_unlock(stream->lock);
736 stream->src_id = silc_memdup(tmp, len);
737 if (!stream->src_id) {
738 silc_mutex_unlock(stream->lock);
741 stream->src_id_type = src_id_type;
742 stream->src_id_len = len;
746 silc_free(stream->dst_id);
747 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
748 silc_mutex_unlock(stream->lock);
751 stream->dst_id = silc_memdup(tmp, len);
752 if (!stream->dst_id) {
753 silc_mutex_unlock(stream->lock);
756 stream->dst_id_type = dst_id_type;
757 stream->dst_id_len = len;
760 silc_mutex_unlock(stream->lock);
767 void silc_packet_free(SilcPacket packet)
769 SilcPacketStream stream = packet->stream;
771 SILC_LOG_DEBUG(("Freeing packet %p", packet));
773 #if defined(SILC_DEBUG)
774 /* Check for double free */
775 assert(packet->stream != NULL);
776 #endif /* SILC_DEBUG */
778 silc_mutex_lock(stream->engine->lock);
780 packet->stream = NULL;
781 packet->src_id = packet->dst_id = NULL;
782 silc_buffer_reset(&packet->buffer);
784 /* Put the packet back to freelist */
785 silc_list_add(stream->engine->packet_pool, packet);
787 silc_mutex_unlock(stream->engine->lock);
790 /* Creates streamer */
792 SilcStream silc_packet_streamer_create(SilcPacketStream stream,
793 SilcPacketType packet_type,
794 SilcPacketFlags packet_flags)
800 /* Destroyes streamer */
802 void silc_packet_streamer_destroy(SilcStream stream)
808 /****************************** Packet Sending ******************************/
810 /* Prepare outgoing data buffer for packet sending. Returns the
811 pointer to that buffer into the `packet'. */
813 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
818 unsigned char *oldptr;
819 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
823 /* Allocate more space if needed */
824 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
825 if (!silc_buffer_realloc(&stream->outbuf,
826 silc_buffer_truelen(&stream->outbuf) + totlen))
830 /* Pull data area for the new packet, and return pointer to the start of
831 the data area and save the pointer in to the `packet'. MAC is pulled
832 later after it's computed. */
833 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
834 silc_buffer_set(packet, oldptr, totlen);
835 silc_buffer_push_tail(packet, mac_len);
840 /* Internal routine to send packet */
842 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
844 SilcPacketFlags flags,
845 SilcIdType src_id_type,
846 unsigned char *src_id,
847 SilcUInt32 src_id_len,
848 SilcIdType dst_id_type,
849 unsigned char *dst_id,
850 SilcUInt32 dst_id_len,
851 const unsigned char *data,
856 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
857 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
858 int i, enclen, truelen, padlen;
859 SilcBufferStruct packet;
861 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
862 "data len %d", silc_get_packet_name(type), stream->send_psn,
863 flags, src_id_type, dst_id_type, data_len));
865 /* Get the true length of the packet. This is saved as payload length
866 into the packet header. This does not include the length of the
868 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
869 src_id_len + dst_id_len));
870 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
871 src_id_len + dst_id_len);
873 /* We automatically figure out the packet structure from the packet
874 type and flags, and calculate correct length. Private messages with
875 private keys and channel messages are special packets as their
876 payload is encrypted already. */
877 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
878 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
879 type == SILC_PACKET_CHANNEL_MESSAGE) {
881 /* Padding is calculated from header + IDs */
882 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
884 dst_id_len), block_len, padlen);
886 /* Length to encrypt, header + IDs + padding. */
887 enclen = SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len + padlen;
890 /* Padding is calculated from true length of the packet */
891 if (flags & SILC_PACKET_FLAG_LONG_PAD)
892 SILC_PACKET_PADLEN_MAX(truelen, block_len, padlen);
894 SILC_PACKET_PADLEN(truelen, block_len, padlen);
899 /* Remove implementation specific flags */
900 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
902 /* Get random padding */
903 for (i = 0; i < padlen; i++) tmppad[i] =
904 silc_rng_get_byte_fast(stream->engine->rng);
906 silc_mutex_lock(stream->lock);
908 /* Get packet pointer from the outgoing buffer */
909 if (!silc_packet_send_prepare(stream, truelen + padlen, hmac, &packet)) {
910 silc_mutex_unlock(stream->lock);
914 /* Create the packet. This creates the SILC header, adds padding, and
915 the actual packet data. */
916 i = silc_buffer_format(&packet,
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 packet.data, silc_buffer_len(&packet));
939 /* Encrypt the packet */
941 SILC_LOG_DEBUG(("Encrypting packet"));
942 if (!silc_cipher_encrypt(cipher, packet.data, packet.data,
944 SILC_LOG_ERROR(("Packet encryption failed"));
945 silc_mutex_unlock(stream->lock);
952 unsigned char psn[4];
955 /* MAC is computed from the entire encrypted packet data, and put
956 to the end of the packet. */
957 silc_hmac_init(hmac);
958 SILC_PUT32_MSB(stream->send_psn, psn);
959 silc_hmac_update(hmac, psn, 4);
960 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
961 silc_hmac_final(hmac, packet.tail, &mac_len);
962 silc_buffer_pull_tail(&packet, mac_len);
966 /* Write the packet to the stream */
967 while (silc_buffer_len(&stream->outbuf) > 0) {
968 i = silc_stream_write(stream->stream, stream->outbuf.data,
969 silc_buffer_len(&stream->outbuf));
972 silc_buffer_reset(&stream->outbuf);
973 silc_mutex_unlock(stream->lock);
974 SILC_PACKET_CALLBACK_EOS(stream);
980 silc_buffer_reset(&stream->outbuf);
981 silc_mutex_unlock(stream->lock);
982 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_WRITE);
987 /* Cannot write now, write later. */
988 silc_mutex_unlock(stream->lock);
993 silc_buffer_pull(&stream->outbuf, i);
995 silc_buffer_reset(&stream->outbuf);
997 silc_mutex_unlock(stream->lock);
1001 /* Sends a packet */
1003 SilcBool silc_packet_send(SilcPacketStream stream,
1004 SilcPacketType type, SilcPacketFlags flags,
1005 const unsigned char *data, SilcUInt32 data_len)
1007 return silc_packet_send_raw(stream, type, flags,
1008 stream->src_id_type,
1011 stream->dst_id_type,
1019 /* Sends a packet, extended routine */
1021 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1022 SilcPacketType type, SilcPacketFlags flags,
1023 SilcIdType src_id_type, void *src_id,
1024 SilcIdType dst_id_type, void *dst_id,
1025 const unsigned char *data, SilcUInt32 data_len,
1026 SilcCipher cipher, SilcHmac hmac)
1028 unsigned char src_id_data[32], dst_id_data[32];
1029 SilcUInt32 src_id_len, dst_id_len;
1032 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1033 sizeof(src_id_data), &src_id_len))
1036 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1037 sizeof(dst_id_data), &dst_id_len))
1040 return silc_packet_send_raw(stream, type, flags,
1053 /***************************** Packet Receiving *****************************/
1055 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1057 static SilcBool silc_packet_check_mac(SilcHmac hmac,
1058 const unsigned char *data,
1059 SilcUInt32 data_len,
1060 const unsigned char *packet_mac,
1061 SilcUInt32 sequence)
1065 unsigned char mac[32], psn[4];
1068 SILC_LOG_DEBUG(("Verifying MAC"));
1070 /* Compute HMAC of packet */
1071 silc_hmac_init(hmac);
1072 SILC_PUT32_MSB(sequence, psn);
1073 silc_hmac_update(hmac, psn, 4);
1074 silc_hmac_update(hmac, data, data_len);
1075 silc_hmac_final(hmac, mac, &mac_len);
1077 /* Compare the MAC's */
1078 if (memcmp(packet_mac, mac, mac_len)) {
1079 SILC_LOG_DEBUG(("MAC failed"));
1083 SILC_LOG_DEBUG(("MAC is Ok"));
1089 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1090 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1092 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1093 SilcUInt32 sequence, SilcBuffer buffer,
1096 if (normal == TRUE) {
1098 /* Decrypt rest of the packet */
1099 SILC_LOG_DEBUG(("Decrypting the packet"));
1100 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1101 silc_buffer_len(buffer), NULL))
1107 /* Decrypt rest of the header plus padding */
1110 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1112 SILC_LOG_DEBUG(("Decrypting the header"));
1114 /* Padding length + src id len + dst id len + header length - 16
1115 bytes already decrypted, gives the rest of the encrypted packet */
1116 silc_buffer_push(buffer, block_len);
1117 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1118 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1120 silc_buffer_pull(buffer, block_len);
1122 if (len > silc_buffer_len(buffer)) {
1123 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1127 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1136 /* Parses the packet. This is called when a whole packet is ready to be
1137 parsed. The buffer sent must be already decrypted before calling this
1140 static SilcBool silc_packet_parse(SilcPacket packet)
1142 SilcBuffer buffer = &packet->buffer;
1143 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1144 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1147 SILC_LOG_DEBUG(("Parsing incoming packet"));
1149 /* Parse the buffer. This parses the SILC header of the packet. */
1150 len = silc_buffer_unformat(buffer,
1152 SILC_STR_UI_CHAR(&src_id_len),
1153 SILC_STR_UI_CHAR(&dst_id_len),
1154 SILC_STR_UI_CHAR(&src_id_type),
1157 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1161 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1162 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1163 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1164 packet->src_id_len, packet->dst_id_len));
1168 ret = silc_buffer_unformat(buffer,
1169 SILC_STR_OFFSET(len),
1170 SILC_STR_UI_XNSTRING(&packet->src_id,
1172 SILC_STR_UI_CHAR(&dst_id_type),
1173 SILC_STR_UI_XNSTRING(&packet->dst_id,
1175 SILC_STR_OFFSET(padlen),
1178 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1182 if (src_id_type > SILC_ID_CHANNEL ||
1183 dst_id_type > SILC_ID_CHANNEL) {
1184 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1185 src_id_type, dst_id_type));
1189 packet->src_id_len = src_id_len;
1190 packet->dst_id_len = dst_id_len;
1191 packet->src_id_type = src_id_type;
1192 packet->dst_id_type = dst_id_type;
1194 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_len(buffer)),
1195 buffer->data, silc_buffer_len(buffer));
1197 /* Pull SILC header and padding from packet to get the data payload */
1198 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
1199 packet->src_id_len + packet->dst_id_len + padlen);
1201 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1202 silc_get_packet_name(packet->type)));
1207 /* Dispatch packet to application. Called with stream->lock locked. */
1209 static void silc_packet_dispatch(SilcPacket packet)
1211 SilcPacketStream stream = packet->stream;
1212 SilcPacketProcess p;
1213 SilcBool default_sent = FALSE;
1216 /* Parse the packet */
1217 if (!silc_packet_parse(packet)) {
1218 silc_mutex_unlock(packet->stream->lock);
1219 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1220 silc_mutex_lock(packet->stream->lock);
1221 silc_packet_free(packet);
1225 /* Dispatch packet to all packet processors that want it */
1227 if (!stream->process) {
1228 /* Send to default processor as no others exist */
1229 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1230 silc_mutex_unlock(packet->stream->lock);
1231 if (!stream->engine->callbacks->
1232 packet_receive(stream->engine, stream, packet,
1233 stream->engine->callback_context,
1234 stream->stream_context))
1235 silc_packet_free(packet);
1236 silc_mutex_lock(packet->stream->lock);
1240 silc_dlist_start(stream->process);
1241 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1243 /* If priority is 0 or less, we send to default processor first
1244 because default processor has 0 priority */
1245 if (!default_sent && p->priority <= 0) {
1246 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1247 default_sent = TRUE;
1248 silc_mutex_unlock(packet->stream->lock);
1249 if (stream->engine->callbacks->
1250 packet_receive(stream->engine, stream, packet,
1251 stream->engine->callback_context,
1252 stream->stream_context)) {
1253 silc_mutex_lock(packet->stream->lock);
1256 silc_mutex_lock(packet->stream->lock);
1259 /* Send to processor */
1261 /* Send all packet types */
1262 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1263 silc_mutex_unlock(packet->stream->lock);
1264 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1265 p->callback_context,
1266 stream->stream_context)) {
1267 silc_mutex_lock(packet->stream->lock);
1270 silc_mutex_lock(packet->stream->lock);
1272 /* Send specific types */
1273 for (pt = p->types; *pt; pt++) {
1274 if (*pt != packet->type)
1276 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1277 silc_mutex_unlock(packet->stream->lock);
1278 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1279 p->callback_context,
1280 stream->stream_context)) {
1281 silc_mutex_lock(packet->stream->lock);
1284 silc_mutex_lock(packet->stream->lock);
1290 if (!default_sent) {
1291 /* Send to default processor as it has not been sent yet */
1292 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1293 silc_mutex_unlock(packet->stream->lock);
1294 if (stream->engine->callbacks->
1295 packet_receive(stream->engine, stream, packet,
1296 stream->engine->callback_context,
1297 stream->stream_context)) {
1298 silc_mutex_lock(packet->stream->lock);
1301 silc_mutex_lock(packet->stream->lock);
1304 /* If we got here, no one wanted the packet, so drop it */
1305 silc_packet_free(packet);
1308 /* Process incoming data and parse packets. Called with stream->lock
1311 static void silc_packet_read_process(SilcPacketStream stream)
1314 SilcUInt16 packetlen;
1315 SilcUInt32 paddedlen, mac_len, block_len;
1316 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1317 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
1318 SilcBool normal = TRUE;
1321 /* Parse the packets from the data */
1322 while (silc_buffer_len(&stream->inbuf) > 0) {
1324 if (silc_buffer_len(&stream->inbuf) < SILC_PACKET_MIN_HEADER_LEN) {
1325 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1329 if (stream->receive_hmac)
1330 mac_len = silc_hmac_len(stream->receive_hmac);
1334 /* Decrypt first block of the packet to get the length field out */
1335 if (stream->receive_key) {
1336 block_len = silc_cipher_get_block_len(stream->receive_key);
1337 memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
1338 silc_cipher_decrypt(stream->receive_key, stream->inbuf.data,
1339 tmp, block_len, iv);
1342 block_len = SILC_PACKET_MIN_HEADER_LEN;
1343 header = stream->inbuf.data;
1346 /* Get packet length and full packet length with padding */
1347 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1350 if (packetlen < SILC_PACKET_MIN_LEN) {
1351 SILC_LOG_ERROR(("Received too short packet"));
1352 silc_mutex_unlock(stream->lock);
1353 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1354 silc_mutex_lock(stream->lock);
1355 memset(tmp, 0, sizeof(tmp));
1356 silc_buffer_reset(&stream->inbuf);
1360 if (silc_buffer_len(&stream->inbuf) < paddedlen + mac_len) {
1361 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1363 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1364 memset(tmp, 0, sizeof(tmp));
1368 /* Check MAC of the packet */
1369 if (!silc_packet_check_mac(stream->receive_hmac, stream->inbuf.data,
1370 paddedlen, stream->inbuf.data + paddedlen,
1371 stream->receive_psn)) {
1372 silc_mutex_unlock(stream->lock);
1373 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1374 silc_mutex_lock(stream->lock);
1375 memset(tmp, 0, sizeof(tmp));
1376 silc_buffer_reset(&stream->inbuf);
1381 packet = silc_packet_alloc(stream->engine);
1383 silc_mutex_unlock(stream->lock);
1384 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1385 silc_mutex_lock(stream->lock);
1386 memset(tmp, 0, sizeof(tmp));
1387 silc_buffer_reset(&stream->inbuf);
1391 /* Allocate more space to packet buffer, if needed */
1392 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1393 if (!silc_buffer_realloc(&packet->buffer,
1394 silc_buffer_truelen(&packet->buffer) +
1396 silc_buffer_truelen(&packet->buffer)))) {
1397 silc_mutex_unlock(stream->lock);
1398 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1399 silc_mutex_lock(stream->lock);
1400 silc_packet_free(packet);
1401 memset(tmp, 0, sizeof(tmp));
1402 silc_buffer_reset(&stream->inbuf);
1407 /* Parse packet header */
1408 packet->flags = (SilcPacketFlags)header[2];
1409 packet->type = (SilcPacketType)header[3];
1411 if (stream->engine->local_is_router) {
1412 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1413 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1415 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1416 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1417 stream->is_router == TRUE))
1420 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1421 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1423 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1427 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1428 stream->receive_psn, paddedlen + mac_len),
1429 stream->inbuf.data, paddedlen + mac_len);
1431 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1432 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1433 silc_buffer_put(&packet->buffer, header, block_len);
1434 silc_buffer_pull(&packet->buffer, block_len);
1435 silc_buffer_put(&packet->buffer, stream->inbuf.data + block_len,
1436 paddedlen - block_len);
1437 if (stream->receive_key) {
1438 silc_cipher_set_iv(stream->receive_key, iv);
1439 ret = silc_packet_decrypt(stream->receive_key, stream->receive_hmac,
1440 stream->receive_psn, &packet->buffer, normal);
1442 silc_mutex_unlock(stream->lock);
1443 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1444 silc_mutex_lock(stream->lock);
1445 silc_packet_free(packet);
1446 memset(tmp, 0, sizeof(tmp));
1450 stream->receive_psn++;
1452 silc_buffer_push(&packet->buffer, block_len);
1454 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1455 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1457 /* Dispatch the packet to application */
1458 packet->stream = stream;
1459 silc_packet_dispatch(packet);
1462 silc_buffer_reset(&stream->inbuf);
1466 /****************************** Packet Waiting ******************************/
1468 /* Packet wait receive callback */
1470 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1471 SilcPacketStream stream,
1473 void *callback_context,
1474 void *stream_context);
1476 /* Packet waiting callbacks */
1477 static SilcPacketCallbacks silc_packet_wait_cbs =
1479 silc_packet_wait_packet_receive, NULL, NULL
1482 /* Packet waiting context */
1484 SilcMutex wait_lock;
1486 SilcList packet_queue;
1490 /* Packet wait receive callback */
1493 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1494 SilcPacketStream stream,
1496 void *callback_context,
1497 void *stream_context)
1499 SilcPacketWait pw = callback_context;
1501 /* Signal the waiting thread for a new packet */
1502 silc_mutex_lock(pw->wait_lock);
1505 silc_mutex_unlock(pw->wait_lock);
1509 silc_list_add(pw->packet_queue, packet);
1510 silc_cond_broadcast(pw->wait_cond);
1512 silc_mutex_unlock(pw->wait_lock);
1517 /* Initialize packet waiting */
1519 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1525 pw = silc_calloc(1, sizeof(*pw));
1529 /* Allocate mutex and conditional variable */
1530 if (!silc_mutex_alloc(&pw->wait_lock)) {
1534 if (!silc_cond_alloc(&pw->wait_cond)) {
1535 silc_mutex_free(pw->wait_lock);
1540 /* Link to the packet stream for the requested packet types */
1541 va_start(ap, stream);
1542 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
1546 silc_cond_free(pw->wait_cond);
1547 silc_mutex_free(pw->wait_lock);
1552 /* Initialize packet queue */
1553 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
1558 /* Uninitialize packet waiting */
1560 void silc_packet_wait_uninit(void *context, SilcPacketStream stream)
1562 SilcPacketWait pw = context;
1565 silc_mutex_lock(pw->wait_lock);
1566 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
1568 /* Free any remaining packets */
1569 silc_list_start(pw->packet_queue);
1570 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
1571 silc_packet_free(packet);
1573 silc_mutex_unlock(pw->wait_lock);
1575 silc_cond_free(pw->wait_cond);
1576 silc_mutex_free(pw->wait_lock);
1580 /* Blocks thread until a packet has been received. */
1582 int silc_packet_wait(void *context, int timeout, SilcPacket *return_packet)
1584 SilcPacketWait pw = context;
1585 SilcBool ret = FALSE;
1587 silc_mutex_lock(pw->wait_lock);
1589 /* Wait here until packet has arrived */
1591 while (silc_list_count(pw->packet_queue) == 0)
1592 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
1595 silc_list_start(pw->packet_queue);
1596 *return_packet = silc_list_get(pw->packet_queue);
1597 silc_list_del(pw->packet_queue, *return_packet);
1599 silc_mutex_unlock(pw->wait_lock);
1601 return ret == TRUE ? 1 : 0;