Fixed UDP transport handling.
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 Pekka Riikonen
8
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.
12
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.
17
18 */
19 /*
20  * Created: Fri Jul 25 18:52:14 1997
21  */
22 /* $Id$ */
23
24 #include "silc.h"
25
26 /************************** Types and definitions ***************************/
27
28 /* Packet engine */
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;
38 };
39
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;
46 } *SilcPacketProcess;
47
48 /* UDP remote stream tuple */
49 typedef struct {
50   char *remote_ip;                       /* Remote IP address */
51   SilcUInt16 remote_port;                /* Remote port */
52 } *SilcPacketRemoteUDP;
53
54 /* Packet stream */
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 */
83 };
84
85 /* Initial size of stream buffers */
86 #define SILC_PACKET_DEFAULT_SIZE  1024
87
88 /* Header length without source and destination ID's. */
89 #define SILC_PACKET_HEADER_LEN 10
90
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
94
95 /* Maximum padding length */
96 #define SILC_PACKET_MAX_PADLEN 128
97
98 /* Default padding length */
99 #define SILC_PACKET_DEFAULT_PADLEN 16
100
101 /* Minimum packet length */
102 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
103
104 /* Returns true length of the packet. */
105 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
106 do {                                                                     \
107   SILC_GET16_MSB((__ret_truelen), (__packetdata));                       \
108   (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4];    \
109 } while(0)
110
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)
120
121 /* Calculates the length of the padding in the packet. */
122 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen)               \
123 do {                                                                        \
124   __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) %                  \
125               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN));  \
126   if (__padlen < 8)                                                         \
127     __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
128 } while(0)
129
130 /* Returns the length of the padding up to the maximum length, which
131    is 128 bytes.*/
132 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen)          \
133 do {                                                                       \
134   __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) %                     \
135               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
136 } while(0)
137
138 /* EOS callback */
139 #define SILC_PACKET_CALLBACK_EOS(s)                                     \
140 do {                                                                    \
141   (s)->engine->callbacks->eos((s)->engine, s,                           \
142                               (s)->engine->callback_context,            \
143                               (s)->stream_context);                     \
144 } while(0)
145
146 /* Error callback */
147 #define SILC_PACKET_CALLBACK_ERROR(s, err)                              \
148 do {                                                                    \
149   (s)->engine->callbacks->error((s)->engine, s, err,                    \
150                                 (s)->engine->callback_context,          \
151                                 (s)->stream_context);                   \
152 } while(0)
153
154 static void silc_packet_dispatch(SilcPacket packet);
155 static void silc_packet_read_process(SilcPacketStream stream);
156
157 /************************ Static utility functions **************************/
158
159 /* Injects packet to new stream created with silc_packet_stream_add_remote. */
160
161 SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
162 {
163   SilcPacket packet = context;
164   SilcPacketStream stream = packet->stream;
165
166   SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
167
168   silc_mutex_lock(stream->lock);
169   silc_packet_dispatch(packet);
170   silc_mutex_unlock(stream->lock);
171 }
172
173 /* Write data to the stream.  Must be called with ps->lock locked.  Unlocks
174    the lock inside this function. */
175
176 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps)
177 {
178   SilcStream stream;
179   SilcBool connected;
180   int i;
181
182   if (ps->udp)
183     stream = ((SilcPacketStream)ps->stream)->stream;
184   else
185     stream = ps->stream;
186
187   if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
188     if (!connected) {
189       /* Connectionless UDP stream */
190       while (silc_buffer_len(&ps->outbuf) > 0) {
191         i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
192                               ps->remote_udp->remote_port,
193                               ps->outbuf.data, silc_buffer_len(&ps->outbuf));
194         if (i == -2) {
195           /* Error */
196           silc_buffer_reset(&ps->outbuf);
197           silc_mutex_unlock(ps->lock);
198           SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
199           return FALSE;
200         }
201
202         if (i == -1) {
203           /* Cannot write now, write later. */
204           silc_mutex_unlock(ps->lock);
205           return TRUE;
206         }
207
208         /* Wrote data */
209         silc_buffer_pull(&ps->outbuf, i);
210       }
211
212       silc_buffer_reset(&ps->outbuf);
213       silc_mutex_unlock(ps->lock);
214
215       return TRUE;
216     }
217   }
218
219   /* Write the data to the stream */
220   while (silc_buffer_len(&ps->outbuf) > 0) {
221     i = silc_stream_write(stream, ps->outbuf.data,
222                           silc_buffer_len(&ps->outbuf));
223     if (i == 0) {
224       /* EOS */
225       silc_buffer_reset(&ps->outbuf);
226       silc_mutex_unlock(ps->lock);
227       SILC_PACKET_CALLBACK_EOS(ps);
228       return FALSE;
229     }
230
231     if (i == -2) {
232       /* Error */
233       silc_buffer_reset(&ps->outbuf);
234       silc_mutex_unlock(ps->lock);
235       SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
236       return FALSE;
237     }
238
239     if (i == -1) {
240       /* Cannot write now, write later. */
241       silc_mutex_unlock(ps->lock);
242       return TRUE;
243     }
244
245     /* Wrote data */
246     silc_buffer_pull(&ps->outbuf, i);
247   }
248
249   silc_buffer_reset(&ps->outbuf);
250   silc_mutex_unlock(ps->lock);
251
252   return TRUE;
253 }
254
255 /* Reads data from stream.  Must be called with the ps->lock locked.  If this
256    returns FALSE the lock has been unlocked.  If this returns packet stream
257    to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
258    It is returned if the stream is UDP and remote UDP stream exists for
259    the sender of the packet. */
260
261 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
262                                                SilcPacketStream *ret_ps)
263 {
264   SilcStream stream;
265   SilcBool connected;
266   int ret;
267
268   stream = ps->stream;
269
270   /* Make sure we have fair amount of free space in inbuf */
271   if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
272     if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
273                              SILC_PACKET_DEFAULT_SIZE * 2)) {
274       silc_mutex_unlock(ps->lock);
275       SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
276       return FALSE;
277     }
278
279   if (silc_socket_stream_is_udp(stream, &connected)) {
280     if (!connected) {
281       /* Connectionless UDP stream, read one UDP packet */
282       char remote_ip[64], tuple[64];
283       int remote_port;
284       SilcPacketStream remote;
285
286       ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
287                                  &remote_port, ps->inbuf.tail,
288                                  silc_buffer_taillen(&ps->inbuf));
289       if (ret == -2) {
290         /* Error */
291         silc_buffer_reset(&ps->inbuf);
292         silc_mutex_unlock(ps->lock);
293         SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
294         return FALSE;
295       }
296
297       if (ret == -1) {
298         /* Cannot read now, do it later. */
299         silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
300         silc_mutex_unlock(ps->lock);
301         return FALSE;
302       }
303
304       /* See if remote packet stream exist for this sender */
305       snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
306       silc_mutex_lock(ps->engine->lock);
307       if (silc_hash_table_find(ps->engine->udp_remote, tuple, NULL,
308                                (void *)&remote)) {
309         /* Found packet stream for this sender, copy the packet */
310         silc_mutex_unlock(ps->engine->lock);
311
312         SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p",
313                         remote_ip, remote_port, remote));
314
315         silc_mutex_lock(remote->lock);
316         if (ret > silc_buffer_taillen(&remote->inbuf))
317           if (!silc_buffer_realloc(&remote->inbuf, ret)) {
318             silc_mutex_unlock(remote->lock);
319             silc_mutex_unlock(ps->lock);
320             SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
321             return FALSE;
322           }
323
324         silc_buffer_put_tail(&remote->inbuf, ps->inbuf.tail, ret);
325         silc_buffer_pull_tail(&remote->inbuf, ret);
326         *ret_ps = remote;
327
328         silc_buffer_reset(&ps->inbuf);
329         silc_mutex_unlock(ps->lock);
330         return TRUE;
331       }
332       silc_mutex_unlock(ps->engine->lock);
333
334       /* Unknown sender */
335       if (!ps->remote_udp) {
336         ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
337         if (!ps->remote_udp) {
338           silc_mutex_unlock(ps->lock);
339           SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
340           return FALSE;
341         }
342       }
343
344       /* Save sender IP and port */
345       silc_free(ps->remote_udp->remote_ip);
346       ps->remote_udp->remote_ip = strdup(remote_ip);
347       ps->remote_udp->remote_port = remote_port;
348
349       silc_buffer_pull_tail(&ps->inbuf, ret);
350       return TRUE;
351     }
352   }
353
354   /* Read data from the stream */
355   ret = silc_stream_read(ps->stream, ps->inbuf.tail,
356                          silc_buffer_taillen(&ps->inbuf));
357
358   if (ret == 0) {
359     /* EOS */
360     silc_buffer_reset(&ps->inbuf);
361     silc_mutex_unlock(ps->lock);
362     SILC_PACKET_CALLBACK_EOS(ps);
363     return FALSE;
364   }
365
366   if (ret == -2) {
367     /* Error */
368     silc_buffer_reset(&ps->inbuf);
369     silc_mutex_unlock(ps->lock);
370     SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
371     return FALSE;
372   }
373
374   if (ret == -1) {
375     /* Cannot read now, do it later. */
376     silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
377     silc_mutex_unlock(ps->lock);
378     return FALSE;
379   }
380
381   silc_buffer_pull_tail(&ps->inbuf, ret);
382   return TRUE;
383 }
384
385 /* Our stream IO notifier callback. */
386
387 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
388                                   void *context)
389 {
390   SilcPacketStream remote = NULL, ps = context;
391
392   silc_mutex_lock(ps->lock);
393
394   if (ps->destroyed) {
395     silc_mutex_unlock(ps->lock);
396     return;
397   }
398
399   switch (status) {
400
401   case SILC_STREAM_CAN_WRITE:
402     SILC_LOG_DEBUG(("Writing pending data to stream"));
403
404     if (!silc_buffer_headlen(&ps->outbuf)) {
405       silc_mutex_unlock(ps->lock);
406       return;
407     }
408
409     /* Write pending data to stream */
410     silc_packet_stream_write(ps);
411     break;
412
413   case SILC_STREAM_CAN_READ:
414     SILC_LOG_DEBUG(("Reading data from stream"));
415
416     /* Read data from stream */
417     if (!silc_packet_stream_read(ps, &remote))
418       return;
419
420     /* Now process the data */
421     if (!remote) {
422       silc_packet_read_process(ps);
423       silc_mutex_unlock(ps->lock);
424     } else {
425       silc_packet_read_process(remote);
426       silc_mutex_unlock(remote->lock);
427     }
428     break;
429
430   default:
431     silc_mutex_unlock(ps->lock);
432     break;
433   }
434 }
435
436 /* Allocate packet */
437
438 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
439 {
440   SilcPacket packet;
441
442   SILC_LOG_DEBUG(("Packet pool count %d",
443                   silc_list_count(engine->packet_pool)));
444
445   silc_mutex_lock(engine->lock);
446
447   /* Get packet from freelist or allocate new one. */
448   packet = silc_list_get(engine->packet_pool);
449   if (!packet) {
450     void *tmp;
451
452     silc_mutex_unlock(engine->lock);
453
454     packet = silc_calloc(1, sizeof(*packet));
455     if (!packet)
456       return NULL;
457
458     SILC_LOG_DEBUG(("Allocating new packet %p", packet));
459
460     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
461     if (!tmp) {
462       silc_free(packet);
463       return NULL;
464     }
465     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
466     silc_buffer_reset(&packet->buffer);
467
468     return packet;
469   }
470
471   SILC_LOG_DEBUG(("Get packet %p", packet));
472
473   /* Delete from freelist */
474   silc_list_del(engine->packet_pool, packet);
475
476   silc_mutex_unlock(engine->lock);
477
478   return packet;
479 }
480
481 /* UDP remote stream hash table destructor */
482
483 static void silc_packet_engine_hash_destr(void *key, void *context,
484                                           void *user_context)
485 {
486   silc_free(key);
487 }
488
489
490 /******************************** Packet API ********************************/
491
492 /* Allocate new packet engine */
493
494 SilcPacketEngine
495 silc_packet_engine_start(SilcRng rng, SilcBool router,
496                          SilcPacketCallbacks *callbacks,
497                          void *callback_context)
498 {
499   SilcPacketEngine engine;
500   SilcPacket packet;
501   int i;
502   void *tmp;
503
504   SILC_LOG_DEBUG(("Starting new packet engine"));
505
506   if (!callbacks)
507     return NULL;
508   if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
509     return NULL;
510
511   engine = silc_calloc(1, sizeof(*engine));
512   if (!engine)
513     return NULL;
514
515   engine->rng = rng;
516   engine->local_is_router = router;
517   engine->callbacks = callbacks;
518   engine->callback_context = callback_context;
519   silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
520   silc_mutex_alloc(&engine->lock);
521
522   /* Allocate packet free list */
523   silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
524   for (i = 0; i < 5; i++) {
525     packet = silc_calloc(1, sizeof(*packet));
526     if (!packet) {
527       silc_packet_engine_stop(engine);
528       return NULL;
529     }
530
531     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
532     if (!tmp) {
533       silc_packet_engine_stop(engine);
534       return NULL;
535     }
536     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
537     silc_buffer_reset(&packet->buffer);
538
539     silc_list_add(engine->packet_pool, packet);
540   }
541   silc_list_start(engine->packet_pool);
542
543   return engine;
544 }
545
546 /* Stop packet engine */
547
548 void silc_packet_engine_stop(SilcPacketEngine engine)
549 {
550
551   SILC_LOG_DEBUG(("Stopping packet engine"));
552
553   if (!engine)
554     return;
555
556   /* XXX */
557
558   silc_free(engine);
559 }
560
561 /* Create new packet stream */
562
563 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
564                                            SilcSchedule schedule,
565                                            SilcStream stream)
566 {
567   SilcPacketStream ps;
568   void *tmp;
569
570   SILC_LOG_DEBUG(("Creating new packet stream"));
571
572   if (!engine || !stream)
573     return NULL;
574
575   ps = silc_calloc(1, sizeof(*ps));
576   if (!ps)
577     return NULL;
578
579   ps->engine = engine;
580   ps->stream = stream;
581   silc_atomic_init8(&ps->refcnt, 1);
582   silc_mutex_alloc(&ps->lock);
583
584   /* Allocate buffers */
585   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
586   if (!tmp) {
587     silc_packet_stream_destroy(ps);
588     return NULL;
589   }
590   silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
591   silc_buffer_reset(&ps->inbuf);
592   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
593   if (!tmp) {
594     silc_packet_stream_destroy(ps);
595     return NULL;
596   }
597   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
598   silc_buffer_reset(&ps->outbuf);
599
600   /* Initialize packet procesors list */
601   ps->process = silc_dlist_init();
602   if (!ps->process) {
603     silc_packet_stream_destroy(ps);
604     return NULL;
605   }
606
607   /* Set IO notifier callback */
608   silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
609
610   /* Add to engine */
611   silc_mutex_lock(engine->lock);
612   silc_list_add(engine->streams, ps);
613   silc_mutex_unlock(engine->lock);
614
615   /* If this is UDP stream, allocate UDP remote stream hash table */
616   if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
617     engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
618                                                silc_hash_string_compare, NULL,
619                                                silc_packet_engine_hash_destr,
620                                                NULL, TRUE);
621
622   return ps;
623 }
624
625 /* Add new remote packet stream for UDP packet streams */
626
627 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
628                                                const char *remote_ip,
629                                                SilcUInt16 remote_port,
630                                                SilcPacket packet)
631 {
632   SilcPacketEngine engine = stream->engine;
633   SilcPacketStream ps;
634   char *tuple;
635   void *tmp;
636
637   SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
638                   remote_ip, remote_port, stream));
639
640   if (!stream || !remote_ip || !remote_port)
641     return NULL;
642
643   if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
644     SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
645     return NULL;
646   }
647
648   ps = silc_calloc(1, sizeof(*ps));
649   if (!ps)
650     return NULL;
651
652   ps->engine = engine;
653   silc_atomic_init8(&ps->refcnt, 1);
654   silc_mutex_alloc(&ps->lock);
655
656   /* Set the UDP packet stream as underlaying stream */
657   silc_packet_stream_ref(stream);
658   ps->stream = (SilcStream)stream;
659   ps->udp = TRUE;
660
661   /* Allocate buffers */
662   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
663   if (!tmp) {
664     silc_packet_stream_destroy(ps);
665     return NULL;
666   }
667   silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
668   silc_buffer_reset(&ps->inbuf);
669   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
670   if (!tmp) {
671     silc_packet_stream_destroy(ps);
672     return NULL;
673   }
674   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
675   silc_buffer_reset(&ps->outbuf);
676
677   /* Initialize packet procesors list */
678   ps->process = silc_dlist_init();
679   if (!ps->process) {
680     silc_packet_stream_destroy(ps);
681     return NULL;
682   }
683
684   /* Add to engine with this IP and port pair */
685   tuple = silc_format("%d%s", remote_port, remote_ip);
686   silc_mutex_lock(engine->lock);
687   if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
688     silc_mutex_unlock(engine->lock);
689     silc_packet_stream_destroy(ps);
690     return NULL;
691   }
692   silc_mutex_unlock(engine->lock);
693
694   /* Save remote IP and port pair */
695   ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
696   if (!ps->remote_udp) {
697     silc_packet_stream_destroy(ps);
698     return NULL;
699   }
700   ps->remote_udp->remote_port = remote_port;
701   ps->remote_udp->remote_ip = strdup(remote_ip);
702   if (!ps->remote_udp->remote_ip) {
703     silc_packet_stream_destroy(ps);
704     return NULL;
705   }
706
707   if (packet) {
708     /* Inject packet to the new stream */
709     packet->stream = ps;
710     silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
711                                    silc_packet_stream_inject_packet, packet,
712                                    0, 0);
713   }
714
715   return ps;
716 }
717
718 /* Destroy packet stream */
719
720 void silc_packet_stream_destroy(SilcPacketStream stream)
721 {
722   if (!stream)
723     return;
724
725   if (silc_atomic_get_int8(&stream->refcnt) > 1) {
726     stream->destroyed = TRUE;
727     return;
728   }
729
730   SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
731
732   if (!stream->udp) {
733     /* Delete from engine */
734     silc_mutex_lock(stream->engine->lock);
735     silc_list_del(stream->engine->streams, stream);
736     silc_mutex_unlock(stream->engine->lock);
737
738     /* Destroy the underlaying stream */
739     if (stream->stream)
740       silc_stream_destroy(stream->stream);
741   } else {
742     /* Delete from UDP remote hash table */
743     char tuple[64];
744     snprintf(tuple, sizeof(tuple), "%d%s", stream->remote_udp->remote_port,
745              stream->remote_udp->remote_ip);
746     silc_mutex_lock(stream->engine->lock);
747     silc_hash_table_del(stream->engine->udp_remote, tuple);
748     silc_mutex_unlock(stream->engine->lock);
749
750     silc_free(stream->remote_udp->remote_ip);
751     silc_free(stream->remote_udp);
752
753     /* Unreference the underlaying packet stream */
754     silc_packet_stream_unref((SilcPacketStream)stream->stream);
755   }
756
757   /* Clear and free buffers */
758   silc_buffer_clear(&stream->inbuf);
759   silc_buffer_clear(&stream->outbuf);
760   silc_buffer_purge(&stream->inbuf);
761   silc_buffer_purge(&stream->outbuf);
762
763   /* XXX */
764
765   silc_atomic_uninit8(&stream->refcnt);
766   silc_dlist_uninit(stream->process);
767   silc_mutex_free(stream->lock);
768   silc_free(stream);
769 }
770
771 /* Marks as router stream */
772
773 void silc_packet_stream_set_router(SilcPacketStream stream)
774 {
775   stream->is_router = TRUE;
776 }
777
778 /* Mark to include IV in ciphertext */
779
780 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
781 {
782   stream->iv_included = TRUE;
783 }
784
785 /* Links `callbacks' to `stream' for specified packet types */
786
787 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
788                                            SilcPacketCallbacks *callbacks,
789                                            void *callback_context,
790                                            int priority, va_list ap)
791 {
792   SilcPacketProcess p, e;
793   SilcInt32 packet_type;
794   int i;
795
796   SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
797
798   if (!callbacks)
799     return FALSE;
800   if (!callbacks->packet_receive)
801     return FALSE;
802
803   p = silc_calloc(1, sizeof(*p));
804   if (!p)
805     return FALSE;
806
807   p->priority = priority;
808   p->callbacks = callbacks;
809   p->callback_context = callback_context;
810
811   silc_mutex_lock(stream->lock);
812
813   if (!stream->process) {
814     stream->process = silc_dlist_init();
815     if (!stream->process) {
816       silc_mutex_unlock(stream->lock);
817       return FALSE;
818     }
819   }
820
821   /* According to priority set the procesor to correct position.  First
822      entry has the highest priority */
823   silc_dlist_start(stream->process);
824   while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
825     if (p->priority > e->priority) {
826       silc_dlist_insert(stream->process, p);
827       break;
828     }
829   }
830   if (!e)
831     silc_dlist_add(stream->process, p);
832
833   /* Get packet types to process */
834   i = 1;
835   while (1) {
836     packet_type = va_arg(ap, SilcInt32);
837
838     if (packet_type == SILC_PACKET_ANY)
839       break;
840
841     if (packet_type == -1)
842       break;
843
844     p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
845     if (!p->types) {
846       silc_mutex_unlock(stream->lock);
847       return FALSE;
848     }
849
850     p->types[i - 1] = (SilcPacketType)packet_type;
851     i++;
852   }
853   if (p->types)
854     p->types[i - 1] = 0;
855
856   silc_mutex_unlock(stream->lock);
857
858   silc_packet_stream_ref(stream);
859
860   return TRUE;
861 }
862
863 /* Links `callbacks' to `stream' for specified packet types */
864
865 SilcBool silc_packet_stream_link(SilcPacketStream stream,
866                                  SilcPacketCallbacks *callbacks,
867                                  void *callback_context,
868                                  int priority, ...)
869 {
870   va_list ap;
871   SilcBool ret;
872
873   va_start(ap, priority);
874   ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
875                                    priority, ap);
876   va_end(ap);
877
878   return ret;
879 }
880
881 /* Unlinks `callbacks' from `stream'. */
882
883 void silc_packet_stream_unlink(SilcPacketStream stream,
884                                SilcPacketCallbacks *callbacks,
885                                void *callback_context)
886 {
887   SilcPacketProcess p;
888
889   SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
890                   callbacks, stream));
891
892   silc_mutex_lock(stream->lock);
893
894   silc_dlist_start(stream->process);
895   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
896     if (p->callbacks == callbacks &&
897         p->callback_context == callback_context) {
898       silc_dlist_del(stream->process, p);
899       silc_free(p);
900       break;
901     }
902
903   if (!silc_dlist_count(stream->process)) {
904     silc_dlist_uninit(stream->process);
905     stream->process = NULL;
906   }
907
908   silc_mutex_unlock(stream->lock);
909
910   silc_packet_stream_unref(stream);
911 }
912
913 /* Return packet sender IP and port for UDP packet stream */
914
915 SilcBool silc_packet_get_sender(SilcPacket packet,
916                                 const char **sender_ip,
917                                 SilcUInt16 *sender_port)
918 {
919   if (!packet->stream->remote_udp)
920     return FALSE;
921
922   *sender_ip = packet->stream->remote_udp->remote_ip;
923   *sender_port = packet->stream->remote_udp->remote_port;
924
925   return TRUE;
926 }
927
928 /* Reference packet stream */
929
930 void silc_packet_stream_ref(SilcPacketStream stream)
931 {
932   silc_atomic_add_int8(&stream->refcnt, 1);
933 }
934
935 /* Unreference packet stream */
936
937 void silc_packet_stream_unref(SilcPacketStream stream)
938 {
939   if (silc_atomic_sub_int8(&stream->refcnt, 1) == 0)
940     silc_packet_stream_destroy(stream);
941 }
942
943 /* Return engine */
944
945 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
946 {
947   return stream->engine;
948 }
949
950 /* Set application context for packet stream */
951
952 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
953 {
954   silc_mutex_lock(stream->lock);
955   stream->stream_context = stream_context;
956   silc_mutex_unlock(stream->lock);
957 }
958
959 /* Return application context from packet stream */
960
961 void *silc_packet_get_context(SilcPacketStream stream)
962 {
963   void *context;
964   silc_mutex_lock(stream->lock);
965   context = stream->stream_context;
966   silc_mutex_unlock(stream->lock);
967   return context;
968 }
969
970 /* Change underlaying stream */
971
972 void silc_packet_stream_set_stream(SilcPacketStream ps,
973                                    SilcStream stream,
974                                    SilcSchedule schedule)
975 {
976   if (ps->stream)
977     silc_stream_set_notifier(ps->stream, schedule, NULL, NULL);
978   ps->stream = stream;
979   silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
980 }
981
982 /* Return underlaying stream */
983
984 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
985 {
986   return stream->stream;
987 }
988
989 /* Set ciphers for packet stream */
990
991 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
992                              SilcCipher receive)
993 {
994   SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
995
996   silc_mutex_lock(stream->lock);
997
998   /* In case IV Included is set, save the old key */
999   if (stream->iv_included) {
1000     if (stream->send_key[1]) {
1001       silc_cipher_free(stream->send_key[1]);
1002       stream->send_key[1] = stream->send_key[0];
1003     }
1004     if (stream->receive_key[1]) {
1005       silc_cipher_free(stream->receive_key[1]);
1006       stream->receive_key[1] = stream->receive_key[0];
1007     }
1008   } else {
1009     if (stream->send_key[0])
1010       silc_cipher_free(stream->send_key[0]);
1011     if (stream->send_key[1])
1012       silc_cipher_free(stream->receive_key[0]);
1013   }
1014
1015   stream->send_key[0] = send;
1016   stream->receive_key[0] = receive;
1017
1018   silc_mutex_unlock(stream->lock);
1019 }
1020
1021 /* Return current ciphers from packet stream */
1022
1023 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
1024                                  SilcCipher *receive)
1025 {
1026   if (!stream->send_key[0] && !stream->receive_key[0])
1027     return FALSE;
1028
1029   silc_mutex_lock(stream->lock);
1030
1031   if (send)
1032     *send = stream->send_key[0];
1033   if (receive)
1034     *receive = stream->receive_key[0];
1035
1036   silc_mutex_unlock(stream->lock);
1037
1038   return TRUE;
1039 }
1040
1041 /* Set HMACs for packet stream */
1042
1043 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
1044                            SilcHmac receive)
1045 {
1046   SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
1047
1048   silc_mutex_lock(stream->lock);
1049
1050   /* In case IV Included is set, save the old HMAC */
1051   if (stream->iv_included) {
1052     if (stream->send_hmac[1]) {
1053       silc_hmac_free(stream->send_hmac[1]);
1054       stream->send_hmac[1] = stream->send_hmac[0];
1055     }
1056     if (stream->receive_hmac[1]) {
1057       silc_hmac_free(stream->receive_hmac[1]);
1058       stream->receive_hmac[1] = stream->receive_hmac[0];
1059     }
1060   } else {
1061     if (stream->send_hmac[0])
1062       silc_hmac_free(stream->send_hmac[0]);
1063     if (stream->receive_hmac[0])
1064       silc_hmac_free(stream->receive_hmac[0]);
1065   }
1066
1067   stream->send_hmac[0] = send;
1068   stream->receive_hmac[0] = receive;
1069
1070   silc_mutex_unlock(stream->lock);
1071 }
1072
1073 /* Return current HMACs from packet stream */
1074
1075 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
1076                                SilcHmac *receive)
1077 {
1078   if (!stream->send_hmac[0] && !stream->receive_hmac[0])
1079     return FALSE;
1080
1081   silc_mutex_lock(stream->lock);
1082
1083   if (send)
1084     *send = stream->send_hmac[0];
1085   if (receive)
1086     *receive = stream->receive_hmac[0];
1087
1088   silc_mutex_unlock(stream->lock);
1089
1090   return TRUE;
1091 }
1092
1093 /* Set SILC IDs to packet stream */
1094
1095 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1096                              SilcIdType src_id_type, const void *src_id,
1097                              SilcIdType dst_id_type, const void *dst_id)
1098 {
1099   SilcUInt32 len;
1100   unsigned char tmp[32];
1101
1102   if (!src_id && !dst_id)
1103     return FALSE;
1104
1105   SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1106
1107   silc_mutex_lock(stream->lock);
1108
1109   if (src_id) {
1110     silc_free(stream->src_id);
1111     if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1112       silc_mutex_unlock(stream->lock);
1113       return FALSE;
1114     }
1115     stream->src_id = silc_memdup(tmp, len);
1116     if (!stream->src_id) {
1117       silc_mutex_unlock(stream->lock);
1118       return FALSE;
1119     }
1120     stream->src_id_type = src_id_type;
1121     stream->src_id_len = len;
1122   }
1123
1124   if (dst_id) {
1125     silc_free(stream->dst_id);
1126     if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1127       silc_mutex_unlock(stream->lock);
1128       return FALSE;
1129     }
1130     stream->dst_id = silc_memdup(tmp, len);
1131     if (!stream->dst_id) {
1132       silc_mutex_unlock(stream->lock);
1133       return FALSE;
1134     }
1135     stream->dst_id_type = dst_id_type;
1136     stream->dst_id_len = len;
1137   }
1138
1139   silc_mutex_unlock(stream->lock);
1140
1141   return TRUE;
1142 }
1143
1144 /* Adds Security ID (SID) */
1145
1146 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1147 {
1148   if (!stream->iv_included)
1149     return FALSE;
1150
1151   SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1152
1153   stream->sid = sid;
1154   return TRUE;
1155 }
1156
1157 /* Free packet */
1158
1159 void silc_packet_free(SilcPacket packet)
1160 {
1161   SilcPacketStream stream = packet->stream;
1162
1163   SILC_LOG_DEBUG(("Freeing packet %p", packet));
1164
1165   /* Check for double free */
1166   SILC_ASSERT(packet->stream != NULL);
1167
1168   packet->stream = NULL;
1169   packet->src_id = packet->dst_id = NULL;
1170   silc_buffer_reset(&packet->buffer);
1171
1172   silc_mutex_lock(stream->engine->lock);
1173
1174   /* Put the packet back to freelist */
1175   silc_list_add(stream->engine->packet_pool, packet);
1176   if (silc_list_count(stream->engine->packet_pool) == 1)
1177     silc_list_start(stream->engine->packet_pool);
1178
1179   silc_mutex_unlock(stream->engine->lock);
1180 }
1181
1182 /****************************** Packet Sending ******************************/
1183
1184 /* Prepare outgoing data buffer for packet sending.  Returns the
1185    pointer to that buffer into the `packet'. */
1186
1187 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1188                                          SilcUInt32 totlen,
1189                                          SilcHmac hmac,
1190                                          SilcBuffer packet)
1191 {
1192   unsigned char *oldptr;
1193   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1194
1195   totlen += mac_len;
1196
1197   /* Allocate more space if needed */
1198   if (silc_buffer_taillen(&stream->outbuf) < totlen) {
1199     if (!silc_buffer_realloc(&stream->outbuf,
1200                              silc_buffer_truelen(&stream->outbuf) + totlen))
1201       return FALSE;
1202   }
1203
1204   /* Pull data area for the new packet, and return pointer to the start of
1205      the data area and save the pointer in to the `packet'.  MAC is pulled
1206      later after it's computed. */
1207   oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1208   silc_buffer_set(packet, oldptr, totlen);
1209   silc_buffer_push_tail(packet, mac_len);
1210
1211   return TRUE;
1212 }
1213
1214 /* Internal routine to send packet */
1215
1216 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
1217                                      SilcPacketType type,
1218                                      SilcPacketFlags flags,
1219                                      SilcIdType src_id_type,
1220                                      unsigned char *src_id,
1221                                      SilcUInt32 src_id_len,
1222                                      SilcIdType dst_id_type,
1223                                      unsigned char *dst_id,
1224                                      SilcUInt32 dst_id_len,
1225                                      const unsigned char *data,
1226                                      SilcUInt32 data_len,
1227                                      SilcCipher cipher,
1228                                      SilcHmac hmac)
1229 {
1230   unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1231   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1232   int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
1233   SilcBufferStruct packet;
1234
1235   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1236                   "data len %d", silc_get_packet_name(type), stream->send_psn,
1237                   flags, src_id_type, dst_id_type, data_len));
1238
1239   /* Get the true length of the packet. This is saved as payload length
1240      into the packet header.  This does not include the length of the
1241      padding. */
1242   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1243                                             src_id_len + dst_id_len));
1244   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1245                       src_id_len + dst_id_len);
1246
1247   /* If IV is included, the SID, IV and sequence number is added to packet */
1248   if (stream->iv_included && cipher) {
1249     psnlen = sizeof(psn);
1250     ivlen = block_len + 1;
1251     iv[0] = stream->sid;
1252     memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1253   }
1254
1255   /* We automatically figure out the packet structure from the packet
1256      type and flags, and calculate correct length.  Private messages with
1257      private keys and channel messages are special packets as their
1258      payload is encrypted already. */
1259   if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1260        flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1261       type == SILC_PACKET_CHANNEL_MESSAGE) {
1262
1263     /* Padding is calculated from header + IDs */
1264     SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1265                         psnlen), block_len, padlen);
1266
1267     /* Length to encrypt, header + IDs + padding. */
1268     enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1269               padlen + psnlen);
1270   } else {
1271
1272     /* Padding is calculated from true length of the packet */
1273     if (flags & SILC_PACKET_FLAG_LONG_PAD)
1274       SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1275     else
1276       SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1277
1278     enclen += padlen + psnlen;
1279   }
1280
1281   /* Remove implementation specific flags */
1282   flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1283
1284   /* Get random padding */
1285   for (i = 0; i < padlen; i++) tmppad[i] =
1286                                  silc_rng_get_byte_fast(stream->engine->rng);
1287
1288   silc_mutex_lock(stream->lock);
1289
1290   /* Get packet pointer from the outgoing buffer */
1291   if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
1292                                 hmac, &packet)) {
1293     silc_mutex_unlock(stream->lock);
1294     return FALSE;
1295   }
1296
1297   SILC_PUT32_MSB(stream->send_psn, psn);
1298
1299   /* Create the packet.  This creates the SILC header, adds padding, and
1300      the actual packet data. */
1301   i = silc_buffer_format(&packet,
1302                          SILC_STR_DATA(iv, ivlen),
1303                          SILC_STR_DATA(psn, psnlen),
1304                          SILC_STR_UI_SHORT(truelen),
1305                          SILC_STR_UI_CHAR(flags),
1306                          SILC_STR_UI_CHAR(type),
1307                          SILC_STR_UI_CHAR(padlen),
1308                          SILC_STR_UI_CHAR(0),
1309                          SILC_STR_UI_CHAR(src_id_len),
1310                          SILC_STR_UI_CHAR(dst_id_len),
1311                          SILC_STR_UI_CHAR(src_id_type),
1312                          SILC_STR_DATA(src_id, src_id_len),
1313                          SILC_STR_UI_CHAR(dst_id_type),
1314                          SILC_STR_DATA(dst_id, dst_id_len),
1315                          SILC_STR_DATA(tmppad, padlen),
1316                          SILC_STR_DATA(data, data_len),
1317                          SILC_STR_END);
1318   if (i < 0) {
1319     silc_mutex_unlock(stream->lock);
1320     return FALSE;
1321   }
1322
1323   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1324                    silc_buffer_data(&packet), silc_buffer_len(&packet));
1325
1326   /* Encrypt the packet */
1327   if (cipher) {
1328     SILC_LOG_DEBUG(("Encrypting packet"));
1329     if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
1330                              packet.data + ivlen, enclen, NULL)) {
1331       SILC_LOG_ERROR(("Packet encryption failed"));
1332       silc_mutex_unlock(stream->lock);
1333       return FALSE;
1334     }
1335   }
1336
1337   /* Compute HMAC */
1338   if (hmac) {
1339     SilcUInt32 mac_len;
1340
1341     /* MAC is computed from the entire encrypted packet data, and put
1342        to the end of the packet. */
1343     silc_hmac_init(hmac);
1344     silc_hmac_update(hmac, psn, sizeof(psn));
1345     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1346     silc_hmac_final(hmac, packet.tail, &mac_len);
1347     silc_buffer_pull_tail(&packet, mac_len);
1348     stream->send_psn++;
1349   }
1350
1351   /* Write the packet to the stream */
1352   return silc_packet_stream_write(stream);
1353 }
1354
1355 /* Sends a packet */
1356
1357 SilcBool silc_packet_send(SilcPacketStream stream,
1358                           SilcPacketType type, SilcPacketFlags flags,
1359                           const unsigned char *data, SilcUInt32 data_len)
1360 {
1361   return silc_packet_send_raw(stream, type, flags,
1362                               stream->src_id_type,
1363                               stream->src_id,
1364                               stream->src_id_len,
1365                               stream->dst_id_type,
1366                               stream->dst_id,
1367                               stream->dst_id_len,
1368                               data, data_len,
1369                               stream->send_key[0],
1370                               stream->send_hmac[0]);
1371 }
1372
1373 /* Sends a packet, extended routine */
1374
1375 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1376                               SilcPacketType type, SilcPacketFlags flags,
1377                               SilcIdType src_id_type, void *src_id,
1378                               SilcIdType dst_id_type, void *dst_id,
1379                               const unsigned char *data, SilcUInt32 data_len,
1380                               SilcCipher cipher, SilcHmac hmac)
1381 {
1382   unsigned char src_id_data[32], dst_id_data[32];
1383   SilcUInt32 src_id_len, dst_id_len;
1384
1385   if (src_id)
1386     if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1387                         sizeof(src_id_data), &src_id_len))
1388       return FALSE;
1389   if (dst_id)
1390     if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1391                         sizeof(dst_id_data), &dst_id_len))
1392       return FALSE;
1393
1394   return silc_packet_send_raw(stream, type, flags,
1395                               src_id ? src_id_type : stream->src_id_type,
1396                               src_id ? src_id_data : stream->src_id,
1397                               src_id ? src_id_len : stream->src_id_len,
1398                               dst_id ? dst_id_type : stream->dst_id_type,
1399                               dst_id ? dst_id_data : stream->dst_id,
1400                               dst_id ? dst_id_len : stream->dst_id_len,
1401                               data, data_len,
1402                               cipher ? cipher : stream->send_key[0],
1403                               hmac ? hmac : stream->send_hmac[0]);
1404 }
1405
1406 /* Sends packet after formatting the arguments to buffer */
1407
1408 SilcBool silc_packet_send_va(SilcPacketStream stream,
1409                              SilcPacketType type, SilcPacketFlags flags, ...)
1410 {
1411   SilcBufferStruct buf;
1412   SilcBool ret;
1413   va_list va;
1414
1415   va_start(va, flags);
1416
1417   memset(&buf, 0, sizeof(buf));
1418   if (silc_buffer_format_vp(&buf, va) < 0) {
1419     va_end(va);
1420     return FALSE;
1421   }
1422
1423   ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1424                          silc_buffer_len(&buf));
1425
1426   silc_buffer_purge(&buf);
1427   va_end(va);
1428
1429   return ret;
1430 }
1431
1432 /* Sends packet after formatting the arguments to buffer, extended routine */
1433
1434 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1435                                  SilcPacketType type, SilcPacketFlags flags,
1436                                  SilcIdType src_id_type, void *src_id,
1437                                  SilcIdType dst_id_type, void *dst_id,
1438                                  SilcCipher cipher, SilcHmac hmac, ...)
1439 {
1440   SilcBufferStruct buf;
1441   SilcBool ret;
1442   va_list va;
1443
1444   va_start(va, hmac);
1445
1446   memset(&buf, 0, sizeof(buf));
1447   if (silc_buffer_format_vp(&buf, va) < 0) {
1448     va_end(va);
1449     return FALSE;
1450   }
1451
1452   ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1453                              dst_id_type, dst_id, silc_buffer_data(&buf),
1454                              silc_buffer_len(&buf), cipher, hmac);
1455
1456   silc_buffer_purge(&buf);
1457   va_end(va);
1458
1459   return TRUE;
1460 }
1461
1462 /***************************** Packet Receiving *****************************/
1463
1464 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1465
1466 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1467                                              const unsigned char *data,
1468                                              SilcUInt32 data_len,
1469                                              const unsigned char *packet_mac,
1470                                              const unsigned char *packet_seq,
1471                                              SilcUInt32 sequence)
1472 {
1473   /* Check MAC */
1474   if (hmac) {
1475     unsigned char mac[32], psn[4];
1476     SilcUInt32 mac_len;
1477
1478     SILC_LOG_DEBUG(("Verifying MAC"));
1479
1480     /* Compute HMAC of packet */
1481     silc_hmac_init(hmac);
1482
1483     if (!packet_seq) {
1484       SILC_PUT32_MSB(sequence, psn);
1485       silc_hmac_update(hmac, psn, 4);
1486     } else
1487       silc_hmac_update(hmac, packet_seq, 4);
1488
1489     silc_hmac_update(hmac, data, data_len);
1490     silc_hmac_final(hmac, mac, &mac_len);
1491
1492     /* Compare the MAC's */
1493     if (memcmp(packet_mac, mac, mac_len)) {
1494       SILC_LOG_DEBUG(("MAC failed"));
1495       return FALSE;
1496     }
1497
1498     SILC_LOG_DEBUG(("MAC is Ok"));
1499   }
1500
1501   return TRUE;
1502 }
1503
1504 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
1505    Return 0 when packet is normal and 1 when it it special, -1 on error. */
1506
1507 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1508                                       SilcUInt32 sequence, SilcBuffer buffer,
1509                                       SilcBool normal)
1510 {
1511   if (normal == TRUE) {
1512     if (cipher) {
1513       /* Decrypt rest of the packet */
1514       SILC_LOG_DEBUG(("Decrypting the packet"));
1515       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1516                                silc_buffer_len(buffer), NULL))
1517         return -1;
1518     }
1519     return 0;
1520
1521   } else {
1522     /* Decrypt rest of the header plus padding */
1523     if (cipher) {
1524       SilcUInt16 len;
1525       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1526
1527       SILC_LOG_DEBUG(("Decrypting the header"));
1528
1529       /* Padding length + src id len + dst id len + header length - 16
1530          bytes already decrypted, gives the rest of the encrypted packet */
1531       silc_buffer_push(buffer, block_len);
1532       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1533               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1534              block_len);
1535       silc_buffer_pull(buffer, block_len);
1536
1537       if (len > silc_buffer_len(buffer)) {
1538         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1539                         "packet dropped"));
1540         return -1;
1541       }
1542       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1543                                len, NULL))
1544         return -1;
1545     }
1546
1547     return 1;
1548   }
1549 }
1550
1551 /* Parses the packet. This is called when a whole packet is ready to be
1552    parsed. The buffer sent must be already decrypted before calling this
1553    function. */
1554
1555 static inline SilcBool silc_packet_parse(SilcPacket packet)
1556 {
1557   SilcBuffer buffer = &packet->buffer;
1558   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1559   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1560   int ret;
1561
1562   SILC_LOG_DEBUG(("Parsing incoming packet"));
1563
1564   /* Parse the buffer.  This parses the SILC header of the packet. */
1565   ret = silc_buffer_unformat(buffer,
1566                              SILC_STR_ADVANCE,
1567                              SILC_STR_OFFSET(6),
1568                              SILC_STR_UI_CHAR(&src_id_len),
1569                              SILC_STR_UI_CHAR(&dst_id_len),
1570                              SILC_STR_UI_CHAR(&src_id_type),
1571                              SILC_STR_END);
1572   if (ret == -1) {
1573     if (!packet->stream->udp &&
1574         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1575       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1576     return FALSE;
1577   }
1578
1579   if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1580       dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1581     if (!packet->stream->udp &&
1582         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1583       SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1584                       packet->src_id_len, packet->dst_id_len));
1585     return FALSE;
1586   }
1587
1588   ret = silc_buffer_unformat(buffer,
1589                              SILC_STR_ADVANCE,
1590                              SILC_STR_DATA(&packet->src_id, src_id_len),
1591                              SILC_STR_UI_CHAR(&dst_id_type),
1592                              SILC_STR_DATA(&packet->dst_id, dst_id_len),
1593                              SILC_STR_OFFSET(padlen),
1594                              SILC_STR_END);
1595   if (ret == -1) {
1596     if (!packet->stream->udp &&
1597         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1598       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1599     return FALSE;
1600   }
1601
1602   if (src_id_type > SILC_ID_CHANNEL ||
1603       dst_id_type > SILC_ID_CHANNEL) {
1604     if (!packet->stream->udp &&
1605         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1606       SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1607                       src_id_type, dst_id_type));
1608     return FALSE;
1609   }
1610
1611   packet->src_id_len = src_id_len;
1612   packet->dst_id_len = dst_id_len;
1613   packet->src_id_type = src_id_type;
1614   packet->dst_id_type = dst_id_type;
1615
1616   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1617                    silc_buffer_len(buffer)), buffer->head,
1618                    silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1619
1620   SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1621                   silc_get_packet_name(packet->type)));
1622
1623   return TRUE;
1624 }
1625
1626 /* Dispatch packet to application.  Called with stream->lock locked. */
1627
1628 static void silc_packet_dispatch(SilcPacket packet)
1629 {
1630   SilcPacketStream stream = packet->stream;
1631   SilcPacketProcess p;
1632   SilcBool default_sent = FALSE;
1633   SilcPacketType *pt;
1634
1635   /* Dispatch packet to all packet processors that want it */
1636
1637   if (!stream->process) {
1638     /* Send to default processor as no others exist */
1639     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1640     silc_mutex_unlock(stream->lock);
1641     if (!stream->engine->callbacks->
1642         packet_receive(stream->engine, stream, packet,
1643                        stream->engine->callback_context,
1644                        stream->stream_context))
1645       silc_packet_free(packet);
1646     silc_mutex_lock(stream->lock);
1647     return;
1648   }
1649
1650   silc_dlist_start(stream->process);
1651   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1652
1653     /* If priority is 0 or less, we send to default processor first
1654        because default processor has 0 priority */
1655     if (!default_sent && p->priority <= 0) {
1656       SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1657       default_sent = TRUE;
1658       silc_mutex_unlock(stream->lock);
1659       if (stream->engine->callbacks->
1660           packet_receive(stream->engine, stream, packet,
1661                          stream->engine->callback_context,
1662                          stream->stream_context)) {
1663         silc_mutex_lock(stream->lock);
1664         return;
1665       }
1666       silc_mutex_lock(stream->lock);
1667     }
1668
1669     /* Send to processor */
1670     if (!p->types) {
1671       /* Send all packet types */
1672       SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1673       silc_mutex_unlock(stream->lock);
1674       if (p->callbacks->packet_receive(stream->engine, stream, packet,
1675                                        p->callback_context,
1676                                        stream->stream_context)) {
1677         silc_mutex_lock(stream->lock);
1678         return;
1679       }
1680       silc_mutex_lock(stream->lock);
1681     } else {
1682       /* Send specific types */
1683       for (pt = p->types; *pt; pt++) {
1684         if (*pt != packet->type)
1685           continue;
1686         SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1687         silc_mutex_unlock(stream->lock);
1688         if (p->callbacks->packet_receive(stream->engine, stream, packet,
1689                                          p->callback_context,
1690                                          stream->stream_context)) {
1691           silc_mutex_lock(stream->lock);
1692           return;
1693         }
1694         silc_mutex_lock(stream->lock);
1695         break;
1696       }
1697     }
1698   }
1699
1700   if (!default_sent) {
1701     /* Send to default processor as it has not been sent yet */
1702     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1703     silc_mutex_unlock(stream->lock);
1704     if (stream->engine->callbacks->
1705         packet_receive(stream->engine, stream, packet,
1706                        stream->engine->callback_context,
1707                        stream->stream_context)) {
1708       silc_mutex_lock(stream->lock);
1709       return;
1710     }
1711     silc_mutex_lock(stream->lock);
1712   }
1713
1714   /* If we got here, no one wanted the packet, so drop it */
1715   silc_packet_free(packet);
1716 }
1717
1718 /* Process incoming data and parse packets.  Called with stream->lock
1719    locked. */
1720
1721 static void silc_packet_read_process(SilcPacketStream stream)
1722 {
1723   SilcCipher cipher;
1724   SilcHmac hmac;
1725   SilcPacket packet;
1726   SilcUInt8 sid;
1727   SilcUInt16 packetlen;
1728   SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1729   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1730   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1731   SilcBool normal;
1732   int ret;
1733
1734   /* Parse the packets from the data */
1735   while (silc_buffer_len(&stream->inbuf) > 0) {
1736     ivlen = psnlen = 0;
1737     cipher = stream->receive_key[0];
1738     hmac = stream->receive_hmac[0];
1739     normal = FALSE;
1740
1741     if (silc_buffer_len(&stream->inbuf) <
1742         (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1743          SILC_PACKET_MIN_HEADER_LEN)) {
1744       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1745       return;
1746     }
1747
1748     if (hmac)
1749       mac_len = silc_hmac_len(hmac);
1750     else
1751       mac_len = 0;
1752
1753     /* Decrypt first block of the packet to get the length field out */
1754     if (cipher) {
1755       block_len = silc_cipher_get_block_len(cipher);
1756
1757       if (stream->iv_included) {
1758         /* SID, IV and sequence number is included in the ciphertext */
1759         sid = (SilcUInt8)stream->inbuf.data[0];
1760         memcpy(iv, stream->inbuf.data + 1, block_len);
1761         ivlen = block_len + 1;
1762         psnlen = 4;
1763
1764         /* Check SID, and get correct decryption key */
1765         if (sid != stream->sid) {
1766           /* If SID is recent get the previous key and use it */
1767           if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1768               stream->receive_key[1] && !stream->receive_hmac[1]) {
1769             cipher = stream->receive_key[1];
1770             hmac = stream->receive_hmac[1];
1771           } else {
1772             /* The SID is unknown, drop rest of the data in buffer */
1773             SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1774                             sid, stream->sid));
1775             silc_mutex_unlock(stream->lock);
1776             SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1777             silc_mutex_lock(stream->lock);
1778             silc_buffer_reset(&stream->inbuf);
1779             return;
1780           }
1781         }
1782       } else {
1783         memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1784       }
1785
1786       silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1787                           block_len, iv);
1788
1789       header = tmp;
1790       if (stream->iv_included) {
1791         /* Take sequence number from packet */
1792         packet_seq = header;
1793         header += 4;
1794       }
1795     } else {
1796       block_len = SILC_PACKET_MIN_HEADER_LEN;
1797       header = stream->inbuf.data;
1798     }
1799
1800     /* Get packet length and full packet length with padding */
1801     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1802
1803     /* Sanity checks */
1804     if (packetlen < SILC_PACKET_MIN_LEN) {
1805       if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
1806         SILC_LOG_ERROR(("Received too short packet"));
1807       silc_mutex_unlock(stream->lock);
1808       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1809       silc_mutex_lock(stream->lock);
1810       memset(tmp, 0, sizeof(tmp));
1811       silc_buffer_reset(&stream->inbuf);
1812       return;
1813     }
1814
1815     if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1816       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1817                       "(%d bytes)",
1818                       paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1819       memset(tmp, 0, sizeof(tmp));
1820       return;
1821     }
1822
1823     /* Check MAC of the packet */
1824     if (!silc_packet_check_mac(hmac, stream->inbuf.data,
1825                                paddedlen + ivlen,
1826                                stream->inbuf.data + ivlen + paddedlen,
1827                                packet_seq, stream->receive_psn)) {
1828       silc_mutex_unlock(stream->lock);
1829       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1830       silc_mutex_lock(stream->lock);
1831       memset(tmp, 0, sizeof(tmp));
1832       silc_buffer_reset(&stream->inbuf);
1833       return;
1834     }
1835
1836     /* Get packet */
1837     packet = silc_packet_alloc(stream->engine);
1838     if (!packet) {
1839       silc_mutex_unlock(stream->lock);
1840       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1841       silc_mutex_lock(stream->lock);
1842       memset(tmp, 0, sizeof(tmp));
1843       silc_buffer_reset(&stream->inbuf);
1844       return;
1845     }
1846     packet->stream = stream;
1847
1848     /* Allocate more space to packet buffer, if needed */
1849     if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1850       if (!silc_buffer_realloc(&packet->buffer,
1851                                silc_buffer_truelen(&packet->buffer) +
1852                                (paddedlen -
1853                                 silc_buffer_truelen(&packet->buffer)))) {
1854         silc_mutex_unlock(stream->lock);
1855         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1856         silc_mutex_lock(stream->lock);
1857         silc_packet_free(packet);
1858         memset(tmp, 0, sizeof(tmp));
1859         silc_buffer_reset(&stream->inbuf);
1860         return;
1861       }
1862     }
1863
1864     /* Parse packet header */
1865     packet->flags = (SilcPacketFlags)header[2];
1866     packet->type = (SilcPacketType)header[3];
1867
1868     if (stream->engine->local_is_router) {
1869       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1870           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1871         normal = FALSE;
1872       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1873                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1874                 stream->is_router == TRUE))
1875         normal = TRUE;
1876     } else {
1877       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1878           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1879         normal = FALSE;
1880       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1881         normal = TRUE;
1882     }
1883
1884     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1885                       stream->receive_psn, paddedlen + ivlen + mac_len),
1886                      stream->inbuf.data, paddedlen + ivlen + mac_len);
1887
1888     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1889     silc_buffer_pull_tail(&packet->buffer, paddedlen);
1890     silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1891     silc_buffer_pull(&packet->buffer, block_len - psnlen);
1892     silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1893                                       psnlen + (block_len - psnlen)),
1894                     paddedlen - ivlen - psnlen - (block_len - psnlen));
1895     if (cipher) {
1896       silc_cipher_set_iv(cipher, iv);
1897       ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1898                                 &packet->buffer, normal);
1899       if (ret < 0) {
1900         silc_mutex_unlock(stream->lock);
1901         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1902         silc_mutex_lock(stream->lock);
1903         silc_packet_free(packet);
1904         memset(tmp, 0, sizeof(tmp));
1905         return;
1906       }
1907
1908       stream->receive_psn++;
1909     }
1910     silc_buffer_push(&packet->buffer, block_len);
1911
1912     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1913     silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1914
1915     /* Parse the packet */
1916     if (!silc_packet_parse(packet)) {
1917       silc_mutex_unlock(stream->lock);
1918       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1919       silc_mutex_lock(stream->lock);
1920       silc_packet_free(packet);
1921       memset(tmp, 0, sizeof(tmp));
1922       return;
1923     }
1924
1925     /* Dispatch the packet to application */
1926     silc_packet_dispatch(packet);
1927   }
1928
1929   silc_buffer_reset(&stream->inbuf);
1930 }
1931
1932
1933 /****************************** Packet Waiting ******************************/
1934
1935 /* Packet wait receive callback */
1936 static SilcBool
1937 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1938                                 SilcPacketStream stream,
1939                                 SilcPacket packet,
1940                                 void *callback_context,
1941                                 void *stream_context);
1942
1943 /* Packet waiting callbacks */
1944 static SilcPacketCallbacks silc_packet_wait_cbs =
1945 {
1946   silc_packet_wait_packet_receive, NULL, NULL
1947 };
1948
1949 /* Packet waiting context */
1950 typedef struct {
1951   SilcMutex wait_lock;
1952   SilcCond wait_cond;
1953   SilcList packet_queue;
1954   unsigned int stopped     : 1;
1955 } *SilcPacketWait;
1956
1957 /* Packet wait receive callback */
1958
1959 static SilcBool
1960 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1961                                 SilcPacketStream stream,
1962                                 SilcPacket packet,
1963                                 void *callback_context,
1964                                 void *stream_context)
1965 {
1966   SilcPacketWait pw = callback_context;
1967
1968   /* Signal the waiting thread for a new packet */
1969   silc_mutex_lock(pw->wait_lock);
1970
1971   if (pw->stopped) {
1972     silc_mutex_unlock(pw->wait_lock);
1973     return FALSE;
1974   }
1975
1976   silc_list_add(pw->packet_queue, packet);
1977   silc_cond_broadcast(pw->wait_cond);
1978
1979   silc_mutex_unlock(pw->wait_lock);
1980
1981   return TRUE;
1982 }
1983
1984 /* Initialize packet waiting */
1985
1986 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1987 {
1988   SilcPacketWait pw;
1989   SilcBool ret;
1990   va_list ap;
1991
1992   pw = silc_calloc(1, sizeof(*pw));
1993   if (!pw)
1994     return NULL;
1995
1996   /* Allocate mutex and conditional variable */
1997   if (!silc_mutex_alloc(&pw->wait_lock)) {
1998     silc_free(pw);
1999     return NULL;
2000   }
2001   if (!silc_cond_alloc(&pw->wait_cond)) {
2002     silc_mutex_free(pw->wait_lock);
2003     silc_free(pw);
2004     return NULL;
2005   }
2006
2007   /* Link to the packet stream for the requested packet types */
2008   va_start(ap, stream);
2009   ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2010                                    10000000, ap);
2011   va_end(ap);
2012   if (!ret) {
2013     silc_cond_free(pw->wait_cond);
2014     silc_mutex_free(pw->wait_lock);
2015     silc_free(pw);
2016     return NULL;
2017   }
2018
2019   /* Initialize packet queue */
2020   silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2021
2022   return (void *)pw;
2023 }
2024
2025 /* Uninitialize packet waiting */
2026
2027 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2028 {
2029   SilcPacketWait pw = waiter;
2030   SilcPacket packet;
2031
2032   /* Signal any threads to stop waiting */
2033   silc_mutex_lock(pw->wait_lock);
2034   pw->stopped = TRUE;
2035   silc_cond_broadcast(pw->wait_cond);
2036   silc_mutex_unlock(pw->wait_lock);
2037
2038   /* Re-acquire lock and free resources */
2039   silc_mutex_lock(pw->wait_lock);
2040   silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2041
2042   /* Free any remaining packets */
2043   silc_list_start(pw->packet_queue);
2044   while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2045     silc_packet_free(packet);
2046
2047   silc_mutex_unlock(pw->wait_lock);
2048   silc_cond_free(pw->wait_cond);
2049   silc_mutex_free(pw->wait_lock);
2050   silc_free(pw);
2051 }
2052
2053 /* Blocks thread until a packet has been received. */
2054
2055 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2056 {
2057   SilcPacketWait pw = waiter;
2058   SilcBool ret = FALSE;
2059
2060   silc_mutex_lock(pw->wait_lock);
2061
2062   /* Wait here until packet has arrived */
2063   while (silc_list_count(pw->packet_queue) == 0) {
2064     if (pw->stopped) {
2065       silc_mutex_unlock(pw->wait_lock);
2066       return -1;
2067     }
2068     ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2069   }
2070
2071   /* Return packet */
2072   silc_list_start(pw->packet_queue);
2073   *return_packet = silc_list_get(pw->packet_queue);
2074   silc_list_del(pw->packet_queue, *return_packet);
2075
2076   silc_mutex_unlock(pw->wait_lock);
2077
2078   return ret == TRUE ? 1 : 0;
2079 }