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