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     if (len1 - 2 > buffer->len) {
467       SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
468                       "packet dropped"));
469       return FALSE;
470     }
471
472     cipher->cipher->decrypt(cipher->context, buffer->data + 2,
473                             buffer->data + 2, len1 - 2,
474                             cipher->iv);
475     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
476   }
477
478   return TRUE;
479 }
480
481 /* Decrypts a packet. This assumes that typical SILC packet is the
482    packet to be decrypted and thus checks for normal and special SILC
483    packets and can handle both of them. This also computes and checks
484    the HMAC of the packet. If any other special or customized decryption
485    processing is required this function cannot be used. This returns
486    -1 on error, 0 when packet is normal packet and 1 when the packet
487    is special and requires special processing. 
488
489    The `check_packet' is a callback funtion that this function will 
490    call.  The callback relates to the checking whether the packet is
491    normal packet or special packet and how it should be processed.  If
492    the callback return TRUE the packet is normal and FALSE if the packet
493    is special and requires special procesing. */
494
495 int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
496                         SilcBuffer buffer, SilcPacketContext *packet,
497                         SilcPacketCheckDecrypt check_packet,
498                         void *context)
499 {
500   int check;
501
502   /* Decrypt start of the packet header */
503   if (cipher)
504     silc_cipher_decrypt(cipher, buffer->data + 2, buffer->data + 2, 
505                         SILC_PACKET_MIN_HEADER_LEN - 2, cipher->iv);
506
507   /* Do packet checking, whether the packet is normal or special */ 
508   check = check_packet((SilcPacketType)buffer->data[3], buffer,
509                        packet, context);
510
511   /* If the packet type is not any special type lets decrypt rest
512      of the packet here. */
513   if (check == TRUE) {
514     /* Normal packet, decrypt rest of the packet */
515     if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
516       return -1;
517
518     /* Check MAC */
519     if (!silc_packet_check_mac(hmac, buffer))
520       return -1;
521
522     return 0;
523   } else {
524     /* Packet requires special handling, decrypt rest of the header.
525        This only decrypts. */
526     if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
527       return -1;
528
529     /* Check MAC */
530     if (!silc_packet_check_mac(hmac, buffer))
531       return -1;
532
533     return 1;
534   }
535 }
536
537 /* Parses the packet. This is called when a whole packet is ready to be
538    parsed. The buffer sent must be already decrypted before calling this 
539    function. The len argument must be the true length of the packet. This 
540    function returns the type of the packet. The data section of the 
541    buffer is parsed, not head or tail sections. */
542
543 SilcPacketType silc_packet_parse(SilcPacketContext *ctx)
544 {
545   SilcBuffer buffer = ctx->buffer;
546   int len, ret;
547
548   SILC_LOG_DEBUG(("Parsing incoming packet"));
549
550   /* Check the length of the buffer */
551   if (buffer->len < SILC_PACKET_MIN_LEN) {
552     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
553     return SILC_PACKET_NONE;
554   }
555
556   /* Parse the buffer. This parses the SILC header of the packet. */
557   len = silc_buffer_unformat(buffer, 
558                              SILC_STR_UI_SHORT(&ctx->truelen),
559                              SILC_STR_UI_CHAR(&ctx->flags),
560                              SILC_STR_UI_CHAR(&ctx->type),
561                              SILC_STR_UI_SHORT(&ctx->src_id_len),
562                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
563                              SILC_STR_UI_CHAR(&ctx->src_id_type),
564                              SILC_STR_END);
565   if (len == -1)
566     return SILC_PACKET_NONE;
567
568   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
569       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
570     SILC_LOG_ERROR(("Bad ID lengths in packet"));
571     return SILC_PACKET_NONE;
572   }
573
574   /* Calculate length of padding in packet */
575   ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen);
576
577   silc_buffer_pull(buffer, len);
578   ret = silc_buffer_unformat(buffer, 
579                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
580                                                         ctx->src_id_len),
581                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
582                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
583                                                         ctx->dst_id_len),
584                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
585                              SILC_STR_END);
586   if (ret == -1)
587     return SILC_PACKET_NONE;
588
589   silc_buffer_push(buffer, len);
590
591   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
592                    ctx->buffer->data, ctx->buffer->len);
593
594   /* Pull SILC header and padding from packet */
595   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
596                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
597
598   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
599
600   return ctx->type;
601 }
602
603 /* Perform special SILC Packet header parsing. This is required to some
604    packet types that have the data payload encrypted with different key
605    than the header area plus padding of the packet. Hence, this parses
606    the header in a way that it does not take the data area into account
607    and parses the header and padding area only. */
608
609 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx)
610 {
611   SilcBuffer buffer = ctx->buffer;
612   int len, tmplen, ret;
613
614   SILC_LOG_DEBUG(("Parsing incoming packet"));
615
616   /* Check the length of the buffer */
617   if (buffer->len < SILC_PACKET_MIN_LEN) {
618     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
619     return SILC_PACKET_NONE;
620   }
621
622   /* Parse the buffer. This parses the SILC header of the packet. */
623   len = silc_buffer_unformat(buffer, 
624                              SILC_STR_UI_SHORT(&ctx->truelen),
625                              SILC_STR_UI_CHAR(&ctx->flags),
626                              SILC_STR_UI_CHAR(&ctx->type),
627                              SILC_STR_UI_SHORT(&ctx->src_id_len),
628                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
629                              SILC_STR_UI_CHAR(&ctx->src_id_type),
630                              SILC_STR_END);
631   if (len == -1)
632     return SILC_PACKET_NONE;
633
634   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
635       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
636     SILC_LOG_ERROR(("Bad ID lengths in packet"));
637     return SILC_PACKET_NONE;
638   }
639
640   /* Calculate length of padding in packet. As this is special packet
641      the data area is not used in the padding calculation as it won't
642      be decrypted by the caller. */
643   tmplen = SILC_PACKET_HEADER_LEN + ctx->src_id_len + ctx->dst_id_len;
644   ctx->padlen = SILC_PACKET_PADLEN(tmplen);
645
646   silc_buffer_pull(buffer, len);
647   ret = silc_buffer_unformat(buffer, 
648                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
649                                                         ctx->src_id_len),
650                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
651                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
652                                                         ctx->dst_id_len),
653                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
654                              SILC_STR_END);
655   if (ret == -1)
656     return SILC_PACKET_NONE;
657
658   silc_buffer_push(buffer, len);
659
660   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
661                    ctx->buffer->data, ctx->buffer->len);
662
663   /* Pull SILC header and padding from packet */
664   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
665                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
666
667   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
668
669   return ctx->type;
670 }
671
672 /* Allocate packet context */
673
674 SilcPacketContext *silc_packet_context_alloc()
675 {
676   SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
677   ctx->users++;
678   return ctx;
679 }
680
681 /* Increse the reference count of the packet context. */
682
683 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
684 {
685   ctx->users++;
686   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
687                   ctx->users));
688   return ctx;
689 }
690
691 /* Decrese the reference count of the packet context and free it only if
692    it is zero. */
693
694 void silc_packet_context_free(SilcPacketContext *ctx)
695 {
696   ctx->users--;
697   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
698                   ctx->users));
699   if (ctx->users < 1)
700     {
701       if (ctx->buffer)
702         silc_buffer_free(ctx->buffer);
703       if (ctx->src_id)
704         silc_free(ctx->src_id);
705       if (ctx->dst_id)
706         silc_free(ctx->dst_id);
707       silc_free(ctx);
708     }
709 }