5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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 /* Packet receiving can only happen in one thread, so locking is not
215 required in packet receiving procedure. */
216 silc_mutex_unlock(ps->lock);
218 SILC_LOG_DEBUG(("Reading data from stream"));
220 /* Make sure we have fair amount of free space in inbuf */
221 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
222 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
223 SILC_PACKET_DEFAULT_SIZE * 2))
226 /* Read data from stream */
227 ret = silc_stream_read(ps->stream, ps->inbuf.tail,
228 silc_buffer_taillen(&ps->inbuf));
232 silc_buffer_reset(&ps->inbuf);
233 SILC_PACKET_CALLBACK_EOS(ps);
239 silc_buffer_reset(&ps->inbuf);
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));
251 silc_buffer_pull_tail(&ps->inbuf, ret);
253 /* Now process the data */
254 silc_packet_read_process(ps);
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_free(silc_buffer_steal(&stream->inbuf, NULL));
450 silc_free(silc_buffer_steal(&stream->outbuf, NULL));
452 silc_dlist_uninit(stream->process);
459 /* Marks as router stream */
461 void silc_packet_stream_set_router(SilcPacketStream stream)
463 stream->is_router = TRUE;
466 /* Links `callbacks' to `stream' for specified packet types */
468 SilcBool silc_packet_stream_link(SilcPacketStream stream,
469 SilcPacketCallbacks *callbacks,
470 void *callback_context,
474 SilcPacketProcess p, e;
475 SilcInt32 packet_type;
478 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
482 if (!callbacks->packet_receive)
485 p = silc_calloc(1, sizeof(*p));
489 p->priority = priority;
490 p->callbacks = callbacks;
491 p->callback_context = callback_context;
493 silc_mutex_lock(stream->lock);
495 if (!stream->process) {
496 stream->process = silc_dlist_init();
497 if (!stream->process)
501 /* According to priority set the procesor to correct position. First
502 entry has the highest priority */
503 silc_dlist_start(stream->process);
504 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
505 if (p->priority > e->priority) {
506 silc_dlist_insert(stream->process, p);
511 silc_dlist_add(stream->process, p);
513 silc_mutex_unlock(stream->lock);
515 /* Get packet types to process */
516 va_start(ap, priority);
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));
531 p->types[i - 1] = (SilcPacketType)packet_type;
538 silc_packet_stream_ref(stream);
543 /* Unlinks `callbacks' from `stream'. */
545 void silc_packet_stream_unlink(SilcPacketStream stream,
546 SilcPacketCallbacks *callbacks,
547 void *callback_context)
551 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
554 silc_mutex_lock(stream->lock);
556 silc_dlist_start(stream->process);
557 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
558 if (p->callbacks == callbacks &&
559 p->callback_context == callback_context) {
560 silc_dlist_del(stream->process, p);
565 if (!silc_dlist_count(stream->process)) {
566 silc_dlist_uninit(stream->process);
567 stream->process = NULL;
570 silc_mutex_unlock(stream->lock);
572 silc_packet_stream_unref(stream);
575 /* Reference packet stream */
577 void silc_packet_stream_ref(SilcPacketStream stream)
579 silc_mutex_lock(stream->lock);
581 silc_mutex_unlock(stream->lock);
584 /* Unreference packet stream */
586 void silc_packet_stream_unref(SilcPacketStream stream)
588 silc_mutex_lock(stream->lock);
590 silc_mutex_unlock(stream->lock);
591 if (stream->refcnt == 0)
592 silc_packet_stream_destroy(stream);
597 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
599 return stream->engine;
602 /* Set application context for packet stream */
604 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
606 stream->stream_context = stream_context;
609 /* Return application context from packet stream */
611 void *silc_packet_get_context(SilcPacketStream stream)
613 return stream->stream_context;
616 /* Return underlaying stream */
618 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
620 return stream->stream;
623 /* Set ciphers for packet stream */
625 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
628 SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
629 stream->send_key = send;
630 stream->receive_key = receive;
633 /* Return current ciphers from packet stream */
635 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
638 if (!stream->send_key && !stream->receive_key)
642 *send = stream->send_key;
644 *receive = stream->receive_key;
649 /* Set HMACs for packet stream */
651 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
654 SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
655 stream->send_hmac = send;
656 stream->receive_hmac = receive;
659 /* Return current HMACs from packet stream */
661 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
664 if (!stream->send_hmac && !stream->receive_hmac)
668 *send = stream->send_hmac;
670 *receive = stream->receive_hmac;
675 /* Set SILC IDs to packet stream */
677 SilcBool silc_packet_set_ids(SilcPacketStream stream,
678 SilcIdType src_id_type, const void *src_id,
679 SilcIdType dst_id_type, const void *dst_id)
682 unsigned char tmp[32];
684 if (!src_id && !dst_id)
687 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
690 silc_free(stream->src_id);
691 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len))
693 stream->src_id = silc_memdup(tmp, len);
696 stream->src_id_type = src_id_type;
697 stream->src_id_len = len;
701 silc_free(stream->dst_id);
702 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len))
704 stream->dst_id = silc_memdup(tmp, len);
707 stream->dst_id_type = dst_id_type;
708 stream->dst_id_len = len;
716 void silc_packet_free(SilcPacket packet)
718 SilcPacketStream stream = packet->stream;
720 SILC_LOG_DEBUG(("Freeing packet %p", packet));
722 #if defined(SILC_DEBUG)
723 /* Check for double free */
724 assert(packet->stream != NULL);
725 #endif /* SILC_DEBUG */
727 silc_mutex_lock(stream->engine->lock);
729 packet->stream = NULL;
730 packet->src_id = packet->dst_id = NULL;
731 silc_buffer_reset(&packet->buffer);
733 /* Put the packet back to freelist */
734 silc_list_add(stream->engine->packet_pool, packet);
736 silc_mutex_unlock(stream->engine->lock);
739 /* Creates streamer */
741 SilcStream silc_packet_streamer_create(SilcPacketStream stream,
742 SilcPacketType packet_type,
743 SilcPacketFlags packet_flags)
749 /* Destroyes streamer */
751 void silc_packet_streamer_destroy(SilcStream stream)
757 /****************************** Packet Sending ******************************/
759 /* Prepare outgoing data buffer for packet sending. Returns the
760 pointer to that buffer into the `packet'. */
762 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
767 unsigned char *oldptr;
768 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
772 /* Allocate more space if needed */
773 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
774 if (!silc_buffer_realloc(&stream->outbuf,
775 silc_buffer_truelen(&stream->outbuf) + totlen))
779 /* Pull data area for the new packet, and return pointer to the start of
780 the data area and save the pointer in to the `packet'. MAC is pulled
781 later after it's computed. */
782 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
783 silc_buffer_set(packet, oldptr, totlen);
784 silc_buffer_push_tail(packet, mac_len);
789 /* Internal routine to send packet */
791 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
793 SilcPacketFlags flags,
794 SilcIdType src_id_type,
795 unsigned char *src_id,
796 SilcUInt32 src_id_len,
797 SilcIdType dst_id_type,
798 unsigned char *dst_id,
799 SilcUInt32 dst_id_len,
800 const unsigned char *data,
805 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
806 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
807 int i, enclen, truelen, padlen;
808 SilcBufferStruct packet;
810 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
811 "data len %d", silc_get_packet_name(type), stream->send_psn,
812 flags, src_id_type, dst_id_type, data_len));
814 /* Get the true length of the packet. This is saved as payload length
815 into the packet header. This does not include the length of the
817 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
818 src_id_len + dst_id_len));
819 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
820 src_id_len + dst_id_len);
822 /* We automatically figure out the packet structure from the packet
823 type and flags, and calculate correct length. Private messages with
824 private keys and channel messages are special packets as their
825 payload is encrypted already. */
826 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
827 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
828 type == SILC_PACKET_CHANNEL_MESSAGE) {
830 /* Padding is calculated from header + IDs */
831 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
833 dst_id_len), block_len, padlen);
835 /* Length to encrypt, header + IDs + padding. */
836 enclen = SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len + padlen;
839 /* Padding is calculated from true length of the packet */
840 if (flags & SILC_PACKET_FLAG_LONG_PAD)
841 SILC_PACKET_PADLEN_MAX(truelen, block_len, padlen);
843 SILC_PACKET_PADLEN(truelen, block_len, padlen);
848 /* Remove implementation specific flags */
849 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
851 /* Get random padding */
852 for (i = 0; i < padlen; i++) tmppad[i] =
853 silc_rng_get_byte_fast(stream->engine->rng);
855 silc_mutex_lock(stream->lock);
857 /* Get packet pointer from the outgoing buffer */
858 if (!silc_packet_send_prepare(stream, truelen + padlen, hmac, &packet)) {
859 silc_mutex_unlock(stream->lock);
863 /* Create the packet. This creates the SILC header, adds padding, and
864 the actual packet data. */
865 i = silc_buffer_format(&packet,
866 SILC_STR_UI_SHORT(truelen),
867 SILC_STR_UI_CHAR(flags),
868 SILC_STR_UI_CHAR(type),
869 SILC_STR_UI_CHAR(padlen),
871 SILC_STR_UI_CHAR(src_id_len),
872 SILC_STR_UI_CHAR(dst_id_len),
873 SILC_STR_UI_CHAR(src_id_type),
874 SILC_STR_UI_XNSTRING(src_id, src_id_len),
875 SILC_STR_UI_CHAR(dst_id_type),
876 SILC_STR_UI_XNSTRING(dst_id, dst_id_len),
877 SILC_STR_UI_XNSTRING(tmppad, padlen),
878 SILC_STR_UI_XNSTRING(data, data_len),
881 silc_mutex_unlock(stream->lock);
885 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
886 packet.data, silc_buffer_len(&packet));
888 /* Encrypt the packet */
890 if (!silc_cipher_encrypt(cipher, packet.data, packet.data,
892 SILC_LOG_ERROR(("Packet encryption failed"));
893 silc_mutex_unlock(stream->lock);
899 unsigned char psn[4];
902 /* MAC is computed from the entire encrypted packet data, and put
903 to the end of the packet. */
904 silc_hmac_init(hmac);
905 SILC_PUT32_MSB(stream->send_psn, psn);
906 silc_hmac_update(hmac, psn, 4);
907 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
908 silc_hmac_final(hmac, packet.tail, &mac_len);
909 silc_buffer_pull_tail(&packet, mac_len);
913 /* Write the packet to the stream */
914 while (silc_buffer_len(&stream->outbuf) > 0) {
915 i = silc_stream_write(stream->stream, stream->outbuf.data,
916 silc_buffer_len(&stream->outbuf));
919 silc_buffer_reset(&stream->outbuf);
920 silc_mutex_unlock(stream->lock);
921 SILC_PACKET_CALLBACK_EOS(stream);
927 silc_buffer_reset(&stream->outbuf);
928 silc_mutex_unlock(stream->lock);
929 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_WRITE);
934 /* Cannot write now, write later. */
935 silc_mutex_unlock(stream->lock);
940 silc_buffer_pull(&stream->outbuf, i);
942 silc_buffer_reset(&stream->outbuf);
944 silc_mutex_unlock(stream->lock);
950 SilcBool silc_packet_send(SilcPacketStream stream,
951 SilcPacketType type, SilcPacketFlags flags,
952 const unsigned char *data, SilcUInt32 data_len)
954 return silc_packet_send_raw(stream, type, flags,
966 /* Sends a packet, extended routine */
968 SilcBool silc_packet_send_ext(SilcPacketStream stream,
969 SilcPacketType type, SilcPacketFlags flags,
970 SilcIdType src_id_type, void *src_id,
971 SilcIdType dst_id_type, void *dst_id,
972 const unsigned char *data, SilcUInt32 data_len,
973 SilcCipher cipher, SilcHmac hmac)
975 unsigned char src_id_data[32], dst_id_data[32];
976 SilcUInt32 src_id_len, dst_id_len;
979 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
980 sizeof(src_id_data), &src_id_len))
983 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
984 sizeof(dst_id_data), &dst_id_len))
987 return silc_packet_send_raw(stream, type, flags,
1000 /***************************** Packet Receiving *****************************/
1002 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1004 static SilcBool silc_packet_check_mac(SilcHmac hmac,
1005 const unsigned char *data,
1006 SilcUInt32 data_len,
1007 const unsigned char *packet_mac,
1008 SilcUInt32 sequence)
1012 unsigned char mac[32], psn[4];
1015 SILC_LOG_DEBUG(("Verifying MAC"));
1017 /* Compute HMAC of packet */
1018 silc_hmac_init(hmac);
1019 SILC_PUT32_MSB(sequence, psn);
1020 silc_hmac_update(hmac, psn, 4);
1021 silc_hmac_update(hmac, data, data_len);
1022 silc_hmac_final(hmac, mac, &mac_len);
1024 /* Compare the MAC's */
1025 if (memcmp(packet_mac, mac, mac_len)) {
1026 SILC_LOG_DEBUG(("MAC failed"));
1030 SILC_LOG_DEBUG(("MAC is Ok"));
1036 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1037 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1039 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1040 SilcUInt32 sequence, SilcBuffer buffer,
1043 if (normal == TRUE) {
1045 /* Decrypt rest of the packet */
1046 SILC_LOG_DEBUG(("Decrypting the packet"));
1047 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1048 silc_buffer_len(buffer), NULL))
1054 /* Decrypt rest of the header plus padding */
1057 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1059 SILC_LOG_DEBUG(("Decrypting the header"));
1061 /* Padding length + src id len + dst id len + header length - 16
1062 bytes already decrypted, gives the rest of the encrypted packet */
1063 silc_buffer_push(buffer, block_len);
1064 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1065 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1067 silc_buffer_pull(buffer, block_len);
1069 if (len > silc_buffer_len(buffer)) {
1070 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1074 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1083 /* Parses the packet. This is called when a whole packet is ready to be
1084 parsed. The buffer sent must be already decrypted before calling this
1087 static SilcBool silc_packet_parse(SilcPacket packet)
1089 SilcBuffer buffer = &packet->buffer;
1090 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1091 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1094 SILC_LOG_DEBUG(("Parsing incoming packet"));
1096 /* Parse the buffer. This parses the SILC header of the packet. */
1097 len = silc_buffer_unformat(buffer,
1099 SILC_STR_UI_CHAR(&src_id_len),
1100 SILC_STR_UI_CHAR(&dst_id_len),
1101 SILC_STR_UI_CHAR(&src_id_type),
1104 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1108 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1109 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1110 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1111 packet->src_id_len, packet->dst_id_len));
1115 ret = silc_buffer_unformat(buffer,
1116 SILC_STR_OFFSET(len),
1117 SILC_STR_UI_XNSTRING(&packet->src_id,
1119 SILC_STR_UI_CHAR(&dst_id_type),
1120 SILC_STR_UI_XNSTRING(&packet->dst_id,
1122 SILC_STR_OFFSET(padlen),
1125 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1129 if (src_id_type > SILC_ID_CHANNEL ||
1130 dst_id_type > SILC_ID_CHANNEL) {
1131 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1132 src_id_type, dst_id_type));
1136 packet->src_id_len = src_id_len;
1137 packet->dst_id_len = dst_id_len;
1138 packet->src_id_type = src_id_type;
1139 packet->dst_id_type = dst_id_type;
1141 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_len(buffer)),
1142 buffer->data, silc_buffer_len(buffer));
1144 /* Pull SILC header and padding from packet to get the data payload */
1145 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
1146 packet->src_id_len + packet->dst_id_len + padlen);
1148 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1149 silc_get_packet_name(packet->type)));
1154 /* Dispatch packet to application */
1156 static void silc_packet_dispatch(SilcPacket packet)
1158 SilcPacketStream stream = packet->stream;
1159 SilcPacketProcess p;
1160 SilcBool default_sent = FALSE;
1163 /* Parse the packet */
1164 if (!silc_packet_parse(packet)) {
1165 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1166 silc_packet_free(packet);
1170 /* Dispatch packet to all packet processors that want it */
1172 if (!stream->process) {
1173 /* Send to default processor as no others exist */
1174 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1175 if (!stream->engine->callbacks->
1176 packet_receive(stream->engine, stream, packet,
1177 stream->engine->callback_context,
1178 stream->stream_context))
1179 silc_packet_free(packet);
1183 silc_dlist_start(stream->process);
1184 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1186 /* If priority is 0 or less, we send to default processor first
1187 because default processor has 0 priority */
1188 if (!default_sent && p->priority <= 0) {
1189 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1190 default_sent = TRUE;
1191 if (stream->engine->callbacks->
1192 packet_receive(stream->engine, stream, packet,
1193 stream->engine->callback_context,
1194 stream->stream_context)) {
1199 /* Send to processor */
1201 /* Send all packet types */
1202 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1203 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1204 p->callback_context,
1205 stream->stream_context))
1208 /* Send specific types */
1209 for (pt = p->types; *pt; pt++)
1210 if (*pt == packet->type) {
1211 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks",
1213 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1214 p->callback_context,
1215 stream->stream_context))
1222 if (!default_sent) {
1223 /* Send to default processor as it has not been sent yet */
1224 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1225 if (stream->engine->callbacks->
1226 packet_receive(stream->engine, stream, packet,
1227 stream->engine->callback_context,
1228 stream->stream_context))
1232 /* If we got here, no one wanted the packet, so drop it */
1233 silc_packet_free(packet);
1236 /* Process incoming data and parse packets. */
1238 static void silc_packet_read_process(SilcPacketStream stream)
1241 SilcUInt16 packetlen;
1242 SilcUInt32 paddedlen, mac_len, block_len;
1243 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1244 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
1245 SilcBool normal = TRUE;
1248 /* Parse the packets from the data */
1249 while (silc_buffer_len(&stream->inbuf) > 0) {
1251 if (silc_buffer_len(&stream->inbuf) < SILC_PACKET_MIN_HEADER_LEN) {
1252 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1256 if (stream->receive_hmac)
1257 mac_len = silc_hmac_len(stream->receive_hmac);
1261 /* Decrypt first block of the packet to get the length field out */
1262 if (stream->receive_key) {
1263 block_len = silc_cipher_get_block_len(stream->receive_key);
1264 memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
1265 silc_cipher_decrypt(stream->receive_key, stream->inbuf.data,
1266 tmp, block_len, iv);
1269 block_len = SILC_PACKET_MIN_HEADER_LEN;
1270 header = stream->inbuf.data;
1273 /* Get packet length and full packet length with padding */
1274 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1277 if (packetlen < SILC_PACKET_MIN_LEN) {
1278 SILC_LOG_ERROR(("Received too short packet"));
1279 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1280 memset(tmp, 0, sizeof(tmp));
1281 silc_buffer_reset(&stream->inbuf);
1285 if (silc_buffer_len(&stream->inbuf) < paddedlen + mac_len) {
1286 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1288 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1289 memset(tmp, 0, sizeof(tmp));
1293 /* Check MAC of the packet */
1294 if (!silc_packet_check_mac(stream->receive_hmac, stream->inbuf.data,
1295 paddedlen, stream->inbuf.data + paddedlen,
1296 stream->receive_psn)) {
1297 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1298 memset(tmp, 0, sizeof(tmp));
1299 silc_buffer_reset(&stream->inbuf);
1304 packet = silc_packet_alloc(stream->engine);
1306 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1307 memset(tmp, 0, sizeof(tmp));
1308 silc_buffer_reset(&stream->inbuf);
1312 /* Allocate more space to packet buffer, if needed */
1313 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1314 if (!silc_buffer_realloc(&packet->buffer,
1315 silc_buffer_truelen(&packet->buffer) +
1317 silc_buffer_truelen(&packet->buffer)))) {
1318 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1319 silc_packet_free(packet);
1320 memset(tmp, 0, sizeof(tmp));
1321 silc_buffer_reset(&stream->inbuf);
1326 /* Parse packet header */
1327 packet->flags = (SilcPacketFlags)header[2];
1328 packet->type = (SilcPacketType)header[3];
1330 if (stream->engine->local_is_router) {
1331 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1332 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1334 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1335 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1336 stream->is_router == TRUE))
1339 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1340 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1342 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1346 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1347 stream->receive_psn, paddedlen + mac_len),
1348 stream->inbuf.data, paddedlen + mac_len);
1350 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1351 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1352 silc_buffer_put(&packet->buffer, header, block_len);
1353 silc_buffer_pull(&packet->buffer, block_len);
1354 silc_buffer_put(&packet->buffer, stream->inbuf.data + block_len,
1355 paddedlen - block_len);
1356 if (stream->receive_key) {
1357 silc_cipher_set_iv(stream->receive_key, iv);
1358 ret = silc_packet_decrypt(stream->receive_key, stream->receive_hmac,
1359 stream->receive_psn, &packet->buffer, normal);
1361 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1362 silc_packet_free(packet);
1363 memset(tmp, 0, sizeof(tmp));
1367 stream->receive_psn++;
1369 silc_buffer_push(&packet->buffer, block_len);
1371 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1372 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1374 /* Dispatch the packet to application */
1375 packet->stream = stream;
1376 silc_packet_dispatch(packet);
1379 silc_buffer_reset(&stream->inbuf);