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