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