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 SilcHashTable udp_remote; /* UDP remote streams, or NULL */
37 SilcBool local_is_router;
40 /* Packet processor context */
41 typedef struct SilcPacketProcessStruct {
42 SilcInt32 priority; /* Priority */
43 SilcPacketType *types; /* Packets to process */
44 SilcPacketCallbacks *callbacks; /* Callbacks or NULL */
45 void *callback_context;
48 /* UDP remote stream tuple */
50 char *remote_ip; /* Remote IP address */
51 SilcUInt16 remote_port; /* Remote port */
52 } *SilcPacketRemoteUDP;
55 struct SilcPacketStreamStruct {
56 struct SilcPacketStreamStruct *next;
57 SilcPacketEngine engine; /* Packet engine */
58 SilcStream stream; /* Underlaying stream */
59 SilcMutex lock; /* Stream lock */
60 SilcDList process; /* Packet processors, or NULL */
61 SilcPacketRemoteUDP remote_udp; /* UDP remote stream tuple, or NULL */
62 void *stream_context; /* Stream context */
63 SilcBufferStruct inbuf; /* In buffer */
64 SilcBufferStruct outbuf; /* Out buffer */
65 SilcCipher send_key[2]; /* Sending key */
66 SilcHmac send_hmac[2]; /* Sending HMAC */
67 SilcCipher receive_key[2]; /* Receiving key */
68 SilcHmac receive_hmac[2]; /* Receiving HMAC */
69 unsigned char *src_id; /* Source ID */
70 unsigned char *dst_id; /* Destination ID */
71 SilcUInt32 send_psn; /* Sending sequence */
72 SilcUInt32 receive_psn; /* Receiving sequence */
73 SilcAtomic8 refcnt; /* Reference counter */
74 SilcUInt8 sid; /* Security ID, set if IV included */
75 unsigned int src_id_len : 6;
76 unsigned int src_id_type : 2;
77 unsigned int dst_id_len : 6;
78 unsigned int dst_id_type : 2;
79 unsigned int is_router : 1; /* Set if router stream */
80 unsigned int destroyed : 1; /* Set if destroyed */
81 unsigned int iv_included : 1; /* Set if IV included */
82 unsigned int udp : 1; /* UDP remote stream */
85 /* Initial size of stream buffers */
86 #define SILC_PACKET_DEFAULT_SIZE 1024
88 /* Header length without source and destination ID's. */
89 #define SILC_PACKET_HEADER_LEN 10
91 /* Minimum length of SILC Packet Header. */
92 #define SILC_PACKET_MIN_HEADER_LEN 16
93 #define SILC_PACKET_MIN_HEADER_LEN_IV 32 + 1
95 /* Maximum padding length */
96 #define SILC_PACKET_MAX_PADLEN 128
98 /* Default padding length */
99 #define SILC_PACKET_DEFAULT_PADLEN 16
101 /* Minimum packet length */
102 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
104 /* Returns true length of the packet. */
105 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
107 SILC_GET16_MSB((__ret_truelen), (__packetdata)); \
108 (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4]; \
111 /* Calculates the data length with given header length. This macro
112 can be used to check whether the data_len with header_len exceeds
113 SILC_PACKET_MAX_LEN. If it does, this returns the new data_len
114 so that the SILC_PACKET_MAX_LEN is not exceeded. If the data_len
115 plus header_len fits SILC_PACKET_MAX_LEN the returned data length
116 is the data_len given as argument. */
117 #define SILC_PACKET_DATALEN(data_len, header_len) \
118 ((data_len + header_len) > SILC_PACKET_MAX_LEN ? \
119 data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
121 /* Calculates the length of the padding in the packet. */
122 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen) \
124 __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) % \
125 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
127 __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
130 /* Returns the length of the padding up to the maximum length, which
132 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen) \
134 __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) % \
135 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
139 #define SILC_PACKET_CALLBACK_EOS(s) \
141 (s)->engine->callbacks->eos((s)->engine, s, \
142 (s)->engine->callback_context, \
143 (s)->stream_context); \
147 #define SILC_PACKET_CALLBACK_ERROR(s, err) \
149 (s)->engine->callbacks->error((s)->engine, s, err, \
150 (s)->engine->callback_context, \
151 (s)->stream_context); \
154 static void silc_packet_dispatch(SilcPacket packet);
155 static void silc_packet_read_process(SilcPacketStream stream);
156 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
158 SilcPacketFlags flags,
159 SilcIdType src_id_type,
160 unsigned char *src_id,
161 SilcUInt32 src_id_len,
162 SilcIdType dst_id_type,
163 unsigned char *dst_id,
164 SilcUInt32 dst_id_len,
165 const unsigned char *data,
170 /************************ Static utility functions **************************/
172 /* Injects packet to new stream created with silc_packet_stream_add_remote. */
174 SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
176 SilcPacket packet = context;
177 SilcPacketStream stream = packet->stream;
179 SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
181 silc_mutex_lock(stream->lock);
182 silc_packet_dispatch(packet);
183 silc_mutex_unlock(stream->lock);
186 /* Write data to the stream. Must be called with ps->lock locked. Unlocks
187 the lock inside this function, unless no_unlock is TRUE. Unlocks always
188 in case it returns FALSE. */
190 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps,
198 stream = ((SilcPacketStream)ps->stream)->stream;
202 if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
204 /* Connectionless UDP stream */
205 while (silc_buffer_len(&ps->outbuf) > 0) {
206 i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
207 ps->remote_udp->remote_port,
208 ps->outbuf.data, silc_buffer_len(&ps->outbuf));
211 silc_buffer_reset(&ps->outbuf);
212 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
217 /* Cannot write now, write later. */
219 silc_mutex_unlock(ps->lock);
224 silc_buffer_pull(&ps->outbuf, i);
227 silc_buffer_reset(&ps->outbuf);
229 silc_mutex_unlock(ps->lock);
235 /* Write the data to the stream */
236 while (silc_buffer_len(&ps->outbuf) > 0) {
237 i = silc_stream_write(stream, ps->outbuf.data,
238 silc_buffer_len(&ps->outbuf));
241 silc_buffer_reset(&ps->outbuf);
242 silc_mutex_unlock(ps->lock);
243 SILC_PACKET_CALLBACK_EOS(ps);
249 silc_buffer_reset(&ps->outbuf);
250 silc_mutex_unlock(ps->lock);
251 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
256 /* Cannot write now, write later. */
258 silc_mutex_unlock(ps->lock);
263 silc_buffer_pull(&ps->outbuf, i);
266 silc_buffer_reset(&ps->outbuf);
268 silc_mutex_unlock(ps->lock);
273 /* Reads data from stream. Must be called with the ps->lock locked. If this
274 returns FALSE the lock has been unlocked. If this returns packet stream
275 to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
276 It is returned if the stream is UDP and remote UDP stream exists for
277 the sender of the packet. */
279 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
280 SilcPacketStream *ret_ps)
288 /* Make sure we have fair amount of free space in inbuf */
289 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
290 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
291 SILC_PACKET_DEFAULT_SIZE * 2)) {
292 silc_mutex_unlock(ps->lock);
293 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
297 if (silc_socket_stream_is_udp(stream, &connected)) {
299 /* Connectionless UDP stream, read one UDP packet */
300 char remote_ip[64], tuple[64];
302 SilcPacketStream remote;
304 ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
305 &remote_port, ps->inbuf.tail,
306 silc_buffer_taillen(&ps->inbuf));
309 silc_buffer_reset(&ps->inbuf);
310 silc_mutex_unlock(ps->lock);
311 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
316 /* Cannot read now, do it later. */
317 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
318 silc_mutex_unlock(ps->lock);
322 /* See if remote packet stream exist for this sender */
323 snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
324 silc_mutex_lock(ps->engine->lock);
325 if (silc_hash_table_find(ps->engine->udp_remote, tuple, NULL,
327 /* Found packet stream for this sender, copy the packet */
328 silc_mutex_unlock(ps->engine->lock);
330 SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p",
331 remote_ip, remote_port, remote));
333 silc_mutex_lock(remote->lock);
334 if (ret > silc_buffer_taillen(&remote->inbuf))
335 if (!silc_buffer_realloc(&remote->inbuf, ret)) {
336 silc_mutex_unlock(remote->lock);
337 silc_mutex_unlock(ps->lock);
338 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
342 silc_buffer_put_tail(&remote->inbuf, ps->inbuf.tail, ret);
343 silc_buffer_pull_tail(&remote->inbuf, ret);
346 silc_buffer_reset(&ps->inbuf);
347 silc_mutex_unlock(ps->lock);
350 silc_mutex_unlock(ps->engine->lock);
353 if (!ps->remote_udp) {
354 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
355 if (!ps->remote_udp) {
356 silc_mutex_unlock(ps->lock);
357 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
362 /* Save sender IP and port */
363 silc_free(ps->remote_udp->remote_ip);
364 ps->remote_udp->remote_ip = strdup(remote_ip);
365 ps->remote_udp->remote_port = remote_port;
367 silc_buffer_pull_tail(&ps->inbuf, ret);
372 /* Read data from the stream */
373 ret = silc_stream_read(ps->stream, ps->inbuf.tail,
374 silc_buffer_taillen(&ps->inbuf));
378 silc_buffer_reset(&ps->inbuf);
379 silc_mutex_unlock(ps->lock);
380 SILC_PACKET_CALLBACK_EOS(ps);
386 silc_buffer_reset(&ps->inbuf);
387 silc_mutex_unlock(ps->lock);
388 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
393 /* Cannot read now, do it later. */
394 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
395 silc_mutex_unlock(ps->lock);
399 silc_buffer_pull_tail(&ps->inbuf, ret);
403 /* Our stream IO notifier callback. */
405 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
408 SilcPacketStream remote = NULL, ps = context;
410 silc_mutex_lock(ps->lock);
413 silc_mutex_unlock(ps->lock);
419 case SILC_STREAM_CAN_WRITE:
420 SILC_LOG_DEBUG(("Writing pending data to stream"));
422 if (!silc_buffer_headlen(&ps->outbuf)) {
423 silc_mutex_unlock(ps->lock);
427 /* Write pending data to stream */
428 silc_packet_stream_write(ps, FALSE);
431 case SILC_STREAM_CAN_READ:
432 SILC_LOG_DEBUG(("Reading data from stream"));
434 /* Read data from stream */
435 if (!silc_packet_stream_read(ps, &remote))
438 /* Now process the data */
440 silc_packet_read_process(ps);
441 silc_mutex_unlock(ps->lock);
443 silc_packet_read_process(remote);
444 silc_mutex_unlock(remote->lock);
449 silc_mutex_unlock(ps->lock);
454 /* Allocate packet */
456 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
460 SILC_LOG_DEBUG(("Packet pool count %d",
461 silc_list_count(engine->packet_pool)));
463 silc_mutex_lock(engine->lock);
465 /* Get packet from freelist or allocate new one. */
466 packet = silc_list_get(engine->packet_pool);
470 silc_mutex_unlock(engine->lock);
472 packet = silc_calloc(1, sizeof(*packet));
476 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
478 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
483 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
484 silc_buffer_reset(&packet->buffer);
489 SILC_LOG_DEBUG(("Get packet %p", packet));
491 /* Delete from freelist */
492 silc_list_del(engine->packet_pool, packet);
494 silc_mutex_unlock(engine->lock);
499 /* UDP remote stream hash table destructor */
501 static void silc_packet_engine_hash_destr(void *key, void *context,
508 /******************************** Packet API ********************************/
510 /* Allocate new packet engine */
513 silc_packet_engine_start(SilcRng rng, SilcBool router,
514 SilcPacketCallbacks *callbacks,
515 void *callback_context)
517 SilcPacketEngine engine;
522 SILC_LOG_DEBUG(("Starting new packet engine"));
526 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
529 engine = silc_calloc(1, sizeof(*engine));
534 engine->local_is_router = router;
535 engine->callbacks = callbacks;
536 engine->callback_context = callback_context;
537 silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
538 silc_mutex_alloc(&engine->lock);
540 /* Allocate packet free list */
541 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
542 for (i = 0; i < 5; i++) {
543 packet = silc_calloc(1, sizeof(*packet));
545 silc_packet_engine_stop(engine);
549 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
551 silc_packet_engine_stop(engine);
554 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
555 silc_buffer_reset(&packet->buffer);
557 silc_list_add(engine->packet_pool, packet);
559 silc_list_start(engine->packet_pool);
564 /* Stop packet engine */
566 void silc_packet_engine_stop(SilcPacketEngine engine)
569 SILC_LOG_DEBUG(("Stopping packet engine"));
579 /* Create new packet stream */
581 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
582 SilcSchedule schedule,
588 SILC_LOG_DEBUG(("Creating new packet stream"));
590 if (!engine || !stream)
593 ps = silc_calloc(1, sizeof(*ps));
599 silc_atomic_init8(&ps->refcnt, 1);
600 silc_mutex_alloc(&ps->lock);
602 /* Allocate buffers */
603 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
605 silc_packet_stream_destroy(ps);
608 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
609 silc_buffer_reset(&ps->inbuf);
610 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
612 silc_packet_stream_destroy(ps);
615 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
616 silc_buffer_reset(&ps->outbuf);
618 /* Initialize packet procesors list */
619 ps->process = silc_dlist_init();
621 silc_packet_stream_destroy(ps);
625 /* Set IO notifier callback */
626 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
629 silc_mutex_lock(engine->lock);
630 silc_list_add(engine->streams, ps);
631 silc_mutex_unlock(engine->lock);
633 /* If this is UDP stream, allocate UDP remote stream hash table */
634 if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
635 engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
636 silc_hash_string_compare, NULL,
637 silc_packet_engine_hash_destr,
643 /* Add new remote packet stream for UDP packet streams */
645 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
646 const char *remote_ip,
647 SilcUInt16 remote_port,
650 SilcPacketEngine engine = stream->engine;
655 SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
656 remote_ip, remote_port, stream));
658 if (!stream || !remote_ip || !remote_port)
661 if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
662 SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
666 ps = silc_calloc(1, sizeof(*ps));
671 silc_atomic_init8(&ps->refcnt, 1);
672 silc_mutex_alloc(&ps->lock);
674 /* Set the UDP packet stream as underlaying stream */
675 silc_packet_stream_ref(stream);
676 ps->stream = (SilcStream)stream;
679 /* Allocate buffers */
680 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
682 silc_packet_stream_destroy(ps);
685 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
686 silc_buffer_reset(&ps->inbuf);
687 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
689 silc_packet_stream_destroy(ps);
692 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
693 silc_buffer_reset(&ps->outbuf);
695 /* Initialize packet procesors list */
696 ps->process = silc_dlist_init();
698 silc_packet_stream_destroy(ps);
702 /* Add to engine with this IP and port pair */
703 tuple = silc_format("%d%s", remote_port, remote_ip);
704 silc_mutex_lock(engine->lock);
705 if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
706 silc_mutex_unlock(engine->lock);
707 silc_packet_stream_destroy(ps);
710 silc_mutex_unlock(engine->lock);
712 /* Save remote IP and port pair */
713 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
714 if (!ps->remote_udp) {
715 silc_packet_stream_destroy(ps);
718 ps->remote_udp->remote_port = remote_port;
719 ps->remote_udp->remote_ip = strdup(remote_ip);
720 if (!ps->remote_udp->remote_ip) {
721 silc_packet_stream_destroy(ps);
726 /* Inject packet to the new stream */
728 silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
729 silc_packet_stream_inject_packet, packet,
736 /* Destroy packet stream */
738 void silc_packet_stream_destroy(SilcPacketStream stream)
743 if (silc_atomic_get_int8(&stream->refcnt) > 1) {
744 stream->destroyed = TRUE;
748 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
751 /* Delete from engine */
752 silc_mutex_lock(stream->engine->lock);
753 silc_list_del(stream->engine->streams, stream);
754 silc_mutex_unlock(stream->engine->lock);
756 /* Destroy the underlaying stream */
758 silc_stream_destroy(stream->stream);
760 /* Delete from UDP remote hash table */
762 snprintf(tuple, sizeof(tuple), "%d%s", stream->remote_udp->remote_port,
763 stream->remote_udp->remote_ip);
764 silc_mutex_lock(stream->engine->lock);
765 silc_hash_table_del(stream->engine->udp_remote, tuple);
766 silc_mutex_unlock(stream->engine->lock);
768 silc_free(stream->remote_udp->remote_ip);
769 silc_free(stream->remote_udp);
771 /* Unreference the underlaying packet stream */
772 silc_packet_stream_unref((SilcPacketStream)stream->stream);
775 /* Clear and free buffers */
776 silc_buffer_clear(&stream->inbuf);
777 silc_buffer_clear(&stream->outbuf);
778 silc_buffer_purge(&stream->inbuf);
779 silc_buffer_purge(&stream->outbuf);
781 if (stream->process) {
783 silc_dlist_start(stream->process);
784 while ((p = silc_dlist_get(stream->process))) {
787 silc_dlist_del(stream->process, p);
789 silc_dlist_uninit(stream->process);
794 silc_atomic_uninit8(&stream->refcnt);
795 silc_mutex_free(stream->lock);
799 /* Marks as router stream */
801 void silc_packet_stream_set_router(SilcPacketStream stream)
803 stream->is_router = TRUE;
806 /* Mark to include IV in ciphertext */
808 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
810 stream->iv_included = TRUE;
813 /* Links `callbacks' to `stream' for specified packet types */
815 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
816 SilcPacketCallbacks *callbacks,
817 void *callback_context,
818 int priority, va_list ap)
820 SilcPacketProcess p, e;
821 SilcInt32 packet_type;
824 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
828 if (!callbacks->packet_receive)
831 p = silc_calloc(1, sizeof(*p));
835 p->priority = priority;
836 p->callbacks = callbacks;
837 p->callback_context = callback_context;
839 silc_mutex_lock(stream->lock);
841 if (!stream->process) {
842 stream->process = silc_dlist_init();
843 if (!stream->process) {
844 silc_mutex_unlock(stream->lock);
849 /* According to priority set the procesor to correct position. First
850 entry has the highest priority */
851 silc_dlist_start(stream->process);
852 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
853 if (p->priority > e->priority) {
854 silc_dlist_insert(stream->process, p);
859 silc_dlist_add(stream->process, p);
861 /* Get packet types to process */
864 packet_type = va_arg(ap, SilcInt32);
866 if (packet_type == SILC_PACKET_ANY)
869 if (packet_type == -1)
872 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
874 silc_mutex_unlock(stream->lock);
878 p->types[i - 1] = (SilcPacketType)packet_type;
884 silc_mutex_unlock(stream->lock);
886 silc_packet_stream_ref(stream);
891 /* Links `callbacks' to `stream' for specified packet types */
893 SilcBool silc_packet_stream_link(SilcPacketStream stream,
894 SilcPacketCallbacks *callbacks,
895 void *callback_context,
901 va_start(ap, priority);
902 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
909 /* Unlinks `callbacks' from `stream'. */
911 void silc_packet_stream_unlink(SilcPacketStream stream,
912 SilcPacketCallbacks *callbacks,
913 void *callback_context)
917 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
920 silc_mutex_lock(stream->lock);
922 silc_dlist_start(stream->process);
923 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
924 if (p->callbacks == callbacks &&
925 p->callback_context == callback_context) {
926 silc_dlist_del(stream->process, p);
932 if (!silc_dlist_count(stream->process)) {
933 silc_dlist_uninit(stream->process);
934 stream->process = NULL;
937 silc_mutex_unlock(stream->lock);
939 silc_packet_stream_unref(stream);
942 /* Returns TRUE if stream is UDP stream */
944 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream)
946 return stream->udp || silc_socket_stream_is_udp(stream->stream, NULL);
949 /* Return packet sender IP and port for UDP packet stream */
951 SilcBool silc_packet_get_sender(SilcPacket packet,
952 const char **sender_ip,
953 SilcUInt16 *sender_port)
955 if (!packet->stream->remote_udp)
958 *sender_ip = packet->stream->remote_udp->remote_ip;
959 *sender_port = packet->stream->remote_udp->remote_port;
964 /* Reference packet stream */
966 void silc_packet_stream_ref(SilcPacketStream stream)
968 silc_atomic_add_int8(&stream->refcnt, 1);
971 /* Unreference packet stream */
973 void silc_packet_stream_unref(SilcPacketStream stream)
975 if (silc_atomic_sub_int8(&stream->refcnt, 1) == 0)
976 silc_packet_stream_destroy(stream);
981 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
983 return stream->engine;
986 /* Set application context for packet stream */
988 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
990 silc_mutex_lock(stream->lock);
991 stream->stream_context = stream_context;
992 silc_mutex_unlock(stream->lock);
995 /* Return application context from packet stream */
997 void *silc_packet_get_context(SilcPacketStream stream)
1000 silc_mutex_lock(stream->lock);
1001 context = stream->stream_context;
1002 silc_mutex_unlock(stream->lock);
1006 /* Change underlaying stream */
1008 void silc_packet_stream_set_stream(SilcPacketStream ps,
1010 SilcSchedule schedule)
1013 silc_stream_set_notifier(ps->stream, schedule, NULL, NULL);
1014 ps->stream = stream;
1015 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
1018 /* Return underlaying stream */
1020 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
1022 return stream->stream;
1027 SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
1028 SilcCipher receive_key, SilcHmac send_hmac,
1029 SilcHmac receive_hmac, SilcBool rekey)
1031 SILC_LOG_DEBUG(("Setting new keys to packet stream %p", stream));
1033 /* If doing rekey, send REKEY_DONE packet */
1035 /* This will take stream lock. */
1036 if (!silc_packet_send_raw(stream, SILC_PACKET_REKEY_DONE, 0,
1037 stream->src_id_type, stream->src_id,
1038 stream->src_id_len, stream->dst_id_type,
1039 stream->dst_id, stream->dst_id_len,
1040 NULL, 0, stream->send_key[0],
1041 stream->send_hmac[0]))
1044 /* Write the packet to the stream */
1045 if (!silc_packet_stream_write(stream, TRUE))
1048 silc_mutex_lock(stream->lock);
1051 /* In case IV Included is set, save the old keys */
1052 if (stream->iv_included) {
1053 if (stream->send_key[1] && send_key) {
1054 silc_cipher_free(stream->send_key[1]);
1055 stream->send_key[1] = stream->send_key[0];
1057 if (stream->receive_key[1] && receive_key) {
1058 silc_cipher_free(stream->receive_key[1]);
1059 stream->receive_key[1] = stream->receive_key[0];
1061 if (stream->send_hmac[1] && send_hmac) {
1062 silc_hmac_free(stream->send_hmac[1]);
1063 stream->send_hmac[1] = stream->send_hmac[0];
1065 if (stream->receive_hmac[1] && receive_hmac) {
1066 silc_hmac_free(stream->receive_hmac[1]);
1067 stream->receive_hmac[1] = stream->receive_hmac[0];
1070 if (stream->send_key[0] && send_key)
1071 silc_cipher_free(stream->send_key[0]);
1072 if (stream->send_key[1] && receive_key)
1073 silc_cipher_free(stream->receive_key[0]);
1074 if (stream->send_hmac[0] && send_hmac)
1075 silc_hmac_free(stream->send_hmac[0]);
1076 if (stream->receive_hmac[0] && receive_hmac)
1077 silc_hmac_free(stream->receive_hmac[0]);
1082 stream->send_key[0] = send_key;
1084 stream->receive_key[0] = receive_key;
1086 stream->send_hmac[0] = send_hmac;
1088 stream->receive_hmac[0] = receive_hmac;
1090 silc_mutex_unlock(stream->lock);
1094 /* Return current ciphers from packet stream */
1096 SilcBool silc_packet_get_keys(SilcPacketStream stream,
1097 SilcCipher *send_key,
1098 SilcCipher *receive_key,
1099 SilcHmac *send_hmac,
1100 SilcHmac *receive_hmac)
1102 if (!stream->send_key[0] && !stream->receive_key[0] &&
1103 !stream->send_hmac[0] && !stream->receive_hmac[0])
1106 silc_mutex_lock(stream->lock);
1109 *send_key = stream->send_key[0];
1111 *receive_key = stream->receive_key[0];
1113 *send_hmac = stream->send_hmac[0];
1115 *receive_hmac = stream->receive_hmac[0];
1117 silc_mutex_unlock(stream->lock);
1122 /* Set SILC IDs to packet stream */
1124 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1125 SilcIdType src_id_type, const void *src_id,
1126 SilcIdType dst_id_type, const void *dst_id)
1129 unsigned char tmp[32];
1131 if (!src_id && !dst_id)
1134 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1136 silc_mutex_lock(stream->lock);
1139 silc_free(stream->src_id);
1140 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1141 silc_mutex_unlock(stream->lock);
1144 stream->src_id = silc_memdup(tmp, len);
1145 if (!stream->src_id) {
1146 silc_mutex_unlock(stream->lock);
1149 stream->src_id_type = src_id_type;
1150 stream->src_id_len = len;
1154 silc_free(stream->dst_id);
1155 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1156 silc_mutex_unlock(stream->lock);
1159 stream->dst_id = silc_memdup(tmp, len);
1160 if (!stream->dst_id) {
1161 silc_mutex_unlock(stream->lock);
1164 stream->dst_id_type = dst_id_type;
1165 stream->dst_id_len = len;
1168 silc_mutex_unlock(stream->lock);
1173 /* Adds Security ID (SID) */
1175 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1177 if (!stream->iv_included)
1180 SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1188 void silc_packet_free(SilcPacket packet)
1190 SilcPacketStream stream = packet->stream;
1192 SILC_LOG_DEBUG(("Freeing packet %p", packet));
1194 /* Check for double free */
1195 SILC_ASSERT(packet->stream != NULL);
1197 packet->stream = NULL;
1198 packet->src_id = packet->dst_id = NULL;
1199 silc_buffer_reset(&packet->buffer);
1201 silc_mutex_lock(stream->engine->lock);
1203 /* Put the packet back to freelist */
1204 silc_list_add(stream->engine->packet_pool, packet);
1205 if (silc_list_count(stream->engine->packet_pool) == 1)
1206 silc_list_start(stream->engine->packet_pool);
1208 silc_mutex_unlock(stream->engine->lock);
1211 /****************************** Packet Sending ******************************/
1213 /* Prepare outgoing data buffer for packet sending. Returns the
1214 pointer to that buffer into the `packet'. */
1216 static inline SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1221 unsigned char *oldptr;
1222 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1226 /* Allocate more space if needed */
1227 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
1228 if (!silc_buffer_realloc(&stream->outbuf,
1229 silc_buffer_truelen(&stream->outbuf) + totlen))
1233 /* Pull data area for the new packet, and return pointer to the start of
1234 the data area and save the pointer in to the `packet'. MAC is pulled
1235 later after it's computed. */
1236 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1237 silc_buffer_set(packet, oldptr, totlen);
1238 silc_buffer_push_tail(packet, mac_len);
1243 /* Internal routine to assemble outgoing packet. Assembles and encryptes
1244 the packet. The silc_packet_stream_write needs to be called to send it
1245 after this returns TRUE. */
1247 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
1248 SilcPacketType type,
1249 SilcPacketFlags flags,
1250 SilcIdType src_id_type,
1251 unsigned char *src_id,
1252 SilcUInt32 src_id_len,
1253 SilcIdType dst_id_type,
1254 unsigned char *dst_id,
1255 SilcUInt32 dst_id_len,
1256 const unsigned char *data,
1257 SilcUInt32 data_len,
1261 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1262 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1263 int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
1264 SilcBufferStruct packet;
1266 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1267 "data len %d", silc_get_packet_name(type), stream->send_psn,
1268 flags, src_id_type, dst_id_type, data_len));
1270 /* Get the true length of the packet. This is saved as payload length
1271 into the packet header. This does not include the length of the
1273 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1274 src_id_len + dst_id_len));
1275 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1276 src_id_len + dst_id_len);
1278 /* If IV is included, the SID, IV and sequence number is added to packet */
1279 if (stream->iv_included && cipher) {
1280 psnlen = sizeof(psn);
1281 ivlen = block_len + 1;
1282 iv[0] = stream->sid;
1283 memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1286 /* We automatically figure out the packet structure from the packet
1287 type and flags, and calculate correct length. Private messages with
1288 private keys and channel messages are special packets as their
1289 payload is encrypted already. */
1290 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1291 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1292 type == SILC_PACKET_CHANNEL_MESSAGE) {
1294 /* Padding is calculated from header + IDs */
1295 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1296 psnlen), block_len, padlen);
1298 /* Length to encrypt, header + IDs + padding. */
1299 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1303 /* Padding is calculated from true length of the packet */
1304 if (flags & SILC_PACKET_FLAG_LONG_PAD)
1305 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1307 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1309 enclen += padlen + psnlen;
1312 /* Remove implementation specific flags */
1313 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1315 /* Get random padding */
1316 for (i = 0; i < padlen; i++) tmppad[i] =
1317 silc_rng_get_byte_fast(stream->engine->rng);
1319 silc_mutex_lock(stream->lock);
1321 /* Get packet pointer from the outgoing buffer */
1322 if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
1324 silc_mutex_unlock(stream->lock);
1328 SILC_PUT32_MSB(stream->send_psn, psn);
1330 /* Create the packet. This creates the SILC header, adds padding, and
1331 the actual packet data. */
1332 i = silc_buffer_format(&packet,
1333 SILC_STR_DATA(iv, ivlen),
1334 SILC_STR_DATA(psn, psnlen),
1335 SILC_STR_UI_SHORT(truelen),
1336 SILC_STR_UI_CHAR(flags),
1337 SILC_STR_UI_CHAR(type),
1338 SILC_STR_UI_CHAR(padlen),
1339 SILC_STR_UI_CHAR(0),
1340 SILC_STR_UI_CHAR(src_id_len),
1341 SILC_STR_UI_CHAR(dst_id_len),
1342 SILC_STR_UI_CHAR(src_id_type),
1343 SILC_STR_DATA(src_id, src_id_len),
1344 SILC_STR_UI_CHAR(dst_id_type),
1345 SILC_STR_DATA(dst_id, dst_id_len),
1346 SILC_STR_DATA(tmppad, padlen),
1347 SILC_STR_DATA(data, data_len),
1350 silc_mutex_unlock(stream->lock);
1354 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1355 silc_buffer_data(&packet), silc_buffer_len(&packet));
1357 /* Encrypt the packet */
1359 SILC_LOG_DEBUG(("Encrypting packet"));
1360 if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
1361 packet.data + ivlen, enclen, NULL)) {
1362 SILC_LOG_ERROR(("Packet encryption failed"));
1363 silc_mutex_unlock(stream->lock);
1372 /* MAC is computed from the entire encrypted packet data, and put
1373 to the end of the packet. */
1374 silc_hmac_init(hmac);
1375 silc_hmac_update(hmac, psn, sizeof(psn));
1376 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1377 silc_hmac_final(hmac, packet.tail, &mac_len);
1378 silc_buffer_pull_tail(&packet, mac_len);
1385 /* Sends a packet */
1387 SilcBool silc_packet_send(SilcPacketStream stream,
1388 SilcPacketType type, SilcPacketFlags flags,
1389 const unsigned char *data, SilcUInt32 data_len)
1393 ret = silc_packet_send_raw(stream, type, flags,
1394 stream->src_id_type,
1397 stream->dst_id_type,
1401 stream->send_key[0],
1402 stream->send_hmac[0]);
1404 /* Write the packet to the stream */
1405 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1408 /* Sends a packet, extended routine */
1410 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1411 SilcPacketType type, SilcPacketFlags flags,
1412 SilcIdType src_id_type, void *src_id,
1413 SilcIdType dst_id_type, void *dst_id,
1414 const unsigned char *data, SilcUInt32 data_len,
1415 SilcCipher cipher, SilcHmac hmac)
1417 unsigned char src_id_data[32], dst_id_data[32];
1418 SilcUInt32 src_id_len, dst_id_len;
1422 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1423 sizeof(src_id_data), &src_id_len))
1426 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1427 sizeof(dst_id_data), &dst_id_len))
1430 ret = silc_packet_send_raw(stream, type, flags,
1431 src_id ? src_id_type : stream->src_id_type,
1432 src_id ? src_id_data : stream->src_id,
1433 src_id ? src_id_len : stream->src_id_len,
1434 dst_id ? dst_id_type : stream->dst_id_type,
1435 dst_id ? dst_id_data : stream->dst_id,
1436 dst_id ? dst_id_len : stream->dst_id_len,
1438 cipher ? cipher : stream->send_key[0],
1439 hmac ? hmac : stream->send_hmac[0]);
1441 /* Write the packet to the stream */
1442 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1445 /* Sends packet after formatting the arguments to buffer */
1447 SilcBool silc_packet_send_va(SilcPacketStream stream,
1448 SilcPacketType type, SilcPacketFlags flags, ...)
1450 SilcBufferStruct buf;
1454 va_start(va, flags);
1456 memset(&buf, 0, sizeof(buf));
1457 if (silc_buffer_format_vp(&buf, va) < 0) {
1462 ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1463 silc_buffer_len(&buf));
1465 silc_buffer_purge(&buf);
1471 /* Sends packet after formatting the arguments to buffer, extended routine */
1473 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1474 SilcPacketType type, SilcPacketFlags flags,
1475 SilcIdType src_id_type, void *src_id,
1476 SilcIdType dst_id_type, void *dst_id,
1477 SilcCipher cipher, SilcHmac hmac, ...)
1479 SilcBufferStruct buf;
1485 memset(&buf, 0, sizeof(buf));
1486 if (silc_buffer_format_vp(&buf, va) < 0) {
1491 ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1492 dst_id_type, dst_id, silc_buffer_data(&buf),
1493 silc_buffer_len(&buf), cipher, hmac);
1495 silc_buffer_purge(&buf);
1501 /***************************** Packet Receiving *****************************/
1503 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1505 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1506 const unsigned char *data,
1507 SilcUInt32 data_len,
1508 const unsigned char *packet_mac,
1509 const unsigned char *packet_seq,
1510 SilcUInt32 sequence)
1514 unsigned char mac[32], psn[4];
1517 SILC_LOG_DEBUG(("Verifying MAC"));
1519 /* Compute HMAC of packet */
1520 silc_hmac_init(hmac);
1523 SILC_PUT32_MSB(sequence, psn);
1524 silc_hmac_update(hmac, psn, 4);
1526 silc_hmac_update(hmac, packet_seq, 4);
1528 silc_hmac_update(hmac, data, data_len);
1529 silc_hmac_final(hmac, mac, &mac_len);
1531 /* Compare the MAC's */
1532 if (memcmp(packet_mac, mac, mac_len)) {
1533 SILC_LOG_DEBUG(("MAC failed"));
1537 SILC_LOG_DEBUG(("MAC is Ok"));
1543 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1544 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1546 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1547 SilcUInt32 sequence, SilcBuffer buffer,
1550 if (normal == TRUE) {
1552 /* Decrypt rest of the packet */
1553 SILC_LOG_DEBUG(("Decrypting the packet"));
1554 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1555 silc_buffer_len(buffer), NULL))
1561 /* Decrypt rest of the header plus padding */
1564 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1566 SILC_LOG_DEBUG(("Decrypting the header"));
1568 /* Padding length + src id len + dst id len + header length - 16
1569 bytes already decrypted, gives the rest of the encrypted packet */
1570 silc_buffer_push(buffer, block_len);
1571 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1572 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1574 silc_buffer_pull(buffer, block_len);
1576 if (len > silc_buffer_len(buffer)) {
1577 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1581 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1590 /* Parses the packet. This is called when a whole packet is ready to be
1591 parsed. The buffer sent must be already decrypted before calling this
1594 static inline SilcBool silc_packet_parse(SilcPacket packet)
1596 SilcBuffer buffer = &packet->buffer;
1597 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1598 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1601 SILC_LOG_DEBUG(("Parsing incoming packet"));
1603 /* Parse the buffer. This parses the SILC header of the packet. */
1604 ret = silc_buffer_unformat(buffer,
1607 SILC_STR_UI_CHAR(&src_id_len),
1608 SILC_STR_UI_CHAR(&dst_id_len),
1609 SILC_STR_UI_CHAR(&src_id_type),
1612 if (!packet->stream->udp &&
1613 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1614 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1618 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1619 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1620 if (!packet->stream->udp &&
1621 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1622 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1623 packet->src_id_len, packet->dst_id_len));
1627 ret = silc_buffer_unformat(buffer,
1629 SILC_STR_DATA(&packet->src_id, src_id_len),
1630 SILC_STR_UI_CHAR(&dst_id_type),
1631 SILC_STR_DATA(&packet->dst_id, dst_id_len),
1632 SILC_STR_OFFSET(padlen),
1635 if (!packet->stream->udp &&
1636 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1637 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1641 if (src_id_type > SILC_ID_CHANNEL ||
1642 dst_id_type > SILC_ID_CHANNEL) {
1643 if (!packet->stream->udp &&
1644 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1645 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1646 src_id_type, dst_id_type));
1650 packet->src_id_len = src_id_len;
1651 packet->dst_id_len = dst_id_len;
1652 packet->src_id_type = src_id_type;
1653 packet->dst_id_type = dst_id_type;
1655 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1656 silc_buffer_len(buffer)), buffer->head,
1657 silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1659 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1660 silc_get_packet_name(packet->type)));
1665 /* Dispatch packet to application. Called with stream->lock locked. */
1667 static void silc_packet_dispatch(SilcPacket packet)
1669 SilcPacketStream stream = packet->stream;
1670 SilcPacketProcess p;
1671 SilcBool default_sent = FALSE;
1674 /* Dispatch packet to all packet processors that want it */
1676 if (!stream->process) {
1677 /* Send to default processor as no others exist */
1678 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1679 silc_mutex_unlock(stream->lock);
1680 if (!stream->engine->callbacks->
1681 packet_receive(stream->engine, stream, packet,
1682 stream->engine->callback_context,
1683 stream->stream_context))
1684 silc_packet_free(packet);
1685 silc_mutex_lock(stream->lock);
1689 silc_dlist_start(stream->process);
1690 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1692 /* If priority is 0 or less, we send to default processor first
1693 because default processor has 0 priority */
1694 if (!default_sent && p->priority <= 0) {
1695 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1696 default_sent = TRUE;
1697 silc_mutex_unlock(stream->lock);
1698 if (stream->engine->callbacks->
1699 packet_receive(stream->engine, stream, packet,
1700 stream->engine->callback_context,
1701 stream->stream_context)) {
1702 silc_mutex_lock(stream->lock);
1705 silc_mutex_lock(stream->lock);
1708 /* Send to processor */
1710 /* Send all packet types */
1711 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1712 silc_mutex_unlock(stream->lock);
1713 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1714 p->callback_context,
1715 stream->stream_context)) {
1716 silc_mutex_lock(stream->lock);
1719 silc_mutex_lock(stream->lock);
1721 /* Send specific types */
1722 for (pt = p->types; *pt; pt++) {
1723 if (*pt != packet->type)
1725 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1726 silc_mutex_unlock(stream->lock);
1727 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1728 p->callback_context,
1729 stream->stream_context)) {
1730 silc_mutex_lock(stream->lock);
1733 silc_mutex_lock(stream->lock);
1739 if (!default_sent) {
1740 /* Send to default processor as it has not been sent yet */
1741 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1742 silc_mutex_unlock(stream->lock);
1743 if (stream->engine->callbacks->
1744 packet_receive(stream->engine, stream, packet,
1745 stream->engine->callback_context,
1746 stream->stream_context)) {
1747 silc_mutex_lock(stream->lock);
1750 silc_mutex_lock(stream->lock);
1753 /* If we got here, no one wanted the packet, so drop it */
1754 silc_packet_free(packet);
1757 /* Process incoming data and parse packets. Called with stream->lock
1760 static void silc_packet_read_process(SilcPacketStream stream)
1766 SilcUInt16 packetlen;
1767 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1768 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1769 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1773 /* Parse the packets from the data */
1774 while (silc_buffer_len(&stream->inbuf) > 0) {
1776 cipher = stream->receive_key[0];
1777 hmac = stream->receive_hmac[0];
1780 if (silc_buffer_len(&stream->inbuf) <
1781 (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1782 SILC_PACKET_MIN_HEADER_LEN)) {
1783 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1788 mac_len = silc_hmac_len(hmac);
1792 /* Decrypt first block of the packet to get the length field out */
1794 block_len = silc_cipher_get_block_len(cipher);
1796 if (stream->iv_included) {
1797 /* SID, IV and sequence number is included in the ciphertext */
1798 sid = (SilcUInt8)stream->inbuf.data[0];
1799 memcpy(iv, stream->inbuf.data + 1, block_len);
1800 ivlen = block_len + 1;
1803 /* Check SID, and get correct decryption key */
1804 if (sid != stream->sid) {
1805 /* If SID is recent get the previous key and use it */
1806 if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1807 stream->receive_key[1] && !stream->receive_hmac[1]) {
1808 cipher = stream->receive_key[1];
1809 hmac = stream->receive_hmac[1];
1811 /* The SID is unknown, drop rest of the data in buffer */
1812 SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1814 silc_mutex_unlock(stream->lock);
1815 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1816 silc_mutex_lock(stream->lock);
1817 silc_buffer_reset(&stream->inbuf);
1822 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1825 silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1829 if (stream->iv_included) {
1830 /* Take sequence number from packet */
1831 packet_seq = header;
1835 block_len = SILC_PACKET_MIN_HEADER_LEN;
1836 header = stream->inbuf.data;
1839 /* Get packet length and full packet length with padding */
1840 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1843 if (packetlen < SILC_PACKET_MIN_LEN) {
1844 if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
1845 SILC_LOG_ERROR(("Received too short packet"));
1846 silc_mutex_unlock(stream->lock);
1847 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1848 silc_mutex_lock(stream->lock);
1849 memset(tmp, 0, sizeof(tmp));
1850 silc_buffer_reset(&stream->inbuf);
1854 if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1855 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1857 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1858 memset(tmp, 0, sizeof(tmp));
1862 /* Check MAC of the packet */
1863 if (!silc_packet_check_mac(hmac, stream->inbuf.data,
1865 stream->inbuf.data + ivlen + paddedlen,
1866 packet_seq, stream->receive_psn)) {
1867 silc_mutex_unlock(stream->lock);
1868 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1869 silc_mutex_lock(stream->lock);
1870 memset(tmp, 0, sizeof(tmp));
1871 silc_buffer_reset(&stream->inbuf);
1876 packet = silc_packet_alloc(stream->engine);
1878 silc_mutex_unlock(stream->lock);
1879 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1880 silc_mutex_lock(stream->lock);
1881 memset(tmp, 0, sizeof(tmp));
1882 silc_buffer_reset(&stream->inbuf);
1885 packet->stream = stream;
1887 /* Allocate more space to packet buffer, if needed */
1888 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1889 if (!silc_buffer_realloc(&packet->buffer,
1890 silc_buffer_truelen(&packet->buffer) +
1892 silc_buffer_truelen(&packet->buffer)))) {
1893 silc_mutex_unlock(stream->lock);
1894 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1895 silc_mutex_lock(stream->lock);
1896 silc_packet_free(packet);
1897 memset(tmp, 0, sizeof(tmp));
1898 silc_buffer_reset(&stream->inbuf);
1903 /* Parse packet header */
1904 packet->flags = (SilcPacketFlags)header[2];
1905 packet->type = (SilcPacketType)header[3];
1907 if (stream->engine->local_is_router) {
1908 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1909 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1911 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1912 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1913 stream->is_router == TRUE))
1916 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1917 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1919 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1923 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1924 stream->receive_psn, paddedlen + ivlen + mac_len),
1925 stream->inbuf.data, paddedlen + ivlen + mac_len);
1927 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1928 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1929 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1930 silc_buffer_pull(&packet->buffer, block_len - psnlen);
1931 silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1932 psnlen + (block_len - psnlen)),
1933 paddedlen - ivlen - psnlen - (block_len - psnlen));
1935 silc_cipher_set_iv(cipher, iv);
1936 ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1937 &packet->buffer, normal);
1939 silc_mutex_unlock(stream->lock);
1940 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1941 silc_mutex_lock(stream->lock);
1942 silc_packet_free(packet);
1943 memset(tmp, 0, sizeof(tmp));
1947 stream->receive_psn++;
1949 silc_buffer_push(&packet->buffer, block_len);
1951 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1952 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1954 /* Parse the packet */
1955 if (!silc_packet_parse(packet)) {
1956 silc_mutex_unlock(stream->lock);
1957 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1958 silc_mutex_lock(stream->lock);
1959 silc_packet_free(packet);
1960 memset(tmp, 0, sizeof(tmp));
1964 /* Dispatch the packet to application */
1965 silc_packet_dispatch(packet);
1968 silc_buffer_reset(&stream->inbuf);
1972 /****************************** Packet Waiting ******************************/
1974 /* Packet wait receive callback */
1976 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1977 SilcPacketStream stream,
1979 void *callback_context,
1980 void *stream_context);
1982 /* Packet waiting callbacks */
1983 static SilcPacketCallbacks silc_packet_wait_cbs =
1985 silc_packet_wait_packet_receive, NULL, NULL
1988 /* Packet waiting context */
1990 SilcMutex wait_lock;
1992 SilcList packet_queue;
1993 unsigned int stopped : 1;
1996 /* Packet wait receive callback */
1999 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2000 SilcPacketStream stream,
2002 void *callback_context,
2003 void *stream_context)
2005 SilcPacketWait pw = callback_context;
2007 /* Signal the waiting thread for a new packet */
2008 silc_mutex_lock(pw->wait_lock);
2011 silc_mutex_unlock(pw->wait_lock);
2015 silc_list_add(pw->packet_queue, packet);
2016 silc_cond_broadcast(pw->wait_cond);
2018 silc_mutex_unlock(pw->wait_lock);
2023 /* Initialize packet waiting */
2025 void *silc_packet_wait_init(SilcPacketStream stream, ...)
2031 pw = silc_calloc(1, sizeof(*pw));
2035 /* Allocate mutex and conditional variable */
2036 if (!silc_mutex_alloc(&pw->wait_lock)) {
2040 if (!silc_cond_alloc(&pw->wait_cond)) {
2041 silc_mutex_free(pw->wait_lock);
2046 /* Link to the packet stream for the requested packet types */
2047 va_start(ap, stream);
2048 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2052 silc_cond_free(pw->wait_cond);
2053 silc_mutex_free(pw->wait_lock);
2058 /* Initialize packet queue */
2059 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2064 /* Uninitialize packet waiting */
2066 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2068 SilcPacketWait pw = waiter;
2071 /* Signal any threads to stop waiting */
2072 silc_mutex_lock(pw->wait_lock);
2074 silc_cond_broadcast(pw->wait_cond);
2075 silc_mutex_unlock(pw->wait_lock);
2077 /* Re-acquire lock and free resources */
2078 silc_mutex_lock(pw->wait_lock);
2079 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2081 /* Free any remaining packets */
2082 silc_list_start(pw->packet_queue);
2083 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2084 silc_packet_free(packet);
2086 silc_mutex_unlock(pw->wait_lock);
2087 silc_cond_free(pw->wait_cond);
2088 silc_mutex_free(pw->wait_lock);
2092 /* Blocks thread until a packet has been received. */
2094 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2096 SilcPacketWait pw = waiter;
2097 SilcBool ret = FALSE;
2099 silc_mutex_lock(pw->wait_lock);
2101 /* Wait here until packet has arrived */
2102 while (silc_list_count(pw->packet_queue) == 0) {
2104 silc_mutex_unlock(pw->wait_lock);
2107 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2111 silc_list_start(pw->packet_queue);
2112 *return_packet = silc_list_get(pw->packet_queue);
2113 silc_list_del(pw->packet_queue, *return_packet);
2115 silc_mutex_unlock(pw->wait_lock);
2117 return ret == TRUE ? 1 : 0;