udpates.
[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   bool cont = TRUE;
336   
337   if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
338     return;
339
340   if (hmac)
341     mac_len = silc_hmac_len(hmac);
342
343   /* Parse the packets from the data */
344   while (sock->inbuf->len > 0 && cont) {
345
346     /* Decrypt first 16 bytes of the packet */
347     if (!SILC_IS_INBUF_PENDING(sock) && cipher)
348       silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data, 
349                           SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
350
351     /* Get packet lenght and full packet length with padding */
352     SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
353
354     /* Sanity checks */
355     if (packetlen < SILC_PACKET_MIN_LEN) {
356       SILC_LOG_DEBUG(("Received invalid packet, dropped"));
357       silc_buffer_clear(sock->inbuf);
358       return;
359     }
360
361     if (sock->inbuf->len < paddedlen + mac_len) {
362       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
363                       "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
364       SILC_SET_INBUF_PENDING(sock);
365       return;
366     }
367
368     SILC_UNSET_INBUF_PENDING(sock);
369     parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
370     parse_ctx->packet = silc_packet_context_alloc();
371     parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
372     parse_ctx->packet->padlen = sock->inbuf->data[4];
373     parse_ctx->packet->sequence = sequence++;
374     parse_ctx->sock = sock;
375     parse_ctx->context = parser_context;
376
377     silc_buffer_pull_tail(parse_ctx->packet->buffer, 
378                           SILC_BUFFER_END(parse_ctx->packet->buffer));
379     silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data, 
380                     paddedlen + mac_len);
381
382     SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d", 
383                       sequence - 1, block_len, paddedlen + mac_len),
384                      sock->inbuf->data, paddedlen + mac_len);
385
386     /* Check whether this is normal or special packet */
387     if (local_is_router) {
388       if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
389           (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
390         parse_ctx->normal = FALSE;
391       else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE || 
392                (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
393                 sock->type == SILC_SOCKET_TYPE_ROUTER))
394         parse_ctx->normal = TRUE;
395     } else {
396       if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
397           (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
398         parse_ctx->normal = FALSE;
399       else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE)
400         parse_ctx->normal = TRUE;
401     }
402
403     /* Decrypt rest of the packet */
404     if (cipher)
405       silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence, 
406                           parse_ctx->packet->buffer, parse_ctx->normal);
407
408     /* Pull the packet from inbuf thus we'll get the next one
409        in the inbuf. */
410     silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
411
412     /* Call the parser */
413     cont = (*parser)(parse_ctx, parser_context);
414   }
415
416   if (cont == FALSE && sock->inbuf->len > 0)
417     return;
418
419   SILC_LOG_DEBUG(("Clearing inbound buffer"));
420   silc_buffer_clear(sock->inbuf);
421 }
422
423 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
424    after packet has been totally decrypted and parsed. */
425
426 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
427                                  uint32 sequence)
428 {
429   /* Check MAC */
430   if (hmac) {
431     unsigned char mac[32], psn[4];
432     uint32 mac_len;
433     
434     SILC_LOG_DEBUG(("Verifying MAC"));
435
436     /* Compute HMAC of packet */
437
438     memset(mac, 0, sizeof(mac));
439     silc_hmac_init(hmac);
440     SILC_PUT32_MSB(sequence, psn);
441     silc_hmac_update(hmac, psn, 4);
442     silc_hmac_update(hmac, buffer->data, buffer->len);
443     silc_hmac_final(hmac, mac, &mac_len);
444
445     /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
446     if (memcmp(mac, buffer->tail, mac_len)) {
447       SILC_LOG_ERROR(("MAC failed"));
448
449       /* XXX Remove */
450       assert(FALSE);
451       return FALSE;
452     }
453     
454     SILC_LOG_DEBUG(("MAC is Ok"));
455     memset(mac, 0, sizeof(mac));
456   }
457   
458   return TRUE;
459 }
460
461 /* Decrypts rest of the packet (after decrypting just the SILC header).
462    After calling this function the packet is ready to be parsed by calling 
463    silc_packet_parse. If everything goes without errors this returns TRUE,
464    if packet is malformed this returns FALSE. */
465
466 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
467                                     SilcBuffer buffer)
468 {
469   if (cipher) {
470
471     /* Pull MAC from packet before decryption */
472     if (hmac) {
473       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
474         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
475       } else {
476         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
477         return FALSE;
478       }
479     }
480
481     SILC_LOG_DEBUG(("Decrypting rest of the packet"));
482
483     /* Decrypt rest of the packet */
484     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
485     silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len, 
486                         cipher->iv);
487     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
488
489     SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
490                      buffer->data, buffer->len);
491   }
492
493   return TRUE;
494 }
495
496 /* Decrypts rest of the SILC Packet header that has been decrypted partly
497    already. This decrypts the padding of the packet also. After calling 
498    this function the packet is ready to be parsed by calling function 
499    silc_packet_parse. This is used in special packet reception (protocol
500    defines the way of decrypting special packets). */
501
502 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
503                                             SilcHmac hmac,
504                                             SilcBuffer buffer)
505 {
506   /* Decrypt rest of the header plus padding */
507   if (cipher) {
508     uint16 len;
509
510     /* Pull MAC from packet before decryption */
511     if (hmac) {
512       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
513         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
514       } else {
515         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
516         return FALSE;
517       }
518     }
519   
520     SILC_LOG_DEBUG(("Decrypting rest of the header"));
521
522     /* padding length + src id len + dst id len + header length - 16
523        bytes already decrypted, gives the rest of the encrypted packet */
524     len = (((uint8)buffer->data[4] + (uint8)buffer->data[6] + 
525            (uint8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
526            SILC_PACKET_MIN_HEADER_LEN);
527
528     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
529     if (len > buffer->len) {
530       SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
531                       "packet dropped"));
532       return FALSE;
533     }
534     silc_cipher_decrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
535     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
536     SILC_LOG_HEXDUMP(("packet, len %d", buffer->len), 
537                      buffer->data, buffer->len);
538   }
539
540   return TRUE;
541 }
542
543 /* Decrypts a packet. This assumes that typical SILC packet is the
544    packet to be decrypted and thus checks for normal and special SILC
545    packets and can handle both of them. This also computes and checks
546    the HMAC of the packet. If any other special or customized decryption
547    processing is required this function cannot be used. This returns
548    -1 on error, 0 when packet is normal packet and 1 when the packet
549    is special and requires special processing. 
550
551    The `check_packet' is a callback funtion that this function will 
552    call.  The callback relates to the checking whether the packet is
553    normal packet or special packet and how it should be processed.  If
554    the callback return TRUE the packet is normal and FALSE if the packet
555    is special and requires special procesing. */
556
557 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
558                                uint32 sequence, SilcBuffer buffer, 
559                                bool normal)
560 {
561   /* If the packet type is not any special type lets decrypt rest
562      of the packet here. */
563   if (normal == TRUE) {
564     /* Normal packet, decrypt rest of the packet */
565     if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
566       return -1;
567
568     /* Check MAC */
569     if (!silc_packet_check_mac(hmac, buffer, sequence))
570       return -1;
571
572     return 0;
573   } else {
574     /* Packet requires special handling, decrypt rest of the header.
575        This only decrypts. */
576     if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
577       return -1;
578
579     /* Check MAC */
580     if (!silc_packet_check_mac(hmac, buffer, sequence))
581       return -1;
582
583     return 1;
584   }
585 }
586
587 /* Parses the packet. This is called when a whole packet is ready to be
588    parsed. The buffer sent must be already decrypted before calling this 
589    function. The len argument must be the true length of the packet. This 
590    function returns the type of the packet. The data section of the 
591    buffer is parsed, not head or tail sections. */
592
593 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
594 {
595   SilcBuffer buffer = ctx->buffer;
596   uint8 tmp;
597   int len, ret;
598
599   SILC_LOG_DEBUG(("Parsing incoming packet"));
600
601   /* Check the length of the buffer */
602   if (buffer->len < SILC_PACKET_MIN_LEN) {
603     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
604     return SILC_PACKET_NONE;
605   }
606
607   /* Parse the buffer. This parses the SILC header of the packet. */
608   len = silc_buffer_unformat(buffer, 
609                              SILC_STR_UI_SHORT(&ctx->truelen),
610                              SILC_STR_UI_CHAR(&ctx->flags),
611                              SILC_STR_UI_CHAR(&ctx->type),
612                              SILC_STR_UI_CHAR(&ctx->padlen),
613                              SILC_STR_UI_CHAR(&tmp),
614                              SILC_STR_UI_CHAR(&ctx->src_id_len),
615                              SILC_STR_UI_CHAR(&ctx->dst_id_len),
616                              SILC_STR_UI_CHAR(&ctx->src_id_type),
617                              SILC_STR_END);
618   if (len == -1 || tmp != 0)
619     return SILC_PACKET_NONE;
620
621   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
622       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
623     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
624                     ctx->src_id_len, ctx->dst_id_len));
625     return SILC_PACKET_NONE;
626   }
627
628   silc_buffer_pull(buffer, len);
629   ret = silc_buffer_unformat(buffer, 
630                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
631                                                         ctx->src_id_len),
632                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
633                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
634                                                         ctx->dst_id_len),
635                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
636                              SILC_STR_END);
637   if (ret == -1)
638     return SILC_PACKET_NONE;
639
640   silc_buffer_push(buffer, len);
641
642   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
643                    ctx->buffer->data, ctx->buffer->len);
644
645   /* Pull SILC header and padding from packet */
646   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
647                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
648
649   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
650
651   return ctx->type;
652 }
653
654 /* Perform special SILC Packet header parsing. This is required to some
655    packet types that have the data payload encrypted with different key
656    than the header area plus padding of the packet. Hence, this parses
657    the header in a way that it does not take the data area into account
658    and parses the header and padding area only. */
659
660 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
661                                          SilcCipher cipher)
662 {
663   SilcBuffer buffer = ctx->buffer;
664   uint8 tmp;
665   int len, ret;
666
667   SILC_LOG_DEBUG(("Parsing incoming packet"));
668
669   /* Check the length of the buffer */
670   if (buffer->len < SILC_PACKET_MIN_LEN) {
671     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
672     return SILC_PACKET_NONE;
673   }
674
675   /* Parse the buffer. This parses the SILC header of the packet. */
676   len = silc_buffer_unformat(buffer, 
677                              SILC_STR_UI_SHORT(&ctx->truelen),
678                              SILC_STR_UI_CHAR(&ctx->flags),
679                              SILC_STR_UI_CHAR(&ctx->type),
680                              SILC_STR_UI_CHAR(&ctx->padlen),
681                              SILC_STR_UI_CHAR(&tmp),
682                              SILC_STR_UI_CHAR(&ctx->src_id_len),
683                              SILC_STR_UI_CHAR(&ctx->dst_id_len),
684                              SILC_STR_UI_CHAR(&ctx->src_id_type),
685                              SILC_STR_END);
686   if (len == -1 || tmp != 0) {
687     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
688     return SILC_PACKET_NONE;
689   }
690
691   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
692       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
693     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
694                     ctx->src_id_len, ctx->dst_id_len));
695     return SILC_PACKET_NONE;
696   }
697
698   silc_buffer_pull(buffer, len);
699   ret = silc_buffer_unformat(buffer, 
700                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
701                                                         ctx->src_id_len),
702                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
703                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
704                                                         ctx->dst_id_len),
705                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
706                              SILC_STR_END);
707   if (ret == -1) {
708     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
709     return SILC_PACKET_NONE;
710   }
711
712   silc_buffer_push(buffer, len);
713
714   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
715                    ctx->buffer->data, ctx->buffer->len);
716
717   /* Pull SILC header and padding from packet */
718   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
719                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
720
721   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
722
723   return ctx->type;
724 }
725
726 /* Allocate packet context */
727
728 SilcPacketContext *silc_packet_context_alloc(void)
729 {
730   SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
731   ctx->users++;
732   return ctx;
733 }
734
735 /* Increse the reference count of the packet context. */
736
737 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
738 {
739   ctx->users++;
740   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
741                   ctx->users));
742   return ctx;
743 }
744
745 /* Decrese the reference count of the packet context and free it only if
746    it is zero. */
747
748 void silc_packet_context_free(SilcPacketContext *ctx)
749 {
750   ctx->users--;
751   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
752                   ctx->users));
753   if (ctx->users < 1)
754     {
755       if (ctx->buffer)
756         silc_buffer_free(ctx->buffer);
757       if (ctx->src_id)
758         silc_free(ctx->src_id);
759       if (ctx->dst_id)
760         silc_free(ctx->dst_id);
761       silc_free(ctx);
762     }
763 }