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 /* Return packet sender IP and port for UDP packet stream */
926 SilcBool silc_packet_get_sender(SilcPacket packet,
927 const char **sender_ip,
928 SilcUInt16 *sender_port)
930 if (!packet->stream->remote_udp)
933 *sender_ip = packet->stream->remote_udp->remote_ip;
934 *sender_port = packet->stream->remote_udp->remote_port;
939 /* Reference packet stream */
941 void silc_packet_stream_ref(SilcPacketStream stream)
943 silc_atomic_add_int8(&stream->refcnt, 1);
946 /* Unreference packet stream */
948 void silc_packet_stream_unref(SilcPacketStream stream)
950 if (silc_atomic_sub_int8(&stream->refcnt, 1) == 0)
951 silc_packet_stream_destroy(stream);
956 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
958 return stream->engine;
961 /* Set application context for packet stream */
963 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
965 silc_mutex_lock(stream->lock);
966 stream->stream_context = stream_context;
967 silc_mutex_unlock(stream->lock);
970 /* Return application context from packet stream */
972 void *silc_packet_get_context(SilcPacketStream stream)
975 silc_mutex_lock(stream->lock);
976 context = stream->stream_context;
977 silc_mutex_unlock(stream->lock);
981 /* Change underlaying stream */
983 void silc_packet_stream_set_stream(SilcPacketStream ps,
985 SilcSchedule schedule)
988 silc_stream_set_notifier(ps->stream, schedule, NULL, NULL);
990 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
993 /* Return underlaying stream */
995 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
997 return stream->stream;
1000 /* Set ciphers for packet stream */
1002 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
1005 SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
1007 silc_mutex_lock(stream->lock);
1009 /* In case IV Included is set, save the old key */
1010 if (stream->iv_included) {
1011 if (stream->send_key[1]) {
1012 silc_cipher_free(stream->send_key[1]);
1013 stream->send_key[1] = stream->send_key[0];
1015 if (stream->receive_key[1]) {
1016 silc_cipher_free(stream->receive_key[1]);
1017 stream->receive_key[1] = stream->receive_key[0];
1020 if (stream->send_key[0])
1021 silc_cipher_free(stream->send_key[0]);
1022 if (stream->send_key[1])
1023 silc_cipher_free(stream->receive_key[0]);
1026 stream->send_key[0] = send;
1027 stream->receive_key[0] = receive;
1029 silc_mutex_unlock(stream->lock);
1032 /* Return current ciphers from packet stream */
1034 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
1035 SilcCipher *receive)
1037 if (!stream->send_key[0] && !stream->receive_key[0])
1040 silc_mutex_lock(stream->lock);
1043 *send = stream->send_key[0];
1045 *receive = stream->receive_key[0];
1047 silc_mutex_unlock(stream->lock);
1052 /* Set HMACs for packet stream */
1054 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
1057 SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
1059 silc_mutex_lock(stream->lock);
1061 /* In case IV Included is set, save the old HMAC */
1062 if (stream->iv_included) {
1063 if (stream->send_hmac[1]) {
1064 silc_hmac_free(stream->send_hmac[1]);
1065 stream->send_hmac[1] = stream->send_hmac[0];
1067 if (stream->receive_hmac[1]) {
1068 silc_hmac_free(stream->receive_hmac[1]);
1069 stream->receive_hmac[1] = stream->receive_hmac[0];
1072 if (stream->send_hmac[0])
1073 silc_hmac_free(stream->send_hmac[0]);
1074 if (stream->receive_hmac[0])
1075 silc_hmac_free(stream->receive_hmac[0]);
1078 stream->send_hmac[0] = send;
1079 stream->receive_hmac[0] = receive;
1081 silc_mutex_unlock(stream->lock);
1084 /* Return current HMACs from packet stream */
1086 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
1089 if (!stream->send_hmac[0] && !stream->receive_hmac[0])
1092 silc_mutex_lock(stream->lock);
1095 *send = stream->send_hmac[0];
1097 *receive = stream->receive_hmac[0];
1099 silc_mutex_unlock(stream->lock);
1104 /* Set SILC IDs to packet stream */
1106 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1107 SilcIdType src_id_type, const void *src_id,
1108 SilcIdType dst_id_type, const void *dst_id)
1111 unsigned char tmp[32];
1113 if (!src_id && !dst_id)
1116 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1118 silc_mutex_lock(stream->lock);
1121 silc_free(stream->src_id);
1122 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1123 silc_mutex_unlock(stream->lock);
1126 stream->src_id = silc_memdup(tmp, len);
1127 if (!stream->src_id) {
1128 silc_mutex_unlock(stream->lock);
1131 stream->src_id_type = src_id_type;
1132 stream->src_id_len = len;
1136 silc_free(stream->dst_id);
1137 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1138 silc_mutex_unlock(stream->lock);
1141 stream->dst_id = silc_memdup(tmp, len);
1142 if (!stream->dst_id) {
1143 silc_mutex_unlock(stream->lock);
1146 stream->dst_id_type = dst_id_type;
1147 stream->dst_id_len = len;
1150 silc_mutex_unlock(stream->lock);
1155 /* Adds Security ID (SID) */
1157 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1159 if (!stream->iv_included)
1162 SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1170 void silc_packet_free(SilcPacket packet)
1172 SilcPacketStream stream = packet->stream;
1174 SILC_LOG_DEBUG(("Freeing packet %p", packet));
1176 /* Check for double free */
1177 SILC_ASSERT(packet->stream != NULL);
1179 packet->stream = NULL;
1180 packet->src_id = packet->dst_id = NULL;
1181 silc_buffer_reset(&packet->buffer);
1183 silc_mutex_lock(stream->engine->lock);
1185 /* Put the packet back to freelist */
1186 silc_list_add(stream->engine->packet_pool, packet);
1187 if (silc_list_count(stream->engine->packet_pool) == 1)
1188 silc_list_start(stream->engine->packet_pool);
1190 silc_mutex_unlock(stream->engine->lock);
1193 /****************************** Packet Sending ******************************/
1195 /* Prepare outgoing data buffer for packet sending. Returns the
1196 pointer to that buffer into the `packet'. */
1198 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1203 unsigned char *oldptr;
1204 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1208 /* Allocate more space if needed */
1209 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
1210 if (!silc_buffer_realloc(&stream->outbuf,
1211 silc_buffer_truelen(&stream->outbuf) + totlen))
1215 /* Pull data area for the new packet, and return pointer to the start of
1216 the data area and save the pointer in to the `packet'. MAC is pulled
1217 later after it's computed. */
1218 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1219 silc_buffer_set(packet, oldptr, totlen);
1220 silc_buffer_push_tail(packet, mac_len);
1225 /* Internal routine to send packet */
1227 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
1228 SilcPacketType type,
1229 SilcPacketFlags flags,
1230 SilcIdType src_id_type,
1231 unsigned char *src_id,
1232 SilcUInt32 src_id_len,
1233 SilcIdType dst_id_type,
1234 unsigned char *dst_id,
1235 SilcUInt32 dst_id_len,
1236 const unsigned char *data,
1237 SilcUInt32 data_len,
1241 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1242 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1243 int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
1244 SilcBufferStruct packet;
1246 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1247 "data len %d", silc_get_packet_name(type), stream->send_psn,
1248 flags, src_id_type, dst_id_type, data_len));
1250 /* Get the true length of the packet. This is saved as payload length
1251 into the packet header. This does not include the length of the
1253 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1254 src_id_len + dst_id_len));
1255 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1256 src_id_len + dst_id_len);
1258 /* If IV is included, the SID, IV and sequence number is added to packet */
1259 if (stream->iv_included && cipher) {
1260 psnlen = sizeof(psn);
1261 ivlen = block_len + 1;
1262 iv[0] = stream->sid;
1263 memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1266 /* We automatically figure out the packet structure from the packet
1267 type and flags, and calculate correct length. Private messages with
1268 private keys and channel messages are special packets as their
1269 payload is encrypted already. */
1270 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1271 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1272 type == SILC_PACKET_CHANNEL_MESSAGE) {
1274 /* Padding is calculated from header + IDs */
1275 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1276 psnlen), block_len, padlen);
1278 /* Length to encrypt, header + IDs + padding. */
1279 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1283 /* Padding is calculated from true length of the packet */
1284 if (flags & SILC_PACKET_FLAG_LONG_PAD)
1285 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1287 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1289 enclen += padlen + psnlen;
1292 /* Remove implementation specific flags */
1293 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1295 /* Get random padding */
1296 for (i = 0; i < padlen; i++) tmppad[i] =
1297 silc_rng_get_byte_fast(stream->engine->rng);
1299 silc_mutex_lock(stream->lock);
1301 /* Get packet pointer from the outgoing buffer */
1302 if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
1304 silc_mutex_unlock(stream->lock);
1308 SILC_PUT32_MSB(stream->send_psn, psn);
1310 /* Create the packet. This creates the SILC header, adds padding, and
1311 the actual packet data. */
1312 i = silc_buffer_format(&packet,
1313 SILC_STR_DATA(iv, ivlen),
1314 SILC_STR_DATA(psn, psnlen),
1315 SILC_STR_UI_SHORT(truelen),
1316 SILC_STR_UI_CHAR(flags),
1317 SILC_STR_UI_CHAR(type),
1318 SILC_STR_UI_CHAR(padlen),
1319 SILC_STR_UI_CHAR(0),
1320 SILC_STR_UI_CHAR(src_id_len),
1321 SILC_STR_UI_CHAR(dst_id_len),
1322 SILC_STR_UI_CHAR(src_id_type),
1323 SILC_STR_DATA(src_id, src_id_len),
1324 SILC_STR_UI_CHAR(dst_id_type),
1325 SILC_STR_DATA(dst_id, dst_id_len),
1326 SILC_STR_DATA(tmppad, padlen),
1327 SILC_STR_DATA(data, data_len),
1330 silc_mutex_unlock(stream->lock);
1334 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1335 silc_buffer_data(&packet), silc_buffer_len(&packet));
1337 /* Encrypt the packet */
1339 SILC_LOG_DEBUG(("Encrypting packet"));
1340 if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
1341 packet.data + ivlen, enclen, NULL)) {
1342 SILC_LOG_ERROR(("Packet encryption failed"));
1343 silc_mutex_unlock(stream->lock);
1352 /* MAC is computed from the entire encrypted packet data, and put
1353 to the end of the packet. */
1354 silc_hmac_init(hmac);
1355 silc_hmac_update(hmac, psn, sizeof(psn));
1356 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1357 silc_hmac_final(hmac, packet.tail, &mac_len);
1358 silc_buffer_pull_tail(&packet, mac_len);
1362 /* Write the packet to the stream */
1363 return silc_packet_stream_write(stream);
1366 /* Sends a packet */
1368 SilcBool silc_packet_send(SilcPacketStream stream,
1369 SilcPacketType type, SilcPacketFlags flags,
1370 const unsigned char *data, SilcUInt32 data_len)
1372 return silc_packet_send_raw(stream, type, flags,
1373 stream->src_id_type,
1376 stream->dst_id_type,
1380 stream->send_key[0],
1381 stream->send_hmac[0]);
1384 /* Sends a packet, extended routine */
1386 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1387 SilcPacketType type, SilcPacketFlags flags,
1388 SilcIdType src_id_type, void *src_id,
1389 SilcIdType dst_id_type, void *dst_id,
1390 const unsigned char *data, SilcUInt32 data_len,
1391 SilcCipher cipher, SilcHmac hmac)
1393 unsigned char src_id_data[32], dst_id_data[32];
1394 SilcUInt32 src_id_len, dst_id_len;
1397 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1398 sizeof(src_id_data), &src_id_len))
1401 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1402 sizeof(dst_id_data), &dst_id_len))
1405 return silc_packet_send_raw(stream, type, flags,
1406 src_id ? src_id_type : stream->src_id_type,
1407 src_id ? src_id_data : stream->src_id,
1408 src_id ? src_id_len : stream->src_id_len,
1409 dst_id ? dst_id_type : stream->dst_id_type,
1410 dst_id ? dst_id_data : stream->dst_id,
1411 dst_id ? dst_id_len : stream->dst_id_len,
1413 cipher ? cipher : stream->send_key[0],
1414 hmac ? hmac : stream->send_hmac[0]);
1417 /* Sends packet after formatting the arguments to buffer */
1419 SilcBool silc_packet_send_va(SilcPacketStream stream,
1420 SilcPacketType type, SilcPacketFlags flags, ...)
1422 SilcBufferStruct buf;
1426 va_start(va, flags);
1428 memset(&buf, 0, sizeof(buf));
1429 if (silc_buffer_format_vp(&buf, va) < 0) {
1434 ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1435 silc_buffer_len(&buf));
1437 silc_buffer_purge(&buf);
1443 /* Sends packet after formatting the arguments to buffer, extended routine */
1445 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1446 SilcPacketType type, SilcPacketFlags flags,
1447 SilcIdType src_id_type, void *src_id,
1448 SilcIdType dst_id_type, void *dst_id,
1449 SilcCipher cipher, SilcHmac hmac, ...)
1451 SilcBufferStruct buf;
1457 memset(&buf, 0, sizeof(buf));
1458 if (silc_buffer_format_vp(&buf, va) < 0) {
1463 ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1464 dst_id_type, dst_id, silc_buffer_data(&buf),
1465 silc_buffer_len(&buf), cipher, hmac);
1467 silc_buffer_purge(&buf);
1473 /***************************** Packet Receiving *****************************/
1475 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1477 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1478 const unsigned char *data,
1479 SilcUInt32 data_len,
1480 const unsigned char *packet_mac,
1481 const unsigned char *packet_seq,
1482 SilcUInt32 sequence)
1486 unsigned char mac[32], psn[4];
1489 SILC_LOG_DEBUG(("Verifying MAC"));
1491 /* Compute HMAC of packet */
1492 silc_hmac_init(hmac);
1495 SILC_PUT32_MSB(sequence, psn);
1496 silc_hmac_update(hmac, psn, 4);
1498 silc_hmac_update(hmac, packet_seq, 4);
1500 silc_hmac_update(hmac, data, data_len);
1501 silc_hmac_final(hmac, mac, &mac_len);
1503 /* Compare the MAC's */
1504 if (memcmp(packet_mac, mac, mac_len)) {
1505 SILC_LOG_DEBUG(("MAC failed"));
1509 SILC_LOG_DEBUG(("MAC is Ok"));
1515 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1516 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1518 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1519 SilcUInt32 sequence, SilcBuffer buffer,
1522 if (normal == TRUE) {
1524 /* Decrypt rest of the packet */
1525 SILC_LOG_DEBUG(("Decrypting the packet"));
1526 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1527 silc_buffer_len(buffer), NULL))
1533 /* Decrypt rest of the header plus padding */
1536 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1538 SILC_LOG_DEBUG(("Decrypting the header"));
1540 /* Padding length + src id len + dst id len + header length - 16
1541 bytes already decrypted, gives the rest of the encrypted packet */
1542 silc_buffer_push(buffer, block_len);
1543 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1544 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1546 silc_buffer_pull(buffer, block_len);
1548 if (len > silc_buffer_len(buffer)) {
1549 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1553 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1562 /* Parses the packet. This is called when a whole packet is ready to be
1563 parsed. The buffer sent must be already decrypted before calling this
1566 static inline SilcBool silc_packet_parse(SilcPacket packet)
1568 SilcBuffer buffer = &packet->buffer;
1569 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1570 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1573 SILC_LOG_DEBUG(("Parsing incoming packet"));
1575 /* Parse the buffer. This parses the SILC header of the packet. */
1576 ret = silc_buffer_unformat(buffer,
1579 SILC_STR_UI_CHAR(&src_id_len),
1580 SILC_STR_UI_CHAR(&dst_id_len),
1581 SILC_STR_UI_CHAR(&src_id_type),
1584 if (!packet->stream->udp &&
1585 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1586 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1590 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1591 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1592 if (!packet->stream->udp &&
1593 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1594 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1595 packet->src_id_len, packet->dst_id_len));
1599 ret = silc_buffer_unformat(buffer,
1601 SILC_STR_DATA(&packet->src_id, src_id_len),
1602 SILC_STR_UI_CHAR(&dst_id_type),
1603 SILC_STR_DATA(&packet->dst_id, dst_id_len),
1604 SILC_STR_OFFSET(padlen),
1607 if (!packet->stream->udp &&
1608 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1609 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1613 if (src_id_type > SILC_ID_CHANNEL ||
1614 dst_id_type > SILC_ID_CHANNEL) {
1615 if (!packet->stream->udp &&
1616 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1617 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1618 src_id_type, dst_id_type));
1622 packet->src_id_len = src_id_len;
1623 packet->dst_id_len = dst_id_len;
1624 packet->src_id_type = src_id_type;
1625 packet->dst_id_type = dst_id_type;
1627 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1628 silc_buffer_len(buffer)), buffer->head,
1629 silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1631 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1632 silc_get_packet_name(packet->type)));
1637 /* Dispatch packet to application. Called with stream->lock locked. */
1639 static void silc_packet_dispatch(SilcPacket packet)
1641 SilcPacketStream stream = packet->stream;
1642 SilcPacketProcess p;
1643 SilcBool default_sent = FALSE;
1646 /* Dispatch packet to all packet processors that want it */
1648 if (!stream->process) {
1649 /* Send to default processor as no others exist */
1650 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1651 silc_mutex_unlock(stream->lock);
1652 if (!stream->engine->callbacks->
1653 packet_receive(stream->engine, stream, packet,
1654 stream->engine->callback_context,
1655 stream->stream_context))
1656 silc_packet_free(packet);
1657 silc_mutex_lock(stream->lock);
1661 silc_dlist_start(stream->process);
1662 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1664 /* If priority is 0 or less, we send to default processor first
1665 because default processor has 0 priority */
1666 if (!default_sent && p->priority <= 0) {
1667 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1668 default_sent = TRUE;
1669 silc_mutex_unlock(stream->lock);
1670 if (stream->engine->callbacks->
1671 packet_receive(stream->engine, stream, packet,
1672 stream->engine->callback_context,
1673 stream->stream_context)) {
1674 silc_mutex_lock(stream->lock);
1677 silc_mutex_lock(stream->lock);
1680 /* Send to processor */
1682 /* Send all packet types */
1683 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1684 silc_mutex_unlock(stream->lock);
1685 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1686 p->callback_context,
1687 stream->stream_context)) {
1688 silc_mutex_lock(stream->lock);
1691 silc_mutex_lock(stream->lock);
1693 /* Send specific types */
1694 for (pt = p->types; *pt; pt++) {
1695 if (*pt != packet->type)
1697 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1698 silc_mutex_unlock(stream->lock);
1699 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1700 p->callback_context,
1701 stream->stream_context)) {
1702 silc_mutex_lock(stream->lock);
1705 silc_mutex_lock(stream->lock);
1711 if (!default_sent) {
1712 /* Send to default processor as it has not been sent yet */
1713 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1714 silc_mutex_unlock(stream->lock);
1715 if (stream->engine->callbacks->
1716 packet_receive(stream->engine, stream, packet,
1717 stream->engine->callback_context,
1718 stream->stream_context)) {
1719 silc_mutex_lock(stream->lock);
1722 silc_mutex_lock(stream->lock);
1725 /* If we got here, no one wanted the packet, so drop it */
1726 silc_packet_free(packet);
1729 /* Process incoming data and parse packets. Called with stream->lock
1732 static void silc_packet_read_process(SilcPacketStream stream)
1738 SilcUInt16 packetlen;
1739 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1740 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1741 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1745 /* Parse the packets from the data */
1746 while (silc_buffer_len(&stream->inbuf) > 0) {
1748 cipher = stream->receive_key[0];
1749 hmac = stream->receive_hmac[0];
1752 if (silc_buffer_len(&stream->inbuf) <
1753 (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1754 SILC_PACKET_MIN_HEADER_LEN)) {
1755 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1760 mac_len = silc_hmac_len(hmac);
1764 /* Decrypt first block of the packet to get the length field out */
1766 block_len = silc_cipher_get_block_len(cipher);
1768 if (stream->iv_included) {
1769 /* SID, IV and sequence number is included in the ciphertext */
1770 sid = (SilcUInt8)stream->inbuf.data[0];
1771 memcpy(iv, stream->inbuf.data + 1, block_len);
1772 ivlen = block_len + 1;
1775 /* Check SID, and get correct decryption key */
1776 if (sid != stream->sid) {
1777 /* If SID is recent get the previous key and use it */
1778 if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1779 stream->receive_key[1] && !stream->receive_hmac[1]) {
1780 cipher = stream->receive_key[1];
1781 hmac = stream->receive_hmac[1];
1783 /* The SID is unknown, drop rest of the data in buffer */
1784 SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1786 silc_mutex_unlock(stream->lock);
1787 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1788 silc_mutex_lock(stream->lock);
1789 silc_buffer_reset(&stream->inbuf);
1794 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1797 silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1801 if (stream->iv_included) {
1802 /* Take sequence number from packet */
1803 packet_seq = header;
1807 block_len = SILC_PACKET_MIN_HEADER_LEN;
1808 header = stream->inbuf.data;
1811 /* Get packet length and full packet length with padding */
1812 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1815 if (packetlen < SILC_PACKET_MIN_LEN) {
1816 if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
1817 SILC_LOG_ERROR(("Received too short packet"));
1818 silc_mutex_unlock(stream->lock);
1819 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1820 silc_mutex_lock(stream->lock);
1821 memset(tmp, 0, sizeof(tmp));
1822 silc_buffer_reset(&stream->inbuf);
1826 if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1827 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1829 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1830 memset(tmp, 0, sizeof(tmp));
1834 /* Check MAC of the packet */
1835 if (!silc_packet_check_mac(hmac, stream->inbuf.data,
1837 stream->inbuf.data + ivlen + paddedlen,
1838 packet_seq, stream->receive_psn)) {
1839 silc_mutex_unlock(stream->lock);
1840 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1841 silc_mutex_lock(stream->lock);
1842 memset(tmp, 0, sizeof(tmp));
1843 silc_buffer_reset(&stream->inbuf);
1848 packet = silc_packet_alloc(stream->engine);
1850 silc_mutex_unlock(stream->lock);
1851 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1852 silc_mutex_lock(stream->lock);
1853 memset(tmp, 0, sizeof(tmp));
1854 silc_buffer_reset(&stream->inbuf);
1857 packet->stream = stream;
1859 /* Allocate more space to packet buffer, if needed */
1860 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1861 if (!silc_buffer_realloc(&packet->buffer,
1862 silc_buffer_truelen(&packet->buffer) +
1864 silc_buffer_truelen(&packet->buffer)))) {
1865 silc_mutex_unlock(stream->lock);
1866 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1867 silc_mutex_lock(stream->lock);
1868 silc_packet_free(packet);
1869 memset(tmp, 0, sizeof(tmp));
1870 silc_buffer_reset(&stream->inbuf);
1875 /* Parse packet header */
1876 packet->flags = (SilcPacketFlags)header[2];
1877 packet->type = (SilcPacketType)header[3];
1879 if (stream->engine->local_is_router) {
1880 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1881 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1883 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1884 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1885 stream->is_router == TRUE))
1888 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1889 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1891 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1895 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1896 stream->receive_psn, paddedlen + ivlen + mac_len),
1897 stream->inbuf.data, paddedlen + ivlen + mac_len);
1899 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1900 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1901 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1902 silc_buffer_pull(&packet->buffer, block_len - psnlen);
1903 silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1904 psnlen + (block_len - psnlen)),
1905 paddedlen - ivlen - psnlen - (block_len - psnlen));
1907 silc_cipher_set_iv(cipher, iv);
1908 ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1909 &packet->buffer, normal);
1911 silc_mutex_unlock(stream->lock);
1912 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1913 silc_mutex_lock(stream->lock);
1914 silc_packet_free(packet);
1915 memset(tmp, 0, sizeof(tmp));
1919 stream->receive_psn++;
1921 silc_buffer_push(&packet->buffer, block_len);
1923 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1924 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1926 /* Parse the packet */
1927 if (!silc_packet_parse(packet)) {
1928 silc_mutex_unlock(stream->lock);
1929 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1930 silc_mutex_lock(stream->lock);
1931 silc_packet_free(packet);
1932 memset(tmp, 0, sizeof(tmp));
1936 /* Dispatch the packet to application */
1937 silc_packet_dispatch(packet);
1940 silc_buffer_reset(&stream->inbuf);
1944 /****************************** Packet Waiting ******************************/
1946 /* Packet wait receive callback */
1948 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1949 SilcPacketStream stream,
1951 void *callback_context,
1952 void *stream_context);
1954 /* Packet waiting callbacks */
1955 static SilcPacketCallbacks silc_packet_wait_cbs =
1957 silc_packet_wait_packet_receive, NULL, NULL
1960 /* Packet waiting context */
1962 SilcMutex wait_lock;
1964 SilcList packet_queue;
1965 unsigned int stopped : 1;
1968 /* Packet wait receive callback */
1971 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1972 SilcPacketStream stream,
1974 void *callback_context,
1975 void *stream_context)
1977 SilcPacketWait pw = callback_context;
1979 /* Signal the waiting thread for a new packet */
1980 silc_mutex_lock(pw->wait_lock);
1983 silc_mutex_unlock(pw->wait_lock);
1987 silc_list_add(pw->packet_queue, packet);
1988 silc_cond_broadcast(pw->wait_cond);
1990 silc_mutex_unlock(pw->wait_lock);
1995 /* Initialize packet waiting */
1997 void *silc_packet_wait_init(SilcPacketStream stream, ...)
2003 pw = silc_calloc(1, sizeof(*pw));
2007 /* Allocate mutex and conditional variable */
2008 if (!silc_mutex_alloc(&pw->wait_lock)) {
2012 if (!silc_cond_alloc(&pw->wait_cond)) {
2013 silc_mutex_free(pw->wait_lock);
2018 /* Link to the packet stream for the requested packet types */
2019 va_start(ap, stream);
2020 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2024 silc_cond_free(pw->wait_cond);
2025 silc_mutex_free(pw->wait_lock);
2030 /* Initialize packet queue */
2031 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2036 /* Uninitialize packet waiting */
2038 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2040 SilcPacketWait pw = waiter;
2043 /* Signal any threads to stop waiting */
2044 silc_mutex_lock(pw->wait_lock);
2046 silc_cond_broadcast(pw->wait_cond);
2047 silc_mutex_unlock(pw->wait_lock);
2049 /* Re-acquire lock and free resources */
2050 silc_mutex_lock(pw->wait_lock);
2051 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2053 /* Free any remaining packets */
2054 silc_list_start(pw->packet_queue);
2055 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2056 silc_packet_free(packet);
2058 silc_mutex_unlock(pw->wait_lock);
2059 silc_cond_free(pw->wait_cond);
2060 silc_mutex_free(pw->wait_lock);
2064 /* Blocks thread until a packet has been received. */
2066 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2068 SilcPacketWait pw = waiter;
2069 SilcBool ret = FALSE;
2071 silc_mutex_lock(pw->wait_lock);
2073 /* Wait here until packet has arrived */
2074 while (silc_list_count(pw->packet_queue) == 0) {
2076 silc_mutex_unlock(pw->wait_lock);
2079 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2083 silc_list_start(pw->packet_queue);
2084 *return_packet = silc_list_get(pw->packet_queue);
2085 silc_list_del(pw->packet_queue, *return_packet);
2087 silc_mutex_unlock(pw->wait_lock);
2089 return ret == TRUE ? 1 : 0;