5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2003 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: %s",
65 SILC_LOG_DEBUG(("Could not force the send, packet put to queue"));
68 SILC_LOG_DEBUG(("Packet in queue"));
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
80 void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, SilcUInt32 sequence,
81 SilcBuffer buffer, SilcUInt32 len)
84 /* Encrypt the data area of the packet. */
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);
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
95 unsigned char mac[32], psn[4];
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);
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);
110 /* Assembles a new packet to be ready for send out. */
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)
118 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
119 unsigned int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
122 SILC_LOG_DEBUG(("Assembling outgoing packet"));
124 /* Calculate the packet's length and padding length if upper layer
125 didn't already do it. */
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
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;
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);
143 SILC_PACKET_PADLEN(packet->truelen, block_len, packet->padlen);
146 /* Now prepare the outgoing data buffer for packet sending and start
147 assembling the packet. */
149 /* Return pointer to the assembled packet */
150 if (!silc_packet_send_prepare(sock, packet->truelen - data_len,
151 packet->padlen, data_len, hmac,
155 /* Get random padding */
157 for (i = 0; i < packet->padlen; i++) tmppad[i] =
158 silc_rng_get_byte_fast(rng);
160 for (i = 0; i < packet->padlen; i++) tmppad[i] =
161 silc_rng_global_get_byte_fast();
163 /* Create the packet. This creates the SILC header, adds padding, and
164 the actual packet data. */
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),
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,
177 SILC_STR_UI_CHAR(packet->dst_id_type),
178 SILC_STR_UI_XNSTRING(packet->dst_id,
180 SILC_STR_UI_XNSTRING(tmppad, packet->padlen),
181 SILC_STR_UI_XNSTRING(data, data_len),
186 SILC_LOG_HEXDUMP(("Assembled packet, len %d", assembled_packet->len),
187 assembled_packet->data, assembled_packet->len);
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'. */
198 bool silc_packet_send_prepare(SilcSocketConnection sock,
199 SilcUInt32 header_len,
203 const SilcBuffer packet)
206 unsigned char *oldptr;
207 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
212 totlen = header_len + pad_len + data_len;
214 /* Prepare the outgoing buffer for packet sending. */
216 /* Allocate new buffer. This is done only once per connection. */
217 SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
219 sock->outbuf = silc_buffer_alloc(totlen > SILC_PACKET_DEFAULT_SIZE ?
220 totlen : SILC_PACKET_DEFAULT_SIZE);
224 if (!SILC_IS_OUTBUF_PENDING(sock)) {
225 /* Buffer is free for use */
226 silc_buffer_clear(sock->outbuf);
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));
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);
248 /******************************************************************************
250 Packet Reception Routines
252 ******************************************************************************/
254 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
255 SilcUInt32 sequence, SilcBuffer buffer,
257 static bool silc_packet_check_mac(SilcHmac hmac,
258 const unsigned char *data,
260 const unsigned char *packet_mac,
261 SilcUInt32 sequence);
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
270 int silc_packet_receive(SilcSocketConnection sock)
274 SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
276 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
277 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
278 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
281 /* Read some data from connection */
282 ret = silc_socket_read(sock);
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
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. */
300 bool silc_packet_receive_process(SilcSocketConnection sock,
301 bool local_is_router,
302 SilcCipher cipher, SilcHmac hmac,
304 SilcPacketParserCallback parser,
305 void *parser_context)
307 SilcPacketParserContext *parse_ctx;
308 SilcUInt16 packetlen;
309 SilcUInt32 paddedlen, mac_len = 0, block_len;
312 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
313 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
315 /* Do not process for disconnected connection */
316 if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
319 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
323 mac_len = silc_hmac_len(hmac);
325 /* Parse the packets from the data */
326 silc_socket_dup(sock);
327 while (sock->inbuf->len > 0 && cont) {
329 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
330 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
331 silc_socket_free(sock);
335 /* Decrypt first block of the packet to get the length field out */
337 block_len = silc_cipher_get_block_len(cipher);
338 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
339 silc_cipher_decrypt(cipher, sock->inbuf->data, tmp, block_len, iv);
342 block_len = SILC_PACKET_MIN_HEADER_LEN;
343 header = sock->inbuf->data;
346 /* Get packet lenght and full packet length with padding */
347 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
350 if (packetlen < SILC_PACKET_MIN_LEN) {
351 SILC_LOG_ERROR(("Received too short packet"));
352 memset(header, 0, sizeof(header));
353 silc_buffer_clear(sock->inbuf);
354 silc_socket_free(sock);
358 if (sock->inbuf->len < paddedlen + mac_len) {
359 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
360 "(%d bytes)", paddedlen + mac_len - sock->inbuf->len));
361 SILC_SET_INBUF_PENDING(sock);
362 memset(tmp, 0, sizeof(tmp));
363 silc_socket_free(sock);
367 /* Check MAC of the packet */
368 if (!silc_packet_check_mac(hmac, sock->inbuf->data, paddedlen,
369 sock->inbuf->data + paddedlen, sequence)) {
370 SILC_LOG_WARNING(("Packet MAC check failed %s:%d "
371 "[%s type %d len %dB blen %dB seq %d] [%s] proto %d",
372 sock->hostname, sock->port,
373 silc_get_packet_name(header[3]),
374 header[3], paddedlen, sock->inbuf->len, sequence,
375 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
376 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
377 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
379 sock->protocol ? sock->protocol->protocol->type : -1));
380 memset(tmp, 0, sizeof(tmp));
381 silc_buffer_clear(sock->inbuf);
382 silc_socket_free(sock);
386 SILC_UNSET_INBUF_PENDING(sock);
387 parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
389 silc_socket_free(sock);
392 parse_ctx->packet = silc_packet_context_alloc();
393 parse_ctx->packet->buffer = silc_buffer_alloc_size(paddedlen);
394 parse_ctx->packet->type = (SilcPacketType)header[3];
395 parse_ctx->packet->padlen = (SilcUInt8)header[4];
396 parse_ctx->packet->sequence = sequence++;
397 parse_ctx->sock = sock;
398 parse_ctx->context = parser_context;
400 /* Check whether this is normal or special packet */
401 if (local_is_router) {
402 if (header[3] == SILC_PACKET_PRIVATE_MESSAGE &&
403 (header[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
404 parse_ctx->normal = FALSE;
405 else if (header[3] != SILC_PACKET_CHANNEL_MESSAGE ||
406 (header[3] == SILC_PACKET_CHANNEL_MESSAGE &&
407 sock->type == SILC_SOCKET_TYPE_ROUTER))
408 parse_ctx->normal = TRUE;
410 if (header[3] == SILC_PACKET_PRIVATE_MESSAGE &&
411 (header[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
412 parse_ctx->normal = FALSE;
413 else if (header[3] != SILC_PACKET_CHANNEL_MESSAGE)
414 parse_ctx->normal = TRUE;
417 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
418 sequence - 1, paddedlen + mac_len),
419 sock->inbuf->data, paddedlen + mac_len);
421 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
422 silc_buffer_put(parse_ctx->packet->buffer, header, block_len);
423 silc_buffer_pull(parse_ctx->packet->buffer, block_len);
424 silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data + block_len,
425 paddedlen - block_len);
427 silc_cipher_set_iv(cipher, iv);
428 ret = silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
429 parse_ctx->packet->buffer,
432 SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s] [%s]",
433 sock->hostname, sock->port,
434 silc_get_packet_name(parse_ctx->packet->type),
435 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
436 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
437 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
439 memset(tmp, 0, sizeof(tmp));
440 silc_packet_context_free(parse_ctx->packet);
441 silc_free(parse_ctx);
442 silc_socket_free(sock);
446 silc_buffer_push(parse_ctx->packet->buffer, block_len);
448 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d",
449 parse_ctx->packet->buffer->len),
450 parse_ctx->packet->buffer->data,
451 parse_ctx->packet->buffer->len);
453 /* Pull the packet from inbuf thus we'll get the next one
455 silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
457 /* Call the parser */
458 cont = (*parser)(parse_ctx, parser_context);
460 /* See if socket disconnected while parsing the packet */
461 if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
462 SILC_LOG_DEBUG(("Abandoning packet processing, socket disconnected"));
466 memset(tmp, 0, sizeof(tmp));
469 /* Don't clear buffer if pending data is in the buffer */
470 if (cont == FALSE && sock->inbuf->len > 0) {
471 silc_socket_free(sock);
475 /* Don't clear buffer if QoS data exists in the buffer */
476 if (sock->qos && sock->qos->data_len > 0) {
477 silc_socket_free(sock);
481 SILC_LOG_DEBUG(("Clearing inbound buffer"));
482 silc_buffer_clear(sock->inbuf);
483 silc_socket_free(sock);
487 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
489 static bool silc_packet_check_mac(SilcHmac hmac,
490 const unsigned char *data,
492 const unsigned char *packet_mac,
497 unsigned char mac[32], psn[4];
500 SILC_LOG_DEBUG(("Verifying MAC"));
502 /* Compute HMAC of packet */
503 silc_hmac_init(hmac);
504 SILC_PUT32_MSB(sequence, psn);
505 silc_hmac_update(hmac, psn, 4);
506 silc_hmac_update(hmac, data, data_len);
507 silc_hmac_final(hmac, mac, &mac_len);
509 /* Compare the MAC's */
510 if (memcmp(packet_mac, mac, mac_len)) {
511 SILC_LOG_ERROR(("MAC failed"));
515 SILC_LOG_DEBUG(("MAC is Ok"));
521 /* Decrypts SILC packet. Handles both normal and special packet decryption.
522 Return 0 when packet is normal and 1 when it it special, -1 on error. */
524 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
525 SilcUInt32 sequence, SilcBuffer buffer,
528 /* If the packet type is not any special type lets decrypt rest
529 of the packet here. */
530 if (normal == TRUE) {
532 /* Decrypt rest of the packet */
533 SILC_LOG_DEBUG(("Decrypting the packet"));
534 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
535 buffer->len, NULL)) {
536 SILC_LOG_ERROR(("silc_cipher_decrypt failed"));
543 /* Decrypt rest of the header plus padding */
546 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
548 SILC_LOG_DEBUG(("Decrypting the header"));
550 /* padding length + src id len + dst id len + header length - 16
551 bytes already decrypted, gives the rest of the encrypted packet */
552 silc_buffer_push(buffer, block_len);
553 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
554 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
556 silc_buffer_pull(buffer, block_len);
558 if (len > buffer->len) {
559 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
563 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
565 SILC_LOG_ERROR(("silc_cipher_decrypt failed"));
574 /* Parses the packet. This is called when a whole packet is ready to be
575 parsed. The buffer sent must be already decrypted before calling this
576 function. The len argument must be the true length of the packet. This
577 function returns the type of the packet. The data section of the
578 buffer is parsed, not head or tail sections. */
580 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
582 SilcBuffer buffer = ctx->buffer;
585 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
587 SILC_LOG_DEBUG(("Parsing incoming packet"));
589 /* Check the length of the buffer */
590 if (buffer->len < SILC_PACKET_MIN_LEN) {
591 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
592 return SILC_PACKET_NONE;
595 /* Parse the buffer. This parses the SILC header of the packet. */
596 len = silc_buffer_unformat(buffer,
597 SILC_STR_UI_SHORT(&ctx->truelen),
598 SILC_STR_UI_CHAR(&ctx->flags),
599 SILC_STR_UI_CHAR(&ctx->type),
600 SILC_STR_UI_CHAR(&padlen),
601 SILC_STR_UI_CHAR(&tmp),
602 SILC_STR_UI_CHAR(&src_id_len),
603 SILC_STR_UI_CHAR(&dst_id_len),
604 SILC_STR_UI_CHAR(&src_id_type),
606 if (len == -1 || tmp != 0)
607 return SILC_PACKET_NONE;
609 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
610 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
611 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
612 src_id_len, dst_id_len));
613 return SILC_PACKET_NONE;
616 silc_buffer_pull(buffer, len);
617 ret = silc_buffer_unformat(buffer,
618 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
620 SILC_STR_UI_CHAR(&dst_id_type),
621 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
623 SILC_STR_UI_XNSTRING(NULL, padlen),
626 return SILC_PACKET_NONE;
628 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
629 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
630 src_id_type, dst_id_type));
631 return SILC_PACKET_NONE;
634 ctx->src_id_len = src_id_len;
635 ctx->dst_id_len = dst_id_len;
636 ctx->src_id_type = src_id_type;
637 ctx->dst_id_type = dst_id_type;
638 ctx->padlen = padlen;
640 silc_buffer_push(buffer, len);
642 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
643 ctx->buffer->data, ctx->buffer->len);
645 /* Pull SILC header and padding from packet */
646 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
647 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
649 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
654 /* Perform special SILC Packet header parsing. This is required to some
655 packet types that have the data payload encrypted with different key
656 than the header area plus padding of the packet. Hence, this parses
657 the header in a way that it does not take the data area into account
658 and parses the header and padding area only. */
660 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
663 SilcBuffer buffer = ctx->buffer;
666 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
668 SILC_LOG_DEBUG(("Parsing incoming packet"));
670 /* Check the length of the buffer */
671 if (buffer->len < SILC_PACKET_MIN_LEN) {
672 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
673 return SILC_PACKET_NONE;
676 /* Parse the buffer. This parses the SILC header of the packet. */
677 len = silc_buffer_unformat(buffer,
678 SILC_STR_UI_SHORT(&ctx->truelen),
679 SILC_STR_UI_CHAR(&ctx->flags),
680 SILC_STR_UI_CHAR(&ctx->type),
681 SILC_STR_UI_CHAR(&padlen),
682 SILC_STR_UI_CHAR(&tmp),
683 SILC_STR_UI_CHAR(&src_id_len),
684 SILC_STR_UI_CHAR(&dst_id_len),
685 SILC_STR_UI_CHAR(&src_id_type),
687 if (len == -1 || tmp != 0) {
688 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
689 return SILC_PACKET_NONE;
692 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
693 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
694 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
695 src_id_len, dst_id_len));
696 return SILC_PACKET_NONE;
699 silc_buffer_pull(buffer, len);
700 ret = silc_buffer_unformat(buffer,
701 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
703 SILC_STR_UI_CHAR(&dst_id_type),
704 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
706 SILC_STR_UI_XNSTRING(NULL, padlen),
709 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
710 return SILC_PACKET_NONE;
713 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
714 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
715 src_id_type, dst_id_type));
716 return SILC_PACKET_NONE;
719 ctx->src_id_len = src_id_len;
720 ctx->dst_id_len = dst_id_len;
721 ctx->src_id_type = src_id_type;
722 ctx->dst_id_type = dst_id_type;
723 ctx->padlen = padlen;
725 silc_buffer_push(buffer, len);
727 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
728 ctx->buffer->data, ctx->buffer->len);
730 /* Pull SILC header and padding from packet */
731 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
732 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
734 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
739 /* Allocate packet context */
741 SilcPacketContext *silc_packet_context_alloc(void)
743 SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
750 /* Increse the reference count of the packet context. */
752 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
755 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
760 /* Decrese the reference count of the packet context and free it only if
763 void silc_packet_context_free(SilcPacketContext *ctx)
766 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
771 silc_buffer_free(ctx->buffer);
773 silc_free(ctx->src_id);
775 silc_free(ctx->dst_id);