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
24 #include "silcincludes.h"
27 struct SilcPacketEngineStruct {
28 SilcSchedule schedule; /* Application's scheduler */
29 SilcRng rng; /* RNG for engine */
30 SilcPacketCallbacks *callbacks; /* Packet callbacks */
31 void *callback_context; /* Context for callbacks */
32 SilcDList streams; /* All streams in engine */
33 SilcList packet_pool; /* Free list for received packets */
34 SilcMutex lock; /* Engine lock */
39 struct SilcPacketStreamStruct {
40 SilcPacketEngine engine; /* Packet engine */
41 SilcStream stream; /* Underlaying stream */
42 SilcHashTable streamers; /* Valid if streamers exist */
43 void *app_context; /* Applicationn context */
44 SilcPacketCallbacks *callbacks; /* Callbacks or NULL */
45 void *callback_context;
46 SilcBufferStruct inbuf; /* In buffer */
47 SilcBufferStruct outbuf; /* Out buffer */
48 SilcUInt32 send_psn; /* Sending sequence */
49 SilcCipher send_key; /* Sending key */
50 SilcHmac send_hmac; /* Sending HMAC */
51 SilcUInt32 receive_psn; /* Receiving sequence */
52 SilcCipher receive_key; /* Receiving key */
53 SilcHmac receive_hmac; /* Receiving HMAC */
54 unsigned char *src_id; /* Source ID */
55 unsigned char *dst_id; /* Destination ID */
56 unsigned int src_id_len : 6;
57 unsigned int src_id_type : 2;
58 unsigned int dst_id_len : 6;
59 unsigned int dst_id_type : 2;
60 SilcUInt8 refcnt; /* Reference counter */
63 /* Initial size of stream buffers */
64 #define SILC_PACKET_DEFAULT_SIZE 1024
66 /* Header length without source and destination ID's. */
67 #define SILC_PACKET_HEADER_LEN 10
69 /* Minimum length of SILC Packet Header. This much is decrypted always
70 when packet is received to be able to get all the relevant data out
72 #define SILC_PACKET_MIN_HEADER_LEN 16
74 /* Maximum padding length */
75 #define SILC_PACKET_MAX_PADLEN 128
77 /* Default padding length */
78 #define SILC_PACKET_DEFAULT_PADLEN 16
80 /* Minimum packet length */
81 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
86 /* Returns true length of the packet. */
87 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
89 SILC_GET16_MSB((__ret_truelen), (__packetdata)); \
90 (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4]; \
93 /* Calculates the data length with given header length. This macro
94 can be used to check whether the data_len with header_len exceeds
95 SILC_PACKET_MAX_LEN. If it does, this returns the new data_len
96 so that the SILC_PACKET_MAX_LEN is not exceeded. If the data_len
97 plus header_len fits SILC_PACKET_MAX_LEN the returned data length
98 is the data_len given as argument. */
99 #define SILC_PACKET_DATALEN(data_len, header_len) \
100 ((data_len + header_len) > SILC_PACKET_MAX_LEN ? \
101 data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
103 /* Calculates the length of the padding in the packet. */
104 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen) \
106 __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) % \
107 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
109 __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
112 /* Returns the length of the padding up to the maximum length, which
114 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen) \
116 __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) % \
117 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
120 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
123 /* Receive packet callback */
124 #define SILC_PACKET_CALLBACK_PACKET(s, p) \
126 if ((s)->callbacks && (s)->callbacks->packet_receive) \
127 (s)->callbacks->packet_receive((s)->engine, s, p, \
128 (s)->callback_context, \
131 (s)->engine->callbacks->packet_receive((s)->engine, s, p, \
132 (s)->callback_context, \
137 #define SILC_PACKET_CALLBACK_EOS(s) \
139 if ((s)->callbacks && (s)->callbacks->eos) \
140 (s)->callbacks->eos((s)->engine, stream, (s)->callback_context, \
143 (s)->engine->callbacks->eos((s)->engine, s, \
144 (s)->callback_context, \
149 #define SILC_PACKET_CALLBACK_ERROR(s, err) \
151 if ((s)->callbacks && (s)->callbacks->error) \
152 (s)->callbacks->error((s)->engine, s, err, (s)->callback_context, \
155 (s)->engine->callbacks->error((s)->engine, s, err, \
156 (s)->callback_context, \
160 static SilcPacket silc_packet_alloc(SilcPacketEngine engine);
161 static void silc_packet_read_process(SilcPacketStream stream);
164 /* Allocate new packet engine */
167 silc_packet_engine_start(SilcSchedule schedule, SilcRng rng, bool router,
168 SilcPacketCallbacks *callbacks,
169 void *callback_context)
171 SilcPacketEngine engine;
176 SILC_LOG_DEBUG(("Starting new packet engine"));
178 if (!schedule || !callbacks)
180 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
183 engine = silc_calloc(1, sizeof(*engine));
188 engine->local_is_router = router;
189 engine->callbacks = callbacks;
190 engine->callback_context = callback_context;
191 engine->streams = silc_dlist_init();
192 silc_mutex_alloc(&engine->lock);
194 /* Allocate packet free list */
195 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
196 for (i = 0; i < 5; i++) {
197 packet = silc_calloc(1, sizeof(*packet));
201 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
204 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
206 silc_list_add(engine->packet_pool, packet);
208 silc_list_start(engine->packet_pool);
213 /* Stop packet engine */
215 void silc_packet_engine_stop(SilcPacketEngine engine)
218 SILC_LOG_DEBUG(("Stopping packet engine"));
228 /* Create new packet stream */
230 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
236 SILC_LOG_DEBUG(("Creating new packet stream"));
238 if (!engine || !stream)
241 ps = silc_calloc(1, sizeof(*ps));
249 /* Allocate buffers */
250 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
253 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
254 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
257 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
259 /* Set IO notifier callback */
260 silc_stream_set_notifier(ps->stream, silc_packet_stream_io, ps);
263 silc_mutex_lock(engine->lock);
264 silc_dlist_add(engine->streams, ps);
265 silc_mutex_unlock(engine->lock);
270 /* Destroy packet stream */
272 void silc_packet_stream_destroy(SilcPacketStream stream)
276 if (stream->refcnt > 1)
279 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
281 /* Delete from engine */
282 silc_mutex_lock(stream->engine->lock);
283 silc_dlist_del(stream->engine->streams, stream);
284 silc_mutex_unlock(stream->engine->lock);
286 /* Clear and free buffers */
287 silc_buffer_clear(&stream->inbuf);
288 silc_buffer_clear(&stream->outbuf);
289 silc_free(silc_buffer_steal(&stream->inbuf, NULL));
290 silc_free(silc_buffer_steal(&stream->outbuf, NULL));
298 /* Set new packet callbacks for stream */
300 void silc_packet_stream_callbacks(SilcPacketStream stream,
301 SilcPacketCallbacks *callbacks,
302 void *callback_context)
304 stream->callbacks = callbacks;
305 stream->callback_context = callback_context;
308 /* Reference packet stream */
310 void silc_packet_stream_ref(SilcPacketStream stream)
315 /* Unreference packet stream */
317 void silc_packet_stream_unref(SilcPacketStream stream)
320 if (stream->refcnt == 0)
321 silc_packet_stream_destroy(stream);
324 /* Set application context for packet stream */
326 void silc_packet_set_context(SilcPacketStream stream, void *app_context)
328 stream->app_context = app_context;
331 /* Return application context from packet stream */
333 void *silc_packet_get_context(SilcPacketStream stream)
335 return stream->app_context;
338 /* Set ciphers for packet stream */
340 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
343 SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
344 stream->send_key = send;
345 stream->receive_key = receive;
348 /* Return current ciphers from packet stream */
350 bool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
353 if (!stream->send_key && !stream->receive_key)
357 *send = stream->send_key;
359 *receive = stream->receive_key;
364 /* Set HMACs for packet stream */
366 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
369 SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
370 stream->send_hmac = send;
371 stream->receive_hmac = receive;
374 /* Return current HMACs from packet stream */
376 bool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
379 if (!stream->send_hmac && !stream->receive_hmac)
383 *send = stream->send_hmac;
385 *receive = stream->receive_hmac;
390 /* Set SILC IDs to packet stream */
392 bool silc_packet_set_ids(SilcPacketStream stream,
393 SilcIdType src_id_type, const void *src_id,
394 SilcIdType dst_id_type, const void *dst_id)
398 if (!src_id && !dst_id)
401 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
404 silc_free(stream->src_id);
405 stream->src_id = silc_id_id2str(src_id, src_id_type, &len);
408 stream->src_id_type = src_id_type;
409 stream->src_id_len = len;
413 silc_free(stream->dst_id);
414 stream->dst_id = silc_id_id2str(dst_id, dst_id_type, &len);
417 stream->dst_id_type = dst_id_type;
418 stream->dst_id_len = len;
424 /* Prepare outgoing data buffer for packet sending. Returns the
425 pointer to that buffer into the `packet'. */
427 static bool silc_packet_send_prepare(SilcPacketStream stream,
430 const SilcBuffer packet)
432 unsigned char *oldptr;
433 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
437 /* If head is empty, the buffer is free for our use (no pending data) */
438 if (!silc_buffer_headlen(&stream->outbuf))
439 silc_buffer_reset(&stream->outbuf);
441 /* Allocate more space if needed */
442 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
443 if (!silc_buffer_realloc(&stream->outbuf,
444 silc_buffer_truelen(&stream->outbuf) + totlen))
448 /* Pull data area for the new packet, and return pointer to the start of
449 the data area and save the pointer in to the `packet'. MAC is pulled
450 later after it's computed. */
451 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen - mac_len);
452 silc_buffer_set(packet, oldptr, totlen);
458 /* Internal routine to send packet */
460 static bool silc_packet_send_raw(SilcPacketStream stream,
462 SilcPacketFlags flags,
463 SilcIdType src_id_type,
464 unsigned char *src_id,
465 SilcUInt32 src_id_len,
466 SilcIdType dst_id_type,
467 unsigned char *dst_id,
468 SilcUInt32 dst_id_len,
469 const unsigned char *data,
474 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
475 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
476 int i, enclen, truelen, padlen;
477 const SilcBufferStruct packet;
479 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
480 "data len %d", silc_get_packet_name(type), stream->send_psn,
481 flags, src_id_type, dst_id_type, data_len));
483 /* Get the true length of the packet. This is saved as payload length
484 into the packet header. This does not include the length of the
486 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
487 src_id_len + dst_id_len));
488 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
489 src_id_len + dst_id_len);
491 /* We automatically figure out the packet structure from the packet
492 type and flags, and calculate correct length. Private messages with
493 private keys and channel messages are special packets as their
494 payload is encrypted already. */
495 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
496 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
497 type == SILC_PACKET_CHANNEL_MESSAGE) {
499 /* Padding is calculated from header + IDs */
500 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
502 dst_id_len), block_len, padlen);
504 /* Length to encrypt, header + IDs + padding. */
505 enclen = SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len + padlen;
508 /* Padding is calculated from true length of the packet */
509 if (flags & SILC_PACKET_FLAG_LONG_PAD)
510 SILC_PACKET_PADLEN_MAX(truelen, block_len, padlen);
512 SILC_PACKET_PADLEN(truelen, block_len, padlen);
515 /* Remove implementation specific flags */
516 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
518 /* Get packet pointer from the outgoing buffer */
519 if (!silc_packet_send_prepare(stream, truelen + padlen, hmac, &packet))
522 /* Get random padding */
523 if (stream->engine->rng)
524 for (i = 0; i < padlen; i++) tmppad[i] =
525 silc_rng_get_byte_fast(stream->engine->rng);
527 for (i = 0; i < padlen; i++) tmppad[i] =
528 silc_rng_global_get_byte_fast();
530 /* Create the packet. This creates the SILC header, adds padding, and
531 the actual packet data. */
532 i = silc_buffer_format(&packet,
533 SILC_STR_UI_SHORT(truelen),
534 SILC_STR_UI_CHAR(flags),
535 SILC_STR_UI_CHAR(type),
536 SILC_STR_UI_CHAR(padlen),
538 SILC_STR_UI_CHAR(src_id_len),
539 SILC_STR_UI_CHAR(dst_id_len),
540 SILC_STR_UI_CHAR(src_id_type),
541 SILC_STR_UI_XNSTRING(src_id, src_id_len),
542 SILC_STR_UI_CHAR(dst_id_type),
543 SILC_STR_UI_XNSTRING(dst_id, dst_id_len),
544 SILC_STR_UI_XNSTRING(tmppad, padlen),
545 SILC_STR_UI_XNSTRING(data, data_len),
550 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
551 packet.data, silc_buffer_len(&packet));
553 /* Encrypt the packet */
555 if (!silc_cipher_encrypt(cipher, packet.data, packet.data, enclen, NULL)) {
556 SILC_LOG_ERROR(("Packet encryption failed"));
562 unsigned char mac[32], psn[4];
565 /* MAC is computed from the entire encrypted packet data, and put
566 to the end of the packet. */
567 silc_hmac_init(hmac);
568 SILC_PUT32_MSB(stream->send_psn, psn);
569 silc_hmac_update(hmac, psn, 4);
570 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
571 silc_hmac_final(hmac, packet.tail, &mac_len);
572 silc_buffer_pull_tail(&packet, mac_len);
576 /* Write the packet to the stream */
577 while (silc_buffer_len(&packet) > 0) {
578 i = silc_stream_write(stream->stream, packet.data,
579 silc_buffer_len(&packet));
582 SILC_PACKET_CALLBACK_EOS(stream);
583 silc_buffer_reset(&stream->outbuf);
589 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_WRITE);
590 silc_buffer_reset(&stream->outbuf);
595 /* Cannot write now, write later. */
596 silc_buffer_pull(&packet, silc_buffer_len(&packet));
601 silc_buffer_pull(&packet, i);
609 bool silc_packet_send(SilcPacketStream stream,
610 SilcPacketType type, SilcPacketFlags flags,
611 const unsigned char *data, SilcUInt32 data_len)
613 return silc_packet_send_raw(stream, type, flags,
625 /* Sends a packet, extended routine */
627 bool silc_packet_send_ext(SilcPacketStream stream,
628 SilcPacketType type, SilcPacketFlags flags,
629 SilcIdType src_id_type, void *src_id,
630 SilcIdType dst_id_type, void *dst_id,
631 const unsigned char *data, SilcUInt32 data_len,
632 SilcCipher cipher, SilcHmac hmac)
635 unsigned char *src_id_data = NULL, *dst_id_data = NULL;
636 SilcUInt32 src_id_len, dst_id_len;
638 /* XXX non-allocating id2str needed! */
641 src_id_data = silc_id_id2str(src_id, src_id_type, &src_id_len);
643 dst_id_data = silc_id_id2str(dst_id, dst_id_type, &dst_id_len);
645 ret = silc_packet_send_raw(stream, type, flags,
656 silc_free(src_id_data);
657 silc_free(dst_id_data);
662 /* Our stream IO notifier callback. */
664 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
667 SilcPacketStream ps = context;
672 case SILC_STREAM_CAN_WRITE:
673 if (!silc_buffer_headlen(&ps->outbuf))
676 SILC_LOG_DEBUG(("Writing pending data to stream"));
678 /* Write pending data to stream */
679 silc_buffer_push(&ps->outbuf, silc_buffer_headlen(&ps->outbuf));
680 while (silc_buffer_len(&ps->outbuf) > 0) {
681 ret = silc_stream_write(ps->stream, ps->outbuf.data,
682 silc_buffer_len(&ps->outbuf));
685 SILC_PACKET_CALLBACK_EOS(ps);
686 silc_buffer_reset(&ps->outbuf);
692 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
693 silc_buffer_reset(&ps->outbuf);
698 /* Cannot write now, write later. */
699 silc_buffer_pull(&ps->outbuf, silc_buffer_len(&ps->outbuf));
704 silc_buffer_pull(&ps->outbuf, ret);
709 case SILC_STREAM_CAN_READ:
710 SILC_LOG_DEBUG(("Reading data from stream"));
712 /* Make sure we have fair amount of free space in inbuf */
713 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
714 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
715 SILC_PACKET_DEFAULT_SIZE * 2))
718 /* Read data from stream */
719 ret = silc_stream_read(ps->stream, &ps->inbuf.tail,
720 silc_buffer_taillen(&ps->inbuf));
724 SILC_PACKET_CALLBACK_EOS(ps);
725 silc_buffer_reset(&ps->inbuf);
731 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
732 silc_buffer_reset(&ps->inbuf);
737 /* Cannot read now, do it later. */
738 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
743 silc_buffer_pull_tail(&ps->inbuf, ret);
745 /* Now process the data */
746 silc_packet_read_process(ps);
755 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
757 static bool silc_packet_check_mac(SilcHmac hmac,
758 const unsigned char *data,
760 const unsigned char *packet_mac,
765 unsigned char mac[32], psn[4];
768 SILC_LOG_DEBUG(("Verifying MAC"));
770 /* Compute HMAC of packet */
771 silc_hmac_init(hmac);
772 SILC_PUT32_MSB(sequence, psn);
773 silc_hmac_update(hmac, psn, 4);
774 silc_hmac_update(hmac, data, data_len);
775 silc_hmac_final(hmac, mac, &mac_len);
777 /* Compare the MAC's */
778 if (memcmp(packet_mac, mac, mac_len)) {
779 SILC_LOG_DEBUG(("MAC failed"));
783 SILC_LOG_DEBUG(("MAC is Ok"));
789 /* Decrypts SILC packet. Handles both normal and special packet decryption.
790 Return 0 when packet is normal and 1 when it it special, -1 on error. */
792 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
793 SilcUInt32 sequence, SilcBuffer buffer,
796 if (normal == TRUE) {
798 /* Decrypt rest of the packet */
799 SILC_LOG_DEBUG(("Decrypting the packet"));
800 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
801 silc_buffer_len(buffer), NULL))
807 /* Decrypt rest of the header plus padding */
810 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
812 SILC_LOG_DEBUG(("Decrypting the header"));
814 /* Padding length + src id len + dst id len + header length - 16
815 bytes already decrypted, gives the rest of the encrypted packet */
816 silc_buffer_push(buffer, block_len);
817 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
818 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
820 silc_buffer_pull(buffer, block_len);
822 if (len > silc_buffer_len(buffer)) {
823 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
827 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
836 /* Parses the packet. This is called when a whole packet is ready to be
837 parsed. The buffer sent must be already decrypted before calling this
840 static bool silc_packet_parse(SilcPacketStream stream, SilcPacket packet)
842 SilcBuffer buffer = &packet->buffer;
843 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
844 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
847 SILC_LOG_DEBUG(("Parsing incoming packet"));
849 /* Parse the buffer. This parses the SILC header of the packet. */
850 len = silc_buffer_unformat(buffer,
852 SILC_STR_UI_CHAR(&src_id_len),
853 SILC_STR_UI_CHAR(&dst_id_len),
854 SILC_STR_UI_CHAR(&src_id_type),
857 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
861 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
862 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
863 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
864 packet->src_id_len, packet->dst_id_len));
868 ret = silc_buffer_unformat(buffer,
869 SILC_STR_OFFSET(len),
870 SILC_STR_UI_XNSTRING(&packet->src_id,
872 SILC_STR_UI_CHAR(&dst_id_type),
873 SILC_STR_UI_XNSTRING(&packet->dst_id,
875 SILC_STR_OFFSET(padlen),
878 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
882 if (src_id_type > SILC_ID_CHANNEL ||
883 dst_id_type > SILC_ID_CHANNEL) {
884 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
885 src_id_type, dst_id_type));
889 packet->src_id_len = src_id_len;
890 packet->dst_id_len = dst_id_len;
891 packet->src_id_type = src_id_type;
892 packet->dst_id_type = dst_id_type;
894 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_len(buffer)),
895 buffer->data, silc_buffer_len(buffer));
897 /* Pull SILC header and padding from packet to get the data payload */
898 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
899 packet->src_id_len + packet->dst_id_len + padlen);
901 SILC_LOG_DEBUG(("Incoming packet type: %d", packet->type));
906 /* Process incoming data and parse packets. */
908 static void silc_packet_read_process(SilcPacketStream stream)
911 SilcUInt16 packetlen;
912 SilcUInt32 paddedlen, mac_len, block_len;
913 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
914 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
918 /* Parse the packets from the data */
919 while (silc_buffer_len(&stream->inbuf) > 0) {
921 if (silc_buffer_len(&stream->inbuf) < SILC_PACKET_MIN_HEADER_LEN) {
922 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
926 if (stream->receive_hmac)
927 mac_len = silc_hmac_len(stream->receive_hmac);
931 /* Decrypt first block of the packet to get the length field out */
932 if (stream->receive_key) {
933 block_len = silc_cipher_get_block_len(stream->receive_key);
934 memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
935 silc_cipher_decrypt(stream->receive_key, stream->inbuf.data,
939 block_len = SILC_PACKET_MIN_HEADER_LEN;
940 header = stream->inbuf.data;
943 /* Get packet length and full packet length with padding */
944 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
947 if (packetlen < SILC_PACKET_MIN_LEN) {
948 SILC_LOG_ERROR(("Received too short packet"));
949 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
950 memset(tmp, 0, sizeof(tmp));
951 silc_buffer_reset(&stream->inbuf);
955 if (silc_buffer_len(&stream->inbuf) < paddedlen + mac_len) {
956 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
958 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
959 memset(tmp, 0, sizeof(tmp));
960 /* silc_buffer_reset(&stream->inbuf); */
964 /* Check MAC of the packet */
965 if (!silc_packet_check_mac(stream->receive_hmac, stream->inbuf.data,
966 paddedlen, stream->inbuf.data + paddedlen,
967 stream->receive_psn)) {
968 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
969 memset(tmp, 0, sizeof(tmp));
970 silc_buffer_reset(&stream->inbuf);
975 packet = silc_packet_alloc(stream->engine);
977 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
978 memset(tmp, 0, sizeof(tmp));
979 silc_buffer_reset(&stream->inbuf);
983 /* Allocate more space to packet buffer, if needed */
984 if (silc_buffer_len(&packet->buffer) < paddedlen) {
985 if (!silc_buffer_realloc(&packet->buffer,
986 silc_buffer_truelen(&packet->buffer) +
988 silc_buffer_truelen(&packet->buffer)))) {
989 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
990 memset(tmp, 0, sizeof(tmp));
991 silc_buffer_reset(&stream->inbuf);
996 /* Parse packet header */
997 packet->flags = (SilcPacketFlags)header[2];
998 packet->type = (SilcPacketType)header[3];
1000 if (stream->engine->local_is_router) {
1001 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1002 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1004 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1005 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1006 stream->engine->local_is_router == TRUE))
1009 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1010 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1012 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1016 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1017 stream->receive_psn, paddedlen + mac_len),
1018 stream->inbuf.data, paddedlen + mac_len);
1020 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1021 silc_buffer_put(&packet->buffer, header, block_len);
1022 silc_buffer_pull(&packet->buffer, block_len);
1023 silc_buffer_put(&packet->buffer, stream->inbuf.data + block_len,
1024 paddedlen - block_len);
1025 if (stream->receive_key) {
1026 silc_cipher_set_iv(stream->receive_key, iv);
1027 ret = silc_packet_decrypt(stream->receive_key, stream->receive_hmac,
1028 stream->receive_psn, &packet->buffer, normal);
1030 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1031 memset(tmp, 0, sizeof(tmp));
1035 stream->receive_psn++;
1037 silc_buffer_push(&packet->buffer, block_len);
1039 /* Parse the packet */
1040 if (!silc_packet_parse(stream, packet)) {
1041 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1042 memset(tmp, 0, sizeof(tmp));
1046 /* Send the packet to application */
1047 SILC_PACKET_CALLBACK_PACKET(stream, packet);
1049 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1050 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1053 SILC_LOG_DEBUG(("Resetting inbound buffer"));
1054 silc_buffer_reset(&stream->inbuf);
1057 /* Allocate packet */
1059 SilcPacket silc_packet_alloc(SilcPacketEngine engine)
1063 SILC_LOG_DEBUG(("Packet pool count %d",
1064 silc_list_count(engine->packet_pool)));
1066 silc_mutex_lock(engine->lock);
1068 /* Get packet from freelist or allocate new one. */
1069 packet = silc_list_get(engine->packet_pool);
1071 silc_mutex_unlock(engine->lock);
1072 packet = silc_calloc(1, sizeof(*packet));
1075 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
1079 SILC_LOG_DEBUG(("Get packet %p", packet));
1081 /* Delete from freelist */
1082 silc_list_del(engine->packet_pool, packet);
1084 silc_mutex_unlock(engine->lock);
1091 void silc_packet_free(SilcPacketEngine engine, SilcPacket packet)
1093 SILC_LOG_DEBUG(("Freeing packet %p", packet));
1095 silc_buffer_reset(&packet->buffer);
1097 /* Put the packet back to freelist */
1098 silc_mutex_lock(engine->lock);
1099 silc_list_add(engine->packet_pool, packet);
1100 silc_mutex_unlock(engine->lock);
1103 /* Creates streamer */
1105 SilcStream silc_packet_streamer_create(SilcPacketStream stream,
1106 SilcPacketType packet_type,
1107 SilcPacketFlags packet_flags)
1113 /* Destroyes streamer */
1115 void silc_packet_streamer_destroy(SilcStream stream)