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 packet->padlen = (packet->long_pad ?
145 SILC_PACKET_PADLEN_MAX(packet->truelen) :
146 SILC_PACKET_PADLEN(packet->truelen, block_len));
149 /* Now prepare the outgoing data buffer for packet sending and start
150 assembling the packet. */
152 /* Return pointer to the assembled packet */
153 if (!silc_packet_send_prepare(sock, packet->truelen - data_len,
154 packet->padlen, data_len, hmac,
158 /* Get random padding */
160 for (i = 0; i < packet->padlen; i++) tmppad[i] =
161 silc_rng_get_byte_fast(rng);
163 for (i = 0; i < packet->padlen; i++) tmppad[i] =
164 silc_rng_global_get_byte_fast();
166 /* Create the packet. This creates the SILC header, adds padding, and
167 the actual packet data. */
169 silc_buffer_format(assembled_packet,
170 SILC_STR_UI_SHORT(packet->truelen),
171 SILC_STR_UI_CHAR(packet->flags),
172 SILC_STR_UI_CHAR(packet->type),
173 SILC_STR_UI_CHAR(packet->padlen),
175 SILC_STR_UI_CHAR(packet->src_id_len),
176 SILC_STR_UI_CHAR(packet->dst_id_len),
177 SILC_STR_UI_CHAR(packet->src_id_type),
178 SILC_STR_UI_XNSTRING(packet->src_id,
180 SILC_STR_UI_CHAR(packet->dst_id_type),
181 SILC_STR_UI_XNSTRING(packet->dst_id,
183 SILC_STR_UI_XNSTRING(tmppad, packet->padlen),
184 SILC_STR_UI_XNSTRING(data, data_len),
189 SILC_LOG_HEXDUMP(("Assembled packet, len %d", assembled_packet->len),
190 assembled_packet->data, assembled_packet->len);
195 /* Prepare outgoing data buffer for packet sending. This moves the data
196 area so that new packet may be added into it. If needed this allocates
197 more space to the buffer. This handles directly the connection's
198 outgoing buffer in SilcSocketConnection object, and returns the
199 pointer to that buffer into the `packet'. */
201 bool silc_packet_send_prepare(SilcSocketConnection sock,
202 SilcUInt32 header_len,
206 const SilcBuffer packet)
209 unsigned char *oldptr;
210 int mac_len = hmac ? silc_hmac_len(hmac) : 0;
215 totlen = header_len + pad_len + data_len;
217 /* Prepare the outgoing buffer for packet sending. */
219 /* Allocate new buffer. This is done only once per connection. */
220 SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
222 sock->outbuf = silc_buffer_alloc(totlen > SILC_PACKET_DEFAULT_SIZE ?
223 totlen : SILC_PACKET_DEFAULT_SIZE);
227 if (!SILC_IS_OUTBUF_PENDING(sock)) {
228 /* Buffer is free for use */
229 silc_buffer_clear(sock->outbuf);
233 /* Allocate more space if needed */
234 if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + mac_len)) {
235 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
236 sock->outbuf = silc_buffer_realloc(sock->outbuf,
237 sock->outbuf->truelen + (totlen * 2));
242 /* Pull data area for the new packet, and return pointer to the start of
243 the data area and save the pointer in to the `packet'. */
244 oldptr = silc_buffer_pull_tail(sock->outbuf, totlen + mac_len);
245 silc_buffer_set(packet, oldptr, totlen + mac_len);
246 silc_buffer_push_tail(packet, mac_len);
251 /******************************************************************************
253 Packet Reception Routines
255 ******************************************************************************/
257 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
258 SilcUInt32 sequence, SilcBuffer buffer,
261 /* Receives packet from network and reads the data into connection's
262 incoming data buffer. If the data was read directly this returns the
263 read bytes, if error occured this returns -1, if the data could not
264 be read directly at this time this returns -2 in which case the data
265 should be read again at some later time, or If EOF occured this returns
268 int silc_packet_receive(SilcSocketConnection sock)
272 SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
274 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
275 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
276 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
279 /* Read some data from connection */
280 ret = silc_socket_read(sock);
285 /* Processes and decrypts the incmoing data, and calls parser callback
286 for each received packet that will handle the actual packet parsing.
287 If more than one packet was received this calls the parser multiple
288 times. The parser callback will get context SilcPacketParserContext
289 that includes the packet and the `parser_context' sent to this
292 The `local_is_router' indicates whether the caller is router server
293 in which case the receiving process of a certain packet types may
294 be special. Normal server and client must set it to FALSE. The
295 SilcPacketParserContext will indicate also whether the received
296 packet was normal or special packet. */
298 bool silc_packet_receive_process(SilcSocketConnection sock,
299 bool local_is_router,
300 SilcCipher cipher, SilcHmac hmac,
302 SilcPacketParserCallback parser,
303 void *parser_context)
305 SilcPacketParserContext *parse_ctx;
306 int packetlen, paddedlen, mac_len = 0;
309 /* Do not process for disconnected connection */
310 if (SILC_IS_DISCONNECTED(sock))
313 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
317 mac_len = silc_hmac_len(hmac);
319 /* Parse the packets from the data */
320 while (sock->inbuf->len > 0 && cont) {
322 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
323 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
327 /* Decrypt first 16 bytes of the packet */
328 if (!SILC_IS_INBUF_PENDING(sock) && cipher)
329 silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data,
330 SILC_PACKET_MIN_HEADER_LEN,
331 silc_cipher_get_iv(cipher));
333 /* Get packet lenght and full packet length with padding */
334 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
337 if (packetlen < SILC_PACKET_MIN_LEN) {
338 SILC_LOG_ERROR(("Received invalid packet, dropped"));
339 silc_buffer_clear(sock->inbuf);
343 if (sock->inbuf->len < paddedlen + mac_len) {
344 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
345 "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
346 SILC_SET_INBUF_PENDING(sock);
350 SILC_UNSET_INBUF_PENDING(sock);
351 parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
354 parse_ctx->packet = silc_packet_context_alloc();
355 parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
356 parse_ctx->packet->type = sock->inbuf->data[3];
357 parse_ctx->packet->padlen = sock->inbuf->data[4];
358 parse_ctx->packet->sequence = sequence++;
359 parse_ctx->sock = sock;
360 parse_ctx->context = parser_context;
362 silc_buffer_pull_tail(parse_ctx->packet->buffer,
363 SILC_BUFFER_END(parse_ctx->packet->buffer));
364 silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data,
365 paddedlen + mac_len);
367 SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d",
368 sequence - 1, SILC_PACKET_MIN_HEADER_LEN,
369 paddedlen + mac_len),
370 sock->inbuf->data, paddedlen + mac_len);
372 /* Check whether this is normal or special packet */
373 if (local_is_router) {
374 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
375 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
376 parse_ctx->normal = FALSE;
377 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE ||
378 (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
379 sock->type == SILC_SOCKET_TYPE_ROUTER))
380 parse_ctx->normal = TRUE;
382 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
383 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
384 parse_ctx->normal = FALSE;
385 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE)
386 parse_ctx->normal = TRUE;
389 /* Decrypt rest of the packet */
391 if (silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
392 parse_ctx->packet->buffer,
393 parse_ctx->normal) == -1) {
394 SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s] [%s]",
395 sock->hostname, sock->port,
396 silc_get_packet_name(parse_ctx->packet->type),
397 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
398 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
399 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
401 silc_packet_context_free(parse_ctx->packet);
402 silc_free(parse_ctx);
406 /* Pull the packet from inbuf thus we'll get the next one
408 silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
410 /* Call the parser */
411 cont = (*parser)(parse_ctx, parser_context);
414 if (cont == FALSE && sock->inbuf->len > 0)
417 SILC_LOG_DEBUG(("Clearing inbound buffer"));
418 silc_buffer_clear(sock->inbuf);
422 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
423 after packet has been totally decrypted and parsed. */
425 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
430 unsigned char mac[32], psn[4];
433 SILC_LOG_DEBUG(("Verifying MAC"));
435 /* Compute HMAC of packet */
437 memset(mac, 0, sizeof(mac));
438 silc_hmac_init(hmac);
439 SILC_PUT32_MSB(sequence, psn);
440 silc_hmac_update(hmac, psn, 4);
441 silc_hmac_update(hmac, buffer->data, buffer->len);
442 silc_hmac_final(hmac, mac, &mac_len);
444 /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
445 if (memcmp(buffer->tail, mac, mac_len)) {
446 SILC_LOG_ERROR(("MAC failed"));
450 SILC_LOG_DEBUG(("MAC is Ok"));
451 memset(mac, 0, sizeof(mac));
457 /* Decrypts rest of the packet (after decrypting just the SILC header).
458 After calling this function the packet is ready to be parsed by calling
459 silc_packet_parse. If everything goes without errors this returns TRUE,
460 if packet is malformed this returns FALSE. */
462 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
467 /* Pull MAC from packet before decryption */
469 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
470 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
472 SILC_LOG_ERROR(("Bad MAC length in packet, packet dropped"));
477 SILC_LOG_DEBUG(("Decrypting rest of the packet"));
479 /* Decrypt rest of the packet */
480 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
481 silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len,
482 silc_cipher_get_iv(cipher));
483 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
485 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
486 buffer->data, buffer->len);
492 /* Decrypts rest of the SILC Packet header that has been decrypted partly
493 already. This decrypts the padding of the packet also. After calling
494 this function the packet is ready to be parsed by calling function
495 silc_packet_parse. This is used in special packet reception (protocol
496 defines the way of decrypting special packets). */
498 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
502 /* Decrypt rest of the header plus padding */
506 /* Pull MAC from packet before decryption */
508 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
509 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
511 SILC_LOG_ERROR(("Bad MAC length in packet, packet dropped"));
516 SILC_LOG_DEBUG(("Decrypting rest of the header"));
518 /* padding length + src id len + dst id len + header length - 16
519 bytes already decrypted, gives the rest of the encrypted packet */
520 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
521 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
522 SILC_PACKET_MIN_HEADER_LEN);
524 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
525 if (len > buffer->len) {
526 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
530 silc_cipher_decrypt(cipher, buffer->data, buffer->data, len,
531 silc_cipher_get_iv(cipher));
532 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
533 SILC_LOG_HEXDUMP(("packet, len %d", buffer->len),
534 buffer->data, buffer->len);
540 /* Decrypts a packet. This assumes that typical SILC packet is the
541 packet to be decrypted and thus checks for normal and special SILC
542 packets and can handle both of them. This also computes and checks
543 the HMAC of the packet. If any other special or customized decryption
544 processing is required this function cannot be used. This returns
545 -1 on error, 0 when packet is normal packet and 1 when the packet
546 is special and requires special processing.
548 The `check_packet' is a callback funtion that this function will
549 call. The callback relates to the checking whether the packet is
550 normal packet or special packet and how it should be processed. If
551 the callback return TRUE the packet is normal and FALSE if the packet
552 is special and requires special procesing. */
554 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
555 SilcUInt32 sequence, SilcBuffer buffer,
558 /* If the packet type is not any special type lets decrypt rest
559 of the packet here. */
560 if (normal == TRUE) {
561 /* Normal packet, decrypt rest of the packet */
562 if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
566 if (!silc_packet_check_mac(hmac, buffer, sequence))
571 /* Packet requires special handling, decrypt rest of the header.
572 This only decrypts. */
573 if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
577 if (!silc_packet_check_mac(hmac, buffer, sequence))
584 /* Parses the packet. This is called when a whole packet is ready to be
585 parsed. The buffer sent must be already decrypted before calling this
586 function. The len argument must be the true length of the packet. This
587 function returns the type of the packet. The data section of the
588 buffer is parsed, not head or tail sections. */
590 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
592 SilcBuffer buffer = ctx->buffer;
595 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
597 SILC_LOG_DEBUG(("Parsing incoming packet"));
599 /* Check the length of the buffer */
600 if (buffer->len < SILC_PACKET_MIN_LEN) {
601 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
602 return SILC_PACKET_NONE;
605 /* Parse the buffer. This parses the SILC header of the packet. */
606 len = silc_buffer_unformat(buffer,
607 SILC_STR_UI_SHORT(&ctx->truelen),
608 SILC_STR_UI_CHAR(&ctx->flags),
609 SILC_STR_UI_CHAR(&ctx->type),
610 SILC_STR_UI_CHAR(&padlen),
611 SILC_STR_UI_CHAR(&tmp),
612 SILC_STR_UI_CHAR(&src_id_len),
613 SILC_STR_UI_CHAR(&dst_id_len),
614 SILC_STR_UI_CHAR(&src_id_type),
616 if (len == -1 || tmp != 0)
617 return SILC_PACKET_NONE;
619 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
620 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
621 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
622 src_id_len, dst_id_len));
623 return SILC_PACKET_NONE;
626 silc_buffer_pull(buffer, len);
627 ret = silc_buffer_unformat(buffer,
628 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
630 SILC_STR_UI_CHAR(&dst_id_type),
631 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
633 SILC_STR_UI_XNSTRING(NULL, padlen),
636 return SILC_PACKET_NONE;
638 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
639 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
640 src_id_type, dst_id_type));
641 return SILC_PACKET_NONE;
644 ctx->src_id_len = src_id_len;
645 ctx->dst_id_len = dst_id_len;
646 ctx->src_id_type = src_id_type;
647 ctx->dst_id_type = dst_id_type;
648 ctx->padlen = padlen;
650 silc_buffer_push(buffer, len);
652 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
653 ctx->buffer->data, ctx->buffer->len);
655 /* Pull SILC header and padding from packet */
656 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
657 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
659 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
664 /* Perform special SILC Packet header parsing. This is required to some
665 packet types that have the data payload encrypted with different key
666 than the header area plus padding of the packet. Hence, this parses
667 the header in a way that it does not take the data area into account
668 and parses the header and padding area only. */
670 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
673 SilcBuffer buffer = ctx->buffer;
676 SilcUInt8 src_id_len, src_id_type, dst_id_len, dst_id_type, padlen;
678 SILC_LOG_DEBUG(("Parsing incoming packet"));
680 /* Check the length of the buffer */
681 if (buffer->len < SILC_PACKET_MIN_LEN) {
682 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
683 return SILC_PACKET_NONE;
686 /* Parse the buffer. This parses the SILC header of the packet. */
687 len = silc_buffer_unformat(buffer,
688 SILC_STR_UI_SHORT(&ctx->truelen),
689 SILC_STR_UI_CHAR(&ctx->flags),
690 SILC_STR_UI_CHAR(&ctx->type),
691 SILC_STR_UI_CHAR(&padlen),
692 SILC_STR_UI_CHAR(&tmp),
693 SILC_STR_UI_CHAR(&src_id_len),
694 SILC_STR_UI_CHAR(&dst_id_len),
695 SILC_STR_UI_CHAR(&src_id_type),
697 if (len == -1 || tmp != 0) {
698 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
699 return SILC_PACKET_NONE;
702 if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
703 dst_id_len > SILC_PACKET_MAX_ID_LEN) {
704 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
705 src_id_len, dst_id_len));
706 return SILC_PACKET_NONE;
709 silc_buffer_pull(buffer, len);
710 ret = silc_buffer_unformat(buffer,
711 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
713 SILC_STR_UI_CHAR(&dst_id_type),
714 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
716 SILC_STR_UI_XNSTRING(NULL, padlen),
719 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
720 return SILC_PACKET_NONE;
723 if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) {
724 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
725 src_id_type, dst_id_type));
726 return SILC_PACKET_NONE;
729 ctx->src_id_len = src_id_len;
730 ctx->dst_id_len = dst_id_len;
731 ctx->src_id_type = src_id_type;
732 ctx->dst_id_type = dst_id_type;
733 ctx->padlen = padlen;
735 silc_buffer_push(buffer, len);
737 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
738 ctx->buffer->data, ctx->buffer->len);
740 /* Pull SILC header and padding from packet */
741 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
742 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
744 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
749 /* Allocate packet context */
751 SilcPacketContext *silc_packet_context_alloc(void)
753 SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
760 /* Increse the reference count of the packet context. */
762 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
765 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
770 /* Decrese the reference count of the packet context and free it only if
773 void silc_packet_context_free(SilcPacketContext *ctx)
776 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
781 silc_buffer_free(ctx->buffer);
783 silc_free(ctx->src_id);
785 silc_free(ctx->dst_id);