5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
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.
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.
20 * Created: Fri Jul 25 18:52:14 1997
24 #include "silcincludes.h"
26 /******************************************************************************
28 Packet Sending Routines
30 ******************************************************************************/
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. */
40 int silc_packet_send(SilcSocketConnection sock, bool force_send)
42 SILC_LOG_DEBUG(("Sending packet to %s:%d [%s]", sock->hostname,
44 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
45 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
46 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
49 /* Send now if forced to do so */
50 if (force_send == TRUE) {
53 SILC_LOG_DEBUG(("Forcing packet send, packet sent immediately"));
55 /* Write to network */
56 ret = silc_socket_write(sock);
59 SILC_LOG_ERROR(("Error sending packet, dropped"));
64 SILC_LOG_DEBUG(("Could not force the send, packet put to queue"));
67 SILC_LOG_DEBUG(("Packet in queue"));
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
79 void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, uint32 sequence,
80 SilcBuffer buffer, uint32 len)
82 unsigned char mac[32];
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
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));
100 /* Encrypt the data area of the packet. */
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);
107 /* Pull the HMAC into the visible data area in the buffer */
109 silc_buffer_pull_tail(buffer, mac_len);
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.
118 The buffer sent as argument should be something like following:
120 --------------------------------------------
121 | head | data | tail |
122 --------------------------------------------
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:
129 --------------------------------------------
131 --------------------------------------------
133 Start of assembled packet
135 Packet construct is as follows:
138 2 bytes Payload length
141 1 byte Padding length
143 1 bytes Source ID Length
144 1 bytes Destination ID Length
145 1 byte Source ID Type
147 1 byte Destination ID Type
148 n bytes Destination ID
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
160 void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher)
162 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
163 int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
166 SILC_LOG_DEBUG(("Assembling outgoing packet"));
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
172 ctx->truelen = ctx->buffer->len + SILC_PACKET_HEADER_LEN +
173 ctx->src_id_len + ctx->dst_id_len;
175 /* Calculate the length of the padding. The padding is calculated from
176 the data that will be encrypted. */
179 ctx->padlen = SILC_PACKET_PADLEN_MAX(ctx->truelen);
181 ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len);
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);
188 /* Get random padding */
190 for (i = 0; i < ctx->padlen; i++) tmppad[i] =
191 silc_rng_global_get_byte_fast();
193 /* XXX: For testing - to be removed */
194 memset(tmppad, 65, sizeof(tmppad));
197 /* Create the packet. This creates the SILC header and adds padding,
198 rest of the buffer remains as it is. */
199 silc_buffer_format(ctx->buffer,
200 SILC_STR_UI_SHORT(ctx->truelen),
201 SILC_STR_UI_CHAR(ctx->flags),
202 SILC_STR_UI_CHAR(ctx->type),
203 SILC_STR_UI_CHAR(ctx->padlen),
205 SILC_STR_UI_CHAR(ctx->src_id_len),
206 SILC_STR_UI_CHAR(ctx->dst_id_len),
207 SILC_STR_UI_CHAR(ctx->src_id_type),
208 SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len),
209 SILC_STR_UI_CHAR(ctx->dst_id_type),
210 SILC_STR_UI_XNSTRING(ctx->dst_id, ctx->dst_id_len),
211 SILC_STR_UI_XNSTRING(tmppad, ctx->padlen),
214 SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len),
215 ctx->buffer->data, ctx->buffer->len);
217 SILC_LOG_DEBUG(("Outgoing packet assembled"));
220 /* Prepare outgoing data buffer for packet sending. This moves the data
221 area so that new packet may be added into it. If needed this allocates
222 more space to the buffer. This handles directly the connection's
223 outgoing buffer in SilcSocketConnection object. */
225 void silc_packet_send_prepare(SilcSocketConnection sock,
232 totlen = header_len + padlen + data_len;
234 /* Prepare the outgoing buffer for packet sending. */
236 /* Allocate new buffer. This is done only once per connection. */
237 SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
239 if (totlen > SILC_PACKET_DEFAULT_SIZE)
240 sock->outbuf = silc_buffer_alloc(totlen);
242 sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
243 silc_buffer_pull_tail(sock->outbuf, totlen);
244 silc_buffer_pull(sock->outbuf, header_len + padlen);
246 if (SILC_IS_OUTBUF_PENDING(sock)) {
247 /* There is some pending data in the buffer. */
249 /* Allocate more space if needed */
250 if ((sock->outbuf->end - sock->outbuf->tail) <
252 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
253 sock->outbuf = silc_buffer_realloc(sock->outbuf,
254 sock->outbuf->truelen +
258 oldlen = sock->outbuf->len;
259 silc_buffer_pull_tail(sock->outbuf, totlen);
260 silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
262 /* Buffer is free for use */
263 silc_buffer_clear(sock->outbuf);
265 /* Allocate more space if needed */
266 if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + 20)) {
267 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
268 sock->outbuf = silc_buffer_realloc(sock->outbuf,
269 sock->outbuf->truelen +
273 silc_buffer_pull_tail(sock->outbuf, totlen);
274 silc_buffer_pull(sock->outbuf, header_len + padlen);
279 /******************************************************************************
281 Packet Reception Routines
283 ******************************************************************************/
285 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
286 uint32 sequence, SilcBuffer buffer,
289 /* Receives packet from network and reads the data into connection's
290 incoming data buffer. If the data was read directly this returns the
291 read bytes, if error occured this returns -1, if the data could not
292 be read directly at this time this returns -2 in which case the data
293 should be read again at some later time, or If EOF occured this returns
296 int silc_packet_receive(SilcSocketConnection sock)
300 SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
302 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
303 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
304 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
307 /* Read some data from connection */
308 ret = silc_socket_read(sock);
313 /* Processes and decrypts the incmoing data, and calls parser callback
314 for each received packet that will handle the actual packet parsing.
315 If more than one packet was received this calls the parser multiple
316 times. The parser callback will get context SilcPacketParserContext
317 that includes the packet and the `parser_context' sent to this
320 The `local_is_router' indicates whether the caller is router server
321 in which case the receiving process of a certain packet types may
322 be special. Normal server and client must set it to FALSE. The
323 SilcPacketParserContext will indicate also whether the received
324 packet was normal or special packet. */
326 bool silc_packet_receive_process(SilcSocketConnection sock,
327 bool local_is_router,
328 SilcCipher cipher, SilcHmac hmac,
330 SilcPacketParserCallback parser,
331 void *parser_context)
333 SilcPacketParserContext *parse_ctx;
334 int packetlen, paddedlen, mac_len = 0;
337 /* Do not process for disconnected connection */
338 if (SILC_IS_DISCONNECTED(sock))
341 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
345 mac_len = silc_hmac_len(hmac);
347 /* Parse the packets from the data */
348 while (sock->inbuf->len > 0 && cont) {
350 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
351 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
355 /* Decrypt first 16 bytes of the packet */
356 if (!SILC_IS_INBUF_PENDING(sock) && cipher)
357 silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data,
358 SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
360 /* Get packet lenght and full packet length with padding */
361 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
364 if (packetlen < SILC_PACKET_MIN_LEN) {
365 SILC_LOG_DEBUG(("Received invalid packet, dropped"));
366 silc_buffer_clear(sock->inbuf);
370 if (sock->inbuf->len < paddedlen + mac_len) {
371 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
372 "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
373 SILC_SET_INBUF_PENDING(sock);
377 SILC_UNSET_INBUF_PENDING(sock);
378 parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
379 parse_ctx->packet = silc_packet_context_alloc();
380 parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
381 parse_ctx->packet->type = sock->inbuf->data[3];
382 parse_ctx->packet->padlen = sock->inbuf->data[4];
383 parse_ctx->packet->sequence = sequence++;
384 parse_ctx->sock = sock;
385 parse_ctx->context = parser_context;
387 silc_buffer_pull_tail(parse_ctx->packet->buffer,
388 SILC_BUFFER_END(parse_ctx->packet->buffer));
389 silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data,
390 paddedlen + mac_len);
392 SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d",
393 sequence - 1, SILC_PACKET_MIN_HEADER_LEN,
394 paddedlen + mac_len),
395 sock->inbuf->data, paddedlen + mac_len);
397 /* Check whether this is normal or special packet */
398 if (local_is_router) {
399 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
400 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
401 parse_ctx->normal = FALSE;
402 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE ||
403 (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
404 sock->type == SILC_SOCKET_TYPE_ROUTER))
405 parse_ctx->normal = TRUE;
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 parse_ctx->normal = TRUE;
414 /* Decrypt rest of the packet */
416 if (silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
417 parse_ctx->packet->buffer,
418 parse_ctx->normal) == -1) {
419 SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s]",
420 sock->hostname, sock->port,
421 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
422 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
423 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
427 /* Pull the packet from inbuf thus we'll get the next one
429 silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
431 /* Call the parser */
432 cont = (*parser)(parse_ctx, parser_context);
435 if (cont == FALSE && sock->inbuf->len > 0)
438 SILC_LOG_DEBUG(("Clearing inbound buffer"));
439 silc_buffer_clear(sock->inbuf);
443 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
444 after packet has been totally decrypted and parsed. */
446 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
451 unsigned char mac[32], psn[4];
454 SILC_LOG_DEBUG(("Verifying MAC"));
456 /* Compute HMAC of packet */
458 memset(mac, 0, sizeof(mac));
459 silc_hmac_init(hmac);
460 SILC_PUT32_MSB(sequence, psn);
461 silc_hmac_update(hmac, psn, 4);
462 silc_hmac_update(hmac, buffer->data, buffer->len);
463 silc_hmac_final(hmac, mac, &mac_len);
465 /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
466 if (memcmp(buffer->tail, mac, mac_len)) {
467 SILC_LOG_ERROR(("MAC failed"));
471 SILC_LOG_DEBUG(("MAC is Ok"));
472 memset(mac, 0, sizeof(mac));
478 /* Decrypts rest of the packet (after decrypting just the SILC header).
479 After calling this function the packet is ready to be parsed by calling
480 silc_packet_parse. If everything goes without errors this returns TRUE,
481 if packet is malformed this returns FALSE. */
483 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
488 /* Pull MAC from packet before decryption */
490 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
491 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
493 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
498 SILC_LOG_DEBUG(("Decrypting rest of the packet"));
500 /* Decrypt rest of the packet */
501 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
502 silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len,
504 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
506 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
507 buffer->data, buffer->len);
513 /* Decrypts rest of the SILC Packet header that has been decrypted partly
514 already. This decrypts the padding of the packet also. After calling
515 this function the packet is ready to be parsed by calling function
516 silc_packet_parse. This is used in special packet reception (protocol
517 defines the way of decrypting special packets). */
519 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
523 /* Decrypt rest of the header plus padding */
527 /* Pull MAC from packet before decryption */
529 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
530 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
532 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
537 SILC_LOG_DEBUG(("Decrypting rest of the header"));
539 /* padding length + src id len + dst id len + header length - 16
540 bytes already decrypted, gives the rest of the encrypted packet */
541 len = (((uint8)buffer->data[4] + (uint8)buffer->data[6] +
542 (uint8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
543 SILC_PACKET_MIN_HEADER_LEN);
545 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
546 if (len > buffer->len) {
547 SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
551 silc_cipher_decrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
552 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
553 SILC_LOG_HEXDUMP(("packet, len %d", buffer->len),
554 buffer->data, buffer->len);
560 /* Decrypts a packet. This assumes that typical SILC packet is the
561 packet to be decrypted and thus checks for normal and special SILC
562 packets and can handle both of them. This also computes and checks
563 the HMAC of the packet. If any other special or customized decryption
564 processing is required this function cannot be used. This returns
565 -1 on error, 0 when packet is normal packet and 1 when the packet
566 is special and requires special processing.
568 The `check_packet' is a callback funtion that this function will
569 call. The callback relates to the checking whether the packet is
570 normal packet or special packet and how it should be processed. If
571 the callback return TRUE the packet is normal and FALSE if the packet
572 is special and requires special procesing. */
574 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
575 uint32 sequence, SilcBuffer buffer,
578 /* If the packet type is not any special type lets decrypt rest
579 of the packet here. */
580 if (normal == TRUE) {
581 /* Normal packet, decrypt rest of the packet */
582 if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
586 if (!silc_packet_check_mac(hmac, buffer, sequence))
591 /* Packet requires special handling, decrypt rest of the header.
592 This only decrypts. */
593 if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
597 if (!silc_packet_check_mac(hmac, buffer, sequence))
604 /* Parses the packet. This is called when a whole packet is ready to be
605 parsed. The buffer sent must be already decrypted before calling this
606 function. The len argument must be the true length of the packet. This
607 function returns the type of the packet. The data section of the
608 buffer is parsed, not head or tail sections. */
610 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
612 SilcBuffer buffer = ctx->buffer;
616 SILC_LOG_DEBUG(("Parsing incoming packet"));
618 /* Check the length of the buffer */
619 if (buffer->len < SILC_PACKET_MIN_LEN) {
620 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
621 return SILC_PACKET_NONE;
624 /* Parse the buffer. This parses the SILC header of the packet. */
625 len = silc_buffer_unformat(buffer,
626 SILC_STR_UI_SHORT(&ctx->truelen),
627 SILC_STR_UI_CHAR(&ctx->flags),
628 SILC_STR_UI_CHAR(&ctx->type),
629 SILC_STR_UI_CHAR(&ctx->padlen),
630 SILC_STR_UI_CHAR(&tmp),
631 SILC_STR_UI_CHAR(&ctx->src_id_len),
632 SILC_STR_UI_CHAR(&ctx->dst_id_len),
633 SILC_STR_UI_CHAR(&ctx->src_id_type),
635 if (len == -1 || tmp != 0)
636 return SILC_PACKET_NONE;
638 if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
639 ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
640 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
641 ctx->src_id_len, ctx->dst_id_len));
642 return SILC_PACKET_NONE;
645 silc_buffer_pull(buffer, len);
646 ret = silc_buffer_unformat(buffer,
647 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
649 SILC_STR_UI_CHAR(&ctx->dst_id_type),
650 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
652 SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
655 return SILC_PACKET_NONE;
657 silc_buffer_push(buffer, len);
659 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
660 ctx->buffer->data, ctx->buffer->len);
662 /* Pull SILC header and padding from packet */
663 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
664 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
666 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
671 /* Perform special SILC Packet header parsing. This is required to some
672 packet types that have the data payload encrypted with different key
673 than the header area plus padding of the packet. Hence, this parses
674 the header in a way that it does not take the data area into account
675 and parses the header and padding area only. */
677 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
680 SilcBuffer buffer = ctx->buffer;
684 SILC_LOG_DEBUG(("Parsing incoming packet"));
686 /* Check the length of the buffer */
687 if (buffer->len < SILC_PACKET_MIN_LEN) {
688 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
689 return SILC_PACKET_NONE;
692 /* Parse the buffer. This parses the SILC header of the packet. */
693 len = silc_buffer_unformat(buffer,
694 SILC_STR_UI_SHORT(&ctx->truelen),
695 SILC_STR_UI_CHAR(&ctx->flags),
696 SILC_STR_UI_CHAR(&ctx->type),
697 SILC_STR_UI_CHAR(&ctx->padlen),
698 SILC_STR_UI_CHAR(&tmp),
699 SILC_STR_UI_CHAR(&ctx->src_id_len),
700 SILC_STR_UI_CHAR(&ctx->dst_id_len),
701 SILC_STR_UI_CHAR(&ctx->src_id_type),
703 if (len == -1 || tmp != 0) {
704 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
705 return SILC_PACKET_NONE;
708 if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
709 ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
710 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
711 ctx->src_id_len, ctx->dst_id_len));
712 return SILC_PACKET_NONE;
715 silc_buffer_pull(buffer, len);
716 ret = silc_buffer_unformat(buffer,
717 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
719 SILC_STR_UI_CHAR(&ctx->dst_id_type),
720 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
722 SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
725 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
726 return SILC_PACKET_NONE;
729 silc_buffer_push(buffer, len);
731 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
732 ctx->buffer->data, ctx->buffer->len);
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);
738 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
743 /* Allocate packet context */
745 SilcPacketContext *silc_packet_context_alloc(void)
747 SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
752 /* Increse the reference count of the packet context. */
754 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
757 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
762 /* Decrese the reference count of the packet context and free it only if
765 void silc_packet_context_free(SilcPacketContext *ctx)
768 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
773 silc_buffer_free(ctx->buffer);
775 silc_free(ctx->src_id);
777 silc_free(ctx->dst_id);