updates.
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /*
21  * Created: Fri Jul 25 18:52:14 1997
22  */
23 /* $Id$ */
24
25 #include "silcincludes.h"
26
27 /******************************************************************************
28
29                           Packet Sending Routines
30
31 ******************************************************************************/
32
33 /* Writes data from encrypted buffer to the socket connection. If the
34    data cannot be written at once, it will be written later with a timeout. 
35    The data is written from the data section of the buffer, not from head
36    or tail section. This automatically pulls the data section towards end
37    after writing the data. */
38
39 int silc_packet_write(int sock, SilcBuffer src)
40 {
41   int ret = 0;
42
43   SILC_LOG_DEBUG(("Writing data to socket %d", sock));
44
45   if (src->len > 0) {
46     ret = write(sock, src->data, src->len);
47     if (ret < 0) {
48       if (errno == EAGAIN) {
49         SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
50         return -2;
51       }
52       SILC_LOG_ERROR(("Cannot write to socket: %s", strerror(errno)));
53       return -1;
54     }
55
56     silc_buffer_pull(src, ret);
57   }
58
59   SILC_LOG_DEBUG(("Wrote data %d bytes", ret));
60
61   return ret;
62 }
63
64 /* Actually sends the packet. This flushes the connections outgoing data
65    buffer. If data is sent directly to the network this returns the bytes
66    written, if error occured this returns -1 and if the data could not
67    be written directly to the network at this time this returns -2, in
68    which case the data should be queued by the caller and sent at some
69    later time. If `force_send' is TRUE this attempts to write the data
70    directly to the network, if FALSE, this returns -2. */
71
72 int silc_packet_send(SilcSocketConnection sock, int force_send)
73 {
74   SILC_LOG_DEBUG(("Sending packet to %s:%d [%s]", sock->hostname,
75                   sock->port,  
76                   (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
77                    sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
78                    sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
79                    "Router")));
80
81   /* Send now if forced to do so */
82   if (force_send == TRUE) {
83     int ret;
84
85     SILC_LOG_DEBUG(("Forcing packet send, packet sent immediately"));
86
87     /* Write to network */
88     ret = silc_packet_write(sock->sock, sock->outbuf);
89
90     if (ret == -1) {
91       SILC_LOG_ERROR(("Error sending packet, dropped"));
92     }
93     if (ret != -2)
94       return ret;
95
96     SILC_LOG_DEBUG(("Could not force the send, packet put to queue"));
97   }  
98
99   SILC_LOG_DEBUG(("Packet in queue"));
100
101   return -2;
102 }
103
104 /* Encrypts a packet. This also creates HMAC of the packet before 
105    encryption and adds the HMAC at the end of the buffer. This assumes
106    that there is enough free space at the end of the buffer to add the
107    computed HMAC. This is the normal way of encrypting packets, if some
108    other process of HMAC computing and encryption is needed this function
109    cannot be used. */
110
111 void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, 
112                          SilcBuffer buffer, uint32 len)
113 {
114   unsigned char mac[32];
115   uint32 mac_len;
116
117   /* Compute HMAC. This assumes that HMAC is created from the entire
118      data area thus this uses the length found in buffer, not the length
119      sent as argument. */
120   if (hmac) {
121     silc_hmac_make(hmac, buffer->data, buffer->len, mac, &mac_len);
122     silc_buffer_put_tail(buffer, mac, mac_len);
123     memset(mac, 0, sizeof(mac));
124   }
125
126   /* Encrypt the data area of the packet. 2 bytes of the packet
127      are not encrypted. */
128   if (cipher) {
129     SILC_LOG_DEBUG(("Encrypting packet, cipher %s, len %d (%d)", 
130                     cipher->cipher->name, len, len - 2));
131     cipher->cipher->encrypt(cipher->context, buffer->data + 2, 
132                             buffer->data + 2, len - 2, cipher->iv);
133   }
134
135   /* Pull the HMAC into the visible data area in the buffer */
136   if (hmac)
137     silc_buffer_pull_tail(buffer, mac_len);
138 }
139
140 /* Assembles a new packet to be ready for send out. The buffer sent as
141    argument must include the data to be sent and it must not be encrypted. 
142    The packet also must have enough free space so that the SILC header
143    and padding maybe added to the packet. The packet is encrypted after 
144    this function has returned.
145
146    The buffer sent as argument should be something like following:
147
148    --------------------------------------------
149    | head             | data           | tail |
150    --------------------------------------------
151    ^                  ^
152    58 bytes           x bytes
153
154    So that the SILC header and 1 - 16 bytes of padding can fit to
155    the buffer. After assembly the buffer might look like this:
156
157    --------------------------------------------
158    | data                              |      |
159    --------------------------------------------
160    ^                                   ^
161    Start of assembled packet
162
163    Packet construct is as follows (* = won't be encrypted):
164
165    n bytes       SILC Header
166       2 bytes     Payload length  (*)
167       1 byte      Flags
168       1 byte      Packet type
169       2 bytes     Source ID Length
170       2 bytes     Destination ID Length
171       1 byte      Source ID Type
172       n bytes     Source ID
173       1 byte      Destination ID Type
174       n bytes     Destination ID
175
176    1 - 16 bytes    Padding
177
178    n bytes        Data payload
179
180    All fields in the packet will be authenticated by MAC. The MAC is
181    not computed here, it must be computed separately before encrypting
182    the packet.
183
184 */
185
186 void silc_packet_assemble(SilcPacketContext *ctx)
187 {
188   unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
189   int i;
190
191   SILC_LOG_DEBUG(("Assembling outgoing packet"));
192   
193   /* Get the true length of the packet. This is saved as payload length
194      into the packet header. This does not include the length of the
195      padding. */
196   if (!ctx->truelen)
197     ctx->truelen = ctx->buffer->len + SILC_PACKET_HEADER_LEN + 
198       ctx->src_id_len + ctx->dst_id_len;
199
200   /* Calculate the length of the padding. The padding is calculated from
201      the data that will be encrypted. As protocol states 3 first bytes
202      of the packet are not encrypted they are not included in the
203      padding calculation. */
204   if (!ctx->padlen)
205     ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen);
206
207   /* Put the start of the data section to the right place. */
208   silc_buffer_push(ctx->buffer, SILC_PACKET_HEADER_LEN + 
209                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
210
211   /* Get random padding */
212 #if 1
213   for (i = 0; i < ctx->padlen; i++) tmppad[i] = silc_rng_global_get_byte();
214 #else
215   /* XXX: For testing - to be removed */
216   memset(tmppad, 65, sizeof(tmppad));
217 #endif
218
219   /* Create the packet. This creates the SILC header and adds padding,
220      rest of the buffer remains as it is. */
221   silc_buffer_format(ctx->buffer, 
222                      SILC_STR_UI_SHORT(ctx->truelen),
223                      SILC_STR_UI_CHAR(ctx->flags),
224                      SILC_STR_UI_CHAR(ctx->type),
225                      SILC_STR_UI_SHORT(ctx->src_id_len),
226                      SILC_STR_UI_SHORT(ctx->dst_id_len),
227                      SILC_STR_UI_CHAR(ctx->src_id_type),
228                      SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len),
229                      SILC_STR_UI_CHAR(ctx->dst_id_type),
230                      SILC_STR_UI_XNSTRING(ctx->dst_id, ctx->dst_id_len),
231                      SILC_STR_UI_XNSTRING(tmppad, ctx->padlen),
232                      SILC_STR_END);
233
234   SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len), 
235                    ctx->buffer->data, ctx->buffer->len);
236
237   SILC_LOG_DEBUG(("Outgoing packet assembled"));
238 }
239
240 /* Prepare outgoing data buffer for packet sending. This moves the data
241    area so that new packet may be added into it. If needed this allocates
242    more space to the buffer. This handles directly the connection's
243    outgoing buffer in SilcSocketConnection object. */
244
245 void silc_packet_send_prepare(SilcSocketConnection sock,
246                               uint32 header_len,
247                               uint32 padlen,
248                               uint32 data_len)
249 {
250   int totlen, oldlen;
251
252   totlen = header_len + padlen + data_len;
253
254   /* Prepare the outgoing buffer for packet sending. */
255   if (!sock->outbuf) {
256     /* Allocate new buffer. This is done only once per connection. */
257     SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
258     
259     sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
260     silc_buffer_pull_tail(sock->outbuf, totlen);
261     silc_buffer_pull(sock->outbuf, header_len + padlen);
262   } else {
263     if (SILC_IS_OUTBUF_PENDING(sock)) {
264       /* There is some pending data in the buffer. */
265
266       /* Allocate more space if needed */
267       if ((sock->outbuf->end - sock->outbuf->tail) < 
268           (totlen + 20)) {
269         SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
270         sock->outbuf = silc_buffer_realloc(sock->outbuf, 
271                                            sock->outbuf->truelen +
272                                            (totlen * 2));
273       }
274
275       oldlen = sock->outbuf->len;
276       silc_buffer_pull_tail(sock->outbuf, totlen);
277       silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
278     } else {
279       /* Buffer is free for use */
280       silc_buffer_clear(sock->outbuf);
281
282       /* Allocate more space if needed */
283       if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + 20)) {
284         SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
285         sock->outbuf = silc_buffer_realloc(sock->outbuf, 
286                                            sock->outbuf->truelen + 
287                                            (totlen * 2));
288       }
289
290       silc_buffer_pull_tail(sock->outbuf, totlen);
291       silc_buffer_pull(sock->outbuf, header_len + padlen);
292     }
293   }
294 }
295
296 /******************************************************************************
297
298                          Packet Reception Routines
299
300 ******************************************************************************/
301
302 /* Reads data from the socket connection into the incoming data buffer.
303    However, this does not parse the packet, it only reads some amount from
304    the network. If there are more data available that can be read at a time
305    the rest of the data will be read later with a timeout and only after
306    that the packet is ready to be parsed. 
307
308    The destination buffer sent as argument must be initialized before 
309    calling this function, and, the data section and the start of the tail
310    section must be same. Ie. we add the read data to the tail section of
311    the buffer hence the data section is the start of the buffer.
312
313    This returns amount of bytes read or -1 on error or -2 on case where
314    all of the data could not be read at once. */
315
316 int silc_packet_read(int fd, SilcSocketConnection sock)
317 {
318   int len = 0;
319   unsigned char buf[SILC_PACKET_READ_SIZE];
320
321   SILC_LOG_DEBUG(("Reading data from socket %d", fd));
322
323   /* Read the data from the socket. */
324   len = read(fd, buf, sizeof(buf));
325   if (len < 0) {
326     if (errno == EAGAIN || errno == EINTR) {
327       SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
328       return -2;
329     }
330     SILC_LOG_ERROR(("Cannot read from socket: %d:%s", fd, strerror(errno)));
331     return -1;
332   }
333
334   if (!len)
335     return 0;
336
337   /* Insert the data to the buffer. */
338
339   if (!sock->inbuf)
340     sock->inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
341   
342   /* If the data does not fit to the buffer reallocate it */
343   if ((sock->inbuf->end - sock->inbuf->tail) < len)
344     sock->inbuf = silc_buffer_realloc(sock->inbuf, sock->inbuf->truelen + 
345                                       (len * 2));
346   silc_buffer_put_tail(sock->inbuf, buf, len);
347   silc_buffer_pull_tail(sock->inbuf, len);
348
349   SILC_LOG_DEBUG(("Read %d bytes", len));
350
351   return len;
352 }
353
354 /* Processes the received data. This checks the received data and 
355    calls parser callback that handles the actual packet decryption
356    and parsing. If more than one packet was received this calls the
357    parser multiple times. The parser callback will get context
358    SilcPacketParserContext that includes the packet and the `context'
359    sent to this function. */
360
361 void silc_packet_receive_process(SilcSocketConnection sock,
362                                  SilcCipher cipher, SilcHmac hmac,
363                                  SilcPacketParserCallback parser,
364                                  void *context)
365 {
366   SilcPacketParserContext *parse_ctx;
367   int packetlen, paddedlen, count, mac_len = 0;
368
369   /* We need at least 2 bytes of data to be able to start processing
370      the packet. */
371   if (sock->inbuf->len < 2)
372     return;
373
374   if (hmac)
375     mac_len = hmac->hmac->len;
376
377   /* Parse the packets from the data */
378   count = 0;
379   while (sock->inbuf->len > 0) {
380     SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
381     paddedlen += 2;
382     count++;
383
384     if (packetlen < SILC_PACKET_MIN_LEN) {
385       SILC_LOG_DEBUG(("Received invalid packet, dropped"));
386       silc_buffer_clear(sock->inbuf);
387       return;
388     }
389
390     if (sock->inbuf->len < paddedlen + mac_len) {
391       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"));
392       return;
393     }
394
395     parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
396     parse_ctx->packet = silc_packet_context_alloc();
397     parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
398     parse_ctx->sock = sock;
399     parse_ctx->context = context;
400
401     silc_buffer_pull_tail(parse_ctx->packet->buffer, 
402                           SILC_BUFFER_END(parse_ctx->packet->buffer));
403     silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data, 
404                     paddedlen + mac_len);
405
406     SILC_LOG_HEXDUMP(("Incoming packet, len %d", 
407                       parse_ctx->packet->buffer->len),
408                      parse_ctx->packet->buffer->data, 
409                      parse_ctx->packet->buffer->len);
410
411     /* Call the parser */
412     if (parser)
413       (*parser)(parse_ctx);
414
415     /* Pull the packet from inbuf thus we'll get the next one
416        in the inbuf. */
417     silc_buffer_pull(sock->inbuf, paddedlen);
418     if (hmac)
419       silc_buffer_pull(sock->inbuf, mac_len);
420   }
421
422   SILC_LOG_DEBUG(("Clearing inbound buffer"));
423   silc_buffer_clear(sock->inbuf);
424 }
425
426 /* Receives packet from network and reads the data into connection's
427    incoming data buffer. If the data was read directly this returns the
428    read bytes, if error occured this returns -1, if the data could not
429    be read directly at this time this returns -2 in which case the data
430    should be read again at some later time, or If EOF occured this returns
431    0. */
432
433 int silc_packet_receive(SilcSocketConnection sock)
434 {
435   int ret;
436
437   SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
438                   sock->port, 
439                   (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
440                    sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
441                    sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
442                    "Router")));
443
444   /* Read some data from connection */
445   ret = silc_packet_read(sock->sock, sock);
446
447   return ret;
448 }
449
450 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
451    after packet has been totally decrypted and parsed. */
452
453 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer)
454 {
455   /* Check MAC */
456   if (hmac) {
457     unsigned char mac[32];
458     uint32 mac_len;
459     
460     SILC_LOG_DEBUG(("Verifying MAC"));
461
462     /* Compute HMAC of packet */
463     memset(mac, 0, sizeof(mac));
464     silc_hmac_make(hmac, buffer->data, buffer->len, mac, &mac_len);
465
466     /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
467     if (memcmp(mac, buffer->tail, mac_len)) {
468       SILC_LOG_ERROR(("MAC failed"));
469       return FALSE;
470     }
471     
472     SILC_LOG_DEBUG(("MAC is Ok"));
473     memset(mac, 0, sizeof(mac));
474   }
475   
476   return TRUE;
477 }
478
479 /* Decrypts rest of the packet (after decrypting just the SILC header).
480    After calling this function the packet is ready to be parsed by calling 
481    silc_packet_parse. If everything goes without errors this returns TRUE,
482    if packet is malformed this returns FALSE. */
483
484 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
485                                     SilcBuffer buffer)
486 {
487   if (cipher) {
488
489     /* Pull MAC from packet before decryption */
490     if (hmac) {
491       if ((buffer->len - hmac->hmac->len) > SILC_PACKET_MIN_LEN) {
492         silc_buffer_push_tail(buffer, hmac->hmac->len);
493       } else {
494         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
495         return FALSE;
496       }
497     }
498
499     SILC_LOG_DEBUG(("Decrypting rest of the packet"));
500
501     /* Decrypt rest of the packet */
502     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
503     cipher->cipher->decrypt(cipher->context, buffer->data + 2,
504                             buffer->data + 2, buffer->len - 2,
505                             cipher->iv);
506     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
507
508     SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
509                      buffer->data, buffer->len);
510   }
511
512   return TRUE;
513 }
514
515 /* Decrypts rest of the SILC Packet header that has been decrypted partly
516    already. This decrypts the padding of the packet also. After calling 
517    this function the packet is ready to be parsed by calling function 
518    silc_packet_parse. This is used in special packet reception (protocol
519    defines the way of decrypting special packets). */
520
521 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
522                                             SilcHmac hmac,
523                                             SilcBuffer buffer)
524 {
525   /* Decrypt rest of the header plus padding */
526   if (cipher) {
527     uint16 truelen, len1, len2, padlen;
528
529     /* Pull MAC from packet before decryption */
530     if (hmac) {
531       if ((buffer->len - hmac->hmac->len) > SILC_PACKET_MIN_LEN) {
532         silc_buffer_push_tail(buffer, hmac->hmac->len);
533       } else {
534         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
535         return FALSE;
536       }
537     }
538   
539     SILC_LOG_DEBUG(("Decrypting rest of the header"));
540
541     SILC_GET16_MSB(len1, &buffer->data[4]);
542     SILC_GET16_MSB(len2, &buffer->data[6]);
543
544     truelen = SILC_PACKET_HEADER_LEN + len1 + len2;
545     padlen = SILC_PACKET_PADLEN(truelen);
546     len1 = (truelen + padlen) - (SILC_PACKET_MIN_HEADER_LEN - 2);
547
548     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
549     cipher->cipher->decrypt(cipher->context, buffer->data + 2,
550                             buffer->data + 2, len1 - 2,
551                             cipher->iv);
552     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
553   }
554
555   return TRUE;
556 }
557
558 /* Decrypts a packet. This assumes that typical SILC packet is the
559    packet to be decrypted and thus checks for normal and special SILC
560    packets and can handle both of them. This also computes and checks
561    the HMAC of the packet. If any other special or customized decryption
562    processing is required this function cannot be used. This returns
563    -1 on error, 0 when packet is normal packet and 1 when the packet
564    is special and requires special processing. 
565
566    The `check_packet' is a callback funtion that this function will 
567    call.  The callback relates to the checking whether the packet is
568    normal packet or special packet and how it should be processed.  If
569    the callback return TRUE the packet is normal and FALSE if the packet
570    is special and requires special procesing. */
571
572 int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
573                         SilcBuffer buffer, SilcPacketContext *packet,
574                         SilcPacketCheckDecrypt check_packet,
575                         void *context)
576 {
577   int check;
578
579   /* Decrypt start of the packet header */
580   if (cipher)
581     silc_cipher_decrypt(cipher, buffer->data + 2, buffer->data + 2, 
582                         SILC_PACKET_MIN_HEADER_LEN - 2, cipher->iv);
583
584   /* Do packet checking, whether the packet is normal or special */ 
585   check = check_packet((SilcPacketType)buffer->data[3], buffer,
586                        packet, context);
587
588   /* If the packet type is not any special type lets decrypt rest
589      of the packet here. */
590   if (check == TRUE) {
591     /* Normal packet, decrypt rest of the packet */
592     if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
593       return -1;
594
595     /* Check MAC */
596     if (!silc_packet_check_mac(hmac, buffer))
597       return -1;
598
599     return 0;
600   } else {
601     /* Packet requires special handling, decrypt rest of the header.
602        This only decrypts. */
603     if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
604       return -1;
605
606     /* Check MAC */
607     if (!silc_packet_check_mac(hmac, buffer))
608       return -1;
609
610     return 1;
611   }
612 }
613
614 /* Parses the packet. This is called when a whole packet is ready to be
615    parsed. The buffer sent must be already decrypted before calling this 
616    function. The len argument must be the true length of the packet. This 
617    function returns the type of the packet. The data section of the 
618    buffer is parsed, not head or tail sections. */
619
620 SilcPacketType silc_packet_parse(SilcPacketContext *ctx)
621 {
622   SilcBuffer buffer = ctx->buffer;
623   int len, ret;
624
625   SILC_LOG_DEBUG(("Parsing incoming packet"));
626
627   /* Check the length of the buffer */
628   if (buffer->len < SILC_PACKET_MIN_LEN) {
629     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
630     return SILC_PACKET_NONE;
631   }
632
633   /* Parse the buffer. This parses the SILC header of the packet. */
634   len = silc_buffer_unformat(buffer, 
635                              SILC_STR_UI_SHORT(&ctx->truelen),
636                              SILC_STR_UI_CHAR(&ctx->flags),
637                              SILC_STR_UI_CHAR(&ctx->type),
638                              SILC_STR_UI_SHORT(&ctx->src_id_len),
639                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
640                              SILC_STR_UI_CHAR(&ctx->src_id_type),
641                              SILC_STR_END);
642   if (len == -1)
643     return SILC_PACKET_NONE;
644
645   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
646       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
647     SILC_LOG_ERROR(("Bad ID lengths in packet"));
648     return SILC_PACKET_NONE;
649   }
650
651   /* Calculate length of padding in packet */
652   ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen);
653
654   silc_buffer_pull(buffer, len);
655   ret = silc_buffer_unformat(buffer, 
656                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
657                                                         ctx->src_id_len),
658                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
659                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
660                                                         ctx->dst_id_len),
661                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
662                              SILC_STR_END);
663   if (ret == -1)
664     return SILC_PACKET_NONE;
665
666   silc_buffer_push(buffer, len);
667
668   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
669                    ctx->buffer->data, ctx->buffer->len);
670
671   /* Pull SILC header and padding from packet */
672   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
673                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
674
675   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
676
677   return ctx->type;
678 }
679
680 /* Perform special SILC Packet header parsing. This is required to some
681    packet types that have the data payload encrypted with different key
682    than the header area plus padding of the packet. Hence, this parses
683    the header in a way that it does not take the data area into account
684    and parses the header and padding area only. */
685
686 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx)
687 {
688   SilcBuffer buffer = ctx->buffer;
689   int len, tmplen, ret;
690
691   SILC_LOG_DEBUG(("Parsing incoming packet"));
692
693   /* Check the length of the buffer */
694   if (buffer->len < SILC_PACKET_MIN_LEN) {
695     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
696     return SILC_PACKET_NONE;
697   }
698
699   /* Parse the buffer. This parses the SILC header of the packet. */
700   len = silc_buffer_unformat(buffer, 
701                              SILC_STR_UI_SHORT(&ctx->truelen),
702                              SILC_STR_UI_CHAR(&ctx->flags),
703                              SILC_STR_UI_CHAR(&ctx->type),
704                              SILC_STR_UI_SHORT(&ctx->src_id_len),
705                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
706                              SILC_STR_UI_CHAR(&ctx->src_id_type),
707                              SILC_STR_END);
708   if (len == -1)
709     return SILC_PACKET_NONE;
710
711   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
712       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
713     SILC_LOG_ERROR(("Bad ID lengths in packet"));
714     return SILC_PACKET_NONE;
715   }
716
717   /* Calculate length of padding in packet. As this is special packet
718      the data area is not used in the padding calculation as it won't
719      be decrypted by the caller. */
720   tmplen = SILC_PACKET_HEADER_LEN + ctx->src_id_len + ctx->dst_id_len;
721   ctx->padlen = SILC_PACKET_PADLEN(tmplen);
722
723   silc_buffer_pull(buffer, len);
724   ret = silc_buffer_unformat(buffer, 
725                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
726                                                         ctx->src_id_len),
727                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
728                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
729                                                         ctx->dst_id_len),
730                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
731                              SILC_STR_END);
732   if (ret == -1)
733     return SILC_PACKET_NONE;
734
735   silc_buffer_push(buffer, len);
736
737   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
738                    ctx->buffer->data, ctx->buffer->len);
739
740   /* Pull SILC header and padding from packet */
741   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
742                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
743
744   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
745
746   return ctx->type;
747 }
748
749 /* Allocate packet context */
750
751 SilcPacketContext *silc_packet_context_alloc()
752 {
753   SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
754   ctx->users++;
755   return ctx;
756 }
757
758 /* Increse the reference count of the packet context. */
759
760 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
761 {
762   ctx->users++;
763   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
764                   ctx->users));
765   return ctx;
766 }
767
768 /* Decrese the reference count of the packet context and free it only if
769    it is zero. */
770
771 void silc_packet_context_free(SilcPacketContext *ctx)
772 {
773   ctx->users--;
774   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
775                   ctx->users));
776   if (ctx->users < 1)
777     {
778       if (ctx->buffer)
779         silc_buffer_free(ctx->buffer);
780       if (ctx->src_id)
781         silc_free(ctx->src_id);
782       if (ctx->dst_id)
783         silc_free(ctx->dst_id);
784       silc_free(ctx);
785     }
786 }