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;
175 if (ctx->truelen > SILC_PACKET_MAX_LEN) {
176 ctx->truelen -= (ctx->truelen - SILC_PACKET_MAX_LEN);
177 silc_buffer_push_tail(ctx->buffer, (ctx->truelen - SILC_PACKET_MAX_LEN));
181 /* Calculate the length of the padding. The padding is calculated from
182 the data that will be encrypted. */
185 ctx->padlen = SILC_PACKET_PADLEN_MAX(ctx->truelen);
187 ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len);
190 /* Put the start of the data section to the right place. */
191 silc_buffer_push(ctx->buffer, SILC_PACKET_HEADER_LEN +
192 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
194 /* Get random padding */
196 for (i = 0; i < ctx->padlen; i++) tmppad[i] =
197 silc_rng_global_get_byte_fast();
199 /* XXX: For testing - to be removed */
200 memset(tmppad, 65, sizeof(tmppad));
203 /* Create the packet. This creates the SILC header and adds padding,
204 rest of the buffer remains as it is. */
205 silc_buffer_format(ctx->buffer,
206 SILC_STR_UI_SHORT(ctx->truelen),
207 SILC_STR_UI_CHAR(ctx->flags),
208 SILC_STR_UI_CHAR(ctx->type),
209 SILC_STR_UI_CHAR(ctx->padlen),
211 SILC_STR_UI_CHAR(ctx->src_id_len),
212 SILC_STR_UI_CHAR(ctx->dst_id_len),
213 SILC_STR_UI_CHAR(ctx->src_id_type),
214 SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len),
215 SILC_STR_UI_CHAR(ctx->dst_id_type),
216 SILC_STR_UI_XNSTRING(ctx->dst_id, ctx->dst_id_len),
217 SILC_STR_UI_XNSTRING(tmppad, ctx->padlen),
220 SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len),
221 ctx->buffer->data, ctx->buffer->len);
223 SILC_LOG_DEBUG(("Outgoing packet assembled"));
226 /* Prepare outgoing data buffer for packet sending. This moves the data
227 area so that new packet may be added into it. If needed this allocates
228 more space to the buffer. This handles directly the connection's
229 outgoing buffer in SilcSocketConnection object. */
231 void silc_packet_send_prepare(SilcSocketConnection sock,
232 SilcUInt32 header_len,
238 totlen = header_len + padlen + data_len;
240 /* Prepare the outgoing buffer for packet sending. */
242 /* Allocate new buffer. This is done only once per connection. */
243 SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
245 if (totlen > SILC_PACKET_DEFAULT_SIZE)
246 sock->outbuf = silc_buffer_alloc(totlen);
248 sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
249 silc_buffer_pull_tail(sock->outbuf, totlen);
250 silc_buffer_pull(sock->outbuf, header_len + padlen);
252 if (SILC_IS_OUTBUF_PENDING(sock)) {
253 /* There is some pending data in the buffer. */
255 /* Allocate more space if needed */
256 if ((sock->outbuf->end - sock->outbuf->tail) <
258 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
259 sock->outbuf = silc_buffer_realloc(sock->outbuf,
260 sock->outbuf->truelen +
264 oldlen = sock->outbuf->len;
265 silc_buffer_pull_tail(sock->outbuf, totlen);
266 silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
268 /* Buffer is free for use */
269 silc_buffer_clear(sock->outbuf);
271 /* Allocate more space if needed */
272 if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + 20)) {
273 SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
274 sock->outbuf = silc_buffer_realloc(sock->outbuf,
275 sock->outbuf->truelen +
279 silc_buffer_pull_tail(sock->outbuf, totlen);
280 silc_buffer_pull(sock->outbuf, header_len + padlen);
285 /******************************************************************************
287 Packet Reception Routines
289 ******************************************************************************/
291 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
292 SilcUInt32 sequence, SilcBuffer buffer,
295 /* Receives packet from network and reads the data into connection's
296 incoming data buffer. If the data was read directly this returns the
297 read bytes, if error occured this returns -1, if the data could not
298 be read directly at this time this returns -2 in which case the data
299 should be read again at some later time, or If EOF occured this returns
302 int silc_packet_receive(SilcSocketConnection sock)
306 SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
308 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
309 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
310 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
313 /* Read some data from connection */
314 ret = silc_socket_read(sock);
319 /* Processes and decrypts the incmoing data, and calls parser callback
320 for each received packet that will handle the actual packet parsing.
321 If more than one packet was received this calls the parser multiple
322 times. The parser callback will get context SilcPacketParserContext
323 that includes the packet and the `parser_context' sent to this
326 The `local_is_router' indicates whether the caller is router server
327 in which case the receiving process of a certain packet types may
328 be special. Normal server and client must set it to FALSE. The
329 SilcPacketParserContext will indicate also whether the received
330 packet was normal or special packet. */
332 bool silc_packet_receive_process(SilcSocketConnection sock,
333 bool local_is_router,
334 SilcCipher cipher, SilcHmac hmac,
336 SilcPacketParserCallback parser,
337 void *parser_context)
339 SilcPacketParserContext *parse_ctx;
340 int packetlen, paddedlen, mac_len = 0;
343 /* Do not process for disconnected connection */
344 if (SILC_IS_DISCONNECTED(sock))
347 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
351 mac_len = silc_hmac_len(hmac);
353 /* Parse the packets from the data */
354 while (sock->inbuf->len > 0 && cont) {
356 if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
357 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
361 /* Decrypt first 16 bytes of the packet */
362 if (!SILC_IS_INBUF_PENDING(sock) && cipher)
363 silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data,
364 SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
366 /* Get packet lenght and full packet length with padding */
367 SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
370 if (packetlen < SILC_PACKET_MIN_LEN) {
371 SILC_LOG_DEBUG(("Received invalid packet, dropped"));
372 silc_buffer_clear(sock->inbuf);
376 if (sock->inbuf->len < paddedlen + mac_len) {
377 SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
378 "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
379 SILC_SET_INBUF_PENDING(sock);
383 SILC_UNSET_INBUF_PENDING(sock);
384 parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
387 parse_ctx->packet = silc_packet_context_alloc();
388 parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
389 parse_ctx->packet->type = sock->inbuf->data[3];
390 parse_ctx->packet->padlen = sock->inbuf->data[4];
391 parse_ctx->packet->sequence = sequence++;
392 parse_ctx->sock = sock;
393 parse_ctx->context = parser_context;
395 silc_buffer_pull_tail(parse_ctx->packet->buffer,
396 SILC_BUFFER_END(parse_ctx->packet->buffer));
397 silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data,
398 paddedlen + mac_len);
400 SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d",
401 sequence - 1, SILC_PACKET_MIN_HEADER_LEN,
402 paddedlen + mac_len),
403 sock->inbuf->data, paddedlen + mac_len);
405 /* Check whether this is normal or special packet */
406 if (local_is_router) {
407 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
408 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
409 parse_ctx->normal = FALSE;
410 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE ||
411 (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
412 sock->type == SILC_SOCKET_TYPE_ROUTER))
413 parse_ctx->normal = TRUE;
415 if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
416 (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
417 parse_ctx->normal = FALSE;
418 else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE)
419 parse_ctx->normal = TRUE;
422 /* Decrypt rest of the packet */
424 if (silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
425 parse_ctx->packet->buffer,
426 parse_ctx->normal) == -1) {
427 SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s]",
428 sock->hostname, sock->port,
429 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
430 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
431 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
435 /* Pull the packet from inbuf thus we'll get the next one
437 silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
439 /* Call the parser */
440 cont = (*parser)(parse_ctx, parser_context);
443 if (cont == FALSE && sock->inbuf->len > 0)
446 SILC_LOG_DEBUG(("Clearing inbound buffer"));
447 silc_buffer_clear(sock->inbuf);
451 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
452 after packet has been totally decrypted and parsed. */
454 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
459 unsigned char mac[32], psn[4];
462 SILC_LOG_DEBUG(("Verifying MAC"));
464 /* Compute HMAC of packet */
466 memset(mac, 0, sizeof(mac));
467 silc_hmac_init(hmac);
468 SILC_PUT32_MSB(sequence, psn);
469 silc_hmac_update(hmac, psn, 4);
470 silc_hmac_update(hmac, buffer->data, buffer->len);
471 silc_hmac_final(hmac, mac, &mac_len);
473 /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
474 if (memcmp(buffer->tail, mac, mac_len)) {
475 SILC_LOG_ERROR(("MAC failed"));
479 SILC_LOG_DEBUG(("MAC is Ok"));
480 memset(mac, 0, sizeof(mac));
486 /* Decrypts rest of the packet (after decrypting just the SILC header).
487 After calling this function the packet is ready to be parsed by calling
488 silc_packet_parse. If everything goes without errors this returns TRUE,
489 if packet is malformed this returns FALSE. */
491 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
496 /* Pull MAC from packet before decryption */
498 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
499 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
501 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
506 SILC_LOG_DEBUG(("Decrypting rest of the packet"));
508 /* Decrypt rest of the packet */
509 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
510 silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len,
512 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
514 SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
515 buffer->data, buffer->len);
521 /* Decrypts rest of the SILC Packet header that has been decrypted partly
522 already. This decrypts the padding of the packet also. After calling
523 this function the packet is ready to be parsed by calling function
524 silc_packet_parse. This is used in special packet reception (protocol
525 defines the way of decrypting special packets). */
527 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
531 /* Decrypt rest of the header plus padding */
535 /* Pull MAC from packet before decryption */
537 if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
538 silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
540 SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
545 SILC_LOG_DEBUG(("Decrypting rest of the header"));
547 /* padding length + src id len + dst id len + header length - 16
548 bytes already decrypted, gives the rest of the encrypted packet */
549 len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
550 (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
551 SILC_PACKET_MIN_HEADER_LEN);
553 silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
554 if (len > buffer->len) {
555 SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
559 silc_cipher_decrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
560 silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
561 SILC_LOG_HEXDUMP(("packet, len %d", buffer->len),
562 buffer->data, buffer->len);
568 /* Decrypts a packet. This assumes that typical SILC packet is the
569 packet to be decrypted and thus checks for normal and special SILC
570 packets and can handle both of them. This also computes and checks
571 the HMAC of the packet. If any other special or customized decryption
572 processing is required this function cannot be used. This returns
573 -1 on error, 0 when packet is normal packet and 1 when the packet
574 is special and requires special processing.
576 The `check_packet' is a callback funtion that this function will
577 call. The callback relates to the checking whether the packet is
578 normal packet or special packet and how it should be processed. If
579 the callback return TRUE the packet is normal and FALSE if the packet
580 is special and requires special procesing. */
582 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
583 SilcUInt32 sequence, SilcBuffer buffer,
586 /* If the packet type is not any special type lets decrypt rest
587 of the packet here. */
588 if (normal == TRUE) {
589 /* Normal packet, decrypt rest of the packet */
590 if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
594 if (!silc_packet_check_mac(hmac, buffer, sequence))
599 /* Packet requires special handling, decrypt rest of the header.
600 This only decrypts. */
601 if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
605 if (!silc_packet_check_mac(hmac, buffer, sequence))
612 /* Parses the packet. This is called when a whole packet is ready to be
613 parsed. The buffer sent must be already decrypted before calling this
614 function. The len argument must be the true length of the packet. This
615 function returns the type of the packet. The data section of the
616 buffer is parsed, not head or tail sections. */
618 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
620 SilcBuffer buffer = ctx->buffer;
624 SILC_LOG_DEBUG(("Parsing incoming packet"));
626 /* Check the length of the buffer */
627 if (buffer->len < SILC_PACKET_MIN_LEN) {
628 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
629 return SILC_PACKET_NONE;
632 /* Parse the buffer. This parses the SILC header of the packet. */
633 len = silc_buffer_unformat(buffer,
634 SILC_STR_UI_SHORT(&ctx->truelen),
635 SILC_STR_UI_CHAR(&ctx->flags),
636 SILC_STR_UI_CHAR(&ctx->type),
637 SILC_STR_UI_CHAR(&ctx->padlen),
638 SILC_STR_UI_CHAR(&tmp),
639 SILC_STR_UI_CHAR(&ctx->src_id_len),
640 SILC_STR_UI_CHAR(&ctx->dst_id_len),
641 SILC_STR_UI_CHAR(&ctx->src_id_type),
643 if (len == -1 || tmp != 0)
644 return SILC_PACKET_NONE;
646 if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
647 ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
648 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
649 ctx->src_id_len, ctx->dst_id_len));
650 return SILC_PACKET_NONE;
653 silc_buffer_pull(buffer, len);
654 ret = silc_buffer_unformat(buffer,
655 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
657 SILC_STR_UI_CHAR(&ctx->dst_id_type),
658 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
660 SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
663 return SILC_PACKET_NONE;
665 silc_buffer_push(buffer, len);
667 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
668 ctx->buffer->data, ctx->buffer->len);
670 /* Pull SILC header and padding from packet */
671 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
672 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
674 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
679 /* Perform special SILC Packet header parsing. This is required to some
680 packet types that have the data payload encrypted with different key
681 than the header area plus padding of the packet. Hence, this parses
682 the header in a way that it does not take the data area into account
683 and parses the header and padding area only. */
685 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
688 SilcBuffer buffer = ctx->buffer;
692 SILC_LOG_DEBUG(("Parsing incoming packet"));
694 /* Check the length of the buffer */
695 if (buffer->len < SILC_PACKET_MIN_LEN) {
696 SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
697 return SILC_PACKET_NONE;
700 /* Parse the buffer. This parses the SILC header of the packet. */
701 len = silc_buffer_unformat(buffer,
702 SILC_STR_UI_SHORT(&ctx->truelen),
703 SILC_STR_UI_CHAR(&ctx->flags),
704 SILC_STR_UI_CHAR(&ctx->type),
705 SILC_STR_UI_CHAR(&ctx->padlen),
706 SILC_STR_UI_CHAR(&tmp),
707 SILC_STR_UI_CHAR(&ctx->src_id_len),
708 SILC_STR_UI_CHAR(&ctx->dst_id_len),
709 SILC_STR_UI_CHAR(&ctx->src_id_type),
711 if (len == -1 || tmp != 0) {
712 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
713 return SILC_PACKET_NONE;
716 if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
717 ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
718 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
719 ctx->src_id_len, ctx->dst_id_len));
720 return SILC_PACKET_NONE;
723 silc_buffer_pull(buffer, len);
724 ret = silc_buffer_unformat(buffer,
725 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
727 SILC_STR_UI_CHAR(&ctx->dst_id_type),
728 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
730 SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
733 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
734 return SILC_PACKET_NONE;
737 silc_buffer_push(buffer, len);
739 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
740 ctx->buffer->data, ctx->buffer->len);
742 /* Pull SILC header and padding from packet */
743 silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
744 ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
746 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
751 /* Allocate packet context */
753 SilcPacketContext *silc_packet_context_alloc(void)
755 SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
762 /* Increse the reference count of the packet context. */
764 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
767 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
772 /* Decrese the reference count of the packet context and free it only if
775 void silc_packet_context_free(SilcPacketContext *ctx)
778 SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
783 silc_buffer_free(ctx->buffer);
785 silc_free(ctx->src_id);
787 silc_free(ctx->dst_id);