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