Fixed memory leaks around the tree.
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2001 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 /******************************************************************************
27
28                           Packet Sending Routines
29
30 ******************************************************************************/
31
32 /* Actually sends the packet. This flushes the connections outgoing data
33    buffer. If data is sent directly to the network this returns the bytes
34    written, if error occured this returns -1 and if the data could not
35    be written directly to the network at this time this returns -2, in
36    which case the data should be queued by the caller and sent at some
37    later time. If `force_send' is TRUE this attempts to write the data
38    directly to the network, if FALSE, this returns -2. */
39
40 int silc_packet_send(SilcSocketConnection sock, bool force_send)
41 {
42   SILC_LOG_DEBUG(("Sending packet to %s:%d [%s]", sock->hostname,
43                   sock->port,  
44                   (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
45                    sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
46                    sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
47                    "Router")));
48
49   /* Send now if forced to do so */
50   if (force_send == TRUE) {
51     int ret;
52
53     SILC_LOG_DEBUG(("Forcing packet send, packet sent immediately"));
54
55     /* Write to network */
56     ret = silc_socket_write(sock);
57
58     if (ret == -1) {
59       SILC_LOG_ERROR(("Error sending packet, dropped: %s", 
60                       strerror(errno)));
61     }
62     if (ret != -2)
63       return ret;
64
65     SILC_LOG_DEBUG(("Could not force the send, packet put to queue"));
66   }  
67
68   SILC_LOG_DEBUG(("Packet in queue"));
69
70   return -2;
71 }
72
73 /* Encrypts a packet. This also creates HMAC of the packet before 
74    encryption and adds the HMAC at the end of the buffer. This assumes
75    that there is enough free space at the end of the buffer to add the
76    computed HMAC. This is the normal way of encrypting packets, if some
77    other process of HMAC computing and encryption is needed this function
78    cannot be used. */
79
80 void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, SilcUInt32 sequence,
81                          SilcBuffer buffer, SilcUInt32 len)
82 {
83   unsigned char mac[32];
84   SilcUInt32 mac_len;
85
86   /* Compute HMAC. This assumes that HMAC is created from the entire
87      data area thus this uses the length found in buffer, not the length
88      sent as argument. */
89   if (hmac) {
90     unsigned char psn[4];
91
92     silc_hmac_init(hmac);
93     SILC_PUT32_MSB(sequence, psn);
94     silc_hmac_update(hmac, psn, 4);
95     silc_hmac_update(hmac, buffer->data, buffer->len);
96     silc_hmac_final(hmac, mac, &mac_len);
97     silc_buffer_put_tail(buffer, mac, mac_len);
98     memset(mac, 0, sizeof(mac));
99   }
100
101   /* Encrypt the data area of the packet. */
102   if (cipher) {
103     SILC_LOG_DEBUG(("Encrypting packet, cipher %s, len %d", 
104                     cipher->cipher->name, len));
105     silc_cipher_encrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
106   }
107
108   /* Pull the HMAC into the visible data area in the buffer */
109   if (hmac)
110     silc_buffer_pull_tail(buffer, mac_len);
111 }
112
113 /* Assembles a new packet to be ready for send out. */
114
115 bool silc_packet_assemble(SilcPacketContext *packet, SilcRng rng,
116                           SilcCipher cipher, SilcHmac hmac,
117                           SilcSocketConnection sock,
118                           const unsigned char *data, SilcUInt32 data_len,
119                           const SilcBuffer assembled_packet)
120
121   unsigned char tmppad[SILC_PACKET_MAX_PADLEN];   
122   int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
123   int i, ret;
124
125   SILC_LOG_DEBUG(("Assembling outgoing packet"));
126
127   /* Calculate the packet's length and padding length if upper layer
128      didn't already do it. */
129
130   /* Get the true length of the packet. This is saved as payload length
131      into the packet header. This does not include the length of the
132      padding. */
133   if (!packet->truelen) {
134     data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
135                                    packet->src_id_len + packet->dst_id_len);
136     packet->truelen = data_len + SILC_PACKET_HEADER_LEN + 
137       packet->src_id_len + packet->dst_id_len;
138   }
139
140   /* Calculate the length of the padding. The padding is calculated from
141      the data that will be encrypted. */
142   if (!packet->padlen) {
143     packet->padlen = (packet->long_pad ?
144                       SILC_PACKET_PADLEN_MAX(packet->truelen) :
145                       SILC_PACKET_PADLEN(packet->truelen, block_len));
146   }
147
148   /* Now prepare the outgoing data buffer for packet sending and start
149      assembling the packet. */
150
151   /* Return pointer to the assembled packet */
152   if (!silc_packet_send_prepare(sock, packet->truelen - data_len,
153                                 packet->padlen, data_len, hmac,
154                                 assembled_packet))
155     return FALSE;
156
157   /* Get random padding */
158   if (rng)
159     for (i = 0; i < packet->padlen; i++) tmppad[i] =
160                                            silc_rng_get_byte_fast(rng);
161   else
162     for (i = 0; i < packet->padlen; i++) tmppad[i] =
163                                            silc_rng_global_get_byte_fast();
164
165   /* Create the packet. This creates the SILC header, adds padding, and
166      the actual packet data. */
167   ret =
168     silc_buffer_format(assembled_packet,
169                        SILC_STR_UI_SHORT(packet->truelen),
170                        SILC_STR_UI_CHAR(packet->flags),
171                        SILC_STR_UI_CHAR(packet->type),
172                        SILC_STR_UI_CHAR(packet->padlen),
173                        SILC_STR_UI_CHAR(0),
174                        SILC_STR_UI_CHAR(packet->src_id_len),
175                        SILC_STR_UI_CHAR(packet->dst_id_len),
176                        SILC_STR_UI_CHAR(packet->src_id_type),
177                        SILC_STR_UI_XNSTRING(packet->src_id,
178                                             packet->src_id_len),
179                        SILC_STR_UI_CHAR(packet->dst_id_type),
180                        SILC_STR_UI_XNSTRING(packet->dst_id,
181                                             packet->dst_id_len),
182                        SILC_STR_UI_XNSTRING(tmppad, packet->padlen),
183                        SILC_STR_UI_XNSTRING(data, data_len),
184                        SILC_STR_END);
185   if (ret < 0)
186     return FALSE;
187
188   SILC_LOG_HEXDUMP(("Assembled packet, len %d", assembled_packet->len),
189                    assembled_packet->data, assembled_packet->len);
190
191   return TRUE;
192 }
193
194 /* Prepare outgoing data buffer for packet sending. This moves the data
195    area so that new packet may be added into it. If needed this allocates
196    more space to the buffer. This handles directly the connection's
197    outgoing buffer in SilcSocketConnection object, and returns the
198    pointer to that buffer into the `packet'. */
199
200 bool silc_packet_send_prepare(SilcSocketConnection sock,
201                               SilcUInt32 header_len,
202                               SilcUInt32 pad_len,
203                               SilcUInt32 data_len,
204                               SilcHmac hmac,
205                               const SilcBuffer packet)
206
207   int totlen;
208   unsigned char *oldptr;
209   int mac_len = hmac ? silc_hmac_len(hmac) : 0;
210
211   if (!packet)
212     return FALSE;
213
214   totlen = header_len + pad_len + data_len;
215
216   /* Prepare the outgoing buffer for packet sending. */
217   if (!sock->outbuf) {
218     /* Allocate new buffer. This is done only once per connection. */
219     SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
220
221     sock->outbuf = silc_buffer_alloc(totlen > SILC_PACKET_DEFAULT_SIZE ?
222                                      totlen : SILC_PACKET_DEFAULT_SIZE);
223     if (!sock->outbuf)
224       return FALSE;
225   } else {
226     if (!SILC_IS_OUTBUF_PENDING(sock)) {
227       /* Buffer is free for use */
228       silc_buffer_clear(sock->outbuf);
229     }
230   }
231
232   /* Allocate more space if needed */
233   if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + mac_len)) {
234     SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
235     sock->outbuf = silc_buffer_realloc(sock->outbuf,
236                                        sock->outbuf->truelen + (totlen * 2));
237     if (!sock->outbuf)
238       return FALSE;
239   }
240
241   /* Pull data area for the new packet, and return pointer to the start of
242      the data area and save the pointer in to the `packet'. */
243   oldptr = silc_buffer_pull_tail(sock->outbuf, totlen + mac_len);
244   silc_buffer_set(packet, oldptr, totlen + mac_len);
245   silc_buffer_push_tail(packet, mac_len);
246
247   return TRUE;
248 }
249
250 /******************************************************************************
251
252                          Packet Reception Routines
253
254 ******************************************************************************/
255
256 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac, 
257                                SilcUInt32 sequence, SilcBuffer buffer, 
258                                bool normal);
259
260 /* Receives packet from network and reads the data into connection's
261    incoming data buffer. If the data was read directly this returns the
262    read bytes, if error occured this returns -1, if the data could not
263    be read directly at this time this returns -2 in which case the data
264    should be read again at some later time, or If EOF occured this returns
265    0. */
266
267 int silc_packet_receive(SilcSocketConnection sock)
268 {
269   int ret;
270
271   SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
272                   sock->port, 
273                   (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
274                    sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
275                    sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
276                    "Router")));
277
278   /* Read some data from connection */
279   ret = silc_socket_read(sock);
280
281   return ret;
282 }
283
284 /* Processes and decrypts the incmoing data, and calls parser callback
285    for each received packet that will handle the actual packet parsing.
286    If more than one packet was received this calls the parser multiple
287    times.  The parser callback will get context SilcPacketParserContext
288    that includes the packet and the `parser_context' sent to this
289    function. 
290    
291    The `local_is_router' indicates whether the caller is router server
292    in which case the receiving process of a certain packet types may
293    be special.  Normal server and client must set it to FALSE.  The
294    SilcPacketParserContext will indicate also whether the received
295    packet was normal or special packet. */
296
297 bool silc_packet_receive_process(SilcSocketConnection sock,
298                                  bool local_is_router,
299                                  SilcCipher cipher, SilcHmac hmac,
300                                  SilcUInt32 sequence,
301                                  SilcPacketParserCallback parser,
302                                  void *parser_context)
303 {
304   SilcPacketParserContext *parse_ctx;
305   int packetlen, paddedlen, mac_len = 0;
306   bool cont = TRUE;
307
308   /* Do not process for disconnected connection */
309   if (SILC_IS_DISCONNECTED(sock))
310     return TRUE;
311
312   if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
313     return TRUE;
314
315   if (hmac)
316     mac_len = silc_hmac_len(hmac);
317
318   /* Parse the packets from the data */
319   while (sock->inbuf->len > 0 && cont) {
320
321     if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
322       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
323       return TRUE;
324     }
325
326     /* Decrypt first 16 bytes of the packet */
327     if (!SILC_IS_INBUF_PENDING(sock) && cipher)
328       silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data, 
329                           SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
330
331     /* Get packet lenght and full packet length with padding */
332     SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
333
334     /* Sanity checks */
335     if (packetlen < SILC_PACKET_MIN_LEN) {
336       SILC_LOG_ERROR(("Received invalid packet, dropped"));
337       silc_buffer_clear(sock->inbuf);
338       return FALSE;
339     }
340
341     if (sock->inbuf->len < paddedlen + mac_len) {
342       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
343                       "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
344       SILC_SET_INBUF_PENDING(sock);
345       return TRUE;
346     }
347
348     SILC_UNSET_INBUF_PENDING(sock);
349     parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
350     if (!parse_ctx)
351       return FALSE;
352     parse_ctx->packet = silc_packet_context_alloc();
353     parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
354     parse_ctx->packet->type = sock->inbuf->data[3];
355     parse_ctx->packet->padlen = sock->inbuf->data[4];
356     parse_ctx->packet->sequence = sequence++;
357     parse_ctx->sock = sock;
358     parse_ctx->context = parser_context;
359
360     silc_buffer_pull_tail(parse_ctx->packet->buffer, 
361                           SILC_BUFFER_END(parse_ctx->packet->buffer));
362     silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data, 
363                     paddedlen + mac_len);
364
365     SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d", 
366                       sequence - 1, SILC_PACKET_MIN_HEADER_LEN, 
367                       paddedlen + mac_len),
368                      sock->inbuf->data, paddedlen + mac_len);
369
370     /* Check whether this is normal or special packet */
371     if (local_is_router) {
372       if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
373           (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
374         parse_ctx->normal = FALSE;
375       else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE || 
376                (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
377                 sock->type == SILC_SOCKET_TYPE_ROUTER))
378         parse_ctx->normal = TRUE;
379     } else {
380       if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
381           (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
382         parse_ctx->normal = FALSE;
383       else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE)
384         parse_ctx->normal = TRUE;
385     }
386
387     /* Decrypt rest of the packet */
388     if (cipher)
389       if (silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence, 
390                               parse_ctx->packet->buffer, 
391                               parse_ctx->normal) == -1) {
392         SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s] [%s]", 
393                           sock->hostname, sock->port,
394                           silc_get_packet_name(parse_ctx->packet->type),
395                           (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
396                            sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
397                            sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
398                            "Router")));
399         silc_packet_context_free(parse_ctx->packet);
400         silc_free(parse_ctx);
401         return FALSE;
402       }
403
404     /* Pull the packet from inbuf thus we'll get the next one
405        in the inbuf. */
406     silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
407
408     /* Call the parser */
409     cont = (*parser)(parse_ctx, parser_context);
410   }
411
412   if (cont == FALSE && sock->inbuf->len > 0)
413     return TRUE;
414
415   SILC_LOG_DEBUG(("Clearing inbound buffer"));
416   silc_buffer_clear(sock->inbuf);
417   return TRUE;
418 }
419
420 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
421    after packet has been totally decrypted and parsed. */
422
423 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
424                                  SilcUInt32 sequence)
425 {
426   /* Check MAC */
427   if (hmac) {
428     unsigned char mac[32], psn[4];
429     SilcUInt32 mac_len;
430     
431     SILC_LOG_DEBUG(("Verifying MAC"));
432
433     /* Compute HMAC of packet */
434
435     memset(mac, 0, sizeof(mac));
436     silc_hmac_init(hmac);
437     SILC_PUT32_MSB(sequence, psn);
438     silc_hmac_update(hmac, psn, 4);
439     silc_hmac_update(hmac, buffer->data, buffer->len);
440     silc_hmac_final(hmac, mac, &mac_len);
441
442     /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
443     if (memcmp(buffer->tail, mac, mac_len)) {
444       SILC_LOG_ERROR(("MAC failed"));
445       return FALSE;
446     }
447     
448     SILC_LOG_DEBUG(("MAC is Ok"));
449     memset(mac, 0, sizeof(mac));
450   }
451   
452   return TRUE;
453 }
454
455 /* Decrypts rest of the packet (after decrypting just the SILC header).
456    After calling this function the packet is ready to be parsed by calling 
457    silc_packet_parse. If everything goes without errors this returns TRUE,
458    if packet is malformed this returns FALSE. */
459
460 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
461                                     SilcBuffer buffer)
462 {
463   if (cipher) {
464
465     /* Pull MAC from packet before decryption */
466     if (hmac) {
467       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
468         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
469       } else {
470         SILC_LOG_ERROR(("Bad MAC length in packet, packet dropped"));
471         return FALSE;
472       }
473     }
474
475     SILC_LOG_DEBUG(("Decrypting rest of the packet"));
476
477     /* Decrypt rest of the packet */
478     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
479     silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len, 
480                         cipher->iv);
481     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
482
483     SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
484                      buffer->data, buffer->len);
485   }
486
487   return TRUE;
488 }
489
490 /* Decrypts rest of the SILC Packet header that has been decrypted partly
491    already. This decrypts the padding of the packet also. After calling 
492    this function the packet is ready to be parsed by calling function 
493    silc_packet_parse. This is used in special packet reception (protocol
494    defines the way of decrypting special packets). */
495
496 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
497                                             SilcHmac hmac,
498                                             SilcBuffer buffer)
499 {
500   /* Decrypt rest of the header plus padding */
501   if (cipher) {
502     SilcUInt16 len;
503
504     /* Pull MAC from packet before decryption */
505     if (hmac) {
506       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
507         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
508       } else {
509         SILC_LOG_ERROR(("Bad MAC length in packet, packet dropped"));
510         return FALSE;
511       }
512     }
513   
514     SILC_LOG_DEBUG(("Decrypting rest of the header"));
515
516     /* padding length + src id len + dst id len + header length - 16
517        bytes already decrypted, gives the rest of the encrypted packet */
518     len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] + 
519            (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
520            SILC_PACKET_MIN_HEADER_LEN);
521
522     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
523     if (len > buffer->len) {
524       SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
525                       "packet dropped"));
526       return FALSE;
527     }
528     silc_cipher_decrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
529     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
530     SILC_LOG_HEXDUMP(("packet, len %d", buffer->len), 
531                      buffer->data, buffer->len);
532   }
533
534   return TRUE;
535 }
536
537 /* Decrypts a packet. This assumes that typical SILC packet is the
538    packet to be decrypted and thus checks for normal and special SILC
539    packets and can handle both of them. This also computes and checks
540    the HMAC of the packet. If any other special or customized decryption
541    processing is required this function cannot be used. This returns
542    -1 on error, 0 when packet is normal packet and 1 when the packet
543    is special and requires special processing. 
544
545    The `check_packet' is a callback funtion that this function will 
546    call.  The callback relates to the checking whether the packet is
547    normal packet or special packet and how it should be processed.  If
548    the callback return TRUE the packet is normal and FALSE if the packet
549    is special and requires special procesing. */
550
551 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
552                                SilcUInt32 sequence, SilcBuffer buffer, 
553                                bool normal)
554 {
555   /* If the packet type is not any special type lets decrypt rest
556      of the packet here. */
557   if (normal == TRUE) {
558     /* Normal packet, decrypt rest of the packet */
559     if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
560       return -1;
561
562     /* Check MAC */
563     if (!silc_packet_check_mac(hmac, buffer, sequence))
564       return -1;
565
566     return 0;
567   } else {
568     /* Packet requires special handling, decrypt rest of the header.
569        This only decrypts. */
570     if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
571       return -1;
572
573     /* Check MAC */
574     if (!silc_packet_check_mac(hmac, buffer, sequence))
575       return -1;
576
577     return 1;
578   }
579 }
580
581 /* Parses the packet. This is called when a whole packet is ready to be
582    parsed. The buffer sent must be already decrypted before calling this 
583    function. The len argument must be the true length of the packet. This 
584    function returns the type of the packet. The data section of the 
585    buffer is parsed, not head or tail sections. */
586
587 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
588 {
589   SilcBuffer buffer = ctx->buffer;
590   SilcUInt8 tmp;
591   int len, ret;
592   SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
593
594   SILC_LOG_DEBUG(("Parsing incoming packet"));
595
596   /* Check the length of the buffer */
597   if (buffer->len < SILC_PACKET_MIN_LEN) {
598     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
599     return SILC_PACKET_NONE;
600   }
601
602   /* Parse the buffer. This parses the SILC header of the packet. */
603   len = silc_buffer_unformat(buffer, 
604                              SILC_STR_UI_SHORT(&ctx->truelen),
605                              SILC_STR_UI_CHAR(&ctx->flags),
606                              SILC_STR_UI_CHAR(&ctx->type),
607                              SILC_STR_UI_CHAR(&padlen),
608                              SILC_STR_UI_CHAR(&tmp),
609                              SILC_STR_UI_CHAR(&src_id_len),
610                              SILC_STR_UI_CHAR(&dst_id_len),
611                              SILC_STR_UI_CHAR(&src_id_type),
612                              SILC_STR_END);
613   if (len == -1 || tmp != 0)
614     return SILC_PACKET_NONE;
615
616   if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
617       dst_id_len > SILC_PACKET_MAX_ID_LEN) {
618     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
619                     src_id_len, dst_id_len));
620     return SILC_PACKET_NONE;
621   }
622
623   silc_buffer_pull(buffer, len);
624   ret = silc_buffer_unformat(buffer, 
625                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
626                                                         src_id_len),
627                              SILC_STR_UI_CHAR(&dst_id_type),
628                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
629                                                         dst_id_len),
630                              SILC_STR_UI_XNSTRING(NULL, padlen),
631                              SILC_STR_END);
632   if (ret == -1)
633     return SILC_PACKET_NONE;
634
635   if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
636     SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
637                    src_id_type, dst_id_type));
638     return SILC_PACKET_NONE;
639   }
640
641   ctx->src_id_len = src_id_len;
642   ctx->dst_id_len = dst_id_len;
643   ctx->src_id_type = src_id_type;
644   ctx->dst_id_type = dst_id_type;
645   ctx->padlen = padlen;
646
647   silc_buffer_push(buffer, len);
648
649   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
650                    ctx->buffer->data, ctx->buffer->len);
651
652   /* Pull SILC header and padding from packet */
653   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
654                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
655
656   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
657
658   return ctx->type;
659 }
660
661 /* Perform special SILC Packet header parsing. This is required to some
662    packet types that have the data payload encrypted with different key
663    than the header area plus padding of the packet. Hence, this parses
664    the header in a way that it does not take the data area into account
665    and parses the header and padding area only. */
666
667 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
668                                          SilcCipher cipher)
669 {
670   SilcBuffer buffer = ctx->buffer;
671   SilcUInt8 tmp;
672   int len, ret;
673   SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
674
675   SILC_LOG_DEBUG(("Parsing incoming packet"));
676
677   /* Check the length of the buffer */
678   if (buffer->len < SILC_PACKET_MIN_LEN) {
679     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
680     return SILC_PACKET_NONE;
681   }
682
683   /* Parse the buffer. This parses the SILC header of the packet. */
684   len = silc_buffer_unformat(buffer, 
685                              SILC_STR_UI_SHORT(&ctx->truelen),
686                              SILC_STR_UI_CHAR(&ctx->flags),
687                              SILC_STR_UI_CHAR(&ctx->type),
688                              SILC_STR_UI_CHAR(&padlen),
689                              SILC_STR_UI_CHAR(&tmp),
690                              SILC_STR_UI_CHAR(&src_id_len),
691                              SILC_STR_UI_CHAR(&dst_id_len),
692                              SILC_STR_UI_CHAR(&src_id_type),
693                              SILC_STR_END);
694   if (len == -1 || tmp != 0) {
695     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
696     return SILC_PACKET_NONE;
697   }
698
699   if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
700       dst_id_len > SILC_PACKET_MAX_ID_LEN) {
701     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
702                     src_id_len, dst_id_len));
703     return SILC_PACKET_NONE;
704   }
705
706   silc_buffer_pull(buffer, len);
707   ret = silc_buffer_unformat(buffer, 
708                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
709                                                         src_id_len),
710                              SILC_STR_UI_CHAR(&dst_id_type),
711                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
712                                                         dst_id_len),
713                              SILC_STR_UI_XNSTRING(NULL, padlen),
714                              SILC_STR_END);
715   if (ret == -1) {
716     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
717     return SILC_PACKET_NONE;
718   }
719
720   if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
721     SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
722                    src_id_type, dst_id_type));
723     return SILC_PACKET_NONE;
724   }
725
726   ctx->src_id_len = src_id_len;
727   ctx->dst_id_len = dst_id_len;
728   ctx->src_id_type = src_id_type;
729   ctx->dst_id_type = dst_id_type;
730   ctx->padlen = padlen;
731
732   silc_buffer_push(buffer, len);
733
734   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
735                    ctx->buffer->data, ctx->buffer->len);
736
737   /* Pull SILC header and padding from packet */
738   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
739                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
740
741   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
742
743   return ctx->type;
744 }
745
746 /* Allocate packet context */
747
748 SilcPacketContext *silc_packet_context_alloc(void)
749 {
750   SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
751   if (!ctx)
752     return NULL;
753   ctx->users++;
754   return ctx;
755 }
756
757 /* Increse the reference count of the packet context. */
758
759 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
760 {
761   ctx->users++;
762   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
763                   ctx->users));
764   return ctx;
765 }
766
767 /* Decrese the reference count of the packet context and free it only if
768    it is zero. */
769
770 void silc_packet_context_free(SilcPacketContext *ctx)
771 {
772   ctx->users--;
773   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
774                   ctx->users));
775   if (ctx->users < 1)
776     {
777       if (ctx->buffer)
778         silc_buffer_free(ctx->buffer);
779       if (ctx->src_id)
780         silc_free(ctx->src_id);
781       if (ctx->dst_id)
782         silc_free(ctx->dst_id);
783       silc_free(ctx);
784     }
785 }