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