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    x bytes       SILC Header
166       2 bytes     Payload length  (*)
167       1 byte      Flags
168       1 byte      Packet type
169       1 byte      Source ID Type
170       2 bytes     Source ID Length
171       x bytes     Source ID
172       1 byte      Destination ID Type
173       2 bytes     Destination ID Length
174       x bytes     Destination ID
175
176    1 - 16 bytes    Padding
177
178    x 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 differently 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) < data_len) {
268         SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
269         sock->outbuf = silc_buffer_realloc(sock->outbuf, 
270                                            sock->outbuf->truelen + totlen);
271       }
272
273       oldlen = sock->outbuf->len;
274       silc_buffer_pull_tail(sock->outbuf, totlen);
275       silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
276     } else {
277       /* Buffer is free for use */
278       silc_buffer_clear(sock->outbuf);
279       silc_buffer_pull_tail(sock->outbuf, totlen);
280       silc_buffer_pull(sock->outbuf, header_len + padlen);
281     }
282   }
283 }
284
285 /******************************************************************************
286
287                          Packet Reception Routines
288
289 ******************************************************************************/
290
291 /* Reads data from the socket connection into the incoming data buffer.
292    However, this does not parse the packet, it only reads some amount from
293    the network. If there are more data available that can be read at a time
294    the rest of the data will be read later with a timeout and only after
295    that the packet is ready to be parsed. 
296
297    The destination buffer sent as argument must be initialized before 
298    calling this function, and, the data section and the start of the tail
299    section must be same. Ie. we add the read data to the tail section of
300    the buffer hence the data section is the start of the buffer.
301
302    This returns amount of bytes read or -1 on error or -2 on case where
303    all of the data could not be read at once. */
304
305 int silc_packet_read(int sock, SilcBuffer dest)
306 {
307   int len = 0;
308   unsigned char buf[SILC_PACKET_READ_SIZE];
309
310   SILC_LOG_DEBUG(("Reading data from socket %d", sock));
311
312   /* Read the data from the socket. */
313   len = read(sock, buf, sizeof(buf));
314   if (len < 0) {
315     if (errno == EAGAIN || errno == EINTR) {
316       SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
317       return -2;
318     }
319     SILC_LOG_ERROR(("Cannot read from socket: %d:%s", sock, strerror(errno)));
320     return -1;
321   }
322
323   if (!len)
324     return 0;
325
326   /* Insert the data to the buffer. If the data doesn't fit to the 
327      buffer space is allocated for the buffer. */
328   /* XXX: This may actually be bad thing as if there is pending data in
329      the buffer they will be lost! */
330   if (dest) {
331
332     /* If the data doesn't fit we just have to allocate a whole new 
333        data area */
334     if (dest->truelen <= len) {
335
336       /* Free the old buffer */
337       memset(dest->head, 'F', dest->truelen);
338       silc_free(dest->head);
339
340       /* Allocate new data area */
341       len += SILC_PACKET_DEFAULT_SIZE;
342       dest->data = silc_calloc(len, sizeof(char));
343       dest->truelen = len;
344       dest->len = 0;
345       dest->head = dest->data;
346       dest->data = dest->data;
347       dest->tail = dest->data;
348       dest->end = dest->data + dest->truelen;
349       len -= SILC_PACKET_DEFAULT_SIZE;
350     }
351
352     silc_buffer_put_tail(dest, buf, len);
353     silc_buffer_pull_tail(dest, len);
354   }
355
356   SILC_LOG_DEBUG(("Read %d bytes", len));
357
358   return len;
359 }
360
361 /* Processes the received data. This checks the received data and 
362    calls parser callback that handles the actual packet decryption
363    and parsing. If more than one packet was received this calls the
364    parser multiple times. The parser callback will get context
365    SilcPacketParserContext that includes the packet and the `context'
366    sent to this function. */
367
368 void silc_packet_receive_process(SilcSocketConnection sock,
369                                  SilcCipher cipher, SilcHmac hmac,
370                                  SilcPacketParserCallback parser,
371                                  void *context)
372 {
373   SilcPacketParserContext *parse_ctx;
374   int packetlen, paddedlen, count, mac_len = 0;
375
376   /* We need at least 2 bytes of data to be able to start processing
377      the packet. */
378   if (sock->inbuf->len < 2)
379     return;
380
381   if (hmac)
382     mac_len = hmac->hmac->len;
383
384   /* Parse the packets from the data */
385   count = 0;
386   while (sock->inbuf->len > 0) {
387     SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
388     paddedlen += 2;
389     count++;
390
391     if (packetlen < SILC_PACKET_MIN_LEN) {
392       SILC_LOG_DEBUG(("Received invalid packet, dropped"));
393       silc_buffer_clear(sock->inbuf);
394       return;
395     }
396
397     if (sock->inbuf->len < paddedlen + mac_len) {
398       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"));
399       return;
400     }
401
402     parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
403     parse_ctx->packet = silc_packet_context_alloc();
404     parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
405     parse_ctx->sock = sock;
406     parse_ctx->cipher = cipher;
407     parse_ctx->hmac = hmac;
408     parse_ctx->context = context;
409
410     silc_buffer_pull_tail(parse_ctx->packet->buffer, 
411                           SILC_BUFFER_END(parse_ctx->packet->buffer));
412     silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data, 
413                     paddedlen + mac_len);
414
415     SILC_LOG_HEXDUMP(("Incoming packet, len %d", 
416                       parse_ctx->packet->buffer->len),
417                      parse_ctx->packet->buffer->data, 
418                      parse_ctx->packet->buffer->len);
419
420     /* Call the parser */
421     if (parser)
422       (*parser)(parse_ctx);
423
424     /* Pull the packet from inbuf thus we'll get the next one
425        in the inbuf. */
426     silc_buffer_pull(sock->inbuf, paddedlen);
427     if (hmac)
428       silc_buffer_pull(sock->inbuf, mac_len);
429   }
430
431   SILC_LOG_DEBUG(("Clearing inbound buffer"));
432   silc_buffer_clear(sock->inbuf);
433 }
434
435 /* Receives packet from network and reads the data into connection's
436    incoming data buffer. If the data was read directly this returns the
437    read bytes, if error occured this returns -1, if the data could not
438    be read directly at this time this returns -2 in which case the data
439    should be read again at some later time, or If EOF occured this returns
440    0. */
441
442 int silc_packet_receive(SilcSocketConnection sock)
443 {
444   int ret;
445
446   SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
447                   sock->port, 
448                   (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
449                    sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
450                    sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
451                    "Router")));
452
453   /* Allocate the incoming data buffer if not done already. */
454   if (!sock->inbuf)
455     sock->inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
456
457   /* Read some data from connection */
458   ret = silc_packet_read(sock->sock, sock->inbuf);
459
460   return ret;
461 }
462
463 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
464    after packet has been totally decrypted and parsed. */
465
466 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer)
467 {
468   /* Check MAC */
469   if (hmac) {
470     unsigned char mac[32];
471     uint32 mac_len;
472     
473     SILC_LOG_DEBUG(("Verifying MAC"));
474
475     /* Compute HMAC of packet */
476     memset(mac, 0, sizeof(mac));
477     silc_hmac_make(hmac, buffer->data, buffer->len, mac, &mac_len);
478
479     /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
480     if (memcmp(mac, buffer->tail, mac_len)) {
481       SILC_LOG_ERROR(("MAC failed"));
482       assert(FALSE);
483       return FALSE;
484     }
485     
486     SILC_LOG_DEBUG(("MAC is Ok"));
487     memset(mac, 0, sizeof(mac));
488   }
489   
490   return TRUE;
491 }
492
493 /* Decrypts rest of the packet (after decrypting just the SILC header).
494    After calling this function the packet is ready to be parsed by calling 
495    silc_packet_parse. If everything goes without errors this returns TRUE,
496    if packet is malformed this returns FALSE. */
497
498 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
499                                     SilcBuffer buffer)
500 {
501   if (cipher) {
502
503     /* Pull MAC from packet before decryption */
504     if (hmac) {
505       if ((buffer->len - hmac->hmac->len) > SILC_PACKET_MIN_LEN) {
506         silc_buffer_push_tail(buffer, hmac->hmac->len);
507       } else {
508         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
509         return FALSE;
510       }
511     }
512
513     SILC_LOG_DEBUG(("Decrypting rest of the packet"));
514
515     /* Decrypt rest of the packet */
516     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
517     cipher->cipher->decrypt(cipher->context, buffer->data + 2,
518                             buffer->data + 2, buffer->len - 2,
519                             cipher->iv);
520     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
521
522     SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
523                      buffer->data, buffer->len);
524   }
525
526   return TRUE;
527 }
528
529 /* Decrypts rest of the SILC Packet header that has been decrypted partly
530    already. This decrypts the padding of the packet also. After calling 
531    this function the packet is ready to be parsed by calling function 
532    silc_packet_parse. This is used in special packet reception (protocol
533    defines the way of decrypting special packets). */
534
535 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
536                                             SilcHmac hmac,
537                                             SilcBuffer buffer)
538 {
539   /* Decrypt rest of the header plus padding */
540   if (cipher) {
541     uint16 truelen, len1, len2, padlen;
542
543     /* Pull MAC from packet before decryption */
544     if (hmac) {
545       if ((buffer->len - hmac->hmac->len) > SILC_PACKET_MIN_LEN) {
546         silc_buffer_push_tail(buffer, hmac->hmac->len);
547       } else {
548         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
549         return FALSE;
550       }
551     }
552   
553     SILC_LOG_DEBUG(("Decrypting rest of the header"));
554
555     SILC_GET16_MSB(len1, &buffer->data[4]);
556     SILC_GET16_MSB(len2, &buffer->data[6]);
557
558     truelen = SILC_PACKET_HEADER_LEN + len1 + len2;
559     padlen = SILC_PACKET_PADLEN(truelen);
560     len1 = (truelen + padlen) - (SILC_PACKET_MIN_HEADER_LEN - 2);
561
562     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
563     cipher->cipher->decrypt(cipher->context, buffer->data + 2,
564                             buffer->data + 2, len1 - 2,
565                             cipher->iv);
566     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN - 2);
567   }
568
569   return TRUE;
570 }
571
572 /* Decrypts a packet. This assumes that typical SILC packet is the
573    packet to be decrypted and thus checks for normal and special SILC
574    packets and can handle both of them. This also computes and checks
575    the HMAC of the packet. If any other special or customized decryption
576    processing is required this function cannot be used. This returns
577    -1 on error, 0 when packet is normal packet and 1 when the packet
578    is special and requires special processing. 
579
580    The `check_packet' is a callback funtion that this function will 
581    call.  The callback relates to the checking whether the packet is
582    normal packet or special packet and how it should be processed.  If
583    the callback return TRUE the packet is normal and FALSE if the packet
584    is special and requires special procesing. */
585
586 int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
587                         SilcBuffer buffer, SilcPacketContext *packet,
588                         SilcPacketCheckDecrypt check_packet,
589                         void *context)
590 {
591   int check;
592
593   /* Decrypt start of the packet header */
594   if (cipher)
595     silc_cipher_decrypt(cipher, buffer->data + 2, buffer->data + 2, 
596                         SILC_PACKET_MIN_HEADER_LEN - 2, cipher->iv);
597
598   /* Do packet checking, whether the packet is normal or special */ 
599   check = check_packet((SilcPacketType)buffer->data[3], buffer,
600                        packet, context);
601
602   /* If the packet type is not any special type lets decrypt rest
603      of the packet here. */
604   if (check == TRUE) {
605     /* Normal packet, decrypt rest of the packet */
606     if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
607       return -1;
608
609     /* Check MAC */
610     if (!silc_packet_check_mac(hmac, buffer))
611       return -1;
612
613     return 0;
614   } else {
615     /* Packet requires special handling, decrypt rest of the header.
616        This only decrypts. */
617     if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
618       return -1;
619
620     /* Check MAC */
621     if (!silc_packet_check_mac(hmac, buffer))
622       return -1;
623
624     return 1;
625   }
626 }
627
628 /* Parses the packet. This is called when a whole packet is ready to be
629    parsed. The buffer sent must be already decrypted before calling this 
630    function. The len argument must be the true length of the packet. This 
631    function returns the type of the packet. The data section of the 
632    buffer is parsed, not head or tail sections. */
633
634 SilcPacketType silc_packet_parse(SilcPacketContext *ctx)
635 {
636   SilcBuffer buffer = ctx->buffer;
637   int len, ret;
638
639   SILC_LOG_DEBUG(("Parsing incoming packet"));
640
641   /* Check the length of the buffer */
642   if (buffer->len < SILC_PACKET_MIN_LEN) {
643     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
644     return SILC_PACKET_NONE;
645   }
646
647   /* Parse the buffer. This parses the SILC header of the packet. */
648   len = silc_buffer_unformat(buffer, 
649                              SILC_STR_UI_SHORT(&ctx->truelen),
650                              SILC_STR_UI_CHAR(&ctx->flags),
651                              SILC_STR_UI_CHAR(&ctx->type),
652                              SILC_STR_UI_SHORT(&ctx->src_id_len),
653                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
654                              SILC_STR_UI_CHAR(&ctx->src_id_type),
655                              SILC_STR_END);
656   if (len == -1)
657     return SILC_PACKET_NONE;
658
659   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
660       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
661     SILC_LOG_ERROR(("Bad ID lengths in packet"));
662     return SILC_PACKET_NONE;
663   }
664
665   /* Calculate length of padding in packet */
666   ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen);
667
668   silc_buffer_pull(buffer, len);
669   ret = silc_buffer_unformat(buffer, 
670                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
671                                                         ctx->src_id_len),
672                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
673                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
674                                                         ctx->dst_id_len),
675                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
676                              SILC_STR_END);
677   if (ret == -1)
678     return SILC_PACKET_NONE;
679
680   silc_buffer_push(buffer, len);
681
682   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
683                    ctx->buffer->data, ctx->buffer->len);
684
685   /* Pull SILC header and padding from packet */
686   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
687                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
688
689   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
690
691   return ctx->type;
692 }
693
694 /* Perform special SILC Packet header parsing. This is required to some
695    packet types that have the data payload encrypted with different key
696    than the header area plus padding of the packet. Hence, this parses
697    the header in a way that it does not take the data area into account
698    and parses the header and padding area only. */
699
700 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx)
701 {
702   SilcBuffer buffer = ctx->buffer;
703   int len, tmplen, ret;
704
705   SILC_LOG_DEBUG(("Parsing incoming packet"));
706
707   /* Check the length of the buffer */
708   if (buffer->len < SILC_PACKET_MIN_LEN) {
709     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
710     return SILC_PACKET_NONE;
711   }
712
713   /* Parse the buffer. This parses the SILC header of the packet. */
714   len = silc_buffer_unformat(buffer, 
715                              SILC_STR_UI_SHORT(&ctx->truelen),
716                              SILC_STR_UI_CHAR(&ctx->flags),
717                              SILC_STR_UI_CHAR(&ctx->type),
718                              SILC_STR_UI_SHORT(&ctx->src_id_len),
719                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
720                              SILC_STR_UI_CHAR(&ctx->src_id_type),
721                              SILC_STR_END);
722   if (len == -1)
723     return SILC_PACKET_NONE;
724
725   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
726       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
727     SILC_LOG_ERROR(("Bad ID lengths in packet"));
728     return SILC_PACKET_NONE;
729   }
730
731   /* Calculate length of padding in packet. As this is special packet
732      the data area is not used in the padding calculation as it won't
733      be decrypted by the caller. */
734   tmplen = SILC_PACKET_HEADER_LEN + ctx->src_id_len + ctx->dst_id_len;
735   ctx->padlen = SILC_PACKET_PADLEN(tmplen);
736
737   silc_buffer_pull(buffer, len);
738   ret = silc_buffer_unformat(buffer, 
739                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
740                                                         ctx->src_id_len),
741                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
742                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
743                                                         ctx->dst_id_len),
744                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
745                              SILC_STR_END);
746   if (ret == -1)
747     return SILC_PACKET_NONE;
748
749   silc_buffer_push(buffer, len);
750
751   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
752                    ctx->buffer->data, ctx->buffer->len);
753
754   /* Pull SILC header and padding from packet */
755   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
756                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
757
758   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
759
760   return ctx->type;
761 }
762
763 /* Allocate packet context */
764
765 SilcPacketContext *silc_packet_context_alloc()
766 {
767   SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
768   ctx->users++;
769   return ctx;
770 }
771
772 /* Increse the reference count of the packet context. */
773
774 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
775 {
776   ctx->users++;
777   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
778                   ctx->users));
779   return ctx;
780 }
781
782 /* Decrese the reference count of the packet context and free it only if
783    it is zero. */
784
785 void silc_packet_context_free(SilcPacketContext *ctx)
786 {
787   ctx->users--;
788   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
789                   ctx->users));
790   if (ctx->users < 1)
791     {
792       if (ctx->buffer)
793         silc_buffer_free(ctx->buffer);
794       if (ctx->src_id)
795         silc_free(ctx->src_id);
796       if (ctx->dst_id)
797         silc_free(ctx->dst_id);
798       silc_free(ctx);
799     }
800 }