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