/*
 * ipv6_reassembly.h
 *
 * =========================================================================
 * Copyright (c) 2012-2019 Daniele De Sensi (d.desensi.software@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * =========================================================================
 */

#ifndef PFWL_IPV6_REASSEMBLY_H_
#define PFWL_IPV6_REASSEMBLY_H_

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct pfwl_ipv6_fragmentation_state pfwl_ipv6_fragmentation_state_t;

/**
 * Enables the IPv6 defragmentation.
 * @param table_size  The size of the table used to store the fragments.
 * @return            A pointer to the IPv6 defragmentation handle.
 */
pfwl_ipv6_fragmentation_state_t *
pfwl_reordering_enable_ipv6_fragmentation(uint16_t table_size);

/**
 * Sets the maximum amount of memory that can be used to store
 * fragments generated by the same source.
 * @param frag_state A pointer to the IPv6 degragmentation handle.
 * @param per_host_memory_limit  The maximum amount of memory that can be
 *                               used to store fragments generated by the
 *                               same source.
 */
void pfwl_reordering_ipv6_fragmentation_set_per_host_memory_limit(
    pfwl_ipv6_fragmentation_state_t *frag_state,
    uint32_t per_host_memory_limit);

/**
 * Sets the maximum (global) amount of memory that can be used for
 * defragmentation purposes.
 * @param frag_state A pointer to the IPv6 defragmentation handle.
 * @param total_memory_limit   The global memory limit.
 */
void pfwl_reordering_ipv6_fragmentation_set_total_memory_limit(
    pfwl_ipv6_fragmentation_state_t *frag_state, uint32_t total_memory_limit);

/**
 * Sets the maximum amount of time (seconds) which can elapse before the
 * complete defragmentation of the datagram.
 * @param frag_state        A pointer to the IPv6 defragmentation handle.
 * @param timeout_seconds   The timeout (seconds).
 */
void pfwl_reordering_ipv6_fragmentation_set_reassembly_timeout(
    pfwl_ipv6_fragmentation_state_t *frag_state, uint8_t timeout_seconds);

/**
 * Disables the IPv6 fragmentation and deallocates the handle.
 * @param frag_state  A pointer to the IPv6 defragmentation handle.
 */
void pfwl_reordering_disable_ipv6_fragmentation(
    pfwl_ipv6_fragmentation_state_t *frag_state);

/**
 * Reassemble the IP datagram if it is fragmented.
 * @param state The state for fragmentation support.
 * @param unfragmentable_start A pointer to the beginning of
 * unfragmentable part. We suppose that unfragmentable and
 * fragmentable data are in the same buffer.
 * @param unfragmentable_size The size of the unfragmentable part.
 * In principle this could obtained by difference (fragmentable_start-
 * unfragmentable_start). By the way this additional level of flexibility
 * allows to store only a part of the unfragmentable header (e.g. only the
 * IPv6 header without additional headers).
 * @param fragmentable_start A pointer to the beginning of the
 * fragmentable part.
 * @param fragmentable_size Size of the fragmentable part.
 * @param offset The data offset specified in the IPv6 fragmentation
 * header.
 * @param more_fragments 1 if the MF flag is set, 0 otherwise.
 * @param identification The identification of the datagram.
 * @param next_header The header which follows the fragmentation
 * header.
 * @param current_time The current time, in seconds.
 * @param tid The thread identifier.
 * @return Returns NULL if the datagram is a fragment but doesn't fill
 * an hole. In this case, the content of the datagram has been copied,
 * so if the user wants, he can release the resources used to store the
 * received packet.
 * Returns a pointer to the recomposed datagram if the datagram is the
 * last fragment of a bigger datagram. This pointer will be different
 * from data. The user should free() this pointer when it is no more
 * needed.
 */
unsigned char *pfwl_reordering_manage_ipv6_fragment(
    pfwl_ipv6_fragmentation_state_t *state,
    const unsigned char *unfragmentable_start, uint16_t unfragmentable_size,
    const unsigned char *fragmentable_start, uint16_t fragmentable_size,
    uint16_t offset, uint8_t more_fragments, uint32_t identification,
    uint8_t next_header, uint32_t current_time, int tid);

#ifdef __cplusplus
}
#endif
#endif /* PFWL_IPV6_REASSEMBLY_H_ */
