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