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