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] = silc_rng_global_get_byte();
191 #else
192   /* XXX: For testing - to be removed */
193   memset(tmppad, 65, sizeof(tmppad));
194 #endif
195
196   /* Create the packet. This creates the SILC header and adds padding,
197      rest of the buffer remains as it is. */
198   silc_buffer_format(ctx->buffer, 
199                      SILC_STR_UI_SHORT(ctx->truelen),
200                      SILC_STR_UI_CHAR(ctx->flags),
201                      SILC_STR_UI_CHAR(ctx->type),
202                      SILC_STR_UI_CHAR(ctx->padlen),
203                      SILC_STR_UI_CHAR(0),
204                      SILC_STR_UI_CHAR(ctx->src_id_len),
205                      SILC_STR_UI_CHAR(ctx->dst_id_len),
206                      SILC_STR_UI_CHAR(ctx->src_id_type),
207                      SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len),
208                      SILC_STR_UI_CHAR(ctx->dst_id_type),
209                      SILC_STR_UI_XNSTRING(ctx->dst_id, ctx->dst_id_len),
210                      SILC_STR_UI_XNSTRING(tmppad, ctx->padlen),
211                      SILC_STR_END);
212
213   SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len), 
214                    ctx->buffer->data, ctx->buffer->len);
215
216   SILC_LOG_DEBUG(("Outgoing packet assembled"));
217 }
218
219 /* Prepare outgoing data buffer for packet sending. This moves the data
220    area so that new packet may be added into it. If needed this allocates
221    more space to the buffer. This handles directly the connection's
222    outgoing buffer in SilcSocketConnection object. */
223
224 void silc_packet_send_prepare(SilcSocketConnection sock,
225                               uint32 header_len,
226                               uint32 padlen,
227                               uint32 data_len)
228 {
229   int totlen, oldlen;
230
231   totlen = header_len + padlen + data_len;
232
233   /* Prepare the outgoing buffer for packet sending. */
234   if (!sock->outbuf) {
235     /* Allocate new buffer. This is done only once per connection. */
236     SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
237     
238     if (totlen > SILC_PACKET_DEFAULT_SIZE)
239       sock->outbuf = silc_buffer_alloc(totlen);
240     else
241       sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
242     silc_buffer_pull_tail(sock->outbuf, totlen);
243     silc_buffer_pull(sock->outbuf, header_len + padlen);
244   } else {
245     if (SILC_IS_OUTBUF_PENDING(sock)) {
246       /* There is some pending data in the buffer. */
247
248       /* Allocate more space if needed */
249       if ((sock->outbuf->end - sock->outbuf->tail) < 
250           (totlen + 20)) {
251         SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
252         sock->outbuf = silc_buffer_realloc(sock->outbuf, 
253                                            sock->outbuf->truelen +
254                                            (totlen * 2));
255       }
256
257       oldlen = sock->outbuf->len;
258       silc_buffer_pull_tail(sock->outbuf, totlen);
259       silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
260     } else {
261       /* Buffer is free for use */
262       silc_buffer_clear(sock->outbuf);
263
264       /* Allocate more space if needed */
265       if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + 20)) {
266         SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
267         sock->outbuf = silc_buffer_realloc(sock->outbuf, 
268                                            sock->outbuf->truelen + 
269                                            (totlen * 2));
270       }
271
272       silc_buffer_pull_tail(sock->outbuf, totlen);
273       silc_buffer_pull(sock->outbuf, header_len + padlen);
274     }
275   }
276 }
277
278 /******************************************************************************
279
280                          Packet Reception Routines
281
282 ******************************************************************************/
283
284 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac, 
285                                uint32 sequence, SilcBuffer buffer, 
286                                bool normal);
287
288 /* Receives packet from network and reads the data into connection's
289    incoming data buffer. If the data was read directly this returns the
290    read bytes, if error occured this returns -1, if the data could not
291    be read directly at this time this returns -2 in which case the data
292    should be read again at some later time, or If EOF occured this returns
293    0. */
294
295 int silc_packet_receive(SilcSocketConnection sock)
296 {
297   int ret;
298
299   SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
300                   sock->port, 
301                   (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
302                    sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
303                    sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
304                    "Router")));
305
306   /* Read some data from connection */
307   ret = silc_socket_read(sock);
308
309   return ret;
310 }
311
312 /* Processes and decrypts the incmoing data, and calls parser callback
313    for each received packet that will handle the actual packet parsing.
314    If more than one packet was received this calls the parser multiple
315    times.  The parser callback will get context SilcPacketParserContext
316    that includes the packet and the `parser_context' sent to this
317    function. 
318    
319    The `local_is_router' indicates whether the caller is router server
320    in which case the receiving process of a certain packet types may
321    be special.  Normal server and client must set it to FALSE.  The
322    SilcPacketParserContext will indicate also whether the received
323    packet was normal or special packet. */
324
325 void silc_packet_receive_process(SilcSocketConnection sock,
326                                  bool local_is_router,
327                                  SilcCipher cipher, SilcHmac hmac,
328                                  uint32 sequence,
329                                  SilcPacketParserCallback parser,
330                                  void *parser_context)
331 {
332   SilcPacketParserContext *parse_ctx;
333   int packetlen, paddedlen, mac_len = 0;
334   int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
335
336   if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
337     return;
338
339   if (hmac)
340     mac_len = silc_hmac_len(hmac);
341
342   /* Parse the packets from the data */
343   while (sock->inbuf->len > 0) {
344
345     /* Decrypt first 16 bytes of the packet */
346     if (!SILC_IS_INBUF_PENDING(sock) && cipher)
347       silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data, 
348                           SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
349
350     /* Get packet lenght and full packet length with padding */
351     SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
352
353     /* Sanity checks */
354     if (packetlen < SILC_PACKET_MIN_LEN) {
355       SILC_LOG_DEBUG(("Received invalid packet, dropped"));
356       silc_buffer_clear(sock->inbuf);
357       return;
358     }
359
360     if (sock->inbuf->len < paddedlen + mac_len) {
361       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
362                       "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
363       SILC_SET_INBUF_PENDING(sock);
364       return;
365     }
366
367     SILC_UNSET_INBUF_PENDING(sock);
368     parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
369     parse_ctx->packet = silc_packet_context_alloc();
370     parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
371     parse_ctx->packet->padlen = sock->inbuf->data[4];
372     parse_ctx->packet->sequence = sequence++;
373     parse_ctx->sock = sock;
374     parse_ctx->context = parser_context;
375
376     silc_buffer_pull_tail(parse_ctx->packet->buffer, 
377                           SILC_BUFFER_END(parse_ctx->packet->buffer));
378     silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data, 
379                     paddedlen + mac_len);
380
381     SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d", 
382                       sequence - 1, block_len, paddedlen + mac_len),
383                      sock->inbuf->data, paddedlen + mac_len);
384
385     /* Check whether this is normal or special packet */
386     if (local_is_router) {
387       if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
388           (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
389         parse_ctx->normal = FALSE;
390       else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE || 
391                (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
392                 sock->type == SILC_SOCKET_TYPE_ROUTER))
393         parse_ctx->normal = TRUE;
394     } else {
395       if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
396           (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
397         parse_ctx->normal = FALSE;
398       else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE)
399         parse_ctx->normal = TRUE;
400     }
401
402     /* Decrypt rest of the packet */
403     if (cipher)
404       silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence, 
405                           parse_ctx->packet->buffer, parse_ctx->normal);
406
407     /* Call the parser */
408     if (parser)
409       (*parser)(parse_ctx, parser_context);
410
411     /* Pull the packet from inbuf thus we'll get the next one
412        in the inbuf. */
413     silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
414   }
415
416   SILC_LOG_DEBUG(("Clearing inbound buffer"));
417   silc_buffer_clear(sock->inbuf);
418 }
419
420 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
421    after packet has been totally decrypted and parsed. */
422
423 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
424                                  uint32 sequence)
425 {
426   /* Check MAC */
427   if (hmac) {
428     unsigned char mac[32], psn[4];
429     uint32 mac_len;
430     
431     SILC_LOG_DEBUG(("Verifying MAC"));
432
433     /* Compute HMAC of packet */
434
435     memset(mac, 0, sizeof(mac));
436     silc_hmac_init(hmac);
437     SILC_PUT32_MSB(sequence, psn);
438     silc_hmac_update(hmac, psn, 4);
439     silc_hmac_update(hmac, buffer->data, buffer->len);
440     silc_hmac_final(hmac, mac, &mac_len);
441
442     /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
443     if (memcmp(mac, buffer->tail, mac_len)) {
444       SILC_LOG_ERROR(("MAC failed"));
445       return FALSE;
446     }
447     
448     SILC_LOG_DEBUG(("MAC is Ok"));
449     memset(mac, 0, sizeof(mac));
450   }
451   
452   return TRUE;
453 }
454
455 /* Decrypts rest of the packet (after decrypting just the SILC header).
456    After calling this function the packet is ready to be parsed by calling 
457    silc_packet_parse. If everything goes without errors this returns TRUE,
458    if packet is malformed this returns FALSE. */
459
460 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
461                                     SilcBuffer buffer)
462 {
463   if (cipher) {
464
465     /* Pull MAC from packet before decryption */
466     if (hmac) {
467       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
468         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
469       } else {
470         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
471         return FALSE;
472       }
473     }
474
475     SILC_LOG_DEBUG(("Decrypting rest of the packet"));
476
477     /* Decrypt rest of the packet */
478     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
479     silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len, 
480                         cipher->iv);
481     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
482
483     SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
484                      buffer->data, buffer->len);
485   }
486
487   return TRUE;
488 }
489
490 /* Decrypts rest of the SILC Packet header that has been decrypted partly
491    already. This decrypts the padding of the packet also. After calling 
492    this function the packet is ready to be parsed by calling function 
493    silc_packet_parse. This is used in special packet reception (protocol
494    defines the way of decrypting special packets). */
495
496 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
497                                             SilcHmac hmac,
498                                             SilcBuffer buffer)
499 {
500   /* Decrypt rest of the header plus padding */
501   if (cipher) {
502     uint16 len;
503
504     /* Pull MAC from packet before decryption */
505     if (hmac) {
506       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
507         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
508       } else {
509         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
510         return FALSE;
511       }
512     }
513   
514     SILC_LOG_DEBUG(("Decrypting rest of the header"));
515
516     /* padding length + src id len + dst id len + header length - 16
517        bytes already decrypted, gives the rest of the encrypted packet */
518     len = (((uint8)buffer->data[4] + (uint8)buffer->data[6] + 
519            (uint8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
520            SILC_PACKET_MIN_HEADER_LEN);
521
522     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
523     if (len > buffer->len) {
524       SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
525                       "packet dropped"));
526       return FALSE;
527     }
528     silc_cipher_decrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
529     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
530     SILC_LOG_HEXDUMP(("packet, len %d", buffer->len), 
531                      buffer->data, buffer->len);
532   }
533
534   return TRUE;
535 }
536
537 /* Decrypts a packet. This assumes that typical SILC packet is the
538    packet to be decrypted and thus checks for normal and special SILC
539    packets and can handle both of them. This also computes and checks
540    the HMAC of the packet. If any other special or customized decryption
541    processing is required this function cannot be used. This returns
542    -1 on error, 0 when packet is normal packet and 1 when the packet
543    is special and requires special processing. 
544
545    The `check_packet' is a callback funtion that this function will 
546    call.  The callback relates to the checking whether the packet is
547    normal packet or special packet and how it should be processed.  If
548    the callback return TRUE the packet is normal and FALSE if the packet
549    is special and requires special procesing. */
550
551 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
552                                uint32 sequence, SilcBuffer buffer, 
553                                bool normal)
554 {
555   /* If the packet type is not any special type lets decrypt rest
556      of the packet here. */
557   if (normal == TRUE) {
558     /* Normal packet, decrypt rest of the packet */
559     if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
560       return -1;
561
562     /* Check MAC */
563     if (!silc_packet_check_mac(hmac, buffer, sequence))
564       return -1;
565
566     return 0;
567   } else {
568     /* Packet requires special handling, decrypt rest of the header.
569        This only decrypts. */
570     if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
571       return -1;
572
573     /* Check MAC */
574     if (!silc_packet_check_mac(hmac, buffer, sequence))
575       return -1;
576
577     return 1;
578   }
579 }
580
581 /* Parses the packet. This is called when a whole packet is ready to be
582    parsed. The buffer sent must be already decrypted before calling this 
583    function. The len argument must be the true length of the packet. This 
584    function returns the type of the packet. The data section of the 
585    buffer is parsed, not head or tail sections. */
586
587 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
588 {
589   SilcBuffer buffer = ctx->buffer;
590   uint8 tmp;
591   int len, ret;
592
593   SILC_LOG_DEBUG(("Parsing incoming packet"));
594
595   /* Check the length of the buffer */
596   if (buffer->len < SILC_PACKET_MIN_LEN) {
597     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
598     return SILC_PACKET_NONE;
599   }
600
601   /* Parse the buffer. This parses the SILC header of the packet. */
602   len = silc_buffer_unformat(buffer, 
603                              SILC_STR_UI_SHORT(&ctx->truelen),
604                              SILC_STR_UI_CHAR(&ctx->flags),
605                              SILC_STR_UI_CHAR(&ctx->type),
606                              SILC_STR_UI_CHAR(&ctx->padlen),
607                              SILC_STR_UI_CHAR(&tmp),
608                              SILC_STR_UI_CHAR(&ctx->src_id_len),
609                              SILC_STR_UI_CHAR(&ctx->dst_id_len),
610                              SILC_STR_UI_CHAR(&ctx->src_id_type),
611                              SILC_STR_END);
612   if (len == -1 || tmp != 0)
613     return SILC_PACKET_NONE;
614
615   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
616       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
617     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
618                     ctx->src_id_len, ctx->dst_id_len));
619     return SILC_PACKET_NONE;
620   }
621
622   silc_buffer_pull(buffer, len);
623   ret = silc_buffer_unformat(buffer, 
624                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
625                                                         ctx->src_id_len),
626                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
627                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
628                                                         ctx->dst_id_len),
629                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
630                              SILC_STR_END);
631   if (ret == -1)
632     return SILC_PACKET_NONE;
633
634   silc_buffer_push(buffer, len);
635
636   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
637                    ctx->buffer->data, ctx->buffer->len);
638
639   /* Pull SILC header and padding from packet */
640   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
641                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
642
643   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
644
645   return ctx->type;
646 }
647
648 /* Perform special SILC Packet header parsing. This is required to some
649    packet types that have the data payload encrypted with different key
650    than the header area plus padding of the packet. Hence, this parses
651    the header in a way that it does not take the data area into account
652    and parses the header and padding area only. */
653
654 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
655                                          SilcCipher cipher)
656 {
657   SilcBuffer buffer = ctx->buffer;
658   uint8 tmp;
659   int len, ret;
660
661   SILC_LOG_DEBUG(("Parsing incoming packet"));
662
663   /* Check the length of the buffer */
664   if (buffer->len < SILC_PACKET_MIN_LEN) {
665     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
666     return SILC_PACKET_NONE;
667   }
668
669   /* Parse the buffer. This parses the SILC header of the packet. */
670   len = silc_buffer_unformat(buffer, 
671                              SILC_STR_UI_SHORT(&ctx->truelen),
672                              SILC_STR_UI_CHAR(&ctx->flags),
673                              SILC_STR_UI_CHAR(&ctx->type),
674                              SILC_STR_UI_CHAR(&ctx->padlen),
675                              SILC_STR_UI_CHAR(&tmp),
676                              SILC_STR_UI_CHAR(&ctx->src_id_len),
677                              SILC_STR_UI_CHAR(&ctx->dst_id_len),
678                              SILC_STR_UI_CHAR(&ctx->src_id_type),
679                              SILC_STR_END);
680   if (len == -1 || tmp != 0) {
681     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
682     return SILC_PACKET_NONE;
683   }
684
685   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
686       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
687     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
688                     ctx->src_id_len, ctx->dst_id_len));
689     return SILC_PACKET_NONE;
690   }
691
692   silc_buffer_pull(buffer, len);
693   ret = silc_buffer_unformat(buffer, 
694                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
695                                                         ctx->src_id_len),
696                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
697                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
698                                                         ctx->dst_id_len),
699                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
700                              SILC_STR_END);
701   if (ret == -1) {
702     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
703     return SILC_PACKET_NONE;
704   }
705
706   silc_buffer_push(buffer, len);
707
708   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
709                    ctx->buffer->data, ctx->buffer->len);
710
711   /* Pull SILC header and padding from packet */
712   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
713                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
714
715   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
716
717   return ctx->type;
718 }
719
720 /* Allocate packet context */
721
722 SilcPacketContext *silc_packet_context_alloc(void)
723 {
724   SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
725   ctx->users++;
726   return ctx;
727 }
728
729 /* Increse the reference count of the packet context. */
730
731 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
732 {
733   ctx->users++;
734   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
735                   ctx->users));
736   return ctx;
737 }
738
739 /* Decrese the reference count of the packet context and free it only if
740    it is zero. */
741
742 void silc_packet_context_free(SilcPacketContext *ctx)
743 {
744   ctx->users--;
745   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
746                   ctx->users));
747   if (ctx->users < 1)
748     {
749       if (ctx->buffer)
750         silc_buffer_free(ctx->buffer);
751       if (ctx->src_id)
752         silc_free(ctx->src_id);
753       if (ctx->dst_id)
754         silc_free(ctx->dst_id);
755       silc_free(ctx);
756     }
757 }