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