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