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