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