Reworking layer2 subsystem
[oonf.git] / docs / rfc5444 / rfc5444_reader.txt
1 RFC 5444 handler library
2 Copyright (c) 2010 Henning Rogge <hrogge@googlemail.com>
3
4 The rfc 5444 library is a combined parser and generator for the
5 'Generalized Mobile Ad Hoc Network (MANET) Packet/Message Format'.
6 The library is split into a separate reader and writer part, both
7 of them use a generic avl-tree and double-linked list implementation.
8
9 The reader and writer allow multiple independent code blocks to read
10 overlapping parts of a RFC 5444 data stream and assemble packets and
11 messages together. This allow API users to separate different sub-
12 protocol in their codebase (e.g. NHDP and OLSRv2).
13
14
15 =======================
16     RFC 5444 reader
17 =======================
18
19 1) general information
20 1.1) using the reader
21 1.2) rfc5444_reader_tlvblock_context
22 1.3) rfc5444_reader_tlvblock_entry
23 1.4) order of callbacks while parsing a rfc5444 stream
24 2) block callback
25 2.1) setting up a Block Callback
26 2.2) implementing the block callback
27 3) stream callbacks
28 4) message forwarding
29
30
31 1) General information
32 **********************
33
34 The basic blocks of information of rfc5444 are addresses of 1 to 16
35 bytes and TLVs. TLV is a shortcut for type-length-value. Each piece
36 of data which is not included in packet, message or address header
37 has a type and a length field, which allows a parser which does not
38 know this TLV to skip to the next TLV without being forced to stop
39 parsing the data stream.
40  
41 The RFC 5444 reader is based on the concept of tlv-block consumers
42 as the basic entities for reading RFC 5444. TLV-blocks can exist on
43 three different levels of hierarchy in RFC 5444:
44
45   * packet TLVs
46   * message TLVs
47   * address TLVs
48
49 Each consumer registers on one of this three levels and can use two
50 different kinds of callbacks to learn about the relevant TLV-block and
51 its context. Both group of callbacks can be used in the same consumer.
52
53 The first callback is the block_callback. It allows the consumer to
54 define a set of TLVs it's interested in. The parser collects all
55 TLV data defined in the set and calls the block_callback.
56 Hence the processing is block-oriented.
57
58 The other callbacks allow a more stream oriented handling of rfc5444
59 data:
60
61  * start_callback
62  * tlv_callback
63  * end_callback
64
65 For each consumer context (packet, message or address) the parser calls
66 the start_callback first, then it calls the tlv_callback for each TLV
67 in the context and finally the end_callback.
68
69 Each consumer has a priority, which defines the order in which the
70 parser calls the consumers. Early consumers can tell the parser to
71 stop processing the current context or the whole packet, which allows
72 creating of security or semantic checking consumers.
73
74 Both block and stream callbacks return two kind of data structures,
75 rfc5444_reader_tlvblock_context and rfc5444_reader_tlvblock_entry. The block
76 callback initializes a pointer to the second one for each
77 rfc5444_reader_tlvblock_consumer_entry it finds in the rfc5444 stream.
78
79
80 1,1) Using the reader
81 *********************
82
83 The rfc5444 reader is very simple to use.
84
85 First the user has to allocate a rfc5444 reader context with
86 rfc5444_reader_init(). All functions of the reader require a pointer to this
87 context as a parameter.
88 If you don't need the reader anymore, call rfc5444_reader_cleanup() to
89 free all allocated memory of the reader including the reader context
90 itself.
91
92 After allocating the context you can register and unregister all
93 necessary callbacks to the reader, as long as you do this outside
94 of the reader callbacks itself!
95
96 To parse binary rfc5444, just call rfc5444_reader_handle_packet(). 
97
98 Example:
99   (...)
100   struct rfc5444_reader *context;
101
102   context = rfc5444_reader_init();
103   assert(context);
104   (...)
105
106
107
108 1.2) rfc5444_reader_tlvblock_context
109 ********************************
110
111 There is a second context: the tlvblock context tells the callback about the
112 enclosing packet header, message header and address entry. It contains all
113 relevant fields of the parsed headers.
114
115 The first field "type" of the context is an enum that defines the scope of the
116 context.
117
118 A type CONTEXT_PACKET applies to callbacks for packet scope and packet tlvs,
119 which means that one the fields relevant for packets are initialized. This
120 context will contain the packet version, it's flags field and (if available)
121 the packet sequence number.
122
123 A type CONTEXT_MESSAGE applies to callbacks for message scope and tlvs. It
124 contains all the data of the packet context in addition to the relevant fields
125 of the message header (msg type, flags, address length and the four optional
126 fields hopcount, hoplimit, originator address and sequence number).
127
128 The last type CONTEXT_ADDRESS applies to an address and it's tlvs.  It contains
129 all data of packet and message context plus the address and its prefix length.
130
131 The whole struct is read-only, DO NOT MODIFY the fields inside
132 a callback.
133
134
135 1.3) rfc5444_reader_tlvblock_entry
136 ******************************
137
138 The tlvblock entry contains the data about a single tlv. It
139 contains the type of the tlv (including the extension type),
140 the raw flags field, the length of the value, a pointer to
141 the binary value (NULL if length is zero) and the index fields
142 for address block TLVs.
143
144 The whole struct is read-only, DO NOT MODIFY the fields inside
145 a callback.
146
147
148 1.4) Order of callbacks while parsing a rfc5444 stream
149 *******************************************************
150
151 The total order of callbacks can be described as:
152
153  * packet consumer "order 1"
154    - start_callback
155    - tlv_callback (tlv_1)
156    - ...
157    - tlv_callback (tlv_n)
158    - block_callback (tlvs)
159  * packet_consumer "order 2"
160    - start_callback
161    - tlv_callback (tlv_1)
162    - ...
163    - tlv_callback (tlv_n)
164    - block_callback (tlvs)
165  
166    * message_consumer "order 1"
167      - start_callback
168      - tlv_callback (tlv_1)
169      - ...
170      - tlv_callback (tlv_n)
171      - block_callback (tlvs)
172
173    * address_consumer "order 1"
174      * address addr_1
175        - start_callback (addr_1)
176        - tlv_callback (addr_1, tlv_1)
177        - ...
178        - tlv_callback (addr_1, tlv_n)
179        - block_callback (tlvs)
180        - end_callback (addr_1)
181    
182      * address addr_2
183        - start_callback (addr_2)
184        - tlv_callback (addr_2, tlv_1)
185        - ...
186        - tlv_callback (addr_2, tlv_n)
187        - block_callback (tlvs)
188        - end_callback (addr_2)
189  
190    * message_consumer "order 1"
191      - end_callback
192   
193    * message_consumer "order 2"
194      - start_callback
195      - tlv_callback (tlv_1)
196      - ...
197      - tlv_callback (tlv_n)
198      - block_callback (tlvs)
199      - end_callback
200
201    * address_consumer "order 3"
202      * address addr_1
203        - start_callback (addr_1)
204        - tlv_callback (addr_1, tlv_1)
205        - ...
206        - tlv_callback (addr_1, tlv_n)
207        - block_callback (tlvs)
208        - end_callback (addr_1)
209    
210      * address addr_2
211        - start_callback (addr_2)
212        - tlv_callback (addr_2, tlv_1)
213        - ...
214        - tlv_callback (addr_2, tlv_n)
215        - block_callback (tlvs)
216        - end_callback (addr_2)
217  
218  * packet_consumer "order 2"
219    - end_callback
220  
221  * packet_consumer "order 1"
222    - end_callback
223
224  
225 2.) Block callback
226 ******************
227
228 The block callback allows you to define a filter for a specific context
229 (packet, message or address) and get data about a fixed number of TLVs
230 your callback needs to know about.
231
232 This makes writing multiple TLV callbacks just to collect the different
233 TLVs from a message or address just to store them in a temporary data
234 structure unnecessary.
235
236
237 2.1) Setting up a Block Callback
238 ********************************
239
240 The first option to parse rfc5444 data is the block_callback.
241 The block_callback is initialized by an array of
242 rfc5444_reader_tlvblock_consumer_entry objects.
243
244 struct rfc5444_reader_tlvblock_consumer_entry consumer[] = {
245     { .type = 4 },
246     { .type = 1, .match_type_ext = true, .type_ext = 1 },
247     { .type = 2, .mandatory = true },
248     { .type = 6, .copy_value = &value, .copy_value_maxlen = sizeof(value) }
249 };
250
251 ...
252     struct rfc5444_reader *context;
253     struct rfc5444_reader_tlvblock_consumer *consumer;
254     ....
255     
256     consumer = rfc5444_reader_add_message_consumer(context,
257       consumer, ARRAYSIZE(consumer),
258       2, /* msg type */
259       1  /* order */);
260     consumer->block_callback = my_block_callback;
261
262 Each entry of the array represents a single TLV type of
263 the context. There are three different optional settings
264 in addition to the tlv type, which can be combined:
265
266  * mandatory (boolean)
267  * match_type_ext (boolean) and type_ext (uint8_t)
268  * copy_value (void *) and copy_value_maxlen (size_t)
269
270 By setting mandatory to 'true' in an entry of the
271 rfc5444_reader_tlvblock_consumer_entry array the consumer tells the parser that
272 the TLV is mandatory. The parser keeps track if all mandatory TLVs
273 are available and tells the consumer this by a callback parameter.
274
275 Setting match_type_ext to 'true' let the consumer specify which extended
276 type of the TLV is relevant for this entry. If not set the type_ext
277 variable is ignored and the first TLV with a matching type (and any kind
278 of extended type) will be used for the block callback.
279
280 Copy_value tells the parser to copy the value of the TLV to a private
281 buffer of the consumer. The copy_value_maxlen variable has to be set
282 to the maximum number of bytes available in the private buffer to
283 prevent a buffer overflow.
284
285
286 2.2) Implementing the block callback
287 ***********************************
288
289 The block callback has three parameters. The first is a pointer to the
290 tlvblock consumer object returned by the register function. The second
291 one is a pointer to a rfc5444_reader_tlvblock_context object, which contains the
292 packet sequence number, the decoded content of the message header (for
293 message and address consumers) and the current address (only for address
294 consumers). The last parameter mandatory_missing is true if one of the
295 tlv entries marked as mandatory is missing.
296
297 enum rfc5444_result
298 callback(struct rfc5444_reader_tlvblock_consumer *consumer,
299       struct rfc5444_reader_tlvblock_context *context,
300       bool mandatory_missing) {
301     ...
302     return RFC5444_OKAY;
303 }
304
305 For each tlv in the block with a corresponding array entry, the parser
306 initializes a rfc5444_reader_tlvblock_entry pointer in the entry which contains
307 all data about the original tlv, including type(ext), value and/or
308 indices.
309
310 The default return value of the block callback is RFC5444_OKAY, which tells
311 the parser that everything is right and the next callback should be called.
312
313 See README.dropcontext for other return values.
314
315
316 3) Stream callbacks
317 *******************
318
319 The stream callbacks are a group of three callbacks that are similar
320 to a SAX XML parser. The consumer gets one callback when its
321 context (the packet, message or address) starts, one callback for each
322 TLV inside the context (with a pointer to a rfc5444_reader_tlvblock_context and
323 a rfc5444_reader_tlvblock_entry object) and one callback when the context ends.
324
325 enum rfc5444_result
326 my_start_callback(struct rfc5444_reader_tlvblock_consumer *,
327        struct rfc5444_reader_tlvblock_context *context) {
328     ...
329     return RFC5444_OKAY;
330 }
331
332 enum rfc5444_result
333 my_tlv_callback(struct rfc5444_reader_tlvblock_entry *,
334       struct rfc5444_reader_tlvblock_context *context) {
335     ...
336     return RFC5444_OKAY;
337 }
338
339 enum rfc5444_result
340 my_end_callback(struct rfc5444_reader_tlvblock_consumer *, 
341       struct rfc5444_reader_tlvblock_context *context,
342       bool dropped);
343     ...
344     return RFC5444_OKAY;
345 }
346
347 ...
348     struct rfc5444_reader *context;
349     struct rfc5444_reader_tlvblock_consumer *consumer;
350     ....
351     
352     consumer = rfc5444_reader_add_message_consumer(context,
353       consumer, ARRAYSIZE(consumer),
354       2, /* msg type */
355       1  /* order */);
356     consumer->start_callback = my_start_callback;
357     consumer->tlv_callback = my_tlv_callback;
358     consumer->end_callback = my_end_callback;
359
360 These three callbacks allow the consumer to analyze the whole tlv-block
361 stream in a linear order without missing duplicate TLVs or unknown one,
362 but are more complex to use for most protocol implementations.
363
364 The end callback has an additional boolean parameter called drop, which tells
365 the callback that the context has been dropped by an earlier callback.
366
367 The default return value of this callbacks is RFC5444_OKAY, which tells
368 the parser that everything is right and the next callback should be called.
369
370 See README.dropcontext for other return values.
371
372
373 4) message forwarding
374 *********************
375
376 Each time after a message has been parsed by all callbacks the parser
377 checks if it should be forwarded to other nodes (hoplimit must be present
378 in the header for this). If yes the message will be forwarded by calling
379 the forward_message() callback of the reader context.