Fixed dispatch locking, fixed incoming packet queue length check.
[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
1112 /***************************** Packet Receiving *****************************/
1113
1114 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1115
1116 static SilcBool silc_packet_check_mac(SilcHmac hmac,
1117                                       const unsigned char *data,
1118                                       SilcUInt32 data_len,
1119                                       const unsigned char *packet_mac,
1120                                       const unsigned char *packet_seq,
1121                                       SilcUInt32 sequence)
1122 {
1123   /* Check MAC */
1124   if (hmac) {
1125     unsigned char mac[32], psn[4];
1126     SilcUInt32 mac_len;
1127
1128     SILC_LOG_DEBUG(("Verifying MAC"));
1129
1130     /* Compute HMAC of packet */
1131     silc_hmac_init(hmac);
1132
1133     if (!packet_seq) {
1134       SILC_PUT32_MSB(sequence, psn);
1135       silc_hmac_update(hmac, psn, 4);
1136     } else
1137       silc_hmac_update(hmac, packet_seq, 4);
1138
1139     silc_hmac_update(hmac, data, data_len);
1140     silc_hmac_final(hmac, mac, &mac_len);
1141
1142     /* Compare the MAC's */
1143     if (memcmp(packet_mac, mac, mac_len)) {
1144       SILC_LOG_DEBUG(("MAC failed"));
1145       return FALSE;
1146     }
1147
1148     SILC_LOG_DEBUG(("MAC is Ok"));
1149   }
1150
1151   return TRUE;
1152 }
1153
1154 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
1155    Return 0 when packet is normal and 1 when it it special, -1 on error. */
1156
1157 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1158                                SilcUInt32 sequence, SilcBuffer buffer,
1159                                SilcBool normal)
1160 {
1161   if (normal == TRUE) {
1162     if (cipher) {
1163       /* Decrypt rest of the packet */
1164       SILC_LOG_DEBUG(("Decrypting the packet"));
1165       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1166                                silc_buffer_len(buffer), NULL))
1167         return -1;
1168     }
1169     return 0;
1170
1171   } else {
1172     /* Decrypt rest of the header plus padding */
1173     if (cipher) {
1174       SilcUInt16 len;
1175       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1176
1177       SILC_LOG_DEBUG(("Decrypting the header"));
1178
1179       /* Padding length + src id len + dst id len + header length - 16
1180          bytes already decrypted, gives the rest of the encrypted packet */
1181       silc_buffer_push(buffer, block_len);
1182       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1183               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1184              block_len);
1185       silc_buffer_pull(buffer, block_len);
1186
1187       if (len > silc_buffer_len(buffer)) {
1188         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1189                         "packet dropped"));
1190         return -1;
1191       }
1192       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1193                                len, NULL))
1194         return -1;
1195     }
1196
1197     return 1;
1198   }
1199 }
1200
1201 /* Parses the packet. This is called when a whole packet is ready to be
1202    parsed. The buffer sent must be already decrypted before calling this
1203    function. */
1204
1205 static SilcBool silc_packet_parse(SilcPacket packet)
1206 {
1207   SilcBuffer buffer = &packet->buffer;
1208   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1209   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1210   int ret;
1211
1212   SILC_LOG_DEBUG(("Parsing incoming packet"));
1213
1214   /* Parse the buffer.  This parses the SILC header of the packet. */
1215   ret = silc_buffer_unformat(buffer,
1216                              SILC_STR_ADVANCE,
1217                              SILC_STR_OFFSET(6),
1218                              SILC_STR_UI_CHAR(&src_id_len),
1219                              SILC_STR_UI_CHAR(&dst_id_len),
1220                              SILC_STR_UI_CHAR(&src_id_type),
1221                              SILC_STR_END);
1222   if (ret == -1) {
1223     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1224     return FALSE;
1225   }
1226
1227   if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1228       dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1229     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1230                     packet->src_id_len, packet->dst_id_len));
1231     return FALSE;
1232   }
1233
1234   ret = silc_buffer_unformat(buffer,
1235                              SILC_STR_ADVANCE,
1236                              SILC_STR_DATA(&packet->src_id, src_id_len),
1237                              SILC_STR_UI_CHAR(&dst_id_type),
1238                              SILC_STR_DATA(&packet->dst_id, dst_id_len),
1239                              SILC_STR_OFFSET(padlen),
1240                              SILC_STR_END);
1241   if (ret == -1) {
1242     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1243     return FALSE;
1244   }
1245
1246   if (src_id_type > SILC_ID_CHANNEL ||
1247       dst_id_type > SILC_ID_CHANNEL) {
1248     SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1249                     src_id_type, dst_id_type));
1250     return FALSE;
1251   }
1252
1253   packet->src_id_len = src_id_len;
1254   packet->dst_id_len = dst_id_len;
1255   packet->src_id_type = src_id_type;
1256   packet->dst_id_type = dst_id_type;
1257
1258   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1259                    silc_buffer_len(buffer)), buffer->head,
1260                    silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1261
1262   SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1263                   silc_get_packet_name(packet->type)));
1264
1265   return TRUE;
1266 }
1267
1268 /* Dispatch packet to application.  Called with stream->lock locked. */
1269
1270 static void silc_packet_dispatch(SilcPacket packet)
1271 {
1272   SilcPacketStream stream = packet->stream;
1273   SilcPacketProcess p;
1274   SilcBool default_sent = FALSE;
1275   SilcPacketType *pt;
1276
1277   /* Parse the packet */
1278   if (!silc_packet_parse(packet)) {
1279     silc_mutex_unlock(stream->lock);
1280     SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1281     silc_mutex_lock(stream->lock);
1282     silc_packet_free(packet);
1283     return;
1284   }
1285
1286   /* Dispatch packet to all packet processors that want it */
1287
1288   if (!stream->process) {
1289     /* Send to default processor as no others exist */
1290     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1291     silc_mutex_unlock(stream->lock);
1292     if (!stream->engine->callbacks->
1293         packet_receive(stream->engine, stream, packet,
1294                        stream->engine->callback_context,
1295                        stream->stream_context))
1296       silc_packet_free(packet);
1297     silc_mutex_lock(stream->lock);
1298     return;
1299   }
1300
1301   silc_dlist_start(stream->process);
1302   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1303
1304     /* If priority is 0 or less, we send to default processor first
1305        because default processor has 0 priority */
1306     if (!default_sent && p->priority <= 0) {
1307       SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1308       default_sent = TRUE;
1309       silc_mutex_unlock(stream->lock);
1310       if (stream->engine->callbacks->
1311           packet_receive(stream->engine, stream, packet,
1312                          stream->engine->callback_context,
1313                          stream->stream_context)) {
1314         silc_mutex_lock(stream->lock);
1315         return;
1316       }
1317       silc_mutex_lock(stream->lock);
1318     }
1319
1320     /* Send to processor */
1321     if (!p->types) {
1322       /* Send all packet types */
1323       SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1324       silc_mutex_unlock(stream->lock);
1325       if (p->callbacks->packet_receive(stream->engine, stream, packet,
1326                                        p->callback_context,
1327                                        stream->stream_context)) {
1328         silc_mutex_lock(stream->lock);
1329         return;
1330       }
1331       silc_mutex_lock(stream->lock);
1332     } else {
1333       /* Send specific types */
1334       for (pt = p->types; *pt; pt++) {
1335         if (*pt != packet->type)
1336           continue;
1337         SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1338         silc_mutex_unlock(stream->lock);
1339         if (p->callbacks->packet_receive(stream->engine, stream, packet,
1340                                          p->callback_context,
1341                                          stream->stream_context)) {
1342           silc_mutex_lock(stream->lock);
1343           return;
1344         }
1345         silc_mutex_lock(stream->lock);
1346         break;
1347       }
1348     }
1349   }
1350
1351   if (!default_sent) {
1352     /* Send to default processor as it has not been sent yet */
1353     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1354     silc_mutex_unlock(stream->lock);
1355     if (stream->engine->callbacks->
1356         packet_receive(stream->engine, stream, packet,
1357                        stream->engine->callback_context,
1358                        stream->stream_context)) {
1359       silc_mutex_lock(stream->lock);
1360       return;
1361     }
1362     silc_mutex_lock(stream->lock);
1363   }
1364
1365   /* If we got here, no one wanted the packet, so drop it */
1366   silc_packet_free(packet);
1367 }
1368
1369 /* Process incoming data and parse packets.  Called with stream->lock
1370    locked. */
1371
1372 static void silc_packet_read_process(SilcPacketStream stream)
1373 {
1374   SilcCipher cipher;
1375   SilcHmac hmac;
1376   SilcPacket packet;
1377   SilcUInt8 sid;
1378   SilcUInt16 packetlen;
1379   SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1380   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1381   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1382   SilcBool normal = TRUE;
1383   int ret;
1384
1385   /* Parse the packets from the data */
1386   while (silc_buffer_len(&stream->inbuf) > 0) {
1387     ivlen = psnlen = 0;
1388     cipher = stream->receive_key[0];
1389     hmac = stream->receive_hmac[0];
1390
1391     if (silc_buffer_len(&stream->inbuf) <
1392         (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1393          SILC_PACKET_MIN_HEADER_LEN)) {
1394       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1395       return;
1396     }
1397
1398     if (hmac)
1399       mac_len = silc_hmac_len(hmac);
1400     else
1401       mac_len = 0;
1402
1403     /* Decrypt first block of the packet to get the length field out */
1404     if (cipher) {
1405       block_len = silc_cipher_get_block_len(cipher);
1406
1407       if (stream->iv_included) {
1408         /* SID, IV and sequence number is included in the ciphertext */
1409         sid = (SilcUInt8)stream->inbuf.data[0];
1410         memcpy(iv, stream->inbuf.data + 1, block_len);
1411         ivlen = block_len + 1;
1412         psnlen = 4;
1413
1414         /* Check SID, and get correct decryption key */
1415         if (sid != stream->sid) {
1416           /* If SID is recent get the previous key and use it */
1417           if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1418               stream->receive_key[1] && !stream->receive_hmac[1]) {
1419             cipher = stream->receive_key[1];
1420             hmac = stream->receive_hmac[1];
1421           } else {
1422             /* The SID is unknown, drop rest of the data in buffer */
1423             SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1424                             sid, stream->sid));
1425             silc_mutex_unlock(stream->lock);
1426             SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1427             silc_mutex_lock(stream->lock);
1428             silc_buffer_reset(&stream->inbuf);
1429             return;
1430           }
1431         }
1432       } else {
1433         memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1434       }
1435
1436       silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1437                           block_len, iv);
1438
1439       header = tmp;
1440       if (stream->iv_included) {
1441         /* Take sequence number from packet */
1442         packet_seq = header;
1443         header += 4;
1444       }
1445     } else {
1446       block_len = SILC_PACKET_MIN_HEADER_LEN;
1447       header = stream->inbuf.data;
1448     }
1449
1450     /* Get packet length and full packet length with padding */
1451     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1452
1453     /* Sanity checks */
1454     if (packetlen < SILC_PACKET_MIN_LEN) {
1455       SILC_LOG_ERROR(("Received too short packet"));
1456       silc_mutex_unlock(stream->lock);
1457       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1458       silc_mutex_lock(stream->lock);
1459       memset(tmp, 0, sizeof(tmp));
1460       silc_buffer_reset(&stream->inbuf);
1461       return;
1462     }
1463
1464     if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1465       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1466                       "(%d bytes)",
1467                       paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1468       memset(tmp, 0, sizeof(tmp));
1469       return;
1470     }
1471
1472     /* Check MAC of the packet */
1473     if (!silc_packet_check_mac(hmac, stream->inbuf.data,
1474                                paddedlen + ivlen,
1475                                stream->inbuf.data + ivlen + paddedlen,
1476                                packet_seq, stream->receive_psn)) {
1477       silc_mutex_unlock(stream->lock);
1478       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1479       silc_mutex_lock(stream->lock);
1480       memset(tmp, 0, sizeof(tmp));
1481       silc_buffer_reset(&stream->inbuf);
1482       return;
1483     }
1484
1485     /* Get packet */
1486     packet = silc_packet_alloc(stream->engine);
1487     if (!packet) {
1488       silc_mutex_unlock(stream->lock);
1489       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1490       silc_mutex_lock(stream->lock);
1491       memset(tmp, 0, sizeof(tmp));
1492       silc_buffer_reset(&stream->inbuf);
1493       return;
1494     }
1495
1496     /* Allocate more space to packet buffer, if needed */
1497     if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1498       if (!silc_buffer_realloc(&packet->buffer,
1499                                silc_buffer_truelen(&packet->buffer) +
1500                                (paddedlen -
1501                                 silc_buffer_truelen(&packet->buffer)))) {
1502         silc_mutex_unlock(stream->lock);
1503         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1504         silc_mutex_lock(stream->lock);
1505         silc_packet_free(packet);
1506         memset(tmp, 0, sizeof(tmp));
1507         silc_buffer_reset(&stream->inbuf);
1508         return;
1509       }
1510     }
1511
1512     /* Parse packet header */
1513     packet->flags = (SilcPacketFlags)header[2];
1514     packet->type = (SilcPacketType)header[3];
1515
1516     if (stream->engine->local_is_router) {
1517       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1518           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1519         normal = FALSE;
1520       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1521                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1522                 stream->is_router == TRUE))
1523         normal = TRUE;
1524     } else {
1525       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1526           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1527         normal = FALSE;
1528       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1529         normal = TRUE;
1530     }
1531
1532     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1533                       stream->receive_psn, paddedlen + ivlen + mac_len),
1534                      stream->inbuf.data, paddedlen + ivlen + mac_len);
1535
1536     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1537     silc_buffer_pull_tail(&packet->buffer, paddedlen);
1538     silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1539     silc_buffer_pull(&packet->buffer, block_len - psnlen);
1540     silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1541                                       psnlen + (block_len - psnlen)),
1542                     paddedlen - ivlen - psnlen - (block_len - psnlen));
1543     if (cipher) {
1544       silc_cipher_set_iv(cipher, iv);
1545       ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1546                                 &packet->buffer, normal);
1547       if (ret < 0) {
1548         silc_mutex_unlock(stream->lock);
1549         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1550         silc_mutex_lock(stream->lock);
1551         silc_packet_free(packet);
1552         memset(tmp, 0, sizeof(tmp));
1553         return;
1554       }
1555
1556       stream->receive_psn++;
1557     }
1558     silc_buffer_push(&packet->buffer, block_len);
1559
1560     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1561     silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1562
1563     /* Dispatch the packet to application */
1564     packet->stream = stream;
1565     silc_packet_dispatch(packet);
1566   }
1567
1568   silc_buffer_reset(&stream->inbuf);
1569 }
1570
1571
1572 /****************************** Packet Waiting ******************************/
1573
1574 /* Packet wait receive callback */
1575 static SilcBool
1576 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1577                                 SilcPacketStream stream,
1578                                 SilcPacket packet,
1579                                 void *callback_context,
1580                                 void *stream_context);
1581
1582 /* Packet waiting callbacks */
1583 static SilcPacketCallbacks silc_packet_wait_cbs =
1584 {
1585   silc_packet_wait_packet_receive, NULL, NULL
1586 };
1587
1588 /* Packet waiting context */
1589 typedef struct {
1590   SilcMutex wait_lock;
1591   SilcCond wait_cond;
1592   SilcList packet_queue;
1593   unsigned int stopped     : 1;
1594 } *SilcPacketWait;
1595
1596 /* Packet wait receive callback */
1597
1598 static SilcBool
1599 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1600                                 SilcPacketStream stream,
1601                                 SilcPacket packet,
1602                                 void *callback_context,
1603                                 void *stream_context)
1604 {
1605   SilcPacketWait pw = callback_context;
1606
1607   /* Signal the waiting thread for a new packet */
1608   silc_mutex_lock(pw->wait_lock);
1609
1610   if (pw->stopped) {
1611     silc_mutex_unlock(pw->wait_lock);
1612     return FALSE;
1613   }
1614
1615   silc_list_add(pw->packet_queue, packet);
1616   silc_cond_broadcast(pw->wait_cond);
1617
1618   silc_mutex_unlock(pw->wait_lock);
1619
1620   return TRUE;
1621 }
1622
1623 /* Initialize packet waiting */
1624
1625 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1626 {
1627   SilcPacketWait pw;
1628   SilcBool ret;
1629   va_list ap;
1630
1631   pw = silc_calloc(1, sizeof(*pw));
1632   if (!pw)
1633     return NULL;
1634
1635   /* Allocate mutex and conditional variable */
1636   if (!silc_mutex_alloc(&pw->wait_lock)) {
1637     silc_free(pw);
1638     return NULL;
1639   }
1640   if (!silc_cond_alloc(&pw->wait_cond)) {
1641     silc_mutex_free(pw->wait_lock);
1642     silc_free(pw);
1643     return NULL;
1644   }
1645
1646   /* Link to the packet stream for the requested packet types */
1647   va_start(ap, stream);
1648   ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
1649                                    10000000, ap);
1650   va_end(ap);
1651   if (!ret) {
1652     silc_cond_free(pw->wait_cond);
1653     silc_mutex_free(pw->wait_lock);
1654     silc_free(pw);
1655     return NULL;
1656   }
1657
1658   /* Initialize packet queue */
1659   silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
1660
1661   return (void *)pw;
1662 }
1663
1664 /* Uninitialize packet waiting */
1665
1666 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
1667 {
1668   SilcPacketWait pw = waiter;
1669   SilcPacket packet;
1670
1671   /* Signal any threads to stop waiting */
1672   silc_mutex_lock(pw->wait_lock);
1673   pw->stopped = TRUE;
1674   silc_cond_broadcast(pw->wait_cond);
1675   silc_mutex_unlock(pw->wait_lock);
1676
1677   /* Re-acquire lock and free resources */
1678   silc_mutex_lock(pw->wait_lock);
1679   silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
1680
1681   /* Free any remaining packets */
1682   silc_list_start(pw->packet_queue);
1683   while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
1684     silc_packet_free(packet);
1685
1686   silc_mutex_unlock(pw->wait_lock);
1687   silc_cond_free(pw->wait_cond);
1688   silc_mutex_free(pw->wait_lock);
1689   silc_free(pw);
1690 }
1691
1692 /* Blocks thread until a packet has been received. */
1693
1694 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
1695 {
1696   SilcPacketWait pw = waiter;
1697   SilcBool ret = FALSE;
1698
1699   silc_mutex_lock(pw->wait_lock);
1700
1701   /* Wait here until packet has arrived */
1702   while (silc_list_count(pw->packet_queue) == 0) {
1703     if (pw->stopped) {
1704       silc_mutex_unlock(pw->wait_lock);
1705       return -1;
1706     }
1707     ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
1708   }
1709
1710   /* Return packet */
1711   silc_list_start(pw->packet_queue);
1712   *return_packet = silc_list_get(pw->packet_queue);
1713   silc_list_del(pw->packet_queue, *return_packet);
1714
1715   silc_mutex_unlock(pw->wait_lock);
1716
1717   return ret == TRUE ? 1 : 0;
1718 }