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