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 silc_cipher_get_name(cipher), len));
105 silc_cipher_encrypt(cipher, buffer->data, buffer->data, len,
106 silc_cipher_get_iv(cipher));
109 /* Pull the HMAC into the visible data area in the buffer */
111 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 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 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,
262 /* Receives packet from network and reads the data into connection's
263 incoming data buffer. If the data was read directly this returns the
264 read bytes, if error occured this returns -1, if the data could not
265 be read directly at this time this returns -2 in which case the data
266 should be read again at some later time, or If EOF occured this returns
269 int silc_packet_receive(SilcSocketConnection sock)
273 SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
275 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
276 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
277 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
280 /* Read some data from connection */
281 ret = silc_socket_read(sock);
286 /* Processes and decrypts the incmoing data, and calls parser callback
287 for each received packet that will handle the actual packet parsing.
288 If more than one packet was received this calls the parser multiple
289 times. The parser callback will get context SilcPacketParserContext
290 that includes the packet and the `parser_context' sent to this
293 The `local_is_router' indicates whether the caller is router server
294 in which case the receiving process of a certain packet types may
295 be special. Normal server and client must set it to FALSE. The
296 SilcPacketParserContext will indicate also whether the received
297 packet was normal or special packet. */
299 bool silc_packet_receive_process(SilcSocketConnection sock,
300 bool local_is_router,
301 SilcCipher cipher, SilcHmac hmac,
303 SilcPacketParserCallback parser,
304 void *parser_context)
306 SilcPacketParserContext *parse_ctx;
307 int packetlen, paddedlen, mac_len = 0;
310 /* Do not process for disconnected connection */
311 if (SILC_IS_DISCONNECTED(sock))
314 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
318 mac_len = silc_hmac_len(hmac);
320 /* Parse the packets from the data */
321 while (sock->inbuf->len > 0 && cont) {
323 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
324 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
328 /* Decrypt first 16 bytes of the packet */
329 if (!SILC_IS_INBUF_PENDING(sock) && cipher)
330 silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data,
331 SILC_PACKET_MIN_HEADER_LEN,
332 silc_cipher_get_iv(cipher));
334 /* Get packet lenght and full packet length with padding */
335 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
338 if (packetlen < SILC_PACKET_MIN_LEN) {
339 SILC_LOG_ERROR(("Received invalid packet, dropped"));
340 silc_buffer_clear(sock->inbuf);
344 if (sock->inbuf->len < paddedlen + mac_len) {
345 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
346 "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
347 SILC_SET_INBUF_PENDING(sock);
351 SILC_UNSET_INBUF_PENDING(sock);
352 parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
355 parse_ctx->packet = silc_packet_context_alloc();
356 parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
357 parse_ctx->packet->type = sock->inbuf->data[3];
358 parse_ctx->packet->padlen = sock->inbuf->data[4];
359 parse_ctx->packet->sequence = sequence++;
360 parse_ctx->sock = sock;
361 parse_ctx->context = parser_context;
363 silc_buffer_pull_tail(parse_ctx->packet->buffer,
364 SILC_BUFFER_END(parse_ctx->packet->buffer));
365 silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data,
366 paddedlen + mac_len);
368 SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d",
369 sequence - 1, SILC_PACKET_MIN_HEADER_LEN,
370 paddedlen + mac_len),
371 sock->inbuf->data, paddedlen + mac_len);
373 /* Check whether this is normal or special packet */
374 if (local_is_router) {
375 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
376 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
377 parse_ctx->normal = FALSE;
378 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE ||
379 (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
380 sock->type == SILC_SOCKET_TYPE_ROUTER))
381 parse_ctx->normal = TRUE;
383 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
384 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
385 parse_ctx->normal = FALSE;
386 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE)
387 parse_ctx->normal = TRUE;
390 /* Decrypt rest of the packet */
392 if (silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
393 parse_ctx->packet->buffer,
394 parse_ctx->normal) == -1) {
395 SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s] [%s]",
396 sock->hostname, sock->port,
397 silc_get_packet_name(parse_ctx->packet->type),
398 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
399 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
400 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
402 silc_packet_context_free(parse_ctx->packet);
403 silc_free(parse_ctx);
407 /* Pull the packet from inbuf thus we'll get the next one
409 silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
411 /* Call the parser */
412 cont = (*parser)(parse_ctx, parser_context);
415 if (cont == FALSE && sock->inbuf->len > 0)
418 SILC_LOG_DEBUG(("Clearing inbound buffer"));
419 silc_buffer_clear(sock->inbuf);
423 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
424 after packet has been totally decrypted and parsed. */
426 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
431 unsigned char mac[32], psn[4];
434 SILC_LOG_DEBUG(("Verifying MAC"));
436 /* Compute HMAC of packet */
438 memset(mac, 0, sizeof(mac));
439 silc_hmac_init(hmac);
440 SILC_PUT32_MSB(sequence, psn);
441 silc_hmac_update(hmac, psn, 4);
442 silc_hmac_update(hmac, buffer->data, buffer->len);
443 silc_hmac_final(hmac, mac, &mac_len);
445 /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
446 if (memcmp(buffer->tail, mac, mac_len)) {
447 SILC_LOG_ERROR(("MAC failed"));
451 SILC_LOG_DEBUG(("MAC is Ok"));
452 memset(mac, 0, sizeof(mac));
458 /* Decrypts rest of the packet (after decrypting just the SILC header).
459 After calling this function the packet is ready to be parsed by calling
460 silc_packet_parse. If everything goes without errors this returns TRUE,
461 if packet is malformed this returns FALSE. */
463 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
468 /* Pull MAC from packet before decryption */
470 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
471 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
473 SILC_LOG_ERROR(("Bad MAC length in packet, packet dropped"));
478 SILC_LOG_DEBUG(("Decrypting rest of the packet"));
480 /* Decrypt rest of the packet */
481 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
482 silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len,
483 silc_cipher_get_iv(cipher));
484 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
486 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
487 buffer->data, buffer->len);
493 /* Decrypts rest of the SILC Packet header that has been decrypted partly
494 already. This decrypts the padding of the packet also. After calling
495 this function the packet is ready to be parsed by calling function
496 silc_packet_parse. This is used in special packet reception (protocol
497 defines the way of decrypting special packets). */
499 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
503 /* Decrypt rest of the header plus padding */
507 /* Pull MAC from packet before decryption */
509 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
510 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
512 SILC_LOG_ERROR(("Bad MAC length in packet, packet dropped"));
517 SILC_LOG_DEBUG(("Decrypting rest of the header"));
519 /* padding length + src id len + dst id len + header length - 16
520 bytes already decrypted, gives the rest of the encrypted packet */
521 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
522 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
523 SILC_PACKET_MIN_HEADER_LEN);
525 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
526 if (len > buffer->len) {
527 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
531 silc_cipher_decrypt(cipher, buffer->data, buffer->data, len,
532 silc_cipher_get_iv(cipher));
533 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
534 SILC_LOG_HEXDUMP(("packet, len %d", buffer->len),
535 buffer->data, buffer->len);
541 /* Decrypts a packet. This assumes that typical SILC packet is the
542 packet to be decrypted and thus checks for normal and special SILC
543 packets and can handle both of them. This also computes and checks
544 the HMAC of the packet. If any other special or customized decryption
545 processing is required this function cannot be used. This returns
546 -1 on error, 0 when packet is normal packet and 1 when the packet
547 is special and requires special processing.
549 The `check_packet' is a callback funtion that this function will
550 call. The callback relates to the checking whether the packet is
551 normal packet or special packet and how it should be processed. If
552 the callback return TRUE the packet is normal and FALSE if the packet
553 is special and requires special procesing. */
555 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
556 SilcUInt32 sequence, SilcBuffer buffer,
559 /* If the packet type is not any special type lets decrypt rest
560 of the packet here. */
561 if (normal == TRUE) {
562 /* Normal packet, decrypt rest of the packet */
563 if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
567 if (!silc_packet_check_mac(hmac, buffer, sequence))
572 /* Packet requires special handling, decrypt rest of the header.
573 This only decrypts. */
574 if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
578 if (!silc_packet_check_mac(hmac, buffer, sequence))
585 /* Parses the packet. This is called when a whole packet is ready to be
586 parsed. The buffer sent must be already decrypted before calling this
587 function. The len argument must be the true length of the packet. This
588 function returns the type of the packet. The data section of the
589 buffer is parsed, not head or tail sections. */
591 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
593 SilcBuffer buffer = ctx->buffer;
596 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
598 SILC_LOG_DEBUG(("Parsing incoming packet"));
600 /* Check the length of the buffer */
601 if (buffer->len < SILC_PACKET_MIN_LEN) {
602 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
603 return SILC_PACKET_NONE;
606 /* Parse the buffer. This parses the SILC header of the packet. */
607 len = silc_buffer_unformat(buffer,
608 SILC_STR_UI_SHORT(&ctx->truelen),
609 SILC_STR_UI_CHAR(&ctx->flags),
610 SILC_STR_UI_CHAR(&ctx->type),
611 SILC_STR_UI_CHAR(&padlen),
612 SILC_STR_UI_CHAR(&tmp),
613 SILC_STR_UI_CHAR(&src_id_len),
614 SILC_STR_UI_CHAR(&dst_id_len),
615 SILC_STR_UI_CHAR(&src_id_type),
617 if (len == -1 || tmp != 0)
618 return SILC_PACKET_NONE;
620 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
621 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
622 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
623 src_id_len, dst_id_len));
624 return SILC_PACKET_NONE;
627 silc_buffer_pull(buffer, len);
628 ret = silc_buffer_unformat(buffer,
629 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
631 SILC_STR_UI_CHAR(&dst_id_type),
632 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
634 SILC_STR_UI_XNSTRING(NULL, padlen),
637 return SILC_PACKET_NONE;
639 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
640 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
641 src_id_type, dst_id_type));
642 return SILC_PACKET_NONE;
645 ctx->src_id_len = src_id_len;
646 ctx->dst_id_len = dst_id_len;
647 ctx->src_id_type = src_id_type;
648 ctx->dst_id_type = dst_id_type;
649 ctx->padlen = padlen;
651 silc_buffer_push(buffer, len);
653 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
654 ctx->buffer->data, ctx->buffer->len);
656 /* Pull SILC header and padding from packet */
657 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
658 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
660 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
665 /* Perform special SILC Packet header parsing. This is required to some
666 packet types that have the data payload encrypted with different key
667 than the header area plus padding of the packet. Hence, this parses
668 the header in a way that it does not take the data area into account
669 and parses the header and padding area only. */
671 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
674 SilcBuffer buffer = ctx->buffer;
677 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
679 SILC_LOG_DEBUG(("Parsing incoming packet"));
681 /* Check the length of the buffer */
682 if (buffer->len < SILC_PACKET_MIN_LEN) {
683 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
684 return SILC_PACKET_NONE;
687 /* Parse the buffer. This parses the SILC header of the packet. */
688 len = silc_buffer_unformat(buffer,
689 SILC_STR_UI_SHORT(&ctx->truelen),
690 SILC_STR_UI_CHAR(&ctx->flags),
691 SILC_STR_UI_CHAR(&ctx->type),
692 SILC_STR_UI_CHAR(&padlen),
693 SILC_STR_UI_CHAR(&tmp),
694 SILC_STR_UI_CHAR(&src_id_len),
695 SILC_STR_UI_CHAR(&dst_id_len),
696 SILC_STR_UI_CHAR(&src_id_type),
698 if (len == -1 || tmp != 0) {
699 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
700 return SILC_PACKET_NONE;
703 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
704 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
705 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
706 src_id_len, dst_id_len));
707 return SILC_PACKET_NONE;
710 silc_buffer_pull(buffer, len);
711 ret = silc_buffer_unformat(buffer,
712 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
714 SILC_STR_UI_CHAR(&dst_id_type),
715 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
717 SILC_STR_UI_XNSTRING(NULL, padlen),
720 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
721 return SILC_PACKET_NONE;
724 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
725 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
726 src_id_type, dst_id_type));
727 return SILC_PACKET_NONE;
730 ctx->src_id_len = src_id_len;
731 ctx->dst_id_len = dst_id_len;
732 ctx->src_id_type = src_id_type;
733 ctx->dst_id_type = dst_id_type;
734 ctx->padlen = padlen;
736 silc_buffer_push(buffer, len);
738 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
739 ctx->buffer->data, ctx->buffer->len);
741 /* Pull SILC header and padding from packet */
742 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
743 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
745 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
750 /* Allocate packet context */
752 SilcPacketContext *silc_packet_context_alloc(void)
754 SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
761 /* Increse the reference count of the packet context. */
763 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
766 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
771 /* Decrese the reference count of the packet context and free it only if
774 void silc_packet_context_free(SilcPacketContext *ctx)
777 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
782 silc_buffer_free(ctx->buffer);
784 silc_free(ctx->src_id);
786 silc_free(ctx->dst_id);