5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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 to %s:%d [%s], dropped: %s",
60 sock->hostname ? sock->hostname : "", sock->port,
61 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
62 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
63 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
64 "Router"), strerror(errno)));
69 SILC_LOG_DEBUG(("Could not force the send, packet put to queue"));
72 SILC_LOG_DEBUG(("Packet in queue"));
77 /* Encrypts a packet. This also creates HMAC of the packet before
78 encryption and adds the HMAC at the end of the buffer. This assumes
79 that there is enough free space at the end of the buffer to add the
80 computed HMAC. This is the normal way of encrypting packets, if some
81 other process of HMAC computing and encryption is needed this function
84 void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, SilcUInt32 sequence,
85 SilcBuffer buffer, SilcUInt32 len)
88 /* Encrypt the data area of the packet. */
90 SILC_LOG_DEBUG(("Encrypting packet (%d), cipher %s, len %d",
91 sequence, silc_cipher_get_name(cipher), len));
92 silc_cipher_encrypt(cipher, buffer->data, buffer->data, len, NULL);
95 /* Compute HMAC. This assumes that MAC is computed from the entire
96 data area thus this uses the length found in buffer, not the length
99 unsigned char mac[32], psn[4];
102 silc_hmac_init(hmac);
103 SILC_PUT32_MSB(sequence, psn);
104 silc_hmac_update(hmac, psn, 4);
105 silc_hmac_update(hmac, buffer->data, buffer->len);
106 silc_hmac_final(hmac, mac, &mac_len);
108 /* Put MAC and pull the it into the visible data area in the buffer */
109 silc_buffer_put_tail(buffer, mac, mac_len);
110 silc_buffer_pull_tail(buffer, mac_len);
114 /* Assembles a new packet to be ready for send out. */
116 bool silc_packet_assemble(SilcPacketContext *packet, SilcRng rng,
117 SilcCipher cipher, SilcHmac hmac,
118 SilcSocketConnection sock,
119 const unsigned char *data, SilcUInt32 data_len,
120 const SilcBuffer assembled_packet)
122 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
123 unsigned int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
126 SILC_LOG_DEBUG(("Assembling outgoing packet"));
128 /* Calculate the packet's length and padding length if upper layer
129 didn't already do it. */
131 /* Get the true length of the packet. This is saved as payload length
132 into the packet header. This does not include the length of the
134 if (!packet->truelen) {
135 data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
136 packet->src_id_len + packet->dst_id_len);
137 packet->truelen = data_len + SILC_PACKET_HEADER_LEN +
138 packet->src_id_len + packet->dst_id_len;
141 /* Calculate the length of the padding. The padding is calculated from
142 the data that will be encrypted. */
143 if (!packet->padlen) {
144 if (packet->long_pad)
145 SILC_PACKET_PADLEN_MAX(packet->truelen, block_len, packet->padlen);
147 SILC_PACKET_PADLEN(packet->truelen, block_len, packet->padlen);
150 /* Now prepare the outgoing data buffer for packet sending and start
151 assembling the packet. */
153 /* Return pointer to the assembled packet */
154 if (!silc_packet_send_prepare(sock, packet->truelen - data_len,
155 packet->padlen, data_len, hmac,
159 /* Get random padding */
161 for (i = 0; i < packet->padlen; i++) tmppad[i] =
162 silc_rng_get_byte_fast(rng);
164 for (i = 0; i < packet->padlen; i++) tmppad[i] =
165 silc_rng_global_get_byte_fast();
167 /* Create the packet. This creates the SILC header, adds padding, and
168 the actual packet data. */
170 silc_buffer_format(assembled_packet,
171 SILC_STR_UI_SHORT(packet->truelen),
172 SILC_STR_UI_CHAR(packet->flags),
173 SILC_STR_UI_CHAR(packet->type),
174 SILC_STR_UI_CHAR(packet->padlen),
176 SILC_STR_UI_CHAR(packet->src_id_len),
177 SILC_STR_UI_CHAR(packet->dst_id_len),
178 SILC_STR_UI_CHAR(packet->src_id_type),
179 SILC_STR_UI_XNSTRING(packet->src_id,
181 SILC_STR_UI_CHAR(packet->dst_id_type),
182 SILC_STR_UI_XNSTRING(packet->dst_id,
184 SILC_STR_UI_XNSTRING(tmppad, packet->padlen),
185 SILC_STR_UI_XNSTRING(data, data_len),
190 SILC_LOG_HEXDUMP(("Assembled packet, len %d", assembled_packet->len),
191 assembled_packet->data, assembled_packet->len);
196 /* Prepare outgoing data buffer for packet sending. This moves the data
197 area so that new packet may be added into it. If needed this allocates
198 more space to the buffer. This handles directly the connection's
199 outgoing buffer in SilcSocketConnection object, and returns the
200 pointer to that buffer into the `packet'. */
202 bool silc_packet_send_prepare(SilcSocketConnection sock,
203 SilcUInt32 header_len,
207 const SilcBuffer packet)
210 unsigned char *oldptr;
211 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
216 totlen = header_len + pad_len + data_len;
218 /* Prepare the outgoing buffer for packet sending. */
220 /* Allocate new buffer. This is done only once per connection. */
221 SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
223 sock->outbuf = silc_buffer_alloc(totlen > SILC_PACKET_DEFAULT_SIZE ?
224 totlen : SILC_PACKET_DEFAULT_SIZE);
228 if (!SILC_IS_OUTBUF_PENDING(sock)) {
229 /* Buffer is free for use */
230 silc_buffer_clear(sock->outbuf);
234 /* Allocate more space if needed */
235 if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + mac_len)) {
236 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
237 sock->outbuf = silc_buffer_realloc(sock->outbuf,
238 sock->outbuf->truelen + (totlen * 2));
243 /* Pull data area for the new packet, and return pointer to the start of
244 the data area and save the pointer in to the `packet'. */
245 oldptr = silc_buffer_pull_tail(sock->outbuf, totlen + mac_len);
246 silc_buffer_set(packet, oldptr, totlen + mac_len);
247 silc_buffer_push_tail(packet, mac_len);
252 /******************************************************************************
254 Packet Reception Routines
256 ******************************************************************************/
258 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
259 SilcUInt32 sequence, SilcBuffer buffer,
261 static bool silc_packet_check_mac(SilcHmac hmac,
262 const unsigned char *data,
264 const unsigned char *packet_mac,
265 SilcUInt32 sequence);
267 /* Receives packet from network and reads the data into connection's
268 incoming data buffer. If the data was read directly this returns the
269 read bytes, if error occured this returns -1, if the data could not
270 be read directly at this time this returns -2 in which case the data
271 should be read again at some later time, or If EOF occured this returns
274 int silc_packet_receive(SilcSocketConnection sock)
278 SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
280 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
281 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
282 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
285 /* Read some data from connection */
286 ret = silc_socket_read(sock);
291 /* Processes and decrypts the incmoing data, and calls parser callback
292 for each received packet that will handle the actual packet parsing.
293 If more than one packet was received this calls the parser multiple
294 times. The parser callback will get context SilcPacketParserContext
295 that includes the packet and the `parser_context' sent to this
298 The `local_is_router' indicates whether the caller is router server
299 in which case the receiving process of a certain packet types may
300 be special. Normal server and client must set it to FALSE. The
301 SilcPacketParserContext will indicate also whether the received
302 packet was normal or special packet. */
304 bool silc_packet_receive_process(SilcSocketConnection sock,
305 bool local_is_router,
306 SilcCipher cipher, SilcHmac hmac,
308 SilcPacketParserCallback parser,
309 void *parser_context)
311 SilcPacketParserContext *parse_ctx;
312 SilcUInt16 packetlen;
313 SilcUInt32 paddedlen, mac_len = 0, block_len;
316 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
317 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
319 /* Do not process for disconnected connection */
320 if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
323 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
327 mac_len = silc_hmac_len(hmac);
329 /* Parse the packets from the data */
330 silc_socket_dup(sock);
331 while (sock->inbuf->len > 0 && cont) {
333 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
334 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
335 silc_socket_free(sock);
339 /* Decrypt first block of the packet to get the length field out */
341 block_len = silc_cipher_get_block_len(cipher);
342 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
343 silc_cipher_decrypt(cipher, sock->inbuf->data, tmp, block_len, iv);
346 block_len = SILC_PACKET_MIN_HEADER_LEN;
347 header = sock->inbuf->data;
350 /* Get packet lenght and full packet length with padding */
351 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
354 if (packetlen < SILC_PACKET_MIN_LEN) {
355 SILC_LOG_ERROR(("Received too short packet"));
356 memset(header, 0, sizeof(header));
357 silc_buffer_clear(sock->inbuf);
358 silc_socket_free(sock);
362 if (sock->inbuf->len < paddedlen + mac_len) {
363 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
364 "(%d bytes)", paddedlen + mac_len - sock->inbuf->len));
365 SILC_SET_INBUF_PENDING(sock);
366 memset(tmp, 0, sizeof(tmp));
367 silc_socket_free(sock);
371 /* Check MAC of the packet */
372 if (!silc_packet_check_mac(hmac, sock->inbuf->data, paddedlen,
373 sock->inbuf->data + paddedlen, sequence)) {
374 SILC_LOG_WARNING(("Packet MAC check failed %s:%d "
375 "[%s type %d len %dB blen %dB seq %d] [%s] proto %d",
376 sock->hostname, sock->port,
377 silc_get_packet_name(header[3]),
378 header[3], paddedlen, sock->inbuf->len, sequence,
379 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
380 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
381 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
383 sock->protocol ? sock->protocol->protocol->type : -1));
384 memset(tmp, 0, sizeof(tmp));
385 silc_buffer_clear(sock->inbuf);
386 silc_socket_free(sock);
390 SILC_UNSET_INBUF_PENDING(sock);
391 parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
393 silc_socket_free(sock);
396 parse_ctx->packet = silc_packet_context_alloc();
397 parse_ctx->packet->buffer = silc_buffer_alloc_size(paddedlen);
398 parse_ctx->packet->type = (SilcPacketType)header[3];
399 parse_ctx->packet->padlen = (SilcUInt8)header[4];
400 parse_ctx->packet->sequence = sequence++;
401 parse_ctx->sock = sock;
402 parse_ctx->context = parser_context;
404 /* Check whether this is normal or special packet */
405 if (local_is_router) {
406 if (header[3] == SILC_PACKET_PRIVATE_MESSAGE &&
407 (header[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
408 parse_ctx->normal = FALSE;
409 else if (header[3] != SILC_PACKET_CHANNEL_MESSAGE ||
410 (header[3] == SILC_PACKET_CHANNEL_MESSAGE &&
411 sock->type == SILC_SOCKET_TYPE_ROUTER))
412 parse_ctx->normal = TRUE;
414 if (header[3] == SILC_PACKET_PRIVATE_MESSAGE &&
415 (header[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
416 parse_ctx->normal = FALSE;
417 else if (header[3] != SILC_PACKET_CHANNEL_MESSAGE)
418 parse_ctx->normal = TRUE;
421 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
422 sequence - 1, paddedlen + mac_len),
423 sock->inbuf->data, paddedlen + mac_len);
425 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
426 silc_buffer_put(parse_ctx->packet->buffer, header, block_len);
427 silc_buffer_pull(parse_ctx->packet->buffer, block_len);
428 silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data + block_len,
429 paddedlen - block_len);
431 silc_cipher_set_iv(cipher, iv);
432 ret = silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
433 parse_ctx->packet->buffer,
436 SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s] [%s]",
437 sock->hostname, sock->port,
438 silc_get_packet_name(parse_ctx->packet->type),
439 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
440 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
441 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
443 memset(tmp, 0, sizeof(tmp));
444 silc_packet_context_free(parse_ctx->packet);
445 silc_free(parse_ctx);
446 silc_socket_free(sock);
450 silc_buffer_push(parse_ctx->packet->buffer, block_len);
452 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d",
453 parse_ctx->packet->buffer->len),
454 parse_ctx->packet->buffer->data,
455 parse_ctx->packet->buffer->len);
457 /* Pull the packet from inbuf thus we'll get the next one
459 silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
461 /* Call the parser */
462 cont = (*parser)(parse_ctx, parser_context);
464 /* See if socket disconnected while parsing the packet */
465 if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
466 SILC_LOG_DEBUG(("Abandoning packet processing, socket disconnected"));
470 memset(tmp, 0, sizeof(tmp));
473 /* Don't clear buffer if pending data is in the buffer */
474 if (cont == FALSE && sock->inbuf->len > 0) {
475 silc_socket_free(sock);
479 /* Don't clear buffer if QoS data exists in the buffer */
480 if (sock->qos && sock->qos->data_len > 0) {
481 silc_socket_free(sock);
485 SILC_LOG_DEBUG(("Clearing inbound buffer"));
486 silc_buffer_clear(sock->inbuf);
487 silc_socket_free(sock);
491 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
493 static bool silc_packet_check_mac(SilcHmac hmac,
494 const unsigned char *data,
496 const unsigned char *packet_mac,
501 unsigned char mac[32], psn[4];
504 SILC_LOG_DEBUG(("Verifying MAC"));
506 /* Compute HMAC of packet */
507 silc_hmac_init(hmac);
508 SILC_PUT32_MSB(sequence, psn);
509 silc_hmac_update(hmac, psn, 4);
510 silc_hmac_update(hmac, data, data_len);
511 silc_hmac_final(hmac, mac, &mac_len);
513 /* Compare the MAC's */
514 if (memcmp(packet_mac, mac, mac_len)) {
515 SILC_LOG_ERROR(("MAC failed"));
519 SILC_LOG_DEBUG(("MAC is Ok"));
525 /* Decrypts SILC packet. Handles both normal and special packet decryption.
526 Return 0 when packet is normal and 1 when it it special, -1 on error. */
528 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
529 SilcUInt32 sequence, SilcBuffer buffer,
532 /* If the packet type is not any special type lets decrypt rest
533 of the packet here. */
534 if (normal == TRUE) {
536 /* Decrypt rest of the packet */
537 SILC_LOG_DEBUG(("Decrypting the packet"));
538 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
539 buffer->len, NULL)) {
540 SILC_LOG_ERROR(("silc_cipher_decrypt failed"));
547 /* Decrypt rest of the header plus padding */
550 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
552 SILC_LOG_DEBUG(("Decrypting the header"));
554 /* padding length + src id len + dst id len + header length - 16
555 bytes already decrypted, gives the rest of the encrypted packet */
556 silc_buffer_push(buffer, block_len);
557 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
558 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
560 silc_buffer_pull(buffer, block_len);
562 if (len > buffer->len) {
563 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
567 if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
569 SILC_LOG_ERROR(("silc_cipher_decrypt failed"));
578 /* Parses the packet. This is called when a whole packet is ready to be
579 parsed. The buffer sent must be already decrypted before calling this
580 function. The len argument must be the true length of the packet. This
581 function returns the type of the packet. The data section of the
582 buffer is parsed, not head or tail sections. */
584 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
586 SilcBuffer buffer = ctx->buffer;
589 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
591 SILC_LOG_DEBUG(("Parsing incoming packet"));
593 /* Check the length of the buffer */
594 if (buffer->len < SILC_PACKET_MIN_LEN) {
595 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
596 return SILC_PACKET_NONE;
599 /* Parse the buffer. This parses the SILC header of the packet. */
600 len = silc_buffer_unformat(buffer,
601 SILC_STR_UI_SHORT(&ctx->truelen),
602 SILC_STR_UI_CHAR(&ctx->flags),
603 SILC_STR_UI_CHAR(&ctx->type),
604 SILC_STR_UI_CHAR(&padlen),
605 SILC_STR_UI_CHAR(&tmp),
606 SILC_STR_UI_CHAR(&src_id_len),
607 SILC_STR_UI_CHAR(&dst_id_len),
608 SILC_STR_UI_CHAR(&src_id_type),
610 if (len == -1 || tmp != 0)
611 return SILC_PACKET_NONE;
613 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
614 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
615 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
616 src_id_len, dst_id_len));
617 return SILC_PACKET_NONE;
620 silc_buffer_pull(buffer, len);
621 ret = silc_buffer_unformat(buffer,
622 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
624 SILC_STR_UI_CHAR(&dst_id_type),
625 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
627 SILC_STR_UI_XNSTRING(NULL, padlen),
630 return SILC_PACKET_NONE;
632 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
633 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
634 src_id_type, dst_id_type));
635 return SILC_PACKET_NONE;
638 ctx->src_id_len = src_id_len;
639 ctx->dst_id_len = dst_id_len;
640 ctx->src_id_type = src_id_type;
641 ctx->dst_id_type = dst_id_type;
642 ctx->padlen = padlen;
644 silc_buffer_push(buffer, len);
646 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
647 ctx->buffer->data, ctx->buffer->len);
649 /* Pull SILC header and padding from packet */
650 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
651 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
653 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
658 /* Perform special SILC Packet header parsing. This is required to some
659 packet types that have the data payload encrypted with different key
660 than the header area plus padding of the packet. Hence, this parses
661 the header in a way that it does not take the data area into account
662 and parses the header and padding area only. */
664 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
667 SilcBuffer buffer = ctx->buffer;
670 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
672 SILC_LOG_DEBUG(("Parsing incoming packet"));
674 /* Check the length of the buffer */
675 if (buffer->len < SILC_PACKET_MIN_LEN) {
676 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
677 return SILC_PACKET_NONE;
680 /* Parse the buffer. This parses the SILC header of the packet. */
681 len = silc_buffer_unformat(buffer,
682 SILC_STR_UI_SHORT(&ctx->truelen),
683 SILC_STR_UI_CHAR(&ctx->flags),
684 SILC_STR_UI_CHAR(&ctx->type),
685 SILC_STR_UI_CHAR(&padlen),
686 SILC_STR_UI_CHAR(&tmp),
687 SILC_STR_UI_CHAR(&src_id_len),
688 SILC_STR_UI_CHAR(&dst_id_len),
689 SILC_STR_UI_CHAR(&src_id_type),
691 if (len == -1 || tmp != 0) {
692 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
693 return SILC_PACKET_NONE;
696 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
697 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
698 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
699 src_id_len, dst_id_len));
700 return SILC_PACKET_NONE;
703 silc_buffer_pull(buffer, len);
704 ret = silc_buffer_unformat(buffer,
705 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
707 SILC_STR_UI_CHAR(&dst_id_type),
708 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
710 SILC_STR_UI_XNSTRING(NULL, padlen),
713 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
714 return SILC_PACKET_NONE;
717 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
718 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
719 src_id_type, dst_id_type));
720 return SILC_PACKET_NONE;
723 ctx->src_id_len = src_id_len;
724 ctx->dst_id_len = dst_id_len;
725 ctx->src_id_type = src_id_type;
726 ctx->dst_id_type = dst_id_type;
727 ctx->padlen = padlen;
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));
754 /* Increse the reference count of the packet context. */
756 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
759 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
764 /* Decrese the reference count of the packet context and free it only if
767 void silc_packet_context_free(SilcPacketContext *ctx)
770 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
775 silc_buffer_free(ctx->buffer);
777 silc_free(ctx->src_id);
779 silc_free(ctx->dst_id);