From: Pekka Riikonen Date: Wed, 6 Dec 2006 18:36:58 +0000 (+0000) Subject: Fixed UDP transport handling. X-Git-Tag: silc.client.1.1.beta1~139 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=a48f197048c2cad8fc48062bf00c71ece3f3c9e3 Fixed UDP transport handling. --- diff --git a/lib/silccore/silcpacket.c b/lib/silccore/silcpacket.c index 05ca279d..e2bf3125 100644 --- a/lib/silccore/silcpacket.c +++ b/lib/silccore/silcpacket.c @@ -151,10 +151,24 @@ do { \ (s)->stream_context); \ } while(0) +static void silc_packet_dispatch(SilcPacket packet); +static void silc_packet_read_process(SilcPacketStream stream); /************************ Static utility functions **************************/ -static void silc_packet_read_process(SilcPacketStream stream); +/* Injects packet to new stream created with silc_packet_stream_add_remote. */ + +SILC_TASK_CALLBACK(silc_packet_stream_inject_packet) +{ + SilcPacket packet = context; + SilcPacketStream stream = packet->stream; + + SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream)); + + silc_mutex_lock(stream->lock); + silc_packet_dispatch(packet); + silc_mutex_unlock(stream->lock); +} /* Write data to the stream. Must be called with ps->lock locked. Unlocks the lock inside this function. */ @@ -328,6 +342,7 @@ static inline SilcBool silc_packet_stream_read(SilcPacketStream ps, } /* Save sender IP and port */ + silc_free(ps->remote_udp->remote_ip); ps->remote_udp->remote_ip = strdup(remote_ip); ps->remote_udp->remote_port = remote_port; @@ -611,7 +626,8 @@ SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine, SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream, const char *remote_ip, - SilcUInt16 remote_port) + SilcUInt16 remote_port, + SilcPacket packet) { SilcPacketEngine engine = stream->engine; SilcPacketStream ps; @@ -688,6 +704,14 @@ SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream, return NULL; } + if (packet) { + /* Inject packet to the new stream */ + packet->stream = ps; + silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream), + silc_packet_stream_inject_packet, packet, + 0, 0); + } + return ps; } @@ -888,15 +912,15 @@ void silc_packet_stream_unlink(SilcPacketStream stream, /* Return packet sender IP and port for UDP packet stream */ -SilcBool silc_packet_stream_get_sender(SilcPacketStream stream, - const char **sender_ip, - SilcUInt16 *sender_port) +SilcBool silc_packet_get_sender(SilcPacket packet, + const char **sender_ip, + SilcUInt16 *sender_port) { - if (!stream->remote_udp) + if (!packet->stream->remote_udp) return FALSE; - *sender_ip = stream->remote_udp->remote_ip; - *sender_port = stream->remote_udp->remote_port; + *sender_ip = packet->stream->remote_udp->remote_ip; + *sender_port = packet->stream->remote_udp->remote_port; return TRUE; } @@ -1439,12 +1463,12 @@ SilcBool silc_packet_send_va_ext(SilcPacketStream stream, /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */ -static SilcBool silc_packet_check_mac(SilcHmac hmac, - const unsigned char *data, - SilcUInt32 data_len, - const unsigned char *packet_mac, - const unsigned char *packet_seq, - SilcUInt32 sequence) +static inline SilcBool silc_packet_check_mac(SilcHmac hmac, + const unsigned char *data, + SilcUInt32 data_len, + const unsigned char *packet_mac, + const unsigned char *packet_seq, + SilcUInt32 sequence) { /* Check MAC */ if (hmac) { @@ -1480,9 +1504,9 @@ static SilcBool silc_packet_check_mac(SilcHmac hmac, /* Decrypts SILC packet. Handles both normal and special packet decryption. Return 0 when packet is normal and 1 when it it special, -1 on error. */ -static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac, - SilcUInt32 sequence, SilcBuffer buffer, - SilcBool normal) +static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac, + SilcUInt32 sequence, SilcBuffer buffer, + SilcBool normal) { if (normal == TRUE) { if (cipher) { @@ -1528,7 +1552,7 @@ static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac, parsed. The buffer sent must be already decrypted before calling this function. */ -static SilcBool silc_packet_parse(SilcPacket packet) +static inline SilcBool silc_packet_parse(SilcPacket packet) { SilcBuffer buffer = &packet->buffer; SilcUInt8 padlen = (SilcUInt8)buffer->data[4]; @@ -1546,14 +1570,18 @@ static SilcBool silc_packet_parse(SilcPacket packet) SILC_STR_UI_CHAR(&src_id_type), SILC_STR_END); if (ret == -1) { - SILC_LOG_ERROR(("Malformed packet header, packet dropped")); + if (!packet->stream->udp && + !silc_socket_stream_is_udp(packet->stream->stream, NULL)) + SILC_LOG_ERROR(("Malformed packet header, packet dropped")); return FALSE; } if (src_id_len > SILC_PACKET_MAX_ID_LEN || dst_id_len > SILC_PACKET_MAX_ID_LEN) { - SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)", - packet->src_id_len, packet->dst_id_len)); + if (!packet->stream->udp && + !silc_socket_stream_is_udp(packet->stream->stream, NULL)) + SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)", + packet->src_id_len, packet->dst_id_len)); return FALSE; } @@ -1565,14 +1593,18 @@ static SilcBool silc_packet_parse(SilcPacket packet) SILC_STR_OFFSET(padlen), SILC_STR_END); if (ret == -1) { - SILC_LOG_ERROR(("Malformed packet header, packet dropped")); + if (!packet->stream->udp && + !silc_socket_stream_is_udp(packet->stream->stream, NULL)) + SILC_LOG_ERROR(("Malformed packet header, packet dropped")); return FALSE; } if (src_id_type > SILC_ID_CHANNEL || dst_id_type > SILC_ID_CHANNEL) { - SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)", - src_id_type, dst_id_type)); + if (!packet->stream->udp && + !silc_socket_stream_is_udp(packet->stream->stream, NULL)) + SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)", + src_id_type, dst_id_type)); return FALSE; } @@ -1600,15 +1632,6 @@ static void silc_packet_dispatch(SilcPacket packet) SilcBool default_sent = FALSE; SilcPacketType *pt; - /* Parse the packet */ - if (!silc_packet_parse(packet)) { - silc_mutex_unlock(stream->lock); - SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED); - silc_mutex_lock(stream->lock); - silc_packet_free(packet); - return; - } - /* Dispatch packet to all packet processors that want it */ if (!stream->process) { @@ -1779,7 +1802,8 @@ static void silc_packet_read_process(SilcPacketStream stream) /* Sanity checks */ if (packetlen < SILC_PACKET_MIN_LEN) { - SILC_LOG_ERROR(("Received too short packet")); + if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL)) + SILC_LOG_ERROR(("Received too short packet")); silc_mutex_unlock(stream->lock); SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED); silc_mutex_lock(stream->lock); @@ -1888,6 +1912,16 @@ static void silc_packet_read_process(SilcPacketStream stream) /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */ silc_buffer_pull(&stream->inbuf, paddedlen + mac_len); + /* Parse the packet */ + if (!silc_packet_parse(packet)) { + silc_mutex_unlock(stream->lock); + SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED); + silc_mutex_lock(stream->lock); + silc_packet_free(packet); + memset(tmp, 0, sizeof(tmp)); + return; + } + /* Dispatch the packet to application */ silc_packet_dispatch(packet); } diff --git a/lib/silccore/silcpacket.h b/lib/silccore/silcpacket.h index 86f7a764..dfc65900 100644 --- a/lib/silccore/silcpacket.h +++ b/lib/silccore/silcpacket.h @@ -406,13 +406,14 @@ SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine, SilcSchedule schedule, SilcStream stream); -/****f* silccore/SilcPacketAPI/silc_packet_stream_shared_create +/****f* silccore/SilcPacketAPI/silc_packet_stream_add_remote * * SYNOPSIS * * SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream, * const char *remote_ip, - * SilcUInt16 remote_port); + * SilcUInt16 remote_port, + * SilcPacket packet); * * DESCRIPTION * @@ -427,9 +428,13 @@ SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine, * and port that does not have its own remote packet stream, it returns * the packet to the packet callback set for `stream'. The sender's * IP address and port can then be retrieved by using the - * silc_packet_stream_get_sender function and to create new packet - * stream by calling this function. After that, all packets from that - * IP address and port will be received by the new packet stream. + * silc_packet_get_sender function and to create new packet stream by + * calling this function. After that, all packets from that IP address + * and port will be received by the new packet stream. + * + * If the `packet' is non-NULL it will be injected into the new packet + * stream as soon as the scheduler associated with `stream' schedules + * new tasks. It can be used to inject an incoming packet to the stream. * * This interface is for connectionless UDP streams. If it is possible * to create connected stream it should be done for performance reasons. @@ -442,15 +447,16 @@ SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine, * * ... * // Received a packet to the parent stream, get the sender information. - * silc_packet_stream_get_sender(parent, &ip, &port); + * silc_packet_get_sender(packet, &ip, &port); * * // Create new packet stream for this remote location. - * remote = silc_packet_stream_set_remote(parent, ip, port); + * remote = silc_packet_stream_add_remote(parent, ip, port, packet); * ***/ SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream, const char *remote_ip, - SilcUInt16 remote_port); + SilcUInt16 remote_port, + SilcPacket packet); /****f* silccore/SilcPacketAPI/silc_packet_stream_destroy * @@ -606,25 +612,25 @@ void silc_packet_stream_unlink(SilcPacketStream stream, SilcPacketCallbacks *callbacks, void *callback_context); -/****f* silccore/SilcPacketAPI/silc_packet_stream_get_sender +/****f* silccore/SilcPacketAPI/silc_packet_get_sender * * SYNOPSIS * - * SilcBool silc_packet_stream_get_sender(SilcPacketStream stream, - * const char **sender_ip, - * SilcUInt16 *sender_port); + * SilcBool silc_packet_get_sender(SilcPacket packet, + * const char **sender_ip, + * SilcUInt16 *sender_port); * * DESCRIPTION * - * Returns the packet sender's IP address and port from UDP packet stream - * indicated by `stream'. This can be called only from the packet + * Returns the packet sender's IP address and port from UDP packet + * indicated by `packet'. This can be called only from the packet * callback to retrieve the information of the packet's sender. Returns * FALSE if the information is not available. * ***/ -SilcBool silc_packet_stream_get_sender(SilcPacketStream stream, - const char **sender_ip, - SilcUInt16 *sender_port); +SilcBool silc_packet_get_sender(SilcPacket packet, + const char **sender_ip, + SilcUInt16 *sender_port); /****f* silccore/SilcPacketAPI/silc_packet_stream_ref *