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 ***************************/
28 /* Per scheduler (which usually means per thread) data. We put per scheduler
29 data here for accessing without locking. SILC Schedule dictates that
30 tasks are dispatched in one thread, hence the per scheduler context. */
32 SilcSchedule schedule; /* The scheduler */
33 SilcPacketEngine engine; /* Packet engine */
34 SilcBufferStruct inbuf; /* Data input buffer */
35 SilcUInt32 stream_count; /* Number of streams using this */
36 } *SilcPacketEngineContext;
39 struct SilcPacketEngineStruct {
40 SilcMutex lock; /* Engine lock */
41 SilcRng rng; /* RNG for engine */
42 SilcHashTable contexts; /* Per scheduler contexts */
43 SilcPacketCallbacks *callbacks; /* Packet callbacks */
44 void *callback_context; /* Context for callbacks */
45 SilcList streams; /* All streams in engine */
46 SilcList packet_pool; /* Free list for received packets */
47 SilcHashTable udp_remote; /* UDP remote streams, or NULL */
48 unsigned int local_is_router : 1;
51 /* Packet processor context */
52 typedef struct SilcPacketProcessStruct {
53 SilcPacketType *types; /* Packets to process */
54 SilcPacketCallbacks *callbacks; /* Callbacks or NULL */
55 void *callback_context;
56 SilcInt32 priority; /* Priority */
59 /* UDP remote stream tuple */
61 char *remote_ip; /* Remote IP address */
62 SilcUInt16 remote_port; /* Remote port */
63 } *SilcPacketRemoteUDP;
66 struct SilcPacketStreamStruct {
67 struct SilcPacketStreamStruct *next;
68 SilcPacketEngineContext sc; /* Per scheduler context */
69 SilcStream stream; /* Underlaying stream */
70 SilcMutex lock; /* Stream lock */
71 SilcDList process; /* Packet processors, or NULL */
72 SilcPacketRemoteUDP remote_udp; /* UDP remote stream tuple, or NULL */
73 void *stream_context; /* Stream context */
74 SilcBufferStruct outbuf; /* Out buffer */
75 SilcCipher send_key[2]; /* Sending key */
76 SilcHmac send_hmac[2]; /* Sending HMAC */
77 SilcCipher receive_key[2]; /* Receiving key */
78 SilcHmac receive_hmac[2]; /* Receiving HMAC */
79 unsigned char *src_id; /* Source ID */
80 unsigned char *dst_id; /* Destination ID */
81 SilcUInt32 send_psn; /* Sending sequence */
82 SilcUInt32 receive_psn; /* Receiving sequence */
83 SilcAtomic8 refcnt; /* Reference counter */
84 SilcUInt8 sid; /* Security ID, set if IV included */
85 unsigned int src_id_len : 6;
86 unsigned int src_id_type : 2;
87 unsigned int dst_id_len : 6;
88 unsigned int dst_id_type : 2;
89 unsigned int is_router : 1; /* Set if router stream */
90 unsigned int destroyed : 1; /* Set if destroyed */
91 unsigned int iv_included : 1; /* Set if IV included */
92 unsigned int udp : 1; /* UDP remote stream */
95 /* Initial size of stream buffers */
96 #define SILC_PACKET_DEFAULT_SIZE 1024
98 /* Header length without source and destination ID's. */
99 #define SILC_PACKET_HEADER_LEN 10
101 /* Minimum length of SILC Packet Header. */
102 #define SILC_PACKET_MIN_HEADER_LEN 16
103 #define SILC_PACKET_MIN_HEADER_LEN_IV 32 + 1
105 /* Maximum padding length */
106 #define SILC_PACKET_MAX_PADLEN 128
108 /* Default padding length */
109 #define SILC_PACKET_DEFAULT_PADLEN 16
111 /* Minimum packet length */
112 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
114 /* Returns true length of the packet. */
115 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
117 SILC_GET16_MSB((__ret_truelen), (__packetdata)); \
118 (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4]; \
121 /* Calculates the data length with given header length. This macro
122 can be used to check whether the data_len with header_len exceeds
123 SILC_PACKET_MAX_LEN. If it does, this returns the new data_len
124 so that the SILC_PACKET_MAX_LEN is not exceeded. If the data_len
125 plus header_len fits SILC_PACKET_MAX_LEN the returned data length
126 is the data_len given as argument. */
127 #define SILC_PACKET_DATALEN(data_len, header_len) \
128 ((data_len + header_len) > SILC_PACKET_MAX_LEN ? \
129 data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
131 /* Calculates the length of the padding in the packet. */
132 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen) \
134 __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) % \
135 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
137 __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
140 /* Returns the length of the padding up to the maximum length, which
142 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen) \
144 __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) % \
145 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
149 #define SILC_PACKET_CALLBACK_EOS(s) \
151 (s)->sc->engine->callbacks->eos((s)->sc->engine, s, \
152 (s)->sc->engine->callback_context, \
153 (s)->stream_context); \
157 #define SILC_PACKET_CALLBACK_ERROR(s, err) \
159 (s)->sc->engine->callbacks->error((s)->sc->engine, s, err, \
160 (s)->sc->engine->callback_context, \
161 (s)->stream_context); \
164 static SilcBool silc_packet_dispatch(SilcPacket packet);
165 static void silc_packet_read_process(SilcPacketStream stream);
166 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
168 SilcPacketFlags flags,
169 SilcIdType src_id_type,
170 unsigned char *src_id,
171 SilcUInt32 src_id_len,
172 SilcIdType dst_id_type,
173 unsigned char *dst_id,
174 SilcUInt32 dst_id_len,
175 const unsigned char *data,
180 /************************ Static utility functions **************************/
182 /* Injects packet to new stream created with silc_packet_stream_add_remote. */
184 SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
186 SilcPacket packet = context;
187 SilcPacketStream stream = packet->stream;
189 SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
191 silc_mutex_lock(stream->lock);
192 if (!stream->destroyed)
193 silc_packet_dispatch(packet);
194 silc_mutex_unlock(stream->lock);
195 silc_packet_stream_unref(stream);
198 /* Write data to the stream. Must be called with ps->lock locked. Unlocks
199 the lock inside this function, unless no_unlock is TRUE. Unlocks always
200 in case it returns FALSE. */
202 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps,
210 stream = ((SilcPacketStream)ps->stream)->stream;
214 if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
216 /* Connectionless UDP stream */
217 while (silc_buffer_len(&ps->outbuf) > 0) {
218 i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
219 ps->remote_udp->remote_port,
220 ps->outbuf.data, silc_buffer_len(&ps->outbuf));
221 if (silc_unlikely(i == -2)) {
223 silc_buffer_reset(&ps->outbuf);
224 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
228 if (silc_unlikely(i == -1)) {
229 /* Cannot write now, write later. */
231 silc_mutex_unlock(ps->lock);
236 silc_buffer_pull(&ps->outbuf, i);
239 silc_buffer_reset(&ps->outbuf);
241 silc_mutex_unlock(ps->lock);
247 /* Write the data to the stream */
248 while (silc_buffer_len(&ps->outbuf) > 0) {
249 i = silc_stream_write(stream, ps->outbuf.data,
250 silc_buffer_len(&ps->outbuf));
251 if (silc_unlikely(i == 0)) {
253 silc_buffer_reset(&ps->outbuf);
254 silc_mutex_unlock(ps->lock);
255 SILC_PACKET_CALLBACK_EOS(ps);
259 if (silc_unlikely(i == -2)) {
261 silc_buffer_reset(&ps->outbuf);
262 silc_mutex_unlock(ps->lock);
263 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
267 if (silc_unlikely(i == -1)) {
268 /* Cannot write now, write later. */
270 silc_mutex_unlock(ps->lock);
275 silc_buffer_pull(&ps->outbuf, i);
278 silc_buffer_reset(&ps->outbuf);
280 silc_mutex_unlock(ps->lock);
285 /* Reads data from stream. Must be called with ps->lock locked. If this
286 returns FALSE the lock has been unlocked. If this returns packet stream
287 to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
288 It is returned if the stream is UDP and remote UDP stream exists for
289 the sender of the packet. */
291 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
292 SilcPacketStream *ret_ps)
300 inbuf = &ps->sc->inbuf;
302 if (silc_socket_stream_is_udp(stream, &connected)) {
304 /* Connectionless UDP stream, read one UDP packet */
305 char remote_ip[64], tuple[64];
307 SilcPacketStream remote;
309 ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
310 &remote_port, inbuf->tail,
311 silc_buffer_taillen(inbuf));
313 if (silc_unlikely(ret < 0)) {
314 silc_mutex_unlock(ps->lock);
316 /* Cannot read now, do it later. */
317 silc_buffer_pull(inbuf, silc_buffer_len(inbuf));
322 silc_buffer_reset(inbuf);
323 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
327 /* See if remote packet stream exist for this sender */
328 silc_snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
329 silc_mutex_lock(ps->sc->engine->lock);
330 if (silc_hash_table_find(ps->sc->engine->udp_remote, tuple, NULL,
332 silc_mutex_unlock(ps->sc->engine->lock);
333 SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p", remote_ip,
334 remote_port, remote));
335 silc_mutex_unlock(ps->lock);
336 silc_mutex_lock(remote->lock);
340 silc_mutex_unlock(ps->sc->engine->lock);
343 if (!ps->remote_udp) {
344 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
345 if (silc_unlikely(!ps->remote_udp)) {
346 silc_mutex_unlock(ps->lock);
347 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
352 /* Save sender IP and port */
353 silc_free(ps->remote_udp->remote_ip);
354 ps->remote_udp->remote_ip = strdup(remote_ip);
355 ps->remote_udp->remote_port = remote_port;
357 silc_buffer_pull_tail(inbuf, ret);
362 /* Read data from the stream */
363 ret = silc_stream_read(stream, inbuf->tail, silc_buffer_taillen(inbuf));
364 if (silc_unlikely(ret <= 0)) {
365 silc_mutex_unlock(ps->lock);
368 silc_buffer_reset(inbuf);
369 SILC_PACKET_CALLBACK_EOS(ps);
374 /* Cannot read now, do it later. */
375 silc_buffer_pull(inbuf, silc_buffer_len(inbuf));
380 silc_buffer_reset(inbuf);
381 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
385 silc_buffer_pull_tail(inbuf, ret);
389 /* Our stream IO notifier callback. */
391 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
394 SilcPacketStream remote = NULL, ps = context;
396 silc_mutex_lock(ps->lock);
398 if (silc_unlikely(ps->destroyed)) {
399 silc_mutex_unlock(ps->lock);
404 case SILC_STREAM_CAN_READ:
405 SILC_LOG_DEBUG(("Reading data from stream"));
407 /* Read data from stream */
408 if (!silc_packet_stream_read(ps, &remote))
411 /* Now process the data */
412 silc_packet_stream_ref(ps);
414 silc_packet_read_process(ps);
415 silc_mutex_unlock(ps->lock);
417 silc_packet_read_process(remote);
418 silc_mutex_unlock(remote->lock);
420 silc_packet_stream_unref(ps);
423 case SILC_STREAM_CAN_WRITE:
424 SILC_LOG_DEBUG(("Writing pending data to stream"));
426 if (silc_unlikely(!silc_buffer_headlen(&ps->outbuf))) {
427 silc_mutex_unlock(ps->lock);
431 /* Write pending data to stream */
432 silc_packet_stream_write(ps, FALSE);
436 silc_mutex_unlock(ps->lock);
441 /* Allocate packet */
443 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
447 SILC_LOG_DEBUG(("Packet pool count %d",
448 silc_list_count(engine->packet_pool)));
450 silc_mutex_lock(engine->lock);
452 /* Get packet from freelist or allocate new one. */
453 packet = silc_list_get(engine->packet_pool);
457 silc_mutex_unlock(engine->lock);
459 packet = silc_calloc(1, sizeof(*packet));
460 if (silc_unlikely(!packet))
463 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
465 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
466 if (silc_unlikely(!tmp)) {
470 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
471 silc_buffer_reset(&packet->buffer);
476 SILC_LOG_DEBUG(("Get packet %p", packet));
478 /* Delete from freelist */
479 silc_list_del(engine->packet_pool, packet);
481 silc_mutex_unlock(engine->lock);
486 /* UDP remote stream hash table destructor */
488 static void silc_packet_engine_hash_destr(void *key, void *context,
494 /* Per scheduler context hash table destructor */
496 static void silc_packet_engine_context_destr(void *key, void *context,
499 SilcPacketEngineContext sc = context;
500 silc_buffer_clear(&sc->inbuf);
501 silc_buffer_purge(&sc->inbuf);
506 /******************************** Packet API ********************************/
508 /* Allocate new packet engine */
511 silc_packet_engine_start(SilcRng rng, SilcBool router,
512 SilcPacketCallbacks *callbacks,
513 void *callback_context)
515 SilcPacketEngine engine;
520 SILC_LOG_DEBUG(("Starting new packet engine"));
524 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
527 engine = silc_calloc(1, sizeof(*engine));
531 engine->contexts = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
532 silc_packet_engine_context_destr,
534 if (!engine->contexts) {
540 engine->local_is_router = router;
541 engine->callbacks = callbacks;
542 engine->callback_context = callback_context;
543 silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
544 silc_mutex_alloc(&engine->lock);
546 /* Allocate packet free list */
547 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
548 for (i = 0; i < 5; i++) {
549 packet = silc_calloc(1, sizeof(*packet));
551 silc_packet_engine_stop(engine);
555 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
557 silc_packet_engine_stop(engine);
560 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
561 silc_buffer_reset(&packet->buffer);
563 silc_list_add(engine->packet_pool, packet);
565 silc_list_start(engine->packet_pool);
570 /* Stop packet engine */
572 void silc_packet_engine_stop(SilcPacketEngine engine)
575 SILC_LOG_DEBUG(("Stopping packet engine"));
585 /* Create new packet stream */
587 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
588 SilcSchedule schedule,
594 SILC_LOG_DEBUG(("Creating new packet stream"));
596 if (!engine || !stream)
599 ps = silc_calloc(1, sizeof(*ps));
604 silc_atomic_init8(&ps->refcnt, 1);
605 silc_mutex_alloc(&ps->lock);
607 /* Allocate out buffer */
608 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
610 silc_packet_stream_destroy(ps);
613 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
614 silc_buffer_reset(&ps->outbuf);
616 /* Initialize packet procesors list */
617 ps->process = silc_dlist_init();
619 silc_packet_stream_destroy(ps);
623 silc_mutex_lock(engine->lock);
625 /* Add per scheduler context */
626 if (!silc_hash_table_find(engine->contexts, schedule, NULL,
628 ps->sc = silc_calloc(1, sizeof(*ps->sc));
630 silc_packet_stream_destroy(ps);
631 silc_mutex_unlock(engine->lock);
634 ps->sc->engine = engine;
635 ps->sc->schedule = schedule;
637 /* Allocate data input buffer */
638 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE * 31);
642 silc_packet_stream_destroy(ps);
643 silc_mutex_unlock(engine->lock);
646 silc_buffer_set(&ps->sc->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE * 31);
647 silc_buffer_reset(&ps->sc->inbuf);
649 /* Add to per scheduler context hash table */
650 if (!silc_hash_table_add(engine->contexts, schedule, ps->sc)) {
651 silc_buffer_purge(&ps->sc->inbuf);
654 silc_packet_stream_destroy(ps);
655 silc_mutex_unlock(engine->lock);
659 ps->sc->stream_count++;
661 /* Add the packet stream to engine */
662 silc_list_add(engine->streams, ps);
664 /* If this is UDP stream, allocate UDP remote stream hash table */
665 if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
666 engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
667 silc_hash_string_compare, NULL,
668 silc_packet_engine_hash_destr,
670 silc_mutex_unlock(engine->lock);
672 /* Set IO notifier callback. This schedules this stream for I/O. */
673 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
678 /* Add new remote packet stream for UDP packet streams */
680 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
681 const char *remote_ip,
682 SilcUInt16 remote_port,
685 SilcPacketEngine engine = stream->sc->engine;
690 SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
691 remote_ip, remote_port, stream));
693 if (!stream || !remote_ip || !remote_port)
696 if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
697 SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
701 ps = silc_calloc(1, sizeof(*ps));
706 silc_atomic_init8(&ps->refcnt, 1);
707 silc_mutex_alloc(&ps->lock);
709 /* Set the UDP packet stream as underlaying stream */
710 silc_packet_stream_ref(stream);
711 ps->stream = (SilcStream)stream;
714 /* Allocate out buffer */
715 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
717 silc_packet_stream_destroy(ps);
720 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
721 silc_buffer_reset(&ps->outbuf);
723 /* Initialize packet procesors list */
724 ps->process = silc_dlist_init();
726 silc_packet_stream_destroy(ps);
730 /* Add to engine with this IP and port pair */
731 tuple = silc_format("%d%s", remote_port, remote_ip);
732 silc_mutex_lock(engine->lock);
733 if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
734 silc_mutex_unlock(engine->lock);
735 silc_packet_stream_destroy(ps);
738 silc_mutex_unlock(engine->lock);
740 /* Save remote IP and port pair */
741 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
742 if (!ps->remote_udp) {
743 silc_packet_stream_destroy(ps);
746 ps->remote_udp->remote_port = remote_port;
747 ps->remote_udp->remote_ip = strdup(remote_ip);
748 if (!ps->remote_udp->remote_ip) {
749 silc_packet_stream_destroy(ps);
754 /* Inject packet to the new stream */
756 silc_packet_stream_ref(ps);
757 silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
758 silc_packet_stream_inject_packet, packet,
765 /* Destroy packet stream */
767 void silc_packet_stream_destroy(SilcPacketStream stream)
772 if (silc_atomic_get_int8(&stream->refcnt) > 1) {
773 stream->destroyed = TRUE;
777 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
780 /* Delete from engine */
781 silc_mutex_lock(stream->sc->engine->lock);
782 silc_list_del(stream->sc->engine->streams, stream);
784 /* Remove per scheduler context, if it is not used anymore */
786 stream->sc->stream_count--;
787 if (!stream->sc->stream_count)
788 silc_hash_table_del(stream->sc->engine->contexts,
789 stream->sc->schedule);
791 silc_mutex_unlock(stream->sc->engine->lock);
793 /* Destroy the underlaying stream */
795 silc_stream_destroy(stream->stream);
797 /* Delete from UDP remote hash table */
799 silc_snprintf(tuple, sizeof(tuple), "%d%s", stream->remote_udp->remote_port,
800 stream->remote_udp->remote_ip);
801 silc_mutex_lock(stream->sc->engine->lock);
802 silc_hash_table_del(stream->sc->engine->udp_remote, tuple);
803 silc_mutex_unlock(stream->sc->engine->lock);
805 silc_free(stream->remote_udp->remote_ip);
806 silc_free(stream->remote_udp);
808 /* Unreference the underlaying packet stream */
809 silc_packet_stream_unref((SilcPacketStream)stream->stream);
812 /* Clear and free buffers */
813 silc_buffer_clear(&stream->outbuf);
814 silc_buffer_purge(&stream->outbuf);
816 if (stream->process) {
818 silc_dlist_start(stream->process);
819 while ((p = silc_dlist_get(stream->process))) {
822 silc_dlist_del(stream->process, p);
824 silc_dlist_uninit(stream->process);
829 silc_atomic_uninit8(&stream->refcnt);
830 silc_mutex_free(stream->lock);
834 /* Marks as router stream */
836 void silc_packet_stream_set_router(SilcPacketStream stream)
838 stream->is_router = TRUE;
841 /* Mark to include IV in ciphertext */
843 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
845 stream->iv_included = TRUE;
848 /* Links `callbacks' to `stream' for specified packet types */
850 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
851 SilcPacketCallbacks *callbacks,
852 void *callback_context,
853 int priority, va_list ap)
855 SilcPacketProcess p, e;
856 SilcInt32 packet_type;
859 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
863 if (!callbacks->packet_receive)
866 p = silc_calloc(1, sizeof(*p));
870 p->priority = priority;
871 p->callbacks = callbacks;
872 p->callback_context = callback_context;
874 silc_mutex_lock(stream->lock);
876 if (!stream->process) {
877 stream->process = silc_dlist_init();
878 if (!stream->process) {
879 silc_mutex_unlock(stream->lock);
884 /* According to priority set the procesor to correct position. First
885 entry has the highest priority */
886 silc_dlist_start(stream->process);
887 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
888 if (p->priority > e->priority) {
889 silc_dlist_insert(stream->process, p);
894 silc_dlist_add(stream->process, p);
896 /* Get packet types to process */
899 packet_type = va_arg(ap, SilcInt32);
901 if (packet_type == SILC_PACKET_ANY)
904 if (packet_type == -1)
907 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
909 silc_mutex_unlock(stream->lock);
913 p->types[i - 1] = (SilcPacketType)packet_type;
919 silc_mutex_unlock(stream->lock);
921 silc_packet_stream_ref(stream);
926 /* Links `callbacks' to `stream' for specified packet types */
928 SilcBool silc_packet_stream_link(SilcPacketStream stream,
929 SilcPacketCallbacks *callbacks,
930 void *callback_context,
936 va_start(ap, priority);
937 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
944 /* Unlinks `callbacks' from `stream'. */
946 void silc_packet_stream_unlink(SilcPacketStream stream,
947 SilcPacketCallbacks *callbacks,
948 void *callback_context)
952 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
955 silc_mutex_lock(stream->lock);
957 silc_dlist_start(stream->process);
958 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
959 if (p->callbacks == callbacks &&
960 p->callback_context == callback_context) {
961 silc_dlist_del(stream->process, p);
967 if (!silc_dlist_count(stream->process)) {
968 silc_dlist_uninit(stream->process);
969 stream->process = NULL;
972 silc_mutex_unlock(stream->lock);
974 silc_packet_stream_unref(stream);
977 /* Returns TRUE if stream is UDP stream */
979 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream)
981 return stream->udp || silc_socket_stream_is_udp(stream->stream, NULL);
984 /* Return packet sender IP and port for UDP packet stream */
986 SilcBool silc_packet_get_sender(SilcPacket packet,
987 const char **sender_ip,
988 SilcUInt16 *sender_port)
990 if (!packet->stream->remote_udp)
993 *sender_ip = packet->stream->remote_udp->remote_ip;
994 *sender_port = packet->stream->remote_udp->remote_port;
999 /* Reference packet stream */
1001 void silc_packet_stream_ref(SilcPacketStream stream)
1003 silc_atomic_add_int8(&stream->refcnt, 1);
1006 /* Unreference packet stream */
1008 void silc_packet_stream_unref(SilcPacketStream stream)
1010 if (silc_atomic_sub_int8(&stream->refcnt, 1) == 0)
1011 silc_packet_stream_destroy(stream);
1016 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
1018 return stream->sc->engine;
1021 /* Set application context for packet stream */
1023 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
1025 silc_mutex_lock(stream->lock);
1026 stream->stream_context = stream_context;
1027 silc_mutex_unlock(stream->lock);
1030 /* Return application context from packet stream */
1032 void *silc_packet_get_context(SilcPacketStream stream)
1035 silc_mutex_lock(stream->lock);
1036 context = stream->stream_context;
1037 silc_mutex_unlock(stream->lock);
1041 /* Change underlaying stream */
1043 void silc_packet_stream_set_stream(SilcPacketStream ps,
1047 silc_stream_set_notifier(ps->stream, ps->sc->schedule, NULL, NULL);
1048 ps->stream = stream;
1049 silc_stream_set_notifier(ps->stream, ps->sc->schedule, silc_packet_stream_io,
1053 /* Return underlaying stream */
1055 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
1057 return stream->stream;
1062 SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
1063 SilcCipher receive_key, SilcHmac send_hmac,
1064 SilcHmac receive_hmac, SilcBool rekey)
1066 SILC_LOG_DEBUG(("Setting new keys to packet stream %p", stream));
1068 /* If doing rekey, send REKEY_DONE packet */
1070 /* This will take stream lock. */
1071 if (!silc_packet_send_raw(stream, SILC_PACKET_REKEY_DONE, 0,
1072 stream->src_id_type, stream->src_id,
1073 stream->src_id_len, stream->dst_id_type,
1074 stream->dst_id, stream->dst_id_len,
1075 NULL, 0, stream->send_key[0],
1076 stream->send_hmac[0]))
1079 /* Write the packet to the stream */
1080 if (!silc_packet_stream_write(stream, TRUE))
1083 silc_mutex_lock(stream->lock);
1086 /* In case IV Included is set, save the old keys */
1087 if (stream->iv_included) {
1088 if (stream->send_key[1] && send_key) {
1089 silc_cipher_free(stream->send_key[1]);
1090 stream->send_key[1] = stream->send_key[0];
1092 if (stream->receive_key[1] && receive_key) {
1093 silc_cipher_free(stream->receive_key[1]);
1094 stream->receive_key[1] = stream->receive_key[0];
1096 if (stream->send_hmac[1] && send_hmac) {
1097 silc_hmac_free(stream->send_hmac[1]);
1098 stream->send_hmac[1] = stream->send_hmac[0];
1100 if (stream->receive_hmac[1] && receive_hmac) {
1101 silc_hmac_free(stream->receive_hmac[1]);
1102 stream->receive_hmac[1] = stream->receive_hmac[0];
1105 if (stream->send_key[0] && send_key)
1106 silc_cipher_free(stream->send_key[0]);
1107 if (stream->send_key[1] && receive_key)
1108 silc_cipher_free(stream->receive_key[0]);
1109 if (stream->send_hmac[0] && send_hmac)
1110 silc_hmac_free(stream->send_hmac[0]);
1111 if (stream->receive_hmac[0] && receive_hmac)
1112 silc_hmac_free(stream->receive_hmac[0]);
1117 stream->send_key[0] = send_key;
1119 stream->receive_key[0] = receive_key;
1121 stream->send_hmac[0] = send_hmac;
1123 stream->receive_hmac[0] = receive_hmac;
1125 silc_mutex_unlock(stream->lock);
1129 /* Return current ciphers from packet stream */
1131 SilcBool silc_packet_get_keys(SilcPacketStream stream,
1132 SilcCipher *send_key,
1133 SilcCipher *receive_key,
1134 SilcHmac *send_hmac,
1135 SilcHmac *receive_hmac)
1137 if (!stream->send_key[0] && !stream->receive_key[0] &&
1138 !stream->send_hmac[0] && !stream->receive_hmac[0])
1141 silc_mutex_lock(stream->lock);
1144 *send_key = stream->send_key[0];
1146 *receive_key = stream->receive_key[0];
1148 *send_hmac = stream->send_hmac[0];
1150 *receive_hmac = stream->receive_hmac[0];
1152 silc_mutex_unlock(stream->lock);
1157 /* Set SILC IDs to packet stream */
1159 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1160 SilcIdType src_id_type, const void *src_id,
1161 SilcIdType dst_id_type, const void *dst_id)
1164 unsigned char tmp[32];
1166 if (!src_id && !dst_id)
1169 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1171 silc_mutex_lock(stream->lock);
1174 silc_free(stream->src_id);
1175 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1176 silc_mutex_unlock(stream->lock);
1179 stream->src_id = silc_memdup(tmp, len);
1180 if (!stream->src_id) {
1181 silc_mutex_unlock(stream->lock);
1184 stream->src_id_type = src_id_type;
1185 stream->src_id_len = len;
1189 silc_free(stream->dst_id);
1190 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1191 silc_mutex_unlock(stream->lock);
1194 stream->dst_id = silc_memdup(tmp, len);
1195 if (!stream->dst_id) {
1196 silc_mutex_unlock(stream->lock);
1199 stream->dst_id_type = dst_id_type;
1200 stream->dst_id_len = len;
1203 silc_mutex_unlock(stream->lock);
1208 /* Adds Security ID (SID) */
1210 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1212 if (!stream->iv_included)
1215 SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1223 void silc_packet_free(SilcPacket packet)
1225 SilcPacketStream stream = packet->stream;
1227 SILC_LOG_DEBUG(("Freeing packet %p", packet));
1229 /* Check for double free */
1230 SILC_ASSERT(packet->stream != NULL);
1232 packet->stream = NULL;
1233 packet->src_id = packet->dst_id = NULL;
1234 silc_buffer_reset(&packet->buffer);
1236 silc_mutex_lock(stream->sc->engine->lock);
1238 /* Put the packet back to freelist */
1239 silc_list_add(stream->sc->engine->packet_pool, packet);
1240 if (silc_list_count(stream->sc->engine->packet_pool) == 1)
1241 silc_list_start(stream->sc->engine->packet_pool);
1243 silc_mutex_unlock(stream->sc->engine->lock);
1246 /****************************** Packet Sending ******************************/
1248 /* Prepare outgoing data buffer for packet sending. Returns the
1249 pointer to that buffer into the `packet'. */
1251 static inline SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1256 unsigned char *oldptr;
1257 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1261 /* Allocate more space if needed */
1262 if (silc_unlikely(silc_buffer_taillen(&stream->outbuf) < totlen)) {
1263 if (!silc_buffer_realloc(&stream->outbuf,
1264 silc_buffer_truelen(&stream->outbuf) + totlen))
1268 /* Pull data area for the new packet, and return pointer to the start of
1269 the data area and save the pointer in to the `packet'. MAC is pulled
1270 later after it's computed. */
1271 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1272 silc_buffer_set(packet, oldptr, totlen);
1273 silc_buffer_push_tail(packet, mac_len);
1278 /* Increments counter when encrypting in counter mode. */
1280 static inline void silc_packet_send_ctr_increment(SilcPacketStream stream,
1282 unsigned char *ret_iv)
1284 unsigned char *iv = silc_cipher_get_iv(cipher);
1287 /* Increment packet counter */
1288 SILC_GET32_MSB(pc, iv + 8);
1290 SILC_PUT32_MSB(pc, iv + 8);
1292 /* Reset block counter */
1293 memset(iv + 12, 0, 4);
1295 /* If IV Included flag, return the 64-bit IV for inclusion in packet */
1296 if (stream->iv_included) {
1298 ret_iv[0] = silc_rng_get_byte_fast(stream->sc->engine->rng);
1299 ret_iv[1] = ret_iv[0] + iv[4];
1300 ret_iv[2] = ret_iv[0] ^ ret_iv[1];
1301 ret_iv[3] = ret_iv[0] + ret_iv[2];
1302 SILC_PUT32_MSB(pc, ret_iv + 4);
1303 SILC_LOG_HEXDUMP(("IV"), ret_iv, 8);
1305 /* Set new nonce to counter block */
1306 memcpy(iv + 4, ret_iv, 4);
1309 SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1312 /* Internal routine to assemble outgoing packet. Assembles and encryptes
1313 the packet. The silc_packet_stream_write needs to be called to send it
1314 after this returns TRUE. */
1316 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
1317 SilcPacketType type,
1318 SilcPacketFlags flags,
1319 SilcIdType src_id_type,
1320 unsigned char *src_id,
1321 SilcUInt32 src_id_len,
1322 SilcIdType dst_id_type,
1323 unsigned char *dst_id,
1324 SilcUInt32 dst_id_len,
1325 const unsigned char *data,
1326 SilcUInt32 data_len,
1330 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1331 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1332 int i, enclen, truelen, padlen = 0, ivlen = 0, psnlen = 0;
1334 SilcBufferStruct packet;
1336 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1337 "data len %d", silc_get_packet_name(type), stream->send_psn,
1338 flags, src_id_type, dst_id_type, data_len));
1340 /* Get the true length of the packet. This is saved as payload length
1341 into the packet header. This does not include the length of the
1343 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1344 src_id_len + dst_id_len));
1345 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1346 src_id_len + dst_id_len);
1348 /* If using CTR mode, increment the counter */
1349 ctr = (cipher && silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR);
1351 silc_packet_send_ctr_increment(stream, cipher, iv + 1);
1353 /* If IV is included, the SID, IV and sequence number is added to packet */
1354 if (stream->iv_included && cipher) {
1355 psnlen = sizeof(psn);
1357 iv[0] = stream->sid;
1360 /* If IV is included, the SID, IV and sequence number is added to packet */
1361 if (stream->iv_included && cipher) {
1362 psnlen = sizeof(psn);
1363 ivlen = block_len + 1;
1364 iv[0] = stream->sid;
1365 memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1369 /* We automatically figure out the packet structure from the packet
1370 type and flags, and calculate correct length. Private messages with
1371 private keys and channel messages are special packets as their
1372 payload is encrypted already. */
1373 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1374 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1375 type == SILC_PACKET_CHANNEL_MESSAGE) {
1377 /* Padding is calculated from header + IDs */
1379 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1380 psnlen), block_len, padlen);
1382 /* Length to encrypt, header + IDs + padding. */
1383 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1387 /* Padding is calculated from true length of the packet */
1388 if (flags & SILC_PACKET_FLAG_LONG_PAD)
1389 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1391 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1393 enclen += padlen + psnlen;
1396 /* Remove implementation specific flags */
1397 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1399 /* Get random padding */
1400 for (i = 0; i < padlen; i++) tmppad[i] =
1401 silc_rng_get_byte_fast(stream->sc->engine->rng);
1403 silc_mutex_lock(stream->lock);
1405 /* Get packet pointer from the outgoing buffer */
1406 if (silc_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen
1407 + psnlen, hmac, &packet))) {
1408 silc_mutex_unlock(stream->lock);
1412 SILC_PUT32_MSB(stream->send_psn, psn);
1414 /* Create the packet. This creates the SILC header, adds padding, and
1415 the actual packet data. */
1416 i = silc_buffer_format(&packet,
1417 SILC_STR_DATA(iv, ivlen),
1418 SILC_STR_DATA(psn, psnlen),
1419 SILC_STR_UI_SHORT(truelen),
1420 SILC_STR_UI_CHAR(flags),
1421 SILC_STR_UI_CHAR(type),
1422 SILC_STR_UI_CHAR(padlen),
1423 SILC_STR_UI_CHAR(0),
1424 SILC_STR_UI_CHAR(src_id_len),
1425 SILC_STR_UI_CHAR(dst_id_len),
1426 SILC_STR_UI_CHAR(src_id_type),
1427 SILC_STR_DATA(src_id, src_id_len),
1428 SILC_STR_UI_CHAR(dst_id_type),
1429 SILC_STR_DATA(dst_id, dst_id_len),
1430 SILC_STR_DATA(tmppad, padlen),
1431 SILC_STR_DATA(data, data_len),
1433 if (silc_unlikely(i < 0)) {
1434 silc_mutex_unlock(stream->lock);
1438 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1439 silc_buffer_data(&packet), silc_buffer_len(&packet));
1441 /* Encrypt the packet */
1442 if (silc_likely(cipher)) {
1443 SILC_LOG_DEBUG(("Encrypting packet"));
1444 if (silc_unlikely(!silc_cipher_encrypt(cipher, packet.data + ivlen,
1445 packet.data + ivlen, enclen,
1447 SILC_LOG_ERROR(("Packet encryption failed"));
1448 silc_mutex_unlock(stream->lock);
1454 if (silc_likely(hmac)) {
1457 /* MAC is computed from the entire encrypted packet data, and put
1458 to the end of the packet. */
1459 silc_hmac_init(hmac);
1460 silc_hmac_update(hmac, psn, sizeof(psn));
1461 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1462 silc_hmac_final(hmac, packet.tail, &mac_len);
1463 silc_buffer_pull_tail(&packet, mac_len);
1470 /* Sends a packet */
1472 SilcBool silc_packet_send(SilcPacketStream stream,
1473 SilcPacketType type, SilcPacketFlags flags,
1474 const unsigned char *data, SilcUInt32 data_len)
1478 ret = silc_packet_send_raw(stream, type, flags,
1479 stream->src_id_type,
1482 stream->dst_id_type,
1486 stream->send_key[0],
1487 stream->send_hmac[0]);
1489 /* Write the packet to the stream */
1490 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1493 /* Sends a packet, extended routine */
1495 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1496 SilcPacketType type, SilcPacketFlags flags,
1497 SilcIdType src_id_type, void *src_id,
1498 SilcIdType dst_id_type, void *dst_id,
1499 const unsigned char *data, SilcUInt32 data_len,
1500 SilcCipher cipher, SilcHmac hmac)
1502 unsigned char src_id_data[32], dst_id_data[32];
1503 SilcUInt32 src_id_len, dst_id_len;
1507 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1508 sizeof(src_id_data), &src_id_len))
1511 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1512 sizeof(dst_id_data), &dst_id_len))
1515 ret = silc_packet_send_raw(stream, type, flags,
1516 src_id ? src_id_type : stream->src_id_type,
1517 src_id ? src_id_data : stream->src_id,
1518 src_id ? src_id_len : stream->src_id_len,
1519 dst_id ? dst_id_type : stream->dst_id_type,
1520 dst_id ? dst_id_data : stream->dst_id,
1521 dst_id ? dst_id_len : stream->dst_id_len,
1523 cipher ? cipher : stream->send_key[0],
1524 hmac ? hmac : stream->send_hmac[0]);
1526 /* Write the packet to the stream */
1527 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1530 /* Sends packet after formatting the arguments to buffer */
1532 SilcBool silc_packet_send_va(SilcPacketStream stream,
1533 SilcPacketType type, SilcPacketFlags flags, ...)
1535 SilcBufferStruct buf;
1539 va_start(va, flags);
1541 memset(&buf, 0, sizeof(buf));
1542 if (silc_buffer_format_vp(&buf, va) < 0) {
1547 ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1548 silc_buffer_len(&buf));
1550 silc_buffer_purge(&buf);
1556 /* Sends packet after formatting the arguments to buffer, extended routine */
1558 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1559 SilcPacketType type, SilcPacketFlags flags,
1560 SilcIdType src_id_type, void *src_id,
1561 SilcIdType dst_id_type, void *dst_id,
1562 SilcCipher cipher, SilcHmac hmac, ...)
1564 SilcBufferStruct buf;
1570 memset(&buf, 0, sizeof(buf));
1571 if (silc_buffer_format_vp(&buf, va) < 0) {
1576 ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1577 dst_id_type, dst_id, silc_buffer_data(&buf),
1578 silc_buffer_len(&buf), cipher, hmac);
1580 silc_buffer_purge(&buf);
1586 /***************************** Packet Receiving *****************************/
1588 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1590 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1591 const unsigned char *data,
1592 SilcUInt32 data_len,
1593 const unsigned char *packet_mac,
1594 const unsigned char *packet_seq,
1595 SilcUInt32 sequence)
1598 if (silc_likely(hmac)) {
1599 unsigned char mac[32], psn[4];
1602 SILC_LOG_DEBUG(("Verifying MAC"));
1604 /* Compute HMAC of packet */
1605 silc_hmac_init(hmac);
1608 SILC_PUT32_MSB(sequence, psn);
1609 silc_hmac_update(hmac, psn, 4);
1611 silc_hmac_update(hmac, packet_seq, 4);
1613 silc_hmac_update(hmac, data, data_len);
1614 silc_hmac_final(hmac, mac, &mac_len);
1616 /* Compare the MAC's */
1617 if (silc_unlikely(memcmp(packet_mac, mac, mac_len))) {
1618 SILC_LOG_DEBUG(("MAC failed"));
1622 SILC_LOG_DEBUG(("MAC is Ok"));
1628 /* Increments/sets counter when decrypting in counter mode. */
1630 static inline void silc_packet_receive_ctr_increment(SilcPacketStream stream,
1632 unsigned char *packet_iv)
1636 /* If IV Included flag, set the IV from packet to block counter. */
1637 if (stream->iv_included) {
1638 memcpy(iv + 4, packet_iv, 8);
1640 /* Increment packet counter */
1641 SILC_GET32_MSB(pc, iv + 8);
1643 SILC_PUT32_MSB(pc, iv + 8);
1646 /* Reset block counter */
1647 memset(iv + 12, 0, 4);
1649 SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1652 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1653 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1655 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1656 SilcUInt32 sequence, SilcBuffer buffer,
1659 if (normal == TRUE) {
1660 if (silc_likely(cipher)) {
1661 /* Decrypt rest of the packet */
1662 SILC_LOG_DEBUG(("Decrypting the packet"));
1663 if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1665 silc_buffer_len(buffer), NULL)))
1671 /* Decrypt rest of the header plus padding */
1672 if (silc_likely(cipher)) {
1674 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1676 SILC_LOG_DEBUG(("Decrypting the header"));
1678 /* Padding length + src id len + dst id len + header length - 16
1679 bytes already decrypted, gives the rest of the encrypted packet */
1680 silc_buffer_push(buffer, block_len);
1681 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1682 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1684 silc_buffer_pull(buffer, block_len);
1686 if (silc_unlikely(len > silc_buffer_len(buffer))) {
1687 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1691 if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1692 buffer->data, len, NULL)))
1700 /* Parses the packet. This is called when a whole packet is ready to be
1701 parsed. The buffer sent must be already decrypted before calling this
1704 static inline SilcBool silc_packet_parse(SilcPacket packet)
1706 SilcBuffer buffer = &packet->buffer;
1707 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1708 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1711 SILC_LOG_DEBUG(("Parsing incoming packet"));
1713 /* Parse the buffer. This parses the SILC header of the packet. */
1714 ret = silc_buffer_unformat(buffer,
1717 SILC_STR_UI_CHAR(&src_id_len),
1718 SILC_STR_UI_CHAR(&dst_id_len),
1719 SILC_STR_UI_CHAR(&src_id_type),
1721 if (silc_unlikely(ret == -1)) {
1722 if (!packet->stream->udp &&
1723 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1724 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1728 if (silc_unlikely(src_id_len > SILC_PACKET_MAX_ID_LEN ||
1729 dst_id_len > SILC_PACKET_MAX_ID_LEN)) {
1730 if (!packet->stream->udp &&
1731 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1732 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1733 packet->src_id_len, packet->dst_id_len));
1737 ret = silc_buffer_unformat(buffer,
1739 SILC_STR_DATA(&packet->src_id, src_id_len),
1740 SILC_STR_UI_CHAR(&dst_id_type),
1741 SILC_STR_DATA(&packet->dst_id, dst_id_len),
1742 SILC_STR_OFFSET(padlen),
1744 if (silc_unlikely(ret == -1)) {
1745 if (!packet->stream->udp &&
1746 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1747 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1751 if (silc_unlikely(src_id_type > SILC_ID_CHANNEL ||
1752 dst_id_type > SILC_ID_CHANNEL)) {
1753 if (!packet->stream->udp &&
1754 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1755 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1756 src_id_type, dst_id_type));
1760 packet->src_id_len = src_id_len;
1761 packet->dst_id_len = dst_id_len;
1762 packet->src_id_type = src_id_type;
1763 packet->dst_id_type = dst_id_type;
1765 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1766 silc_buffer_len(buffer)), buffer->head,
1767 silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1769 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1770 silc_get_packet_name(packet->type)));
1775 /* Dispatch packet to application. Called with stream->lock locked.
1776 Returns FALSE if the stream was destroyed while dispatching a packet. */
1778 static SilcBool silc_packet_dispatch(SilcPacket packet)
1780 SilcPacketStream stream = packet->stream;
1781 SilcPacketProcess p;
1782 SilcBool default_sent = FALSE;
1785 /* Dispatch packet to all packet processors that want it */
1787 if (silc_likely(!stream->process)) {
1788 /* Send to default processor as no others exist */
1789 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1790 silc_mutex_unlock(stream->lock);
1791 if (silc_unlikely(!stream->sc->engine->callbacks->
1792 packet_receive(stream->sc->engine, stream, packet,
1793 stream->sc->engine->callback_context,
1794 stream->stream_context)))
1795 silc_packet_free(packet);
1796 silc_mutex_lock(stream->lock);
1797 return stream->destroyed == FALSE;
1800 silc_dlist_start(stream->process);
1801 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1803 /* If priority is 0 or less, we send to default processor first
1804 because default processor has 0 priority */
1805 if (!default_sent && p->priority <= 0) {
1806 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1807 default_sent = TRUE;
1808 silc_mutex_unlock(stream->lock);
1809 if (stream->sc->engine->callbacks->
1810 packet_receive(stream->sc->engine, stream, packet,
1811 stream->sc->engine->callback_context,
1812 stream->stream_context)) {
1813 silc_mutex_lock(stream->lock);
1814 return stream->destroyed == FALSE;
1816 silc_mutex_lock(stream->lock);
1819 /* Send to processor */
1821 /* Send all packet types */
1822 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1823 silc_mutex_unlock(stream->lock);
1824 if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
1825 p->callback_context,
1826 stream->stream_context)) {
1827 silc_mutex_lock(stream->lock);
1828 return stream->destroyed == FALSE;
1830 silc_mutex_lock(stream->lock);
1832 /* Send specific types */
1833 for (pt = p->types; *pt; pt++) {
1834 if (*pt != packet->type)
1836 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1837 silc_mutex_unlock(stream->lock);
1838 if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
1839 p->callback_context,
1840 stream->stream_context)) {
1841 silc_mutex_lock(stream->lock);
1842 return stream->destroyed == FALSE;
1844 silc_mutex_lock(stream->lock);
1850 if (!default_sent) {
1851 /* Send to default processor as it has not been sent yet */
1852 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1853 silc_mutex_unlock(stream->lock);
1854 if (stream->sc->engine->callbacks->
1855 packet_receive(stream->sc->engine, stream, packet,
1856 stream->sc->engine->callback_context,
1857 stream->stream_context)) {
1858 silc_mutex_lock(stream->lock);
1859 return stream->destroyed == FALSE;
1861 silc_mutex_lock(stream->lock);
1864 /* If we got here, no one wanted the packet, so drop it */
1865 silc_packet_free(packet);
1866 return stream->destroyed == FALSE;
1869 /* Process incoming data and parse packets. Called with stream->lock
1872 static void silc_packet_read_process(SilcPacketStream stream)
1874 SilcBuffer inbuf = &stream->sc->inbuf;
1879 SilcUInt16 packetlen;
1880 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1881 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1882 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1886 /* Parse the packets from the data */
1887 while (silc_buffer_len(inbuf) > 0) {
1889 cipher = stream->receive_key[0];
1890 hmac = stream->receive_hmac[0];
1893 if (silc_unlikely(silc_buffer_len(inbuf) <
1894 (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1895 SILC_PACKET_MIN_HEADER_LEN))) {
1896 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1900 if (silc_likely(hmac))
1901 mac_len = silc_hmac_len(hmac);
1905 /* Decrypt first block of the packet to get the length field out */
1906 if (silc_likely(cipher)) {
1907 block_len = silc_cipher_get_block_len(cipher);
1909 if (stream->iv_included) {
1910 /* SID, IV and sequence number is included in the ciphertext */
1911 sid = (SilcUInt8)inbuf->data[0];
1913 if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR) {
1914 /* Set the CTR mode IV from packet to counter block */
1915 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1916 silc_packet_receive_ctr_increment(stream, iv, inbuf->data + 1);
1919 /* Get IV from packet */
1920 memcpy(iv, inbuf->data + 1, block_len);
1921 ivlen = block_len + 1;
1925 /* Check SID, and get correct decryption key */
1926 if (sid != stream->sid) {
1927 /* If SID is recent get the previous key and use it */
1928 if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1929 stream->receive_key[1] && !stream->receive_hmac[1]) {
1930 cipher = stream->receive_key[1];
1931 hmac = stream->receive_hmac[1];
1933 /* The SID is unknown, drop rest of the data in buffer */
1934 SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1936 silc_mutex_unlock(stream->lock);
1937 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1938 silc_mutex_lock(stream->lock);
1939 silc_buffer_reset(inbuf);
1944 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1946 /* If using CTR mode, increment the counter */
1947 if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
1948 silc_packet_receive_ctr_increment(stream, iv, NULL);
1951 silc_cipher_decrypt(cipher, inbuf->data + ivlen, tmp,
1955 if (stream->iv_included) {
1956 /* Take sequence number from packet */
1957 packet_seq = header;
1961 /* Unencrypted packet */
1962 block_len = SILC_PACKET_MIN_HEADER_LEN;
1963 header = inbuf->data;
1966 /* Get packet length and full packet length with padding */
1967 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1970 if (silc_unlikely(packetlen < SILC_PACKET_MIN_LEN)) {
1971 if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
1972 SILC_LOG_ERROR(("Received too short packet"));
1973 silc_mutex_unlock(stream->lock);
1974 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1975 silc_mutex_lock(stream->lock);
1976 memset(tmp, 0, sizeof(tmp));
1977 silc_buffer_reset(inbuf);
1981 if (silc_buffer_len(inbuf) < paddedlen + ivlen + mac_len) {
1982 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1984 paddedlen + mac_len - silc_buffer_len(inbuf)));
1985 memset(tmp, 0, sizeof(tmp));
1989 /* Check MAC of the packet */
1990 if (silc_unlikely(!silc_packet_check_mac(hmac, inbuf->data,
1992 inbuf->data + ivlen +
1993 paddedlen, packet_seq,
1994 stream->receive_psn))) {
1995 silc_mutex_unlock(stream->lock);
1996 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1997 silc_mutex_lock(stream->lock);
1998 memset(tmp, 0, sizeof(tmp));
1999 silc_buffer_reset(inbuf);
2004 packet = silc_packet_alloc(stream->sc->engine);
2005 if (silc_unlikely(!packet)) {
2006 silc_mutex_unlock(stream->lock);
2007 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2008 silc_mutex_lock(stream->lock);
2009 memset(tmp, 0, sizeof(tmp));
2010 silc_buffer_reset(inbuf);
2013 packet->stream = stream;
2015 /* Allocate more space to packet buffer, if needed */
2016 if (silc_unlikely(silc_buffer_truelen(&packet->buffer) < paddedlen)) {
2017 if (!silc_buffer_realloc(&packet->buffer,
2018 silc_buffer_truelen(&packet->buffer) +
2020 silc_buffer_truelen(&packet->buffer)))) {
2021 silc_mutex_unlock(stream->lock);
2022 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2023 silc_mutex_lock(stream->lock);
2024 silc_packet_free(packet);
2025 memset(tmp, 0, sizeof(tmp));
2026 silc_buffer_reset(inbuf);
2031 /* Parse packet header */
2032 packet->flags = (SilcPacketFlags)header[2];
2033 packet->type = (SilcPacketType)header[3];
2035 if (stream->sc->engine->local_is_router) {
2036 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2037 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2039 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
2040 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
2041 stream->is_router == TRUE))
2044 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2045 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2047 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
2051 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
2052 stream->receive_psn, paddedlen + ivlen + mac_len),
2053 inbuf->data, paddedlen + ivlen + mac_len);
2055 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
2056 silc_buffer_pull_tail(&packet->buffer, paddedlen);
2057 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
2058 silc_buffer_pull(&packet->buffer, block_len - psnlen);
2059 silc_buffer_put(&packet->buffer, (inbuf->data + ivlen +
2060 psnlen + (block_len - psnlen)),
2061 paddedlen - ivlen - psnlen - (block_len - psnlen));
2062 if (silc_likely(cipher)) {
2063 silc_cipher_set_iv(cipher, iv);
2064 ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
2065 &packet->buffer, normal);
2066 if (silc_unlikely(ret < 0)) {
2067 silc_mutex_unlock(stream->lock);
2068 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
2069 silc_mutex_lock(stream->lock);
2070 silc_packet_free(packet);
2071 memset(tmp, 0, sizeof(tmp));
2075 stream->receive_psn++;
2077 silc_buffer_push(&packet->buffer, block_len);
2079 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
2080 silc_buffer_pull(inbuf, paddedlen + mac_len);
2082 /* Parse the packet */
2083 if (silc_unlikely(!silc_packet_parse(packet))) {
2084 silc_mutex_unlock(stream->lock);
2085 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2086 silc_mutex_lock(stream->lock);
2087 silc_packet_free(packet);
2088 memset(tmp, 0, sizeof(tmp));
2092 /* Dispatch the packet to application */
2093 if (!silc_packet_dispatch(packet))
2097 silc_buffer_reset(inbuf);
2101 /****************************** Packet Waiting ******************************/
2103 /* Packet wait receive callback */
2105 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2106 SilcPacketStream stream,
2108 void *callback_context,
2109 void *stream_context);
2111 /* Packet waiting callbacks */
2112 static SilcPacketCallbacks silc_packet_wait_cbs =
2114 silc_packet_wait_packet_receive, NULL, NULL
2117 /* Packet waiting context */
2119 SilcMutex wait_lock;
2121 SilcList packet_queue;
2122 unsigned int stopped : 1;
2125 /* Packet wait receive callback */
2128 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2129 SilcPacketStream stream,
2131 void *callback_context,
2132 void *stream_context)
2134 SilcPacketWait pw = callback_context;
2136 /* Signal the waiting thread for a new packet */
2137 silc_mutex_lock(pw->wait_lock);
2139 if (silc_unlikely(pw->stopped)) {
2140 silc_mutex_unlock(pw->wait_lock);
2144 silc_list_add(pw->packet_queue, packet);
2145 silc_cond_broadcast(pw->wait_cond);
2147 silc_mutex_unlock(pw->wait_lock);
2152 /* Initialize packet waiting */
2154 void *silc_packet_wait_init(SilcPacketStream stream, ...)
2160 pw = silc_calloc(1, sizeof(*pw));
2164 /* Allocate mutex and conditional variable */
2165 if (!silc_mutex_alloc(&pw->wait_lock)) {
2169 if (!silc_cond_alloc(&pw->wait_cond)) {
2170 silc_mutex_free(pw->wait_lock);
2175 /* Link to the packet stream for the requested packet types */
2176 va_start(ap, stream);
2177 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2181 silc_cond_free(pw->wait_cond);
2182 silc_mutex_free(pw->wait_lock);
2187 /* Initialize packet queue */
2188 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2193 /* Uninitialize packet waiting */
2195 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2197 SilcPacketWait pw = waiter;
2200 /* Signal any threads to stop waiting */
2201 silc_mutex_lock(pw->wait_lock);
2203 silc_cond_broadcast(pw->wait_cond);
2204 silc_mutex_unlock(pw->wait_lock);
2206 /* Re-acquire lock and free resources */
2207 silc_mutex_lock(pw->wait_lock);
2208 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2210 /* Free any remaining packets */
2211 silc_list_start(pw->packet_queue);
2212 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2213 silc_packet_free(packet);
2215 silc_mutex_unlock(pw->wait_lock);
2216 silc_cond_free(pw->wait_cond);
2217 silc_mutex_free(pw->wait_lock);
2221 /* Blocks thread until a packet has been received. */
2223 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2225 SilcPacketWait pw = waiter;
2226 SilcBool ret = FALSE;
2228 silc_mutex_lock(pw->wait_lock);
2230 /* Wait here until packet has arrived */
2231 while (silc_list_count(pw->packet_queue) == 0) {
2232 if (silc_unlikely(pw->stopped)) {
2233 silc_mutex_unlock(pw->wait_lock);
2236 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2240 silc_list_start(pw->packet_queue);
2241 *return_packet = silc_list_get(pw->packet_queue);
2242 silc_list_del(pw->packet_queue, *return_packet);
2244 silc_mutex_unlock(pw->wait_lock);
2246 return ret == TRUE ? 1 : 0;