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. */
115 bool silc_packet_assemble(SilcPacketContext *packet, SilcRng rng,
116 SilcCipher cipher, SilcHmac hmac,
117 SilcSocketConnection sock,
118 const unsigned char *data, SilcUInt32 data_len,
119 const SilcBuffer assembled_packet)
121 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
122 int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
125 SILC_LOG_DEBUG(("Assembling outgoing packet"));
127 /* Calculate the packet's length and padding length if upper layer
128 didn't already do it. */
130 /* Get the true length of the packet. This is saved as payload length
131 into the packet header. This does not include the length of the
133 if (!packet->truelen) {
134 data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
135 packet->src_id_len + packet->dst_id_len);
136 packet->truelen = data_len + SILC_PACKET_HEADER_LEN +
137 packet->src_id_len + packet->dst_id_len;
140 /* Calculate the length of the padding. The padding is calculated from
141 the data that will be encrypted. */
142 if (!packet->padlen) {
143 packet->padlen = (packet->long_pad ?
144 SILC_PACKET_PADLEN_MAX(packet->truelen) :
145 SILC_PACKET_PADLEN(packet->truelen, block_len));
148 /* Now prepare the outgoing data buffer for packet sending and start
149 assembling the packet. */
151 /* Return pointer to the assembled packet */
152 if (!silc_packet_send_prepare(sock, packet->truelen - data_len,
153 packet->padlen, data_len, hmac,
157 /* Get random padding */
159 for (i = 0; i < packet->padlen; i++) tmppad[i] =
160 silc_rng_get_byte_fast(rng);
162 for (i = 0; i < packet->padlen; i++) tmppad[i] =
163 silc_rng_global_get_byte_fast();
165 /* Create the packet. This creates the SILC header, adds padding, and
166 the actual packet data. */
168 silc_buffer_format(assembled_packet,
169 SILC_STR_UI_SHORT(packet->truelen),
170 SILC_STR_UI_CHAR(packet->flags),
171 SILC_STR_UI_CHAR(packet->type),
172 SILC_STR_UI_CHAR(packet->padlen),
174 SILC_STR_UI_CHAR(packet->src_id_len),
175 SILC_STR_UI_CHAR(packet->dst_id_len),
176 SILC_STR_UI_CHAR(packet->src_id_type),
177 SILC_STR_UI_XNSTRING(packet->src_id,
179 SILC_STR_UI_CHAR(packet->dst_id_type),
180 SILC_STR_UI_XNSTRING(packet->dst_id,
182 SILC_STR_UI_XNSTRING(tmppad, packet->padlen),
183 SILC_STR_UI_XNSTRING(data, data_len),
188 SILC_LOG_HEXDUMP(("Assembled packet, len %d", assembled_packet->len),
189 assembled_packet->data, assembled_packet->len);
194 /* Prepare outgoing data buffer for packet sending. This moves the data
195 area so that new packet may be added into it. If needed this allocates
196 more space to the buffer. This handles directly the connection's
197 outgoing buffer in SilcSocketConnection object, and returns the
198 pointer to that buffer into the `packet'. */
200 bool silc_packet_send_prepare(SilcSocketConnection sock,
201 SilcUInt32 header_len,
205 const SilcBuffer packet)
208 unsigned char *oldptr;
209 int mac_len = hmac ? silc_hmac_len(hmac) : 0;
214 totlen = header_len + pad_len + data_len;
216 /* Prepare the outgoing buffer for packet sending. */
218 /* Allocate new buffer. This is done only once per connection. */
219 SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
221 sock->outbuf = silc_buffer_alloc(totlen > SILC_PACKET_DEFAULT_SIZE ?
222 totlen : SILC_PACKET_DEFAULT_SIZE);
226 if (!SILC_IS_OUTBUF_PENDING(sock)) {
227 /* Buffer is free for use */
228 silc_buffer_clear(sock->outbuf);
232 /* Allocate more space if needed */
233 if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + mac_len)) {
234 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
235 sock->outbuf = silc_buffer_realloc(sock->outbuf,
236 sock->outbuf->truelen + (totlen * 2));
241 /* Pull data area for the new packet, and return pointer to the start of
242 the data area and save the pointer in to the `packet'. */
243 oldptr = silc_buffer_pull_tail(sock->outbuf, totlen + mac_len);
244 silc_buffer_set(packet, oldptr, totlen + mac_len);
245 silc_buffer_push_tail(packet, mac_len);
250 /******************************************************************************
252 Packet Reception Routines
254 ******************************************************************************/
256 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
257 SilcUInt32 sequence, SilcBuffer buffer,
260 /* Receives packet from network and reads the data into connection's
261 incoming data buffer. If the data was read directly this returns the
262 read bytes, if error occured this returns -1, if the data could not
263 be read directly at this time this returns -2 in which case the data
264 should be read again at some later time, or If EOF occured this returns
267 int silc_packet_receive(SilcSocketConnection sock)
271 SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
273 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
274 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
275 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
278 /* Read some data from connection */
279 ret = silc_socket_read(sock);
284 /* Processes and decrypts the incmoing data, and calls parser callback
285 for each received packet that will handle the actual packet parsing.
286 If more than one packet was received this calls the parser multiple
287 times. The parser callback will get context SilcPacketParserContext
288 that includes the packet and the `parser_context' sent to this
291 The `local_is_router' indicates whether the caller is router server
292 in which case the receiving process of a certain packet types may
293 be special. Normal server and client must set it to FALSE. The
294 SilcPacketParserContext will indicate also whether the received
295 packet was normal or special packet. */
297 bool silc_packet_receive_process(SilcSocketConnection sock,
298 bool local_is_router,
299 SilcCipher cipher, SilcHmac hmac,
301 SilcPacketParserCallback parser,
302 void *parser_context)
304 SilcPacketParserContext *parse_ctx;
305 int packetlen, paddedlen, mac_len = 0;
308 /* Do not process for disconnected connection */
309 if (SILC_IS_DISCONNECTED(sock))
312 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
316 mac_len = silc_hmac_len(hmac);
318 /* Parse the packets from the data */
319 while (sock->inbuf->len > 0 && cont) {
321 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
322 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
326 /* Decrypt first 16 bytes of the packet */
327 if (!SILC_IS_INBUF_PENDING(sock) && cipher)
328 silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data,
329 SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
331 /* Get packet lenght and full packet length with padding */
332 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
335 if (packetlen < SILC_PACKET_MIN_LEN) {
336 SILC_LOG_ERROR(("Received invalid packet, dropped"));
337 silc_buffer_clear(sock->inbuf);
341 if (sock->inbuf->len < paddedlen + mac_len) {
342 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
343 "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
344 SILC_SET_INBUF_PENDING(sock);
348 SILC_UNSET_INBUF_PENDING(sock);
349 parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
352 parse_ctx->packet = silc_packet_context_alloc();
353 parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
354 parse_ctx->packet->type = sock->inbuf->data[3];
355 parse_ctx->packet->padlen = sock->inbuf->data[4];
356 parse_ctx->packet->sequence = sequence++;
357 parse_ctx->sock = sock;
358 parse_ctx->context = parser_context;
360 silc_buffer_pull_tail(parse_ctx->packet->buffer,
361 SILC_BUFFER_END(parse_ctx->packet->buffer));
362 silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data,
363 paddedlen + mac_len);
365 SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d",
366 sequence - 1, SILC_PACKET_MIN_HEADER_LEN,
367 paddedlen + mac_len),
368 sock->inbuf->data, paddedlen + mac_len);
370 /* Check whether this is normal or special packet */
371 if (local_is_router) {
372 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
373 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
374 parse_ctx->normal = FALSE;
375 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE ||
376 (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
377 sock->type == SILC_SOCKET_TYPE_ROUTER))
378 parse_ctx->normal = TRUE;
380 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
381 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
382 parse_ctx->normal = FALSE;
383 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE)
384 parse_ctx->normal = TRUE;
387 /* Decrypt rest of the packet */
389 if (silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
390 parse_ctx->packet->buffer,
391 parse_ctx->normal) == -1) {
392 SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s] [%s]",
393 sock->hostname, sock->port,
394 silc_get_packet_name(parse_ctx->packet->type),
395 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
396 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
397 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
399 silc_packet_context_free(parse_ctx->packet);
400 silc_free(parse_ctx);
404 /* Pull the packet from inbuf thus we'll get the next one
406 silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
408 /* Call the parser */
409 cont = (*parser)(parse_ctx, parser_context);
412 if (cont == FALSE && sock->inbuf->len > 0)
415 SILC_LOG_DEBUG(("Clearing inbound buffer"));
416 silc_buffer_clear(sock->inbuf);
420 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
421 after packet has been totally decrypted and parsed. */
423 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
428 unsigned char mac[32], psn[4];
431 SILC_LOG_DEBUG(("Verifying MAC"));
433 /* Compute HMAC of packet */
435 memset(mac, 0, sizeof(mac));
436 silc_hmac_init(hmac);
437 SILC_PUT32_MSB(sequence, psn);
438 silc_hmac_update(hmac, psn, 4);
439 silc_hmac_update(hmac, buffer->data, buffer->len);
440 silc_hmac_final(hmac, mac, &mac_len);
442 /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
443 if (memcmp(buffer->tail, mac, mac_len)) {
444 SILC_LOG_ERROR(("MAC failed"));
448 SILC_LOG_DEBUG(("MAC is Ok"));
449 memset(mac, 0, sizeof(mac));
455 /* Decrypts rest of the packet (after decrypting just the SILC header).
456 After calling this function the packet is ready to be parsed by calling
457 silc_packet_parse. If everything goes without errors this returns TRUE,
458 if packet is malformed this returns FALSE. */
460 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
465 /* Pull MAC from packet before decryption */
467 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
468 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
470 SILC_LOG_ERROR(("Bad MAC length in packet, packet dropped"));
475 SILC_LOG_DEBUG(("Decrypting rest of the packet"));
477 /* Decrypt rest of the packet */
478 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
479 silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len,
481 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
483 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
484 buffer->data, buffer->len);
490 /* Decrypts rest of the SILC Packet header that has been decrypted partly
491 already. This decrypts the padding of the packet also. After calling
492 this function the packet is ready to be parsed by calling function
493 silc_packet_parse. This is used in special packet reception (protocol
494 defines the way of decrypting special packets). */
496 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
500 /* Decrypt rest of the header plus padding */
504 /* Pull MAC from packet before decryption */
506 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
507 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
509 SILC_LOG_ERROR(("Bad MAC length in packet, packet dropped"));
514 SILC_LOG_DEBUG(("Decrypting rest of the header"));
516 /* padding length + src id len + dst id len + header length - 16
517 bytes already decrypted, gives the rest of the encrypted packet */
518 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
519 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
520 SILC_PACKET_MIN_HEADER_LEN);
522 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
523 if (len > buffer->len) {
524 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
528 silc_cipher_decrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
529 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
530 SILC_LOG_HEXDUMP(("packet, len %d", buffer->len),
531 buffer->data, buffer->len);
537 /* Decrypts a packet. This assumes that typical SILC packet is the
538 packet to be decrypted and thus checks for normal and special SILC
539 packets and can handle both of them. This also computes and checks
540 the HMAC of the packet. If any other special or customized decryption
541 processing is required this function cannot be used. This returns
542 -1 on error, 0 when packet is normal packet and 1 when the packet
543 is special and requires special processing.
545 The `check_packet' is a callback funtion that this function will
546 call. The callback relates to the checking whether the packet is
547 normal packet or special packet and how it should be processed. If
548 the callback return TRUE the packet is normal and FALSE if the packet
549 is special and requires special procesing. */
551 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
552 SilcUInt32 sequence, SilcBuffer buffer,
555 /* If the packet type is not any special type lets decrypt rest
556 of the packet here. */
557 if (normal == TRUE) {
558 /* Normal packet, decrypt rest of the packet */
559 if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
563 if (!silc_packet_check_mac(hmac, buffer, sequence))
568 /* Packet requires special handling, decrypt rest of the header.
569 This only decrypts. */
570 if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
574 if (!silc_packet_check_mac(hmac, buffer, sequence))
581 /* Parses the packet. This is called when a whole packet is ready to be
582 parsed. The buffer sent must be already decrypted before calling this
583 function. The len argument must be the true length of the packet. This
584 function returns the type of the packet. The data section of the
585 buffer is parsed, not head or tail sections. */
587 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
589 SilcBuffer buffer = ctx->buffer;
592 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
594 SILC_LOG_DEBUG(("Parsing incoming packet"));
596 /* Check the length of the buffer */
597 if (buffer->len < SILC_PACKET_MIN_LEN) {
598 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
599 return SILC_PACKET_NONE;
602 /* Parse the buffer. This parses the SILC header of the packet. */
603 len = silc_buffer_unformat(buffer,
604 SILC_STR_UI_SHORT(&ctx->truelen),
605 SILC_STR_UI_CHAR(&ctx->flags),
606 SILC_STR_UI_CHAR(&ctx->type),
607 SILC_STR_UI_CHAR(&padlen),
608 SILC_STR_UI_CHAR(&tmp),
609 SILC_STR_UI_CHAR(&src_id_len),
610 SILC_STR_UI_CHAR(&dst_id_len),
611 SILC_STR_UI_CHAR(&src_id_type),
613 if (len == -1 || tmp != 0)
614 return SILC_PACKET_NONE;
616 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
617 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
618 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
619 src_id_len, dst_id_len));
620 return SILC_PACKET_NONE;
623 silc_buffer_pull(buffer, len);
624 ret = silc_buffer_unformat(buffer,
625 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
627 SILC_STR_UI_CHAR(&dst_id_type),
628 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
630 SILC_STR_UI_XNSTRING(NULL, padlen),
633 return SILC_PACKET_NONE;
635 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
636 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
637 src_id_type, dst_id_type));
638 return SILC_PACKET_NONE;
641 ctx->src_id_len = src_id_len;
642 ctx->dst_id_len = dst_id_len;
643 ctx->src_id_type = src_id_type;
644 ctx->dst_id_type = dst_id_type;
645 ctx->padlen = padlen;
647 silc_buffer_push(buffer, len);
649 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
650 ctx->buffer->data, ctx->buffer->len);
652 /* Pull SILC header and padding from packet */
653 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
654 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
656 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
661 /* Perform special SILC Packet header parsing. This is required to some
662 packet types that have the data payload encrypted with different key
663 than the header area plus padding of the packet. Hence, this parses
664 the header in a way that it does not take the data area into account
665 and parses the header and padding area only. */
667 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
670 SilcBuffer buffer = ctx->buffer;
673 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
675 SILC_LOG_DEBUG(("Parsing incoming packet"));
677 /* Check the length of the buffer */
678 if (buffer->len < SILC_PACKET_MIN_LEN) {
679 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
680 return SILC_PACKET_NONE;
683 /* Parse the buffer. This parses the SILC header of the packet. */
684 len = silc_buffer_unformat(buffer,
685 SILC_STR_UI_SHORT(&ctx->truelen),
686 SILC_STR_UI_CHAR(&ctx->flags),
687 SILC_STR_UI_CHAR(&ctx->type),
688 SILC_STR_UI_CHAR(&padlen),
689 SILC_STR_UI_CHAR(&tmp),
690 SILC_STR_UI_CHAR(&src_id_len),
691 SILC_STR_UI_CHAR(&dst_id_len),
692 SILC_STR_UI_CHAR(&src_id_type),
694 if (len == -1 || tmp != 0) {
695 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
696 return SILC_PACKET_NONE;
699 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
700 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
701 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
702 src_id_len, dst_id_len));
703 return SILC_PACKET_NONE;
706 silc_buffer_pull(buffer, len);
707 ret = silc_buffer_unformat(buffer,
708 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
710 SILC_STR_UI_CHAR(&dst_id_type),
711 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
713 SILC_STR_UI_XNSTRING(NULL, padlen),
716 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
717 return SILC_PACKET_NONE;
720 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
721 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
722 src_id_type, dst_id_type));
723 return SILC_PACKET_NONE;
726 ctx->src_id_len = src_id_len;
727 ctx->dst_id_len = dst_id_len;
728 ctx->src_id_type = src_id_type;
729 ctx->dst_id_type = dst_id_type;
730 ctx->padlen = padlen;
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);