Fixed counter mode encryption/decryption.
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2007 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 /* Per scheduler (which usually means per thread) data.  We put per scheduler
29    data here for accessing without locking.  SILC Schedule dictates that
30    tasks are dispatched in one thread, hence the per scheduler context. */
31 typedef struct {
32   SilcSchedule schedule;                 /* The scheduler */
33   SilcPacketEngine engine;               /* Packet engine */
34   SilcDList inbufs;                      /* Data inbut buffer list */
35   SilcUInt32 stream_count;               /* Number of streams using this */
36 } *SilcPacketEngineContext;
37
38 /* Packet engine */
39 struct SilcPacketEngineStruct {
40   SilcMutex lock;                        /* Engine lock */
41   SilcRng rng;                           /* RNG for engine */
42   SilcHashTable contexts;                /* Per scheduler contexts */
43   SilcPacketCallbacks *callbacks;        /* Packet callbacks */
44   void *callback_context;                /* Context for callbacks */
45   SilcList streams;                      /* All streams in engine */
46   SilcList packet_pool;                  /* Free list for received packets */
47   SilcHashTable udp_remote;              /* UDP remote streams, or NULL */
48   unsigned int local_is_router    : 1;
49 };
50
51 /* Packet processor context */
52 typedef struct SilcPacketProcessStruct {
53   SilcPacketType *types;                 /* Packets to process */
54   SilcPacketCallbacks *callbacks;        /* Callbacks or NULL */
55   void *callback_context;
56   SilcInt32 priority;                    /* Priority */
57 } *SilcPacketProcess;
58
59 /* UDP remote stream tuple */
60 typedef struct {
61   char *remote_ip;                       /* Remote IP address */
62   SilcUInt16 remote_port;                /* Remote port */
63 } *SilcPacketRemoteUDP;
64
65 /* Packet stream */
66 struct SilcPacketStreamStruct {
67   struct SilcPacketStreamStruct *next;
68   SilcPacketEngineContext sc;            /* Per scheduler context */
69   SilcStream stream;                     /* Underlaying stream */
70   SilcMutex lock;                        /* Packet stream lock */
71   SilcDList process;                     /* Packet processors, or NULL */
72   SilcPacketRemoteUDP remote_udp;        /* UDP remote stream tuple, or NULL */
73   void *stream_context;                  /* Stream context */
74   SilcBufferStruct outbuf;               /* Out buffer */
75   SilcBuffer inbuf;                      /* Inbuf from inbuf list or NULL */
76   SilcCipher send_key[2];                /* Sending key */
77   SilcHmac send_hmac[2];                 /* Sending HMAC */
78   SilcCipher receive_key[2];             /* Receiving key */
79   SilcHmac receive_hmac[2];              /* Receiving HMAC */
80   unsigned char *src_id;                 /* Source ID */
81   unsigned char *dst_id;                 /* Destination ID */
82   SilcUInt32 send_psn;                   /* Sending sequence */
83   SilcUInt32 receive_psn;                /* Receiving sequence */
84   SilcAtomic8 refcnt;                    /* Reference counter */
85   SilcUInt8 sid;                         /* Security ID, set if IV included */
86   unsigned int src_id_len  : 6;
87   unsigned int src_id_type : 2;
88   unsigned int dst_id_len  : 6;
89   unsigned int dst_id_type : 2;
90   unsigned int is_router   : 1;          /* Set if router stream */
91   unsigned int destroyed   : 1;          /* Set if destroyed */
92   unsigned int iv_included : 1;          /* Set if IV included */
93   unsigned int udp         : 1;          /* UDP remote stream */
94 };
95
96 /* Initial size of stream buffers */
97 #define SILC_PACKET_DEFAULT_SIZE  1024
98
99 /* Header length without source and destination ID's. */
100 #define SILC_PACKET_HEADER_LEN 10
101
102 /* Minimum length of SILC Packet Header. */
103 #define SILC_PACKET_MIN_HEADER_LEN 16
104 #define SILC_PACKET_MIN_HEADER_LEN_IV 32 + 1
105
106 /* Maximum padding length */
107 #define SILC_PACKET_MAX_PADLEN 128
108
109 /* Default padding length */
110 #define SILC_PACKET_DEFAULT_PADLEN 16
111
112 /* Minimum packet length */
113 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
114
115 /* Returns true length of the packet. */
116 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
117 do {                                                                     \
118   SILC_GET16_MSB((__ret_truelen), (__packetdata));                       \
119   (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4];    \
120 } while(0)
121
122 /* Calculates the data length with given header length.  This macro
123    can be used to check whether the data_len with header_len exceeds
124    SILC_PACKET_MAX_LEN.  If it does, this returns the new data_len
125    so that the SILC_PACKET_MAX_LEN is not exceeded.  If the data_len
126    plus header_len fits SILC_PACKET_MAX_LEN the returned data length
127    is the data_len given as argument. */
128 #define SILC_PACKET_DATALEN(data_len, header_len)                         \
129   ((data_len + header_len) > SILC_PACKET_MAX_LEN ?                        \
130    data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
131
132 /* Calculates the length of the padding in the packet. */
133 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen)               \
134 do {                                                                        \
135   __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) %                  \
136               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN));  \
137   if (__padlen < 8)                                                         \
138     __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
139 } while(0)
140
141 /* Returns the length of the padding up to the maximum length, which
142    is 128 bytes.*/
143 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen)          \
144 do {                                                                       \
145   __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) %                     \
146               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
147 } while(0)
148
149 /* EOS callback */
150 #define SILC_PACKET_CALLBACK_EOS(s)                                     \
151 do {                                                                    \
152   (s)->sc->engine->callbacks->eos((s)->sc->engine, s,                   \
153                                   (s)->sc->engine->callback_context,    \
154                                   (s)->stream_context);                 \
155 } while(0)
156
157 /* Error callback */
158 #define SILC_PACKET_CALLBACK_ERROR(s, err)                              \
159 do {                                                                    \
160   (s)->sc->engine->callbacks->error((s)->sc->engine, s, err,            \
161                                     (s)->sc->engine->callback_context,  \
162                                     (s)->stream_context);               \
163 } while(0)
164
165 static SilcBool silc_packet_dispatch(SilcPacket packet);
166 static void silc_packet_read_process(SilcPacketStream stream);
167 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
168                                             SilcPacketType type,
169                                             SilcPacketFlags flags,
170                                             SilcIdType src_id_type,
171                                             unsigned char *src_id,
172                                             SilcUInt32 src_id_len,
173                                             SilcIdType dst_id_type,
174                                             unsigned char *dst_id,
175                                             SilcUInt32 dst_id_len,
176                                             const unsigned char *data,
177                                             SilcUInt32 data_len,
178                                             SilcCipher cipher,
179                                             SilcHmac hmac);
180
181 /************************ Static utility functions **************************/
182
183 /* Injects packet to new stream created with silc_packet_stream_add_remote. */
184
185 SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
186 {
187   SilcPacket packet = context;
188   SilcPacketStream stream = packet->stream;
189
190   SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
191
192   silc_mutex_lock(stream->lock);
193   if (!stream->destroyed)
194     silc_packet_dispatch(packet);
195   silc_mutex_unlock(stream->lock);
196   silc_packet_stream_unref(stream);
197 }
198
199 /* Write data to the stream.  Must be called with ps->lock locked.  Unlocks
200    the lock inside this function, unless no_unlock is TRUE.  Unlocks always
201    in case it returns FALSE. */
202
203 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps,
204                                                 SilcBool no_unlock)
205 {
206   SilcStream stream;
207   SilcBool connected;
208   int i;
209
210   if (ps->udp)
211     stream = ((SilcPacketStream)ps->stream)->stream;
212   else
213     stream = ps->stream;
214
215   if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
216     if (!connected) {
217       /* Connectionless UDP stream */
218       while (silc_buffer_len(&ps->outbuf) > 0) {
219         i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
220                               ps->remote_udp->remote_port,
221                               ps->outbuf.data, silc_buffer_len(&ps->outbuf));
222         if (silc_unlikely(i == -2)) {
223           /* Error */
224           silc_buffer_reset(&ps->outbuf);
225           SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
226           return FALSE;
227         }
228
229         if (silc_unlikely(i == -1)) {
230           /* Cannot write now, write later. */
231           if (!no_unlock)
232             silc_mutex_unlock(ps->lock);
233           return TRUE;
234         }
235
236         /* Wrote data */
237         silc_buffer_pull(&ps->outbuf, i);
238       }
239
240       silc_buffer_reset(&ps->outbuf);
241       if (!no_unlock)
242         silc_mutex_unlock(ps->lock);
243
244       return TRUE;
245     }
246   }
247
248   /* Write the data to the stream */
249   while (silc_buffer_len(&ps->outbuf) > 0) {
250     i = silc_stream_write(stream, ps->outbuf.data,
251                           silc_buffer_len(&ps->outbuf));
252     if (silc_unlikely(i == 0)) {
253       /* EOS */
254       silc_buffer_reset(&ps->outbuf);
255       silc_mutex_unlock(ps->lock);
256       SILC_PACKET_CALLBACK_EOS(ps);
257       return FALSE;
258     }
259
260     if (silc_unlikely(i == -2)) {
261       /* Error */
262       silc_buffer_reset(&ps->outbuf);
263       silc_mutex_unlock(ps->lock);
264       SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
265       return FALSE;
266     }
267
268     if (silc_unlikely(i == -1)) {
269       /* Cannot write now, write later. */
270       if (!no_unlock)
271         silc_mutex_unlock(ps->lock);
272       return TRUE;
273     }
274
275     /* Wrote data */
276     silc_buffer_pull(&ps->outbuf, i);
277   }
278
279   silc_buffer_reset(&ps->outbuf);
280   if (!no_unlock)
281     silc_mutex_unlock(ps->lock);
282
283   return TRUE;
284 }
285
286 /* Reads data from stream.  Must be called with ps->lock locked.  If this
287    returns FALSE the lock has been unlocked.  If this returns packet stream
288    to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
289    It is returned if the stream is UDP and remote UDP stream exists for
290    the sender of the packet. */
291
292 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
293                                                SilcPacketStream *ret_ps)
294 {
295   SilcStream stream = ps->stream;
296   SilcBuffer inbuf;
297   SilcBool connected;
298   int ret;
299
300   /* Get inbuf.  If there is already some data for this stream in the buffer
301      we already have it.  Otherwise get the current one from list, it will
302      include the data. */
303   inbuf = ps->inbuf;
304   if (!inbuf) {
305     silc_dlist_start(ps->sc->inbufs);
306     inbuf = silc_dlist_get(ps->sc->inbufs);
307     if (!inbuf) {
308       /* Allocate new data input buffer */
309       inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE * 31);
310       if (!inbuf) {
311         silc_mutex_unlock(ps->lock);
312         return FALSE;
313       }
314       silc_buffer_reset(inbuf);
315       silc_dlist_add(ps->sc->inbufs, inbuf);
316     }
317   }
318
319   /* Make sure there is enough room to read */
320   if (SILC_PACKET_DEFAULT_SIZE * 2 > silc_buffer_taillen(inbuf))
321     silc_buffer_realloc(inbuf, silc_buffer_truelen(inbuf) +
322                         (SILC_PACKET_DEFAULT_SIZE * 2));
323
324   if (silc_socket_stream_is_udp(stream, &connected)) {
325     if (!connected) {
326       /* Connectionless UDP stream, read one UDP packet */
327       char remote_ip[64], tuple[64];
328       int remote_port;
329       SilcPacketStream remote;
330
331       ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
332                                  &remote_port, inbuf->tail,
333                                  silc_buffer_taillen(inbuf));
334
335       if (silc_unlikely(ret < 0)) {
336         silc_mutex_unlock(ps->lock);
337         if (ret == -1) {
338           /* Cannot read now, do it later. */
339           silc_buffer_pull(inbuf, silc_buffer_len(inbuf));
340           return FALSE;
341         }
342
343         /* Error */
344         silc_buffer_reset(inbuf);
345         SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
346         return FALSE;
347       }
348
349       /* See if remote packet stream exist for this sender */
350       silc_snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
351       silc_mutex_lock(ps->sc->engine->lock);
352       if (silc_hash_table_find(ps->sc->engine->udp_remote, tuple, NULL,
353                                (void *)&remote)) {
354         silc_mutex_unlock(ps->sc->engine->lock);
355         SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p", remote_ip,
356                         remote_port, remote));
357         silc_mutex_unlock(ps->lock);
358         silc_mutex_lock(remote->lock);
359         *ret_ps = remote;
360         return TRUE;
361       }
362       silc_mutex_unlock(ps->sc->engine->lock);
363
364       /* Unknown sender */
365       if (!ps->remote_udp) {
366         ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
367         if (silc_unlikely(!ps->remote_udp)) {
368           silc_mutex_unlock(ps->lock);
369           SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
370           return FALSE;
371         }
372       }
373
374       /* Save sender IP and port */
375       silc_free(ps->remote_udp->remote_ip);
376       ps->remote_udp->remote_ip = strdup(remote_ip);
377       ps->remote_udp->remote_port = remote_port;
378
379       silc_buffer_pull_tail(inbuf, ret);
380       return TRUE;
381     }
382   }
383
384   /* Read data from the stream */
385   ret = silc_stream_read(stream, inbuf->tail, silc_buffer_taillen(inbuf));
386   if (silc_unlikely(ret <= 0)) {
387     silc_mutex_unlock(ps->lock);
388     if (ret == 0) {
389       /* EOS */
390       silc_buffer_reset(inbuf);
391       SILC_PACKET_CALLBACK_EOS(ps);
392       return FALSE;
393     }
394
395     if (ret == -1) {
396       /* Cannot read now, do it later. */
397       silc_buffer_pull(inbuf, silc_buffer_len(inbuf));
398       return FALSE;
399     }
400
401     /* Error */
402     silc_buffer_reset(inbuf);
403     SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
404     return FALSE;
405   }
406
407   silc_buffer_pull_tail(inbuf, ret);
408   return TRUE;
409 }
410
411 /* Our stream IO notifier callback. */
412
413 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
414                                   void *context)
415 {
416   SilcPacketStream remote = NULL, ps = context;
417
418   silc_mutex_lock(ps->lock);
419
420   if (silc_unlikely(ps->destroyed)) {
421     silc_mutex_unlock(ps->lock);
422     return;
423   }
424
425   switch (status) {
426   case SILC_STREAM_CAN_READ:
427     /* Reading is locked also with stream->lock because we may be reading
428        at the same time other thread is writing to same underlaying stream. */
429     SILC_LOG_DEBUG(("Reading data from stream %p, ps %p", ps->stream, ps));
430
431     /* Read data from stream */
432     if (!silc_packet_stream_read(ps, &remote))
433       return;
434
435     /* Now process the data */
436     silc_packet_stream_ref(ps);
437     if (!remote) {
438       silc_packet_read_process(ps);
439       silc_mutex_unlock(ps->lock);
440     } else {
441       silc_packet_read_process(remote);
442       silc_mutex_unlock(remote->lock);
443     }
444     silc_packet_stream_unref(ps);
445     break;
446
447   case SILC_STREAM_CAN_WRITE:
448     SILC_LOG_DEBUG(("Writing pending data to stream %p, ps %p",
449                     ps->stream, ps));
450
451     if (silc_unlikely(!silc_buffer_headlen(&ps->outbuf))) {
452       silc_mutex_unlock(ps->lock);
453       return;
454     }
455
456     /* Write pending data to stream */
457     silc_packet_stream_write(ps, FALSE);
458     break;
459
460   default:
461     silc_mutex_unlock(ps->lock);
462     break;
463   }
464 }
465
466 /* Allocate packet */
467
468 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
469 {
470   SilcPacket packet;
471
472   SILC_LOG_DEBUG(("Packet pool count %d",
473                   silc_list_count(engine->packet_pool)));
474
475   silc_mutex_lock(engine->lock);
476
477   /* Get packet from freelist or allocate new one. */
478   packet = silc_list_get(engine->packet_pool);
479   if (!packet) {
480     void *tmp;
481
482     silc_mutex_unlock(engine->lock);
483
484     packet = silc_calloc(1, sizeof(*packet));
485     if (silc_unlikely(!packet))
486       return NULL;
487
488     SILC_LOG_DEBUG(("Allocating new packet %p", packet));
489
490     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
491     if (silc_unlikely(!tmp)) {
492       silc_free(packet);
493       return NULL;
494     }
495     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
496     silc_buffer_reset(&packet->buffer);
497
498     return packet;
499   }
500
501   SILC_LOG_DEBUG(("Get packet %p", packet));
502
503   /* Delete from freelist */
504   silc_list_del(engine->packet_pool, packet);
505
506   silc_mutex_unlock(engine->lock);
507
508   return packet;
509 }
510
511 /* UDP remote stream hash table destructor */
512
513 static void silc_packet_engine_hash_destr(void *key, void *context,
514                                           void *user_context)
515 {
516   silc_free(key);
517 }
518
519 /* Per scheduler context hash table destructor */
520
521 static void silc_packet_engine_context_destr(void *key, void *context,
522                                              void *user_context)
523 {
524   SilcPacketEngineContext sc = context;
525   SilcBuffer buffer;
526
527   silc_dlist_start(sc->inbufs);
528   while ((buffer = silc_dlist_get(sc->inbufs))) {
529     silc_buffer_clear(buffer);
530     silc_buffer_free(buffer);
531     silc_dlist_del(sc->inbufs, buffer);
532   }
533
534   silc_dlist_uninit(sc->inbufs);
535   silc_free(sc);
536 }
537
538
539 /******************************** Packet API ********************************/
540
541 /* Allocate new packet engine */
542
543 SilcPacketEngine
544 silc_packet_engine_start(SilcRng rng, SilcBool router,
545                          SilcPacketCallbacks *callbacks,
546                          void *callback_context)
547 {
548   SilcPacketEngine engine;
549   SilcPacket packet;
550   int i;
551   void *tmp;
552
553   SILC_LOG_DEBUG(("Starting new packet engine"));
554
555   if (!callbacks)
556     return NULL;
557   if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
558     return NULL;
559
560   engine = silc_calloc(1, sizeof(*engine));
561   if (!engine)
562     return NULL;
563
564   engine->contexts = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
565                                            silc_packet_engine_context_destr,
566                                            engine, TRUE);
567   if (!engine->contexts) {
568     silc_free(engine);
569     return NULL;
570   }
571
572   engine->rng = rng;
573   engine->local_is_router = router;
574   engine->callbacks = callbacks;
575   engine->callback_context = callback_context;
576   silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
577   silc_mutex_alloc(&engine->lock);
578
579   /* Allocate packet free list */
580   silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
581   for (i = 0; i < 5; i++) {
582     packet = silc_calloc(1, sizeof(*packet));
583     if (!packet) {
584       silc_packet_engine_stop(engine);
585       return NULL;
586     }
587
588     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
589     if (!tmp) {
590       silc_packet_engine_stop(engine);
591       return NULL;
592     }
593     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
594     silc_buffer_reset(&packet->buffer);
595
596     silc_list_add(engine->packet_pool, packet);
597   }
598   silc_list_start(engine->packet_pool);
599
600   return engine;
601 }
602
603 /* Stop packet engine */
604
605 void silc_packet_engine_stop(SilcPacketEngine engine)
606 {
607   SilcPacket packet;
608
609   SILC_LOG_DEBUG(("Stopping packet engine"));
610
611   if (!engine)
612     return;
613
614   /* Free packet free list */
615   silc_list_start(engine->packet_pool);
616   while ((packet = silc_list_get(engine->packet_pool))) {
617     silc_buffer_purge(&packet->buffer);
618     silc_free(packet);
619   }
620
621   silc_hash_table_free(engine->contexts);
622   silc_mutex_free(engine->lock);
623   silc_free(engine);
624 }
625
626 /* Create new packet stream */
627
628 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
629                                            SilcSchedule schedule,
630                                            SilcStream stream)
631 {
632   SilcPacketStream ps;
633   SilcBuffer inbuf;
634   void *tmp;
635
636   SILC_LOG_DEBUG(("Creating new packet stream"));
637
638   if (!engine || !stream)
639     return NULL;
640
641   ps = silc_calloc(1, sizeof(*ps));
642   if (!ps)
643     return NULL;
644
645   ps->stream = stream;
646   silc_atomic_init8(&ps->refcnt, 1);
647   silc_mutex_alloc(&ps->lock);
648
649   /* Allocate out buffer */
650   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
651   if (!tmp) {
652     silc_packet_stream_destroy(ps);
653     return NULL;
654   }
655   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
656   silc_buffer_reset(&ps->outbuf);
657
658   /* Initialize packet procesors list */
659   ps->process = silc_dlist_init();
660   if (!ps->process) {
661     silc_packet_stream_destroy(ps);
662     return NULL;
663   }
664
665   silc_mutex_lock(engine->lock);
666
667   /* Add per scheduler context */
668   if (!silc_hash_table_find(engine->contexts, schedule, NULL,
669                             (void *)&ps->sc)) {
670     ps->sc = silc_calloc(1, sizeof(*ps->sc));
671     if (!ps->sc) {
672       silc_packet_stream_destroy(ps);
673       silc_mutex_unlock(engine->lock);
674       return NULL;
675     }
676     ps->sc->engine = engine;
677     ps->sc->schedule = schedule;
678
679     /* Allocate data input buffer */
680     inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE * 31);
681     if (!inbuf) {
682       silc_free(ps->sc);
683       ps->sc = NULL;
684       silc_packet_stream_destroy(ps);
685       silc_mutex_unlock(engine->lock);
686       return NULL;
687     }
688     silc_buffer_reset(inbuf);
689
690     ps->sc->inbufs = silc_dlist_init();
691     if (!ps->sc->inbufs) {
692       silc_buffer_free(inbuf);
693       silc_free(ps->sc);
694       ps->sc = NULL;
695       silc_packet_stream_destroy(ps);
696       silc_mutex_unlock(engine->lock);
697       return NULL;
698     }
699     silc_dlist_add(ps->sc->inbufs, inbuf);
700
701     /* Add to per scheduler context hash table */
702     if (!silc_hash_table_add(engine->contexts, schedule, ps->sc)) {
703       silc_buffer_free(inbuf);
704       silc_dlist_del(ps->sc->inbufs, inbuf);
705       silc_free(ps->sc);
706       ps->sc = NULL;
707       silc_packet_stream_destroy(ps);
708       silc_mutex_unlock(engine->lock);
709       return NULL;
710     }
711   }
712   ps->sc->stream_count++;
713
714   /* Add the packet stream to engine */
715   silc_list_add(engine->streams, ps);
716
717   /* If this is UDP stream, allocate UDP remote stream hash table */
718   if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
719     engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
720                                                silc_hash_string_compare, NULL,
721                                                silc_packet_engine_hash_destr,
722                                                NULL, TRUE);
723
724   silc_mutex_unlock(engine->lock);
725
726   /* Set IO notifier callback.  This schedules this stream for I/O. */
727   if (!silc_stream_set_notifier(ps->stream, schedule,
728                                 silc_packet_stream_io, ps)) {
729     SILC_LOG_DEBUG(("Cannot set stream notifier for packet stream"));
730     silc_packet_stream_destroy(ps);
731     return NULL;
732   }
733
734   return ps;
735 }
736
737 /* Add new remote packet stream for UDP packet streams */
738
739 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
740                                                const char *remote_ip,
741                                                SilcUInt16 remote_port,
742                                                SilcPacket packet)
743 {
744   SilcPacketEngine engine = stream->sc->engine;
745   SilcPacketStream ps;
746   char *tuple;
747   void *tmp;
748
749   SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
750                   remote_ip, remote_port, stream));
751
752   if (!stream || !remote_ip || !remote_port)
753     return NULL;
754
755   if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
756     SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
757     return NULL;
758   }
759
760   ps = silc_calloc(1, sizeof(*ps));
761   if (!ps)
762     return NULL;
763   ps->sc = stream->sc;
764
765   silc_atomic_init8(&ps->refcnt, 1);
766   silc_mutex_alloc(&ps->lock);
767
768   /* Set the UDP packet stream as underlaying stream */
769   silc_packet_stream_ref(stream);
770   ps->stream = (SilcStream)stream;
771   ps->udp = TRUE;
772
773   /* Allocate out buffer */
774   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
775   if (!tmp) {
776     silc_packet_stream_destroy(ps);
777     return NULL;
778   }
779   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
780   silc_buffer_reset(&ps->outbuf);
781
782   /* Initialize packet procesors list */
783   ps->process = silc_dlist_init();
784   if (!ps->process) {
785     silc_packet_stream_destroy(ps);
786     return NULL;
787   }
788
789   /* Add to engine with this IP and port pair */
790   tuple = silc_format("%d%s", remote_port, remote_ip);
791   silc_mutex_lock(engine->lock);
792   if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
793     silc_mutex_unlock(engine->lock);
794     silc_packet_stream_destroy(ps);
795     return NULL;
796   }
797   silc_mutex_unlock(engine->lock);
798
799   /* Save remote IP and port pair */
800   ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
801   if (!ps->remote_udp) {
802     silc_packet_stream_destroy(ps);
803     return NULL;
804   }
805   ps->remote_udp->remote_port = remote_port;
806   ps->remote_udp->remote_ip = strdup(remote_ip);
807   if (!ps->remote_udp->remote_ip) {
808     silc_packet_stream_destroy(ps);
809     return NULL;
810   }
811
812   if (packet) {
813     /* Inject packet to the new stream */
814     packet->stream = ps;
815     silc_packet_stream_ref(ps);
816     silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
817                                    silc_packet_stream_inject_packet, packet,
818                                    0, 0);
819   }
820
821   return ps;
822 }
823
824 /* Destroy packet stream */
825
826 void silc_packet_stream_destroy(SilcPacketStream stream)
827 {
828   if (!stream)
829     return;
830
831   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0) {
832     stream->destroyed = TRUE;
833
834     /* Close the underlaying stream */
835     if (!stream->udp && stream->stream)
836       silc_stream_close(stream->stream);
837     return;
838   }
839
840   SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
841
842   if (!stream->udp) {
843     /* Delete from engine */
844     silc_mutex_lock(stream->sc->engine->lock);
845     silc_list_del(stream->sc->engine->streams, stream);
846
847     /* Remove per scheduler context, if it is not used anymore */
848     if (stream->sc) {
849       stream->sc->stream_count--;
850       if (!stream->sc->stream_count)
851         silc_hash_table_del(stream->sc->engine->contexts,
852                             stream->sc->schedule);
853     }
854     silc_mutex_unlock(stream->sc->engine->lock);
855
856     /* Destroy the underlaying stream */
857     if (stream->stream)
858       silc_stream_destroy(stream->stream);
859   } else {
860     /* Delete from UDP remote hash table */
861     char tuple[64];
862     silc_snprintf(tuple, sizeof(tuple), "%d%s", stream->remote_udp->remote_port,
863              stream->remote_udp->remote_ip);
864     silc_mutex_lock(stream->sc->engine->lock);
865     silc_hash_table_del(stream->sc->engine->udp_remote, tuple);
866     silc_mutex_unlock(stream->sc->engine->lock);
867
868     silc_free(stream->remote_udp->remote_ip);
869     silc_free(stream->remote_udp);
870
871     /* Unreference the underlaying packet stream */
872     silc_packet_stream_unref((SilcPacketStream)stream->stream);
873   }
874
875   /* Clear and free buffers */
876   silc_buffer_clear(&stream->outbuf);
877   silc_buffer_purge(&stream->outbuf);
878
879   if (stream->process) {
880     SilcPacketProcess p;
881     silc_dlist_start(stream->process);
882     while ((p = silc_dlist_get(stream->process))) {
883       silc_free(p->types);
884       silc_free(p);
885       silc_dlist_del(stream->process, p);
886     }
887     silc_dlist_uninit(stream->process);
888   }
889
890   /* Destroy ciphers and HMACs */
891   if (stream->send_key[0])
892     silc_cipher_free(stream->send_key[0]);
893   if (stream->receive_key[0])
894     silc_cipher_free(stream->receive_key[0]);
895   if (stream->send_hmac[0])
896     silc_hmac_free(stream->send_hmac[0]);
897   if (stream->receive_hmac[0])
898     silc_hmac_free(stream->receive_hmac[0]);
899   if (stream->send_key[1])
900     silc_cipher_free(stream->send_key[1]);
901   if (stream->receive_key[1])
902     silc_cipher_free(stream->receive_key[1]);
903   if (stream->send_hmac[1])
904     silc_hmac_free(stream->send_hmac[1]);
905   if (stream->receive_hmac[1])
906     silc_hmac_free(stream->receive_hmac[1]);
907
908   /* Free IDs */
909   silc_free(stream->src_id);
910   silc_free(stream->dst_id);
911
912   silc_atomic_uninit8(&stream->refcnt);
913   silc_mutex_free(stream->lock);
914   silc_free(stream);
915 }
916
917 /* Marks as router stream */
918
919 void silc_packet_stream_set_router(SilcPacketStream stream)
920 {
921   stream->is_router = TRUE;
922 }
923
924 /* Mark to include IV in ciphertext */
925
926 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
927 {
928   stream->iv_included = TRUE;
929 }
930
931 /* Links `callbacks' to `stream' for specified packet types */
932
933 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
934                                            SilcPacketCallbacks *callbacks,
935                                            void *callback_context,
936                                            int priority, va_list ap)
937 {
938   SilcPacketProcess p, e;
939   SilcInt32 packet_type;
940   int i;
941
942   SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
943
944   if (!callbacks)
945     return FALSE;
946   if (!callbacks->packet_receive)
947     return FALSE;
948
949   p = silc_calloc(1, sizeof(*p));
950   if (!p)
951     return FALSE;
952
953   p->priority = priority;
954   p->callbacks = callbacks;
955   p->callback_context = callback_context;
956
957   silc_mutex_lock(stream->lock);
958
959   if (!stream->process) {
960     stream->process = silc_dlist_init();
961     if (!stream->process) {
962       silc_mutex_unlock(stream->lock);
963       return FALSE;
964     }
965   }
966
967   /* According to priority set the procesor to correct position.  First
968      entry has the highest priority */
969   silc_dlist_start(stream->process);
970   while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
971     if (p->priority > e->priority) {
972       silc_dlist_insert(stream->process, p);
973       break;
974     }
975   }
976   if (!e)
977     silc_dlist_add(stream->process, p);
978
979   /* Get packet types to process */
980   i = 1;
981   while (1) {
982     packet_type = va_arg(ap, SilcInt32);
983
984     if (packet_type == SILC_PACKET_ANY)
985       break;
986
987     if (packet_type == -1)
988       break;
989
990     p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
991     if (!p->types) {
992       silc_mutex_unlock(stream->lock);
993       return FALSE;
994     }
995
996     p->types[i - 1] = (SilcPacketType)packet_type;
997     i++;
998   }
999   if (p->types)
1000     p->types[i - 1] = 0;
1001
1002   silc_mutex_unlock(stream->lock);
1003
1004   silc_packet_stream_ref(stream);
1005
1006   return TRUE;
1007 }
1008
1009 /* Links `callbacks' to `stream' for specified packet types */
1010
1011 SilcBool silc_packet_stream_link(SilcPacketStream stream,
1012                                  SilcPacketCallbacks *callbacks,
1013                                  void *callback_context,
1014                                  int priority, ...)
1015 {
1016   va_list ap;
1017   SilcBool ret;
1018
1019   va_start(ap, priority);
1020   ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
1021                                    priority, ap);
1022   va_end(ap);
1023
1024   return ret;
1025 }
1026
1027 /* Unlinks `callbacks' from `stream'. */
1028
1029 void silc_packet_stream_unlink(SilcPacketStream stream,
1030                                SilcPacketCallbacks *callbacks,
1031                                void *callback_context)
1032 {
1033   SilcPacketProcess p;
1034
1035   SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
1036                   callbacks, stream));
1037
1038   silc_mutex_lock(stream->lock);
1039
1040   silc_dlist_start(stream->process);
1041   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
1042     if (p->callbacks == callbacks &&
1043         p->callback_context == callback_context) {
1044       silc_dlist_del(stream->process, p);
1045       silc_free(p->types);
1046       silc_free(p);
1047       break;
1048     }
1049
1050   if (!silc_dlist_count(stream->process)) {
1051     silc_dlist_uninit(stream->process);
1052     stream->process = NULL;
1053   }
1054
1055   silc_mutex_unlock(stream->lock);
1056
1057   silc_packet_stream_unref(stream);
1058 }
1059
1060 /* Returns TRUE if stream is UDP stream */
1061
1062 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream)
1063 {
1064   return stream->udp || silc_socket_stream_is_udp(stream->stream, NULL);
1065 }
1066
1067 /* Return packet sender IP and port for UDP packet stream */
1068
1069 SilcBool silc_packet_get_sender(SilcPacket packet,
1070                                 const char **sender_ip,
1071                                 SilcUInt16 *sender_port)
1072 {
1073   if (!packet->stream->remote_udp)
1074     return FALSE;
1075
1076   *sender_ip = packet->stream->remote_udp->remote_ip;
1077   *sender_port = packet->stream->remote_udp->remote_port;
1078
1079   return TRUE;
1080 }
1081
1082 /* Reference packet stream */
1083
1084 void silc_packet_stream_ref(SilcPacketStream stream)
1085 {
1086   silc_atomic_add_int8(&stream->refcnt, 1);
1087   SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1088                   silc_atomic_get_int8(&stream->refcnt) - 1,
1089                   silc_atomic_get_int8(&stream->refcnt)));
1090 }
1091
1092 /* Unreference packet stream */
1093
1094 void silc_packet_stream_unref(SilcPacketStream stream)
1095 {
1096   SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1097                   silc_atomic_get_int8(&stream->refcnt),
1098                   silc_atomic_get_int8(&stream->refcnt) - 1));
1099   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0)
1100     return;
1101   silc_atomic_add_int8(&stream->refcnt, 1);
1102   silc_packet_stream_destroy(stream);
1103 }
1104
1105 /* Return engine */
1106
1107 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
1108 {
1109   return stream->sc->engine;
1110 }
1111
1112 /* Set application context for packet stream */
1113
1114 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
1115 {
1116   silc_mutex_lock(stream->lock);
1117   stream->stream_context = stream_context;
1118   silc_mutex_unlock(stream->lock);
1119 }
1120
1121 /* Return application context from packet stream */
1122
1123 void *silc_packet_get_context(SilcPacketStream stream)
1124 {
1125   void *context;
1126   silc_mutex_lock(stream->lock);
1127   context = stream->stream_context;
1128   silc_mutex_unlock(stream->lock);
1129   return context;
1130 }
1131
1132 /* Change underlaying stream */
1133
1134 void silc_packet_stream_set_stream(SilcPacketStream ps,
1135                                    SilcStream stream)
1136 {
1137   if (ps->stream)
1138     silc_stream_set_notifier(ps->stream, ps->sc->schedule, NULL, NULL);
1139   ps->stream = stream;
1140   silc_stream_set_notifier(ps->stream, ps->sc->schedule, silc_packet_stream_io,
1141                            ps);
1142 }
1143
1144 /* Return underlaying stream */
1145
1146 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
1147 {
1148   return stream->stream;
1149 }
1150
1151 /* Set keys. */
1152
1153 SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
1154                               SilcCipher receive_key, SilcHmac send_hmac,
1155                               SilcHmac receive_hmac, SilcBool rekey)
1156 {
1157   SILC_LOG_DEBUG(("Setting new keys to packet stream %p", stream));
1158
1159   /* If doing rekey, send REKEY_DONE packet */
1160   if (rekey) {
1161     /* This will take stream lock. */
1162     if (!silc_packet_send_raw(stream, SILC_PACKET_REKEY_DONE, 0,
1163                               stream->src_id_type, stream->src_id,
1164                               stream->src_id_len, stream->dst_id_type,
1165                               stream->dst_id, stream->dst_id_len,
1166                               NULL, 0, stream->send_key[0],
1167                               stream->send_hmac[0]))
1168       return FALSE;
1169
1170     /* Write the packet to the stream */
1171     if (!silc_packet_stream_write(stream, TRUE))
1172       return FALSE;
1173   } else {
1174     silc_mutex_lock(stream->lock);
1175   }
1176
1177   /* In case IV Included is set, save the old keys */
1178   if (stream->iv_included) {
1179     if (stream->send_key[1] && send_key) {
1180       silc_cipher_free(stream->send_key[1]);
1181       stream->send_key[1] = stream->send_key[0];
1182     }
1183     if (stream->receive_key[1] && receive_key) {
1184       silc_cipher_free(stream->receive_key[1]);
1185       stream->receive_key[1] = stream->receive_key[0];
1186     }
1187     if (stream->send_hmac[1] && send_hmac) {
1188       silc_hmac_free(stream->send_hmac[1]);
1189       stream->send_hmac[1] = stream->send_hmac[0];
1190     }
1191     if (stream->receive_hmac[1] && receive_hmac) {
1192       silc_hmac_free(stream->receive_hmac[1]);
1193       stream->receive_hmac[1] = stream->receive_hmac[0];
1194     }
1195   } else {
1196     if (stream->send_key[0] && send_key)
1197       silc_cipher_free(stream->send_key[0]);
1198     if (stream->receive_key[0] && receive_key)
1199       silc_cipher_free(stream->receive_key[0]);
1200     if (stream->send_hmac[0] && send_hmac)
1201       silc_hmac_free(stream->send_hmac[0]);
1202     if (stream->receive_hmac[0] && receive_hmac)
1203       silc_hmac_free(stream->receive_hmac[0]);
1204   }
1205
1206   /* Set keys */
1207   if (send_key)
1208     stream->send_key[0] = send_key;
1209   if (receive_key)
1210     stream->receive_key[0] = receive_key;
1211   if (send_hmac)
1212     stream->send_hmac[0] = send_hmac;
1213   if (receive_hmac)
1214     stream->receive_hmac[0] = receive_hmac;
1215
1216   silc_mutex_unlock(stream->lock);
1217   return TRUE;
1218 }
1219
1220 /* Return current ciphers from packet stream */
1221
1222 SilcBool silc_packet_get_keys(SilcPacketStream stream,
1223                               SilcCipher *send_key,
1224                               SilcCipher *receive_key,
1225                               SilcHmac *send_hmac,
1226                               SilcHmac *receive_hmac)
1227 {
1228   if (!stream->send_key[0] && !stream->receive_key[0] &&
1229       !stream->send_hmac[0] && !stream->receive_hmac[0])
1230     return FALSE;
1231
1232   silc_mutex_lock(stream->lock);
1233
1234   if (send_key)
1235     *send_key = stream->send_key[0];
1236   if (receive_key)
1237     *receive_key = stream->receive_key[0];
1238   if (send_hmac)
1239     *send_hmac = stream->send_hmac[0];
1240   if (receive_hmac)
1241     *receive_hmac = stream->receive_hmac[0];
1242
1243   silc_mutex_unlock(stream->lock);
1244
1245   return TRUE;
1246 }
1247
1248 /* Set SILC IDs to packet stream */
1249
1250 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1251                              SilcIdType src_id_type, const void *src_id,
1252                              SilcIdType dst_id_type, const void *dst_id)
1253 {
1254   SilcUInt32 len;
1255   unsigned char tmp[32];
1256
1257   if (!src_id && !dst_id)
1258     return FALSE;
1259
1260   SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1261
1262   silc_mutex_lock(stream->lock);
1263
1264   if (src_id) {
1265     silc_free(stream->src_id);
1266     if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1267       silc_mutex_unlock(stream->lock);
1268       return FALSE;
1269     }
1270     stream->src_id = silc_memdup(tmp, len);
1271     if (!stream->src_id) {
1272       silc_mutex_unlock(stream->lock);
1273       return FALSE;
1274     }
1275     stream->src_id_type = src_id_type;
1276     stream->src_id_len = len;
1277   }
1278
1279   if (dst_id) {
1280     silc_free(stream->dst_id);
1281     if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1282       silc_mutex_unlock(stream->lock);
1283       return FALSE;
1284     }
1285     stream->dst_id = silc_memdup(tmp, len);
1286     if (!stream->dst_id) {
1287       silc_mutex_unlock(stream->lock);
1288       return FALSE;
1289     }
1290     stream->dst_id_type = dst_id_type;
1291     stream->dst_id_len = len;
1292   }
1293
1294   silc_mutex_unlock(stream->lock);
1295
1296   return TRUE;
1297 }
1298
1299 /* Adds Security ID (SID) */
1300
1301 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1302 {
1303   if (!stream->iv_included)
1304     return FALSE;
1305
1306   SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1307
1308   stream->sid = sid;
1309   return TRUE;
1310 }
1311
1312 /* Free packet */
1313
1314 void silc_packet_free(SilcPacket packet)
1315 {
1316   SilcPacketStream stream = packet->stream;
1317
1318   SILC_LOG_DEBUG(("Freeing packet %p", packet));
1319
1320   /* Check for double free */
1321   SILC_ASSERT(packet->stream != NULL);
1322
1323   packet->stream = NULL;
1324   packet->src_id = packet->dst_id = NULL;
1325   silc_buffer_reset(&packet->buffer);
1326
1327   silc_mutex_lock(stream->sc->engine->lock);
1328
1329   /* Put the packet back to freelist */
1330   silc_list_add(stream->sc->engine->packet_pool, packet);
1331   if (silc_list_count(stream->sc->engine->packet_pool) == 1)
1332     silc_list_start(stream->sc->engine->packet_pool);
1333
1334   silc_mutex_unlock(stream->sc->engine->lock);
1335 }
1336
1337 /****************************** Packet Sending ******************************/
1338
1339 /* Prepare outgoing data buffer for packet sending.  Returns the
1340    pointer to that buffer into the `packet'. */
1341
1342 static inline SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1343                                                 SilcUInt32 totlen,
1344                                                 SilcHmac hmac,
1345                                                 SilcBuffer packet)
1346 {
1347   unsigned char *oldptr;
1348   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1349
1350   totlen += mac_len;
1351
1352   /* Allocate more space if needed */
1353   if (silc_unlikely(silc_buffer_taillen(&stream->outbuf) < totlen)) {
1354     if (!silc_buffer_realloc(&stream->outbuf,
1355                              silc_buffer_truelen(&stream->outbuf) + totlen))
1356       return FALSE;
1357   }
1358
1359   /* Pull data area for the new packet, and return pointer to the start of
1360      the data area and save the pointer in to the `packet'.  MAC is pulled
1361      later after it's computed. */
1362   oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1363   silc_buffer_set(packet, oldptr, totlen);
1364   silc_buffer_push_tail(packet, mac_len);
1365
1366   return TRUE;
1367 }
1368
1369 /* Increments counter when encrypting in counter mode. */
1370
1371 static inline void silc_packet_send_ctr_increment(SilcPacketStream stream,
1372                                                   SilcCipher cipher,
1373                                                   unsigned char *ret_iv)
1374 {
1375   unsigned char *iv = silc_cipher_get_iv(cipher);
1376   SilcUInt32 pc1, pc2;
1377
1378   /* Increment 64-bit packet counter.*/
1379   SILC_GET32_MSB(pc1, iv + 4);
1380   SILC_GET32_MSB(pc2, iv + 8);
1381   if (++pc2 == 0)
1382     ++pc1;
1383   SILC_PUT32_MSB(pc1, iv + 4);
1384   SILC_PUT32_MSB(pc2, iv + 8);
1385
1386   /* Reset block counter */
1387   memset(iv + 12, 0, 4);
1388
1389   /* If IV Included flag, return the 64-bit IV for inclusion in packet */
1390   if (stream->iv_included) {
1391     /* Get new nonce */
1392     ret_iv[0] = silc_rng_get_byte_fast(stream->sc->engine->rng);
1393     ret_iv[1] = ret_iv[0] + iv[4];
1394     ret_iv[2] = ret_iv[0] ^ ret_iv[1];
1395     ret_iv[3] = ret_iv[0] + ret_iv[2];
1396     SILC_PUT32_MSB(pc2, ret_iv + 4);
1397     SILC_LOG_HEXDUMP(("IV"), ret_iv, 8);
1398
1399     /* Set new nonce to counter block */
1400     memcpy(iv + 4, ret_iv, 4);
1401   }
1402
1403   SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1404 }
1405
1406 /* Internal routine to assemble outgoing packet.  Assembles and encryptes
1407    the packet.  The silc_packet_stream_write needs to be called to send it
1408    after this returns TRUE. */
1409
1410 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
1411                                             SilcPacketType type,
1412                                             SilcPacketFlags flags,
1413                                             SilcIdType src_id_type,
1414                                             unsigned char *src_id,
1415                                             SilcUInt32 src_id_len,
1416                                             SilcIdType dst_id_type,
1417                                             unsigned char *dst_id,
1418                                             SilcUInt32 dst_id_len,
1419                                             const unsigned char *data,
1420                                             SilcUInt32 data_len,
1421                                             SilcCipher cipher,
1422                                             SilcHmac hmac)
1423 {
1424   unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1425   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1426   int i, enclen, truelen, padlen = 0, ivlen = 0, psnlen = 0;
1427   SilcBool ctr;
1428   SilcBufferStruct packet;
1429
1430   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1431                   "data len %d", silc_get_packet_name(type), stream->send_psn,
1432                   flags, src_id_type, dst_id_type, data_len));
1433
1434   /* Get the true length of the packet. This is saved as payload length
1435      into the packet header.  This does not include the length of the
1436      padding. */
1437   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1438                                             src_id_len + dst_id_len));
1439   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1440                       src_id_len + dst_id_len);
1441
1442   /* If using CTR mode, increment the counter */
1443   ctr = (cipher && silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR);
1444   if (ctr) {
1445     silc_packet_send_ctr_increment(stream, cipher, iv + 1);
1446
1447     /* If IV is included, the SID, IV and sequence number is added to packet */
1448     if (stream->iv_included && cipher) {
1449       psnlen = sizeof(psn);
1450       ivlen = 8 + 1;
1451       iv[0] = stream->sid;
1452     }
1453   } else {
1454     /* If IV is included, the SID, IV and sequence number is added to packet */
1455     if (stream->iv_included && cipher) {
1456       psnlen = sizeof(psn);
1457       ivlen = block_len + 1;
1458       iv[0] = stream->sid;
1459       memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1460     }
1461   }
1462
1463   /* We automatically figure out the packet structure from the packet
1464      type and flags, and calculate correct length.  Private messages with
1465      private keys and channel messages are special packets as their
1466      payload is encrypted already. */
1467   if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1468        flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1469       type == SILC_PACKET_CHANNEL_MESSAGE) {
1470
1471     /* Padding is calculated from header + IDs */
1472     if (!ctr)
1473       SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1474                           psnlen), block_len, padlen);
1475
1476     /* Length to encrypt, header + IDs + padding. */
1477     enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1478               padlen + psnlen);
1479   } else {
1480
1481     /* Padding is calculated from true length of the packet */
1482     if (flags & SILC_PACKET_FLAG_LONG_PAD)
1483       SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1484     else if (!ctr)
1485       SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1486
1487     enclen += padlen + psnlen;
1488   }
1489
1490   /* Remove implementation specific flags */
1491   flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1492
1493   /* Get random padding */
1494   for (i = 0; i < padlen; i++) tmppad[i] =
1495     silc_rng_get_byte_fast(stream->sc->engine->rng);
1496
1497   silc_mutex_lock(stream->lock);
1498
1499   /* Get packet pointer from the outgoing buffer */
1500   if (silc_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen
1501                                               + psnlen, hmac, &packet))) {
1502     silc_mutex_unlock(stream->lock);
1503     return FALSE;
1504   }
1505
1506   SILC_PUT32_MSB(stream->send_psn, psn);
1507
1508   /* Create the packet.  This creates the SILC header, adds padding, and
1509      the actual packet data. */
1510   i = silc_buffer_format(&packet,
1511                          SILC_STR_DATA(iv, ivlen),
1512                          SILC_STR_DATA(psn, psnlen),
1513                          SILC_STR_UI_SHORT(truelen),
1514                          SILC_STR_UI_CHAR(flags),
1515                          SILC_STR_UI_CHAR(type),
1516                          SILC_STR_UI_CHAR(padlen),
1517                          SILC_STR_UI_CHAR(0),
1518                          SILC_STR_UI_CHAR(src_id_len),
1519                          SILC_STR_UI_CHAR(dst_id_len),
1520                          SILC_STR_UI_CHAR(src_id_type),
1521                          SILC_STR_DATA(src_id, src_id_len),
1522                          SILC_STR_UI_CHAR(dst_id_type),
1523                          SILC_STR_DATA(dst_id, dst_id_len),
1524                          SILC_STR_DATA(tmppad, padlen),
1525                          SILC_STR_DATA(data, data_len),
1526                          SILC_STR_END);
1527   if (silc_unlikely(i < 0)) {
1528     silc_mutex_unlock(stream->lock);
1529     return FALSE;
1530   }
1531
1532   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1533                    silc_buffer_data(&packet), silc_buffer_len(&packet));
1534
1535   /* Encrypt the packet */
1536   if (silc_likely(cipher)) {
1537     SILC_LOG_DEBUG(("Encrypting packet"));
1538     silc_cipher_set_iv(cipher, NULL);
1539     if (silc_unlikely(!silc_cipher_encrypt(cipher, packet.data + ivlen,
1540                                            packet.data + ivlen, enclen,
1541                                            NULL))) {
1542       SILC_LOG_ERROR(("Packet encryption failed"));
1543       silc_mutex_unlock(stream->lock);
1544       return FALSE;
1545     }
1546   }
1547
1548   /* Compute HMAC */
1549   if (silc_likely(hmac)) {
1550     SilcUInt32 mac_len;
1551
1552     /* MAC is computed from the entire encrypted packet data, and put
1553        to the end of the packet. */
1554     silc_hmac_init(hmac);
1555     silc_hmac_update(hmac, psn, sizeof(psn));
1556     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1557     silc_hmac_final(hmac, packet.tail, &mac_len);
1558     silc_buffer_pull_tail(&packet, mac_len);
1559     stream->send_psn++;
1560   }
1561
1562   return TRUE;
1563 }
1564
1565 /* Sends a packet */
1566
1567 SilcBool silc_packet_send(SilcPacketStream stream,
1568                           SilcPacketType type, SilcPacketFlags flags,
1569                           const unsigned char *data, SilcUInt32 data_len)
1570 {
1571   SilcBool ret;
1572
1573   ret = silc_packet_send_raw(stream, type, flags,
1574                              stream->src_id_type,
1575                              stream->src_id,
1576                              stream->src_id_len,
1577                              stream->dst_id_type,
1578                              stream->dst_id,
1579                              stream->dst_id_len,
1580                              data, data_len,
1581                              stream->send_key[0],
1582                              stream->send_hmac[0]);
1583
1584   /* Write the packet to the stream */
1585   return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1586 }
1587
1588 /* Sends a packet, extended routine */
1589
1590 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1591                               SilcPacketType type, SilcPacketFlags flags,
1592                               SilcIdType src_id_type, void *src_id,
1593                               SilcIdType dst_id_type, void *dst_id,
1594                               const unsigned char *data, SilcUInt32 data_len,
1595                               SilcCipher cipher, SilcHmac hmac)
1596 {
1597   unsigned char src_id_data[32], dst_id_data[32];
1598   SilcUInt32 src_id_len, dst_id_len;
1599   SilcBool ret;
1600
1601   if (src_id)
1602     if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1603                         sizeof(src_id_data), &src_id_len))
1604       return FALSE;
1605   if (dst_id)
1606     if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1607                         sizeof(dst_id_data), &dst_id_len))
1608       return FALSE;
1609
1610   ret = silc_packet_send_raw(stream, type, flags,
1611                              src_id ? src_id_type : stream->src_id_type,
1612                              src_id ? src_id_data : stream->src_id,
1613                              src_id ? src_id_len : stream->src_id_len,
1614                              dst_id ? dst_id_type : stream->dst_id_type,
1615                              dst_id ? dst_id_data : stream->dst_id,
1616                              dst_id ? dst_id_len : stream->dst_id_len,
1617                              data, data_len,
1618                              cipher ? cipher : stream->send_key[0],
1619                              hmac ? hmac : stream->send_hmac[0]);
1620
1621   /* Write the packet to the stream */
1622   return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1623 }
1624
1625 /* Sends packet after formatting the arguments to buffer */
1626
1627 SilcBool silc_packet_send_va(SilcPacketStream stream,
1628                              SilcPacketType type, SilcPacketFlags flags, ...)
1629 {
1630   SilcBufferStruct buf;
1631   SilcBool ret;
1632   va_list va;
1633
1634   va_start(va, flags);
1635
1636   memset(&buf, 0, sizeof(buf));
1637   if (silc_buffer_format_vp(&buf, va) < 0) {
1638     va_end(va);
1639     return FALSE;
1640   }
1641
1642   ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1643                          silc_buffer_len(&buf));
1644
1645   silc_buffer_purge(&buf);
1646   va_end(va);
1647
1648   return ret;
1649 }
1650
1651 /* Sends packet after formatting the arguments to buffer, extended routine */
1652
1653 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1654                                  SilcPacketType type, SilcPacketFlags flags,
1655                                  SilcIdType src_id_type, void *src_id,
1656                                  SilcIdType dst_id_type, void *dst_id,
1657                                  SilcCipher cipher, SilcHmac hmac, ...)
1658 {
1659   SilcBufferStruct buf;
1660   SilcBool ret;
1661   va_list va;
1662
1663   va_start(va, hmac);
1664
1665   memset(&buf, 0, sizeof(buf));
1666   if (silc_buffer_format_vp(&buf, va) < 0) {
1667     va_end(va);
1668     return FALSE;
1669   }
1670
1671   ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1672                              dst_id_type, dst_id, silc_buffer_data(&buf),
1673                              silc_buffer_len(&buf), cipher, hmac);
1674
1675   silc_buffer_purge(&buf);
1676   va_end(va);
1677
1678   return TRUE;
1679 }
1680
1681 /***************************** Packet Receiving *****************************/
1682
1683 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1684
1685 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1686                                              const unsigned char *data,
1687                                              SilcUInt32 data_len,
1688                                              const unsigned char *packet_mac,
1689                                              const unsigned char *packet_seq,
1690                                              SilcUInt32 sequence)
1691 {
1692   /* Check MAC */
1693   if (silc_likely(hmac)) {
1694     unsigned char mac[32], psn[4];
1695     SilcUInt32 mac_len;
1696
1697     SILC_LOG_DEBUG(("Verifying MAC"));
1698
1699     /* Compute HMAC of packet */
1700     silc_hmac_init(hmac);
1701
1702     if (!packet_seq) {
1703       SILC_PUT32_MSB(sequence, psn);
1704       silc_hmac_update(hmac, psn, 4);
1705     } else
1706       silc_hmac_update(hmac, packet_seq, 4);
1707
1708     silc_hmac_update(hmac, data, data_len);
1709     silc_hmac_final(hmac, mac, &mac_len);
1710
1711     /* Compare the MAC's */
1712     if (silc_unlikely(memcmp(packet_mac, mac, mac_len))) {
1713       SILC_LOG_DEBUG(("MAC failed"));
1714       return FALSE;
1715     }
1716
1717     SILC_LOG_DEBUG(("MAC is Ok"));
1718   }
1719
1720   return TRUE;
1721 }
1722
1723 /* Increments/sets counter when decrypting in counter mode. */
1724
1725 static inline void silc_packet_receive_ctr_increment(SilcPacketStream stream,
1726                                                      unsigned char *iv,
1727                                                      unsigned char *packet_iv)
1728 {
1729   SilcUInt32 pc1, pc2;
1730
1731   /* If IV Included flag, set the IV from packet to block counter. */
1732   if (stream->iv_included) {
1733     memcpy(iv + 4, packet_iv, 8);
1734   } else {
1735     /* Increment 64-bit packet counter. */
1736     SILC_GET32_MSB(pc1, iv + 4);
1737     SILC_GET32_MSB(pc2, iv + 8);
1738     if (++pc2 == 0)
1739       ++pc1;
1740     SILC_PUT32_MSB(pc1, iv + 4);
1741     SILC_PUT32_MSB(pc2, iv + 8);
1742   }
1743
1744   /* Reset block counter */
1745   memset(iv + 12, 0, 4);
1746
1747   SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1748 }
1749
1750 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
1751    Return 0 when packet is normal and 1 when it it special, -1 on error. */
1752
1753 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1754                                       SilcUInt32 sequence, SilcBuffer buffer,
1755                                       SilcBool normal)
1756 {
1757   if (normal == TRUE) {
1758     if (silc_likely(cipher)) {
1759       /* Decrypt rest of the packet */
1760       SILC_LOG_DEBUG(("Decrypting the packet"));
1761       if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1762                                              buffer->data,
1763                                              silc_buffer_len(buffer), NULL)))
1764         return -1;
1765     }
1766     return 0;
1767
1768   } else {
1769     /* Decrypt rest of the header plus padding */
1770     if (silc_likely(cipher)) {
1771       SilcUInt16 len;
1772       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1773
1774       SILC_LOG_DEBUG(("Decrypting the header"));
1775
1776       /* Padding length + src id len + dst id len + header length - 16
1777          bytes already decrypted, gives the rest of the encrypted packet */
1778       silc_buffer_push(buffer, block_len);
1779       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1780               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1781              block_len);
1782       silc_buffer_pull(buffer, block_len);
1783
1784       if (silc_unlikely(len > silc_buffer_len(buffer))) {
1785         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1786                         "packet dropped"));
1787         return -1;
1788       }
1789       if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1790                                              buffer->data, len, NULL)))
1791         return -1;
1792     }
1793
1794     return 1;
1795   }
1796 }
1797
1798 /* Parses the packet. This is called when a whole packet is ready to be
1799    parsed. The buffer sent must be already decrypted before calling this
1800    function. */
1801
1802 static inline SilcBool silc_packet_parse(SilcPacket packet)
1803 {
1804   SilcBuffer buffer = &packet->buffer;
1805   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1806   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1807   int ret;
1808
1809   SILC_LOG_DEBUG(("Parsing incoming packet"));
1810
1811   /* Parse the buffer.  This parses the SILC header of the packet. */
1812   ret = silc_buffer_unformat(buffer,
1813                              SILC_STR_ADVANCE,
1814                              SILC_STR_OFFSET(6),
1815                              SILC_STR_UI_CHAR(&src_id_len),
1816                              SILC_STR_UI_CHAR(&dst_id_len),
1817                              SILC_STR_UI_CHAR(&src_id_type),
1818                              SILC_STR_END);
1819   if (silc_unlikely(ret == -1)) {
1820     if (!packet->stream->udp &&
1821         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1822       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1823     return FALSE;
1824   }
1825
1826   if (silc_unlikely(src_id_len > SILC_PACKET_MAX_ID_LEN ||
1827                     dst_id_len > SILC_PACKET_MAX_ID_LEN)) {
1828     if (!packet->stream->udp &&
1829         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1830       SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1831                       packet->src_id_len, packet->dst_id_len));
1832     return FALSE;
1833   }
1834
1835   ret = silc_buffer_unformat(buffer,
1836                              SILC_STR_ADVANCE,
1837                              SILC_STR_DATA(&packet->src_id, src_id_len),
1838                              SILC_STR_UI_CHAR(&dst_id_type),
1839                              SILC_STR_DATA(&packet->dst_id, dst_id_len),
1840                              SILC_STR_OFFSET(padlen),
1841                              SILC_STR_END);
1842   if (silc_unlikely(ret == -1)) {
1843     if (!packet->stream->udp &&
1844         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1845       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1846     return FALSE;
1847   }
1848
1849   if (silc_unlikely(src_id_type > SILC_ID_CHANNEL ||
1850                     dst_id_type > SILC_ID_CHANNEL)) {
1851     if (!packet->stream->udp &&
1852         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1853       SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1854                       src_id_type, dst_id_type));
1855     return FALSE;
1856   }
1857
1858   packet->src_id_len = src_id_len;
1859   packet->dst_id_len = dst_id_len;
1860   packet->src_id_type = src_id_type;
1861   packet->dst_id_type = dst_id_type;
1862
1863   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1864                    silc_buffer_len(buffer)), buffer->head,
1865                    silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1866
1867   SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1868                   silc_get_packet_name(packet->type)));
1869
1870   return TRUE;
1871 }
1872
1873 /* Dispatch packet to application.  Called with stream->lock locked.
1874    Returns FALSE if the stream was destroyed while dispatching a packet. */
1875
1876 static SilcBool silc_packet_dispatch(SilcPacket packet)
1877 {
1878   SilcPacketStream stream = packet->stream;
1879   SilcPacketProcess p;
1880   SilcBool default_sent = FALSE;
1881   SilcPacketType *pt;
1882
1883   /* Dispatch packet to all packet processors that want it */
1884
1885   if (silc_likely(!stream->process)) {
1886     /* Send to default processor as no others exist */
1887     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1888     silc_mutex_unlock(stream->lock);
1889     if (silc_unlikely(!stream->sc->engine->callbacks->
1890                       packet_receive(stream->sc->engine, stream, packet,
1891                                      stream->sc->engine->callback_context,
1892                                      stream->stream_context)))
1893       silc_packet_free(packet);
1894     silc_mutex_lock(stream->lock);
1895     return stream->destroyed == FALSE;
1896   }
1897
1898   silc_dlist_start(stream->process);
1899   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1900
1901     /* If priority is 0 or less, we send to default processor first
1902        because default processor has 0 priority */
1903     if (!default_sent && p->priority <= 0) {
1904       SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1905       default_sent = TRUE;
1906       silc_mutex_unlock(stream->lock);
1907       if (stream->sc->engine->callbacks->
1908           packet_receive(stream->sc->engine, stream, packet,
1909                          stream->sc->engine->callback_context,
1910                          stream->stream_context)) {
1911         silc_mutex_lock(stream->lock);
1912         return stream->destroyed == FALSE;
1913       }
1914       silc_mutex_lock(stream->lock);
1915     }
1916
1917     /* Send to processor */
1918     if (!p->types) {
1919       /* Send all packet types */
1920       SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1921       silc_mutex_unlock(stream->lock);
1922       if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
1923                                        p->callback_context,
1924                                        stream->stream_context)) {
1925         silc_mutex_lock(stream->lock);
1926         return stream->destroyed == FALSE;
1927       }
1928       silc_mutex_lock(stream->lock);
1929     } else {
1930       /* Send specific types */
1931       for (pt = p->types; *pt; pt++) {
1932         if (*pt != packet->type)
1933           continue;
1934         SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1935         silc_mutex_unlock(stream->lock);
1936         if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
1937                                          p->callback_context,
1938                                          stream->stream_context)) {
1939           silc_mutex_lock(stream->lock);
1940           return stream->destroyed == FALSE;
1941         }
1942         silc_mutex_lock(stream->lock);
1943         break;
1944       }
1945     }
1946   }
1947
1948   if (!default_sent) {
1949     /* Send to default processor as it has not been sent yet */
1950     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1951     silc_mutex_unlock(stream->lock);
1952     if (stream->sc->engine->callbacks->
1953         packet_receive(stream->sc->engine, stream, packet,
1954                        stream->sc->engine->callback_context,
1955                        stream->stream_context)) {
1956       silc_mutex_lock(stream->lock);
1957       return stream->destroyed == FALSE;
1958     }
1959     silc_mutex_lock(stream->lock);
1960   }
1961
1962   /* If we got here, no one wanted the packet, so drop it */
1963   silc_packet_free(packet);
1964   return stream->destroyed == FALSE;
1965 }
1966
1967 /* Process incoming data and parse packets.  Called with stream->lock
1968    locked. */
1969
1970 static void silc_packet_read_process(SilcPacketStream stream)
1971 {
1972   SilcBuffer inbuf;
1973   SilcCipher cipher;
1974   SilcHmac hmac;
1975   SilcPacket packet;
1976   SilcUInt8 sid;
1977   SilcUInt16 packetlen;
1978   SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1979   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1980   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1981   SilcBool normal;
1982   int ret;
1983
1984   /* Get inbuf.  If there is already some data for this stream in the buffer
1985      we already have it.  Otherwise get the current one from list, it will
1986      include the data. */
1987   inbuf = stream->inbuf;
1988   if (!inbuf) {
1989     silc_dlist_start(stream->sc->inbufs);
1990     inbuf = silc_dlist_get(stream->sc->inbufs);
1991   }
1992
1993   /* Parse the packets from the data */
1994   while (silc_buffer_len(inbuf) > 0) {
1995     ivlen = psnlen = 0;
1996     cipher = stream->receive_key[0];
1997     hmac = stream->receive_hmac[0];
1998     normal = FALSE;
1999
2000     if (silc_unlikely(silc_buffer_len(inbuf) <
2001                       (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
2002                        SILC_PACKET_MIN_HEADER_LEN))) {
2003       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
2004       silc_dlist_del(stream->sc->inbufs, inbuf);
2005       stream->inbuf = inbuf;
2006       return;
2007     }
2008
2009     if (silc_likely(hmac))
2010       mac_len = silc_hmac_len(hmac);
2011     else
2012       mac_len = 0;
2013
2014     /* Decrypt first block of the packet to get the length field out */
2015     if (silc_likely(cipher)) {
2016       block_len = silc_cipher_get_block_len(cipher);
2017
2018       if (stream->iv_included) {
2019         /* SID, IV and sequence number is included in the ciphertext */
2020         sid = (SilcUInt8)inbuf->data[0];
2021
2022         if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR) {
2023           /* Set the CTR mode IV from packet to counter block */
2024           memcpy(iv, silc_cipher_get_iv(cipher), block_len);
2025           silc_packet_receive_ctr_increment(stream, iv, inbuf->data + 1);
2026           ivlen = 8 + 1;
2027         } else {
2028           /* Get IV from packet */
2029           memcpy(iv, inbuf->data + 1, block_len);
2030           ivlen = block_len + 1;
2031         }
2032         psnlen = 4;
2033
2034         /* Check SID, and get correct decryption key */
2035         if (sid != stream->sid) {
2036           /* If SID is recent get the previous key and use it */
2037           if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
2038               stream->receive_key[1] && !stream->receive_hmac[1]) {
2039             cipher = stream->receive_key[1];
2040             hmac = stream->receive_hmac[1];
2041           } else {
2042             /* The SID is unknown, drop rest of the data in buffer */
2043             SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
2044                             sid, stream->sid));
2045             silc_mutex_unlock(stream->lock);
2046             SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
2047             silc_mutex_lock(stream->lock);
2048             goto out;
2049           }
2050         }
2051       } else {
2052         memcpy(iv, silc_cipher_get_iv(cipher), block_len);
2053
2054         /* If using CTR mode, increment the counter */
2055         if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
2056           silc_packet_receive_ctr_increment(stream, iv, NULL);
2057       }
2058
2059       if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
2060         silc_cipher_set_iv(cipher, NULL);
2061       silc_cipher_decrypt(cipher, inbuf->data + ivlen, tmp, block_len, iv);
2062
2063       header = tmp;
2064       if (stream->iv_included) {
2065         /* Take sequence number from packet */
2066         packet_seq = header;
2067         header += 4;
2068       }
2069     } else {
2070       /* Unencrypted packet */
2071       block_len = SILC_PACKET_MIN_HEADER_LEN;
2072       header = inbuf->data;
2073     }
2074
2075     /* Get packet length and full packet length with padding */
2076     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
2077
2078     /* Sanity checks */
2079     if (silc_unlikely(packetlen < SILC_PACKET_MIN_LEN)) {
2080       if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
2081         SILC_LOG_ERROR(("Received too short packet"));
2082       silc_mutex_unlock(stream->lock);
2083       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2084       silc_mutex_lock(stream->lock);
2085       memset(tmp, 0, sizeof(tmp));
2086       goto out;
2087     }
2088
2089     if (silc_buffer_len(inbuf) < paddedlen + ivlen + mac_len) {
2090       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
2091                       "(%d bytes)",
2092                       paddedlen + mac_len - silc_buffer_len(inbuf)));
2093       memset(tmp, 0, sizeof(tmp));
2094       silc_dlist_del(stream->sc->inbufs, inbuf);
2095       stream->inbuf = inbuf;
2096       return;
2097     }
2098
2099     /* Check MAC of the packet */
2100     if (silc_unlikely(!silc_packet_check_mac(hmac, inbuf->data,
2101                                              paddedlen + ivlen,
2102                                              inbuf->data + ivlen +
2103                                              paddedlen, packet_seq,
2104                                              stream->receive_psn))) {
2105       silc_mutex_unlock(stream->lock);
2106       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
2107       silc_mutex_lock(stream->lock);
2108       memset(tmp, 0, sizeof(tmp));
2109       goto out;
2110     }
2111
2112     /* Get packet */
2113     packet = silc_packet_alloc(stream->sc->engine);
2114     if (silc_unlikely(!packet)) {
2115       silc_mutex_unlock(stream->lock);
2116       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2117       silc_mutex_lock(stream->lock);
2118       memset(tmp, 0, sizeof(tmp));
2119       goto out;
2120     }
2121     packet->stream = stream;
2122
2123     /* Allocate more space to packet buffer, if needed */
2124     if (silc_unlikely(silc_buffer_truelen(&packet->buffer) < paddedlen)) {
2125       if (!silc_buffer_realloc(&packet->buffer,
2126                                silc_buffer_truelen(&packet->buffer) +
2127                                (paddedlen -
2128                                 silc_buffer_truelen(&packet->buffer)))) {
2129         silc_mutex_unlock(stream->lock);
2130         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2131         silc_mutex_lock(stream->lock);
2132         silc_packet_free(packet);
2133         memset(tmp, 0, sizeof(tmp));
2134         goto out;
2135       }
2136     }
2137
2138     /* Parse packet header */
2139     packet->flags = (SilcPacketFlags)header[2];
2140     packet->type = (SilcPacketType)header[3];
2141
2142     if (stream->sc->engine->local_is_router) {
2143       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2144           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2145         normal = FALSE;
2146       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
2147                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
2148                 stream->is_router == TRUE))
2149         normal = TRUE;
2150     } else {
2151       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2152           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2153         normal = FALSE;
2154       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
2155         normal = TRUE;
2156     }
2157
2158     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
2159                       stream->receive_psn, paddedlen + ivlen + mac_len),
2160                      inbuf->data, paddedlen + ivlen + mac_len);
2161
2162     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
2163     silc_buffer_pull_tail(&packet->buffer, paddedlen);
2164     silc_buffer_put(&packet->buffer, header, block_len - psnlen);
2165     silc_buffer_pull(&packet->buffer, block_len - psnlen);
2166     silc_buffer_put(&packet->buffer, (inbuf->data + ivlen +
2167                                       psnlen + (block_len - psnlen)),
2168                     paddedlen - ivlen - psnlen - (block_len - psnlen));
2169     if (silc_likely(cipher)) {
2170       silc_cipher_set_iv(cipher, iv);
2171       ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
2172                                 &packet->buffer, normal);
2173       if (silc_unlikely(ret < 0)) {
2174         silc_mutex_unlock(stream->lock);
2175         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
2176         silc_mutex_lock(stream->lock);
2177         silc_packet_free(packet);
2178         memset(tmp, 0, sizeof(tmp));
2179         goto out;
2180       }
2181
2182       stream->receive_psn++;
2183     }
2184     silc_buffer_push(&packet->buffer, block_len);
2185
2186     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
2187     silc_buffer_pull(inbuf, paddedlen + mac_len);
2188
2189     /* Parse the packet */
2190     if (silc_unlikely(!silc_packet_parse(packet))) {
2191       silc_mutex_unlock(stream->lock);
2192       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2193       silc_mutex_lock(stream->lock);
2194       silc_packet_free(packet);
2195       memset(tmp, 0, sizeof(tmp));
2196       goto out;
2197     }
2198
2199     /* Dispatch the packet to application */
2200     if (!silc_packet_dispatch(packet))
2201       break;
2202   }
2203
2204  out:
2205   /* Add inbuf back to free list, if we owned it. */
2206   if (stream->inbuf) {
2207     silc_dlist_add(stream->sc->inbufs, inbuf);
2208     stream->inbuf = NULL;
2209   }
2210
2211   silc_buffer_reset(inbuf);
2212 }
2213
2214 /****************************** Packet Waiting ******************************/
2215
2216 /* Packet wait receive callback */
2217 static SilcBool
2218 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2219                                 SilcPacketStream stream,
2220                                 SilcPacket packet,
2221                                 void *callback_context,
2222                                 void *stream_context);
2223
2224 /* Packet waiting callbacks */
2225 static SilcPacketCallbacks silc_packet_wait_cbs =
2226 {
2227   silc_packet_wait_packet_receive, NULL, NULL
2228 };
2229
2230 /* Packet waiting context */
2231 typedef struct {
2232   SilcMutex wait_lock;
2233   SilcCond wait_cond;
2234   SilcList packet_queue;
2235   unsigned int stopped     : 1;
2236 } *SilcPacketWait;
2237
2238 /* Packet wait receive callback */
2239
2240 static SilcBool
2241 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2242                                 SilcPacketStream stream,
2243                                 SilcPacket packet,
2244                                 void *callback_context,
2245                                 void *stream_context)
2246 {
2247   SilcPacketWait pw = callback_context;
2248
2249   /* Signal the waiting thread for a new packet */
2250   silc_mutex_lock(pw->wait_lock);
2251
2252   if (silc_unlikely(pw->stopped)) {
2253     silc_mutex_unlock(pw->wait_lock);
2254     return FALSE;
2255   }
2256
2257   silc_list_add(pw->packet_queue, packet);
2258   silc_cond_broadcast(pw->wait_cond);
2259
2260   silc_mutex_unlock(pw->wait_lock);
2261
2262   return TRUE;
2263 }
2264
2265 /* Initialize packet waiting */
2266
2267 void *silc_packet_wait_init(SilcPacketStream stream, ...)
2268 {
2269   SilcPacketWait pw;
2270   SilcBool ret;
2271   va_list ap;
2272
2273   pw = silc_calloc(1, sizeof(*pw));
2274   if (!pw)
2275     return NULL;
2276
2277   /* Allocate mutex and conditional variable */
2278   if (!silc_mutex_alloc(&pw->wait_lock)) {
2279     silc_free(pw);
2280     return NULL;
2281   }
2282   if (!silc_cond_alloc(&pw->wait_cond)) {
2283     silc_mutex_free(pw->wait_lock);
2284     silc_free(pw);
2285     return NULL;
2286   }
2287
2288   /* Link to the packet stream for the requested packet types */
2289   va_start(ap, stream);
2290   ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2291                                    10000000, ap);
2292   va_end(ap);
2293   if (!ret) {
2294     silc_cond_free(pw->wait_cond);
2295     silc_mutex_free(pw->wait_lock);
2296     silc_free(pw);
2297     return NULL;
2298   }
2299
2300   /* Initialize packet queue */
2301   silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2302
2303   return (void *)pw;
2304 }
2305
2306 /* Uninitialize packet waiting */
2307
2308 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2309 {
2310   SilcPacketWait pw = waiter;
2311   SilcPacket packet;
2312
2313   /* Signal any threads to stop waiting */
2314   silc_mutex_lock(pw->wait_lock);
2315   pw->stopped = TRUE;
2316   silc_cond_broadcast(pw->wait_cond);
2317   silc_mutex_unlock(pw->wait_lock);
2318
2319   /* Re-acquire lock and free resources */
2320   silc_mutex_lock(pw->wait_lock);
2321   silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2322
2323   /* Free any remaining packets */
2324   silc_list_start(pw->packet_queue);
2325   while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2326     silc_packet_free(packet);
2327
2328   silc_mutex_unlock(pw->wait_lock);
2329   silc_cond_free(pw->wait_cond);
2330   silc_mutex_free(pw->wait_lock);
2331   silc_free(pw);
2332 }
2333
2334 /* Blocks thread until a packet has been received. */
2335
2336 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2337 {
2338   SilcPacketWait pw = waiter;
2339   SilcBool ret = FALSE;
2340
2341   silc_mutex_lock(pw->wait_lock);
2342
2343   /* Wait here until packet has arrived */
2344   while (silc_list_count(pw->packet_queue) == 0) {
2345     if (silc_unlikely(pw->stopped)) {
2346       silc_mutex_unlock(pw->wait_lock);
2347       return -1;
2348     }
2349     ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2350   }
2351
2352   /* Return packet */
2353   silc_list_start(pw->packet_queue);
2354   *return_packet = silc_list_get(pw->packet_queue);
2355   silc_list_del(pw->packet_queue, *return_packet);
2356
2357   silc_mutex_unlock(pw->wait_lock);
2358
2359   return ret == TRUE ? 1 : 0;
2360 }
2361
2362 /************************** Packet Stream Wrapper ***************************/
2363
2364 /* Packet stream wrapper receive callback */
2365 static SilcBool
2366 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2367                                 SilcPacketStream stream,
2368                                 SilcPacket packet,
2369                                 void *callback_context,
2370                                 void *stream_context);
2371
2372 const SilcStreamOps silc_packet_stream_ops;
2373
2374 /* Packet stream wrapper context */
2375 typedef struct {
2376   const SilcStreamOps *ops;
2377   SilcPacketStream stream;
2378   SilcMutex lock;
2379   void *waiter;                   /* Waiter context in blocking mode */
2380   SilcPacketWrapCoder coder;
2381   void *coder_context;
2382   SilcBuffer encbuf;
2383   SilcStreamNotifier callback;
2384   void *context;
2385   SilcList in_queue;
2386   SilcPacketType type;
2387   SilcPacketFlags flags;
2388   unsigned int closed        : 1;
2389   unsigned int blocking      : 1;
2390   unsigned int read_more     : 1;
2391 } *SilcPacketWrapperStream;
2392
2393 /* Packet wrapper callbacks */
2394 static SilcPacketCallbacks silc_packet_wrap_cbs =
2395 {
2396   silc_packet_wrap_packet_receive, NULL, NULL
2397 };
2398
2399 /* Packet stream wrapper receive callback, non-blocking mode */
2400
2401 static SilcBool
2402 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2403                                 SilcPacketStream stream,
2404                                 SilcPacket packet,
2405                                 void *callback_context,
2406                                 void *stream_context)
2407 {
2408   SilcPacketWrapperStream pws = callback_context;
2409
2410   if (pws->closed || !pws->callback)
2411     return FALSE;
2412
2413   silc_mutex_lock(pws->lock);
2414   silc_list_add(pws->in_queue, packet);
2415   silc_mutex_unlock(pws->lock);
2416
2417   /* Call notifier callback */
2418   pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2419
2420   return TRUE;
2421 }
2422
2423 /* Task callback to notify more data is available for reading */
2424
2425 SILC_TASK_CALLBACK(silc_packet_wrap_read_more)
2426 {
2427   SilcPacketWrapperStream pws = context;
2428
2429   if (pws->closed || !pws->callback)
2430     return;
2431
2432   /* Call notifier callback */
2433   pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2434 }
2435
2436 /* Read SILC packet */
2437
2438 int silc_packet_wrap_read(SilcStream stream, unsigned char *buf,
2439                           SilcUInt32 buf_len)
2440 {
2441   SilcPacketWrapperStream pws = stream;
2442   SilcPacket packet;
2443   SilcBool read_more = FALSE;
2444   int len;
2445
2446   if (pws->closed)
2447     return -2;
2448
2449   if (pws->blocking) {
2450     /* Block until packet is received */
2451     if ((silc_packet_wait(pws->waiter, 0, &packet)) < 0)
2452       return -2;
2453     if (pws->closed)
2454       return -2;
2455   } else {
2456     /* Non-blocking mode */
2457     silc_mutex_lock(pws->lock);
2458     if (!silc_list_count(pws->in_queue)) {
2459       silc_mutex_unlock(pws->lock);
2460       return -1;
2461     }
2462
2463     silc_list_start(pws->in_queue);
2464     packet = silc_list_get(pws->in_queue);
2465     silc_list_del(pws->in_queue, packet);
2466     silc_mutex_unlock(pws->lock);
2467   }
2468
2469   /* Call decoder if set */
2470   if (pws->coder && !pws->read_more)
2471     pws->coder(stream, SILC_STREAM_CAN_READ, &packet->buffer,
2472                pws->coder_context);
2473
2474   len = silc_buffer_len(&packet->buffer);
2475   if (len > buf_len) {
2476     len = buf_len;
2477     read_more = TRUE;
2478   }
2479
2480   /* Read data */
2481   memcpy(buf, packet->buffer.data, len);
2482
2483   if (read_more && !pws->blocking) {
2484     /* More data will be available (in blocking mode not supported). */
2485     silc_buffer_pull(&packet->buffer, len);
2486     silc_list_insert(pws->in_queue, NULL, packet);
2487     silc_schedule_task_add_timeout(pws->stream->sc->schedule,
2488                                    silc_packet_wrap_read_more, pws, 0, 0);
2489     pws->read_more = TRUE;
2490     return len;
2491   }
2492
2493   pws->read_more = FALSE;
2494   silc_packet_free(packet);
2495   return len;
2496 }
2497
2498 /* Write SILC packet */
2499
2500 int silc_packet_wrap_write(SilcStream stream, const unsigned char *data,
2501                            SilcUInt32 data_len)
2502 {
2503   SilcPacketWrapperStream pws = stream;
2504   SilcBool ret = FALSE;
2505
2506   /* Call decoder if set */
2507   if (pws->coder) {
2508     silc_buffer_reset(pws->encbuf);
2509     ret = pws->coder(stream, SILC_STREAM_CAN_WRITE, pws->encbuf,
2510                      pws->coder_context);
2511   }
2512
2513   /* Send the SILC packet */
2514   if (ret) {
2515     if (!silc_packet_send_va(pws->stream, pws->type, pws->flags,
2516                              SILC_STR_DATA(silc_buffer_data(pws->encbuf),
2517                                            silc_buffer_len(pws->encbuf)),
2518                              SILC_STR_DATA(data, data_len),
2519                              SILC_STR_END))
2520       return -2;
2521   } else {
2522     if (!silc_packet_send(pws->stream, pws->type, pws->flags, data, data_len))
2523       return -2;
2524   }
2525
2526   return data_len;
2527 }
2528
2529 /* Close stream */
2530
2531 SilcBool silc_packet_wrap_close(SilcStream stream)
2532 {
2533   SilcPacketWrapperStream pws = stream;
2534
2535   if (pws->closed)
2536     return TRUE;
2537
2538   if (pws->blocking) {
2539     /* Close packet waiter */
2540     silc_packet_wait_uninit(pws->waiter, pws->stream);
2541   } else {
2542     /* Unlink */
2543     if (pws->callback)
2544       silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2545   }
2546   pws->closed = TRUE;
2547
2548   return TRUE;
2549 }
2550
2551 /* Destroy wrapper stream */
2552
2553 void silc_packet_wrap_destroy(SilcStream stream)
2554
2555 {
2556   SilcPacketWrapperStream pws = stream;
2557   SilcPacket packet;
2558
2559   SILC_LOG_DEBUG(("Destroying wrapped packet stream %p", pws));
2560
2561   silc_stream_close(stream);
2562   silc_list_start(pws->in_queue);
2563   while ((packet = silc_list_get(pws->in_queue)))
2564     silc_packet_free(packet);
2565   if (pws->lock)
2566     silc_mutex_free(pws->lock);
2567   if (pws->encbuf)
2568     silc_buffer_free(pws->encbuf);
2569   silc_packet_stream_unref(pws->stream);
2570
2571   silc_free(pws);
2572 }
2573
2574 /* Link stream to receive packets */
2575
2576 SilcBool silc_packet_wrap_notifier(SilcStream stream,
2577                                    SilcSchedule schedule,
2578                                    SilcStreamNotifier callback,
2579                                    void *context)
2580 {
2581   SilcPacketWrapperStream pws = stream;
2582
2583   if (pws->closed || pws->blocking)
2584     return FALSE;
2585
2586   /* Link to receive packets */
2587   if (callback)
2588     silc_packet_stream_link(pws->stream, &silc_packet_wrap_cbs, pws,
2589                             100000, pws->type, -1);
2590   else
2591     silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2592
2593   pws->callback = callback;
2594   pws->context = context;
2595
2596   return TRUE;
2597 }
2598
2599 /* Return schedule */
2600
2601 SilcSchedule silc_packet_wrap_get_schedule(SilcStream stream)
2602 {
2603   return NULL;
2604 }
2605
2606 /* Wraps packet stream into SilcStream. */
2607
2608 SilcStream silc_packet_stream_wrap(SilcPacketStream stream,
2609                                    SilcPacketType type,
2610                                    SilcPacketFlags flags,
2611                                    SilcBool blocking_mode,
2612                                    SilcPacketWrapCoder coder,
2613                                    void *context)
2614 {
2615   SilcPacketWrapperStream pws;
2616
2617   pws = silc_calloc(1, sizeof(*pws));
2618   if (!pws)
2619     return NULL;
2620
2621   SILC_LOG_DEBUG(("Wrapping packet stream %p to stream %p", stream, pws));
2622
2623   pws->ops = &silc_packet_stream_ops;
2624   pws->stream = stream;
2625   pws->type = type;
2626   pws->flags = flags;
2627   pws->blocking = blocking_mode;
2628   pws->coder = coder;
2629   pws->coder_context = context;
2630
2631   /* Allocate small amount for encoder buffer. */
2632   if (pws->coder)
2633     pws->encbuf = silc_buffer_alloc(8);
2634
2635   if (pws->blocking) {
2636     /* Blocking mode.  Use packet waiter to do the thing. */
2637     pws->waiter = silc_packet_wait_init(pws->stream, pws->type, -1);
2638     if (!pws->waiter) {
2639       silc_free(pws);
2640       return NULL;
2641     }
2642   } else {
2643     /* Non-blocking mode */
2644     silc_mutex_alloc(&pws->lock);
2645     silc_list_init(pws->in_queue, struct SilcPacketStruct, next);
2646   }
2647
2648   silc_packet_stream_ref(stream);
2649
2650   return (SilcStream)pws;
2651 }
2652
2653 const SilcStreamOps silc_packet_stream_ops =
2654 {
2655   silc_packet_wrap_read,
2656   silc_packet_wrap_write,
2657   silc_packet_wrap_close,
2658   silc_packet_wrap_destroy,
2659   silc_packet_wrap_notifier,
2660   silc_packet_wrap_get_schedule,
2661 };