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