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