070662f290503847125c13c4ddd06995c72ab4bf
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2005 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /*
20  * Created: Fri Jul 25 18:52:14 1997
21  */
22 /* $Id$ */
23
24 #include "silcincludes.h"
25
26 /* Packet engine */
27 struct SilcPacketEngineStruct {
28   SilcSchedule schedule;                 /* Application's scheduler */
29   SilcRng rng;                           /* RNG for engine */
30   SilcPacketCallbacks *callbacks;        /* Packet callbacks */
31   void *callback_context;                /* Context for callbacks */
32   SilcDList streams;                     /* All streams in engine */
33   SilcList packet_pool;                  /* Free list for received packets */
34   SilcMutex lock;                        /* Engine lock */
35   bool local_is_router;
36 };
37
38 /* Packet stream */
39 struct SilcPacketStreamStruct {
40   SilcPacketEngine engine;               /* Packet engine */
41   SilcStream stream;                     /* Underlaying stream */
42   SilcHashTable streamers;               /* Valid if streamers exist */
43   void *app_context;                     /* Applicationn context */
44   SilcPacketCallbacks *callbacks;        /* Callbacks or NULL */
45   void *callback_context;
46   SilcBufferStruct inbuf;                /* In buffer */
47   SilcBufferStruct outbuf;               /* Out buffer */
48   SilcUInt32 send_psn;                   /* Sending sequence */
49   SilcCipher send_key;                   /* Sending key */
50   SilcHmac send_hmac;                    /* Sending HMAC */
51   SilcUInt32 receive_psn;                /* Receiving sequence */
52   SilcCipher receive_key;                /* Receiving key */
53   SilcHmac receive_hmac;                 /* Receiving HMAC */
54   unsigned char *src_id;                 /* Source ID */
55   unsigned char *dst_id;                 /* Destination ID */
56   unsigned int src_id_len  : 6;
57   unsigned int src_id_type : 2;
58   unsigned int dst_id_len  : 6;
59   unsigned int dst_id_type : 2;
60   SilcUInt8 refcnt;                      /* Reference counter */
61 };
62
63 /* Initial size of stream buffers */
64 #define SILC_PACKET_DEFAULT_SIZE  1024
65
66 /* Header length without source and destination ID's. */
67 #define SILC_PACKET_HEADER_LEN 10
68
69 /* Minimum length of SILC Packet Header. This much is decrypted always
70    when packet is received to be able to get all the relevant data out
71    from the header. */
72 #define SILC_PACKET_MIN_HEADER_LEN 16
73
74 /* Maximum padding length */
75 #define SILC_PACKET_MAX_PADLEN 128
76
77 /* Default padding length */
78 #define SILC_PACKET_DEFAULT_PADLEN 16
79
80 /* Minimum packet length */
81 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
82
83
84 /* Macros */
85
86 /* Returns true length of the packet. */
87 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
88 do {                                                                     \
89   SILC_GET16_MSB((__ret_truelen), (__packetdata));                       \
90   (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4];    \
91 } while(0)
92
93 /* Calculates the data length with given header length.  This macro
94    can be used to check whether the data_len with header_len exceeds
95    SILC_PACKET_MAX_LEN.  If it does, this returns the new data_len
96    so that the SILC_PACKET_MAX_LEN is not exceeded.  If the data_len
97    plus header_len fits SILC_PACKET_MAX_LEN the returned data length
98    is the data_len given as argument. */
99 #define SILC_PACKET_DATALEN(data_len, header_len)                         \
100   ((data_len + header_len) > SILC_PACKET_MAX_LEN ?                        \
101    data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
102
103 /* Calculates the length of the padding in the packet. */
104 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen)               \
105 do {                                                                        \
106   __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) %                  \
107               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN));  \
108   if (__padlen < 8)                                                         \
109     __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
110 } while(0)
111
112 /* Returns the length of the padding up to the maximum length, which
113    is 128 bytes.*/
114 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen)          \
115 do {                                                                       \
116   __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) %                     \
117               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
118 } while(0)
119
120 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
121                                   void *context);
122
123 /* Receive packet callback */
124 #define SILC_PACKET_CALLBACK_PACKET(s, p)                               \
125 do {                                                                    \
126   if ((s)->callbacks && (s)->callbacks->packet_receive)                 \
127     (s)->callbacks->packet_receive((s)->engine, s, p,                   \
128                                    (s)->callback_context,               \
129                                    (s)->app_context);                   \
130   else                                                                  \
131     (s)->engine->callbacks->packet_receive((s)->engine, s, p,           \
132                                            (s)->callback_context,       \
133                                            (s)->app_context);           \
134 } while(0)
135
136 /* EOS callback */
137 #define SILC_PACKET_CALLBACK_EOS(s)                                     \
138 do {                                                                    \
139   if ((s)->callbacks && (s)->callbacks->eos)                            \
140     (s)->callbacks->eos((s)->engine, stream, (s)->callback_context,     \
141                         (s)->app_context);                              \
142   else                                                                  \
143     (s)->engine->callbacks->eos((s)->engine, s,                         \
144                                 (s)->callback_context,                  \
145                                 (s)->app_context);                      \
146 } while(0)
147
148 /* Error callback */
149 #define SILC_PACKET_CALLBACK_ERROR(s, err)                              \
150 do {                                                                    \
151   if ((s)->callbacks && (s)->callbacks->error)                          \
152     (s)->callbacks->error((s)->engine, s, err, (s)->callback_context,   \
153                           (s)->app_context);                            \
154   else                                                                  \
155     (s)->engine->callbacks->error((s)->engine, s, err,                  \
156                                   (s)->callback_context,                \
157                                   (s)->app_context);                    \
158 } while(0)
159
160 static SilcPacket silc_packet_alloc(SilcPacketEngine engine);
161 static void silc_packet_read_process(SilcPacketStream stream);
162
163
164 /* Allocate new packet engine */
165
166 SilcPacketEngine
167 silc_packet_engine_start(SilcSchedule schedule, SilcRng rng, bool router,
168                          SilcPacketCallbacks *callbacks,
169                          void *callback_context)
170 {
171   SilcPacketEngine engine;
172   SilcPacket packet;
173   int i;
174   void *tmp;
175
176   SILC_LOG_DEBUG(("Starting new packet engine"));
177
178   if (!schedule || !callbacks)
179     return NULL;
180   if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
181     return NULL;
182
183   engine = silc_calloc(1, sizeof(*engine));
184   if (!engine)
185     return NULL;
186
187   engine->rng = rng;
188   engine->local_is_router = router;
189   engine->callbacks = callbacks;
190   engine->callback_context = callback_context;
191   engine->streams = silc_dlist_init();
192   silc_mutex_alloc(&engine->lock);
193
194   /* Allocate packet free list */
195   silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
196   for (i = 0; i < 5; i++) {
197     packet = silc_calloc(1, sizeof(*packet));
198     if (!packet)
199       return NULL;
200
201     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
202     if (!tmp)
203       return NULL;
204     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
205
206     silc_list_add(engine->packet_pool, packet);
207   }
208   silc_list_start(engine->packet_pool);
209
210   return engine;
211 }
212
213 /* Stop packet engine */
214
215 void silc_packet_engine_stop(SilcPacketEngine engine)
216 {
217
218   SILC_LOG_DEBUG(("Stopping packet engine"));
219
220   if (!engine)
221     return;
222
223   /* XXX */
224
225   silc_free(engine);
226 }
227
228 /* Create new packet stream */
229
230 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
231                                            SilcStream stream)
232 {
233   SilcPacketStream ps;
234   void *tmp;
235
236   SILC_LOG_DEBUG(("Creating new packet stream"));
237
238   if (!engine || !stream)
239     return NULL;
240
241   ps = silc_calloc(1, sizeof(*ps));
242   if (!ps)
243     return NULL;
244
245   ps->engine = engine;
246   ps->stream = stream;
247   ps->refcnt++;
248
249   /* Allocate buffers */
250   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
251   if (!tmp)
252     return NULL;
253   silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
254   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
255   if (!tmp)
256     return NULL;
257   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
258
259   /* Set IO notifier callback */
260   silc_stream_set_notifier(ps->stream, silc_packet_stream_io, ps);
261
262   /* Add to engine */
263   silc_mutex_lock(engine->lock);
264   silc_dlist_add(engine->streams, ps);
265   silc_mutex_unlock(engine->lock);
266
267   return ps;
268 }
269
270 /* Destroy packet stream */
271
272 void silc_packet_stream_destroy(SilcPacketStream stream)
273 {
274   if (!stream)
275     return;
276   if (stream->refcnt > 1)
277     return;
278
279   SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
280
281   /* Delete from engine */
282   silc_mutex_lock(stream->engine->lock);
283   silc_dlist_del(stream->engine->streams, stream);
284   silc_mutex_unlock(stream->engine->lock);
285
286   /* Clear and free buffers */
287   silc_buffer_clear(&stream->inbuf);
288   silc_buffer_clear(&stream->outbuf);
289   silc_free(silc_buffer_steal(&stream->inbuf, NULL));
290   silc_free(silc_buffer_steal(&stream->outbuf, NULL));
291
292   /* XXX */
293
294   silc_free(stream);
295 }
296
297
298 /* Set new packet callbacks for stream */
299
300 void silc_packet_stream_callbacks(SilcPacketStream stream,
301                                   SilcPacketCallbacks *callbacks,
302                                   void *callback_context)
303 {
304   stream->callbacks = callbacks;
305   stream->callback_context = callback_context;
306 }
307
308 /* Reference packet stream */
309
310 void silc_packet_stream_ref(SilcPacketStream stream)
311 {
312   stream->refcnt++;
313 }
314
315 /* Unreference packet stream */
316
317 void silc_packet_stream_unref(SilcPacketStream stream)
318 {
319   stream->refcnt--;
320   if (stream->refcnt == 0)
321     silc_packet_stream_destroy(stream);
322 }
323
324 /* Set application context for packet stream */
325
326 void silc_packet_set_context(SilcPacketStream stream, void *app_context)
327 {
328   stream->app_context = app_context;
329 }
330
331 /* Return application context from packet stream */
332
333 void *silc_packet_get_context(SilcPacketStream stream)
334 {
335   return stream->app_context;
336 }
337
338 /* Set ciphers for packet stream */
339
340 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
341                              SilcCipher receive)
342 {
343   SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
344   stream->send_key = send;
345   stream->receive_key = receive;
346 }
347
348 /* Return current ciphers from packet stream */
349
350 bool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
351                              SilcCipher *receive)
352 {
353   if (!stream->send_key && !stream->receive_key)
354     return FALSE;
355
356   if (send)
357     *send = stream->send_key;
358   if (receive)
359     *receive = stream->receive_key;
360
361   return TRUE;
362 }
363
364 /* Set HMACs for packet stream */
365
366 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
367                            SilcHmac receive)
368 {
369   SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
370   stream->send_hmac = send;
371   stream->receive_hmac = receive;
372 }
373
374 /* Return current HMACs from packet stream */
375
376 bool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
377                            SilcHmac *receive)
378 {
379   if (!stream->send_hmac && !stream->receive_hmac)
380     return FALSE;
381
382   if (send)
383     *send = stream->send_hmac;
384   if (receive)
385     *receive = stream->receive_hmac;
386
387   return TRUE;
388 }
389
390 /* Set SILC IDs to packet stream */
391
392 bool silc_packet_set_ids(SilcPacketStream stream,
393                         SilcIdType src_id_type, const void *src_id,
394                          SilcIdType dst_id_type, const void *dst_id)
395 {
396   SilcUInt32 len;
397
398   if (!src_id && !dst_id)
399     return FALSE;
400
401   SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
402
403   if (src_id) {
404     silc_free(stream->src_id);
405     stream->src_id = silc_id_id2str(src_id, src_id_type, &len);
406     if (!stream->src_id)
407       return FALSE;
408     stream->src_id_type = src_id_type;
409     stream->src_id_len = len;
410   }
411
412   if (dst_id) {
413     silc_free(stream->dst_id);
414     stream->dst_id = silc_id_id2str(dst_id, dst_id_type, &len);
415     if (!stream->dst_id)
416       return FALSE;
417     stream->dst_id_type = dst_id_type;
418     stream->dst_id_len = len;
419   }
420
421   return TRUE;
422 }
423
424 /* Prepare outgoing data buffer for packet sending.  Returns the
425    pointer to that buffer into the `packet'. */
426
427 static bool silc_packet_send_prepare(SilcPacketStream stream,
428                                      SilcUInt32 totlen,
429                                                           SilcHmac hmac,
430                                      const SilcBuffer packet)
431 {
432   unsigned char *oldptr;
433   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
434
435   totlen += mac_len;
436
437   /* If head is empty, the buffer is free for our use (no pending data) */
438   if (!silc_buffer_headlen(&stream->outbuf))
439     silc_buffer_reset(&stream->outbuf);
440
441   /* Allocate more space if needed */
442   if (silc_buffer_taillen(&stream->outbuf) < totlen) {
443     if (!silc_buffer_realloc(&stream->outbuf,
444                              silc_buffer_truelen(&stream->outbuf) + totlen))
445       return FALSE;
446   }
447
448   /* Pull data area for the new packet, and return pointer to the start of
449      the data area and save the pointer in to the `packet'.  MAC is pulled
450      later after it's computed. */
451   oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen - mac_len);
452   silc_buffer_set(packet, oldptr, totlen);
453
454   return TRUE;
455 }
456
457
458 /* Internal routine to send packet */
459
460 static bool silc_packet_send_raw(SilcPacketStream stream,
461                                  SilcPacketType type,
462                                  SilcPacketFlags flags,
463                                  SilcIdType src_id_type,
464                                  unsigned char *src_id,
465                                  SilcUInt32 src_id_len,
466                                  SilcIdType dst_id_type,
467                                  unsigned char *dst_id,
468                                  SilcUInt32 dst_id_len,
469                                  const unsigned char *data,
470                                  SilcUInt32 data_len,
471                                  SilcCipher cipher,
472                                  SilcHmac hmac)
473 {
474   unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
475   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
476   int i, enclen, truelen, padlen;
477   const SilcBufferStruct packet;
478
479   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
480                   "data len %d", silc_get_packet_name(type), stream->send_psn,
481                   flags, src_id_type, dst_id_type, data_len));
482
483   /* Get the true length of the packet. This is saved as payload length
484      into the packet header.  This does not include the length of the
485      padding. */
486   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
487                                             src_id_len + dst_id_len));
488   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
489                       src_id_len + dst_id_len);
490
491   /* We automatically figure out the packet structure from the packet
492      type and flags, and calculate correct length.  Private messages with
493      private keys and channel messages are special packets as their
494      payload is encrypted already. */
495   if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
496        flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
497       type == SILC_PACKET_CHANNEL_MESSAGE) {
498
499     /* Padding is calculated from header + IDs */
500     SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
501                         src_id_len +
502                         dst_id_len), block_len, padlen);
503
504     /* Length to encrypt, header + IDs + padding. */
505     enclen = SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len + padlen;
506   } else {
507
508     /* Padding is calculated from true length of the packet */
509     if (flags & SILC_PACKET_FLAG_LONG_PAD)
510       SILC_PACKET_PADLEN_MAX(truelen, block_len, padlen);
511     else
512       SILC_PACKET_PADLEN(truelen, block_len, padlen);
513   }
514
515   /* Remove implementation specific flags */
516   flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
517
518   /* Get packet pointer from the outgoing buffer */
519   if (!silc_packet_send_prepare(stream, truelen + padlen, hmac, &packet))
520     return FALSE;
521
522   /* Get random padding */
523   if (stream->engine->rng)
524     for (i = 0; i < padlen; i++) tmppad[i] =
525                                            silc_rng_get_byte_fast(stream->engine->rng);
526   else
527     for (i = 0; i < padlen; i++) tmppad[i] =
528                                            silc_rng_global_get_byte_fast();
529
530   /* Create the packet.  This creates the SILC header, adds padding, and
531      the actual packet data. */
532   i = silc_buffer_format(&packet,
533                          SILC_STR_UI_SHORT(truelen),
534                          SILC_STR_UI_CHAR(flags),
535                          SILC_STR_UI_CHAR(type),
536                          SILC_STR_UI_CHAR(padlen),
537                          SILC_STR_UI_CHAR(0),
538                          SILC_STR_UI_CHAR(src_id_len),
539                          SILC_STR_UI_CHAR(dst_id_len),
540                          SILC_STR_UI_CHAR(src_id_type),
541                          SILC_STR_UI_XNSTRING(src_id, src_id_len),
542                          SILC_STR_UI_CHAR(dst_id_type),
543                          SILC_STR_UI_XNSTRING(dst_id, dst_id_len),
544                          SILC_STR_UI_XNSTRING(tmppad, padlen),
545                          SILC_STR_UI_XNSTRING(data, data_len),
546                          SILC_STR_END);
547   if (i < 0)
548     return FALSE;
549
550   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
551                    packet.data, silc_buffer_len(&packet));
552
553   /* Encrypt the packet */
554   if (cipher)
555     if (!silc_cipher_encrypt(cipher, packet.data, packet.data, enclen, NULL)) {
556       SILC_LOG_ERROR(("Packet encryption failed"));
557       return FALSE;
558     }
559
560   /* Compute HMAC */
561   if (hmac) {
562     unsigned char mac[32], psn[4];
563     SilcUInt32 mac_len;
564
565     /* MAC is computed from the entire encrypted packet data, and put
566        to the end of the packet. */
567     silc_hmac_init(hmac);
568     SILC_PUT32_MSB(stream->send_psn, psn);
569     silc_hmac_update(hmac, psn, 4);
570     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
571     silc_hmac_final(hmac, packet.tail, &mac_len);
572     silc_buffer_pull_tail(&packet, mac_len);
573     stream->send_psn++;
574   }
575
576   /* Write the packet to the stream */
577   while (silc_buffer_len(&packet) > 0) {
578     i = silc_stream_write(stream->stream, packet.data,
579                           silc_buffer_len(&packet));
580     if (i == 0) {
581       /* EOS */
582       SILC_PACKET_CALLBACK_EOS(stream);
583       silc_buffer_reset(&stream->outbuf);
584       return FALSE;
585     }
586
587     if (i == -2) {
588       /* Error */
589       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_WRITE);
590       silc_buffer_reset(&stream->outbuf);
591       return FALSE;
592     }
593
594     if (i == -1) {
595       /* Cannot write now, write later. */
596       silc_buffer_pull(&packet, silc_buffer_len(&packet));
597       return TRUE;
598     }
599
600     /* Wrote data */
601     silc_buffer_pull(&packet, i);
602   }
603
604   return TRUE;
605 }
606
607 /* Sends a packet */
608
609 bool silc_packet_send(SilcPacketStream stream,
610                       SilcPacketType type, SilcPacketFlags flags,
611                       const unsigned char *data, SilcUInt32 data_len)
612 {
613   return silc_packet_send_raw(stream, type, flags,
614                               stream->src_id_type,
615                               stream->src_id,
616                               stream->src_id_len,
617                               stream->dst_id_type,
618                               stream->dst_id,
619                               stream->dst_id_len,
620                               data, data_len,
621                               stream->send_key,
622                               stream->send_hmac);
623 }
624
625 /* Sends a packet, extended routine */
626
627 bool silc_packet_send_ext(SilcPacketStream stream,
628                           SilcPacketType type, SilcPacketFlags flags,
629                           SilcIdType src_id_type, void *src_id,
630                           SilcIdType dst_id_type, void *dst_id,
631                           const unsigned char *data, SilcUInt32 data_len,
632                           SilcCipher cipher, SilcHmac hmac)
633 {
634   bool ret;
635   unsigned char *src_id_data = NULL, *dst_id_data = NULL;
636   SilcUInt32 src_id_len, dst_id_len;
637
638   /* XXX non-allocating id2str needed! */
639
640   if (src_id)
641     src_id_data = silc_id_id2str(src_id, src_id_type, &src_id_len);
642   if (src_id)
643     dst_id_data = silc_id_id2str(dst_id, dst_id_type, &dst_id_len);
644
645   ret = silc_packet_send_raw(stream, type, flags,
646                              src_id_type,
647                              src_id_data,
648                              src_id_len,
649                              dst_id_type,
650                              dst_id_data,
651                              dst_id_len,
652                              data, data_len,
653                              cipher,
654                              hmac);
655
656   silc_free(src_id_data);
657   silc_free(dst_id_data);
658
659   return ret;
660 }
661
662 /* Our stream IO notifier callback. */
663
664 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
665                                   void *context)
666 {
667   SilcPacketStream ps = context;
668   int ret;
669
670   switch (status) {
671
672   case SILC_STREAM_CAN_WRITE:
673     if (!silc_buffer_headlen(&ps->outbuf))
674       return;
675
676     SILC_LOG_DEBUG(("Writing pending data to stream"));
677
678     /* Write pending data to stream */
679     silc_buffer_push(&ps->outbuf, silc_buffer_headlen(&ps->outbuf));
680     while (silc_buffer_len(&ps->outbuf) > 0) {
681       ret = silc_stream_write(ps->stream, ps->outbuf.data,
682                               silc_buffer_len(&ps->outbuf));
683       if (ret == 0) {
684         /* EOS */
685         SILC_PACKET_CALLBACK_EOS(ps);
686         silc_buffer_reset(&ps->outbuf);
687         return;
688       }
689
690       if (ret == -2) {
691         /* Error */
692         SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
693         silc_buffer_reset(&ps->outbuf);
694         return;
695       }
696
697       if (ret == -1) {
698         /* Cannot write now, write later. */
699         silc_buffer_pull(&ps->outbuf, silc_buffer_len(&ps->outbuf));
700         return;
701       }
702
703       /* Wrote data */
704       silc_buffer_pull(&ps->outbuf, ret);
705     }
706
707     break;
708
709   case SILC_STREAM_CAN_READ:
710     SILC_LOG_DEBUG(("Reading data from stream"));
711
712     /* Make sure we have fair amount of free space in inbuf */
713     if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
714       if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
715                                SILC_PACKET_DEFAULT_SIZE * 2))
716         return;
717
718     /* Read data from stream */
719     ret = silc_stream_read(ps->stream, &ps->inbuf.tail,
720                            silc_buffer_taillen(&ps->inbuf));
721
722     if (ret == 0) {
723       /* EOS */
724       SILC_PACKET_CALLBACK_EOS(ps);
725       silc_buffer_reset(&ps->inbuf);
726       return;
727     }
728
729     if (ret == -2) {
730       /* Error */
731       SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
732       silc_buffer_reset(&ps->inbuf);
733       return;
734     }
735
736     if (ret == -1) {
737       /* Cannot read now, do it later. */
738       silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
739       return;
740     }
741
742     /* Read some data */
743     silc_buffer_pull_tail(&ps->inbuf, ret);
744
745     /* Now process the data */
746     silc_packet_read_process(ps);
747
748     break;
749
750   default:
751     break;
752   }
753 }
754
755 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
756
757 static bool silc_packet_check_mac(SilcHmac hmac,
758                                   const unsigned char *data,
759                                   SilcUInt32 data_len,
760                                   const unsigned char *packet_mac,
761                                   SilcUInt32 sequence)
762 {
763   /* Check MAC */
764   if (hmac) {
765     unsigned char mac[32], psn[4];
766     SilcUInt32 mac_len;
767
768     SILC_LOG_DEBUG(("Verifying MAC"));
769
770     /* Compute HMAC of packet */
771     silc_hmac_init(hmac);
772     SILC_PUT32_MSB(sequence, psn);
773     silc_hmac_update(hmac, psn, 4);
774     silc_hmac_update(hmac, data, data_len);
775     silc_hmac_final(hmac, mac, &mac_len);
776
777     /* Compare the MAC's */
778     if (memcmp(packet_mac, mac, mac_len)) {
779       SILC_LOG_DEBUG(("MAC failed"));
780       return FALSE;
781     }
782
783     SILC_LOG_DEBUG(("MAC is Ok"));
784   }
785
786   return TRUE;
787 }
788
789 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
790    Return 0 when packet is normal and 1 when it it special, -1 on error. */
791
792 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
793                                SilcUInt32 sequence, SilcBuffer buffer,
794                                bool normal)
795 {
796   if (normal == TRUE) {
797     if (cipher) {
798       /* Decrypt rest of the packet */
799       SILC_LOG_DEBUG(("Decrypting the packet"));
800       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
801                                silc_buffer_len(buffer), NULL))
802         return -1;
803     }
804     return 0;
805
806   } else {
807     /* Decrypt rest of the header plus padding */
808     if (cipher) {
809       SilcUInt16 len;
810       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
811
812       SILC_LOG_DEBUG(("Decrypting the header"));
813
814       /* Padding length + src id len + dst id len + header length - 16
815          bytes already decrypted, gives the rest of the encrypted packet */
816       silc_buffer_push(buffer, block_len);
817       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
818               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
819              block_len);
820       silc_buffer_pull(buffer, block_len);
821
822       if (len > silc_buffer_len(buffer)) {
823         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
824                         "packet dropped"));
825         return -1;
826       }
827       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
828                                len, NULL))
829         return -1;
830     }
831
832     return 1;
833   }
834 }
835
836 /* Parses the packet. This is called when a whole packet is ready to be
837    parsed. The buffer sent must be already decrypted before calling this
838    function. */
839
840 static bool silc_packet_parse(SilcPacketStream stream, SilcPacket packet)
841 {
842   SilcBuffer buffer = &packet->buffer;
843   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
844   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
845   int len, ret;
846
847   SILC_LOG_DEBUG(("Parsing incoming packet"));
848
849   /* Parse the buffer.  This parses the SILC header of the packet. */
850   len = silc_buffer_unformat(buffer,
851                              SILC_STR_OFFSET(6),
852                              SILC_STR_UI_CHAR(&src_id_len),
853                              SILC_STR_UI_CHAR(&dst_id_len),
854                              SILC_STR_UI_CHAR(&src_id_type),
855                              SILC_STR_END);
856   if (len == -1) {
857     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
858     return FALSE;
859   }
860
861   if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
862       dst_id_len > SILC_PACKET_MAX_ID_LEN) {
863     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
864                     packet->src_id_len, packet->dst_id_len));
865     return FALSE;
866   }
867
868   ret = silc_buffer_unformat(buffer,
869                              SILC_STR_OFFSET(len),
870                              SILC_STR_UI_XNSTRING(&packet->src_id,
871                                                   src_id_len),
872                              SILC_STR_UI_CHAR(&dst_id_type),
873                              SILC_STR_UI_XNSTRING(&packet->dst_id,
874                                                   dst_id_len),
875                              SILC_STR_OFFSET(padlen),
876                              SILC_STR_END);
877   if (ret == -1) {
878     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
879     return FALSE;
880   }
881
882   if (src_id_type > SILC_ID_CHANNEL ||
883       dst_id_type > SILC_ID_CHANNEL) {
884     SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
885                     src_id_type, dst_id_type));
886     return FALSE;
887   }
888
889   packet->src_id_len = src_id_len;
890   packet->dst_id_len = dst_id_len;
891   packet->src_id_type = src_id_type;
892   packet->dst_id_type = dst_id_type;
893
894   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_len(buffer)),
895                    buffer->data, silc_buffer_len(buffer));
896
897   /* Pull SILC header and padding from packet to get the data payload */
898   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
899                    packet->src_id_len + packet->dst_id_len + padlen);
900
901   SILC_LOG_DEBUG(("Incoming packet type: %d", packet->type));
902
903   return TRUE;
904 }
905
906 /* Process incoming data and parse packets. */
907
908 static void silc_packet_read_process(SilcPacketStream stream)
909 {
910   SilcPacket packet;
911   SilcUInt16 packetlen;
912   SilcUInt32 paddedlen, mac_len, block_len;
913   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
914   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
915   bool normal = TRUE;
916   int ret;
917
918   /* Parse the packets from the data */
919   while (silc_buffer_len(&stream->inbuf) > 0) {
920
921     if (silc_buffer_len(&stream->inbuf) < SILC_PACKET_MIN_HEADER_LEN) {
922       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
923       return;
924     }
925
926     if (stream->receive_hmac)
927       mac_len = silc_hmac_len(stream->receive_hmac);
928     else
929       mac_len = 0;
930
931     /* Decrypt first block of the packet to get the length field out */
932     if (stream->receive_key) {
933       block_len = silc_cipher_get_block_len(stream->receive_key);
934       memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
935       silc_cipher_decrypt(stream->receive_key, stream->inbuf.data,
936                           tmp, block_len, iv);
937       header = tmp;
938     } else {
939       block_len = SILC_PACKET_MIN_HEADER_LEN;
940       header = stream->inbuf.data;
941     }
942
943     /* Get packet length and full packet length with padding */
944     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
945
946     /* Sanity checks */
947     if (packetlen < SILC_PACKET_MIN_LEN) {
948       SILC_LOG_ERROR(("Received too short packet"));
949       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
950       memset(tmp, 0, sizeof(tmp));
951       silc_buffer_reset(&stream->inbuf);
952       return;
953     }
954
955     if (silc_buffer_len(&stream->inbuf) < paddedlen + mac_len) {
956       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
957                       "(%d bytes)",
958                       paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
959       memset(tmp, 0, sizeof(tmp));
960 /*      silc_buffer_reset(&stream->inbuf); */
961       return;
962     }
963
964     /* Check MAC of the packet */
965     if (!silc_packet_check_mac(stream->receive_hmac, stream->inbuf.data,
966                                paddedlen, stream->inbuf.data + paddedlen,
967                                stream->receive_psn)) {
968       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
969       memset(tmp, 0, sizeof(tmp));
970       silc_buffer_reset(&stream->inbuf);
971       return;
972     }
973
974     /* Get packet */
975     packet = silc_packet_alloc(stream->engine);
976     if (!packet) {
977       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
978       memset(tmp, 0, sizeof(tmp));
979       silc_buffer_reset(&stream->inbuf);
980       return;
981     }
982
983     /* Allocate more space to packet buffer, if needed */
984     if (silc_buffer_len(&packet->buffer) < paddedlen) {
985       if (!silc_buffer_realloc(&packet->buffer,
986                                silc_buffer_truelen(&packet->buffer) +
987                                (paddedlen -
988                                 silc_buffer_truelen(&packet->buffer)))) {
989         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
990         memset(tmp, 0, sizeof(tmp));
991       silc_buffer_reset(&stream->inbuf);
992         return;
993       }
994     }
995
996     /* Parse packet header */
997     packet->flags = (SilcPacketFlags)header[2];
998     packet->type = (SilcPacketType)header[3];
999
1000     if (stream->engine->local_is_router) {
1001       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1002           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1003         normal = FALSE;
1004       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1005                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1006                 stream->engine->local_is_router == TRUE))
1007         normal = TRUE;
1008     } else {
1009       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1010           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1011         normal = FALSE;
1012       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1013         normal = TRUE;
1014     }
1015
1016     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1017                       stream->receive_psn, paddedlen + mac_len),
1018                      stream->inbuf.data, paddedlen + mac_len);
1019
1020     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1021     silc_buffer_put(&packet->buffer, header, block_len);
1022     silc_buffer_pull(&packet->buffer, block_len);
1023     silc_buffer_put(&packet->buffer, stream->inbuf.data + block_len,
1024                     paddedlen - block_len);
1025     if (stream->receive_key) {
1026       silc_cipher_set_iv(stream->receive_key, iv);
1027       ret = silc_packet_decrypt(stream->receive_key, stream->receive_hmac,
1028                                 stream->receive_psn, &packet->buffer, normal);
1029       if (ret < 0) {
1030         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1031         memset(tmp, 0, sizeof(tmp));
1032         return;
1033       }
1034
1035       stream->receive_psn++;
1036     }
1037     silc_buffer_push(&packet->buffer, block_len);
1038
1039     /* Parse the packet */
1040     if (!silc_packet_parse(stream, packet)) {
1041       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1042       memset(tmp, 0, sizeof(tmp));
1043       return;
1044     }
1045
1046     /* Send the packet to application */
1047     SILC_PACKET_CALLBACK_PACKET(stream, packet);
1048
1049     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1050     silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1051   }
1052
1053   SILC_LOG_DEBUG(("Resetting inbound buffer"));
1054   silc_buffer_reset(&stream->inbuf);
1055 }
1056
1057 /* Allocate packet */
1058
1059 SilcPacket silc_packet_alloc(SilcPacketEngine engine)
1060 {
1061   SilcPacket packet;
1062
1063   SILC_LOG_DEBUG(("Packet pool count %d",
1064                   silc_list_count(engine->packet_pool)));
1065
1066   silc_mutex_lock(engine->lock);
1067
1068   /* Get packet from freelist or allocate new one. */
1069   packet = silc_list_get(engine->packet_pool);
1070   if (!packet) {
1071     silc_mutex_unlock(engine->lock);
1072     packet = silc_calloc(1, sizeof(*packet));
1073     if (!packet)
1074       return NULL;
1075     SILC_LOG_DEBUG(("Allocating new packet %p", packet));
1076     return packet;
1077   }
1078
1079   SILC_LOG_DEBUG(("Get packet %p", packet));
1080
1081   /* Delete from freelist */
1082   silc_list_del(engine->packet_pool, packet);
1083
1084   silc_mutex_unlock(engine->lock);
1085
1086   return packet;
1087 }
1088
1089 /* Free packet */
1090
1091 void silc_packet_free(SilcPacketEngine engine, SilcPacket packet)
1092 {
1093   SILC_LOG_DEBUG(("Freeing packet %p", packet));
1094
1095   silc_buffer_reset(&packet->buffer);
1096
1097   /* Put the packet back to freelist */
1098   silc_mutex_lock(engine->lock);
1099   silc_list_add(engine->packet_pool, packet);
1100   silc_mutex_unlock(engine->lock);
1101 }
1102
1103 /* Creates streamer */
1104
1105 SilcStream silc_packet_streamer_create(SilcPacketStream stream,
1106                                        SilcPacketType packet_type,
1107                                        SilcPacketFlags packet_flags)
1108 {
1109   /* XXX TODO */
1110   return NULL;
1111 }
1112
1113 /* Destroyes streamer */
1114
1115 void silc_packet_streamer_destroy(SilcStream stream)
1116 {
1117
1118 }