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