Added silc_packet_engine_free_streams_list.
[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 * 65);
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 static const char *packet_error[] = {
627   "Cannot read from stream",
628   "Cannot write to stream",
629   "Packet MAC failed",
630   "Packet decryption failed",
631   "Unknown SID",
632   "Packet is malformed",
633   "System out of memory",
634 };
635
636 /* Return packet error string */
637
638 const char *silc_packet_error_string(SilcPacketError error)
639 {
640   if (error < SILC_PACKET_ERR_READ || error > SILC_PACKET_ERR_NO_MEMORY)
641     return "<invalid error code>";
642   return packet_error[error];
643 }
644
645 /* Return list of packet streams in the engine */
646
647 SilcDList silc_packet_engine_get_streams(SilcPacketEngine engine)
648 {
649   SilcDList list;
650   SilcPacketStream ps;
651
652   list = silc_dlist_init();
653   if (!list)
654     return NULL;
655
656   silc_mutex_lock(engine->lock);
657   silc_list_start(engine->streams);
658   while ((ps = silc_list_get(engine->streams))) {
659     silc_packet_stream_ref(ps);
660     silc_dlist_add(list, ps);
661   }
662   silc_mutex_unlock(engine->lock);
663
664   return list;
665 }
666
667 /* Free list returned by silc_packet_engine_get_streams */
668
669 void silc_packet_engine_free_streams_list(SilcDList streams)
670 {
671   SilcPacketStream ps;
672
673   silc_dlist_start(streams);
674   while ((ps = silc_dlist_get(streams)))
675     silc_packet_stream_unref(ps);
676
677   silc_dlist_uninit(streams);
678 }
679
680 /* Create new packet stream */
681
682 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
683                                            SilcSchedule schedule,
684                                            SilcStream stream)
685 {
686   SilcPacketStream ps;
687   SilcBuffer inbuf;
688   void *tmp;
689
690   SILC_LOG_DEBUG(("Creating new packet stream"));
691
692   if (!engine || !stream)
693     return NULL;
694
695   ps = silc_calloc(1, sizeof(*ps));
696   if (!ps)
697     return NULL;
698
699   ps->stream = stream;
700   silc_atomic_init8(&ps->refcnt, 1);
701   silc_mutex_alloc(&ps->lock);
702
703   /* Allocate out buffer */
704   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
705   if (!tmp) {
706     silc_packet_stream_destroy(ps);
707     return NULL;
708   }
709   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
710   silc_buffer_reset(&ps->outbuf);
711
712   /* Initialize packet procesors list */
713   ps->process = silc_dlist_init();
714   if (!ps->process) {
715     silc_packet_stream_destroy(ps);
716     return NULL;
717   }
718
719   silc_mutex_lock(engine->lock);
720
721   /* Add per scheduler context */
722   if (!silc_hash_table_find(engine->contexts, schedule, NULL,
723                             (void *)&ps->sc)) {
724     ps->sc = silc_calloc(1, sizeof(*ps->sc));
725     if (!ps->sc) {
726       silc_packet_stream_destroy(ps);
727       silc_mutex_unlock(engine->lock);
728       return NULL;
729     }
730     ps->sc->engine = engine;
731     ps->sc->schedule = schedule;
732
733     /* Allocate data input buffer */
734     inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE * 65);
735     if (!inbuf) {
736       silc_free(ps->sc);
737       ps->sc = NULL;
738       silc_packet_stream_destroy(ps);
739       silc_mutex_unlock(engine->lock);
740       return NULL;
741     }
742     silc_buffer_reset(inbuf);
743
744     ps->sc->inbufs = silc_dlist_init();
745     if (!ps->sc->inbufs) {
746       silc_buffer_free(inbuf);
747       silc_free(ps->sc);
748       ps->sc = NULL;
749       silc_packet_stream_destroy(ps);
750       silc_mutex_unlock(engine->lock);
751       return NULL;
752     }
753     silc_dlist_add(ps->sc->inbufs, inbuf);
754
755     /* Add to per scheduler context hash table */
756     if (!silc_hash_table_add(engine->contexts, schedule, ps->sc)) {
757       silc_buffer_free(inbuf);
758       silc_dlist_del(ps->sc->inbufs, inbuf);
759       silc_free(ps->sc);
760       ps->sc = NULL;
761       silc_packet_stream_destroy(ps);
762       silc_mutex_unlock(engine->lock);
763       return NULL;
764     }
765   }
766   ps->sc->stream_count++;
767
768   /* Add the packet stream to engine */
769   silc_list_add(engine->streams, ps);
770
771   /* If this is UDP stream, allocate UDP remote stream hash table */
772   if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
773     engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
774                                                silc_hash_string_compare, NULL,
775                                                silc_packet_engine_hash_destr,
776                                                NULL, TRUE);
777
778   silc_mutex_unlock(engine->lock);
779
780   /* Set IO notifier callback.  This schedules this stream for I/O. */
781   if (!silc_stream_set_notifier(ps->stream, schedule,
782                                 silc_packet_stream_io, ps)) {
783     SILC_LOG_DEBUG(("Cannot set stream notifier for packet stream"));
784     silc_packet_stream_destroy(ps);
785     return NULL;
786   }
787
788   return ps;
789 }
790
791 /* Add new remote packet stream for UDP packet streams */
792
793 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
794                                                const char *remote_ip,
795                                                SilcUInt16 remote_port,
796                                                SilcPacket packet)
797 {
798   SilcPacketEngine engine = stream->sc->engine;
799   SilcPacketStream ps;
800   char *tuple;
801   void *tmp;
802
803   SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
804                   remote_ip, remote_port, stream));
805
806   if (!stream || !remote_ip || !remote_port)
807     return NULL;
808
809   if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
810     SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
811     return NULL;
812   }
813
814   ps = silc_calloc(1, sizeof(*ps));
815   if (!ps)
816     return NULL;
817   ps->sc = stream->sc;
818
819   silc_atomic_init8(&ps->refcnt, 1);
820   silc_mutex_alloc(&ps->lock);
821
822   /* Set the UDP packet stream as underlaying stream */
823   silc_packet_stream_ref(stream);
824   ps->stream = (SilcStream)stream;
825   ps->udp = TRUE;
826
827   /* Allocate out buffer */
828   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
829   if (!tmp) {
830     silc_packet_stream_destroy(ps);
831     return NULL;
832   }
833   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
834   silc_buffer_reset(&ps->outbuf);
835
836   /* Initialize packet procesors list */
837   ps->process = silc_dlist_init();
838   if (!ps->process) {
839     silc_packet_stream_destroy(ps);
840     return NULL;
841   }
842
843   /* Add to engine with this IP and port pair */
844   tuple = silc_format("%d%s", remote_port, remote_ip);
845   silc_mutex_lock(engine->lock);
846   if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
847     silc_mutex_unlock(engine->lock);
848     silc_packet_stream_destroy(ps);
849     return NULL;
850   }
851   silc_mutex_unlock(engine->lock);
852
853   /* Save remote IP and port pair */
854   ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
855   if (!ps->remote_udp) {
856     silc_packet_stream_destroy(ps);
857     return NULL;
858   }
859   ps->remote_udp->remote_port = remote_port;
860   ps->remote_udp->remote_ip = strdup(remote_ip);
861   if (!ps->remote_udp->remote_ip) {
862     silc_packet_stream_destroy(ps);
863     return NULL;
864   }
865
866   if (packet) {
867     /* Inject packet to the new stream */
868     packet->stream = ps;
869     silc_packet_stream_ref(ps);
870     silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
871                                    silc_packet_stream_inject_packet, packet,
872                                    0, 0);
873   }
874
875   return ps;
876 }
877
878 /* Destroy packet stream */
879
880 void silc_packet_stream_destroy(SilcPacketStream stream)
881 {
882   SilcPacketEngine engine;
883
884   if (!stream)
885     return;
886
887   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0) {
888     stream->destroyed = TRUE;
889
890     /* Close the underlaying stream */
891     if (!stream->udp && stream->stream)
892       silc_stream_close(stream->stream);
893     return;
894   }
895
896   SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
897
898   if (!stream->udp) {
899     /* Delete from engine */
900     engine = stream->sc->engine;
901     silc_mutex_lock(engine->lock);
902     silc_list_del(engine->streams, stream);
903
904     /* Remove per scheduler context, if it is not used anymore */
905     if (stream->sc) {
906       stream->sc->stream_count--;
907       if (!stream->sc->stream_count)
908         silc_hash_table_del(engine->contexts, stream->sc->schedule);
909     }
910     silc_mutex_unlock(engine->lock);
911
912     /* Destroy the underlaying stream */
913     if (stream->stream)
914       silc_stream_destroy(stream->stream);
915   } else {
916     /* Delete from UDP remote hash table */
917     char tuple[64];
918     engine = stream->sc->engine;
919     silc_snprintf(tuple, sizeof(tuple), "%d%s",
920                   stream->remote_udp->remote_port,
921                   stream->remote_udp->remote_ip);
922     silc_mutex_lock(engine->lock);
923     silc_hash_table_del(engine->udp_remote, tuple);
924     silc_mutex_unlock(engine->lock);
925
926     silc_free(stream->remote_udp->remote_ip);
927     silc_free(stream->remote_udp);
928
929     /* Unreference the underlaying packet stream */
930     silc_packet_stream_unref((SilcPacketStream)stream->stream);
931   }
932
933   /* Clear and free buffers */
934   silc_buffer_clear(&stream->outbuf);
935   silc_buffer_purge(&stream->outbuf);
936
937   if (stream->process) {
938     SilcPacketProcess p;
939     silc_dlist_start(stream->process);
940     while ((p = silc_dlist_get(stream->process))) {
941       silc_free(p->types);
942       silc_free(p);
943       silc_dlist_del(stream->process, p);
944     }
945     silc_dlist_uninit(stream->process);
946   }
947
948   /* Destroy ciphers and HMACs */
949   if (stream->send_key[0])
950     silc_cipher_free(stream->send_key[0]);
951   if (stream->receive_key[0])
952     silc_cipher_free(stream->receive_key[0]);
953   if (stream->send_hmac[0])
954     silc_hmac_free(stream->send_hmac[0]);
955   if (stream->receive_hmac[0])
956     silc_hmac_free(stream->receive_hmac[0]);
957   if (stream->send_key[1])
958     silc_cipher_free(stream->send_key[1]);
959   if (stream->receive_key[1])
960     silc_cipher_free(stream->receive_key[1]);
961   if (stream->send_hmac[1])
962     silc_hmac_free(stream->send_hmac[1]);
963   if (stream->receive_hmac[1])
964     silc_hmac_free(stream->receive_hmac[1]);
965
966   /* Free IDs */
967   silc_free(stream->src_id);
968   silc_free(stream->dst_id);
969
970   silc_atomic_uninit8(&stream->refcnt);
971   silc_mutex_free(stream->lock);
972   silc_free(stream);
973 }
974
975 /* Return TRUE if the stream is valid */
976
977 SilcBool silc_packet_stream_is_valid(SilcPacketStream stream)
978 {
979   return stream->destroyed == FALSE;
980 }
981
982 /* Marks as router stream */
983
984 void silc_packet_stream_set_router(SilcPacketStream stream)
985 {
986   stream->is_router = TRUE;
987 }
988
989 /* Mark to include IV in ciphertext */
990
991 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
992 {
993   stream->iv_included = TRUE;
994 }
995
996 /* Links `callbacks' to `stream' for specified packet types */
997
998 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
999                                            SilcPacketCallbacks *callbacks,
1000                                            void *callback_context,
1001                                            int priority, va_list ap)
1002 {
1003   SilcPacketProcess p, e;
1004   SilcInt32 packet_type;
1005   int i;
1006
1007   SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
1008
1009   if (!callbacks)
1010     return FALSE;
1011   if (!callbacks->packet_receive)
1012     return FALSE;
1013
1014   p = silc_calloc(1, sizeof(*p));
1015   if (!p)
1016     return FALSE;
1017
1018   p->priority = priority;
1019   p->callbacks = callbacks;
1020   p->callback_context = callback_context;
1021
1022   silc_mutex_lock(stream->lock);
1023
1024   if (!stream->process) {
1025     stream->process = silc_dlist_init();
1026     if (!stream->process) {
1027       silc_mutex_unlock(stream->lock);
1028       return FALSE;
1029     }
1030   }
1031
1032   /* According to priority set the procesor to correct position.  First
1033      entry has the highest priority */
1034   silc_dlist_start(stream->process);
1035   while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1036     if (p->priority > e->priority) {
1037       silc_dlist_insert(stream->process, p);
1038       break;
1039     }
1040   }
1041   if (!e)
1042     silc_dlist_add(stream->process, p);
1043
1044   /* Get packet types to process */
1045   i = 1;
1046   while (1) {
1047     packet_type = va_arg(ap, SilcInt32);
1048
1049     if (packet_type == SILC_PACKET_ANY)
1050       break;
1051
1052     if (packet_type == -1)
1053       break;
1054
1055     p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
1056     if (!p->types) {
1057       silc_mutex_unlock(stream->lock);
1058       return FALSE;
1059     }
1060
1061     p->types[i - 1] = (SilcPacketType)packet_type;
1062     i++;
1063   }
1064   if (p->types)
1065     p->types[i - 1] = 0;
1066
1067   silc_mutex_unlock(stream->lock);
1068
1069   silc_packet_stream_ref(stream);
1070
1071   return TRUE;
1072 }
1073
1074 /* Links `callbacks' to `stream' for specified packet types */
1075
1076 SilcBool silc_packet_stream_link(SilcPacketStream stream,
1077                                  SilcPacketCallbacks *callbacks,
1078                                  void *callback_context,
1079                                  int priority, ...)
1080 {
1081   va_list ap;
1082   SilcBool ret;
1083
1084   va_start(ap, priority);
1085   ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
1086                                    priority, ap);
1087   va_end(ap);
1088
1089   return ret;
1090 }
1091
1092 /* Unlinks `callbacks' from `stream'. */
1093
1094 void silc_packet_stream_unlink(SilcPacketStream stream,
1095                                SilcPacketCallbacks *callbacks,
1096                                void *callback_context)
1097 {
1098   SilcPacketProcess p;
1099
1100   SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
1101                   callbacks, stream));
1102
1103   silc_mutex_lock(stream->lock);
1104
1105   silc_dlist_start(stream->process);
1106   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
1107     if (p->callbacks == callbacks &&
1108         p->callback_context == callback_context) {
1109       silc_dlist_del(stream->process, p);
1110       silc_free(p->types);
1111       silc_free(p);
1112       break;
1113     }
1114
1115   if (!silc_dlist_count(stream->process)) {
1116     silc_dlist_uninit(stream->process);
1117     stream->process = NULL;
1118   }
1119
1120   silc_mutex_unlock(stream->lock);
1121
1122   silc_packet_stream_unref(stream);
1123 }
1124
1125 /* Returns TRUE if stream is UDP stream */
1126
1127 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream)
1128 {
1129   return stream->udp || silc_socket_stream_is_udp(stream->stream, NULL);
1130 }
1131
1132 /* Return packet sender IP and port for UDP packet stream */
1133
1134 SilcBool silc_packet_get_sender(SilcPacket packet,
1135                                 const char **sender_ip,
1136                                 SilcUInt16 *sender_port)
1137 {
1138   if (!packet->stream->remote_udp)
1139     return FALSE;
1140
1141   *sender_ip = packet->stream->remote_udp->remote_ip;
1142   *sender_port = packet->stream->remote_udp->remote_port;
1143
1144   return TRUE;
1145 }
1146
1147 /* Reference packet stream */
1148
1149 void silc_packet_stream_ref(SilcPacketStream stream)
1150 {
1151   silc_atomic_add_int8(&stream->refcnt, 1);
1152   SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1153                   silc_atomic_get_int8(&stream->refcnt) - 1,
1154                   silc_atomic_get_int8(&stream->refcnt)));
1155 }
1156
1157 /* Unreference packet stream */
1158
1159 void silc_packet_stream_unref(SilcPacketStream stream)
1160 {
1161   SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1162                   silc_atomic_get_int8(&stream->refcnt),
1163                   silc_atomic_get_int8(&stream->refcnt) - 1));
1164   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0)
1165     return;
1166   silc_atomic_add_int8(&stream->refcnt, 1);
1167   silc_packet_stream_destroy(stream);
1168 }
1169
1170 /* Return engine */
1171
1172 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
1173 {
1174   return stream->sc->engine;
1175 }
1176
1177 /* Set application context for packet stream */
1178
1179 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
1180 {
1181   silc_mutex_lock(stream->lock);
1182   stream->stream_context = stream_context;
1183   silc_mutex_unlock(stream->lock);
1184 }
1185
1186 /* Return application context from packet stream */
1187
1188 void *silc_packet_get_context(SilcPacketStream stream)
1189 {
1190   void *context;
1191   silc_mutex_lock(stream->lock);
1192   context = stream->stream_context;
1193   silc_mutex_unlock(stream->lock);
1194   return context;
1195 }
1196
1197 /* Change underlaying stream */
1198
1199 void silc_packet_stream_set_stream(SilcPacketStream ps,
1200                                    SilcStream stream)
1201 {
1202   if (ps->stream)
1203     silc_stream_set_notifier(ps->stream, ps->sc->schedule, NULL, NULL);
1204   ps->stream = stream;
1205   silc_stream_set_notifier(ps->stream, ps->sc->schedule, silc_packet_stream_io,
1206                            ps);
1207 }
1208
1209 /* Return underlaying stream */
1210
1211 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
1212 {
1213   return stream->stream;
1214 }
1215
1216 /* Set keys. */
1217
1218 SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
1219                               SilcCipher receive_key, SilcHmac send_hmac,
1220                               SilcHmac receive_hmac, SilcBool rekey)
1221 {
1222   SILC_LOG_DEBUG(("Setting new keys to packet stream %p", stream));
1223
1224   /* If doing rekey, send REKEY_DONE packet */
1225   if (rekey) {
1226     /* This will take stream lock. */
1227     if (!silc_packet_send_raw(stream, SILC_PACKET_REKEY_DONE, 0,
1228                               stream->src_id_type, stream->src_id,
1229                               stream->src_id_len, stream->dst_id_type,
1230                               stream->dst_id, stream->dst_id_len,
1231                               NULL, 0, stream->send_key[0],
1232                               stream->send_hmac[0]))
1233       return FALSE;
1234
1235     /* Write the packet to the stream */
1236     if (!silc_packet_stream_write(stream, TRUE))
1237       return FALSE;
1238   } else {
1239     silc_mutex_lock(stream->lock);
1240   }
1241
1242   /* In case IV Included is set, save the old keys */
1243   if (stream->iv_included) {
1244     if (stream->send_key[1] && send_key) {
1245       silc_cipher_free(stream->send_key[1]);
1246       stream->send_key[1] = stream->send_key[0];
1247     }
1248     if (stream->receive_key[1] && receive_key) {
1249       silc_cipher_free(stream->receive_key[1]);
1250       stream->receive_key[1] = stream->receive_key[0];
1251     }
1252     if (stream->send_hmac[1] && send_hmac) {
1253       silc_hmac_free(stream->send_hmac[1]);
1254       stream->send_hmac[1] = stream->send_hmac[0];
1255     }
1256     if (stream->receive_hmac[1] && receive_hmac) {
1257       silc_hmac_free(stream->receive_hmac[1]);
1258       stream->receive_hmac[1] = stream->receive_hmac[0];
1259     }
1260   } else {
1261     if (stream->send_key[0] && send_key)
1262       silc_cipher_free(stream->send_key[0]);
1263     if (stream->receive_key[0] && receive_key)
1264       silc_cipher_free(stream->receive_key[0]);
1265     if (stream->send_hmac[0] && send_hmac)
1266       silc_hmac_free(stream->send_hmac[0]);
1267     if (stream->receive_hmac[0] && receive_hmac)
1268       silc_hmac_free(stream->receive_hmac[0]);
1269   }
1270
1271   /* Set keys */
1272   if (send_key)
1273     stream->send_key[0] = send_key;
1274   if (receive_key)
1275     stream->receive_key[0] = receive_key;
1276   if (send_hmac)
1277     stream->send_hmac[0] = send_hmac;
1278   if (receive_hmac)
1279     stream->receive_hmac[0] = receive_hmac;
1280
1281   silc_mutex_unlock(stream->lock);
1282   return TRUE;
1283 }
1284
1285 /* Return current ciphers from packet stream */
1286
1287 SilcBool silc_packet_get_keys(SilcPacketStream stream,
1288                               SilcCipher *send_key,
1289                               SilcCipher *receive_key,
1290                               SilcHmac *send_hmac,
1291                               SilcHmac *receive_hmac)
1292 {
1293   if (!stream->send_key[0] && !stream->receive_key[0] &&
1294       !stream->send_hmac[0] && !stream->receive_hmac[0])
1295     return FALSE;
1296
1297   silc_mutex_lock(stream->lock);
1298
1299   if (send_key)
1300     *send_key = stream->send_key[0];
1301   if (receive_key)
1302     *receive_key = stream->receive_key[0];
1303   if (send_hmac)
1304     *send_hmac = stream->send_hmac[0];
1305   if (receive_hmac)
1306     *receive_hmac = stream->receive_hmac[0];
1307
1308   silc_mutex_unlock(stream->lock);
1309
1310   return TRUE;
1311 }
1312
1313 /* Set SILC IDs to packet stream */
1314
1315 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1316                              SilcIdType src_id_type, const void *src_id,
1317                              SilcIdType dst_id_type, const void *dst_id)
1318 {
1319   SilcUInt32 len;
1320   unsigned char tmp[32];
1321
1322   if (!src_id && !dst_id)
1323     return FALSE;
1324
1325   SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1326
1327   silc_mutex_lock(stream->lock);
1328
1329   if (src_id) {
1330     silc_free(stream->src_id);
1331     if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1332       silc_mutex_unlock(stream->lock);
1333       return FALSE;
1334     }
1335     stream->src_id = silc_memdup(tmp, len);
1336     if (!stream->src_id) {
1337       silc_mutex_unlock(stream->lock);
1338       return FALSE;
1339     }
1340     stream->src_id_type = src_id_type;
1341     stream->src_id_len = len;
1342   }
1343
1344   if (dst_id) {
1345     silc_free(stream->dst_id);
1346     if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1347       silc_mutex_unlock(stream->lock);
1348       return FALSE;
1349     }
1350     stream->dst_id = silc_memdup(tmp, len);
1351     if (!stream->dst_id) {
1352       silc_mutex_unlock(stream->lock);
1353       return FALSE;
1354     }
1355     stream->dst_id_type = dst_id_type;
1356     stream->dst_id_len = len;
1357   }
1358
1359   silc_mutex_unlock(stream->lock);
1360
1361   return TRUE;
1362 }
1363
1364 /* Return IDs from the packet stream */
1365
1366 SilcBool silc_packet_get_ids(SilcPacketStream stream,
1367                              SilcBool *src_id_set, SilcID *src_id,
1368                              SilcBool *dst_id_set, SilcID *dst_id)
1369 {
1370   if (src_id && stream->src_id)
1371     if (!silc_id_str2id2(stream->src_id, stream->src_id_len,
1372                          stream->src_id_type, src_id))
1373       return FALSE;
1374
1375   if (stream->src_id && src_id_set)
1376     *src_id_set = TRUE;
1377
1378   if (dst_id && stream->dst_id)
1379     if (!silc_id_str2id2(stream->dst_id, stream->dst_id_len,
1380                          stream->dst_id_type, dst_id))
1381       return FALSE;
1382
1383   if (stream->dst_id && dst_id_set)
1384     *dst_id_set = TRUE;
1385
1386   return TRUE;
1387 }
1388
1389 /* Adds Security ID (SID) */
1390
1391 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1392 {
1393   if (!stream->iv_included)
1394     return FALSE;
1395
1396   SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1397
1398   stream->sid = sid;
1399   return TRUE;
1400 }
1401
1402 /* Free packet */
1403
1404 void silc_packet_free(SilcPacket packet)
1405 {
1406   SilcPacketStream stream = packet->stream;
1407
1408   SILC_LOG_DEBUG(("Freeing packet %p", packet));
1409
1410   /* Check for double free */
1411   SILC_ASSERT(packet->stream != NULL);
1412
1413   packet->stream = NULL;
1414   packet->src_id = packet->dst_id = NULL;
1415   silc_buffer_reset(&packet->buffer);
1416
1417   silc_mutex_lock(stream->sc->engine->lock);
1418
1419   /* Put the packet back to freelist */
1420   silc_list_add(stream->sc->engine->packet_pool, packet);
1421   if (silc_list_count(stream->sc->engine->packet_pool) == 1)
1422     silc_list_start(stream->sc->engine->packet_pool);
1423
1424   silc_mutex_unlock(stream->sc->engine->lock);
1425 }
1426
1427 /****************************** Packet Sending ******************************/
1428
1429 /* Prepare outgoing data buffer for packet sending.  Returns the
1430    pointer to that buffer into the `packet'. */
1431
1432 static inline SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1433                                                 SilcUInt32 totlen,
1434                                                 SilcHmac hmac,
1435                                                 SilcBuffer packet)
1436 {
1437   unsigned char *oldptr;
1438   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1439
1440   totlen += mac_len;
1441
1442   /* Allocate more space if needed */
1443   if (silc_unlikely(silc_buffer_taillen(&stream->outbuf) < totlen)) {
1444     if (!silc_buffer_realloc(&stream->outbuf,
1445                              silc_buffer_truelen(&stream->outbuf) + totlen))
1446       return FALSE;
1447   }
1448
1449   /* Pull data area for the new packet, and return pointer to the start of
1450      the data area and save the pointer in to the `packet'.  MAC is pulled
1451      later after it's computed. */
1452   oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1453   silc_buffer_set(packet, oldptr, totlen);
1454   silc_buffer_push_tail(packet, mac_len);
1455
1456   return TRUE;
1457 }
1458
1459 /* Increments counter when encrypting in counter mode. */
1460
1461 static inline void silc_packet_send_ctr_increment(SilcPacketStream stream,
1462                                                   SilcCipher cipher,
1463                                                   unsigned char *ret_iv)
1464 {
1465   unsigned char *iv = silc_cipher_get_iv(cipher);
1466   SilcUInt32 pc1, pc2;
1467
1468   /* Increment 64-bit packet counter */
1469   SILC_GET32_MSB(pc1, iv + 4);
1470   SILC_GET32_MSB(pc2, iv + 8);
1471   if (++pc2 == 0)
1472     ++pc1;
1473   SILC_PUT32_MSB(pc1, iv + 4);
1474   SILC_PUT32_MSB(pc2, iv + 8);
1475
1476   /* Reset block counter */
1477   memset(iv + 12, 0, 4);
1478
1479   /* If IV Included flag, return the 64-bit IV for inclusion in packet */
1480   if (stream->iv_included) {
1481     /* Get new nonce */
1482     ret_iv[0] = silc_rng_get_byte_fast(stream->sc->engine->rng);
1483     ret_iv[1] = ret_iv[0] + iv[4];
1484     ret_iv[2] = ret_iv[0] ^ ret_iv[1];
1485     ret_iv[3] = ret_iv[0] + ret_iv[2];
1486     SILC_PUT32_MSB(pc2, ret_iv + 4);
1487     SILC_LOG_HEXDUMP(("IV"), ret_iv, 8);
1488
1489     /* Set new nonce to counter block */
1490     memcpy(iv + 4, ret_iv, 4);
1491   }
1492
1493   SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1494 }
1495
1496 /* Internal routine to assemble outgoing packet.  Assembles and encryptes
1497    the packet.  The silc_packet_stream_write needs to be called to send it
1498    after this returns TRUE. */
1499
1500 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
1501                                             SilcPacketType type,
1502                                             SilcPacketFlags flags,
1503                                             SilcIdType src_id_type,
1504                                             unsigned char *src_id,
1505                                             SilcUInt32 src_id_len,
1506                                             SilcIdType dst_id_type,
1507                                             unsigned char *dst_id,
1508                                             SilcUInt32 dst_id_len,
1509                                             const unsigned char *data,
1510                                             SilcUInt32 data_len,
1511                                             SilcCipher cipher,
1512                                             SilcHmac hmac)
1513 {
1514   unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1515   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1516   int i, enclen, truelen, padlen = 0, ivlen = 0, psnlen = 0;
1517   SilcBool ctr;
1518   SilcBufferStruct packet;
1519
1520   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1521                   "data len %d", silc_get_packet_name(type), stream->send_psn,
1522                   flags, src_id_type, dst_id_type, data_len));
1523
1524   /* Get the true length of the packet. This is saved as payload length
1525      into the packet header.  This does not include the length of the
1526      padding. */
1527   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1528                                             src_id_len + dst_id_len));
1529   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1530                       src_id_len + dst_id_len);
1531
1532   /* If using CTR mode, increment the counter */
1533   ctr = (cipher && silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR);
1534   if (ctr) {
1535     silc_packet_send_ctr_increment(stream, cipher, iv + 1);
1536
1537     /* If IV is included, the SID, IV and sequence number is added to packet */
1538     if (stream->iv_included && cipher) {
1539       psnlen = sizeof(psn);
1540       ivlen = 8 + 1;
1541       iv[0] = stream->sid;
1542     }
1543   } else {
1544     /* If IV is included, the SID, IV and sequence number is added to packet */
1545     if (stream->iv_included && cipher) {
1546       psnlen = sizeof(psn);
1547       ivlen = block_len + 1;
1548       iv[0] = stream->sid;
1549       memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1550     }
1551   }
1552
1553   /* We automatically figure out the packet structure from the packet
1554      type and flags, and calculate correct length.  Private messages with
1555      private keys and channel messages are special packets as their
1556      payload is encrypted already. */
1557   if (type == SILC_PACKET_PRIVATE_MESSAGE &&
1558       flags & SILC_PACKET_FLAG_PRIVMSG_KEY) {
1559     /* Padding is calculated from header + IDs */
1560     if (!ctr)
1561       SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1562                           psnlen), block_len, padlen);
1563
1564     /* Length to encrypt, header + IDs + padding. */
1565     enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1566               padlen + psnlen);
1567
1568   } else if (type == SILC_PACKET_CHANNEL_MESSAGE) {
1569     if (stream->sc->engine->local_is_router && stream->is_router) {
1570       /* Channel messages between routers are encrypted as normal packets.
1571          Padding is calculated from true length of the packet. */
1572       if (!ctr)
1573         SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1574
1575       enclen += padlen + psnlen;
1576     } else {
1577       /* Padding is calculated from header + IDs */
1578       if (!ctr)
1579         SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1580                             psnlen), block_len, padlen);
1581
1582       /* Length to encrypt, header + IDs + padding. */
1583       enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1584                 padlen + psnlen);
1585     }
1586   } else {
1587     /* Padding is calculated from true length of the packet */
1588     if (flags & SILC_PACKET_FLAG_LONG_PAD)
1589       SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1590     else if (!ctr)
1591       SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1592
1593     enclen += padlen + psnlen;
1594   }
1595
1596   /* Remove implementation specific flags */
1597   flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1598
1599   /* Get random padding */
1600   for (i = 0; i < padlen; i++) tmppad[i] =
1601     silc_rng_get_byte_fast(stream->sc->engine->rng);
1602
1603   silc_mutex_lock(stream->lock);
1604
1605   /* Get packet pointer from the outgoing buffer */
1606   if (silc_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen
1607                                               + psnlen, hmac, &packet))) {
1608     silc_mutex_unlock(stream->lock);
1609     return FALSE;
1610   }
1611
1612   SILC_PUT32_MSB(stream->send_psn, psn);
1613
1614   /* Create the packet.  This creates the SILC header, adds padding, and
1615      the actual packet data. */
1616   i = silc_buffer_format(&packet,
1617                          SILC_STR_DATA(iv, ivlen),
1618                          SILC_STR_DATA(psn, psnlen),
1619                          SILC_STR_UI_SHORT(truelen),
1620                          SILC_STR_UI_CHAR(flags),
1621                          SILC_STR_UI_CHAR(type),
1622                          SILC_STR_UI_CHAR(padlen),
1623                          SILC_STR_UI_CHAR(0),
1624                          SILC_STR_UI_CHAR(src_id_len),
1625                          SILC_STR_UI_CHAR(dst_id_len),
1626                          SILC_STR_UI_CHAR(src_id_type),
1627                          SILC_STR_DATA(src_id, src_id_len),
1628                          SILC_STR_UI_CHAR(dst_id_type),
1629                          SILC_STR_DATA(dst_id, dst_id_len),
1630                          SILC_STR_DATA(tmppad, padlen),
1631                          SILC_STR_DATA(data, data_len),
1632                          SILC_STR_END);
1633   if (silc_unlikely(i < 0)) {
1634     silc_mutex_unlock(stream->lock);
1635     return FALSE;
1636   }
1637
1638   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1639                    silc_buffer_data(&packet), silc_buffer_len(&packet));
1640
1641   /* Encrypt the packet */
1642   if (silc_likely(cipher)) {
1643     SILC_LOG_DEBUG(("Encrypting packet"));
1644     silc_cipher_set_iv(cipher, NULL);
1645     if (silc_unlikely(!silc_cipher_encrypt(cipher, packet.data + ivlen,
1646                                            packet.data + ivlen, enclen,
1647                                            NULL))) {
1648       SILC_LOG_ERROR(("Packet encryption failed"));
1649       silc_mutex_unlock(stream->lock);
1650       return FALSE;
1651     }
1652   }
1653
1654   /* Compute HMAC */
1655   if (silc_likely(hmac)) {
1656     SilcUInt32 mac_len;
1657
1658     /* MAC is computed from the entire encrypted packet data, and put
1659        to the end of the packet. */
1660     silc_hmac_init(hmac);
1661     silc_hmac_update(hmac, psn, sizeof(psn));
1662     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1663     silc_hmac_final(hmac, packet.tail, &mac_len);
1664     silc_buffer_pull_tail(&packet, mac_len);
1665     stream->send_psn++;
1666   }
1667
1668   return TRUE;
1669 }
1670
1671 /* Sends a packet */
1672
1673 SilcBool silc_packet_send(SilcPacketStream stream,
1674                           SilcPacketType type, SilcPacketFlags flags,
1675                           const unsigned char *data, SilcUInt32 data_len)
1676 {
1677   SilcBool ret;
1678
1679   ret = silc_packet_send_raw(stream, type, flags,
1680                              stream->src_id_type,
1681                              stream->src_id,
1682                              stream->src_id_len,
1683                              stream->dst_id_type,
1684                              stream->dst_id,
1685                              stream->dst_id_len,
1686                              data, data_len,
1687                              stream->send_key[0],
1688                              stream->send_hmac[0]);
1689
1690   /* Write the packet to the stream */
1691   return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1692 }
1693
1694 /* Sends a packet, extended routine */
1695
1696 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1697                               SilcPacketType type, SilcPacketFlags flags,
1698                               SilcIdType src_id_type, void *src_id,
1699                               SilcIdType dst_id_type, void *dst_id,
1700                               const unsigned char *data, SilcUInt32 data_len,
1701                               SilcCipher cipher, SilcHmac hmac)
1702 {
1703   unsigned char src_id_data[32], dst_id_data[32];
1704   SilcUInt32 src_id_len, dst_id_len;
1705   SilcBool ret;
1706
1707   if (src_id)
1708     if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1709                         sizeof(src_id_data), &src_id_len))
1710       return FALSE;
1711   if (dst_id)
1712     if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1713                         sizeof(dst_id_data), &dst_id_len))
1714       return FALSE;
1715
1716   ret = silc_packet_send_raw(stream, type, flags,
1717                              src_id ? src_id_type : stream->src_id_type,
1718                              src_id ? src_id_data : stream->src_id,
1719                              src_id ? src_id_len : stream->src_id_len,
1720                              dst_id ? dst_id_type : stream->dst_id_type,
1721                              dst_id ? dst_id_data : stream->dst_id,
1722                              dst_id ? dst_id_len : stream->dst_id_len,
1723                              data, data_len,
1724                              cipher ? cipher : stream->send_key[0],
1725                              hmac ? hmac : stream->send_hmac[0]);
1726
1727   /* Write the packet to the stream */
1728   return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1729 }
1730
1731 /* Sends packet after formatting the arguments to buffer */
1732
1733 SilcBool silc_packet_send_va(SilcPacketStream stream,
1734                              SilcPacketType type, SilcPacketFlags flags, ...)
1735 {
1736   SilcBufferStruct buf;
1737   SilcBool ret;
1738   va_list va;
1739
1740   va_start(va, flags);
1741
1742   memset(&buf, 0, sizeof(buf));
1743   if (silc_buffer_format_vp(&buf, va) < 0) {
1744     va_end(va);
1745     return FALSE;
1746   }
1747
1748   ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1749                          silc_buffer_len(&buf));
1750
1751   silc_buffer_purge(&buf);
1752   va_end(va);
1753
1754   return ret;
1755 }
1756
1757 /* Sends packet after formatting the arguments to buffer, extended routine */
1758
1759 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1760                                  SilcPacketType type, SilcPacketFlags flags,
1761                                  SilcIdType src_id_type, void *src_id,
1762                                  SilcIdType dst_id_type, void *dst_id,
1763                                  SilcCipher cipher, SilcHmac hmac, ...)
1764 {
1765   SilcBufferStruct buf;
1766   SilcBool ret;
1767   va_list va;
1768
1769   va_start(va, hmac);
1770
1771   memset(&buf, 0, sizeof(buf));
1772   if (silc_buffer_format_vp(&buf, va) < 0) {
1773     va_end(va);
1774     return FALSE;
1775   }
1776
1777   ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1778                              dst_id_type, dst_id, silc_buffer_data(&buf),
1779                              silc_buffer_len(&buf), cipher, hmac);
1780
1781   silc_buffer_purge(&buf);
1782   va_end(va);
1783
1784   return TRUE;
1785 }
1786
1787 /***************************** Packet Receiving *****************************/
1788
1789 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1790
1791 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1792                                              const unsigned char *data,
1793                                              SilcUInt32 data_len,
1794                                              const unsigned char *packet_mac,
1795                                              const unsigned char *packet_seq,
1796                                              SilcUInt32 sequence)
1797 {
1798   /* Check MAC */
1799   if (silc_likely(hmac)) {
1800     unsigned char mac[32], psn[4];
1801     SilcUInt32 mac_len;
1802
1803     SILC_LOG_DEBUG(("Verifying MAC"));
1804
1805     /* Compute HMAC of packet */
1806     silc_hmac_init(hmac);
1807
1808     if (!packet_seq) {
1809       SILC_PUT32_MSB(sequence, psn);
1810       silc_hmac_update(hmac, psn, 4);
1811     } else
1812       silc_hmac_update(hmac, packet_seq, 4);
1813
1814     silc_hmac_update(hmac, data, data_len);
1815     silc_hmac_final(hmac, mac, &mac_len);
1816
1817     /* Compare the MAC's */
1818     if (silc_unlikely(memcmp(packet_mac, mac, mac_len))) {
1819       SILC_LOG_DEBUG(("MAC failed"));
1820       return FALSE;
1821     }
1822
1823     SILC_LOG_DEBUG(("MAC is Ok"));
1824   }
1825
1826   return TRUE;
1827 }
1828
1829 /* Increments/sets counter when decrypting in counter mode. */
1830
1831 static inline void silc_packet_receive_ctr_increment(SilcPacketStream stream,
1832                                                      unsigned char *iv,
1833                                                      unsigned char *packet_iv)
1834 {
1835   SilcUInt32 pc1, pc2;
1836
1837   /* If IV Included flag, set the IV from packet to block counter. */
1838   if (stream->iv_included) {
1839     memcpy(iv + 4, packet_iv, 8);
1840   } else {
1841     /* Increment 64-bit packet counter. */
1842     SILC_GET32_MSB(pc1, iv + 4);
1843     SILC_GET32_MSB(pc2, iv + 8);
1844     if (++pc2 == 0)
1845       ++pc1;
1846     SILC_PUT32_MSB(pc1, iv + 4);
1847     SILC_PUT32_MSB(pc2, iv + 8);
1848   }
1849
1850   /* Reset block counter */
1851   memset(iv + 12, 0, 4);
1852
1853   SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1854 }
1855
1856 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
1857    Return 0 when packet is normal and 1 when it it special, -1 on error. */
1858
1859 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1860                                       SilcUInt32 sequence, SilcBuffer buffer,
1861                                       SilcBool normal)
1862 {
1863   if (normal == TRUE) {
1864     if (silc_likely(cipher)) {
1865       /* Decrypt rest of the packet */
1866       SILC_LOG_DEBUG(("Decrypting the packet"));
1867       if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1868                                              buffer->data,
1869                                              silc_buffer_len(buffer), NULL)))
1870         return -1;
1871     }
1872     return 0;
1873
1874   } else {
1875     /* Decrypt rest of the header plus padding */
1876     if (silc_likely(cipher)) {
1877       SilcUInt16 len;
1878       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1879
1880       SILC_LOG_DEBUG(("Decrypting the header"));
1881
1882       /* Padding length + src id len + dst id len + header length - 16
1883          bytes already decrypted, gives the rest of the encrypted packet */
1884       silc_buffer_push(buffer, block_len);
1885       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1886               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1887              block_len);
1888       silc_buffer_pull(buffer, block_len);
1889
1890       if (silc_unlikely(len > silc_buffer_len(buffer))) {
1891         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1892                         "packet dropped"));
1893         return -1;
1894       }
1895       if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1896                                              buffer->data, len, NULL)))
1897         return -1;
1898     }
1899
1900     return 1;
1901   }
1902 }
1903
1904 /* Parses the packet. This is called when a whole packet is ready to be
1905    parsed. The buffer sent must be already decrypted before calling this
1906    function. */
1907
1908 static inline SilcBool silc_packet_parse(SilcPacket packet)
1909 {
1910   SilcBuffer buffer = &packet->buffer;
1911   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1912   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1913   int ret;
1914
1915   SILC_LOG_DEBUG(("Parsing incoming packet"));
1916
1917   /* Parse the buffer.  This parses the SILC header of the packet. */
1918   ret = silc_buffer_unformat(buffer,
1919                              SILC_STR_ADVANCE,
1920                              SILC_STR_OFFSET(6),
1921                              SILC_STR_UI_CHAR(&src_id_len),
1922                              SILC_STR_UI_CHAR(&dst_id_len),
1923                              SILC_STR_UI_CHAR(&src_id_type),
1924                              SILC_STR_END);
1925   if (silc_unlikely(ret == -1)) {
1926     if (!packet->stream->udp &&
1927         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1928       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1929     return FALSE;
1930   }
1931
1932   if (silc_unlikely(src_id_len > SILC_PACKET_MAX_ID_LEN ||
1933                     dst_id_len > SILC_PACKET_MAX_ID_LEN)) {
1934     if (!packet->stream->udp &&
1935         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1936       SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1937                       packet->src_id_len, packet->dst_id_len));
1938     return FALSE;
1939   }
1940
1941   ret = silc_buffer_unformat(buffer,
1942                              SILC_STR_ADVANCE,
1943                              SILC_STR_DATA(&packet->src_id, src_id_len),
1944                              SILC_STR_UI_CHAR(&dst_id_type),
1945                              SILC_STR_DATA(&packet->dst_id, dst_id_len),
1946                              SILC_STR_OFFSET(padlen),
1947                              SILC_STR_END);
1948   if (silc_unlikely(ret == -1)) {
1949     if (!packet->stream->udp &&
1950         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1951       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1952     return FALSE;
1953   }
1954
1955   if (silc_unlikely(src_id_type > SILC_ID_CHANNEL ||
1956                     dst_id_type > SILC_ID_CHANNEL)) {
1957     if (!packet->stream->udp &&
1958         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1959       SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1960                       src_id_type, dst_id_type));
1961     return FALSE;
1962   }
1963
1964   packet->src_id_len = src_id_len;
1965   packet->dst_id_len = dst_id_len;
1966   packet->src_id_type = src_id_type;
1967   packet->dst_id_type = dst_id_type;
1968
1969   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1970                    silc_buffer_len(buffer)), buffer->head,
1971                    silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1972
1973   SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1974                   silc_get_packet_name(packet->type)));
1975
1976   return TRUE;
1977 }
1978
1979 /* Dispatch packet to application.  Called with stream->lock locked.
1980    Returns FALSE if the stream was destroyed while dispatching a packet. */
1981
1982 static SilcBool silc_packet_dispatch(SilcPacket packet)
1983 {
1984   SilcPacketStream stream = packet->stream;
1985   SilcPacketProcess p;
1986   SilcBool default_sent = FALSE;
1987   SilcPacketType *pt;
1988
1989   /* Dispatch packet to all packet processors that want it */
1990
1991   if (silc_likely(!stream->process)) {
1992     /* Send to default processor as no others exist */
1993     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1994     silc_mutex_unlock(stream->lock);
1995     if (silc_unlikely(!stream->sc->engine->callbacks->
1996                       packet_receive(stream->sc->engine, stream, packet,
1997                                      stream->sc->engine->callback_context,
1998                                      stream->stream_context)))
1999       silc_packet_free(packet);
2000     silc_mutex_lock(stream->lock);
2001     return stream->destroyed == FALSE;
2002   }
2003
2004   silc_dlist_start(stream->process);
2005   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
2006
2007     /* If priority is 0 or less, we send to default processor first
2008        because default processor has 0 priority */
2009     if (!default_sent && p->priority <= 0) {
2010       SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
2011       default_sent = TRUE;
2012       silc_mutex_unlock(stream->lock);
2013       if (stream->sc->engine->callbacks->
2014           packet_receive(stream->sc->engine, stream, packet,
2015                          stream->sc->engine->callback_context,
2016                          stream->stream_context)) {
2017         silc_mutex_lock(stream->lock);
2018         return stream->destroyed == FALSE;
2019       }
2020       silc_mutex_lock(stream->lock);
2021     }
2022
2023     /* Send to processor */
2024     if (!p->types) {
2025       /* Send all packet types */
2026       SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
2027       silc_mutex_unlock(stream->lock);
2028       if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
2029                                        p->callback_context,
2030                                        stream->stream_context)) {
2031         silc_mutex_lock(stream->lock);
2032         return stream->destroyed == FALSE;
2033       }
2034       silc_mutex_lock(stream->lock);
2035     } else {
2036       /* Send specific types */
2037       for (pt = p->types; *pt; pt++) {
2038         if (*pt != packet->type)
2039           continue;
2040         SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
2041         silc_mutex_unlock(stream->lock);
2042         if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
2043                                          p->callback_context,
2044                                          stream->stream_context)) {
2045           silc_mutex_lock(stream->lock);
2046           return stream->destroyed == FALSE;
2047         }
2048         silc_mutex_lock(stream->lock);
2049         break;
2050       }
2051     }
2052   }
2053
2054   if (!default_sent) {
2055     /* Send to default processor as it has not been sent yet */
2056     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
2057     silc_mutex_unlock(stream->lock);
2058     if (stream->sc->engine->callbacks->
2059         packet_receive(stream->sc->engine, stream, packet,
2060                        stream->sc->engine->callback_context,
2061                        stream->stream_context)) {
2062       silc_mutex_lock(stream->lock);
2063       return stream->destroyed == FALSE;
2064     }
2065     silc_mutex_lock(stream->lock);
2066   }
2067
2068   /* If we got here, no one wanted the packet, so drop it */
2069   silc_packet_free(packet);
2070   return stream->destroyed == FALSE;
2071 }
2072
2073 /* Process incoming data and parse packets.  Called with stream->lock
2074    locked. */
2075
2076 static void silc_packet_read_process(SilcPacketStream stream)
2077 {
2078   SilcBuffer inbuf;
2079   SilcCipher cipher;
2080   SilcHmac hmac;
2081   SilcPacket packet;
2082   SilcUInt8 sid;
2083   SilcUInt16 packetlen;
2084   SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
2085   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
2086   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
2087   SilcBool normal;
2088   int ret;
2089
2090   /* Get inbuf.  If there is already some data for this stream in the buffer
2091      we already have it.  Otherwise get the current one from list, it will
2092      include the data. */
2093   inbuf = stream->inbuf;
2094   if (!inbuf) {
2095     silc_dlist_start(stream->sc->inbufs);
2096     inbuf = silc_dlist_get(stream->sc->inbufs);
2097   }
2098
2099   /* Parse the packets from the data */
2100   while (silc_buffer_len(inbuf) > 0) {
2101     ivlen = psnlen = 0;
2102     cipher = stream->receive_key[0];
2103     hmac = stream->receive_hmac[0];
2104     normal = FALSE;
2105
2106     if (silc_unlikely(silc_buffer_len(inbuf) <
2107                       (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
2108                        SILC_PACKET_MIN_HEADER_LEN))) {
2109       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
2110       silc_dlist_del(stream->sc->inbufs, inbuf);
2111       stream->inbuf = inbuf;
2112       return;
2113     }
2114
2115     if (silc_likely(hmac))
2116       mac_len = silc_hmac_len(hmac);
2117     else
2118       mac_len = 0;
2119
2120     /* Decrypt first block of the packet to get the length field out */
2121     if (silc_likely(cipher)) {
2122       block_len = silc_cipher_get_block_len(cipher);
2123
2124       if (stream->iv_included) {
2125         /* SID, IV and sequence number is included in the ciphertext */
2126         sid = (SilcUInt8)inbuf->data[0];
2127
2128         if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR) {
2129           /* Set the CTR mode IV from packet to counter block */
2130           memcpy(iv, silc_cipher_get_iv(cipher), block_len);
2131           silc_packet_receive_ctr_increment(stream, iv, inbuf->data + 1);
2132           ivlen = 8 + 1;
2133         } else {
2134           /* Get IV from packet */
2135           memcpy(iv, inbuf->data + 1, block_len);
2136           ivlen = block_len + 1;
2137         }
2138         psnlen = 4;
2139
2140         /* Check SID, and get correct decryption key */
2141         if (sid != stream->sid) {
2142           /* If SID is recent get the previous key and use it */
2143           if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
2144               stream->receive_key[1] && !stream->receive_hmac[1]) {
2145             cipher = stream->receive_key[1];
2146             hmac = stream->receive_hmac[1];
2147           } else {
2148             /* The SID is unknown, drop rest of the data in buffer */
2149             SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
2150                             sid, stream->sid));
2151             silc_mutex_unlock(stream->lock);
2152             SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
2153             silc_mutex_lock(stream->lock);
2154             goto out;
2155           }
2156         }
2157       } else {
2158         memcpy(iv, silc_cipher_get_iv(cipher), block_len);
2159
2160         /* If using CTR mode, increment the counter */
2161         if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
2162           silc_packet_receive_ctr_increment(stream, iv, NULL);
2163       }
2164
2165       if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
2166         silc_cipher_set_iv(cipher, NULL);
2167       silc_cipher_decrypt(cipher, inbuf->data + ivlen, tmp, block_len, iv);
2168
2169       header = tmp;
2170       if (stream->iv_included) {
2171         /* Take sequence number from packet */
2172         packet_seq = header;
2173         header += 4;
2174       }
2175     } else {
2176       /* Unencrypted packet */
2177       block_len = SILC_PACKET_MIN_HEADER_LEN;
2178       header = inbuf->data;
2179     }
2180
2181     /* Get packet length and full packet length with padding */
2182     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
2183
2184     /* Sanity checks */
2185     if (silc_unlikely(packetlen < SILC_PACKET_MIN_LEN)) {
2186       if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
2187         SILC_LOG_ERROR(("Received too short packet"));
2188       silc_mutex_unlock(stream->lock);
2189       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2190       silc_mutex_lock(stream->lock);
2191       memset(tmp, 0, sizeof(tmp));
2192       goto out;
2193     }
2194
2195     if (silc_buffer_len(inbuf) < paddedlen + ivlen + mac_len) {
2196       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
2197                       "(%d bytes)",
2198                       paddedlen + mac_len - silc_buffer_len(inbuf)));
2199       memset(tmp, 0, sizeof(tmp));
2200       silc_dlist_del(stream->sc->inbufs, inbuf);
2201       stream->inbuf = inbuf;
2202       return;
2203     }
2204
2205     /* Check MAC of the packet */
2206     if (silc_unlikely(!silc_packet_check_mac(hmac, inbuf->data,
2207                                              paddedlen + ivlen,
2208                                              inbuf->data + ivlen +
2209                                              paddedlen, packet_seq,
2210                                              stream->receive_psn))) {
2211       silc_mutex_unlock(stream->lock);
2212       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
2213       silc_mutex_lock(stream->lock);
2214       memset(tmp, 0, sizeof(tmp));
2215       goto out;
2216     }
2217
2218     /* Get packet */
2219     packet = silc_packet_alloc(stream->sc->engine);
2220     if (silc_unlikely(!packet)) {
2221       silc_mutex_unlock(stream->lock);
2222       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2223       silc_mutex_lock(stream->lock);
2224       memset(tmp, 0, sizeof(tmp));
2225       goto out;
2226     }
2227     packet->stream = stream;
2228
2229     /* Allocate more space to packet buffer, if needed */
2230     if (silc_unlikely(silc_buffer_truelen(&packet->buffer) < paddedlen)) {
2231       if (!silc_buffer_realloc(&packet->buffer,
2232                                silc_buffer_truelen(&packet->buffer) +
2233                                (paddedlen -
2234                                 silc_buffer_truelen(&packet->buffer)))) {
2235         silc_mutex_unlock(stream->lock);
2236         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2237         silc_mutex_lock(stream->lock);
2238         silc_packet_free(packet);
2239         memset(tmp, 0, sizeof(tmp));
2240         goto out;
2241       }
2242     }
2243
2244     /* Parse packet header */
2245     packet->flags = (SilcPacketFlags)header[2];
2246     packet->type = (SilcPacketType)header[3];
2247
2248     if (stream->sc->engine->local_is_router) {
2249       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2250           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2251         normal = FALSE;
2252       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
2253                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
2254                 stream->is_router == TRUE))
2255         normal = TRUE;
2256     } else {
2257       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2258           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2259         normal = FALSE;
2260       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
2261         normal = TRUE;
2262     }
2263
2264     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
2265                       stream->receive_psn, paddedlen + ivlen + mac_len),
2266                      inbuf->data, paddedlen + ivlen + mac_len);
2267
2268     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
2269     silc_buffer_pull_tail(&packet->buffer, paddedlen);
2270     silc_buffer_put(&packet->buffer, header, block_len - psnlen);
2271     silc_buffer_pull(&packet->buffer, block_len - psnlen);
2272     silc_buffer_put(&packet->buffer, (inbuf->data + ivlen +
2273                                       psnlen + (block_len - psnlen)),
2274                     paddedlen - ivlen - psnlen - (block_len - psnlen));
2275     if (silc_likely(cipher)) {
2276       silc_cipher_set_iv(cipher, iv);
2277       ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
2278                                 &packet->buffer, normal);
2279       if (silc_unlikely(ret < 0)) {
2280         silc_mutex_unlock(stream->lock);
2281         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
2282         silc_mutex_lock(stream->lock);
2283         silc_packet_free(packet);
2284         memset(tmp, 0, sizeof(tmp));
2285         goto out;
2286       }
2287
2288       stream->receive_psn++;
2289     }
2290     silc_buffer_push(&packet->buffer, block_len);
2291
2292     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
2293     silc_buffer_pull(inbuf, paddedlen + mac_len);
2294
2295     /* Parse the packet */
2296     if (silc_unlikely(!silc_packet_parse(packet))) {
2297       silc_mutex_unlock(stream->lock);
2298       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2299       silc_mutex_lock(stream->lock);
2300       silc_packet_free(packet);
2301       memset(tmp, 0, sizeof(tmp));
2302       goto out;
2303     }
2304
2305     /* Dispatch the packet to application */
2306     if (!silc_packet_dispatch(packet))
2307       break;
2308   }
2309
2310  out:
2311   /* Add inbuf back to free list, if we owned it. */
2312   if (stream->inbuf) {
2313     silc_dlist_add(stream->sc->inbufs, inbuf);
2314     stream->inbuf = NULL;
2315   }
2316
2317   silc_buffer_reset(inbuf);
2318 }
2319
2320 /****************************** Packet Waiting ******************************/
2321
2322 /* Packet wait receive callback */
2323 static SilcBool
2324 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2325                                 SilcPacketStream stream,
2326                                 SilcPacket packet,
2327                                 void *callback_context,
2328                                 void *stream_context);
2329
2330 /* Packet waiting callbacks */
2331 static SilcPacketCallbacks silc_packet_wait_cbs =
2332 {
2333   silc_packet_wait_packet_receive, NULL, NULL
2334 };
2335
2336 /* Packet waiting context */
2337 typedef struct {
2338   SilcMutex wait_lock;
2339   SilcCond wait_cond;
2340   SilcList packet_queue;
2341   unsigned char id[28];
2342   unsigned int id_type     : 2;
2343   unsigned int id_len      : 5;
2344   unsigned int stopped     : 1;
2345 } *SilcPacketWait;
2346
2347 /* Packet wait receive callback */
2348
2349 static SilcBool
2350 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2351                                 SilcPacketStream stream,
2352                                 SilcPacket packet,
2353                                 void *callback_context,
2354                                 void *stream_context)
2355 {
2356   SilcPacketWait pw = callback_context;
2357
2358   /* If source ID is specified check for it */
2359   if (pw->id_len) {
2360     if (pw->id_type != packet->src_id_type ||
2361         memcmp(pw->id, packet->src_id, pw->id_len))
2362       return FALSE;
2363   }
2364
2365   /* Signal the waiting thread for a new packet */
2366   silc_mutex_lock(pw->wait_lock);
2367
2368   if (silc_unlikely(pw->stopped)) {
2369     silc_mutex_unlock(pw->wait_lock);
2370     return FALSE;
2371   }
2372
2373   silc_list_add(pw->packet_queue, packet);
2374   silc_cond_broadcast(pw->wait_cond);
2375
2376   silc_mutex_unlock(pw->wait_lock);
2377
2378   return TRUE;
2379 }
2380
2381 /* Initialize packet waiting */
2382
2383 void *silc_packet_wait_init(SilcPacketStream stream,
2384                             const SilcID *source_id, ...)
2385 {
2386   SilcPacketWait pw;
2387   SilcBool ret;
2388   va_list ap;
2389
2390   pw = silc_calloc(1, sizeof(*pw));
2391   if (!pw)
2392     return NULL;
2393
2394   /* Allocate mutex and conditional variable */
2395   if (!silc_mutex_alloc(&pw->wait_lock)) {
2396     silc_free(pw);
2397     return NULL;
2398   }
2399   if (!silc_cond_alloc(&pw->wait_cond)) {
2400     silc_mutex_free(pw->wait_lock);
2401     silc_free(pw);
2402     return NULL;
2403   }
2404
2405   /* Link to the packet stream for the requested packet types */
2406   va_start(ap, source_id);
2407   ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2408                                    10000000, ap);
2409   va_end(ap);
2410   if (!ret) {
2411     silc_cond_free(pw->wait_cond);
2412     silc_mutex_free(pw->wait_lock);
2413     silc_free(pw);
2414     return NULL;
2415   }
2416
2417   /* Initialize packet queue */
2418   silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2419
2420   if (source_id) {
2421     SilcUInt32 id_len;
2422     silc_id_id2str(SILC_ID_GET_ID(*source_id), source_id->type, pw->id,
2423                    sizeof(pw->id), &id_len);
2424     pw->id_type = source_id->type;
2425     pw->id_len = id_len;
2426   }
2427
2428   return (void *)pw;
2429 }
2430
2431 /* Uninitialize packet waiting */
2432
2433 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2434 {
2435   SilcPacketWait pw = waiter;
2436   SilcPacket packet;
2437
2438   /* Signal any threads to stop waiting */
2439   silc_mutex_lock(pw->wait_lock);
2440   pw->stopped = TRUE;
2441   silc_cond_broadcast(pw->wait_cond);
2442   silc_mutex_unlock(pw->wait_lock);
2443   silc_thread_yield();
2444
2445   /* Re-acquire lock and free resources */
2446   silc_mutex_lock(pw->wait_lock);
2447   silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2448
2449   /* Free any remaining packets */
2450   silc_list_start(pw->packet_queue);
2451   while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2452     silc_packet_free(packet);
2453
2454   silc_mutex_unlock(pw->wait_lock);
2455   silc_cond_free(pw->wait_cond);
2456   silc_mutex_free(pw->wait_lock);
2457   silc_free(pw);
2458 }
2459
2460 /* Blocks thread until a packet has been received. */
2461
2462 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2463 {
2464   SilcPacketWait pw = waiter;
2465   SilcBool ret = FALSE;
2466
2467   silc_mutex_lock(pw->wait_lock);
2468
2469   /* Wait here until packet has arrived */
2470   while (silc_list_count(pw->packet_queue) == 0) {
2471     if (silc_unlikely(pw->stopped)) {
2472       silc_mutex_unlock(pw->wait_lock);
2473       return -1;
2474     }
2475     ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2476   }
2477
2478   /* Return packet */
2479   silc_list_start(pw->packet_queue);
2480   *return_packet = silc_list_get(pw->packet_queue);
2481   silc_list_del(pw->packet_queue, *return_packet);
2482
2483   silc_mutex_unlock(pw->wait_lock);
2484
2485   return ret == TRUE ? 1 : 0;
2486 }
2487
2488 /************************** Packet Stream Wrapper ***************************/
2489
2490 /* Packet stream wrapper receive callback */
2491 static SilcBool
2492 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2493                                 SilcPacketStream stream,
2494                                 SilcPacket packet,
2495                                 void *callback_context,
2496                                 void *stream_context);
2497
2498 const SilcStreamOps silc_packet_stream_ops;
2499
2500 /* Packet stream wrapper context */
2501 typedef struct {
2502   const SilcStreamOps *ops;
2503   SilcPacketStream stream;
2504   SilcMutex lock;
2505   void *waiter;                   /* Waiter context in blocking mode */
2506   SilcPacketWrapCoder coder;
2507   void *coder_context;
2508   SilcBuffer encbuf;
2509   SilcStreamNotifier callback;
2510   void *context;
2511   SilcList in_queue;
2512   SilcPacketType type;
2513   SilcPacketFlags flags;
2514   unsigned int closed        : 1;
2515   unsigned int blocking      : 1;
2516   unsigned int read_more     : 1;
2517 } *SilcPacketWrapperStream;
2518
2519 /* Packet wrapper callbacks */
2520 static SilcPacketCallbacks silc_packet_wrap_cbs =
2521 {
2522   silc_packet_wrap_packet_receive, NULL, NULL
2523 };
2524
2525 /* Packet stream wrapper receive callback, non-blocking mode */
2526
2527 static SilcBool
2528 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2529                                 SilcPacketStream stream,
2530                                 SilcPacket packet,
2531                                 void *callback_context,
2532                                 void *stream_context)
2533 {
2534   SilcPacketWrapperStream pws = callback_context;
2535
2536   if (pws->closed || !pws->callback)
2537     return FALSE;
2538
2539   silc_mutex_lock(pws->lock);
2540   silc_list_add(pws->in_queue, packet);
2541   silc_mutex_unlock(pws->lock);
2542
2543   /* Call notifier callback */
2544   pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2545
2546   return TRUE;
2547 }
2548
2549 /* Task callback to notify more data is available for reading */
2550
2551 SILC_TASK_CALLBACK(silc_packet_wrap_read_more)
2552 {
2553   SilcPacketWrapperStream pws = context;
2554
2555   if (pws->closed || !pws->callback)
2556     return;
2557
2558   /* Call notifier callback */
2559   pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2560 }
2561
2562 /* Read SILC packet */
2563
2564 int silc_packet_wrap_read(SilcStream stream, unsigned char *buf,
2565                           SilcUInt32 buf_len)
2566 {
2567   SilcPacketWrapperStream pws = stream;
2568   SilcPacket packet;
2569   SilcBool read_more = FALSE;
2570   int len;
2571
2572   if (pws->closed)
2573     return -2;
2574
2575   if (pws->blocking) {
2576     /* Block until packet is received */
2577     if ((silc_packet_wait(pws->waiter, 0, &packet)) < 0)
2578       return -2;
2579     if (pws->closed)
2580       return -2;
2581   } else {
2582     /* Non-blocking mode */
2583     silc_mutex_lock(pws->lock);
2584     if (!silc_list_count(pws->in_queue)) {
2585       silc_mutex_unlock(pws->lock);
2586       return -1;
2587     }
2588
2589     silc_list_start(pws->in_queue);
2590     packet = silc_list_get(pws->in_queue);
2591     silc_list_del(pws->in_queue, packet);
2592     silc_mutex_unlock(pws->lock);
2593   }
2594
2595   /* Call decoder if set */
2596   if (pws->coder && !pws->read_more)
2597     pws->coder(stream, SILC_STREAM_CAN_READ, &packet->buffer,
2598                pws->coder_context);
2599
2600   len = silc_buffer_len(&packet->buffer);
2601   if (len > buf_len) {
2602     len = buf_len;
2603     read_more = TRUE;
2604   }
2605
2606   /* Read data */
2607   memcpy(buf, packet->buffer.data, len);
2608
2609   if (read_more && !pws->blocking) {
2610     /* More data will be available (in blocking mode not supported). */
2611     silc_buffer_pull(&packet->buffer, len);
2612     silc_list_insert(pws->in_queue, NULL, packet);
2613     silc_schedule_task_add_timeout(pws->stream->sc->schedule,
2614                                    silc_packet_wrap_read_more, pws, 0, 0);
2615     pws->read_more = TRUE;
2616     return len;
2617   }
2618
2619   pws->read_more = FALSE;
2620   silc_packet_free(packet);
2621   return len;
2622 }
2623
2624 /* Write SILC packet */
2625
2626 int silc_packet_wrap_write(SilcStream stream, const unsigned char *data,
2627                            SilcUInt32 data_len)
2628 {
2629   SilcPacketWrapperStream pws = stream;
2630   SilcBool ret = FALSE;
2631
2632   /* Call encoder if set */
2633   if (pws->coder) {
2634     silc_buffer_reset(pws->encbuf);
2635     ret = pws->coder(stream, SILC_STREAM_CAN_WRITE, pws->encbuf,
2636                      pws->coder_context);
2637   }
2638
2639   /* Send the SILC packet */
2640   if (ret) {
2641     if (!silc_packet_send_va(pws->stream, pws->type, pws->flags,
2642                              SILC_STR_DATA(silc_buffer_data(pws->encbuf),
2643                                            silc_buffer_len(pws->encbuf)),
2644                              SILC_STR_DATA(data, data_len),
2645                              SILC_STR_END))
2646       return -2;
2647   } else {
2648     if (!silc_packet_send(pws->stream, pws->type, pws->flags, data, data_len))
2649       return -2;
2650   }
2651
2652   return data_len;
2653 }
2654
2655 /* Close stream */
2656
2657 SilcBool silc_packet_wrap_close(SilcStream stream)
2658 {
2659   SilcPacketWrapperStream pws = stream;
2660
2661   if (pws->closed)
2662     return TRUE;
2663
2664   if (pws->blocking) {
2665     /* Close packet waiter */
2666     silc_packet_wait_uninit(pws->waiter, pws->stream);
2667   } else {
2668     /* Unlink */
2669     if (pws->callback)
2670       silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2671   }
2672   pws->closed = TRUE;
2673
2674   return TRUE;
2675 }
2676
2677 /* Destroy wrapper stream */
2678
2679 void silc_packet_wrap_destroy(SilcStream stream)
2680
2681 {
2682   SilcPacketWrapperStream pws = stream;
2683   SilcPacket packet;
2684
2685   SILC_LOG_DEBUG(("Destroying wrapped packet stream %p", pws));
2686
2687   silc_stream_close(stream);
2688   silc_list_start(pws->in_queue);
2689   while ((packet = silc_list_get(pws->in_queue)))
2690     silc_packet_free(packet);
2691   if (pws->lock)
2692     silc_mutex_free(pws->lock);
2693   if (pws->encbuf)
2694     silc_buffer_free(pws->encbuf);
2695   silc_packet_stream_unref(pws->stream);
2696
2697   silc_free(pws);
2698 }
2699
2700 /* Link stream to receive packets */
2701
2702 SilcBool silc_packet_wrap_notifier(SilcStream stream,
2703                                    SilcSchedule schedule,
2704                                    SilcStreamNotifier callback,
2705                                    void *context)
2706 {
2707   SilcPacketWrapperStream pws = stream;
2708
2709   if (pws->closed || pws->blocking)
2710     return FALSE;
2711
2712   /* Link to receive packets */
2713   if (callback)
2714     silc_packet_stream_link(pws->stream, &silc_packet_wrap_cbs, pws,
2715                             100000, pws->type, -1);
2716   else
2717     silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2718
2719   pws->callback = callback;
2720   pws->context = context;
2721
2722   return TRUE;
2723 }
2724
2725 /* Return schedule */
2726
2727 SilcSchedule silc_packet_wrap_get_schedule(SilcStream stream)
2728 {
2729   return NULL;
2730 }
2731
2732 /* Wraps packet stream into SilcStream. */
2733
2734 SilcStream silc_packet_stream_wrap(SilcPacketStream stream,
2735                                    SilcPacketType type,
2736                                    SilcPacketFlags flags,
2737                                    SilcBool blocking_mode,
2738                                    SilcPacketWrapCoder coder,
2739                                    void *context)
2740 {
2741   SilcPacketWrapperStream pws;
2742
2743   pws = silc_calloc(1, sizeof(*pws));
2744   if (!pws)
2745     return NULL;
2746
2747   SILC_LOG_DEBUG(("Wrapping packet stream %p to stream %p", stream, pws));
2748
2749   pws->ops = &silc_packet_stream_ops;
2750   pws->stream = stream;
2751   pws->type = type;
2752   pws->flags = flags;
2753   pws->blocking = blocking_mode;
2754   pws->coder = coder;
2755   pws->coder_context = context;
2756
2757   /* Allocate small amount for encoder buffer. */
2758   if (pws->coder)
2759     pws->encbuf = silc_buffer_alloc(8);
2760
2761   if (pws->blocking) {
2762     /* Blocking mode.  Use packet waiter to do the thing. */
2763     pws->waiter = silc_packet_wait_init(pws->stream, NULL, pws->type, -1);
2764     if (!pws->waiter) {
2765       silc_free(pws);
2766       return NULL;
2767     }
2768   } else {
2769     /* Non-blocking mode */
2770     silc_mutex_alloc(&pws->lock);
2771     silc_list_init(pws->in_queue, struct SilcPacketStruct, next);
2772   }
2773
2774   silc_packet_stream_ref(stream);
2775
2776   return (SilcStream)pws;
2777 }
2778
2779 const SilcStreamOps silc_packet_stream_ops =
2780 {
2781   silc_packet_wrap_read,
2782   silc_packet_wrap_write,
2783   silc_packet_wrap_close,
2784   silc_packet_wrap_destroy,
2785   silc_packet_wrap_notifier,
2786   silc_packet_wrap_get_schedule,
2787 };