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