Fix DLEP handling of mandatory TLVs
[oonf.git] / src-plugins / generic / dlep / dlep_session.h
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
4  * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 /**
43  * @file
44  */
45
46 #ifndef _DLEP_SESSION_H_
47 #define _DLEP_SESSION_H_
48
49 struct dlep_session;
50 struct dlep_writer;
51
52 #include "common/autobuf.h"
53 #include "common/avl.h"
54 #include "common/common_types.h"
55 #include "common/netaddr.h"
56 #include "subsystems/oonf_layer2.h"
57 #include "subsystems/oonf_stream_socket.h"
58 #include "subsystems/oonf_timer.h"
59 #include "subsystems/os_interface.h"
60
61 #include "dlep/dlep_extension.h"
62 #include "dlep/dlep_iana.h"
63
64 /**
65  * Return codes for DLEP parser
66  */
67 enum dlep_parser_error
68 {
69   /*! parsing successful */
70   DLEP_NEW_PARSER_OKAY = 0,
71
72   /*! Signal terminates session, session is now invalid! */
73   DLEP_NEW_PARSER_TERMINDATED = -1,
74
75   /*! signal too short, incomplete TLV header */
76   DLEP_NEW_PARSER_INCOMPLETE_TLV_HEADER = -2,
77
78   /*! signal too short, incomplete TLV */
79   DLEP_NEW_PARSER_INCOMPLETE_TLV = -3,
80
81   /*! TLV type is not supported by session */
82   DLEP_NEW_PARSER_UNSUPPORTED_TLV = -4,
83
84   /*! TLV length is not supported */
85   DLEP_NEW_PARSER_ILLEGAL_TLV_LENGTH = -5,
86
87   /*! mandatory TLV is missing */
88   DLEP_NEW_PARSER_MISSING_MANDATORY_TLV = -6,
89
90   /*! this TLV must not be used more than once */
91   DLEP_NEW_PARSER_DUPLICATE_TLV = -7,
92
93   /*! out of memory error */
94   DLEP_NEW_PARSER_OUT_OF_MEMORY = -8,
95
96   /*! internal parser error, inconsistent data structures */
97   DLEP_NEW_PARSER_INTERNAL_ERROR = -9,
98 };
99
100 /**
101  * Definition of a TLV that has been parsed by DLEP
102  */
103 struct dlep_parser_tlv {
104   /*! tlv id */
105   uint16_t id;
106
107   /*! index of first session value for tlv, -1 if none */
108   int32_t tlv_first;
109
110   /*! index of last session value for tlv, -1 if none */
111   int32_t tlv_last;
112
113   /*! minimal length of tlv */
114   uint16_t length_min;
115
116   /*! maximal length of tlv */
117   uint16_t length_max;
118
119   /*! used to remove unsupported TLVs */
120   bool remove;
121
122   /*! node for session tlv tree */
123   struct avl_node _node;
124 };
125
126 /**
127  * header for binary data gathered for a TLV of a certain type
128  */
129 struct dlep_parser_value {
130   /*! index of next session value */
131   int32_t tlv_next;
132
133   /*! index of value within signal buffer */
134   uint16_t index;
135
136   /*! length of tlv in bytes */
137   uint16_t length;
138 };
139
140 /**
141  * Session for the DLEP tlv parser
142  */
143 struct dlep_session_parser {
144   /*! tree of allowed TLVs for this session */
145   struct avl_tree allowed_tlvs;
146
147   /*! array of TLV values */
148   struct dlep_parser_value *values;
149
150   /*! size of array for TLV value headers */
151   size_t value_max_count;
152
153   /*! array of active dlep extensions */
154   struct dlep_extension **extensions;
155
156   /*! number of active dlep extensions */
157   size_t extension_count;
158
159   /*! start of signal tlvs that is has been parsed */
160   const uint8_t *tlv_ptr;
161
162   /*! neighbor MAC a signal is referring to */
163   struct netaddr signal_neighbor_mac;
164 };
165
166 /**
167  * DLEP writer for TLV data
168  */
169 struct dlep_writer {
170   /*! output buffer for binary data */
171   struct autobuf *out;
172
173   /*! type of signal */
174   uint16_t signal_type;
175
176   /*! index of first byte of signal */
177   size_t signal_start;
178 };
179
180 /**
181  * Status of a DLEP neighbor
182  */
183 enum dlep_neighbor_state
184 {
185   /*! neighbor has not yet been used in session */
186   DLEP_NEIGHBOR_IDLE = 0,
187
188   /*! a destination up has been sent */
189   DLEP_NEIGHBOR_UP_SENT = 1,
190
191   /*! a destination up has been sent and acked */
192   DLEP_NEIGHBOR_UP_ACKED = 2,
193
194   /*! a destination down has been sent */
195   DLEP_NEIGHBOR_DOWN_SENT = 3,
196
197   /*! a destination down has been sent and acked*/
198   DLEP_NEIGHBOR_DOWN_ACKED = 4,
199 };
200
201 /**
202  * Neighbor that has been used in a DLEP session
203  */
204 struct dlep_local_neighbor {
205   /**
206    * mac address of the endpoint of the neighbor
207    * (might be proxied ethernet)
208    */
209   struct netaddr addr;
210
211   /*! state of neighbor */
212   enum dlep_neighbor_state state;
213
214   /*! true if the neighbor changes since the last update */
215   bool changed;
216
217   /*! true if iterative updates are be used for destination IPs */
218   bool destination_ip_iterative;
219
220   /*! mac address of the neighbors wireless interface */
221   struct netaddr neigh_addr;
222
223   /*! back-pointer to dlep session */
224   struct dlep_session *session;
225
226   /*! timeout for acknowledgement signal */
227   struct oonf_timer_instance _ack_timeout;
228
229   /*! tree of modifications which should be put into the next destination update */
230   struct avl_tree _ip_prefix_modification;
231
232   /*! hook into the sessions tree of neighbors */
233   struct avl_node _node;
234 };
235
236 /**
237  * Configuration of a dlep session
238  */
239 struct dlep_session_config {
240   /*! peer type of local session */
241   char *peer_type;
242
243   /*! discovery interval */
244   uint64_t discovery_interval;
245
246   /*! heartbeat settings for our heartbeats */
247   uint64_t heartbeat_interval;
248
249   /*! true if normal neighbors should be sent with DLEP */
250   bool send_neighbors;
251
252   /*! true if proxied neighbors should be sent with DLEP */
253   bool send_proxied;
254 };
255
256 /**
257  * Records the state of the peer regarding PEER UPDATE messages
258  */
259 enum dlep_peer_state
260 {
261   DLEP_PEER_NOT_CONNECTED,
262   DLEP_PEER_WAIT_FOR_INIT,
263   DLEP_PEER_WAIT_FOR_UPDATE_ACK,
264   DLEP_PEER_SEND_UPDATE,
265   DLEP_PEER_IDLE,
266   DLEP_PEER_TERMINATED,
267 };
268
269 /**
270  * Generic DLEP session, might be radio or router
271  */
272 struct dlep_session {
273   /*! copy of local configuration */
274   struct dlep_session_config cfg;
275
276   /*! restrict incoming signals to a special signal */
277   enum dlep_signals restrict_signal;
278
279   /*! initialize restrict signal with this variable after processing if not 0 */
280   enum dlep_signals next_restrict_signal;
281
282   /*! true if this is a radio session */
283   bool radio;
284
285   /*! parser for this dlep session */
286   struct dlep_session_parser parser;
287
288   /*! signal writer*/
289   struct dlep_writer writer;
290
291   /*! tree of local neighbors being processed by DLEP */
292   struct avl_tree local_neighbor_tree;
293
294   /*! oonf layer2 origin for dlep session */
295   const struct oonf_layer2_origin *l2_origin;
296
297   /*! oonf layer2 origin for dlep session defaults */
298   const struct oonf_layer2_origin *l2_default_origin;
299
300   /*! send content of output buffer */
301   void (*cb_send_buffer)(struct dlep_session *, int af_family);
302
303   /*! terminate the current session */
304   void (*cb_end_session)(struct dlep_session *);
305
306   /*! handle timeout for destination */
307   void (*cb_destination_timeout)(struct dlep_session *, struct dlep_local_neighbor *);
308
309   /*! log source for usage of this session */
310   enum oonf_log_source log_source;
311
312   /*! local layer2 data interface */
313   struct os_interface_listener l2_listener;
314
315   /*! timer to generate discovery/heartbeats */
316   struct oonf_timer_instance local_event_timer;
317
318   /*! keep track of remote heartbeats */
319   struct oonf_timer_instance remote_heartbeat_timeout;
320
321   /*! rate of remote heartbeats */
322   uint64_t remote_heartbeat_interval;
323
324   /*! remote endpoint of current communication */
325   union netaddr_socket remote_socket;
326
327   /*! timeout for acknowledgement signal */
328   struct oonf_timer_instance _ack_timeout;
329
330   /*! true if we cannot send a peer update at the moment */
331   enum dlep_peer_state _peer_state;
332
333   /*! tree of modifications which should be put into the next peer update */
334   struct avl_tree _ip_prefix_modification;
335 };
336
337 void dlep_session_init(void);
338
339 int dlep_session_add(struct dlep_session *session, const char *l2_ifname, const struct oonf_layer2_origin *l2_origin,
340   const struct oonf_layer2_origin *l2_default_origin, struct autobuf *out, bool radio,
341   int (*if_changed)(struct os_interface_listener *), enum oonf_log_source);
342 void dlep_session_remove(struct dlep_session *session);
343 void dlep_session_terminate(struct dlep_session *session, enum dlep_status status, const char *status_text);
344
345 int dlep_session_update_extensions(struct dlep_session *session, const uint8_t *extvalues, size_t extcount);
346 enum oonf_stream_session_state dlep_session_process_tcp(
347   struct oonf_stream_session *tcp_session, struct dlep_session *session);
348 ssize_t dlep_session_process_buffer(struct dlep_session *session, const void *buffer, size_t length, bool is_udp);
349 ssize_t dlep_session_process_signal(struct dlep_session *session, const void *buffer, size_t length, bool is_udp);
350 int dlep_session_generate_signal(struct dlep_session *session, int32_t signal, const struct netaddr *neighbor);
351 int dlep_session_generate_signal_status(struct dlep_session *session, int32_t signal, const struct netaddr *neighbor,
352   enum dlep_status status, const char *msg);
353 struct dlep_parser_value *dlep_session_get_tlv_value(struct dlep_session *session, uint16_t tlvtype);
354
355 struct dlep_local_neighbor *dlep_session_add_local_neighbor(struct dlep_session *session, const struct netaddr *neigh);
356 void dlep_session_remove_local_neighbor(struct dlep_session *session, struct dlep_local_neighbor *local);
357 struct oonf_layer2_neigh *dlep_session_get_local_l2_neighbor(struct dlep_session *session, const struct netaddr *neigh);
358 struct oonf_layer2_neigh *dlep_session_get_l2_from_neighbor(struct dlep_local_neighbor *dlep_neigh);
359
360 /**
361  * get the dlep session tlv
362  * @param parser dlep session parser
363  * @param tlvtype tlvtype
364  * @return tlv parser information, NULL if not available
365  */
366 static INLINE struct dlep_parser_tlv *
367 dlep_parser_get_tlv(struct dlep_session_parser *parser, uint16_t tlvtype) {
368   struct dlep_parser_tlv *tlv;
369   return avl_find_element(&parser->allowed_tlvs, &tlvtype, tlv, _node);
370 }
371
372 /**
373  * Get value of first appearance of a TLV
374  * @param session dlep session parser
375  * @param tlv dlep session tlv
376  * @return dlep tlv value, NULL if no value available
377  */
378 static INLINE struct dlep_parser_value *
379 dlep_session_get_tlv_first_value(struct dlep_session *session, struct dlep_parser_tlv *tlv) {
380   if (tlv->tlv_first == -1) {
381     return NULL;
382   }
383   return &session->parser.values[tlv->tlv_first];
384 }
385
386 /**
387  * Get the next value of a TLV
388  * @param session dlep session parser
389  * @param value current dlep parser value
390  * @return next dlep tlv value, NULL if no further values
391  */
392 static INLINE struct dlep_parser_value *
393 dlep_session_get_next_tlv_value(struct dlep_session *session, struct dlep_parser_value *value) {
394   if (value->tlv_next == -1) {
395     return NULL;
396   }
397   return &session->parser.values[value->tlv_next];
398 }
399
400 /**
401  * Get the binary data of a tlv
402  * @param parser dlep session parser
403  * @param value dlep tlv value
404  * @return binary data pointer
405  */
406 static INLINE const uint8_t *
407 dlep_parser_get_tlv_binary(struct dlep_session_parser *parser, struct dlep_parser_value *value) {
408   return &parser->tlv_ptr[value->index];
409 }
410
411 /**
412  * Shortcut for getting the binary data of a TLV for a session
413  * @param session dlep session
414  * @param value dlep tlv value
415  * @return binary data pointer
416  */
417 static INLINE const uint8_t *
418 dlep_session_get_tlv_binary(struct dlep_session *session, struct dlep_parser_value *value) {
419   return &session->parser.tlv_ptr[value->index];
420 }
421
422 /**
423  * Get a DLEP neighbor
424  * @param session dlep session
425  * @param neigh neighbor MAC address
426  * @return DLEP neighbor, NULL if not found
427  */
428 static INLINE struct dlep_local_neighbor *
429 dlep_session_get_local_neighbor(struct dlep_session *session, const struct netaddr *neigh) {
430   struct dlep_local_neighbor *local;
431   return avl_find_element(&session->local_neighbor_tree, neigh, local, _node);
432 }
433
434 #endif /* _DLEP_SESSION_H_ */