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 SilcBool silc_packet_dispatch(SilcPacket packet);
155 static void silc_packet_read_process(SilcPacketStream stream);
156 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
158 SilcPacketFlags flags,
159 SilcIdType src_id_type,
160 unsigned char *src_id,
161 SilcUInt32 src_id_len,
162 SilcIdType dst_id_type,
163 unsigned char *dst_id,
164 SilcUInt32 dst_id_len,
165 const unsigned char *data,
170 /************************ Static utility functions **************************/
172 /* Injects packet to new stream created with silc_packet_stream_add_remote. */
174 SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
176 SilcPacket packet = context;
177 SilcPacketStream stream = packet->stream;
179 SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
181 silc_mutex_lock(stream->lock);
182 if (!stream->destroyed)
183 silc_packet_dispatch(packet);
184 silc_mutex_unlock(stream->lock);
185 silc_packet_stream_unref(stream);
188 /* Write data to the stream. Must be called with ps->lock locked. Unlocks
189 the lock inside this function, unless no_unlock is TRUE. Unlocks always
190 in case it returns FALSE. */
192 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps,
200 stream = ((SilcPacketStream)ps->stream)->stream;
204 if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
206 /* Connectionless UDP stream */
207 while (silc_buffer_len(&ps->outbuf) > 0) {
208 i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
209 ps->remote_udp->remote_port,
210 ps->outbuf.data, silc_buffer_len(&ps->outbuf));
211 if (silc_unlikely(i == -2)) {
213 silc_buffer_reset(&ps->outbuf);
214 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
218 if (silc_unlikely(i == -1)) {
219 /* Cannot write now, write later. */
221 silc_mutex_unlock(ps->lock);
226 silc_buffer_pull(&ps->outbuf, i);
229 silc_buffer_reset(&ps->outbuf);
231 silc_mutex_unlock(ps->lock);
237 /* Write the data to the stream */
238 while (silc_buffer_len(&ps->outbuf) > 0) {
239 i = silc_stream_write(stream, ps->outbuf.data,
240 silc_buffer_len(&ps->outbuf));
241 if (silc_unlikely(i == 0)) {
243 silc_buffer_reset(&ps->outbuf);
244 silc_mutex_unlock(ps->lock);
245 SILC_PACKET_CALLBACK_EOS(ps);
249 if (silc_unlikely(i == -2)) {
251 silc_buffer_reset(&ps->outbuf);
252 silc_mutex_unlock(ps->lock);
253 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
257 if (silc_unlikely(i == -1)) {
258 /* Cannot write now, write later. */
260 silc_mutex_unlock(ps->lock);
265 silc_buffer_pull(&ps->outbuf, i);
268 silc_buffer_reset(&ps->outbuf);
270 silc_mutex_unlock(ps->lock);
275 /* Reads data from stream. Must be called with the ps->lock locked. If this
276 returns FALSE the lock has been unlocked. If this returns packet stream
277 to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
278 It is returned if the stream is UDP and remote UDP stream exists for
279 the sender of the packet. */
281 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
282 SilcPacketStream *ret_ps)
290 /* Make sure we have fair amount of free space in inbuf */
291 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
292 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
293 SILC_PACKET_DEFAULT_SIZE * 2)) {
294 silc_mutex_unlock(ps->lock);
295 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
299 if (silc_socket_stream_is_udp(stream, &connected)) {
301 /* Connectionless UDP stream, read one UDP packet */
302 char remote_ip[64], tuple[64];
304 SilcPacketStream remote;
306 ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
307 &remote_port, ps->inbuf.tail,
308 silc_buffer_taillen(&ps->inbuf));
309 if (silc_unlikely(ret == -2)) {
311 silc_buffer_reset(&ps->inbuf);
312 silc_mutex_unlock(ps->lock);
313 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
318 /* Cannot read now, do it later. */
319 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
320 silc_mutex_unlock(ps->lock);
324 /* See if remote packet stream exist for this sender */
325 snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
326 silc_mutex_lock(ps->engine->lock);
327 if (silc_hash_table_find(ps->engine->udp_remote, tuple, NULL,
329 /* Found packet stream for this sender, copy the packet */
330 silc_mutex_unlock(ps->engine->lock);
332 SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p",
333 remote_ip, remote_port, remote));
335 silc_mutex_lock(remote->lock);
336 if (ret > silc_buffer_taillen(&remote->inbuf))
337 if (silc_unlikely(!silc_buffer_realloc(&remote->inbuf, ret))) {
338 silc_mutex_unlock(remote->lock);
339 silc_mutex_unlock(ps->lock);
340 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
344 silc_buffer_put_tail(&remote->inbuf, ps->inbuf.tail, ret);
345 silc_buffer_pull_tail(&remote->inbuf, ret);
348 silc_buffer_reset(&ps->inbuf);
349 silc_mutex_unlock(ps->lock);
352 silc_mutex_unlock(ps->engine->lock);
355 if (!ps->remote_udp) {
356 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
357 if (silc_unlikely(!ps->remote_udp)) {
358 silc_mutex_unlock(ps->lock);
359 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
364 /* Save sender IP and port */
365 silc_free(ps->remote_udp->remote_ip);
366 ps->remote_udp->remote_ip = strdup(remote_ip);
367 ps->remote_udp->remote_port = remote_port;
369 silc_buffer_pull_tail(&ps->inbuf, ret);
374 /* Read data from the stream */
375 ret = silc_stream_read(ps->stream, ps->inbuf.tail,
376 silc_buffer_taillen(&ps->inbuf));
378 if (silc_unlikely(ret == 0)) {
380 silc_buffer_reset(&ps->inbuf);
381 silc_mutex_unlock(ps->lock);
382 SILC_PACKET_CALLBACK_EOS(ps);
386 if (silc_unlikely(ret == -2)) {
388 silc_buffer_reset(&ps->inbuf);
389 silc_mutex_unlock(ps->lock);
390 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
395 /* Cannot read now, do it later. */
396 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
397 silc_mutex_unlock(ps->lock);
401 silc_buffer_pull_tail(&ps->inbuf, ret);
405 /* Our stream IO notifier callback. */
407 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
410 SilcPacketStream remote = NULL, ps = context;
412 silc_mutex_lock(ps->lock);
414 if (silc_unlikely(ps->destroyed)) {
415 silc_mutex_unlock(ps->lock);
421 case SILC_STREAM_CAN_WRITE:
422 SILC_LOG_DEBUG(("Writing pending data to stream"));
424 if (silc_unlikely(!silc_buffer_headlen(&ps->outbuf))) {
425 silc_mutex_unlock(ps->lock);
429 /* Write pending data to stream */
430 silc_packet_stream_write(ps, FALSE);
433 case SILC_STREAM_CAN_READ:
434 SILC_LOG_DEBUG(("Reading data from stream"));
436 /* Read data from stream */
437 if (!silc_packet_stream_read(ps, &remote))
440 /* Now process the data */
441 silc_packet_stream_ref(ps);
443 silc_packet_read_process(ps);
444 silc_mutex_unlock(ps->lock);
446 silc_packet_read_process(remote);
447 silc_mutex_unlock(remote->lock);
449 silc_packet_stream_unref(ps);
453 silc_mutex_unlock(ps->lock);
458 /* Allocate packet */
460 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
464 SILC_LOG_DEBUG(("Packet pool count %d",
465 silc_list_count(engine->packet_pool)));
467 silc_mutex_lock(engine->lock);
469 /* Get packet from freelist or allocate new one. */
470 packet = silc_list_get(engine->packet_pool);
474 silc_mutex_unlock(engine->lock);
476 packet = silc_calloc(1, sizeof(*packet));
477 if (silc_unlikely(!packet))
480 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
482 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
483 if (silc_unlikely(!tmp)) {
487 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
488 silc_buffer_reset(&packet->buffer);
493 SILC_LOG_DEBUG(("Get packet %p", packet));
495 /* Delete from freelist */
496 silc_list_del(engine->packet_pool, packet);
498 silc_mutex_unlock(engine->lock);
503 /* UDP remote stream hash table destructor */
505 static void silc_packet_engine_hash_destr(void *key, void *context,
512 /******************************** Packet API ********************************/
514 /* Allocate new packet engine */
517 silc_packet_engine_start(SilcRng rng, SilcBool router,
518 SilcPacketCallbacks *callbacks,
519 void *callback_context)
521 SilcPacketEngine engine;
526 SILC_LOG_DEBUG(("Starting new packet engine"));
530 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
533 engine = silc_calloc(1, sizeof(*engine));
538 engine->local_is_router = router;
539 engine->callbacks = callbacks;
540 engine->callback_context = callback_context;
541 silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
542 silc_mutex_alloc(&engine->lock);
544 /* Allocate packet free list */
545 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
546 for (i = 0; i < 5; i++) {
547 packet = silc_calloc(1, sizeof(*packet));
549 silc_packet_engine_stop(engine);
553 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
555 silc_packet_engine_stop(engine);
558 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
559 silc_buffer_reset(&packet->buffer);
561 silc_list_add(engine->packet_pool, packet);
563 silc_list_start(engine->packet_pool);
568 /* Stop packet engine */
570 void silc_packet_engine_stop(SilcPacketEngine engine)
573 SILC_LOG_DEBUG(("Stopping packet engine"));
583 /* Create new packet stream */
585 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
586 SilcSchedule schedule,
592 SILC_LOG_DEBUG(("Creating new packet stream"));
594 if (!engine || !stream)
597 ps = silc_calloc(1, sizeof(*ps));
603 silc_atomic_init8(&ps->refcnt, 1);
604 silc_mutex_alloc(&ps->lock);
606 /* Allocate buffers */
607 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
609 silc_packet_stream_destroy(ps);
612 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
613 silc_buffer_reset(&ps->inbuf);
614 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
616 silc_packet_stream_destroy(ps);
619 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
620 silc_buffer_reset(&ps->outbuf);
622 /* Initialize packet procesors list */
623 ps->process = silc_dlist_init();
625 silc_packet_stream_destroy(ps);
629 /* Set IO notifier callback */
630 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
633 silc_mutex_lock(engine->lock);
634 silc_list_add(engine->streams, ps);
635 silc_mutex_unlock(engine->lock);
637 /* If this is UDP stream, allocate UDP remote stream hash table */
638 if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
639 engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
640 silc_hash_string_compare, NULL,
641 silc_packet_engine_hash_destr,
647 /* Add new remote packet stream for UDP packet streams */
649 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
650 const char *remote_ip,
651 SilcUInt16 remote_port,
654 SilcPacketEngine engine = stream->engine;
659 SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
660 remote_ip, remote_port, stream));
662 if (!stream || !remote_ip || !remote_port)
665 if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
666 SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
670 ps = silc_calloc(1, sizeof(*ps));
675 silc_atomic_init8(&ps->refcnt, 1);
676 silc_mutex_alloc(&ps->lock);
678 /* Set the UDP packet stream as underlaying stream */
679 silc_packet_stream_ref(stream);
680 ps->stream = (SilcStream)stream;
683 /* Allocate buffers */
684 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
686 silc_packet_stream_destroy(ps);
689 silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
690 silc_buffer_reset(&ps->inbuf);
691 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
693 silc_packet_stream_destroy(ps);
696 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
697 silc_buffer_reset(&ps->outbuf);
699 /* Initialize packet procesors list */
700 ps->process = silc_dlist_init();
702 silc_packet_stream_destroy(ps);
706 /* Add to engine with this IP and port pair */
707 tuple = silc_format("%d%s", remote_port, remote_ip);
708 silc_mutex_lock(engine->lock);
709 if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
710 silc_mutex_unlock(engine->lock);
711 silc_packet_stream_destroy(ps);
714 silc_mutex_unlock(engine->lock);
716 /* Save remote IP and port pair */
717 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
718 if (!ps->remote_udp) {
719 silc_packet_stream_destroy(ps);
722 ps->remote_udp->remote_port = remote_port;
723 ps->remote_udp->remote_ip = strdup(remote_ip);
724 if (!ps->remote_udp->remote_ip) {
725 silc_packet_stream_destroy(ps);
730 /* Inject packet to the new stream */
732 silc_packet_stream_ref(ps);
733 silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
734 silc_packet_stream_inject_packet, packet,
741 /* Destroy packet stream */
743 void silc_packet_stream_destroy(SilcPacketStream stream)
748 if (silc_atomic_get_int8(&stream->refcnt) > 1) {
749 stream->destroyed = TRUE;
753 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
756 /* Delete from engine */
757 silc_mutex_lock(stream->engine->lock);
758 silc_list_del(stream->engine->streams, stream);
759 silc_mutex_unlock(stream->engine->lock);
761 /* Destroy the underlaying stream */
763 silc_stream_destroy(stream->stream);
765 /* Delete from UDP remote hash table */
767 snprintf(tuple, sizeof(tuple), "%d%s", stream->remote_udp->remote_port,
768 stream->remote_udp->remote_ip);
769 silc_mutex_lock(stream->engine->lock);
770 silc_hash_table_del(stream->engine->udp_remote, tuple);
771 silc_mutex_unlock(stream->engine->lock);
773 silc_free(stream->remote_udp->remote_ip);
774 silc_free(stream->remote_udp);
776 /* Unreference the underlaying packet stream */
777 silc_packet_stream_unref((SilcPacketStream)stream->stream);
780 /* Clear and free buffers */
781 silc_buffer_clear(&stream->inbuf);
782 silc_buffer_clear(&stream->outbuf);
783 silc_buffer_purge(&stream->inbuf);
784 silc_buffer_purge(&stream->outbuf);
786 if (stream->process) {
788 silc_dlist_start(stream->process);
789 while ((p = silc_dlist_get(stream->process))) {
792 silc_dlist_del(stream->process, p);
794 silc_dlist_uninit(stream->process);
799 silc_atomic_uninit8(&stream->refcnt);
800 silc_mutex_free(stream->lock);
804 /* Marks as router stream */
806 void silc_packet_stream_set_router(SilcPacketStream stream)
808 stream->is_router = TRUE;
811 /* Mark to include IV in ciphertext */
813 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
815 stream->iv_included = TRUE;
818 /* Links `callbacks' to `stream' for specified packet types */
820 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
821 SilcPacketCallbacks *callbacks,
822 void *callback_context,
823 int priority, va_list ap)
825 SilcPacketProcess p, e;
826 SilcInt32 packet_type;
829 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
833 if (!callbacks->packet_receive)
836 p = silc_calloc(1, sizeof(*p));
840 p->priority = priority;
841 p->callbacks = callbacks;
842 p->callback_context = callback_context;
844 silc_mutex_lock(stream->lock);
846 if (!stream->process) {
847 stream->process = silc_dlist_init();
848 if (!stream->process) {
849 silc_mutex_unlock(stream->lock);
854 /* According to priority set the procesor to correct position. First
855 entry has the highest priority */
856 silc_dlist_start(stream->process);
857 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
858 if (p->priority > e->priority) {
859 silc_dlist_insert(stream->process, p);
864 silc_dlist_add(stream->process, p);
866 /* Get packet types to process */
869 packet_type = va_arg(ap, SilcInt32);
871 if (packet_type == SILC_PACKET_ANY)
874 if (packet_type == -1)
877 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
879 silc_mutex_unlock(stream->lock);
883 p->types[i - 1] = (SilcPacketType)packet_type;
889 silc_mutex_unlock(stream->lock);
891 silc_packet_stream_ref(stream);
896 /* Links `callbacks' to `stream' for specified packet types */
898 SilcBool silc_packet_stream_link(SilcPacketStream stream,
899 SilcPacketCallbacks *callbacks,
900 void *callback_context,
906 va_start(ap, priority);
907 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
914 /* Unlinks `callbacks' from `stream'. */
916 void silc_packet_stream_unlink(SilcPacketStream stream,
917 SilcPacketCallbacks *callbacks,
918 void *callback_context)
922 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
925 silc_mutex_lock(stream->lock);
927 silc_dlist_start(stream->process);
928 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
929 if (p->callbacks == callbacks &&
930 p->callback_context == callback_context) {
931 silc_dlist_del(stream->process, p);
937 if (!silc_dlist_count(stream->process)) {
938 silc_dlist_uninit(stream->process);
939 stream->process = NULL;
942 silc_mutex_unlock(stream->lock);
944 silc_packet_stream_unref(stream);
947 /* Returns TRUE if stream is UDP stream */
949 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream)
951 return stream->udp || silc_socket_stream_is_udp(stream->stream, NULL);
954 /* Return packet sender IP and port for UDP packet stream */
956 SilcBool silc_packet_get_sender(SilcPacket packet,
957 const char **sender_ip,
958 SilcUInt16 *sender_port)
960 if (!packet->stream->remote_udp)
963 *sender_ip = packet->stream->remote_udp->remote_ip;
964 *sender_port = packet->stream->remote_udp->remote_port;
969 /* Reference packet stream */
971 void silc_packet_stream_ref(SilcPacketStream stream)
973 silc_atomic_add_int8(&stream->refcnt, 1);
976 /* Unreference packet stream */
978 void silc_packet_stream_unref(SilcPacketStream stream)
980 if (silc_atomic_sub_int8(&stream->refcnt, 1) == 0)
981 silc_packet_stream_destroy(stream);
986 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
988 return stream->engine;
991 /* Set application context for packet stream */
993 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
995 silc_mutex_lock(stream->lock);
996 stream->stream_context = stream_context;
997 silc_mutex_unlock(stream->lock);
1000 /* Return application context from packet stream */
1002 void *silc_packet_get_context(SilcPacketStream stream)
1005 silc_mutex_lock(stream->lock);
1006 context = stream->stream_context;
1007 silc_mutex_unlock(stream->lock);
1011 /* Change underlaying stream */
1013 void silc_packet_stream_set_stream(SilcPacketStream ps,
1015 SilcSchedule schedule)
1018 silc_stream_set_notifier(ps->stream, schedule, NULL, NULL);
1019 ps->stream = stream;
1020 silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
1023 /* Return underlaying stream */
1025 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
1027 return stream->stream;
1032 SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
1033 SilcCipher receive_key, SilcHmac send_hmac,
1034 SilcHmac receive_hmac, SilcBool rekey)
1036 SILC_LOG_DEBUG(("Setting new keys to packet stream %p", stream));
1038 /* If doing rekey, send REKEY_DONE packet */
1040 /* This will take stream lock. */
1041 if (!silc_packet_send_raw(stream, SILC_PACKET_REKEY_DONE, 0,
1042 stream->src_id_type, stream->src_id,
1043 stream->src_id_len, stream->dst_id_type,
1044 stream->dst_id, stream->dst_id_len,
1045 NULL, 0, stream->send_key[0],
1046 stream->send_hmac[0]))
1049 /* Write the packet to the stream */
1050 if (!silc_packet_stream_write(stream, TRUE))
1053 silc_mutex_lock(stream->lock);
1056 /* In case IV Included is set, save the old keys */
1057 if (stream->iv_included) {
1058 if (stream->send_key[1] && send_key) {
1059 silc_cipher_free(stream->send_key[1]);
1060 stream->send_key[1] = stream->send_key[0];
1062 if (stream->receive_key[1] && receive_key) {
1063 silc_cipher_free(stream->receive_key[1]);
1064 stream->receive_key[1] = stream->receive_key[0];
1066 if (stream->send_hmac[1] && send_hmac) {
1067 silc_hmac_free(stream->send_hmac[1]);
1068 stream->send_hmac[1] = stream->send_hmac[0];
1070 if (stream->receive_hmac[1] && receive_hmac) {
1071 silc_hmac_free(stream->receive_hmac[1]);
1072 stream->receive_hmac[1] = stream->receive_hmac[0];
1075 if (stream->send_key[0] && send_key)
1076 silc_cipher_free(stream->send_key[0]);
1077 if (stream->send_key[1] && receive_key)
1078 silc_cipher_free(stream->receive_key[0]);
1079 if (stream->send_hmac[0] && send_hmac)
1080 silc_hmac_free(stream->send_hmac[0]);
1081 if (stream->receive_hmac[0] && receive_hmac)
1082 silc_hmac_free(stream->receive_hmac[0]);
1087 stream->send_key[0] = send_key;
1089 stream->receive_key[0] = receive_key;
1091 stream->send_hmac[0] = send_hmac;
1093 stream->receive_hmac[0] = receive_hmac;
1095 silc_mutex_unlock(stream->lock);
1099 /* Return current ciphers from packet stream */
1101 SilcBool silc_packet_get_keys(SilcPacketStream stream,
1102 SilcCipher *send_key,
1103 SilcCipher *receive_key,
1104 SilcHmac *send_hmac,
1105 SilcHmac *receive_hmac)
1107 if (!stream->send_key[0] && !stream->receive_key[0] &&
1108 !stream->send_hmac[0] && !stream->receive_hmac[0])
1111 silc_mutex_lock(stream->lock);
1114 *send_key = stream->send_key[0];
1116 *receive_key = stream->receive_key[0];
1118 *send_hmac = stream->send_hmac[0];
1120 *receive_hmac = stream->receive_hmac[0];
1122 silc_mutex_unlock(stream->lock);
1127 /* Set SILC IDs to packet stream */
1129 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1130 SilcIdType src_id_type, const void *src_id,
1131 SilcIdType dst_id_type, const void *dst_id)
1134 unsigned char tmp[32];
1136 if (!src_id && !dst_id)
1139 SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1141 silc_mutex_lock(stream->lock);
1144 silc_free(stream->src_id);
1145 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1146 silc_mutex_unlock(stream->lock);
1149 stream->src_id = silc_memdup(tmp, len);
1150 if (!stream->src_id) {
1151 silc_mutex_unlock(stream->lock);
1154 stream->src_id_type = src_id_type;
1155 stream->src_id_len = len;
1159 silc_free(stream->dst_id);
1160 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1161 silc_mutex_unlock(stream->lock);
1164 stream->dst_id = silc_memdup(tmp, len);
1165 if (!stream->dst_id) {
1166 silc_mutex_unlock(stream->lock);
1169 stream->dst_id_type = dst_id_type;
1170 stream->dst_id_len = len;
1173 silc_mutex_unlock(stream->lock);
1178 /* Adds Security ID (SID) */
1180 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1182 if (!stream->iv_included)
1185 SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1193 void silc_packet_free(SilcPacket packet)
1195 SilcPacketStream stream = packet->stream;
1197 SILC_LOG_DEBUG(("Freeing packet %p", packet));
1199 /* Check for double free */
1200 SILC_ASSERT(packet->stream != NULL);
1202 packet->stream = NULL;
1203 packet->src_id = packet->dst_id = NULL;
1204 silc_buffer_reset(&packet->buffer);
1206 silc_mutex_lock(stream->engine->lock);
1208 /* Put the packet back to freelist */
1209 silc_list_add(stream->engine->packet_pool, packet);
1210 if (silc_list_count(stream->engine->packet_pool) == 1)
1211 silc_list_start(stream->engine->packet_pool);
1213 silc_mutex_unlock(stream->engine->lock);
1216 /****************************** Packet Sending ******************************/
1218 /* Prepare outgoing data buffer for packet sending. Returns the
1219 pointer to that buffer into the `packet'. */
1221 static inline SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1226 unsigned char *oldptr;
1227 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1231 /* Allocate more space if needed */
1232 if (silc_unlikely(silc_buffer_taillen(&stream->outbuf) < totlen)) {
1233 if (!silc_buffer_realloc(&stream->outbuf,
1234 silc_buffer_truelen(&stream->outbuf) + totlen))
1238 /* Pull data area for the new packet, and return pointer to the start of
1239 the data area and save the pointer in to the `packet'. MAC is pulled
1240 later after it's computed. */
1241 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1242 silc_buffer_set(packet, oldptr, totlen);
1243 silc_buffer_push_tail(packet, mac_len);
1248 /* Internal routine to assemble outgoing packet. Assembles and encryptes
1249 the packet. The silc_packet_stream_write needs to be called to send it
1250 after this returns TRUE. */
1252 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
1253 SilcPacketType type,
1254 SilcPacketFlags flags,
1255 SilcIdType src_id_type,
1256 unsigned char *src_id,
1257 SilcUInt32 src_id_len,
1258 SilcIdType dst_id_type,
1259 unsigned char *dst_id,
1260 SilcUInt32 dst_id_len,
1261 const unsigned char *data,
1262 SilcUInt32 data_len,
1266 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1267 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1268 int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
1269 SilcBufferStruct packet;
1271 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1272 "data len %d", silc_get_packet_name(type), stream->send_psn,
1273 flags, src_id_type, dst_id_type, data_len));
1275 /* Get the true length of the packet. This is saved as payload length
1276 into the packet header. This does not include the length of the
1278 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1279 src_id_len + dst_id_len));
1280 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1281 src_id_len + dst_id_len);
1283 /* If IV is included, the SID, IV and sequence number is added to packet */
1284 if (stream->iv_included && cipher) {
1285 psnlen = sizeof(psn);
1286 ivlen = block_len + 1;
1287 iv[0] = stream->sid;
1288 memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1291 /* We automatically figure out the packet structure from the packet
1292 type and flags, and calculate correct length. Private messages with
1293 private keys and channel messages are special packets as their
1294 payload is encrypted already. */
1295 if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1296 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1297 type == SILC_PACKET_CHANNEL_MESSAGE) {
1299 /* Padding is calculated from header + IDs */
1300 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1301 psnlen), block_len, padlen);
1303 /* Length to encrypt, header + IDs + padding. */
1304 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1308 /* Padding is calculated from true length of the packet */
1309 if (flags & SILC_PACKET_FLAG_LONG_PAD)
1310 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1312 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1314 enclen += padlen + psnlen;
1317 /* Remove implementation specific flags */
1318 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1320 /* Get random padding */
1321 for (i = 0; i < padlen; i++) tmppad[i] =
1322 silc_rng_get_byte_fast(stream->engine->rng);
1324 silc_mutex_lock(stream->lock);
1326 /* Get packet pointer from the outgoing buffer */
1327 if (silc_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen
1328 + psnlen, hmac, &packet))) {
1329 silc_mutex_unlock(stream->lock);
1333 SILC_PUT32_MSB(stream->send_psn, psn);
1335 /* Create the packet. This creates the SILC header, adds padding, and
1336 the actual packet data. */
1337 i = silc_buffer_format(&packet,
1338 SILC_STR_DATA(iv, ivlen),
1339 SILC_STR_DATA(psn, psnlen),
1340 SILC_STR_UI_SHORT(truelen),
1341 SILC_STR_UI_CHAR(flags),
1342 SILC_STR_UI_CHAR(type),
1343 SILC_STR_UI_CHAR(padlen),
1344 SILC_STR_UI_CHAR(0),
1345 SILC_STR_UI_CHAR(src_id_len),
1346 SILC_STR_UI_CHAR(dst_id_len),
1347 SILC_STR_UI_CHAR(src_id_type),
1348 SILC_STR_DATA(src_id, src_id_len),
1349 SILC_STR_UI_CHAR(dst_id_type),
1350 SILC_STR_DATA(dst_id, dst_id_len),
1351 SILC_STR_DATA(tmppad, padlen),
1352 SILC_STR_DATA(data, data_len),
1354 if (silc_unlikely(i < 0)) {
1355 silc_mutex_unlock(stream->lock);
1359 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1360 silc_buffer_data(&packet), silc_buffer_len(&packet));
1362 /* Encrypt the packet */
1363 if (silc_likely(cipher)) {
1364 SILC_LOG_DEBUG(("Encrypting packet"));
1365 if (silc_unlikely(!silc_cipher_encrypt(cipher, packet.data + ivlen,
1366 packet.data + ivlen, enclen,
1368 SILC_LOG_ERROR(("Packet encryption failed"));
1369 silc_mutex_unlock(stream->lock);
1375 if (silc_likely(hmac)) {
1378 /* MAC is computed from the entire encrypted packet data, and put
1379 to the end of the packet. */
1380 silc_hmac_init(hmac);
1381 silc_hmac_update(hmac, psn, sizeof(psn));
1382 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1383 silc_hmac_final(hmac, packet.tail, &mac_len);
1384 silc_buffer_pull_tail(&packet, mac_len);
1391 /* Sends a packet */
1393 SilcBool silc_packet_send(SilcPacketStream stream,
1394 SilcPacketType type, SilcPacketFlags flags,
1395 const unsigned char *data, SilcUInt32 data_len)
1399 ret = silc_packet_send_raw(stream, type, flags,
1400 stream->src_id_type,
1403 stream->dst_id_type,
1407 stream->send_key[0],
1408 stream->send_hmac[0]);
1410 /* Write the packet to the stream */
1411 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1414 /* Sends a packet, extended routine */
1416 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1417 SilcPacketType type, SilcPacketFlags flags,
1418 SilcIdType src_id_type, void *src_id,
1419 SilcIdType dst_id_type, void *dst_id,
1420 const unsigned char *data, SilcUInt32 data_len,
1421 SilcCipher cipher, SilcHmac hmac)
1423 unsigned char src_id_data[32], dst_id_data[32];
1424 SilcUInt32 src_id_len, dst_id_len;
1428 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1429 sizeof(src_id_data), &src_id_len))
1432 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1433 sizeof(dst_id_data), &dst_id_len))
1436 ret = silc_packet_send_raw(stream, type, flags,
1437 src_id ? src_id_type : stream->src_id_type,
1438 src_id ? src_id_data : stream->src_id,
1439 src_id ? src_id_len : stream->src_id_len,
1440 dst_id ? dst_id_type : stream->dst_id_type,
1441 dst_id ? dst_id_data : stream->dst_id,
1442 dst_id ? dst_id_len : stream->dst_id_len,
1444 cipher ? cipher : stream->send_key[0],
1445 hmac ? hmac : stream->send_hmac[0]);
1447 /* Write the packet to the stream */
1448 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1451 /* Sends packet after formatting the arguments to buffer */
1453 SilcBool silc_packet_send_va(SilcPacketStream stream,
1454 SilcPacketType type, SilcPacketFlags flags, ...)
1456 SilcBufferStruct buf;
1460 va_start(va, flags);
1462 memset(&buf, 0, sizeof(buf));
1463 if (silc_buffer_format_vp(&buf, va) < 0) {
1468 ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1469 silc_buffer_len(&buf));
1471 silc_buffer_purge(&buf);
1477 /* Sends packet after formatting the arguments to buffer, extended routine */
1479 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1480 SilcPacketType type, SilcPacketFlags flags,
1481 SilcIdType src_id_type, void *src_id,
1482 SilcIdType dst_id_type, void *dst_id,
1483 SilcCipher cipher, SilcHmac hmac, ...)
1485 SilcBufferStruct buf;
1491 memset(&buf, 0, sizeof(buf));
1492 if (silc_buffer_format_vp(&buf, va) < 0) {
1497 ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1498 dst_id_type, dst_id, silc_buffer_data(&buf),
1499 silc_buffer_len(&buf), cipher, hmac);
1501 silc_buffer_purge(&buf);
1507 /***************************** Packet Receiving *****************************/
1509 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1511 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1512 const unsigned char *data,
1513 SilcUInt32 data_len,
1514 const unsigned char *packet_mac,
1515 const unsigned char *packet_seq,
1516 SilcUInt32 sequence)
1519 if (silc_likely(hmac)) {
1520 unsigned char mac[32], psn[4];
1523 SILC_LOG_DEBUG(("Verifying MAC"));
1525 /* Compute HMAC of packet */
1526 silc_hmac_init(hmac);
1529 SILC_PUT32_MSB(sequence, psn);
1530 silc_hmac_update(hmac, psn, 4);
1532 silc_hmac_update(hmac, packet_seq, 4);
1534 silc_hmac_update(hmac, data, data_len);
1535 silc_hmac_final(hmac, mac, &mac_len);
1537 /* Compare the MAC's */
1538 if (silc_unlikely(memcmp(packet_mac, mac, mac_len))) {
1539 SILC_LOG_DEBUG(("MAC failed"));
1543 SILC_LOG_DEBUG(("MAC is Ok"));
1549 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1550 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1552 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1553 SilcUInt32 sequence, SilcBuffer buffer,
1556 if (normal == TRUE) {
1557 if (silc_likely(cipher)) {
1558 /* Decrypt rest of the packet */
1559 SILC_LOG_DEBUG(("Decrypting the packet"));
1560 if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1562 silc_buffer_len(buffer), NULL)))
1568 /* Decrypt rest of the header plus padding */
1569 if (silc_likely(cipher)) {
1571 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1573 SILC_LOG_DEBUG(("Decrypting the header"));
1575 /* Padding length + src id len + dst id len + header length - 16
1576 bytes already decrypted, gives the rest of the encrypted packet */
1577 silc_buffer_push(buffer, block_len);
1578 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1579 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1581 silc_buffer_pull(buffer, block_len);
1583 if (silc_unlikely(len > silc_buffer_len(buffer))) {
1584 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1588 if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1589 buffer->data, len, NULL)))
1597 /* Parses the packet. This is called when a whole packet is ready to be
1598 parsed. The buffer sent must be already decrypted before calling this
1601 static inline SilcBool silc_packet_parse(SilcPacket packet)
1603 SilcBuffer buffer = &packet->buffer;
1604 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1605 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1608 SILC_LOG_DEBUG(("Parsing incoming packet"));
1610 /* Parse the buffer. This parses the SILC header of the packet. */
1611 ret = silc_buffer_unformat(buffer,
1614 SILC_STR_UI_CHAR(&src_id_len),
1615 SILC_STR_UI_CHAR(&dst_id_len),
1616 SILC_STR_UI_CHAR(&src_id_type),
1618 if (silc_unlikely(ret == -1)) {
1619 if (!packet->stream->udp &&
1620 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1621 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1625 if (silc_unlikely(src_id_len > SILC_PACKET_MAX_ID_LEN ||
1626 dst_id_len > SILC_PACKET_MAX_ID_LEN)) {
1627 if (!packet->stream->udp &&
1628 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1629 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1630 packet->src_id_len, packet->dst_id_len));
1634 ret = silc_buffer_unformat(buffer,
1636 SILC_STR_DATA(&packet->src_id, src_id_len),
1637 SILC_STR_UI_CHAR(&dst_id_type),
1638 SILC_STR_DATA(&packet->dst_id, dst_id_len),
1639 SILC_STR_OFFSET(padlen),
1641 if (silc_unlikely(ret == -1)) {
1642 if (!packet->stream->udp &&
1643 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1644 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1648 if (silc_unlikely(src_id_type > SILC_ID_CHANNEL ||
1649 dst_id_type > SILC_ID_CHANNEL)) {
1650 if (!packet->stream->udp &&
1651 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1652 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1653 src_id_type, dst_id_type));
1657 packet->src_id_len = src_id_len;
1658 packet->dst_id_len = dst_id_len;
1659 packet->src_id_type = src_id_type;
1660 packet->dst_id_type = dst_id_type;
1662 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1663 silc_buffer_len(buffer)), buffer->head,
1664 silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1666 SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1667 silc_get_packet_name(packet->type)));
1672 /* Dispatch packet to application. Called with stream->lock locked.
1673 Returns FALSE if the stream was destroyed while dispatching a packet. */
1675 static SilcBool silc_packet_dispatch(SilcPacket packet)
1677 SilcPacketStream stream = packet->stream;
1678 SilcPacketProcess p;
1679 SilcBool default_sent = FALSE;
1682 /* Dispatch packet to all packet processors that want it */
1684 if (silc_likely(!stream->process)) {
1685 /* Send to default processor as no others exist */
1686 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1687 silc_mutex_unlock(stream->lock);
1688 if (silc_unlikely(!stream->engine->callbacks->
1689 packet_receive(stream->engine, stream, packet,
1690 stream->engine->callback_context,
1691 stream->stream_context)))
1692 silc_packet_free(packet);
1693 silc_mutex_lock(stream->lock);
1694 return stream->destroyed == FALSE;
1697 silc_dlist_start(stream->process);
1698 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1700 /* If priority is 0 or less, we send to default processor first
1701 because default processor has 0 priority */
1702 if (!default_sent && p->priority <= 0) {
1703 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1704 default_sent = TRUE;
1705 silc_mutex_unlock(stream->lock);
1706 if (stream->engine->callbacks->
1707 packet_receive(stream->engine, stream, packet,
1708 stream->engine->callback_context,
1709 stream->stream_context)) {
1710 silc_mutex_lock(stream->lock);
1711 return stream->destroyed == FALSE;
1713 silc_mutex_lock(stream->lock);
1716 /* Send to processor */
1718 /* Send all packet types */
1719 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1720 silc_mutex_unlock(stream->lock);
1721 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1722 p->callback_context,
1723 stream->stream_context)) {
1724 silc_mutex_lock(stream->lock);
1725 return stream->destroyed == FALSE;
1727 silc_mutex_lock(stream->lock);
1729 /* Send specific types */
1730 for (pt = p->types; *pt; pt++) {
1731 if (*pt != packet->type)
1733 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1734 silc_mutex_unlock(stream->lock);
1735 if (p->callbacks->packet_receive(stream->engine, stream, packet,
1736 p->callback_context,
1737 stream->stream_context)) {
1738 silc_mutex_lock(stream->lock);
1739 return stream->destroyed == FALSE;
1741 silc_mutex_lock(stream->lock);
1747 if (!default_sent) {
1748 /* Send to default processor as it has not been sent yet */
1749 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1750 silc_mutex_unlock(stream->lock);
1751 if (stream->engine->callbacks->
1752 packet_receive(stream->engine, stream, packet,
1753 stream->engine->callback_context,
1754 stream->stream_context)) {
1755 silc_mutex_lock(stream->lock);
1756 return stream->destroyed == FALSE;
1758 silc_mutex_lock(stream->lock);
1761 /* If we got here, no one wanted the packet, so drop it */
1762 silc_packet_free(packet);
1763 return stream->destroyed == FALSE;
1766 /* Process incoming data and parse packets. Called with stream->lock
1769 static void silc_packet_read_process(SilcPacketStream stream)
1775 SilcUInt16 packetlen;
1776 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1777 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1778 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1782 /* Parse the packets from the data */
1783 while (silc_buffer_len(&stream->inbuf) > 0) {
1785 cipher = stream->receive_key[0];
1786 hmac = stream->receive_hmac[0];
1789 if (silc_unlikely(silc_buffer_len(&stream->inbuf) <
1790 (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1791 SILC_PACKET_MIN_HEADER_LEN))) {
1792 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1796 if (silc_likely(hmac))
1797 mac_len = silc_hmac_len(hmac);
1801 /* Decrypt first block of the packet to get the length field out */
1802 if (silc_likely(cipher)) {
1803 block_len = silc_cipher_get_block_len(cipher);
1805 if (stream->iv_included) {
1806 /* SID, IV and sequence number is included in the ciphertext */
1807 sid = (SilcUInt8)stream->inbuf.data[0];
1808 memcpy(iv, stream->inbuf.data + 1, block_len);
1809 ivlen = block_len + 1;
1812 /* Check SID, and get correct decryption key */
1813 if (sid != stream->sid) {
1814 /* If SID is recent get the previous key and use it */
1815 if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1816 stream->receive_key[1] && !stream->receive_hmac[1]) {
1817 cipher = stream->receive_key[1];
1818 hmac = stream->receive_hmac[1];
1820 /* The SID is unknown, drop rest of the data in buffer */
1821 SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1823 silc_mutex_unlock(stream->lock);
1824 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1825 silc_mutex_lock(stream->lock);
1826 silc_buffer_reset(&stream->inbuf);
1831 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1834 silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1838 if (stream->iv_included) {
1839 /* Take sequence number from packet */
1840 packet_seq = header;
1844 block_len = SILC_PACKET_MIN_HEADER_LEN;
1845 header = stream->inbuf.data;
1848 /* Get packet length and full packet length with padding */
1849 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1852 if (silc_unlikely(packetlen < SILC_PACKET_MIN_LEN)) {
1853 if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
1854 SILC_LOG_ERROR(("Received too short packet"));
1855 silc_mutex_unlock(stream->lock);
1856 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1857 silc_mutex_lock(stream->lock);
1858 memset(tmp, 0, sizeof(tmp));
1859 silc_buffer_reset(&stream->inbuf);
1863 if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1864 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1866 paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1867 memset(tmp, 0, sizeof(tmp));
1871 /* Check MAC of the packet */
1872 if (silc_unlikely(!silc_packet_check_mac(hmac, stream->inbuf.data,
1874 stream->inbuf.data + ivlen +
1875 paddedlen, packet_seq,
1876 stream->receive_psn))) {
1877 silc_mutex_unlock(stream->lock);
1878 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1879 silc_mutex_lock(stream->lock);
1880 memset(tmp, 0, sizeof(tmp));
1881 silc_buffer_reset(&stream->inbuf);
1886 packet = silc_packet_alloc(stream->engine);
1887 if (silc_unlikely(!packet)) {
1888 silc_mutex_unlock(stream->lock);
1889 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1890 silc_mutex_lock(stream->lock);
1891 memset(tmp, 0, sizeof(tmp));
1892 silc_buffer_reset(&stream->inbuf);
1895 packet->stream = stream;
1897 /* Allocate more space to packet buffer, if needed */
1898 if (silc_unlikely(silc_buffer_truelen(&packet->buffer) < paddedlen)) {
1899 if (!silc_buffer_realloc(&packet->buffer,
1900 silc_buffer_truelen(&packet->buffer) +
1902 silc_buffer_truelen(&packet->buffer)))) {
1903 silc_mutex_unlock(stream->lock);
1904 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1905 silc_mutex_lock(stream->lock);
1906 silc_packet_free(packet);
1907 memset(tmp, 0, sizeof(tmp));
1908 silc_buffer_reset(&stream->inbuf);
1913 /* Parse packet header */
1914 packet->flags = (SilcPacketFlags)header[2];
1915 packet->type = (SilcPacketType)header[3];
1917 if (stream->engine->local_is_router) {
1918 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1919 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1921 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1922 (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1923 stream->is_router == TRUE))
1926 if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1927 (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1929 else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1933 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1934 stream->receive_psn, paddedlen + ivlen + mac_len),
1935 stream->inbuf.data, paddedlen + ivlen + mac_len);
1937 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1938 silc_buffer_pull_tail(&packet->buffer, paddedlen);
1939 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1940 silc_buffer_pull(&packet->buffer, block_len - psnlen);
1941 silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1942 psnlen + (block_len - psnlen)),
1943 paddedlen - ivlen - psnlen - (block_len - psnlen));
1944 if (silc_likely(cipher)) {
1945 silc_cipher_set_iv(cipher, iv);
1946 ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1947 &packet->buffer, normal);
1948 if (silc_unlikely(ret < 0)) {
1949 silc_mutex_unlock(stream->lock);
1950 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1951 silc_mutex_lock(stream->lock);
1952 silc_packet_free(packet);
1953 memset(tmp, 0, sizeof(tmp));
1957 stream->receive_psn++;
1959 silc_buffer_push(&packet->buffer, block_len);
1961 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1962 silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1964 /* Parse the packet */
1965 if (silc_unlikely(!silc_packet_parse(packet))) {
1966 silc_mutex_unlock(stream->lock);
1967 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1968 silc_mutex_lock(stream->lock);
1969 silc_packet_free(packet);
1970 memset(tmp, 0, sizeof(tmp));
1974 /* Dispatch the packet to application */
1975 if (!silc_packet_dispatch(packet))
1979 silc_buffer_reset(&stream->inbuf);
1983 /****************************** Packet Waiting ******************************/
1985 /* Packet wait receive callback */
1987 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1988 SilcPacketStream stream,
1990 void *callback_context,
1991 void *stream_context);
1993 /* Packet waiting callbacks */
1994 static SilcPacketCallbacks silc_packet_wait_cbs =
1996 silc_packet_wait_packet_receive, NULL, NULL
1999 /* Packet waiting context */
2001 SilcMutex wait_lock;
2003 SilcList packet_queue;
2004 unsigned int stopped : 1;
2007 /* Packet wait receive callback */
2010 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2011 SilcPacketStream stream,
2013 void *callback_context,
2014 void *stream_context)
2016 SilcPacketWait pw = callback_context;
2018 /* Signal the waiting thread for a new packet */
2019 silc_mutex_lock(pw->wait_lock);
2021 if (silc_unlikely(pw->stopped)) {
2022 silc_mutex_unlock(pw->wait_lock);
2026 silc_list_add(pw->packet_queue, packet);
2027 silc_cond_broadcast(pw->wait_cond);
2029 silc_mutex_unlock(pw->wait_lock);
2034 /* Initialize packet waiting */
2036 void *silc_packet_wait_init(SilcPacketStream stream, ...)
2042 pw = silc_calloc(1, sizeof(*pw));
2046 /* Allocate mutex and conditional variable */
2047 if (!silc_mutex_alloc(&pw->wait_lock)) {
2051 if (!silc_cond_alloc(&pw->wait_cond)) {
2052 silc_mutex_free(pw->wait_lock);
2057 /* Link to the packet stream for the requested packet types */
2058 va_start(ap, stream);
2059 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2063 silc_cond_free(pw->wait_cond);
2064 silc_mutex_free(pw->wait_lock);
2069 /* Initialize packet queue */
2070 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2075 /* Uninitialize packet waiting */
2077 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2079 SilcPacketWait pw = waiter;
2082 /* Signal any threads to stop waiting */
2083 silc_mutex_lock(pw->wait_lock);
2085 silc_cond_broadcast(pw->wait_cond);
2086 silc_mutex_unlock(pw->wait_lock);
2088 /* Re-acquire lock and free resources */
2089 silc_mutex_lock(pw->wait_lock);
2090 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2092 /* Free any remaining packets */
2093 silc_list_start(pw->packet_queue);
2094 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2095 silc_packet_free(packet);
2097 silc_mutex_unlock(pw->wait_lock);
2098 silc_cond_free(pw->wait_cond);
2099 silc_mutex_free(pw->wait_lock);
2103 /* Blocks thread until a packet has been received. */
2105 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2107 SilcPacketWait pw = waiter;
2108 SilcBool ret = FALSE;
2110 silc_mutex_lock(pw->wait_lock);
2112 /* Wait here until packet has arrived */
2113 while (silc_list_count(pw->packet_queue) == 0) {
2114 if (silc_unlikely(pw->stopped)) {
2115 silc_mutex_unlock(pw->wait_lock);
2118 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2122 silc_list_start(pw->packet_queue);
2123 *return_packet = silc_list_get(pw->packet_queue);
2124 silc_list_del(pw->packet_queue, *return_packet);
2126 silc_mutex_unlock(pw->wait_lock);
2128 return ret == TRUE ? 1 : 0;