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