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: %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)
83 unsigned char mac[32];
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
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));
101 /* Encrypt the data area of the packet. */
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);
108 /* Pull the HMAC into the visible data area in the buffer */
110 silc_buffer_pull_tail(buffer, mac_len);
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.
119 The buffer sent as argument should be something like following:
121 --------------------------------------------
122 | head | data | tail |
123 --------------------------------------------
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:
130 --------------------------------------------
132 --------------------------------------------
134 Start of assembled packet
136 Packet construct is as follows:
139 2 bytes Payload length
142 1 byte Padding length
144 1 bytes Source ID Length
145 1 bytes Destination ID Length
146 1 byte Source ID Type
148 1 byte Destination ID Type
149 n bytes Destination ID
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
161 void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher)
163 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
164 int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
167 SILC_LOG_DEBUG(("Assembling outgoing packet"));
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
173 ctx->truelen = ctx->buffer->len + SILC_PACKET_HEADER_LEN +
174 ctx->src_id_len + ctx->dst_id_len;
176 /* Calculate the length of the padding. The padding is calculated from
177 the data that will be encrypted. */
180 ctx->padlen = SILC_PACKET_PADLEN_MAX(ctx->truelen);
182 ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len);
185 /* Put the start of the data section to the right place. */
186 silc_buffer_push(ctx->buffer, SILC_PACKET_HEADER_LEN +
187 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
189 /* Get random padding */
191 for (i = 0; i < ctx->padlen; i++) tmppad[i] =
192 silc_rng_global_get_byte_fast();
194 /* XXX: For testing - to be removed */
195 memset(tmppad, 65, sizeof(tmppad));
198 /* Create the packet. This creates the SILC header and adds padding,
199 rest of the buffer remains as it is. */
200 silc_buffer_format(ctx->buffer,
201 SILC_STR_UI_SHORT(ctx->truelen),
202 SILC_STR_UI_CHAR(ctx->flags),
203 SILC_STR_UI_CHAR(ctx->type),
204 SILC_STR_UI_CHAR(ctx->padlen),
206 SILC_STR_UI_CHAR(ctx->src_id_len),
207 SILC_STR_UI_CHAR(ctx->dst_id_len),
208 SILC_STR_UI_CHAR(ctx->src_id_type),
209 SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len),
210 SILC_STR_UI_CHAR(ctx->dst_id_type),
211 SILC_STR_UI_XNSTRING(ctx->dst_id, ctx->dst_id_len),
212 SILC_STR_UI_XNSTRING(tmppad, ctx->padlen),
215 SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len),
216 ctx->buffer->data, ctx->buffer->len);
218 SILC_LOG_DEBUG(("Outgoing packet assembled"));
221 /* Prepare outgoing data buffer for packet sending. This moves the data
222 area so that new packet may be added into it. If needed this allocates
223 more space to the buffer. This handles directly the connection's
224 outgoing buffer in SilcSocketConnection object. */
226 void silc_packet_send_prepare(SilcSocketConnection sock,
227 SilcUInt32 header_len,
233 totlen = header_len + padlen + data_len;
235 /* Prepare the outgoing buffer for packet sending. */
237 /* Allocate new buffer. This is done only once per connection. */
238 SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
240 if (totlen > SILC_PACKET_DEFAULT_SIZE)
241 sock->outbuf = silc_buffer_alloc(totlen);
243 sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
244 silc_buffer_pull_tail(sock->outbuf, totlen);
245 silc_buffer_pull(sock->outbuf, header_len + padlen);
247 if (SILC_IS_OUTBUF_PENDING(sock)) {
248 /* There is some pending data in the buffer. */
250 /* Allocate more space if needed */
251 if ((sock->outbuf->end - sock->outbuf->tail) <
253 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
254 sock->outbuf = silc_buffer_realloc(sock->outbuf,
255 sock->outbuf->truelen +
259 oldlen = sock->outbuf->len;
260 silc_buffer_pull_tail(sock->outbuf, totlen);
261 silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
263 /* Buffer is free for use */
264 silc_buffer_clear(sock->outbuf);
266 /* Allocate more space if needed */
267 if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + 20)) {
268 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
269 sock->outbuf = silc_buffer_realloc(sock->outbuf,
270 sock->outbuf->truelen +
274 silc_buffer_pull_tail(sock->outbuf, totlen);
275 silc_buffer_pull(sock->outbuf, header_len + padlen);
280 /******************************************************************************
282 Packet Reception Routines
284 ******************************************************************************/
286 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
287 SilcUInt32 sequence, SilcBuffer buffer,
290 /* Receives packet from network and reads the data into connection's
291 incoming data buffer. If the data was read directly this returns the
292 read bytes, if error occured this returns -1, if the data could not
293 be read directly at this time this returns -2 in which case the data
294 should be read again at some later time, or If EOF occured this returns
297 int silc_packet_receive(SilcSocketConnection sock)
301 SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
303 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
304 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
305 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
308 /* Read some data from connection */
309 ret = silc_socket_read(sock);
314 /* Processes and decrypts the incmoing data, and calls parser callback
315 for each received packet that will handle the actual packet parsing.
316 If more than one packet was received this calls the parser multiple
317 times. The parser callback will get context SilcPacketParserContext
318 that includes the packet and the `parser_context' sent to this
321 The `local_is_router' indicates whether the caller is router server
322 in which case the receiving process of a certain packet types may
323 be special. Normal server and client must set it to FALSE. The
324 SilcPacketParserContext will indicate also whether the received
325 packet was normal or special packet. */
327 bool silc_packet_receive_process(SilcSocketConnection sock,
328 bool local_is_router,
329 SilcCipher cipher, SilcHmac hmac,
331 SilcPacketParserCallback parser,
332 void *parser_context)
334 SilcPacketParserContext *parse_ctx;
335 int packetlen, paddedlen, mac_len = 0;
338 /* Do not process for disconnected connection */
339 if (SILC_IS_DISCONNECTED(sock))
342 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
346 mac_len = silc_hmac_len(hmac);
348 /* Parse the packets from the data */
349 while (sock->inbuf->len > 0 && cont) {
351 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
352 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
356 /* Decrypt first 16 bytes of the packet */
357 if (!SILC_IS_INBUF_PENDING(sock) && cipher)
358 silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data,
359 SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
361 /* Get packet lenght and full packet length with padding */
362 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
365 if (packetlen < SILC_PACKET_MIN_LEN) {
366 SILC_LOG_DEBUG(("Received invalid packet, dropped"));
367 silc_buffer_clear(sock->inbuf);
371 if (sock->inbuf->len < paddedlen + mac_len) {
372 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
373 "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
374 SILC_SET_INBUF_PENDING(sock);
378 SILC_UNSET_INBUF_PENDING(sock);
379 parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
382 parse_ctx->packet = silc_packet_context_alloc();
383 parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
384 parse_ctx->packet->type = sock->inbuf->data[3];
385 parse_ctx->packet->padlen = sock->inbuf->data[4];
386 parse_ctx->packet->sequence = sequence++;
387 parse_ctx->sock = sock;
388 parse_ctx->context = parser_context;
390 silc_buffer_pull_tail(parse_ctx->packet->buffer,
391 SILC_BUFFER_END(parse_ctx->packet->buffer));
392 silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data,
393 paddedlen + mac_len);
395 SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d",
396 sequence - 1, SILC_PACKET_MIN_HEADER_LEN,
397 paddedlen + mac_len),
398 sock->inbuf->data, paddedlen + mac_len);
400 /* Check whether this is normal or special packet */
401 if (local_is_router) {
402 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
403 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
404 parse_ctx->normal = FALSE;
405 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE ||
406 (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
407 sock->type == SILC_SOCKET_TYPE_ROUTER))
408 parse_ctx->normal = TRUE;
410 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
411 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
412 parse_ctx->normal = FALSE;
413 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE)
414 parse_ctx->normal = TRUE;
417 /* Decrypt rest of the packet */
419 if (silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
420 parse_ctx->packet->buffer,
421 parse_ctx->normal) == -1) {
422 SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s]",
423 sock->hostname, sock->port,
424 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
425 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
426 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
430 /* Pull the packet from inbuf thus we'll get the next one
432 silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
434 /* Call the parser */
435 cont = (*parser)(parse_ctx, parser_context);
438 if (cont == FALSE && sock->inbuf->len > 0)
441 SILC_LOG_DEBUG(("Clearing inbound buffer"));
442 silc_buffer_clear(sock->inbuf);
446 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
447 after packet has been totally decrypted and parsed. */
449 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
454 unsigned char mac[32], psn[4];
457 SILC_LOG_DEBUG(("Verifying MAC"));
459 /* Compute HMAC of packet */
461 memset(mac, 0, sizeof(mac));
462 silc_hmac_init(hmac);
463 SILC_PUT32_MSB(sequence, psn);
464 silc_hmac_update(hmac, psn, 4);
465 silc_hmac_update(hmac, buffer->data, buffer->len);
466 silc_hmac_final(hmac, mac, &mac_len);
468 /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
469 if (memcmp(buffer->tail, mac, mac_len)) {
470 SILC_LOG_ERROR(("MAC failed"));
474 SILC_LOG_DEBUG(("MAC is Ok"));
475 memset(mac, 0, sizeof(mac));
481 /* Decrypts rest of the packet (after decrypting just the SILC header).
482 After calling this function the packet is ready to be parsed by calling
483 silc_packet_parse. If everything goes without errors this returns TRUE,
484 if packet is malformed this returns FALSE. */
486 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
491 /* Pull MAC from packet before decryption */
493 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
494 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
496 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
501 SILC_LOG_DEBUG(("Decrypting rest of the packet"));
503 /* Decrypt rest of the packet */
504 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
505 silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len,
507 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
509 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
510 buffer->data, buffer->len);
516 /* Decrypts rest of the SILC Packet header that has been decrypted partly
517 already. This decrypts the padding of the packet also. After calling
518 this function the packet is ready to be parsed by calling function
519 silc_packet_parse. This is used in special packet reception (protocol
520 defines the way of decrypting special packets). */
522 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
526 /* Decrypt rest of the header plus padding */
530 /* Pull MAC from packet before decryption */
532 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
533 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
535 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
540 SILC_LOG_DEBUG(("Decrypting rest of the header"));
542 /* padding length + src id len + dst id len + header length - 16
543 bytes already decrypted, gives the rest of the encrypted packet */
544 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
545 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
546 SILC_PACKET_MIN_HEADER_LEN);
548 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
549 if (len > buffer->len) {
550 SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
554 silc_cipher_decrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
555 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
556 SILC_LOG_HEXDUMP(("packet, len %d", buffer->len),
557 buffer->data, buffer->len);
563 /* Decrypts a packet. This assumes that typical SILC packet is the
564 packet to be decrypted and thus checks for normal and special SILC
565 packets and can handle both of them. This also computes and checks
566 the HMAC of the packet. If any other special or customized decryption
567 processing is required this function cannot be used. This returns
568 -1 on error, 0 when packet is normal packet and 1 when the packet
569 is special and requires special processing.
571 The `check_packet' is a callback funtion that this function will
572 call. The callback relates to the checking whether the packet is
573 normal packet or special packet and how it should be processed. If
574 the callback return TRUE the packet is normal and FALSE if the packet
575 is special and requires special procesing. */
577 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
578 SilcUInt32 sequence, SilcBuffer buffer,
581 /* If the packet type is not any special type lets decrypt rest
582 of the packet here. */
583 if (normal == TRUE) {
584 /* Normal packet, decrypt rest of the packet */
585 if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
589 if (!silc_packet_check_mac(hmac, buffer, sequence))
594 /* Packet requires special handling, decrypt rest of the header.
595 This only decrypts. */
596 if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
600 if (!silc_packet_check_mac(hmac, buffer, sequence))
607 /* Parses the packet. This is called when a whole packet is ready to be
608 parsed. The buffer sent must be already decrypted before calling this
609 function. The len argument must be the true length of the packet. This
610 function returns the type of the packet. The data section of the
611 buffer is parsed, not head or tail sections. */
613 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
615 SilcBuffer buffer = ctx->buffer;
619 SILC_LOG_DEBUG(("Parsing incoming packet"));
621 /* Check the length of the buffer */
622 if (buffer->len < SILC_PACKET_MIN_LEN) {
623 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
624 return SILC_PACKET_NONE;
627 /* Parse the buffer. This parses the SILC header of the packet. */
628 len = silc_buffer_unformat(buffer,
629 SILC_STR_UI_SHORT(&ctx->truelen),
630 SILC_STR_UI_CHAR(&ctx->flags),
631 SILC_STR_UI_CHAR(&ctx->type),
632 SILC_STR_UI_CHAR(&ctx->padlen),
633 SILC_STR_UI_CHAR(&tmp),
634 SILC_STR_UI_CHAR(&ctx->src_id_len),
635 SILC_STR_UI_CHAR(&ctx->dst_id_len),
636 SILC_STR_UI_CHAR(&ctx->src_id_type),
638 if (len == -1 || tmp != 0)
639 return SILC_PACKET_NONE;
641 if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
642 ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
643 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
644 ctx->src_id_len, ctx->dst_id_len));
645 return SILC_PACKET_NONE;
648 silc_buffer_pull(buffer, len);
649 ret = silc_buffer_unformat(buffer,
650 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
652 SILC_STR_UI_CHAR(&ctx->dst_id_type),
653 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
655 SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
658 return SILC_PACKET_NONE;
660 silc_buffer_push(buffer, len);
662 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
663 ctx->buffer->data, ctx->buffer->len);
665 /* Pull SILC header and padding from packet */
666 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
667 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
669 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
674 /* Perform special SILC Packet header parsing. This is required to some
675 packet types that have the data payload encrypted with different key
676 than the header area plus padding of the packet. Hence, this parses
677 the header in a way that it does not take the data area into account
678 and parses the header and padding area only. */
680 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
683 SilcBuffer buffer = ctx->buffer;
687 SILC_LOG_DEBUG(("Parsing incoming packet"));
689 /* Check the length of the buffer */
690 if (buffer->len < SILC_PACKET_MIN_LEN) {
691 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
692 return SILC_PACKET_NONE;
695 /* Parse the buffer. This parses the SILC header of the packet. */
696 len = silc_buffer_unformat(buffer,
697 SILC_STR_UI_SHORT(&ctx->truelen),
698 SILC_STR_UI_CHAR(&ctx->flags),
699 SILC_STR_UI_CHAR(&ctx->type),
700 SILC_STR_UI_CHAR(&ctx->padlen),
701 SILC_STR_UI_CHAR(&tmp),
702 SILC_STR_UI_CHAR(&ctx->src_id_len),
703 SILC_STR_UI_CHAR(&ctx->dst_id_len),
704 SILC_STR_UI_CHAR(&ctx->src_id_type),
706 if (len == -1 || tmp != 0) {
707 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
708 return SILC_PACKET_NONE;
711 if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
712 ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
713 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
714 ctx->src_id_len, ctx->dst_id_len));
715 return SILC_PACKET_NONE;
718 silc_buffer_pull(buffer, len);
719 ret = silc_buffer_unformat(buffer,
720 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
722 SILC_STR_UI_CHAR(&ctx->dst_id_type),
723 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
725 SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
728 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
729 return SILC_PACKET_NONE;
732 silc_buffer_push(buffer, len);
734 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
735 ctx->buffer->data, ctx->buffer->len);
737 /* Pull SILC header and padding from packet */
738 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
739 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
741 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
746 /* Allocate packet context */
748 SilcPacketContext *silc_packet_context_alloc(void)
750 SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
757 /* Increse the reference count of the packet context. */
759 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
762 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
767 /* Decrese the reference count of the packet context and free it only if
770 void silc_packet_context_free(SilcPacketContext *ctx)
773 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
778 silc_buffer_free(ctx->buffer);
780 silc_free(ctx->src_id);
782 silc_free(ctx->dst_id);