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);
765 silc_atomic_uninit8(&stream->refcnt);
766 silc_dlist_uninit(stream->process);
767 silc_mutex_free(stream->lock);
771 /* Marks as router stream */
773 void silc_packet_stream_set_router(SilcPacketStream stream)
775 stream->is_router = TRUE;
778 /* Mark to include IV in ciphertext */
780 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
782 stream->iv_included = TRUE;
785 /* Links `callbacks' to `stream' for specified packet types */
787 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
788 SilcPacketCallbacks *callbacks,
789 void *callback_context,
790 int priority, va_list ap)
792 SilcPacketProcess p, e;
793 SilcInt32 packet_type;
796 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
800 if (!callbacks->packet_receive)
803 p = silc_calloc(1, sizeof(*p));
807 p->priority = priority;
808 p->callbacks = callbacks;
809 p->callback_context = callback_context;
811 silc_mutex_lock(stream->lock);
813 if (!stream->process) {
814 stream->process = silc_dlist_init();
815 if (!stream->process) {
816 silc_mutex_unlock(stream->lock);
821 /* According to priority set the procesor to correct position. First
822 entry has the highest priority */
823 silc_dlist_start(stream->process);
824 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
825 if (p->priority > e->priority) {
826 silc_dlist_insert(stream->process, p);
831 silc_dlist_add(stream->process, p);
833 /* Get packet types to process */
836 packet_type = va_arg(ap, SilcInt32);
838 if (packet_type == SILC_PACKET_ANY)
841 if (packet_type == -1)
844 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
846 silc_mutex_unlock(stream->lock);
850 p->types[i - 1] = (SilcPacketType)packet_type;
856 silc_mutex_unlock(stream->lock);
858 silc_packet_stream_ref(stream);
863 /* Links `callbacks' to `stream' for specified packet types */
865 SilcBool silc_packet_stream_link(SilcPacketStream stream,
866 SilcPacketCallbacks *callbacks,
867 void *callback_context,
873 va_start(ap, priority);
874 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
881 /* Unlinks `callbacks' from `stream'. */
883 void silc_packet_stream_unlink(SilcPacketStream stream,
884 SilcPacketCallbacks *callbacks,
885 void *callback_context)
889 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
892 silc_mutex_lock(stream->lock);
894 silc_dlist_start(stream->process);
895 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
896 if (p->callbacks == callbacks &&
897 p->callback_context == callback_context) {
898 silc_dlist_del(stream->process, p);
903 if (!silc_dlist_count(stream->process)) {
904 silc_dlist_uninit(stream->process);
905 stream->process = NULL;
908 silc_mutex_unlock(stream->lock);
910 silc_packet_stream_unref(stream);
913 /* Return packet sender IP and port for UDP packet stream */
915 SilcBool silc_packet_get_sender(SilcPacket packet,
916 const char **sender_ip,
917 SilcUInt16 *sender_port)
919 if (!packet->stream->remote_udp)
922 *sender_ip = packet->stream->remote_udp->remote_ip;
923 *sender_port = packet->stream->remote_udp->remote_port;
928 /* Reference packet stream */
930 void silc_packet_stream_ref(SilcPacketStream stream)
932 silc_atomic_add_int8(&stream->refcnt, 1);
935 /* Unreference packet stream */
937 void silc_packet_stream_unref(SilcPacketStream stream)
939 if (silc_atomic_sub_int8(&stream->refcnt, 1) == 0)
940 silc_packet_stream_destroy(stream);
945 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
947 return stream->engine;
950 /* Set application context for packet stream */
952 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
954 silc_mutex_lock(stream->lock);
955 stream->stream_context = stream_context;
956 silc_mutex_unlock(stream->lock);
959 /* Return application context from packet stream */
961 void *silc_packet_get_context(SilcPacketStream stream)
964 silc_mutex_lock(stream->lock);
965 context = stream->stream_context;
966 silc_mutex_unlock(stream->lock);
970 /* Change underlaying stream */
972 void silc_packet_stream_set_stream(SilcPacketStream ps,
974 SilcSchedule schedule)
977 silc_stream_set_notifier(ps->stream, schedule, NULL, NULL);
979 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
982 /* Return underlaying stream */
984 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
986 return stream->stream;
989 /* Set ciphers for packet stream */
991 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
994 SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
996 silc_mutex_lock(stream->lock);
998 /* In case IV Included is set, save the old key */
999 if (stream->iv_included) {
1000 if (stream->send_key[1]) {
1001 silc_cipher_free(stream->send_key[1]);
1002 stream->send_key[1] = stream->send_key[0];
1004 if (stream->receive_key[1]) {
1005 silc_cipher_free(stream->receive_key[1]);
1006 stream->receive_key[1] = stream->receive_key[0];
1009 if (stream->send_key[0])
1010 silc_cipher_free(stream->send_key[0]);
1011 if (stream->send_key[1])
1012 silc_cipher_free(stream->receive_key[0]);
1015 stream->send_key[0] = send;
1016 stream->receive_key[0] = receive;
1018 silc_mutex_unlock(stream->lock);
1021 /* Return current ciphers from packet stream */
1023 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
1024 SilcCipher *receive)
1026 if (!stream->send_key[0] && !stream->receive_key[0])
1029 silc_mutex_lock(stream->lock);
1032 *send = stream->send_key[0];
1034 *receive = stream->receive_key[0];
1036 silc_mutex_unlock(stream->lock);
1041 /* Set HMACs for packet stream */
1043 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
1046 SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
1048 silc_mutex_lock(stream->lock);
1050 /* In case IV Included is set, save the old HMAC */
1051 if (stream->iv_included) {
1052 if (stream->send_hmac[1]) {
1053 silc_hmac_free(stream->send_hmac[1]);
1054 stream->send_hmac[1] = stream->send_hmac[0];
1056 if (stream->receive_hmac[1]) {
1057 silc_hmac_free(stream->receive_hmac[1]);
1058 stream->receive_hmac[1] = stream->receive_hmac[0];
1061 if (stream->send_hmac[0])
1062 silc_hmac_free(stream->send_hmac[0]);
1063 if (stream->receive_hmac[0])
1064 silc_hmac_free(stream->receive_hmac[0]);
1067 stream->send_hmac[0] = send;
1068 stream->receive_hmac[0] = receive;
1070 silc_mutex_unlock(stream->lock);
1073 /* Return current HMACs from packet stream */
1075 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
1078 if (!stream->send_hmac[0] && !stream->receive_hmac[0])
1081 silc_mutex_lock(stream->lock);
1084 *send = stream->send_hmac[0];
1086 *receive = stream->receive_hmac[0];
1088 silc_mutex_unlock(stream->lock);
1093 /* Set SILC IDs to packet stream */
1095 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1096 SilcIdType src_id_type, const void *src_id,
1097 SilcIdType dst_id_type, const void *dst_id)
1100 unsigned char tmp[32];
1102 if (!src_id && !dst_id)
1105 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1107 silc_mutex_lock(stream->lock);
1110 silc_free(stream->src_id);
1111 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1112 silc_mutex_unlock(stream->lock);
1115 stream->src_id = silc_memdup(tmp, len);
1116 if (!stream->src_id) {
1117 silc_mutex_unlock(stream->lock);
1120 stream->src_id_type = src_id_type;
1121 stream->src_id_len = len;
1125 silc_free(stream->dst_id);
1126 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1127 silc_mutex_unlock(stream->lock);
1130 stream->dst_id = silc_memdup(tmp, len);
1131 if (!stream->dst_id) {
1132 silc_mutex_unlock(stream->lock);
1135 stream->dst_id_type = dst_id_type;
1136 stream->dst_id_len = len;
1139 silc_mutex_unlock(stream->lock);
1144 /* Adds Security ID (SID) */
1146 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1148 if (!stream->iv_included)
1151 SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1159 void silc_packet_free(SilcPacket packet)
1161 SilcPacketStream stream = packet->stream;
1163 SILC_LOG_DEBUG(("Freeing packet %p", packet));
1165 /* Check for double free */
1166 SILC_ASSERT(packet->stream != NULL);
1168 packet->stream = NULL;
1169 packet->src_id = packet->dst_id = NULL;
1170 silc_buffer_reset(&packet->buffer);
1172 silc_mutex_lock(stream->engine->lock);
1174 /* Put the packet back to freelist */
1175 silc_list_add(stream->engine->packet_pool, packet);
1176 if (silc_list_count(stream->engine->packet_pool) == 1)
1177 silc_list_start(stream->engine->packet_pool);
1179 silc_mutex_unlock(stream->engine->lock);
1182 /****************************** Packet Sending ******************************/
1184 /* Prepare outgoing data buffer for packet sending. Returns the
1185 pointer to that buffer into the `packet'. */
1187 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1192 unsigned char *oldptr;
1193 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1197 /* Allocate more space if needed */
1198 if (silc_buffer_taillen(&stream->outbuf) < totlen) {
1199 if (!silc_buffer_realloc(&stream->outbuf,
1200 silc_buffer_truelen(&stream->outbuf) + totlen))
1204 /* Pull data area for the new packet, and return pointer to the start of
1205 the data area and save the pointer in to the `packet'. MAC is pulled
1206 later after it's computed. */
1207 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1208 silc_buffer_set(packet, oldptr, totlen);
1209 silc_buffer_push_tail(packet, mac_len);
1214 /* Internal routine to send packet */
1216 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
1217 SilcPacketType type,
1218 SilcPacketFlags flags,
1219 SilcIdType src_id_type,
1220 unsigned char *src_id,
1221 SilcUInt32 src_id_len,
1222 SilcIdType dst_id_type,
1223 unsigned char *dst_id,
1224 SilcUInt32 dst_id_len,
1225 const unsigned char *data,
1226 SilcUInt32 data_len,
1230 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1231 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1232 int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
1233 SilcBufferStruct packet;
1235 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1236 "data len %d", silc_get_packet_name(type), stream->send_psn,
1237 flags, src_id_type, dst_id_type, data_len));
1239 /* Get the true length of the packet. This is saved as payload length
1240 into the packet header. This does not include the length of the
1242 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1243 src_id_len + dst_id_len));
1244 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1245 src_id_len + dst_id_len);
1247 /* If IV is included, the SID, IV and sequence number is added to packet */
1248 if (stream->iv_included && cipher) {
1249 psnlen = sizeof(psn);
1250 ivlen = block_len + 1;
1251 iv[0] = stream->sid;
1252 memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1255 /* We automatically figure out the packet structure from the packet
1256 type and flags, and calculate correct length. Private messages with
1257 private keys and channel messages are special packets as their
1258 payload is encrypted already. */
1259 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1260 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1261 type == SILC_PACKET_CHANNEL_MESSAGE) {
1263 /* Padding is calculated from header + IDs */
1264 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1265 psnlen), block_len, padlen);
1267 /* Length to encrypt, header + IDs + padding. */
1268 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1272 /* Padding is calculated from true length of the packet */
1273 if (flags & SILC_PACKET_FLAG_LONG_PAD)
1274 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1276 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1278 enclen += padlen + psnlen;
1281 /* Remove implementation specific flags */
1282 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1284 /* Get random padding */
1285 for (i = 0; i < padlen; i++) tmppad[i] =
1286 silc_rng_get_byte_fast(stream->engine->rng);
1288 silc_mutex_lock(stream->lock);
1290 /* Get packet pointer from the outgoing buffer */
1291 if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
1293 silc_mutex_unlock(stream->lock);
1297 SILC_PUT32_MSB(stream->send_psn, psn);
1299 /* Create the packet. This creates the SILC header, adds padding, and
1300 the actual packet data. */
1301 i = silc_buffer_format(&packet,
1302 SILC_STR_DATA(iv, ivlen),
1303 SILC_STR_DATA(psn, psnlen),
1304 SILC_STR_UI_SHORT(truelen),
1305 SILC_STR_UI_CHAR(flags),
1306 SILC_STR_UI_CHAR(type),
1307 SILC_STR_UI_CHAR(padlen),
1308 SILC_STR_UI_CHAR(0),
1309 SILC_STR_UI_CHAR(src_id_len),
1310 SILC_STR_UI_CHAR(dst_id_len),
1311 SILC_STR_UI_CHAR(src_id_type),
1312 SILC_STR_DATA(src_id, src_id_len),
1313 SILC_STR_UI_CHAR(dst_id_type),
1314 SILC_STR_DATA(dst_id, dst_id_len),
1315 SILC_STR_DATA(tmppad, padlen),
1316 SILC_STR_DATA(data, data_len),
1319 silc_mutex_unlock(stream->lock);
1323 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1324 silc_buffer_data(&packet), silc_buffer_len(&packet));
1326 /* Encrypt the packet */
1328 SILC_LOG_DEBUG(("Encrypting packet"));
1329 if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
1330 packet.data + ivlen, enclen, NULL)) {
1331 SILC_LOG_ERROR(("Packet encryption failed"));
1332 silc_mutex_unlock(stream->lock);
1341 /* MAC is computed from the entire encrypted packet data, and put
1342 to the end of the packet. */
1343 silc_hmac_init(hmac);
1344 silc_hmac_update(hmac, psn, sizeof(psn));
1345 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1346 silc_hmac_final(hmac, packet.tail, &mac_len);
1347 silc_buffer_pull_tail(&packet, mac_len);
1351 /* Write the packet to the stream */
1352 return silc_packet_stream_write(stream);
1355 /* Sends a packet */
1357 SilcBool silc_packet_send(SilcPacketStream stream,
1358 SilcPacketType type, SilcPacketFlags flags,
1359 const unsigned char *data, SilcUInt32 data_len)
1361 return silc_packet_send_raw(stream, type, flags,
1362 stream->src_id_type,
1365 stream->dst_id_type,
1369 stream->send_key[0],
1370 stream->send_hmac[0]);
1373 /* Sends a packet, extended routine */
1375 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1376 SilcPacketType type, SilcPacketFlags flags,
1377 SilcIdType src_id_type, void *src_id,
1378 SilcIdType dst_id_type, void *dst_id,
1379 const unsigned char *data, SilcUInt32 data_len,
1380 SilcCipher cipher, SilcHmac hmac)
1382 unsigned char src_id_data[32], dst_id_data[32];
1383 SilcUInt32 src_id_len, dst_id_len;
1386 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1387 sizeof(src_id_data), &src_id_len))
1390 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1391 sizeof(dst_id_data), &dst_id_len))
1394 return silc_packet_send_raw(stream, type, flags,
1395 src_id ? src_id_type : stream->src_id_type,
1396 src_id ? src_id_data : stream->src_id,
1397 src_id ? src_id_len : stream->src_id_len,
1398 dst_id ? dst_id_type : stream->dst_id_type,
1399 dst_id ? dst_id_data : stream->dst_id,
1400 dst_id ? dst_id_len : stream->dst_id_len,
1402 cipher ? cipher : stream->send_key[0],
1403 hmac ? hmac : stream->send_hmac[0]);
1406 /* Sends packet after formatting the arguments to buffer */
1408 SilcBool silc_packet_send_va(SilcPacketStream stream,
1409 SilcPacketType type, SilcPacketFlags flags, ...)
1411 SilcBufferStruct buf;
1415 va_start(va, flags);
1417 memset(&buf, 0, sizeof(buf));
1418 if (silc_buffer_format_vp(&buf, va) < 0) {
1423 ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1424 silc_buffer_len(&buf));
1426 silc_buffer_purge(&buf);
1432 /* Sends packet after formatting the arguments to buffer, extended routine */
1434 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1435 SilcPacketType type, SilcPacketFlags flags,
1436 SilcIdType src_id_type, void *src_id,
1437 SilcIdType dst_id_type, void *dst_id,
1438 SilcCipher cipher, SilcHmac hmac, ...)
1440 SilcBufferStruct buf;
1446 memset(&buf, 0, sizeof(buf));
1447 if (silc_buffer_format_vp(&buf, va) < 0) {
1452 ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1453 dst_id_type, dst_id, silc_buffer_data(&buf),
1454 silc_buffer_len(&buf), cipher, hmac);
1456 silc_buffer_purge(&buf);
1462 /***************************** Packet Receiving *****************************/
1464 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1466 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1467 const unsigned char *data,
1468 SilcUInt32 data_len,
1469 const unsigned char *packet_mac,
1470 const unsigned char *packet_seq,
1471 SilcUInt32 sequence)
1475 unsigned char mac[32], psn[4];
1478 SILC_LOG_DEBUG(("Verifying MAC"));
1480 /* Compute HMAC of packet */
1481 silc_hmac_init(hmac);
1484 SILC_PUT32_MSB(sequence, psn);
1485 silc_hmac_update(hmac, psn, 4);
1487 silc_hmac_update(hmac, packet_seq, 4);
1489 silc_hmac_update(hmac, data, data_len);
1490 silc_hmac_final(hmac, mac, &mac_len);
1492 /* Compare the MAC's */
1493 if (memcmp(packet_mac, mac, mac_len)) {
1494 SILC_LOG_DEBUG(("MAC failed"));
1498 SILC_LOG_DEBUG(("MAC is Ok"));
1504 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1505 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1507 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1508 SilcUInt32 sequence, SilcBuffer buffer,
1511 if (normal == TRUE) {
1513 /* Decrypt rest of the packet */
1514 SILC_LOG_DEBUG(("Decrypting the packet"));
1515 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1516 silc_buffer_len(buffer), NULL))
1522 /* Decrypt rest of the header plus padding */
1525 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1527 SILC_LOG_DEBUG(("Decrypting the header"));
1529 /* Padding length + src id len + dst id len + header length - 16
1530 bytes already decrypted, gives the rest of the encrypted packet */
1531 silc_buffer_push(buffer, block_len);
1532 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1533 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1535 silc_buffer_pull(buffer, block_len);
1537 if (len > silc_buffer_len(buffer)) {
1538 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1542 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1551 /* Parses the packet. This is called when a whole packet is ready to be
1552 parsed. The buffer sent must be already decrypted before calling this
1555 static inline SilcBool silc_packet_parse(SilcPacket packet)
1557 SilcBuffer buffer = &packet->buffer;
1558 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1559 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1562 SILC_LOG_DEBUG(("Parsing incoming packet"));
1564 /* Parse the buffer. This parses the SILC header of the packet. */
1565 ret = silc_buffer_unformat(buffer,
1568 SILC_STR_UI_CHAR(&src_id_len),
1569 SILC_STR_UI_CHAR(&dst_id_len),
1570 SILC_STR_UI_CHAR(&src_id_type),
1573 if (!packet->stream->udp &&
1574 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1575 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1579 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1580 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1581 if (!packet->stream->udp &&
1582 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1583 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1584 packet->src_id_len, packet->dst_id_len));
1588 ret = silc_buffer_unformat(buffer,
1590 SILC_STR_DATA(&packet->src_id, src_id_len),
1591 SILC_STR_UI_CHAR(&dst_id_type),
1592 SILC_STR_DATA(&packet->dst_id, dst_id_len),
1593 SILC_STR_OFFSET(padlen),
1596 if (!packet->stream->udp &&
1597 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1598 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1602 if (src_id_type > SILC_ID_CHANNEL ||
1603 dst_id_type > SILC_ID_CHANNEL) {
1604 if (!packet->stream->udp &&
1605 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1606 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1607 src_id_type, dst_id_type));
1611 packet->src_id_len = src_id_len;
1612 packet->dst_id_len = dst_id_len;
1613 packet->src_id_type = src_id_type;
1614 packet->dst_id_type = dst_id_type;
1616 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1617 silc_buffer_len(buffer)), buffer->head,
1618 silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1620 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1621 silc_get_packet_name(packet->type)));
1626 /* Dispatch packet to application. Called with stream->lock locked. */
1628 static void silc_packet_dispatch(SilcPacket packet)
1630 SilcPacketStream stream = packet->stream;
1631 SilcPacketProcess p;
1632 SilcBool default_sent = FALSE;
1635 /* Dispatch packet to all packet processors that want it */
1637 if (!stream->process) {
1638 /* Send to default processor as no others exist */
1639 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1640 silc_mutex_unlock(stream->lock);
1641 if (!stream->engine->callbacks->
1642 packet_receive(stream->engine, stream, packet,
1643 stream->engine->callback_context,
1644 stream->stream_context))
1645 silc_packet_free(packet);
1646 silc_mutex_lock(stream->lock);
1650 silc_dlist_start(stream->process);
1651 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1653 /* If priority is 0 or less, we send to default processor first
1654 because default processor has 0 priority */
1655 if (!default_sent && p->priority <= 0) {
1656 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1657 default_sent = TRUE;
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_mutex_lock(stream->lock);
1666 silc_mutex_lock(stream->lock);
1669 /* Send to processor */
1671 /* Send all packet types */
1672 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1673 silc_mutex_unlock(stream->lock);
1674 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1675 p->callback_context,
1676 stream->stream_context)) {
1677 silc_mutex_lock(stream->lock);
1680 silc_mutex_lock(stream->lock);
1682 /* Send specific types */
1683 for (pt = p->types; *pt; pt++) {
1684 if (*pt != packet->type)
1686 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1687 silc_mutex_unlock(stream->lock);
1688 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1689 p->callback_context,
1690 stream->stream_context)) {
1691 silc_mutex_lock(stream->lock);
1694 silc_mutex_lock(stream->lock);
1700 if (!default_sent) {
1701 /* Send to default processor as it has not been sent yet */
1702 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1703 silc_mutex_unlock(stream->lock);
1704 if (stream->engine->callbacks->
1705 packet_receive(stream->engine, stream, packet,
1706 stream->engine->callback_context,
1707 stream->stream_context)) {
1708 silc_mutex_lock(stream->lock);
1711 silc_mutex_lock(stream->lock);
1714 /* If we got here, no one wanted the packet, so drop it */
1715 silc_packet_free(packet);
1718 /* Process incoming data and parse packets. Called with stream->lock
1721 static void silc_packet_read_process(SilcPacketStream stream)
1727 SilcUInt16 packetlen;
1728 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1729 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1730 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1734 /* Parse the packets from the data */
1735 while (silc_buffer_len(&stream->inbuf) > 0) {
1737 cipher = stream->receive_key[0];
1738 hmac = stream->receive_hmac[0];
1741 if (silc_buffer_len(&stream->inbuf) <
1742 (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1743 SILC_PACKET_MIN_HEADER_LEN)) {
1744 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1749 mac_len = silc_hmac_len(hmac);
1753 /* Decrypt first block of the packet to get the length field out */
1755 block_len = silc_cipher_get_block_len(cipher);
1757 if (stream->iv_included) {
1758 /* SID, IV and sequence number is included in the ciphertext */
1759 sid = (SilcUInt8)stream->inbuf.data[0];
1760 memcpy(iv, stream->inbuf.data + 1, block_len);
1761 ivlen = block_len + 1;
1764 /* Check SID, and get correct decryption key */
1765 if (sid != stream->sid) {
1766 /* If SID is recent get the previous key and use it */
1767 if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1768 stream->receive_key[1] && !stream->receive_hmac[1]) {
1769 cipher = stream->receive_key[1];
1770 hmac = stream->receive_hmac[1];
1772 /* The SID is unknown, drop rest of the data in buffer */
1773 SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1775 silc_mutex_unlock(stream->lock);
1776 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1777 silc_mutex_lock(stream->lock);
1778 silc_buffer_reset(&stream->inbuf);
1783 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1786 silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1790 if (stream->iv_included) {
1791 /* Take sequence number from packet */
1792 packet_seq = header;
1796 block_len = SILC_PACKET_MIN_HEADER_LEN;
1797 header = stream->inbuf.data;
1800 /* Get packet length and full packet length with padding */
1801 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1804 if (packetlen < SILC_PACKET_MIN_LEN) {
1805 if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
1806 SILC_LOG_ERROR(("Received too short packet"));
1807 silc_mutex_unlock(stream->lock);
1808 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1809 silc_mutex_lock(stream->lock);
1810 memset(tmp, 0, sizeof(tmp));
1811 silc_buffer_reset(&stream->inbuf);
1815 if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1816 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1818 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1819 memset(tmp, 0, sizeof(tmp));
1823 /* Check MAC of the packet */
1824 if (!silc_packet_check_mac(hmac, stream->inbuf.data,
1826 stream->inbuf.data + ivlen + paddedlen,
1827 packet_seq, stream->receive_psn)) {
1828 silc_mutex_unlock(stream->lock);
1829 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1830 silc_mutex_lock(stream->lock);
1831 memset(tmp, 0, sizeof(tmp));
1832 silc_buffer_reset(&stream->inbuf);
1837 packet = silc_packet_alloc(stream->engine);
1839 silc_mutex_unlock(stream->lock);
1840 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1841 silc_mutex_lock(stream->lock);
1842 memset(tmp, 0, sizeof(tmp));
1843 silc_buffer_reset(&stream->inbuf);
1846 packet->stream = stream;
1848 /* Allocate more space to packet buffer, if needed */
1849 if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1850 if (!silc_buffer_realloc(&packet->buffer,
1851 silc_buffer_truelen(&packet->buffer) +
1853 silc_buffer_truelen(&packet->buffer)))) {
1854 silc_mutex_unlock(stream->lock);
1855 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1856 silc_mutex_lock(stream->lock);
1857 silc_packet_free(packet);
1858 memset(tmp, 0, sizeof(tmp));
1859 silc_buffer_reset(&stream->inbuf);
1864 /* Parse packet header */
1865 packet->flags = (SilcPacketFlags)header[2];
1866 packet->type = (SilcPacketType)header[3];
1868 if (stream->engine->local_is_router) {
1869 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1870 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1872 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1873 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1874 stream->is_router == TRUE))
1877 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1878 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1880 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1884 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1885 stream->receive_psn, paddedlen + ivlen + mac_len),
1886 stream->inbuf.data, paddedlen + ivlen + mac_len);
1888 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1889 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1890 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1891 silc_buffer_pull(&packet->buffer, block_len - psnlen);
1892 silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1893 psnlen + (block_len - psnlen)),
1894 paddedlen - ivlen - psnlen - (block_len - psnlen));
1896 silc_cipher_set_iv(cipher, iv);
1897 ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1898 &packet->buffer, normal);
1900 silc_mutex_unlock(stream->lock);
1901 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1902 silc_mutex_lock(stream->lock);
1903 silc_packet_free(packet);
1904 memset(tmp, 0, sizeof(tmp));
1908 stream->receive_psn++;
1910 silc_buffer_push(&packet->buffer, block_len);
1912 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1913 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1915 /* Parse the packet */
1916 if (!silc_packet_parse(packet)) {
1917 silc_mutex_unlock(stream->lock);
1918 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1919 silc_mutex_lock(stream->lock);
1920 silc_packet_free(packet);
1921 memset(tmp, 0, sizeof(tmp));
1925 /* Dispatch the packet to application */
1926 silc_packet_dispatch(packet);
1929 silc_buffer_reset(&stream->inbuf);
1933 /****************************** Packet Waiting ******************************/
1935 /* Packet wait receive callback */
1937 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1938 SilcPacketStream stream,
1940 void *callback_context,
1941 void *stream_context);
1943 /* Packet waiting callbacks */
1944 static SilcPacketCallbacks silc_packet_wait_cbs =
1946 silc_packet_wait_packet_receive, NULL, NULL
1949 /* Packet waiting context */
1951 SilcMutex wait_lock;
1953 SilcList packet_queue;
1954 unsigned int stopped : 1;
1957 /* Packet wait receive callback */
1960 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1961 SilcPacketStream stream,
1963 void *callback_context,
1964 void *stream_context)
1966 SilcPacketWait pw = callback_context;
1968 /* Signal the waiting thread for a new packet */
1969 silc_mutex_lock(pw->wait_lock);
1972 silc_mutex_unlock(pw->wait_lock);
1976 silc_list_add(pw->packet_queue, packet);
1977 silc_cond_broadcast(pw->wait_cond);
1979 silc_mutex_unlock(pw->wait_lock);
1984 /* Initialize packet waiting */
1986 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1992 pw = silc_calloc(1, sizeof(*pw));
1996 /* Allocate mutex and conditional variable */
1997 if (!silc_mutex_alloc(&pw->wait_lock)) {
2001 if (!silc_cond_alloc(&pw->wait_cond)) {
2002 silc_mutex_free(pw->wait_lock);
2007 /* Link to the packet stream for the requested packet types */
2008 va_start(ap, stream);
2009 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2013 silc_cond_free(pw->wait_cond);
2014 silc_mutex_free(pw->wait_lock);
2019 /* Initialize packet queue */
2020 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2025 /* Uninitialize packet waiting */
2027 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2029 SilcPacketWait pw = waiter;
2032 /* Signal any threads to stop waiting */
2033 silc_mutex_lock(pw->wait_lock);
2035 silc_cond_broadcast(pw->wait_cond);
2036 silc_mutex_unlock(pw->wait_lock);
2038 /* Re-acquire lock and free resources */
2039 silc_mutex_lock(pw->wait_lock);
2040 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2042 /* Free any remaining packets */
2043 silc_list_start(pw->packet_queue);
2044 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2045 silc_packet_free(packet);
2047 silc_mutex_unlock(pw->wait_lock);
2048 silc_cond_free(pw->wait_cond);
2049 silc_mutex_free(pw->wait_lock);
2053 /* Blocks thread until a packet has been received. */
2055 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2057 SilcPacketWait pw = waiter;
2058 SilcBool ret = FALSE;
2060 silc_mutex_lock(pw->wait_lock);
2062 /* Wait here until packet has arrived */
2063 while (silc_list_count(pw->packet_queue) == 0) {
2065 silc_mutex_unlock(pw->wait_lock);
2068 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2072 silc_list_start(pw->packet_queue);
2073 *return_packet = silc_list_get(pw->packet_queue);
2074 silc_list_del(pw->packet_queue, *return_packet);
2076 silc_mutex_unlock(pw->wait_lock);
2078 return ret == TRUE ? 1 : 0;