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); \
155 /************************ Static utility functions **************************/
157 static void silc_packet_read_process(SilcPacketStream stream);
159 /* Write data to the stream. Must be called with ps->lock locked. Unlocks
160 the lock inside this function. */
162 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps)
169 stream = ((SilcPacketStream)ps->stream)->stream;
173 if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
175 /* Connectionless UDP stream */
176 while (silc_buffer_len(&ps->outbuf) > 0) {
177 i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
178 ps->remote_udp->remote_port,
179 ps->outbuf.data, silc_buffer_len(&ps->outbuf));
182 silc_buffer_reset(&ps->outbuf);
183 silc_mutex_unlock(ps->lock);
184 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
189 /* Cannot write now, write later. */
190 silc_mutex_unlock(ps->lock);
195 silc_buffer_pull(&ps->outbuf, i);
198 silc_buffer_reset(&ps->outbuf);
199 silc_mutex_unlock(ps->lock);
205 /* Write the data to the stream */
206 while (silc_buffer_len(&ps->outbuf) > 0) {
207 i = silc_stream_write(stream, ps->outbuf.data,
208 silc_buffer_len(&ps->outbuf));
211 silc_buffer_reset(&ps->outbuf);
212 silc_mutex_unlock(ps->lock);
213 SILC_PACKET_CALLBACK_EOS(ps);
219 silc_buffer_reset(&ps->outbuf);
220 silc_mutex_unlock(ps->lock);
221 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
226 /* Cannot write now, write later. */
227 silc_mutex_unlock(ps->lock);
232 silc_buffer_pull(&ps->outbuf, i);
235 silc_buffer_reset(&ps->outbuf);
236 silc_mutex_unlock(ps->lock);
241 /* Reads data from stream. Must be called with the ps->lock locked. If this
242 returns FALSE the lock has been unlocked. If this returns packet stream
243 to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
244 It is returned if the stream is UDP and remote UDP stream exists for
245 the sender of the packet. */
247 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
248 SilcPacketStream *ret_ps)
256 /* Make sure we have fair amount of free space in inbuf */
257 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
258 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
259 SILC_PACKET_DEFAULT_SIZE * 2)) {
260 silc_mutex_unlock(ps->lock);
261 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
265 if (silc_socket_stream_is_udp(stream, &connected)) {
267 /* Connectionless UDP stream, read one UDP packet */
268 char remote_ip[64], tuple[64];
270 SilcPacketStream remote;
272 ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
273 &remote_port, ps->inbuf.tail,
274 silc_buffer_taillen(&ps->inbuf));
277 silc_buffer_reset(&ps->inbuf);
278 silc_mutex_unlock(ps->lock);
279 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
284 /* Cannot read now, do it later. */
285 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
286 silc_mutex_unlock(ps->lock);
290 /* See if remote packet stream exist for this sender */
291 snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
292 silc_mutex_lock(ps->engine->lock);
293 if (silc_hash_table_find(ps->engine->udp_remote, tuple, NULL,
295 /* Found packet stream for this sender, copy the packet */
296 silc_mutex_unlock(ps->engine->lock);
298 SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p",
299 remote_ip, remote_port, remote));
301 silc_mutex_lock(remote->lock);
302 if (ret > silc_buffer_taillen(&remote->inbuf))
303 if (!silc_buffer_realloc(&remote->inbuf, ret)) {
304 silc_mutex_unlock(remote->lock);
305 silc_mutex_unlock(ps->lock);
306 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
310 silc_buffer_put_tail(&remote->inbuf, ps->inbuf.tail, ret);
311 silc_buffer_pull_tail(&remote->inbuf, ret);
314 silc_buffer_reset(&ps->inbuf);
315 silc_mutex_unlock(ps->lock);
318 silc_mutex_unlock(ps->engine->lock);
321 if (!ps->remote_udp) {
322 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
323 if (!ps->remote_udp) {
324 silc_mutex_unlock(ps->lock);
325 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
330 /* Save sender IP and port */
331 ps->remote_udp->remote_ip = strdup(remote_ip);
332 ps->remote_udp->remote_port = remote_port;
334 silc_buffer_pull_tail(&ps->inbuf, ret);
339 /* Read data from the stream */
340 ret = silc_stream_read(ps->stream, ps->inbuf.tail,
341 silc_buffer_taillen(&ps->inbuf));
345 silc_buffer_reset(&ps->inbuf);
346 silc_mutex_unlock(ps->lock);
347 SILC_PACKET_CALLBACK_EOS(ps);
353 silc_buffer_reset(&ps->inbuf);
354 silc_mutex_unlock(ps->lock);
355 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
360 /* Cannot read now, do it later. */
361 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
362 silc_mutex_unlock(ps->lock);
366 silc_buffer_pull_tail(&ps->inbuf, ret);
370 /* Our stream IO notifier callback. */
372 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
375 SilcPacketStream remote = NULL, ps = context;
377 silc_mutex_lock(ps->lock);
380 silc_mutex_unlock(ps->lock);
386 case SILC_STREAM_CAN_WRITE:
387 SILC_LOG_DEBUG(("Writing pending data to stream"));
389 if (!silc_buffer_headlen(&ps->outbuf)) {
390 silc_mutex_unlock(ps->lock);
394 /* Write pending data to stream */
395 silc_packet_stream_write(ps);
398 case SILC_STREAM_CAN_READ:
399 SILC_LOG_DEBUG(("Reading data from stream"));
401 /* Read data from stream */
402 if (!silc_packet_stream_read(ps, &remote))
405 /* Now process the data */
407 silc_packet_read_process(ps);
408 silc_mutex_unlock(ps->lock);
410 silc_packet_read_process(remote);
411 silc_mutex_unlock(remote->lock);
416 silc_mutex_unlock(ps->lock);
421 /* Allocate packet */
423 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
427 SILC_LOG_DEBUG(("Packet pool count %d",
428 silc_list_count(engine->packet_pool)));
430 silc_mutex_lock(engine->lock);
432 /* Get packet from freelist or allocate new one. */
433 packet = silc_list_get(engine->packet_pool);
437 silc_mutex_unlock(engine->lock);
439 packet = silc_calloc(1, sizeof(*packet));
443 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
445 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
450 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
451 silc_buffer_reset(&packet->buffer);
456 SILC_LOG_DEBUG(("Get packet %p", packet));
458 /* Delete from freelist */
459 silc_list_del(engine->packet_pool, packet);
461 silc_mutex_unlock(engine->lock);
466 /* UDP remote stream hash table destructor */
468 static void silc_packet_engine_hash_destr(void *key, void *context,
475 /******************************** Packet API ********************************/
477 /* Allocate new packet engine */
480 silc_packet_engine_start(SilcRng rng, SilcBool router,
481 SilcPacketCallbacks *callbacks,
482 void *callback_context)
484 SilcPacketEngine engine;
489 SILC_LOG_DEBUG(("Starting new packet engine"));
493 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
496 engine = silc_calloc(1, sizeof(*engine));
501 engine->local_is_router = router;
502 engine->callbacks = callbacks;
503 engine->callback_context = callback_context;
504 silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
505 silc_mutex_alloc(&engine->lock);
507 /* Allocate packet free list */
508 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
509 for (i = 0; i < 5; i++) {
510 packet = silc_calloc(1, sizeof(*packet));
512 silc_packet_engine_stop(engine);
516 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
518 silc_packet_engine_stop(engine);
521 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
522 silc_buffer_reset(&packet->buffer);
524 silc_list_add(engine->packet_pool, packet);
526 silc_list_start(engine->packet_pool);
531 /* Stop packet engine */
533 void silc_packet_engine_stop(SilcPacketEngine engine)
536 SILC_LOG_DEBUG(("Stopping packet engine"));
546 /* Create new packet stream */
548 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
549 SilcSchedule schedule,
555 SILC_LOG_DEBUG(("Creating new packet stream"));
557 if (!engine || !stream)
560 ps = silc_calloc(1, sizeof(*ps));
566 silc_atomic_init8(&ps->refcnt, 1);
567 silc_mutex_alloc(&ps->lock);
569 /* Allocate buffers */
570 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
572 silc_packet_stream_destroy(ps);
575 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
576 silc_buffer_reset(&ps->inbuf);
577 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
579 silc_packet_stream_destroy(ps);
582 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
583 silc_buffer_reset(&ps->outbuf);
585 /* Initialize packet procesors list */
586 ps->process = silc_dlist_init();
588 silc_packet_stream_destroy(ps);
592 /* Set IO notifier callback */
593 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
596 silc_mutex_lock(engine->lock);
597 silc_list_add(engine->streams, ps);
598 silc_mutex_unlock(engine->lock);
600 /* If this is UDP stream, allocate UDP remote stream hash table */
601 if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
602 engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
603 silc_hash_string_compare, NULL,
604 silc_packet_engine_hash_destr,
610 /* Add new remote packet stream for UDP packet streams */
612 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
613 const char *remote_ip,
614 SilcUInt16 remote_port)
616 SilcPacketEngine engine = stream->engine;
621 SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
622 remote_ip, remote_port, stream));
624 if (!stream || !remote_ip || !remote_port)
627 if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
628 SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
632 ps = silc_calloc(1, sizeof(*ps));
637 silc_atomic_init8(&ps->refcnt, 1);
638 silc_mutex_alloc(&ps->lock);
640 /* Set the UDP packet stream as underlaying stream */
641 silc_packet_stream_ref(stream);
642 ps->stream = (SilcStream)stream;
645 /* Allocate buffers */
646 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
648 silc_packet_stream_destroy(ps);
651 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
652 silc_buffer_reset(&ps->inbuf);
653 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
655 silc_packet_stream_destroy(ps);
658 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
659 silc_buffer_reset(&ps->outbuf);
661 /* Initialize packet procesors list */
662 ps->process = silc_dlist_init();
664 silc_packet_stream_destroy(ps);
668 /* Add to engine with this IP and port pair */
669 tuple = silc_format("%d%s", remote_port, remote_ip);
670 silc_mutex_lock(engine->lock);
671 if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
672 silc_mutex_unlock(engine->lock);
673 silc_packet_stream_destroy(ps);
676 silc_mutex_unlock(engine->lock);
678 /* Save remote IP and port pair */
679 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
680 if (!ps->remote_udp) {
681 silc_packet_stream_destroy(ps);
684 ps->remote_udp->remote_port = remote_port;
685 ps->remote_udp->remote_ip = strdup(remote_ip);
686 if (!ps->remote_udp->remote_ip) {
687 silc_packet_stream_destroy(ps);
694 /* Destroy packet stream */
696 void silc_packet_stream_destroy(SilcPacketStream stream)
701 if (silc_atomic_get_int8(&stream->refcnt) > 1) {
702 stream->destroyed = TRUE;
706 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
709 /* Delete from engine */
710 silc_mutex_lock(stream->engine->lock);
711 silc_list_del(stream->engine->streams, stream);
712 silc_mutex_unlock(stream->engine->lock);
714 /* Destroy the underlaying stream */
716 silc_stream_destroy(stream->stream);
718 /* Delete from UDP remote hash table */
720 snprintf(tuple, sizeof(tuple), "%d%s", stream->remote_udp->remote_port,
721 stream->remote_udp->remote_ip);
722 silc_mutex_lock(stream->engine->lock);
723 silc_hash_table_del(stream->engine->udp_remote, tuple);
724 silc_mutex_unlock(stream->engine->lock);
726 silc_free(stream->remote_udp->remote_ip);
727 silc_free(stream->remote_udp);
729 /* Unreference the underlaying packet stream */
730 silc_packet_stream_unref((SilcPacketStream)stream->stream);
733 /* Clear and free buffers */
734 silc_buffer_clear(&stream->inbuf);
735 silc_buffer_clear(&stream->outbuf);
736 silc_buffer_purge(&stream->inbuf);
737 silc_buffer_purge(&stream->outbuf);
741 silc_atomic_uninit8(&stream->refcnt);
742 silc_dlist_uninit(stream->process);
743 silc_mutex_free(stream->lock);
747 /* Marks as router stream */
749 void silc_packet_stream_set_router(SilcPacketStream stream)
751 stream->is_router = TRUE;
754 /* Mark to include IV in ciphertext */
756 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
758 stream->iv_included = TRUE;
761 /* Links `callbacks' to `stream' for specified packet types */
763 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
764 SilcPacketCallbacks *callbacks,
765 void *callback_context,
766 int priority, va_list ap)
768 SilcPacketProcess p, e;
769 SilcInt32 packet_type;
772 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
776 if (!callbacks->packet_receive)
779 p = silc_calloc(1, sizeof(*p));
783 p->priority = priority;
784 p->callbacks = callbacks;
785 p->callback_context = callback_context;
787 silc_mutex_lock(stream->lock);
789 if (!stream->process) {
790 stream->process = silc_dlist_init();
791 if (!stream->process) {
792 silc_mutex_unlock(stream->lock);
797 /* According to priority set the procesor to correct position. First
798 entry has the highest priority */
799 silc_dlist_start(stream->process);
800 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
801 if (p->priority > e->priority) {
802 silc_dlist_insert(stream->process, p);
807 silc_dlist_add(stream->process, p);
809 /* Get packet types to process */
812 packet_type = va_arg(ap, SilcInt32);
814 if (packet_type == SILC_PACKET_ANY)
817 if (packet_type == -1)
820 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
822 silc_mutex_unlock(stream->lock);
826 p->types[i - 1] = (SilcPacketType)packet_type;
832 silc_mutex_unlock(stream->lock);
834 silc_packet_stream_ref(stream);
839 /* Links `callbacks' to `stream' for specified packet types */
841 SilcBool silc_packet_stream_link(SilcPacketStream stream,
842 SilcPacketCallbacks *callbacks,
843 void *callback_context,
849 va_start(ap, priority);
850 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
857 /* Unlinks `callbacks' from `stream'. */
859 void silc_packet_stream_unlink(SilcPacketStream stream,
860 SilcPacketCallbacks *callbacks,
861 void *callback_context)
865 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
868 silc_mutex_lock(stream->lock);
870 silc_dlist_start(stream->process);
871 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
872 if (p->callbacks == callbacks &&
873 p->callback_context == callback_context) {
874 silc_dlist_del(stream->process, p);
879 if (!silc_dlist_count(stream->process)) {
880 silc_dlist_uninit(stream->process);
881 stream->process = NULL;
884 silc_mutex_unlock(stream->lock);
886 silc_packet_stream_unref(stream);
889 /* Return packet sender IP and port for UDP packet stream */
891 SilcBool silc_packet_stream_get_sender(SilcPacketStream stream,
892 const char **sender_ip,
893 SilcUInt16 *sender_port)
895 if (!stream->remote_udp)
898 *sender_ip = stream->remote_udp->remote_ip;
899 *sender_port = stream->remote_udp->remote_port;
904 /* Reference packet stream */
906 void silc_packet_stream_ref(SilcPacketStream stream)
908 silc_atomic_add_int8(&stream->refcnt, 1);
911 /* Unreference packet stream */
913 void silc_packet_stream_unref(SilcPacketStream stream)
915 if (silc_atomic_sub_int8(&stream->refcnt, 1) == 0)
916 silc_packet_stream_destroy(stream);
921 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
923 return stream->engine;
926 /* Set application context for packet stream */
928 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
930 silc_mutex_lock(stream->lock);
931 stream->stream_context = stream_context;
932 silc_mutex_unlock(stream->lock);
935 /* Return application context from packet stream */
937 void *silc_packet_get_context(SilcPacketStream stream)
940 silc_mutex_lock(stream->lock);
941 context = stream->stream_context;
942 silc_mutex_unlock(stream->lock);
946 /* Change underlaying stream */
948 void silc_packet_stream_set_stream(SilcPacketStream ps,
950 SilcSchedule schedule)
953 silc_stream_set_notifier(ps->stream, schedule, NULL, NULL);
955 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
958 /* Return underlaying stream */
960 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
962 return stream->stream;
965 /* Set ciphers for packet stream */
967 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
970 SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
972 silc_mutex_lock(stream->lock);
974 /* In case IV Included is set, save the old key */
975 if (stream->iv_included) {
976 if (stream->send_key[1]) {
977 silc_cipher_free(stream->send_key[1]);
978 stream->send_key[1] = stream->send_key[0];
980 if (stream->receive_key[1]) {
981 silc_cipher_free(stream->receive_key[1]);
982 stream->receive_key[1] = stream->receive_key[0];
985 if (stream->send_key[0])
986 silc_cipher_free(stream->send_key[0]);
987 if (stream->send_key[1])
988 silc_cipher_free(stream->receive_key[0]);
991 stream->send_key[0] = send;
992 stream->receive_key[0] = receive;
994 silc_mutex_unlock(stream->lock);
997 /* Return current ciphers from packet stream */
999 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
1000 SilcCipher *receive)
1002 if (!stream->send_key[0] && !stream->receive_key[0])
1005 silc_mutex_lock(stream->lock);
1008 *send = stream->send_key[0];
1010 *receive = stream->receive_key[0];
1012 silc_mutex_unlock(stream->lock);
1017 /* Set HMACs for packet stream */
1019 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
1022 SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
1024 silc_mutex_lock(stream->lock);
1026 /* In case IV Included is set, save the old HMAC */
1027 if (stream->iv_included) {
1028 if (stream->send_hmac[1]) {
1029 silc_hmac_free(stream->send_hmac[1]);
1030 stream->send_hmac[1] = stream->send_hmac[0];
1032 if (stream->receive_hmac[1]) {
1033 silc_hmac_free(stream->receive_hmac[1]);
1034 stream->receive_hmac[1] = stream->receive_hmac[0];
1037 if (stream->send_hmac[0])
1038 silc_hmac_free(stream->send_hmac[0]);
1039 if (stream->receive_hmac[0])
1040 silc_hmac_free(stream->receive_hmac[0]);
1043 stream->send_hmac[0] = send;
1044 stream->receive_hmac[0] = receive;
1046 silc_mutex_unlock(stream->lock);
1049 /* Return current HMACs from packet stream */
1051 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
1054 if (!stream->send_hmac[0] && !stream->receive_hmac[0])
1057 silc_mutex_lock(stream->lock);
1060 *send = stream->send_hmac[0];
1062 *receive = stream->receive_hmac[0];
1064 silc_mutex_unlock(stream->lock);
1069 /* Set SILC IDs to packet stream */
1071 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1072 SilcIdType src_id_type, const void *src_id,
1073 SilcIdType dst_id_type, const void *dst_id)
1076 unsigned char tmp[32];
1078 if (!src_id && !dst_id)
1081 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1083 silc_mutex_lock(stream->lock);
1086 silc_free(stream->src_id);
1087 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1088 silc_mutex_unlock(stream->lock);
1091 stream->src_id = silc_memdup(tmp, len);
1092 if (!stream->src_id) {
1093 silc_mutex_unlock(stream->lock);
1096 stream->src_id_type = src_id_type;
1097 stream->src_id_len = len;
1101 silc_free(stream->dst_id);
1102 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1103 silc_mutex_unlock(stream->lock);
1106 stream->dst_id = silc_memdup(tmp, len);
1107 if (!stream->dst_id) {
1108 silc_mutex_unlock(stream->lock);
1111 stream->dst_id_type = dst_id_type;
1112 stream->dst_id_len = len;
1115 silc_mutex_unlock(stream->lock);
1120 /* Adds Security ID (SID) */
1122 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1124 if (!stream->iv_included)
1127 SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1135 void silc_packet_free(SilcPacket packet)
1137 SilcPacketStream stream = packet->stream;
1139 SILC_LOG_DEBUG(("Freeing packet %p", packet));
1141 /* Check for double free */
1142 SILC_ASSERT(packet->stream != NULL);
1144 packet->stream = NULL;
1145 packet->src_id = packet->dst_id = NULL;
1146 silc_buffer_reset(&packet->buffer);
1148 silc_mutex_lock(stream->engine->lock);
1150 /* Put the packet back to freelist */
1151 silc_list_add(stream->engine->packet_pool, packet);
1152 if (silc_list_count(stream->engine->packet_pool) == 1)
1153 silc_list_start(stream->engine->packet_pool);
1155 silc_mutex_unlock(stream->engine->lock);
1158 /****************************** Packet Sending ******************************/
1160 /* Prepare outgoing data buffer for packet sending. Returns the
1161 pointer to that buffer into the `packet'. */
1163 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1168 unsigned char *oldptr;
1169 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1173 /* Allocate more space if needed */
1174 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
1175 if (!silc_buffer_realloc(&stream->outbuf,
1176 silc_buffer_truelen(&stream->outbuf) + totlen))
1180 /* Pull data area for the new packet, and return pointer to the start of
1181 the data area and save the pointer in to the `packet'. MAC is pulled
1182 later after it's computed. */
1183 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1184 silc_buffer_set(packet, oldptr, totlen);
1185 silc_buffer_push_tail(packet, mac_len);
1190 /* Internal routine to send packet */
1192 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
1193 SilcPacketType type,
1194 SilcPacketFlags flags,
1195 SilcIdType src_id_type,
1196 unsigned char *src_id,
1197 SilcUInt32 src_id_len,
1198 SilcIdType dst_id_type,
1199 unsigned char *dst_id,
1200 SilcUInt32 dst_id_len,
1201 const unsigned char *data,
1202 SilcUInt32 data_len,
1206 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1207 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1208 int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
1209 SilcBufferStruct packet;
1211 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1212 "data len %d", silc_get_packet_name(type), stream->send_psn,
1213 flags, src_id_type, dst_id_type, data_len));
1215 /* Get the true length of the packet. This is saved as payload length
1216 into the packet header. This does not include the length of the
1218 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1219 src_id_len + dst_id_len));
1220 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1221 src_id_len + dst_id_len);
1223 /* If IV is included, the SID, IV and sequence number is added to packet */
1224 if (stream->iv_included && cipher) {
1225 psnlen = sizeof(psn);
1226 ivlen = block_len + 1;
1227 iv[0] = stream->sid;
1228 memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1231 /* We automatically figure out the packet structure from the packet
1232 type and flags, and calculate correct length. Private messages with
1233 private keys and channel messages are special packets as their
1234 payload is encrypted already. */
1235 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1236 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1237 type == SILC_PACKET_CHANNEL_MESSAGE) {
1239 /* Padding is calculated from header + IDs */
1240 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1241 psnlen), block_len, padlen);
1243 /* Length to encrypt, header + IDs + padding. */
1244 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1248 /* Padding is calculated from true length of the packet */
1249 if (flags & SILC_PACKET_FLAG_LONG_PAD)
1250 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1252 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1254 enclen += padlen + psnlen;
1257 /* Remove implementation specific flags */
1258 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1260 /* Get random padding */
1261 for (i = 0; i < padlen; i++) tmppad[i] =
1262 silc_rng_get_byte_fast(stream->engine->rng);
1264 silc_mutex_lock(stream->lock);
1266 /* Get packet pointer from the outgoing buffer */
1267 if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
1269 silc_mutex_unlock(stream->lock);
1273 SILC_PUT32_MSB(stream->send_psn, psn);
1275 /* Create the packet. This creates the SILC header, adds padding, and
1276 the actual packet data. */
1277 i = silc_buffer_format(&packet,
1278 SILC_STR_DATA(iv, ivlen),
1279 SILC_STR_DATA(psn, psnlen),
1280 SILC_STR_UI_SHORT(truelen),
1281 SILC_STR_UI_CHAR(flags),
1282 SILC_STR_UI_CHAR(type),
1283 SILC_STR_UI_CHAR(padlen),
1284 SILC_STR_UI_CHAR(0),
1285 SILC_STR_UI_CHAR(src_id_len),
1286 SILC_STR_UI_CHAR(dst_id_len),
1287 SILC_STR_UI_CHAR(src_id_type),
1288 SILC_STR_DATA(src_id, src_id_len),
1289 SILC_STR_UI_CHAR(dst_id_type),
1290 SILC_STR_DATA(dst_id, dst_id_len),
1291 SILC_STR_DATA(tmppad, padlen),
1292 SILC_STR_DATA(data, data_len),
1295 silc_mutex_unlock(stream->lock);
1299 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1300 silc_buffer_data(&packet), silc_buffer_len(&packet));
1302 /* Encrypt the packet */
1304 SILC_LOG_DEBUG(("Encrypting packet"));
1305 if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
1306 packet.data + ivlen, enclen, NULL)) {
1307 SILC_LOG_ERROR(("Packet encryption failed"));
1308 silc_mutex_unlock(stream->lock);
1317 /* MAC is computed from the entire encrypted packet data, and put
1318 to the end of the packet. */
1319 silc_hmac_init(hmac);
1320 silc_hmac_update(hmac, psn, sizeof(psn));
1321 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1322 silc_hmac_final(hmac, packet.tail, &mac_len);
1323 silc_buffer_pull_tail(&packet, mac_len);
1327 /* Write the packet to the stream */
1328 return silc_packet_stream_write(stream);
1331 /* Sends a packet */
1333 SilcBool silc_packet_send(SilcPacketStream stream,
1334 SilcPacketType type, SilcPacketFlags flags,
1335 const unsigned char *data, SilcUInt32 data_len)
1337 return silc_packet_send_raw(stream, type, flags,
1338 stream->src_id_type,
1341 stream->dst_id_type,
1345 stream->send_key[0],
1346 stream->send_hmac[0]);
1349 /* Sends a packet, extended routine */
1351 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1352 SilcPacketType type, SilcPacketFlags flags,
1353 SilcIdType src_id_type, void *src_id,
1354 SilcIdType dst_id_type, void *dst_id,
1355 const unsigned char *data, SilcUInt32 data_len,
1356 SilcCipher cipher, SilcHmac hmac)
1358 unsigned char src_id_data[32], dst_id_data[32];
1359 SilcUInt32 src_id_len, dst_id_len;
1362 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1363 sizeof(src_id_data), &src_id_len))
1366 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1367 sizeof(dst_id_data), &dst_id_len))
1370 return silc_packet_send_raw(stream, type, flags,
1371 src_id ? src_id_type : stream->src_id_type,
1372 src_id ? src_id_data : stream->src_id,
1373 src_id ? src_id_len : stream->src_id_len,
1374 dst_id ? dst_id_type : stream->dst_id_type,
1375 dst_id ? dst_id_data : stream->dst_id,
1376 dst_id ? dst_id_len : stream->dst_id_len,
1378 cipher ? cipher : stream->send_key[0],
1379 hmac ? hmac : stream->send_hmac[0]);
1382 /* Sends packet after formatting the arguments to buffer */
1384 SilcBool silc_packet_send_va(SilcPacketStream stream,
1385 SilcPacketType type, SilcPacketFlags flags, ...)
1387 SilcBufferStruct buf;
1391 va_start(va, flags);
1393 memset(&buf, 0, sizeof(buf));
1394 if (silc_buffer_format_vp(&buf, va) < 0) {
1399 ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1400 silc_buffer_len(&buf));
1402 silc_buffer_purge(&buf);
1408 /* Sends packet after formatting the arguments to buffer, extended routine */
1410 SilcBool silc_packet_send_va_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 SilcCipher cipher, SilcHmac hmac, ...)
1416 SilcBufferStruct buf;
1422 memset(&buf, 0, sizeof(buf));
1423 if (silc_buffer_format_vp(&buf, va) < 0) {
1428 ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1429 dst_id_type, dst_id, silc_buffer_data(&buf),
1430 silc_buffer_len(&buf), cipher, hmac);
1432 silc_buffer_purge(&buf);
1438 /***************************** Packet Receiving *****************************/
1440 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1442 static SilcBool silc_packet_check_mac(SilcHmac hmac,
1443 const unsigned char *data,
1444 SilcUInt32 data_len,
1445 const unsigned char *packet_mac,
1446 const unsigned char *packet_seq,
1447 SilcUInt32 sequence)
1451 unsigned char mac[32], psn[4];
1454 SILC_LOG_DEBUG(("Verifying MAC"));
1456 /* Compute HMAC of packet */
1457 silc_hmac_init(hmac);
1460 SILC_PUT32_MSB(sequence, psn);
1461 silc_hmac_update(hmac, psn, 4);
1463 silc_hmac_update(hmac, packet_seq, 4);
1465 silc_hmac_update(hmac, data, data_len);
1466 silc_hmac_final(hmac, mac, &mac_len);
1468 /* Compare the MAC's */
1469 if (memcmp(packet_mac, mac, mac_len)) {
1470 SILC_LOG_DEBUG(("MAC failed"));
1474 SILC_LOG_DEBUG(("MAC is Ok"));
1480 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1481 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1483 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1484 SilcUInt32 sequence, SilcBuffer buffer,
1487 if (normal == TRUE) {
1489 /* Decrypt rest of the packet */
1490 SILC_LOG_DEBUG(("Decrypting the packet"));
1491 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1492 silc_buffer_len(buffer), NULL))
1498 /* Decrypt rest of the header plus padding */
1501 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1503 SILC_LOG_DEBUG(("Decrypting the header"));
1505 /* Padding length + src id len + dst id len + header length - 16
1506 bytes already decrypted, gives the rest of the encrypted packet */
1507 silc_buffer_push(buffer, block_len);
1508 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1509 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1511 silc_buffer_pull(buffer, block_len);
1513 if (len > silc_buffer_len(buffer)) {
1514 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1518 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1527 /* Parses the packet. This is called when a whole packet is ready to be
1528 parsed. The buffer sent must be already decrypted before calling this
1531 static SilcBool silc_packet_parse(SilcPacket packet)
1533 SilcBuffer buffer = &packet->buffer;
1534 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1535 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1538 SILC_LOG_DEBUG(("Parsing incoming packet"));
1540 /* Parse the buffer. This parses the SILC header of the packet. */
1541 ret = silc_buffer_unformat(buffer,
1544 SILC_STR_UI_CHAR(&src_id_len),
1545 SILC_STR_UI_CHAR(&dst_id_len),
1546 SILC_STR_UI_CHAR(&src_id_type),
1549 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1553 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1554 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1555 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1556 packet->src_id_len, packet->dst_id_len));
1560 ret = silc_buffer_unformat(buffer,
1562 SILC_STR_DATA(&packet->src_id, src_id_len),
1563 SILC_STR_UI_CHAR(&dst_id_type),
1564 SILC_STR_DATA(&packet->dst_id, dst_id_len),
1565 SILC_STR_OFFSET(padlen),
1568 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1572 if (src_id_type > SILC_ID_CHANNEL ||
1573 dst_id_type > SILC_ID_CHANNEL) {
1574 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1575 src_id_type, dst_id_type));
1579 packet->src_id_len = src_id_len;
1580 packet->dst_id_len = dst_id_len;
1581 packet->src_id_type = src_id_type;
1582 packet->dst_id_type = dst_id_type;
1584 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1585 silc_buffer_len(buffer)), buffer->head,
1586 silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1588 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1589 silc_get_packet_name(packet->type)));
1594 /* Dispatch packet to application. Called with stream->lock locked. */
1596 static void silc_packet_dispatch(SilcPacket packet)
1598 SilcPacketStream stream = packet->stream;
1599 SilcPacketProcess p;
1600 SilcBool default_sent = FALSE;
1603 /* Parse the packet */
1604 if (!silc_packet_parse(packet)) {
1605 silc_mutex_unlock(stream->lock);
1606 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1607 silc_mutex_lock(stream->lock);
1608 silc_packet_free(packet);
1612 /* Dispatch packet to all packet processors that want it */
1614 if (!stream->process) {
1615 /* Send to default processor as no others exist */
1616 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1617 silc_mutex_unlock(stream->lock);
1618 if (!stream->engine->callbacks->
1619 packet_receive(stream->engine, stream, packet,
1620 stream->engine->callback_context,
1621 stream->stream_context))
1622 silc_packet_free(packet);
1623 silc_mutex_lock(stream->lock);
1627 silc_dlist_start(stream->process);
1628 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1630 /* If priority is 0 or less, we send to default processor first
1631 because default processor has 0 priority */
1632 if (!default_sent && p->priority <= 0) {
1633 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1634 default_sent = TRUE;
1635 silc_mutex_unlock(stream->lock);
1636 if (stream->engine->callbacks->
1637 packet_receive(stream->engine, stream, packet,
1638 stream->engine->callback_context,
1639 stream->stream_context)) {
1640 silc_mutex_lock(stream->lock);
1643 silc_mutex_lock(stream->lock);
1646 /* Send to processor */
1648 /* Send all packet types */
1649 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1650 silc_mutex_unlock(stream->lock);
1651 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1652 p->callback_context,
1653 stream->stream_context)) {
1654 silc_mutex_lock(stream->lock);
1657 silc_mutex_lock(stream->lock);
1659 /* Send specific types */
1660 for (pt = p->types; *pt; pt++) {
1661 if (*pt != packet->type)
1663 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1664 silc_mutex_unlock(stream->lock);
1665 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1666 p->callback_context,
1667 stream->stream_context)) {
1668 silc_mutex_lock(stream->lock);
1671 silc_mutex_lock(stream->lock);
1677 if (!default_sent) {
1678 /* Send to default processor as it has not been sent yet */
1679 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1680 silc_mutex_unlock(stream->lock);
1681 if (stream->engine->callbacks->
1682 packet_receive(stream->engine, stream, packet,
1683 stream->engine->callback_context,
1684 stream->stream_context)) {
1685 silc_mutex_lock(stream->lock);
1688 silc_mutex_lock(stream->lock);
1691 /* If we got here, no one wanted the packet, so drop it */
1692 silc_packet_free(packet);
1695 /* Process incoming data and parse packets. Called with stream->lock
1698 static void silc_packet_read_process(SilcPacketStream stream)
1704 SilcUInt16 packetlen;
1705 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1706 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1707 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1711 /* Parse the packets from the data */
1712 while (silc_buffer_len(&stream->inbuf) > 0) {
1714 cipher = stream->receive_key[0];
1715 hmac = stream->receive_hmac[0];
1718 if (silc_buffer_len(&stream->inbuf) <
1719 (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1720 SILC_PACKET_MIN_HEADER_LEN)) {
1721 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1726 mac_len = silc_hmac_len(hmac);
1730 /* Decrypt first block of the packet to get the length field out */
1732 block_len = silc_cipher_get_block_len(cipher);
1734 if (stream->iv_included) {
1735 /* SID, IV and sequence number is included in the ciphertext */
1736 sid = (SilcUInt8)stream->inbuf.data[0];
1737 memcpy(iv, stream->inbuf.data + 1, block_len);
1738 ivlen = block_len + 1;
1741 /* Check SID, and get correct decryption key */
1742 if (sid != stream->sid) {
1743 /* If SID is recent get the previous key and use it */
1744 if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1745 stream->receive_key[1] && !stream->receive_hmac[1]) {
1746 cipher = stream->receive_key[1];
1747 hmac = stream->receive_hmac[1];
1749 /* The SID is unknown, drop rest of the data in buffer */
1750 SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1752 silc_mutex_unlock(stream->lock);
1753 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1754 silc_mutex_lock(stream->lock);
1755 silc_buffer_reset(&stream->inbuf);
1760 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1763 silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1767 if (stream->iv_included) {
1768 /* Take sequence number from packet */
1769 packet_seq = header;
1773 block_len = SILC_PACKET_MIN_HEADER_LEN;
1774 header = stream->inbuf.data;
1777 /* Get packet length and full packet length with padding */
1778 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1781 if (packetlen < SILC_PACKET_MIN_LEN) {
1782 SILC_LOG_ERROR(("Received too short packet"));
1783 silc_mutex_unlock(stream->lock);
1784 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1785 silc_mutex_lock(stream->lock);
1786 memset(tmp, 0, sizeof(tmp));
1787 silc_buffer_reset(&stream->inbuf);
1791 if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1792 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1794 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1795 memset(tmp, 0, sizeof(tmp));
1799 /* Check MAC of the packet */
1800 if (!silc_packet_check_mac(hmac, stream->inbuf.data,
1802 stream->inbuf.data + ivlen + paddedlen,
1803 packet_seq, stream->receive_psn)) {
1804 silc_mutex_unlock(stream->lock);
1805 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1806 silc_mutex_lock(stream->lock);
1807 memset(tmp, 0, sizeof(tmp));
1808 silc_buffer_reset(&stream->inbuf);
1813 packet = silc_packet_alloc(stream->engine);
1815 silc_mutex_unlock(stream->lock);
1816 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1817 silc_mutex_lock(stream->lock);
1818 memset(tmp, 0, sizeof(tmp));
1819 silc_buffer_reset(&stream->inbuf);
1822 packet->stream = stream;
1824 /* Allocate more space to packet buffer, if needed */
1825 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1826 if (!silc_buffer_realloc(&packet->buffer,
1827 silc_buffer_truelen(&packet->buffer) +
1829 silc_buffer_truelen(&packet->buffer)))) {
1830 silc_mutex_unlock(stream->lock);
1831 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1832 silc_mutex_lock(stream->lock);
1833 silc_packet_free(packet);
1834 memset(tmp, 0, sizeof(tmp));
1835 silc_buffer_reset(&stream->inbuf);
1840 /* Parse packet header */
1841 packet->flags = (SilcPacketFlags)header[2];
1842 packet->type = (SilcPacketType)header[3];
1844 if (stream->engine->local_is_router) {
1845 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1846 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1848 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1849 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1850 stream->is_router == TRUE))
1853 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1854 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1856 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1860 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1861 stream->receive_psn, paddedlen + ivlen + mac_len),
1862 stream->inbuf.data, paddedlen + ivlen + mac_len);
1864 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1865 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1866 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1867 silc_buffer_pull(&packet->buffer, block_len - psnlen);
1868 silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1869 psnlen + (block_len - psnlen)),
1870 paddedlen - ivlen - psnlen - (block_len - psnlen));
1872 silc_cipher_set_iv(cipher, iv);
1873 ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1874 &packet->buffer, normal);
1876 silc_mutex_unlock(stream->lock);
1877 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1878 silc_mutex_lock(stream->lock);
1879 silc_packet_free(packet);
1880 memset(tmp, 0, sizeof(tmp));
1884 stream->receive_psn++;
1886 silc_buffer_push(&packet->buffer, block_len);
1888 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1889 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1891 /* Dispatch the packet to application */
1892 silc_packet_dispatch(packet);
1895 silc_buffer_reset(&stream->inbuf);
1899 /****************************** Packet Waiting ******************************/
1901 /* Packet wait receive callback */
1903 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1904 SilcPacketStream stream,
1906 void *callback_context,
1907 void *stream_context);
1909 /* Packet waiting callbacks */
1910 static SilcPacketCallbacks silc_packet_wait_cbs =
1912 silc_packet_wait_packet_receive, NULL, NULL
1915 /* Packet waiting context */
1917 SilcMutex wait_lock;
1919 SilcList packet_queue;
1920 unsigned int stopped : 1;
1923 /* Packet wait receive callback */
1926 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1927 SilcPacketStream stream,
1929 void *callback_context,
1930 void *stream_context)
1932 SilcPacketWait pw = callback_context;
1934 /* Signal the waiting thread for a new packet */
1935 silc_mutex_lock(pw->wait_lock);
1938 silc_mutex_unlock(pw->wait_lock);
1942 silc_list_add(pw->packet_queue, packet);
1943 silc_cond_broadcast(pw->wait_cond);
1945 silc_mutex_unlock(pw->wait_lock);
1950 /* Initialize packet waiting */
1952 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1958 pw = silc_calloc(1, sizeof(*pw));
1962 /* Allocate mutex and conditional variable */
1963 if (!silc_mutex_alloc(&pw->wait_lock)) {
1967 if (!silc_cond_alloc(&pw->wait_cond)) {
1968 silc_mutex_free(pw->wait_lock);
1973 /* Link to the packet stream for the requested packet types */
1974 va_start(ap, stream);
1975 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
1979 silc_cond_free(pw->wait_cond);
1980 silc_mutex_free(pw->wait_lock);
1985 /* Initialize packet queue */
1986 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
1991 /* Uninitialize packet waiting */
1993 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
1995 SilcPacketWait pw = waiter;
1998 /* Signal any threads to stop waiting */
1999 silc_mutex_lock(pw->wait_lock);
2001 silc_cond_broadcast(pw->wait_cond);
2002 silc_mutex_unlock(pw->wait_lock);
2004 /* Re-acquire lock and free resources */
2005 silc_mutex_lock(pw->wait_lock);
2006 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2008 /* Free any remaining packets */
2009 silc_list_start(pw->packet_queue);
2010 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2011 silc_packet_free(packet);
2013 silc_mutex_unlock(pw->wait_lock);
2014 silc_cond_free(pw->wait_cond);
2015 silc_mutex_free(pw->wait_lock);
2019 /* Blocks thread until a packet has been received. */
2021 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2023 SilcPacketWait pw = waiter;
2024 SilcBool ret = FALSE;
2026 silc_mutex_lock(pw->wait_lock);
2028 /* Wait here until packet has arrived */
2029 while (silc_list_count(pw->packet_queue) == 0) {
2031 silc_mutex_unlock(pw->wait_lock);
2034 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2038 silc_list_start(pw->packet_queue);
2039 *return_packet = silc_list_get(pw->packet_queue);
2040 silc_list_del(pw->packet_queue, *return_packet);
2042 silc_mutex_unlock(pw->wait_lock);
2044 return ret == TRUE ? 1 : 0;