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