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