nmsg 1.1.2
base/ipreasm.h
1#ifndef NMSG_BASE_IPREASM_H
2#define NMSG_BASE_IPREASM_H
3
4/*
5 * Copyright (c) 2007 Jan Andres <jandres@gmx.net>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 */
11
12#include <stdbool.h>
13#include <stdint.h>
14#include <time.h>
15
16struct reasm_ip;
17
18enum entry_state {
19 STATE_ACTIVE,
20 STATE_INVALID
21};
22
23enum reasm_proto {
24 PROTO_IPV4,
25 PROTO_IPV6
26};
27
28/*
29 * This tuple uniquely identifies all fragments belonging to
30 * the same IPv4 packet.
31 */
33 uint8_t ip_src[4];
34 uint8_t ip_dst[4];
35 uint16_t ip_id;
36 uint8_t ip_proto;
37};
38
39/*
40 * Same for IPv6.
41 */
43 uint8_t ip_src[16];
44 uint8_t ip_dst[16];
45 uint32_t ip_id;
46};
47
48union reasm_id {
49 struct reasm_id_ipv4 ipv4;
50 struct reasm_id_ipv6 ipv6;
51};
52
54 struct timespec ts;
55 unsigned len; /* payload length of this fragment */
56 unsigned offset; /* offset of this fragment into the payload of the reassembled packet */
57 unsigned data_offset; /* offset to the data pointer where payload starts */
58 unsigned last_nxt;
59 unsigned ip6f_nxt;
60 uint8_t *data; /* payload starts at data + data_offset */
61 struct reasm_frag_entry *next;
62};
63
64/*
65 * Reception of a complete packet is detected by counting the number
66 * of "holes" that remain between the cached fragments. A hole is
67 * assumed to exist at the upper end of the packet until the final
68 * fragment has been received. When the number of holes drops to 0,
69 * all fragments have been received and the packet can be reassembled.
70 */
72 union reasm_id id;
73 unsigned len;
74 unsigned holes;
75 unsigned frag_count;
76 unsigned hash;
77 struct timespec timeout;
78 enum entry_state state;
79 enum reasm_proto protocol;
80 struct reasm_frag_entry *frags;
81 struct reasm_ip_entry *prev, *next;
82 struct reasm_ip_entry *time_prev, *time_next;
83};
84
85/*
86 * Functions to create and destroy the reassembly environment.
87 */
88struct reasm_ip *reasm_ip_new(void);
89void reasm_ip_free(struct reasm_ip *reasm);
90
91/*
92 * This is the main packet processing function. It inputs one packet,
93 * and MAY output one packet in turn. If the input was not a fragment,
94 * no output is generated, and false is returned. If the input was a
95 * fragment, true is returned.
96 * The unsigned pointed to by output_len should initially be set to the
97 * size of the buffer behind out_packet. On return, it will be set to
98 * the length of the packet returned, or 0 if no packet was returned
99 * (this will happen if a fragment is recognized, but reassembly of the
100 * corresponding packet has not completed yet).
101 */
102bool reasm_ip_next(struct reasm_ip *reasm, const uint8_t *packet, unsigned len,
103 const struct timespec *timestamp, struct reasm_ip_entry **out_entry);
104
105/*
106 * Create fragment structure from an IPv4 or IPv6 packet. Returns NULL
107 * if the input is not a fragment.
108 *
109 * \param[in] packet
110 * \param[in] len
111 * \param[in] ts
112 * \param[out] protocol
113 * \param[out] id
114 * \param[out] hash
115 * \param[out] last_frag
116 */
117struct reasm_frag_entry *reasm_parse_packet(const uint8_t *packet, unsigned len,
118 const struct timespec *ts,
119 enum reasm_proto *protocol, union reasm_id *id,
120 unsigned *hash, bool *last_frag);
121
122/*
123 * Set the timeout after which a noncompleted reassembly expires.
124 */
125bool reasm_ip_set_timeout(struct reasm_ip *reasm, const struct timespec *timeout);
126
127/*
128 * Query certain information about the current state.
129 */
130unsigned reasm_ip_waiting(const struct reasm_ip *reasm);
131unsigned reasm_ip_max_waiting(const struct reasm_ip *reasm);
132unsigned reasm_ip_timed_out(const struct reasm_ip *reasm);
133unsigned reasm_ip_dropped_frags(const struct reasm_ip *reasm);
134
135/*
136 * Is the entry complete, ready for reassembly?
137 */
138bool reasm_is_complete(struct reasm_ip_entry *entry);
139
140/*
141 * Create the reassembled packet.
142 *
143 * \param[in] entry
144 * \param[out] out_packet
145 * \param[in,out] output_len
146 */
147void reasm_assemble(struct reasm_ip_entry *entry,
148 uint8_t *out_packet, size_t *output_len);
149
150/*
151 * Insert a new fragment to the correct position in the list of fragments.
152 * Check for fragment overlap and other error conditions.
153 */
154bool reasm_add_fragment(struct reasm_ip_entry *entry,
155 struct reasm_frag_entry *frag,
156 bool last_frag);
157
158void reasm_free_entry(struct reasm_ip_entry *entry);
159
160#endif /* NMSG_BASE_IPREASM_H */