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);
157 /************************ Static utility functions **************************/
159 /* Injects packet to new stream created with silc_packet_stream_add_remote. */
161 SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
163 SilcPacket packet = context;
164 SilcPacketStream stream = packet->stream;
166 SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
168 silc_mutex_lock(stream->lock);
169 silc_packet_dispatch(packet);
170 silc_mutex_unlock(stream->lock);
173 /* Write data to the stream. Must be called with ps->lock locked. Unlocks
174 the lock inside this function. */
176 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps)
183 stream = ((SilcPacketStream)ps->stream)->stream;
187 if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
189 /* Connectionless UDP stream */
190 while (silc_buffer_len(&ps->outbuf) > 0) {
191 i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
192 ps->remote_udp->remote_port,
193 ps->outbuf.data, silc_buffer_len(&ps->outbuf));
196 silc_buffer_reset(&ps->outbuf);
197 silc_mutex_unlock(ps->lock);
198 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
203 /* Cannot write now, write later. */
204 silc_mutex_unlock(ps->lock);
209 silc_buffer_pull(&ps->outbuf, i);
212 silc_buffer_reset(&ps->outbuf);
213 silc_mutex_unlock(ps->lock);
219 /* Write the data to the stream */
220 while (silc_buffer_len(&ps->outbuf) > 0) {
221 i = silc_stream_write(stream, ps->outbuf.data,
222 silc_buffer_len(&ps->outbuf));
225 silc_buffer_reset(&ps->outbuf);
226 silc_mutex_unlock(ps->lock);
227 SILC_PACKET_CALLBACK_EOS(ps);
233 silc_buffer_reset(&ps->outbuf);
234 silc_mutex_unlock(ps->lock);
235 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
240 /* Cannot write now, write later. */
241 silc_mutex_unlock(ps->lock);
246 silc_buffer_pull(&ps->outbuf, i);
249 silc_buffer_reset(&ps->outbuf);
250 silc_mutex_unlock(ps->lock);
255 /* Reads data from stream. Must be called with the ps->lock locked. If this
256 returns FALSE the lock has been unlocked. If this returns packet stream
257 to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
258 It is returned if the stream is UDP and remote UDP stream exists for
259 the sender of the packet. */
261 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
262 SilcPacketStream *ret_ps)
270 /* Make sure we have fair amount of free space in inbuf */
271 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
272 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
273 SILC_PACKET_DEFAULT_SIZE * 2)) {
274 silc_mutex_unlock(ps->lock);
275 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
279 if (silc_socket_stream_is_udp(stream, &connected)) {
281 /* Connectionless UDP stream, read one UDP packet */
282 char remote_ip[64], tuple[64];
284 SilcPacketStream remote;
286 ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
287 &remote_port, ps->inbuf.tail,
288 silc_buffer_taillen(&ps->inbuf));
291 silc_buffer_reset(&ps->inbuf);
292 silc_mutex_unlock(ps->lock);
293 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
298 /* Cannot read now, do it later. */
299 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
300 silc_mutex_unlock(ps->lock);
304 /* See if remote packet stream exist for this sender */
305 snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
306 silc_mutex_lock(ps->engine->lock);
307 if (silc_hash_table_find(ps->engine->udp_remote, tuple, NULL,
309 /* Found packet stream for this sender, copy the packet */
310 silc_mutex_unlock(ps->engine->lock);
312 SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p",
313 remote_ip, remote_port, remote));
315 silc_mutex_lock(remote->lock);
316 if (ret > silc_buffer_taillen(&remote->inbuf))
317 if (!silc_buffer_realloc(&remote->inbuf, ret)) {
318 silc_mutex_unlock(remote->lock);
319 silc_mutex_unlock(ps->lock);
320 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
324 silc_buffer_put_tail(&remote->inbuf, ps->inbuf.tail, ret);
325 silc_buffer_pull_tail(&remote->inbuf, ret);
328 silc_buffer_reset(&ps->inbuf);
329 silc_mutex_unlock(ps->lock);
332 silc_mutex_unlock(ps->engine->lock);
335 if (!ps->remote_udp) {
336 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
337 if (!ps->remote_udp) {
338 silc_mutex_unlock(ps->lock);
339 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
344 /* Save sender IP and port */
345 silc_free(ps->remote_udp->remote_ip);
346 ps->remote_udp->remote_ip = strdup(remote_ip);
347 ps->remote_udp->remote_port = remote_port;
349 silc_buffer_pull_tail(&ps->inbuf, ret);
354 /* Read data from the stream */
355 ret = silc_stream_read(ps->stream, ps->inbuf.tail,
356 silc_buffer_taillen(&ps->inbuf));
360 silc_buffer_reset(&ps->inbuf);
361 silc_mutex_unlock(ps->lock);
362 SILC_PACKET_CALLBACK_EOS(ps);
368 silc_buffer_reset(&ps->inbuf);
369 silc_mutex_unlock(ps->lock);
370 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
375 /* Cannot read now, do it later. */
376 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
377 silc_mutex_unlock(ps->lock);
381 silc_buffer_pull_tail(&ps->inbuf, ret);
385 /* Our stream IO notifier callback. */
387 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
390 SilcPacketStream remote = NULL, ps = context;
392 silc_mutex_lock(ps->lock);
395 silc_mutex_unlock(ps->lock);
401 case SILC_STREAM_CAN_WRITE:
402 SILC_LOG_DEBUG(("Writing pending data to stream"));
404 if (!silc_buffer_headlen(&ps->outbuf)) {
405 silc_mutex_unlock(ps->lock);
409 /* Write pending data to stream */
410 silc_packet_stream_write(ps);
413 case SILC_STREAM_CAN_READ:
414 SILC_LOG_DEBUG(("Reading data from stream"));
416 /* Read data from stream */
417 if (!silc_packet_stream_read(ps, &remote))
420 /* Now process the data */
422 silc_packet_read_process(ps);
423 silc_mutex_unlock(ps->lock);
425 silc_packet_read_process(remote);
426 silc_mutex_unlock(remote->lock);
431 silc_mutex_unlock(ps->lock);
436 /* Allocate packet */
438 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
442 SILC_LOG_DEBUG(("Packet pool count %d",
443 silc_list_count(engine->packet_pool)));
445 silc_mutex_lock(engine->lock);
447 /* Get packet from freelist or allocate new one. */
448 packet = silc_list_get(engine->packet_pool);
452 silc_mutex_unlock(engine->lock);
454 packet = silc_calloc(1, sizeof(*packet));
458 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
460 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
465 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
466 silc_buffer_reset(&packet->buffer);
471 SILC_LOG_DEBUG(("Get packet %p", packet));
473 /* Delete from freelist */
474 silc_list_del(engine->packet_pool, packet);
476 silc_mutex_unlock(engine->lock);
481 /* UDP remote stream hash table destructor */
483 static void silc_packet_engine_hash_destr(void *key, void *context,
490 /******************************** Packet API ********************************/
492 /* Allocate new packet engine */
495 silc_packet_engine_start(SilcRng rng, SilcBool router,
496 SilcPacketCallbacks *callbacks,
497 void *callback_context)
499 SilcPacketEngine engine;
504 SILC_LOG_DEBUG(("Starting new packet engine"));
508 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
511 engine = silc_calloc(1, sizeof(*engine));
516 engine->local_is_router = router;
517 engine->callbacks = callbacks;
518 engine->callback_context = callback_context;
519 silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
520 silc_mutex_alloc(&engine->lock);
522 /* Allocate packet free list */
523 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
524 for (i = 0; i < 5; i++) {
525 packet = silc_calloc(1, sizeof(*packet));
527 silc_packet_engine_stop(engine);
531 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
533 silc_packet_engine_stop(engine);
536 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
537 silc_buffer_reset(&packet->buffer);
539 silc_list_add(engine->packet_pool, packet);
541 silc_list_start(engine->packet_pool);
546 /* Stop packet engine */
548 void silc_packet_engine_stop(SilcPacketEngine engine)
551 SILC_LOG_DEBUG(("Stopping packet engine"));
561 /* Create new packet stream */
563 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
564 SilcSchedule schedule,
570 SILC_LOG_DEBUG(("Creating new packet stream"));
572 if (!engine || !stream)
575 ps = silc_calloc(1, sizeof(*ps));
581 silc_atomic_init8(&ps->refcnt, 1);
582 silc_mutex_alloc(&ps->lock);
584 /* Allocate buffers */
585 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
587 silc_packet_stream_destroy(ps);
590 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
591 silc_buffer_reset(&ps->inbuf);
592 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
594 silc_packet_stream_destroy(ps);
597 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
598 silc_buffer_reset(&ps->outbuf);
600 /* Initialize packet procesors list */
601 ps->process = silc_dlist_init();
603 silc_packet_stream_destroy(ps);
607 /* Set IO notifier callback */
608 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
611 silc_mutex_lock(engine->lock);
612 silc_list_add(engine->streams, ps);
613 silc_mutex_unlock(engine->lock);
615 /* If this is UDP stream, allocate UDP remote stream hash table */
616 if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
617 engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
618 silc_hash_string_compare, NULL,
619 silc_packet_engine_hash_destr,
625 /* Add new remote packet stream for UDP packet streams */
627 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
628 const char *remote_ip,
629 SilcUInt16 remote_port,
632 SilcPacketEngine engine = stream->engine;
637 SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
638 remote_ip, remote_port, stream));
640 if (!stream || !remote_ip || !remote_port)
643 if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
644 SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
648 ps = silc_calloc(1, sizeof(*ps));
653 silc_atomic_init8(&ps->refcnt, 1);
654 silc_mutex_alloc(&ps->lock);
656 /* Set the UDP packet stream as underlaying stream */
657 silc_packet_stream_ref(stream);
658 ps->stream = (SilcStream)stream;
661 /* Allocate buffers */
662 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
664 silc_packet_stream_destroy(ps);
667 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
668 silc_buffer_reset(&ps->inbuf);
669 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
671 silc_packet_stream_destroy(ps);
674 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
675 silc_buffer_reset(&ps->outbuf);
677 /* Initialize packet procesors list */
678 ps->process = silc_dlist_init();
680 silc_packet_stream_destroy(ps);
684 /* Add to engine with this IP and port pair */
685 tuple = silc_format("%d%s", remote_port, remote_ip);
686 silc_mutex_lock(engine->lock);
687 if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
688 silc_mutex_unlock(engine->lock);
689 silc_packet_stream_destroy(ps);
692 silc_mutex_unlock(engine->lock);
694 /* Save remote IP and port pair */
695 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
696 if (!ps->remote_udp) {
697 silc_packet_stream_destroy(ps);
700 ps->remote_udp->remote_port = remote_port;
701 ps->remote_udp->remote_ip = strdup(remote_ip);
702 if (!ps->remote_udp->remote_ip) {
703 silc_packet_stream_destroy(ps);
708 /* Inject packet to the new stream */
710 silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
711 silc_packet_stream_inject_packet, packet,
718 /* Destroy packet stream */
720 void silc_packet_stream_destroy(SilcPacketStream stream)
725 if (silc_atomic_get_int8(&stream->refcnt) > 1) {
726 stream->destroyed = TRUE;
730 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
733 /* Delete from engine */
734 silc_mutex_lock(stream->engine->lock);
735 silc_list_del(stream->engine->streams, stream);
736 silc_mutex_unlock(stream->engine->lock);
738 /* Destroy the underlaying stream */
740 silc_stream_destroy(stream->stream);
742 /* Delete from UDP remote hash table */
744 snprintf(tuple, sizeof(tuple), "%d%s", stream->remote_udp->remote_port,
745 stream->remote_udp->remote_ip);
746 silc_mutex_lock(stream->engine->lock);
747 silc_hash_table_del(stream->engine->udp_remote, tuple);
748 silc_mutex_unlock(stream->engine->lock);
750 silc_free(stream->remote_udp->remote_ip);
751 silc_free(stream->remote_udp);
753 /* Unreference the underlaying packet stream */
754 silc_packet_stream_unref((SilcPacketStream)stream->stream);
757 /* Clear and free buffers */
758 silc_buffer_clear(&stream->inbuf);
759 silc_buffer_clear(&stream->outbuf);
760 silc_buffer_purge(&stream->inbuf);
761 silc_buffer_purge(&stream->outbuf);
763 if (stream->process) {
765 silc_dlist_start(stream->process);
766 while ((p = silc_dlist_get(stream->process))) {
769 silc_dlist_del(stream->process, p);
771 silc_dlist_uninit(stream->process);
776 silc_atomic_uninit8(&stream->refcnt);
777 silc_mutex_free(stream->lock);
781 /* Marks as router stream */
783 void silc_packet_stream_set_router(SilcPacketStream stream)
785 stream->is_router = TRUE;
788 /* Mark to include IV in ciphertext */
790 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
792 stream->iv_included = TRUE;
795 /* Links `callbacks' to `stream' for specified packet types */
797 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
798 SilcPacketCallbacks *callbacks,
799 void *callback_context,
800 int priority, va_list ap)
802 SilcPacketProcess p, e;
803 SilcInt32 packet_type;
806 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
810 if (!callbacks->packet_receive)
813 p = silc_calloc(1, sizeof(*p));
817 p->priority = priority;
818 p->callbacks = callbacks;
819 p->callback_context = callback_context;
821 silc_mutex_lock(stream->lock);
823 if (!stream->process) {
824 stream->process = silc_dlist_init();
825 if (!stream->process) {
826 silc_mutex_unlock(stream->lock);
831 /* According to priority set the procesor to correct position. First
832 entry has the highest priority */
833 silc_dlist_start(stream->process);
834 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
835 if (p->priority > e->priority) {
836 silc_dlist_insert(stream->process, p);
841 silc_dlist_add(stream->process, p);
843 /* Get packet types to process */
846 packet_type = va_arg(ap, SilcInt32);
848 if (packet_type == SILC_PACKET_ANY)
851 if (packet_type == -1)
854 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
856 silc_mutex_unlock(stream->lock);
860 p->types[i - 1] = (SilcPacketType)packet_type;
866 silc_mutex_unlock(stream->lock);
868 silc_packet_stream_ref(stream);
873 /* Links `callbacks' to `stream' for specified packet types */
875 SilcBool silc_packet_stream_link(SilcPacketStream stream,
876 SilcPacketCallbacks *callbacks,
877 void *callback_context,
883 va_start(ap, priority);
884 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
891 /* Unlinks `callbacks' from `stream'. */
893 void silc_packet_stream_unlink(SilcPacketStream stream,
894 SilcPacketCallbacks *callbacks,
895 void *callback_context)
899 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
902 silc_mutex_lock(stream->lock);
904 silc_dlist_start(stream->process);
905 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
906 if (p->callbacks == callbacks &&
907 p->callback_context == callback_context) {
908 silc_dlist_del(stream->process, p);
914 if (!silc_dlist_count(stream->process)) {
915 silc_dlist_uninit(stream->process);
916 stream->process = NULL;
919 silc_mutex_unlock(stream->lock);
921 silc_packet_stream_unref(stream);
924 /* Returns TRUE if stream is UDP stream */
926 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream)
928 return stream->udp || silc_socket_stream_is_udp(stream->stream, NULL);
931 /* Return packet sender IP and port for UDP packet stream */
933 SilcBool silc_packet_get_sender(SilcPacket packet,
934 const char **sender_ip,
935 SilcUInt16 *sender_port)
937 if (!packet->stream->remote_udp)
940 *sender_ip = packet->stream->remote_udp->remote_ip;
941 *sender_port = packet->stream->remote_udp->remote_port;
946 /* Reference packet stream */
948 void silc_packet_stream_ref(SilcPacketStream stream)
950 silc_atomic_add_int8(&stream->refcnt, 1);
953 /* Unreference packet stream */
955 void silc_packet_stream_unref(SilcPacketStream stream)
957 if (silc_atomic_sub_int8(&stream->refcnt, 1) == 0)
958 silc_packet_stream_destroy(stream);
963 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
965 return stream->engine;
968 /* Set application context for packet stream */
970 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
972 silc_mutex_lock(stream->lock);
973 stream->stream_context = stream_context;
974 silc_mutex_unlock(stream->lock);
977 /* Return application context from packet stream */
979 void *silc_packet_get_context(SilcPacketStream stream)
982 silc_mutex_lock(stream->lock);
983 context = stream->stream_context;
984 silc_mutex_unlock(stream->lock);
988 /* Change underlaying stream */
990 void silc_packet_stream_set_stream(SilcPacketStream ps,
992 SilcSchedule schedule)
995 silc_stream_set_notifier(ps->stream, schedule, NULL, NULL);
997 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
1000 /* Return underlaying stream */
1002 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
1004 return stream->stream;
1007 /* Set ciphers for packet stream */
1009 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
1012 SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
1014 silc_mutex_lock(stream->lock);
1016 /* In case IV Included is set, save the old key */
1017 if (stream->iv_included) {
1018 if (stream->send_key[1]) {
1019 silc_cipher_free(stream->send_key[1]);
1020 stream->send_key[1] = stream->send_key[0];
1022 if (stream->receive_key[1]) {
1023 silc_cipher_free(stream->receive_key[1]);
1024 stream->receive_key[1] = stream->receive_key[0];
1027 if (stream->send_key[0])
1028 silc_cipher_free(stream->send_key[0]);
1029 if (stream->send_key[1])
1030 silc_cipher_free(stream->receive_key[0]);
1033 stream->send_key[0] = send;
1034 stream->receive_key[0] = receive;
1036 silc_mutex_unlock(stream->lock);
1039 /* Return current ciphers from packet stream */
1041 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
1042 SilcCipher *receive)
1044 if (!stream->send_key[0] && !stream->receive_key[0])
1047 silc_mutex_lock(stream->lock);
1050 *send = stream->send_key[0];
1052 *receive = stream->receive_key[0];
1054 silc_mutex_unlock(stream->lock);
1059 /* Set HMACs for packet stream */
1061 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
1064 SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
1066 silc_mutex_lock(stream->lock);
1068 /* In case IV Included is set, save the old HMAC */
1069 if (stream->iv_included) {
1070 if (stream->send_hmac[1]) {
1071 silc_hmac_free(stream->send_hmac[1]);
1072 stream->send_hmac[1] = stream->send_hmac[0];
1074 if (stream->receive_hmac[1]) {
1075 silc_hmac_free(stream->receive_hmac[1]);
1076 stream->receive_hmac[1] = stream->receive_hmac[0];
1079 if (stream->send_hmac[0])
1080 silc_hmac_free(stream->send_hmac[0]);
1081 if (stream->receive_hmac[0])
1082 silc_hmac_free(stream->receive_hmac[0]);
1085 stream->send_hmac[0] = send;
1086 stream->receive_hmac[0] = receive;
1088 silc_mutex_unlock(stream->lock);
1091 /* Return current HMACs from packet stream */
1093 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
1096 if (!stream->send_hmac[0] && !stream->receive_hmac[0])
1099 silc_mutex_lock(stream->lock);
1102 *send = stream->send_hmac[0];
1104 *receive = stream->receive_hmac[0];
1106 silc_mutex_unlock(stream->lock);
1111 /* Set SILC IDs to packet stream */
1113 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1114 SilcIdType src_id_type, const void *src_id,
1115 SilcIdType dst_id_type, const void *dst_id)
1118 unsigned char tmp[32];
1120 if (!src_id && !dst_id)
1123 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1125 silc_mutex_lock(stream->lock);
1128 silc_free(stream->src_id);
1129 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1130 silc_mutex_unlock(stream->lock);
1133 stream->src_id = silc_memdup(tmp, len);
1134 if (!stream->src_id) {
1135 silc_mutex_unlock(stream->lock);
1138 stream->src_id_type = src_id_type;
1139 stream->src_id_len = len;
1143 silc_free(stream->dst_id);
1144 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1145 silc_mutex_unlock(stream->lock);
1148 stream->dst_id = silc_memdup(tmp, len);
1149 if (!stream->dst_id) {
1150 silc_mutex_unlock(stream->lock);
1153 stream->dst_id_type = dst_id_type;
1154 stream->dst_id_len = len;
1157 silc_mutex_unlock(stream->lock);
1162 /* Adds Security ID (SID) */
1164 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1166 if (!stream->iv_included)
1169 SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1177 void silc_packet_free(SilcPacket packet)
1179 SilcPacketStream stream = packet->stream;
1181 SILC_LOG_DEBUG(("Freeing packet %p", packet));
1183 /* Check for double free */
1184 SILC_ASSERT(packet->stream != NULL);
1186 packet->stream = NULL;
1187 packet->src_id = packet->dst_id = NULL;
1188 silc_buffer_reset(&packet->buffer);
1190 silc_mutex_lock(stream->engine->lock);
1192 /* Put the packet back to freelist */
1193 silc_list_add(stream->engine->packet_pool, packet);
1194 if (silc_list_count(stream->engine->packet_pool) == 1)
1195 silc_list_start(stream->engine->packet_pool);
1197 silc_mutex_unlock(stream->engine->lock);
1200 /****************************** Packet Sending ******************************/
1202 /* Prepare outgoing data buffer for packet sending. Returns the
1203 pointer to that buffer into the `packet'. */
1205 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1210 unsigned char *oldptr;
1211 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1215 /* Allocate more space if needed */
1216 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
1217 if (!silc_buffer_realloc(&stream->outbuf,
1218 silc_buffer_truelen(&stream->outbuf) + totlen))
1222 /* Pull data area for the new packet, and return pointer to the start of
1223 the data area and save the pointer in to the `packet'. MAC is pulled
1224 later after it's computed. */
1225 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1226 silc_buffer_set(packet, oldptr, totlen);
1227 silc_buffer_push_tail(packet, mac_len);
1232 /* Internal routine to send packet */
1234 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
1235 SilcPacketType type,
1236 SilcPacketFlags flags,
1237 SilcIdType src_id_type,
1238 unsigned char *src_id,
1239 SilcUInt32 src_id_len,
1240 SilcIdType dst_id_type,
1241 unsigned char *dst_id,
1242 SilcUInt32 dst_id_len,
1243 const unsigned char *data,
1244 SilcUInt32 data_len,
1248 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1249 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1250 int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
1251 SilcBufferStruct packet;
1253 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1254 "data len %d", silc_get_packet_name(type), stream->send_psn,
1255 flags, src_id_type, dst_id_type, data_len));
1257 /* Get the true length of the packet. This is saved as payload length
1258 into the packet header. This does not include the length of the
1260 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1261 src_id_len + dst_id_len));
1262 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1263 src_id_len + dst_id_len);
1265 /* If IV is included, the SID, IV and sequence number is added to packet */
1266 if (stream->iv_included && cipher) {
1267 psnlen = sizeof(psn);
1268 ivlen = block_len + 1;
1269 iv[0] = stream->sid;
1270 memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1273 /* We automatically figure out the packet structure from the packet
1274 type and flags, and calculate correct length. Private messages with
1275 private keys and channel messages are special packets as their
1276 payload is encrypted already. */
1277 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1278 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1279 type == SILC_PACKET_CHANNEL_MESSAGE) {
1281 /* Padding is calculated from header + IDs */
1282 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1283 psnlen), block_len, padlen);
1285 /* Length to encrypt, header + IDs + padding. */
1286 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1290 /* Padding is calculated from true length of the packet */
1291 if (flags & SILC_PACKET_FLAG_LONG_PAD)
1292 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1294 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1296 enclen += padlen + psnlen;
1299 /* Remove implementation specific flags */
1300 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1302 /* Get random padding */
1303 for (i = 0; i < padlen; i++) tmppad[i] =
1304 silc_rng_get_byte_fast(stream->engine->rng);
1306 silc_mutex_lock(stream->lock);
1308 /* Get packet pointer from the outgoing buffer */
1309 if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
1311 silc_mutex_unlock(stream->lock);
1315 SILC_PUT32_MSB(stream->send_psn, psn);
1317 /* Create the packet. This creates the SILC header, adds padding, and
1318 the actual packet data. */
1319 i = silc_buffer_format(&packet,
1320 SILC_STR_DATA(iv, ivlen),
1321 SILC_STR_DATA(psn, psnlen),
1322 SILC_STR_UI_SHORT(truelen),
1323 SILC_STR_UI_CHAR(flags),
1324 SILC_STR_UI_CHAR(type),
1325 SILC_STR_UI_CHAR(padlen),
1326 SILC_STR_UI_CHAR(0),
1327 SILC_STR_UI_CHAR(src_id_len),
1328 SILC_STR_UI_CHAR(dst_id_len),
1329 SILC_STR_UI_CHAR(src_id_type),
1330 SILC_STR_DATA(src_id, src_id_len),
1331 SILC_STR_UI_CHAR(dst_id_type),
1332 SILC_STR_DATA(dst_id, dst_id_len),
1333 SILC_STR_DATA(tmppad, padlen),
1334 SILC_STR_DATA(data, data_len),
1337 silc_mutex_unlock(stream->lock);
1341 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1342 silc_buffer_data(&packet), silc_buffer_len(&packet));
1344 /* Encrypt the packet */
1346 SILC_LOG_DEBUG(("Encrypting packet"));
1347 if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
1348 packet.data + ivlen, enclen, NULL)) {
1349 SILC_LOG_ERROR(("Packet encryption failed"));
1350 silc_mutex_unlock(stream->lock);
1359 /* MAC is computed from the entire encrypted packet data, and put
1360 to the end of the packet. */
1361 silc_hmac_init(hmac);
1362 silc_hmac_update(hmac, psn, sizeof(psn));
1363 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1364 silc_hmac_final(hmac, packet.tail, &mac_len);
1365 silc_buffer_pull_tail(&packet, mac_len);
1369 /* Write the packet to the stream */
1370 return silc_packet_stream_write(stream);
1373 /* Sends a packet */
1375 SilcBool silc_packet_send(SilcPacketStream stream,
1376 SilcPacketType type, SilcPacketFlags flags,
1377 const unsigned char *data, SilcUInt32 data_len)
1379 return silc_packet_send_raw(stream, type, flags,
1380 stream->src_id_type,
1383 stream->dst_id_type,
1387 stream->send_key[0],
1388 stream->send_hmac[0]);
1391 /* Sends a packet, extended routine */
1393 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1394 SilcPacketType type, SilcPacketFlags flags,
1395 SilcIdType src_id_type, void *src_id,
1396 SilcIdType dst_id_type, void *dst_id,
1397 const unsigned char *data, SilcUInt32 data_len,
1398 SilcCipher cipher, SilcHmac hmac)
1400 unsigned char src_id_data[32], dst_id_data[32];
1401 SilcUInt32 src_id_len, dst_id_len;
1404 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1405 sizeof(src_id_data), &src_id_len))
1408 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1409 sizeof(dst_id_data), &dst_id_len))
1412 return silc_packet_send_raw(stream, type, flags,
1413 src_id ? src_id_type : stream->src_id_type,
1414 src_id ? src_id_data : stream->src_id,
1415 src_id ? src_id_len : stream->src_id_len,
1416 dst_id ? dst_id_type : stream->dst_id_type,
1417 dst_id ? dst_id_data : stream->dst_id,
1418 dst_id ? dst_id_len : stream->dst_id_len,
1420 cipher ? cipher : stream->send_key[0],
1421 hmac ? hmac : stream->send_hmac[0]);
1424 /* Sends packet after formatting the arguments to buffer */
1426 SilcBool silc_packet_send_va(SilcPacketStream stream,
1427 SilcPacketType type, SilcPacketFlags flags, ...)
1429 SilcBufferStruct buf;
1433 va_start(va, flags);
1435 memset(&buf, 0, sizeof(buf));
1436 if (silc_buffer_format_vp(&buf, va) < 0) {
1441 ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1442 silc_buffer_len(&buf));
1444 silc_buffer_purge(&buf);
1450 /* Sends packet after formatting the arguments to buffer, extended routine */
1452 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1453 SilcPacketType type, SilcPacketFlags flags,
1454 SilcIdType src_id_type, void *src_id,
1455 SilcIdType dst_id_type, void *dst_id,
1456 SilcCipher cipher, SilcHmac hmac, ...)
1458 SilcBufferStruct buf;
1464 memset(&buf, 0, sizeof(buf));
1465 if (silc_buffer_format_vp(&buf, va) < 0) {
1470 ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1471 dst_id_type, dst_id, silc_buffer_data(&buf),
1472 silc_buffer_len(&buf), cipher, hmac);
1474 silc_buffer_purge(&buf);
1480 /***************************** Packet Receiving *****************************/
1482 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1484 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1485 const unsigned char *data,
1486 SilcUInt32 data_len,
1487 const unsigned char *packet_mac,
1488 const unsigned char *packet_seq,
1489 SilcUInt32 sequence)
1493 unsigned char mac[32], psn[4];
1496 SILC_LOG_DEBUG(("Verifying MAC"));
1498 /* Compute HMAC of packet */
1499 silc_hmac_init(hmac);
1502 SILC_PUT32_MSB(sequence, psn);
1503 silc_hmac_update(hmac, psn, 4);
1505 silc_hmac_update(hmac, packet_seq, 4);
1507 silc_hmac_update(hmac, data, data_len);
1508 silc_hmac_final(hmac, mac, &mac_len);
1510 /* Compare the MAC's */
1511 if (memcmp(packet_mac, mac, mac_len)) {
1512 SILC_LOG_DEBUG(("MAC failed"));
1516 SILC_LOG_DEBUG(("MAC is Ok"));
1522 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1523 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1525 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1526 SilcUInt32 sequence, SilcBuffer buffer,
1529 if (normal == TRUE) {
1531 /* Decrypt rest of the packet */
1532 SILC_LOG_DEBUG(("Decrypting the packet"));
1533 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1534 silc_buffer_len(buffer), NULL))
1540 /* Decrypt rest of the header plus padding */
1543 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1545 SILC_LOG_DEBUG(("Decrypting the header"));
1547 /* Padding length + src id len + dst id len + header length - 16
1548 bytes already decrypted, gives the rest of the encrypted packet */
1549 silc_buffer_push(buffer, block_len);
1550 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1551 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1553 silc_buffer_pull(buffer, block_len);
1555 if (len > silc_buffer_len(buffer)) {
1556 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1560 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1569 /* Parses the packet. This is called when a whole packet is ready to be
1570 parsed. The buffer sent must be already decrypted before calling this
1573 static inline SilcBool silc_packet_parse(SilcPacket packet)
1575 SilcBuffer buffer = &packet->buffer;
1576 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1577 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1580 SILC_LOG_DEBUG(("Parsing incoming packet"));
1582 /* Parse the buffer. This parses the SILC header of the packet. */
1583 ret = silc_buffer_unformat(buffer,
1586 SILC_STR_UI_CHAR(&src_id_len),
1587 SILC_STR_UI_CHAR(&dst_id_len),
1588 SILC_STR_UI_CHAR(&src_id_type),
1591 if (!packet->stream->udp &&
1592 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1593 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1597 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1598 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1599 if (!packet->stream->udp &&
1600 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1601 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1602 packet->src_id_len, packet->dst_id_len));
1606 ret = silc_buffer_unformat(buffer,
1608 SILC_STR_DATA(&packet->src_id, src_id_len),
1609 SILC_STR_UI_CHAR(&dst_id_type),
1610 SILC_STR_DATA(&packet->dst_id, dst_id_len),
1611 SILC_STR_OFFSET(padlen),
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 (src_id_type > SILC_ID_CHANNEL ||
1621 dst_id_type > SILC_ID_CHANNEL) {
1622 if (!packet->stream->udp &&
1623 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1624 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1625 src_id_type, dst_id_type));
1629 packet->src_id_len = src_id_len;
1630 packet->dst_id_len = dst_id_len;
1631 packet->src_id_type = src_id_type;
1632 packet->dst_id_type = dst_id_type;
1634 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1635 silc_buffer_len(buffer)), buffer->head,
1636 silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1638 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1639 silc_get_packet_name(packet->type)));
1644 /* Dispatch packet to application. Called with stream->lock locked. */
1646 static void silc_packet_dispatch(SilcPacket packet)
1648 SilcPacketStream stream = packet->stream;
1649 SilcPacketProcess p;
1650 SilcBool default_sent = FALSE;
1653 /* Dispatch packet to all packet processors that want it */
1655 if (!stream->process) {
1656 /* Send to default processor as no others exist */
1657 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1658 silc_mutex_unlock(stream->lock);
1659 if (!stream->engine->callbacks->
1660 packet_receive(stream->engine, stream, packet,
1661 stream->engine->callback_context,
1662 stream->stream_context))
1663 silc_packet_free(packet);
1664 silc_mutex_lock(stream->lock);
1668 silc_dlist_start(stream->process);
1669 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1671 /* If priority is 0 or less, we send to default processor first
1672 because default processor has 0 priority */
1673 if (!default_sent && p->priority <= 0) {
1674 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1675 default_sent = TRUE;
1676 silc_mutex_unlock(stream->lock);
1677 if (stream->engine->callbacks->
1678 packet_receive(stream->engine, stream, packet,
1679 stream->engine->callback_context,
1680 stream->stream_context)) {
1681 silc_mutex_lock(stream->lock);
1684 silc_mutex_lock(stream->lock);
1687 /* Send to processor */
1689 /* Send all packet types */
1690 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1691 silc_mutex_unlock(stream->lock);
1692 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1693 p->callback_context,
1694 stream->stream_context)) {
1695 silc_mutex_lock(stream->lock);
1698 silc_mutex_lock(stream->lock);
1700 /* Send specific types */
1701 for (pt = p->types; *pt; pt++) {
1702 if (*pt != packet->type)
1704 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1705 silc_mutex_unlock(stream->lock);
1706 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1707 p->callback_context,
1708 stream->stream_context)) {
1709 silc_mutex_lock(stream->lock);
1712 silc_mutex_lock(stream->lock);
1718 if (!default_sent) {
1719 /* Send to default processor as it has not been sent yet */
1720 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1721 silc_mutex_unlock(stream->lock);
1722 if (stream->engine->callbacks->
1723 packet_receive(stream->engine, stream, packet,
1724 stream->engine->callback_context,
1725 stream->stream_context)) {
1726 silc_mutex_lock(stream->lock);
1729 silc_mutex_lock(stream->lock);
1732 /* If we got here, no one wanted the packet, so drop it */
1733 silc_packet_free(packet);
1736 /* Process incoming data and parse packets. Called with stream->lock
1739 static void silc_packet_read_process(SilcPacketStream stream)
1745 SilcUInt16 packetlen;
1746 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1747 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1748 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1752 /* Parse the packets from the data */
1753 while (silc_buffer_len(&stream->inbuf) > 0) {
1755 cipher = stream->receive_key[0];
1756 hmac = stream->receive_hmac[0];
1759 if (silc_buffer_len(&stream->inbuf) <
1760 (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1761 SILC_PACKET_MIN_HEADER_LEN)) {
1762 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1767 mac_len = silc_hmac_len(hmac);
1771 /* Decrypt first block of the packet to get the length field out */
1773 block_len = silc_cipher_get_block_len(cipher);
1775 if (stream->iv_included) {
1776 /* SID, IV and sequence number is included in the ciphertext */
1777 sid = (SilcUInt8)stream->inbuf.data[0];
1778 memcpy(iv, stream->inbuf.data + 1, block_len);
1779 ivlen = block_len + 1;
1782 /* Check SID, and get correct decryption key */
1783 if (sid != stream->sid) {
1784 /* If SID is recent get the previous key and use it */
1785 if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1786 stream->receive_key[1] && !stream->receive_hmac[1]) {
1787 cipher = stream->receive_key[1];
1788 hmac = stream->receive_hmac[1];
1790 /* The SID is unknown, drop rest of the data in buffer */
1791 SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1793 silc_mutex_unlock(stream->lock);
1794 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1795 silc_mutex_lock(stream->lock);
1796 silc_buffer_reset(&stream->inbuf);
1801 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1804 silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1808 if (stream->iv_included) {
1809 /* Take sequence number from packet */
1810 packet_seq = header;
1814 block_len = SILC_PACKET_MIN_HEADER_LEN;
1815 header = stream->inbuf.data;
1818 /* Get packet length and full packet length with padding */
1819 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1822 if (packetlen < SILC_PACKET_MIN_LEN) {
1823 if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
1824 SILC_LOG_ERROR(("Received too short packet"));
1825 silc_mutex_unlock(stream->lock);
1826 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1827 silc_mutex_lock(stream->lock);
1828 memset(tmp, 0, sizeof(tmp));
1829 silc_buffer_reset(&stream->inbuf);
1833 if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1834 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1836 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1837 memset(tmp, 0, sizeof(tmp));
1841 /* Check MAC of the packet */
1842 if (!silc_packet_check_mac(hmac, stream->inbuf.data,
1844 stream->inbuf.data + ivlen + paddedlen,
1845 packet_seq, stream->receive_psn)) {
1846 silc_mutex_unlock(stream->lock);
1847 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1848 silc_mutex_lock(stream->lock);
1849 memset(tmp, 0, sizeof(tmp));
1850 silc_buffer_reset(&stream->inbuf);
1855 packet = silc_packet_alloc(stream->engine);
1857 silc_mutex_unlock(stream->lock);
1858 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1859 silc_mutex_lock(stream->lock);
1860 memset(tmp, 0, sizeof(tmp));
1861 silc_buffer_reset(&stream->inbuf);
1864 packet->stream = stream;
1866 /* Allocate more space to packet buffer, if needed */
1867 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1868 if (!silc_buffer_realloc(&packet->buffer,
1869 silc_buffer_truelen(&packet->buffer) +
1871 silc_buffer_truelen(&packet->buffer)))) {
1872 silc_mutex_unlock(stream->lock);
1873 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1874 silc_mutex_lock(stream->lock);
1875 silc_packet_free(packet);
1876 memset(tmp, 0, sizeof(tmp));
1877 silc_buffer_reset(&stream->inbuf);
1882 /* Parse packet header */
1883 packet->flags = (SilcPacketFlags)header[2];
1884 packet->type = (SilcPacketType)header[3];
1886 if (stream->engine->local_is_router) {
1887 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1888 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1890 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1891 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1892 stream->is_router == TRUE))
1895 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1896 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1898 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1902 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1903 stream->receive_psn, paddedlen + ivlen + mac_len),
1904 stream->inbuf.data, paddedlen + ivlen + mac_len);
1906 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1907 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1908 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1909 silc_buffer_pull(&packet->buffer, block_len - psnlen);
1910 silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1911 psnlen + (block_len - psnlen)),
1912 paddedlen - ivlen - psnlen - (block_len - psnlen));
1914 silc_cipher_set_iv(cipher, iv);
1915 ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1916 &packet->buffer, normal);
1918 silc_mutex_unlock(stream->lock);
1919 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1920 silc_mutex_lock(stream->lock);
1921 silc_packet_free(packet);
1922 memset(tmp, 0, sizeof(tmp));
1926 stream->receive_psn++;
1928 silc_buffer_push(&packet->buffer, block_len);
1930 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1931 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1933 /* Parse the packet */
1934 if (!silc_packet_parse(packet)) {
1935 silc_mutex_unlock(stream->lock);
1936 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1937 silc_mutex_lock(stream->lock);
1938 silc_packet_free(packet);
1939 memset(tmp, 0, sizeof(tmp));
1943 /* Dispatch the packet to application */
1944 silc_packet_dispatch(packet);
1947 silc_buffer_reset(&stream->inbuf);
1951 /****************************** Packet Waiting ******************************/
1953 /* Packet wait receive callback */
1955 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1956 SilcPacketStream stream,
1958 void *callback_context,
1959 void *stream_context);
1961 /* Packet waiting callbacks */
1962 static SilcPacketCallbacks silc_packet_wait_cbs =
1964 silc_packet_wait_packet_receive, NULL, NULL
1967 /* Packet waiting context */
1969 SilcMutex wait_lock;
1971 SilcList packet_queue;
1972 unsigned int stopped : 1;
1975 /* Packet wait receive callback */
1978 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1979 SilcPacketStream stream,
1981 void *callback_context,
1982 void *stream_context)
1984 SilcPacketWait pw = callback_context;
1986 /* Signal the waiting thread for a new packet */
1987 silc_mutex_lock(pw->wait_lock);
1990 silc_mutex_unlock(pw->wait_lock);
1994 silc_list_add(pw->packet_queue, packet);
1995 silc_cond_broadcast(pw->wait_cond);
1997 silc_mutex_unlock(pw->wait_lock);
2002 /* Initialize packet waiting */
2004 void *silc_packet_wait_init(SilcPacketStream stream, ...)
2010 pw = silc_calloc(1, sizeof(*pw));
2014 /* Allocate mutex and conditional variable */
2015 if (!silc_mutex_alloc(&pw->wait_lock)) {
2019 if (!silc_cond_alloc(&pw->wait_cond)) {
2020 silc_mutex_free(pw->wait_lock);
2025 /* Link to the packet stream for the requested packet types */
2026 va_start(ap, stream);
2027 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2031 silc_cond_free(pw->wait_cond);
2032 silc_mutex_free(pw->wait_lock);
2037 /* Initialize packet queue */
2038 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2043 /* Uninitialize packet waiting */
2045 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2047 SilcPacketWait pw = waiter;
2050 /* Signal any threads to stop waiting */
2051 silc_mutex_lock(pw->wait_lock);
2053 silc_cond_broadcast(pw->wait_cond);
2054 silc_mutex_unlock(pw->wait_lock);
2056 /* Re-acquire lock and free resources */
2057 silc_mutex_lock(pw->wait_lock);
2058 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2060 /* Free any remaining packets */
2061 silc_list_start(pw->packet_queue);
2062 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2063 silc_packet_free(packet);
2065 silc_mutex_unlock(pw->wait_lock);
2066 silc_cond_free(pw->wait_cond);
2067 silc_mutex_free(pw->wait_lock);
2071 /* Blocks thread until a packet has been received. */
2073 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2075 SilcPacketWait pw = waiter;
2076 SilcBool ret = FALSE;
2078 silc_mutex_lock(pw->wait_lock);
2080 /* Wait here until packet has arrived */
2081 while (silc_list_count(pw->packet_queue) == 0) {
2083 silc_mutex_unlock(pw->wait_lock);
2086 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2090 silc_list_start(pw->packet_queue);
2091 *return_packet = silc_list_get(pw->packet_queue);
2092 silc_list_del(pw->packet_queue, *return_packet);
2094 silc_mutex_unlock(pw->wait_lock);
2096 return ret == TRUE ? 1 : 0;