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) (%dB 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
446       /* XXX Remove */
447       assert(FALSE);
448       return FALSE;
449     }
450     
451     SILC_LOG_DEBUG(("MAC is Ok"));
452     memset(mac, 0, sizeof(mac));
453   }
454   
455   return TRUE;
456 }
457
458 /* Decrypts rest of the packet (after decrypting just the SILC header).
459    After calling this function the packet is ready to be parsed by calling 
460    silc_packet_parse. If everything goes without errors this returns TRUE,
461    if packet is malformed this returns FALSE. */
462
463 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
464                                     SilcBuffer buffer)
465 {
466   if (cipher) {
467
468     /* Pull MAC from packet before decryption */
469     if (hmac) {
470       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
471         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
472       } else {
473         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
474         return FALSE;
475       }
476     }
477
478     SILC_LOG_DEBUG(("Decrypting rest of the packet"));
479
480     /* Decrypt rest of the packet */
481     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
482     silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len, 
483                         cipher->iv);
484     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
485
486     SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
487                      buffer->data, buffer->len);
488   }
489
490   return TRUE;
491 }
492
493 /* Decrypts rest of the SILC Packet header that has been decrypted partly
494    already. This decrypts the padding of the packet also. After calling 
495    this function the packet is ready to be parsed by calling function 
496    silc_packet_parse. This is used in special packet reception (protocol
497    defines the way of decrypting special packets). */
498
499 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
500                                             SilcHmac hmac,
501                                             SilcBuffer buffer)
502 {
503   /* Decrypt rest of the header plus padding */
504   if (cipher) {
505     uint16 len;
506
507     /* Pull MAC from packet before decryption */
508     if (hmac) {
509       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
510         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
511       } else {
512         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
513         return FALSE;
514       }
515     }
516   
517     SILC_LOG_DEBUG(("Decrypting rest of the header"));
518
519     /* padding length + src id len + dst id len + header length - 16
520        bytes already decrypted, gives the rest of the encrypted packet */
521     len = (((uint8)buffer->data[4] + (uint8)buffer->data[6] + 
522            (uint8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
523            SILC_PACKET_MIN_HEADER_LEN);
524
525     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
526     if (len > buffer->len) {
527       SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
528                       "packet dropped"));
529       return FALSE;
530     }
531     silc_cipher_decrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
532     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
533     SILC_LOG_HEXDUMP(("packet, len %d", buffer->len), 
534                      buffer->data, buffer->len);
535   }
536
537   return TRUE;
538 }
539
540 /* Decrypts a packet. This assumes that typical SILC packet is the
541    packet to be decrypted and thus checks for normal and special SILC
542    packets and can handle both of them. This also computes and checks
543    the HMAC of the packet. If any other special or customized decryption
544    processing is required this function cannot be used. This returns
545    -1 on error, 0 when packet is normal packet and 1 when the packet
546    is special and requires special processing. 
547
548    The `check_packet' is a callback funtion that this function will 
549    call.  The callback relates to the checking whether the packet is
550    normal packet or special packet and how it should be processed.  If
551    the callback return TRUE the packet is normal and FALSE if the packet
552    is special and requires special procesing. */
553
554 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
555                                uint32 sequence, SilcBuffer buffer, 
556                                bool normal)
557 {
558   /* If the packet type is not any special type lets decrypt rest
559      of the packet here. */
560   if (normal == TRUE) {
561     /* Normal packet, decrypt rest of the packet */
562     if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
563       return -1;
564
565     /* Check MAC */
566     if (!silc_packet_check_mac(hmac, buffer, sequence))
567       return -1;
568
569     return 0;
570   } else {
571     /* Packet requires special handling, decrypt rest of the header.
572        This only decrypts. */
573     if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
574       return -1;
575
576     /* Check MAC */
577     if (!silc_packet_check_mac(hmac, buffer, sequence))
578       return -1;
579
580     return 1;
581   }
582 }
583
584 /* Parses the packet. This is called when a whole packet is ready to be
585    parsed. The buffer sent must be already decrypted before calling this 
586    function. The len argument must be the true length of the packet. This 
587    function returns the type of the packet. The data section of the 
588    buffer is parsed, not head or tail sections. */
589
590 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
591 {
592   SilcBuffer buffer = ctx->buffer;
593   uint8 tmp;
594   int len, ret;
595
596   SILC_LOG_DEBUG(("Parsing incoming packet"));
597
598   /* Check the length of the buffer */
599   if (buffer->len < SILC_PACKET_MIN_LEN) {
600     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
601     return SILC_PACKET_NONE;
602   }
603
604   /* Parse the buffer. This parses the SILC header of the packet. */
605   len = silc_buffer_unformat(buffer, 
606                              SILC_STR_UI_SHORT(&ctx->truelen),
607                              SILC_STR_UI_CHAR(&ctx->flags),
608                              SILC_STR_UI_CHAR(&ctx->type),
609                              SILC_STR_UI_CHAR(&ctx->padlen),
610                              SILC_STR_UI_CHAR(&tmp),
611                              SILC_STR_UI_CHAR(&ctx->src_id_len),
612                              SILC_STR_UI_CHAR(&ctx->dst_id_len),
613                              SILC_STR_UI_CHAR(&ctx->src_id_type),
614                              SILC_STR_END);
615   if (len == -1 || tmp != 0)
616     return SILC_PACKET_NONE;
617
618   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
619       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
620     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
621                     ctx->src_id_len, ctx->dst_id_len));
622     return SILC_PACKET_NONE;
623   }
624
625   silc_buffer_pull(buffer, len);
626   ret = silc_buffer_unformat(buffer, 
627                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
628                                                         ctx->src_id_len),
629                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
630                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
631                                                         ctx->dst_id_len),
632                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
633                              SILC_STR_END);
634   if (ret == -1)
635     return SILC_PACKET_NONE;
636
637   silc_buffer_push(buffer, len);
638
639   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
640                    ctx->buffer->data, ctx->buffer->len);
641
642   /* Pull SILC header and padding from packet */
643   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
644                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
645
646   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
647
648   return ctx->type;
649 }
650
651 /* Perform special SILC Packet header parsing. This is required to some
652    packet types that have the data payload encrypted with different key
653    than the header area plus padding of the packet. Hence, this parses
654    the header in a way that it does not take the data area into account
655    and parses the header and padding area only. */
656
657 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
658                                          SilcCipher cipher)
659 {
660   SilcBuffer buffer = ctx->buffer;
661   uint8 tmp;
662   int len, ret;
663
664   SILC_LOG_DEBUG(("Parsing incoming packet"));
665
666   /* Check the length of the buffer */
667   if (buffer->len < SILC_PACKET_MIN_LEN) {
668     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
669     return SILC_PACKET_NONE;
670   }
671
672   /* Parse the buffer. This parses the SILC header of the packet. */
673   len = silc_buffer_unformat(buffer, 
674                              SILC_STR_UI_SHORT(&ctx->truelen),
675                              SILC_STR_UI_CHAR(&ctx->flags),
676                              SILC_STR_UI_CHAR(&ctx->type),
677                              SILC_STR_UI_CHAR(&ctx->padlen),
678                              SILC_STR_UI_CHAR(&tmp),
679                              SILC_STR_UI_CHAR(&ctx->src_id_len),
680                              SILC_STR_UI_CHAR(&ctx->dst_id_len),
681                              SILC_STR_UI_CHAR(&ctx->src_id_type),
682                              SILC_STR_END);
683   if (len == -1 || tmp != 0) {
684     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
685     return SILC_PACKET_NONE;
686   }
687
688   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
689       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
690     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
691                     ctx->src_id_len, ctx->dst_id_len));
692     return SILC_PACKET_NONE;
693   }
694
695   silc_buffer_pull(buffer, len);
696   ret = silc_buffer_unformat(buffer, 
697                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
698                                                         ctx->src_id_len),
699                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
700                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
701                                                         ctx->dst_id_len),
702                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
703                              SILC_STR_END);
704   if (ret == -1) {
705     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
706     return SILC_PACKET_NONE;
707   }
708
709   silc_buffer_push(buffer, len);
710
711   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
712                    ctx->buffer->data, ctx->buffer->len);
713
714   /* Pull SILC header and padding from packet */
715   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
716                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
717
718   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
719
720   return ctx->type;
721 }
722
723 /* Allocate packet context */
724
725 SilcPacketContext *silc_packet_context_alloc(void)
726 {
727   SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
728   ctx->users++;
729   return ctx;
730 }
731
732 /* Increse the reference count of the packet context. */
733
734 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
735 {
736   ctx->users++;
737   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
738                   ctx->users));
739   return ctx;
740 }
741
742 /* Decrese the reference count of the packet context and free it only if
743    it is zero. */
744
745 void silc_packet_context_free(SilcPacketContext *ctx)
746 {
747   ctx->users--;
748   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
749                   ctx->users));
750   if (ctx->users < 1)
751     {
752       if (ctx->buffer)
753         silc_buffer_free(ctx->buffer);
754       if (ctx->src_id)
755         silc_free(ctx->src_id);
756       if (ctx->dst_id)
757         silc_free(ctx->dst_id);
758       silc_free(ctx);
759     }
760 }