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));
209 if (silc_unlikely(i == -2)) {
211 silc_buffer_reset(&ps->outbuf);
212 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
216 if (silc_unlikely(i == -1)) {
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));
239 if (silc_unlikely(i == 0)) {
241 silc_buffer_reset(&ps->outbuf);
242 silc_mutex_unlock(ps->lock);
243 SILC_PACKET_CALLBACK_EOS(ps);
247 if (silc_unlikely(i == -2)) {
249 silc_buffer_reset(&ps->outbuf);
250 silc_mutex_unlock(ps->lock);
251 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
255 if (silc_unlikely(i == -1)) {
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));
307 if (silc_unlikely(ret == -2)) {
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_unlikely(!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 (silc_unlikely(!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));
376 if (silc_unlikely(ret == 0)) {
378 silc_buffer_reset(&ps->inbuf);
379 silc_mutex_unlock(ps->lock);
380 SILC_PACKET_CALLBACK_EOS(ps);
384 if (silc_unlikely(ret == -2)) {
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);
412 if (silc_unlikely(ps->destroyed)) {
413 silc_mutex_unlock(ps->lock);
419 case SILC_STREAM_CAN_WRITE:
420 SILC_LOG_DEBUG(("Writing pending data to stream"));
422 if (silc_unlikely(!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));
473 if (silc_unlikely(!packet))
476 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
478 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
479 if (silc_unlikely(!tmp)) {
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_unlikely(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_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen
1323 + psnlen, hmac, &packet))) {
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),
1349 if (silc_unlikely(i < 0)) {
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 */
1358 if (silc_likely(cipher)) {
1359 SILC_LOG_DEBUG(("Encrypting packet"));
1360 if (silc_unlikely(!silc_cipher_encrypt(cipher, packet.data + ivlen,
1361 packet.data + ivlen, enclen,
1363 SILC_LOG_ERROR(("Packet encryption failed"));
1364 silc_mutex_unlock(stream->lock);
1370 if (silc_likely(hmac)) {
1373 /* MAC is computed from the entire encrypted packet data, and put
1374 to the end of the packet. */
1375 silc_hmac_init(hmac);
1376 silc_hmac_update(hmac, psn, sizeof(psn));
1377 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1378 silc_hmac_final(hmac, packet.tail, &mac_len);
1379 silc_buffer_pull_tail(&packet, mac_len);
1386 /* Sends a packet */
1388 SilcBool silc_packet_send(SilcPacketStream stream,
1389 SilcPacketType type, SilcPacketFlags flags,
1390 const unsigned char *data, SilcUInt32 data_len)
1394 ret = silc_packet_send_raw(stream, type, flags,
1395 stream->src_id_type,
1398 stream->dst_id_type,
1402 stream->send_key[0],
1403 stream->send_hmac[0]);
1405 /* Write the packet to the stream */
1406 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1409 /* Sends a packet, extended routine */
1411 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1412 SilcPacketType type, SilcPacketFlags flags,
1413 SilcIdType src_id_type, void *src_id,
1414 SilcIdType dst_id_type, void *dst_id,
1415 const unsigned char *data, SilcUInt32 data_len,
1416 SilcCipher cipher, SilcHmac hmac)
1418 unsigned char src_id_data[32], dst_id_data[32];
1419 SilcUInt32 src_id_len, dst_id_len;
1423 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1424 sizeof(src_id_data), &src_id_len))
1427 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1428 sizeof(dst_id_data), &dst_id_len))
1431 ret = silc_packet_send_raw(stream, type, flags,
1432 src_id ? src_id_type : stream->src_id_type,
1433 src_id ? src_id_data : stream->src_id,
1434 src_id ? src_id_len : stream->src_id_len,
1435 dst_id ? dst_id_type : stream->dst_id_type,
1436 dst_id ? dst_id_data : stream->dst_id,
1437 dst_id ? dst_id_len : stream->dst_id_len,
1439 cipher ? cipher : stream->send_key[0],
1440 hmac ? hmac : stream->send_hmac[0]);
1442 /* Write the packet to the stream */
1443 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1446 /* Sends packet after formatting the arguments to buffer */
1448 SilcBool silc_packet_send_va(SilcPacketStream stream,
1449 SilcPacketType type, SilcPacketFlags flags, ...)
1451 SilcBufferStruct buf;
1455 va_start(va, flags);
1457 memset(&buf, 0, sizeof(buf));
1458 if (silc_buffer_format_vp(&buf, va) < 0) {
1463 ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1464 silc_buffer_len(&buf));
1466 silc_buffer_purge(&buf);
1472 /* Sends packet after formatting the arguments to buffer, extended routine */
1474 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1475 SilcPacketType type, SilcPacketFlags flags,
1476 SilcIdType src_id_type, void *src_id,
1477 SilcIdType dst_id_type, void *dst_id,
1478 SilcCipher cipher, SilcHmac hmac, ...)
1480 SilcBufferStruct buf;
1486 memset(&buf, 0, sizeof(buf));
1487 if (silc_buffer_format_vp(&buf, va) < 0) {
1492 ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1493 dst_id_type, dst_id, silc_buffer_data(&buf),
1494 silc_buffer_len(&buf), cipher, hmac);
1496 silc_buffer_purge(&buf);
1502 /***************************** Packet Receiving *****************************/
1504 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1506 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1507 const unsigned char *data,
1508 SilcUInt32 data_len,
1509 const unsigned char *packet_mac,
1510 const unsigned char *packet_seq,
1511 SilcUInt32 sequence)
1514 if (silc_likely(hmac)) {
1515 unsigned char mac[32], psn[4];
1518 SILC_LOG_DEBUG(("Verifying MAC"));
1520 /* Compute HMAC of packet */
1521 silc_hmac_init(hmac);
1524 SILC_PUT32_MSB(sequence, psn);
1525 silc_hmac_update(hmac, psn, 4);
1527 silc_hmac_update(hmac, packet_seq, 4);
1529 silc_hmac_update(hmac, data, data_len);
1530 silc_hmac_final(hmac, mac, &mac_len);
1532 /* Compare the MAC's */
1533 if (silc_unlikely(memcmp(packet_mac, mac, mac_len))) {
1534 SILC_LOG_DEBUG(("MAC failed"));
1538 SILC_LOG_DEBUG(("MAC is Ok"));
1544 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1545 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1547 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1548 SilcUInt32 sequence, SilcBuffer buffer,
1551 if (normal == TRUE) {
1552 if (silc_likely(cipher)) {
1553 /* Decrypt rest of the packet */
1554 SILC_LOG_DEBUG(("Decrypting the packet"));
1555 if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1557 silc_buffer_len(buffer), NULL)))
1563 /* Decrypt rest of the header plus padding */
1564 if (silc_likely(cipher)) {
1566 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1568 SILC_LOG_DEBUG(("Decrypting the header"));
1570 /* Padding length + src id len + dst id len + header length - 16
1571 bytes already decrypted, gives the rest of the encrypted packet */
1572 silc_buffer_push(buffer, block_len);
1573 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1574 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1576 silc_buffer_pull(buffer, block_len);
1578 if (silc_unlikely(len > silc_buffer_len(buffer))) {
1579 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1583 if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1584 buffer->data, len, NULL)))
1592 /* Parses the packet. This is called when a whole packet is ready to be
1593 parsed. The buffer sent must be already decrypted before calling this
1596 static inline SilcBool silc_packet_parse(SilcPacket packet)
1598 SilcBuffer buffer = &packet->buffer;
1599 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1600 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1603 SILC_LOG_DEBUG(("Parsing incoming packet"));
1605 /* Parse the buffer. This parses the SILC header of the packet. */
1606 ret = silc_buffer_unformat(buffer,
1609 SILC_STR_UI_CHAR(&src_id_len),
1610 SILC_STR_UI_CHAR(&dst_id_len),
1611 SILC_STR_UI_CHAR(&src_id_type),
1613 if (silc_unlikely(ret == -1)) {
1614 if (!packet->stream->udp &&
1615 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1616 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1620 if (silc_unlikely(src_id_len > SILC_PACKET_MAX_ID_LEN ||
1621 dst_id_len > SILC_PACKET_MAX_ID_LEN)) {
1622 if (!packet->stream->udp &&
1623 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1624 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1625 packet->src_id_len, packet->dst_id_len));
1629 ret = silc_buffer_unformat(buffer,
1631 SILC_STR_DATA(&packet->src_id, src_id_len),
1632 SILC_STR_UI_CHAR(&dst_id_type),
1633 SILC_STR_DATA(&packet->dst_id, dst_id_len),
1634 SILC_STR_OFFSET(padlen),
1636 if (silc_unlikely(ret == -1)) {
1637 if (!packet->stream->udp &&
1638 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1639 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1643 if (silc_unlikely(src_id_type > SILC_ID_CHANNEL ||
1644 dst_id_type > SILC_ID_CHANNEL)) {
1645 if (!packet->stream->udp &&
1646 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1647 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1648 src_id_type, dst_id_type));
1652 packet->src_id_len = src_id_len;
1653 packet->dst_id_len = dst_id_len;
1654 packet->src_id_type = src_id_type;
1655 packet->dst_id_type = dst_id_type;
1657 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1658 silc_buffer_len(buffer)), buffer->head,
1659 silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1661 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1662 silc_get_packet_name(packet->type)));
1667 /* Dispatch packet to application. Called with stream->lock locked. */
1669 static void silc_packet_dispatch(SilcPacket packet)
1671 SilcPacketStream stream = packet->stream;
1672 SilcPacketProcess p;
1673 SilcBool default_sent = FALSE;
1676 /* Dispatch packet to all packet processors that want it */
1678 if (silc_likely(!stream->process)) {
1679 /* Send to default processor as no others exist */
1680 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1681 silc_mutex_unlock(stream->lock);
1682 if (silc_unlikely(!stream->engine->callbacks->
1683 packet_receive(stream->engine, stream, packet,
1684 stream->engine->callback_context,
1685 stream->stream_context)))
1686 silc_packet_free(packet);
1687 silc_mutex_lock(stream->lock);
1691 silc_dlist_start(stream->process);
1692 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1694 /* If priority is 0 or less, we send to default processor first
1695 because default processor has 0 priority */
1696 if (!default_sent && p->priority <= 0) {
1697 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1698 default_sent = TRUE;
1699 silc_mutex_unlock(stream->lock);
1700 if (stream->engine->callbacks->
1701 packet_receive(stream->engine, stream, packet,
1702 stream->engine->callback_context,
1703 stream->stream_context)) {
1704 silc_mutex_lock(stream->lock);
1707 silc_mutex_lock(stream->lock);
1710 /* Send to processor */
1712 /* Send all packet types */
1713 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1714 silc_mutex_unlock(stream->lock);
1715 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1716 p->callback_context,
1717 stream->stream_context)) {
1718 silc_mutex_lock(stream->lock);
1721 silc_mutex_lock(stream->lock);
1723 /* Send specific types */
1724 for (pt = p->types; *pt; pt++) {
1725 if (*pt != packet->type)
1727 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1728 silc_mutex_unlock(stream->lock);
1729 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1730 p->callback_context,
1731 stream->stream_context)) {
1732 silc_mutex_lock(stream->lock);
1735 silc_mutex_lock(stream->lock);
1741 if (!default_sent) {
1742 /* Send to default processor as it has not been sent yet */
1743 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1744 silc_mutex_unlock(stream->lock);
1745 if (stream->engine->callbacks->
1746 packet_receive(stream->engine, stream, packet,
1747 stream->engine->callback_context,
1748 stream->stream_context)) {
1749 silc_mutex_lock(stream->lock);
1752 silc_mutex_lock(stream->lock);
1755 /* If we got here, no one wanted the packet, so drop it */
1756 silc_packet_free(packet);
1759 /* Process incoming data and parse packets. Called with stream->lock
1762 static void silc_packet_read_process(SilcPacketStream stream)
1768 SilcUInt16 packetlen;
1769 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1770 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1771 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1775 /* Parse the packets from the data */
1776 while (silc_buffer_len(&stream->inbuf) > 0) {
1778 cipher = stream->receive_key[0];
1779 hmac = stream->receive_hmac[0];
1782 if (silc_unlikely(silc_buffer_len(&stream->inbuf) <
1783 (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1784 SILC_PACKET_MIN_HEADER_LEN))) {
1785 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1789 if (silc_likely(hmac))
1790 mac_len = silc_hmac_len(hmac);
1794 /* Decrypt first block of the packet to get the length field out */
1795 if (silc_likely(cipher)) {
1796 block_len = silc_cipher_get_block_len(cipher);
1798 if (stream->iv_included) {
1799 /* SID, IV and sequence number is included in the ciphertext */
1800 sid = (SilcUInt8)stream->inbuf.data[0];
1801 memcpy(iv, stream->inbuf.data + 1, block_len);
1802 ivlen = block_len + 1;
1805 /* Check SID, and get correct decryption key */
1806 if (sid != stream->sid) {
1807 /* If SID is recent get the previous key and use it */
1808 if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1809 stream->receive_key[1] && !stream->receive_hmac[1]) {
1810 cipher = stream->receive_key[1];
1811 hmac = stream->receive_hmac[1];
1813 /* The SID is unknown, drop rest of the data in buffer */
1814 SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1816 silc_mutex_unlock(stream->lock);
1817 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1818 silc_mutex_lock(stream->lock);
1819 silc_buffer_reset(&stream->inbuf);
1824 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1827 silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1831 if (stream->iv_included) {
1832 /* Take sequence number from packet */
1833 packet_seq = header;
1837 block_len = SILC_PACKET_MIN_HEADER_LEN;
1838 header = stream->inbuf.data;
1841 /* Get packet length and full packet length with padding */
1842 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1845 if (silc_unlikely(packetlen < SILC_PACKET_MIN_LEN)) {
1846 if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
1847 SILC_LOG_ERROR(("Received too short packet"));
1848 silc_mutex_unlock(stream->lock);
1849 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1850 silc_mutex_lock(stream->lock);
1851 memset(tmp, 0, sizeof(tmp));
1852 silc_buffer_reset(&stream->inbuf);
1856 if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1857 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1859 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1860 memset(tmp, 0, sizeof(tmp));
1864 /* Check MAC of the packet */
1865 if (silc_unlikely(!silc_packet_check_mac(hmac, stream->inbuf.data,
1867 stream->inbuf.data + ivlen +
1868 paddedlen, packet_seq,
1869 stream->receive_psn))) {
1870 silc_mutex_unlock(stream->lock);
1871 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1872 silc_mutex_lock(stream->lock);
1873 memset(tmp, 0, sizeof(tmp));
1874 silc_buffer_reset(&stream->inbuf);
1879 packet = silc_packet_alloc(stream->engine);
1880 if (silc_unlikely(!packet)) {
1881 silc_mutex_unlock(stream->lock);
1882 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1883 silc_mutex_lock(stream->lock);
1884 memset(tmp, 0, sizeof(tmp));
1885 silc_buffer_reset(&stream->inbuf);
1888 packet->stream = stream;
1890 /* Allocate more space to packet buffer, if needed */
1891 if (silc_unlikely(silc_buffer_truelen(&packet->buffer) < paddedlen)) {
1892 if (!silc_buffer_realloc(&packet->buffer,
1893 silc_buffer_truelen(&packet->buffer) +
1895 silc_buffer_truelen(&packet->buffer)))) {
1896 silc_mutex_unlock(stream->lock);
1897 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1898 silc_mutex_lock(stream->lock);
1899 silc_packet_free(packet);
1900 memset(tmp, 0, sizeof(tmp));
1901 silc_buffer_reset(&stream->inbuf);
1906 /* Parse packet header */
1907 packet->flags = (SilcPacketFlags)header[2];
1908 packet->type = (SilcPacketType)header[3];
1910 if (stream->engine->local_is_router) {
1911 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1912 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1914 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1915 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1916 stream->is_router == TRUE))
1919 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1920 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1922 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1926 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1927 stream->receive_psn, paddedlen + ivlen + mac_len),
1928 stream->inbuf.data, paddedlen + ivlen + mac_len);
1930 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1931 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1932 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1933 silc_buffer_pull(&packet->buffer, block_len - psnlen);
1934 silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1935 psnlen + (block_len - psnlen)),
1936 paddedlen - ivlen - psnlen - (block_len - psnlen));
1937 if (silc_likely(cipher)) {
1938 silc_cipher_set_iv(cipher, iv);
1939 ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1940 &packet->buffer, normal);
1941 if (silc_unlikely(ret < 0)) {
1942 silc_mutex_unlock(stream->lock);
1943 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1944 silc_mutex_lock(stream->lock);
1945 silc_packet_free(packet);
1946 memset(tmp, 0, sizeof(tmp));
1950 stream->receive_psn++;
1952 silc_buffer_push(&packet->buffer, block_len);
1954 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1955 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1957 /* Parse the packet */
1958 if (silc_unlikely(!silc_packet_parse(packet))) {
1959 silc_mutex_unlock(stream->lock);
1960 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1961 silc_mutex_lock(stream->lock);
1962 silc_packet_free(packet);
1963 memset(tmp, 0, sizeof(tmp));
1967 /* Dispatch the packet to application */
1968 silc_packet_dispatch(packet);
1971 silc_buffer_reset(&stream->inbuf);
1975 /****************************** Packet Waiting ******************************/
1977 /* Packet wait receive callback */
1979 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1980 SilcPacketStream stream,
1982 void *callback_context,
1983 void *stream_context);
1985 /* Packet waiting callbacks */
1986 static SilcPacketCallbacks silc_packet_wait_cbs =
1988 silc_packet_wait_packet_receive, NULL, NULL
1991 /* Packet waiting context */
1993 SilcMutex wait_lock;
1995 SilcList packet_queue;
1996 unsigned int stopped : 1;
1999 /* Packet wait receive callback */
2002 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2003 SilcPacketStream stream,
2005 void *callback_context,
2006 void *stream_context)
2008 SilcPacketWait pw = callback_context;
2010 /* Signal the waiting thread for a new packet */
2011 silc_mutex_lock(pw->wait_lock);
2014 silc_mutex_unlock(pw->wait_lock);
2018 silc_list_add(pw->packet_queue, packet);
2019 silc_cond_broadcast(pw->wait_cond);
2021 silc_mutex_unlock(pw->wait_lock);
2026 /* Initialize packet waiting */
2028 void *silc_packet_wait_init(SilcPacketStream stream, ...)
2034 pw = silc_calloc(1, sizeof(*pw));
2038 /* Allocate mutex and conditional variable */
2039 if (!silc_mutex_alloc(&pw->wait_lock)) {
2043 if (!silc_cond_alloc(&pw->wait_cond)) {
2044 silc_mutex_free(pw->wait_lock);
2049 /* Link to the packet stream for the requested packet types */
2050 va_start(ap, stream);
2051 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2055 silc_cond_free(pw->wait_cond);
2056 silc_mutex_free(pw->wait_lock);
2061 /* Initialize packet queue */
2062 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2067 /* Uninitialize packet waiting */
2069 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2071 SilcPacketWait pw = waiter;
2074 /* Signal any threads to stop waiting */
2075 silc_mutex_lock(pw->wait_lock);
2077 silc_cond_broadcast(pw->wait_cond);
2078 silc_mutex_unlock(pw->wait_lock);
2080 /* Re-acquire lock and free resources */
2081 silc_mutex_lock(pw->wait_lock);
2082 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2084 /* Free any remaining packets */
2085 silc_list_start(pw->packet_queue);
2086 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2087 silc_packet_free(packet);
2089 silc_mutex_unlock(pw->wait_lock);
2090 silc_cond_free(pw->wait_cond);
2091 silc_mutex_free(pw->wait_lock);
2095 /* Blocks thread until a packet has been received. */
2097 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2099 SilcPacketWait pw = waiter;
2100 SilcBool ret = FALSE;
2102 silc_mutex_lock(pw->wait_lock);
2104 /* Wait here until packet has arrived */
2105 while (silc_list_count(pw->packet_queue) == 0) {
2107 silc_mutex_unlock(pw->wait_lock);
2110 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2114 silc_list_start(pw->packet_queue);
2115 *return_packet = silc_list_get(pw->packet_queue);
2116 silc_list_del(pw->packet_queue, *return_packet);
2118 silc_mutex_unlock(pw->wait_lock);
2120 return ret == TRUE ? 1 : 0;