updates.
[silc.git] / lib / silccore / silcpacket.h
1 /****h* silccore/silcpacket.h
2  *
3  * NAME
4  *
5  * silcpacket.h
6  *
7  * COPYRIGHT
8  *
9  * Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
10  *
11  * Copyright (C) 1997 - 2001 Pekka Riikonen
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * DESCRIPTION
24  *
25  * Implementation of the packet routines for sending and receiving
26  * SILC Packets. These includes the data sending routines and data
27  * reading routines, encrypting and decrypting routines, packet assembling
28  * and packet parsing routines.
29  *
30  ***/
31
32 #ifndef SILCPACKET_H
33 #define SILCPACKET_H
34
35 /* Amount of bytes to be read from the socket connection at once. */
36 #define SILC_PACKET_READ_SIZE 16384
37
38 /* Default byte size of the packet. This can be set larger if this
39    is not enough, we shall see. */
40 #define SILC_PACKET_DEFAULT_SIZE 2048
41
42 /* Header length without source and destination ID's. */
43 #define SILC_PACKET_HEADER_LEN 8 + 2
44
45 /* Minimum length of SILC Packet Header. This much is decrypted always
46    when packet is received to be able to get all the relevant data out
47    from the header. */
48 #define SILC_PACKET_MIN_HEADER_LEN 16 + 2
49
50 /* Maximum padding length */
51 #define SILC_PACKET_MAX_PADLEN 16
52
53 /* Minimum packet length */
54 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
55
56 /* Maximum length of ID */
57 #define SILC_PACKET_MAX_ID_LEN 16
58
59 /****d* silccore/SilcPacketAPI/SilcPacketType
60  *
61  * NAME
62  * 
63  *    typedef unsigned char SilcPacketType;
64  *
65  * DESCRIPTION
66  *
67  *    SILC packet type definition and all the packet types.
68  *
69  * SOURCE
70  */
71 typedef unsigned char SilcPacketType;
72
73 /* SILC Packet types. */
74 #define SILC_PACKET_NONE                 0       /* NULL, never sent */
75 #define SILC_PACKET_DISCONNECT           1       /* Disconnection */
76 #define SILC_PACKET_SUCCESS              2       /* Success */
77 #define SILC_PACKET_FAILURE              3       /* Failure */
78 #define SILC_PACKET_REJECT               4       /* Rejected */
79 #define SILC_PACKET_NOTIFY               5       /* Notify message */
80 #define SILC_PACKET_ERROR                6       /* Error message */
81 #define SILC_PACKET_CHANNEL_MESSAGE      7       /* Message for channel */
82 #define SILC_PACKET_CHANNEL_KEY          8       /* Key of the channel */
83 #define SILC_PACKET_PRIVATE_MESSAGE      9       /* Private message */
84 #define SILC_PACKET_PRIVATE_MESSAGE_KEY  10      /* Private message key*/
85 #define SILC_PACKET_COMMAND              11      /* Command */
86 #define SILC_PACKET_COMMAND_REPLY        12      /* Reply to a command */
87 #define SILC_PACKET_KEY_EXCHANGE         13      /* Start of KE */
88 #define SILC_PACKET_KEY_EXCHANGE_1       14      /* KE1 */
89 #define SILC_PACKET_KEY_EXCHANGE_2       15      /* KE2 */
90 #define SILC_PACKET_CONNECTION_AUTH_REQUEST 16   /* Request of auth meth */
91 #define SILC_PACKET_CONNECTION_AUTH      17      /* Connectinon auth */
92 #define SILC_PACKET_NEW_ID               18      /* Sending new ID */
93 #define SILC_PACKET_NEW_CLIENT           19      /* Client registering */
94 #define SILC_PACKET_NEW_SERVER           20      /* Server registering */
95 #define SILC_PACKET_NEW_CHANNEL          21      /* Channel registering */
96 #define SILC_PACKET_REKEY                22      /* Re-key start */
97 #define SILC_PACKET_REKEY_DONE           23      /* Re-key done */
98 #define SILC_PACKET_HEARTBEAT            24      /* Heartbeat */
99 #define SILC_PACKET_KEY_AGREEMENT        25      /* Key Agreement request */
100 #define SILC_PACKET_CELL_ROUTERS         26      /* Cell routers backup */
101
102 #define SILC_PACKET_PRIVATE              200     /* Private range start  */
103 #define SILC_PACKET_MAX                  255     /* RESERVED */
104 /***/
105
106 /****d* silccore/SilcPacketAPI/SilcPacketVersion
107  *
108  * NAME
109  * 
110  *    typedef unsigned char SilcPacketVersion;
111  *
112  * DESCRIPTION
113  *
114  *    SILC packet version type definition.
115  *
116  ***/
117 typedef unsigned char SilcPacketVersion;
118
119 /****d* silccore/SilcPacketAPI/SilcPacketFlags
120  *
121  * NAME
122  * 
123  *    typedef unsigned char SilcPacketFlags;
124  *
125  * DESCRIPTION
126  *
127  *    SILC packet flags type definition and all the packet flags.
128  *
129  * SOURCE
130  */
131 typedef unsigned char SilcPacketFlags;
132
133 /* All defined packet flags */
134 #define SILC_PACKET_FLAG_NONE             0x00    /* No flags */
135 #define SILC_PACKET_FLAG_PRIVMSG_KEY      0x01    /* Private message key */
136 #define SILC_PACKET_FLAG_LIST             0x02    /* Packet is a list */
137 #define SILC_PACKET_FLAG_BROADCAST        0x04    /* Packet is a broadcast */
138 /***/
139
140 /* Rest of flags still available
141 #define SILC_PACKET_FLAG_XXX              0x08
142 #define SILC_PACKET_FLAG_XXX              0x10
143 #define SILC_PACKET_FLAG_XXX              0x20
144 #define SILC_PACKET_FLAG_XXX              0x40
145 #define SILC_PACKET_FLAG_XXX              0x80
146 */
147
148 /****s* silccore/SilcPacketAPI/SilcPacketContext
149  *
150  * NAME
151  * 
152  *    typedef struct { ... } SilcPacketContext;
153  *
154  * DESCRIPTION
155  *
156  *    In packet sending this is filled and sent to silc_packet_assemble 
157  *    which then uses it to assemble new packet. In packet reception pointer 
158  *    to this context is sent to silc_packet_parse which parses the packet 
159  *    and returns the relevant information to this structure. On packet 
160  *    reception returned ID's are always the hash values of the ID's from 
161  *    the packet. 
162  *
163  *    Short description of the fields following:
164  *
165  *    SilcBuffer buffer
166  *
167  *      The data buffer.
168  *
169  *    SilcPacketType type
170  *
171  *      Type of the packet. Types are defined below.
172  *
173  *    SilcPacketFlags flags
174  *
175  *      Packet flags. Flags are defined above.
176  *
177  *    unsigned char *src_id
178  *    uint16 src_id_len
179  *    unsigned char src_id_type
180  *
181  *      Source ID, its length and type. On packet reception retuned ID's
182  *      are always the hash values of the ID's from the packet.
183  *
184  *    unsigned char *dst_id;
185  *    uint16 dst_id_len;
186  *    unsigned char src_id_type;
187  *
188  *      Destination ID, its length and type. On packet reception retuned
189  *      ID's are always the hash values of the ID's from the packet.
190  *
191  *    uint16 truelen
192  *    uint16 padlen
193  *
194  *      The true lenght of the packet and the padded length of the packet.
195  *      These may be set by the caller before calling any of the 
196  *      silc_packet_* routines. If not provided the library will calculate
197  *      the values.
198  *
199  *    in users;
200  *
201  *      Reference counter for this context. The context is freed only 
202  *      after the reference counter hits zero. The counter is added
203  *      calling silc_packet_context_dup and decreased by calling the
204  *      silc_packet_context_free.
205  *
206  ***/
207 typedef struct {
208   SilcBuffer buffer;
209   SilcPacketType type;
210   SilcPacketFlags flags;
211
212   unsigned char *src_id;
213   uint16 src_id_len;
214   unsigned char src_id_type;
215
216   unsigned char *dst_id;
217   uint16 dst_id_len;
218   unsigned char dst_id_type;
219
220   uint16 truelen;
221   uint16 padlen;
222
223   /* Back pointers */
224   void *context;
225   SilcSocketConnection sock;
226
227   int users;
228 } SilcPacketContext;
229
230 /****s* silccore/SilcPacketAPI/SilcPacketParserContext
231  *
232  * NAME
233  * 
234  *    typedef struct { ... } SilcPacketParserContext;
235  *
236  * DESCRIPTION
237  *
238  *    This context is used in packet reception when silc_packet_receive_process
239  *    function calls parser callback that performs the actual packet decryption
240  *    and parsing. This context is sent as argument to the parser function.
241  *    This context must be free'd by the parser callback function.
242  *
243  *    Following description of the fields:
244  *
245  *    SilcPacketContext *packet
246  *
247  *      The actual packet received from the network. In this phase the
248  *      context is not parsed, only the packet->buffer is allocated and
249  *      it includes the raw packet data, which is encrypted.
250  *
251  *    SilcSocketConnection sock
252  *
253  *      The associated connection.
254  *
255  *    void *context
256  *
257  *      User context that is sent to the silc_packet_receive_process
258  *      function. This usually includes application and connection specific
259  *      data.
260  *
261  ***/
262 typedef struct {
263   SilcPacketContext *packet;
264   SilcSocketConnection sock;
265   void *context;
266 } SilcPacketParserContext;
267
268 /****f* silccore/SilcPacketAPI/SilcPacketParserCallback
269  *
270  * SYNOPSIS
271  *
272  *    typedef void (*SilcPacketParserCallback)(SilcPacketParserContext 
273  *                                             *parse_context);
274  *
275  * DESCRIPTION
276  *
277  *    This callback is given to the silc_packet_receive_process function.
278  *    The callback is called by the library every time a packet is
279  *    received from the network. After the packet has been decrypted
280  *    and at least partially parsed it is passed to the application
281  *    for further parsing using this callback and the SilcPacketParserContext
282  *    context. The application receiving the SilcPacketParserContext
283  *    must free it.
284  *
285  ***/
286 typedef void (*SilcPacketParserCallback)(SilcPacketParserContext 
287                                          *parse_context);
288
289 /****f* silccore/SilcPacketAPI/SilcPacketCheckDecrypt
290  *
291  * SYNOPSIS
292  *
293  *    typedef int (*SilcPacketCheckDecrypt)(SilcPacketType packet_type,
294  *                                          SilcBuffer buffer,
295  *                                          SilcPacketContext *packet,
296  *                                          void *context);
297  *
298  * DESCRIPTION
299  *
300  *    This callback function relates to the checking whether the packet is
301  *    normal packet or special packet and how it should be processed.  If
302  *    the callback returns TRUE the packet is normal and FALSE if the packet
303  *    is special and requires special procesing. Some of the packets in
304  *    SILC are special (like channel message packets that are encrypted
305  *    using channel specific keys) and requires special processing. That
306  *    is the reason for this callback function.
307  *
308  *    The library will call this function if provided for the
309  *    silc_packet_decrypt function. The `packet_type' is the type of
310  *    packet received (this is also actually the first time application
311  *    receives information of the received packet, next time it receives
312  *    it is when the SilcPacketParserCallback function is called),
313  *    the `buffer' is the raw packet data the `packet' the allocated
314  *    SilcPacketContext that is filled when parsing the packet and `context'
315  *    is application specific user context.
316  *
317  ***/
318 typedef int (*SilcPacketCheckDecrypt)(SilcPacketType packet_type,
319                                       SilcBuffer buffer,
320                                       SilcPacketContext *packet,
321                                       void *context);
322
323 /* Macros */
324
325 /****d* silccore/SilcPacketAPI/SILC_PACKET_LENGTH
326  *
327  * NAME
328  * 
329  *    #define SILC_PACKET_LENGTH ...
330  *
331  * DESCRIPTION
332  *
333  *    Returns true length of the packet and padded length of the packet.
334  *    This is primarily used by the libary in packet parsing phase but
335  *    the application may use it as well if needed.
336  *
337  * SOURCE
338  */
339 #define SILC_PACKET_LENGTH(__packet, __ret_truelen, __ret_padlen)            \
340 do {                                                                         \
341   SILC_GET16_MSB((__ret_truelen), (__packet)->data);                         \
342   (__ret_padlen) = (((__ret_truelen) - 2) +                                  \
343                     SILC_PACKET_MAX_PADLEN) & ~(SILC_PACKET_MAX_PADLEN - 1); \
344 } while(0)
345 /***/
346
347 /****d* silccore/SilcPacketAPI/SILC_PACKET_PADLEN
348  *
349  * NAME
350  * 
351  *    #define SILC_PACKET_PADLEN ...
352  *
353  * DESCRIPTION
354  *
355  *    Returns the length of the padding in the packet. This is used
356  *    by various library routines to determine needed padding length.
357  *
358  * SOURCE
359  */
360 #define SILC_PACKET_PADLEN(__packetlen)                                  \
361   SILC_PACKET_MAX_PADLEN - ((__packetlen) - 2) % SILC_PACKET_MAX_PADLEN;
362 /***/
363
364 /* Prototypes */
365
366 /****f* silccore/SilcPacketAPI/silc_packet_write
367  *
368  * SYNOPSIS
369  *
370  *    int silc_packet_write(int sock, SilcBuffer src);
371  *
372  * DESCRIPTION
373  *
374  *    Writes data from encrypted buffer to the socket connection. If the
375  *    data cannot be written at once, it will be written later with a timeout. 
376  *    The data is written from the data section of the buffer, not from head
377  *    or tail section. This automatically pulls the data section towards end
378  *    after writing the data.
379  *
380  ***/
381 int silc_packet_write(int sock, SilcBuffer src);
382
383 /****f* silccore/SilcPacketAPI/silc_packet_send
384  *
385  * SYNOPSIS
386  *
387  *    int silc_packet_send(SilcSocketConnection sock, int force_send);
388  *
389  * DESCRIPTION
390  *
391  *    Actually sends the packet. This flushes the connections outgoing data
392  *    buffer. If data is sent directly to the network this returns the bytes
393  *    written, if error occured this returns -1 and if the data could not
394  *    be written directly to the network at this time this returns -2, in
395  *    which case the data should be queued by the caller and sent at some
396  *    later time. If `force_send' is TRUE this attempts to write the data
397  *    directly to the network, if FALSE, this returns -2.
398  *
399  ***/
400 int silc_packet_send(SilcSocketConnection sock, int force_send);
401
402 /****f* silccore/SilcPacketAPI/silc_packet_encrypt
403  *
404  * SYNOPSIS
405  *
406  *    void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, 
407  *                             SilcBuffer buffer, uint32 len);
408  *
409  * DESCRIPTION
410  *
411  *    Encrypts a packet. This also creates HMAC of the packet before 
412  *    encryption and adds the HMAC at the end of the buffer. This assumes
413  *    that there is enough free space at the end of the buffer to add the
414  *    computed HMAC. This is the normal way of encrypting packets, if some
415  *    other process of HMAC computing and encryption is needed this function
416  *    cannot be used. 
417  *
418  ***/
419 void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, 
420                          SilcBuffer buffer, uint32 len);
421
422 /****f* silccore/SilcPacketAPI/silc_packet_assemble
423  *
424  * SYNOPSIS
425  *
426  *    void silc_packet_assemble(SilcPacketContext *ctx);
427  *
428  * DESCRIPTION
429  *
430  *    Assembles a new packet to be ready for send out. The buffer sent as
431  *    argument must include the data to be sent and it must not be encrypted. 
432  *    The packet also must have enough free space so that the SILC header
433  *    and padding maybe added to the packet. The packet is encrypted after 
434  *    this function has returned.
435  *
436  *    The buffer sent as argument should be something like following:
437  *
438  *    --------------------------------------------
439  *    | head             | data           | tail |
440  *    --------------------------------------------
441  *    ^                  ^
442  *    58 bytes           x bytes
443  *
444  *    So that the SILC header and 1 - 16 bytes of padding can fit to
445  *    the buffer. After assembly the buffer might look like this:
446  *
447  *    --------------------------------------------
448  *    | data                              |      |
449  *    --------------------------------------------
450  *    ^                                   ^
451  *    Start of assembled packet
452  *
453  *    Packet construct is as follows (* = won't be encrypted):
454  *
455  *    n bytes       SILC Header
456  *      2 bytes     Payload length  (*)
457  *      1 byte      Flags
458  *      1 byte      Packet type
459  *      2 bytes     Source ID Length
460  *      2 bytes     Destination ID Length
461  *      1 byte      Source ID Type
462  *      n bytes     Source ID
463  *      1 byte      Destination ID Type
464  *      n bytes     Destination ID
465  *
466  *    1 - 16 bytes    Padding
467  *
468  *    n bytes        Data payload
469  *
470  *    All fields in the packet will be authenticated by MAC. The MAC is
471  *    not computed here, it must be computed separately before encrypting
472  *    the packet.
473  *
474  ***/
475 void silc_packet_assemble(SilcPacketContext *ctx);
476
477 /****f* silccore/SilcPacketAPI/silc_packet_send_prepare
478  *
479  * SYNOPSIS
480  *
481  *    void silc_packet_send_prepare(SilcSocketConnection sock,
482  *                                  uint32 header_len,
483  *                                  uint32 padlen,
484  *                                  uint32 data_len);
485  *
486  * DESCRIPTION
487  *
488  *    Prepare outgoing data buffer for packet sending. This moves the data
489  *    area so that new packet may be added into it. If needed this allocates
490  *    more space to the buffer. This handles directly the connection's
491  *    outgoing buffer in SilcSocketConnection object.
492  *
493  ***/
494 void silc_packet_send_prepare(SilcSocketConnection sock,
495                               uint32 header_len,
496                               uint32 padlen,
497                               uint32 data_len);
498
499 /****f* silccore/SilcPacketAPI/silc_packet_read
500  *
501  * SYNOPSIS
502  *
503  *    int silc_packet_read(int sock, SilcBuffer dest);
504  *
505  * DESCRIPTION
506  *
507  *    Reads data from the socket connection into the incoming data buffer.
508  *    However, this does not parse the packet, it only reads some amount from
509  *    the network. If there are more data available that can be read at a time
510  *    the rest of the data will be read later with a timeout and only after
511  *    that the packet is ready to be parsed. 
512  *
513  *    The destination buffer sent as argument must be initialized before 
514  *    calling this function, and, the data section and the start of the tail
515  *    section must be same. Ie. we add the read data to the tail section of
516  *    the buffer hence the data section is the start of the buffer.
517  *
518  *    This returns amount of bytes read or -1 on error or -2 on case where
519  *    all of the data could not be read at once.
520  *
521  ***/
522 int silc_packet_read(int sock, SilcBuffer dest);
523
524 /****f* silccore/SilcPacketAPI/silc_packet_receive
525  *
526  * SYNOPSIS
527  *
528  *    int silc_packet_receive(SilcSocketConnection sock);
529  *
530  * DESCRIPTION
531  *
532  *    Receives packet from network and reads the data into connection's
533  *    incoming data buffer. If the data was read directly this returns the
534  *    read bytes, if error occured this returns -1, if the data could not
535  *    be read directly at this time this returns -2 in which case the data
536  *    should be read again at some later time, or If EOF occured this returns
537  *    0.
538  *
539  ***/
540 int silc_packet_receive(SilcSocketConnection sock);
541
542 /****f* silccore/SilcPacketAPI/silc_packet_decrypt
543  *
544  * SYNOPSIS
545  *
546  *    int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
547  *                            SilcBuffer buffer, SilcPacketContext *packet,
548  *                            SilcPacketCheckDecrypt check_packet,
549  *                            void *context);
550  *
551  * DESCRIPTION
552  *
553  *    Decrypts a packet. This assumes that typical SILC packet is the
554  *    packet to be decrypted and thus checks for normal and special SILC
555  *    packets and can handle both of them. This also computes and checks
556  *    the HMAC of the packet. If any other special or customized decryption
557  *    processing is required this function cannot be used. This returns
558  *    -1 on error, 0 when packet is normal packet and 1 when the packet
559  *    is special and requires special processing. 
560  *
561  *    The `check_packet' is a callback funtion that this function will 
562  *    call.  The callback relates to the checking whether the packet is
563  *    normal packet or special packet and how it should be processed.  If
564  *    the callback return TRUE the packet is normal and FALSE if the packet
565  *    is special and requires special procesing.
566  *
567  ***/
568 int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
569                         SilcBuffer buffer, SilcPacketContext *packet,
570                         SilcPacketCheckDecrypt check_packet,
571                         void *context);
572
573 /****f* silccore/SilcPacketAPI/silc_packet_receive_process
574  *
575  * SYNOPSIS
576  *
577  *    void silc_packet_receive_process(SilcSocketConnection sock,
578  *                                     SilcCipher cipher, SilcHmac hmac,
579  *                                     SilcPacketParserCallback parser,
580  *                                     void *context);
581  *
582  * DESCRIPTION
583  *
584  *    Processes the received data. This checks the received data and 
585  *    calls parser callback that handles the actual packet decryption
586  *    and parsing. If more than one packet was received this calls the
587  *    parser multiple times. The parser callback will get context
588  *    SilcPacketParserContext that includes the packet and the `context'
589  *    sent to this function.
590  *
591  ***/
592 void silc_packet_receive_process(SilcSocketConnection sock,
593                                  SilcCipher cipher, SilcHmac hmac,
594                                  SilcPacketParserCallback parser,
595                                  void *context);
596
597 /****f* silccore/SilcPacketAPI/silc_packet_parse
598  *
599  * SYNOPSIS
600  *
601  *    SilcPacketType silc_packet_parse(SilcPacketContext *ctx);
602  *
603  * DESCRIPTION
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  ***/
612 SilcPacketType silc_packet_parse(SilcPacketContext *ctx);
613
614 /****f* silccore/SilcPacketAPI/silc_packet_parse_special
615  *
616  * SYNOPSIS
617  *
618  *    SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx);
619  *
620  * DESCRIPTION
621  *
622  *    Perform special SILC Packet header parsing. This is required to some
623  *    packet types that have the data payload encrypted with different key
624  *    than the header area plus padding of the packet. Hence, this parses
625  *    the header in a way that it does not take the data area into account
626  *    and parses the header and padding area only.
627  *
628  ***/
629 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx);
630
631 /****f* silccore/SilcPacketAPI/silc_packet_context_alloc
632  *
633  * SYNOPSIS
634  *
635  *    SilcPacketContext *silc_packet_context_alloc();
636  *
637  * DESCRIPTION
638  *
639  *    Allocates a packet context. Packet contexts are used when 
640  *    packets are assembled and parsed. The context is freed by the
641  *    silc_packet_context_free function.
642  *
643  ***/
644 SilcPacketContext *silc_packet_context_alloc();
645
646 /****f* silccore/SilcPacketAPI/silc_packet_context_dup
647  *
648  * SYNOPSIS
649  *
650  *    SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx);
651  *
652  * DESCRIPTION
653  *
654  *    Duplicates the packet context. It actually does not duplicate
655  *    any data, instead a reference counter is increased.
656  *
657  ***/
658 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx);
659
660 /****f* silccore/SilcPacketAPI/silc_packet_context_free
661  *
662  * SYNOPSIS
663  *
664  *    void silc_packet_context_free(SilcPacketContext *ctx);
665  *
666  * DESCRIPTION
667  *
668  *    Frees the packet context. The context is actually freed when the
669  *    reference counter hits zero.
670  *
671  ***/
672 void silc_packet_context_free(SilcPacketContext *ctx);
673
674 #endif