3 * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
4 * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 * Visit http://www.olsr.org for more information.
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.
46 #include <oonf/libcommon/avl.h>
47 #include <oonf/libcommon/avl_comp.h>
48 #include <oonf/oonf.h>
49 #include <oonf/libconfig/cfg_db.h>
50 #include <oonf/libconfig/cfg_schema.h>
51 #include <oonf/libcore/oonf_logging.h>
52 #include <oonf/libcore/oonf_subsystem.h>
53 #include <oonf/libcore/os_core.h>
54 #include <oonf/librfc5444/rfc5444_iana.h>
55 #include <oonf/librfc5444/rfc5444_print.h>
56 #include <oonf/librfc5444/rfc5444_reader.h>
57 #include <oonf/librfc5444/rfc5444_writer.h>
58 #include <oonf/base/oonf_class.h>
59 #include <oonf/base/oonf_duplicate_set.h>
60 #include <oonf/base/oonf_packet_socket.h>
61 #include <oonf/base/oonf_timer.h>
63 #include <oonf/base/oonf_rfc5444.h>
65 /* constants and definitions */
66 #define LOG_RFC5444 _oonf_rfc5444_subsystem.logging
69 * RFC5444 configuration
71 struct _rfc5444_config {
72 /*! port number to be used for RFC5444 communication */
75 /*! IP protocol number to be used for RFC5444 communication */
80 * RFC5444 interface specific configuration
82 struct _rfc5444_if_config {
83 /*! packet socket configuration */
84 struct oonf_packet_managed_config sock;
86 /*! maximum aggregation interval for this interface */
87 uint64_t aggregation_interval;
91 static int _init(void);
92 static void _cleanup(void);
94 static struct oonf_rfc5444_target *_create_target(struct oonf_rfc5444_interface *, struct netaddr *dst, bool unicast);
95 static void _destroy_target(struct oonf_rfc5444_target *);
96 static void _print_packet_to_buffer(enum oonf_log_source source, union netaddr_socket *sock,
97 struct oonf_rfc5444_interface *interf, const uint8_t *ptr, size_t len, const char *success, const char *error);
99 static void _cb_receive_data(struct oonf_packet_socket *, union netaddr_socket *from, void *ptr, size_t length);
100 static void _cb_send_unicast_packet(struct rfc5444_writer *, struct rfc5444_writer_target *, void *, size_t);
101 static void _cb_send_multicast_packet(struct rfc5444_writer *, struct rfc5444_writer_target *, void *, size_t);
102 static void _cb_forward_message(struct rfc5444_reader_tlvblock_context *context, const uint8_t *buffer, size_t length);
103 static void _cb_msggen_notifier(struct rfc5444_writer_target *);
105 static bool _cb_single_target_selector(struct rfc5444_writer *, struct rfc5444_writer_target *, void *);
106 static bool _cb_filtered_targets_selector(
107 struct rfc5444_writer *writer, struct rfc5444_writer_target *rfc5444_target, void *ptr);
109 static struct rfc5444_reader_addrblock_entry *_alloc_addrblock_entry(void);
110 static struct rfc5444_reader_tlvblock_entry *_alloc_tlvblock_entry(void);
111 static struct rfc5444_writer_address *_alloc_address_entry(void);
112 static struct rfc5444_writer_addrtlv *_alloc_addrtlv_entry(void);
113 static void _free_addrblock_entry(struct rfc5444_reader_addrblock_entry *addrblock);
114 static void _free_tlvblock_entry(struct rfc5444_reader_tlvblock_entry *tlvblock);
115 static void _free_address_entry(struct rfc5444_writer_address *);
116 static void _free_addrtlv_entry(struct rfc5444_writer_addrtlv *);
118 static void _cb_add_seqno(struct rfc5444_writer *, struct rfc5444_writer_target *);
119 static void _cb_aggregation_event(struct oonf_timer_instance *);
121 static void _cb_cfg_rfc5444_changed(void);
122 static void _cb_cfg_interface_changed(void);
123 static void _cb_interface_changed(struct oonf_packet_managed *managed, bool);
125 /* memory block for rfc5444 targets plus MTU sized packet buffer */
126 static struct oonf_class _protocol_memcookie = {
127 .name = RFC5444_CLASS_PROTOCOL,
128 .size = sizeof(struct oonf_rfc5444_protocol),
131 static struct oonf_class _interface_memcookie = {
132 .name = RFC5444_CLASS_INTERFACE,
133 .size = sizeof(struct oonf_rfc5444_interface),
136 static struct oonf_class _target_memcookie = {
137 .name = RFC5444_CLASS_TARGET,
138 .size = sizeof(struct oonf_rfc5444_target),
141 static struct oonf_class _tlvblock_memcookie = {
142 .name = "RFC5444 TLVblock",
143 .size = sizeof(struct rfc5444_reader_tlvblock_entry),
144 .min_free_count = 32,
147 static struct oonf_class _addrblock_memcookie = {
148 .name = "RFC5444 Addrblock",
149 .size = sizeof(struct rfc5444_reader_addrblock_entry),
150 .min_free_count = 32,
153 static struct oonf_class _address_memcookie = {
154 .name = "RFC5444 Address",
155 .size = sizeof(struct rfc5444_writer_address),
156 .min_free_count = 32,
159 static struct oonf_class _addrtlv_memcookie = {
160 .name = "RFC5444 AddrTLV",
161 .size = sizeof(struct rfc5444_writer_addrtlv),
162 .min_free_count = 32,
165 /* timer for aggregating multiple rfc5444 messages to the same target */
166 static struct oonf_timer_class _aggregation_timer = {
167 .name = "RFC5444 aggregation",
168 .callback = _cb_aggregation_event,
171 /* configuration settings for handler */
172 static struct cfg_schema_entry _rfc5444_entries[] = {
173 CFG_MAP_INT32_MINMAX(
174 _rfc5444_config, port, "port", RFC5444_MANET_UDP_PORT_TXT, "UDP port for RFC5444 interface", 0, 1, 65535),
175 CFG_MAP_INT32_MINMAX(
176 _rfc5444_config, ip_proto, "ip_proto", RFC5444_MANET_IPPROTO_TXT, "IP protocol for RFC5444 interface", 0, 1, 255),
179 static struct cfg_schema_section _rfc5444_section = {
180 .type = CFG_RFC5444_SECTION,
181 .mode = CFG_SSMODE_UNNAMED,
182 .cb_delta_handler = _cb_cfg_rfc5444_changed,
183 .entries = _rfc5444_entries,
184 .entry_count = ARRAYSIZE(_rfc5444_entries),
187 static struct cfg_schema_entry _interface_entries[] = {
188 CFG_MAP_ACL_V46(_rfc5444_if_config, sock.acl, "acl", ACL_DEFAULT_ACCEPT, "Access control list for RFC5444 interface"),
189 CFG_MAP_ACL_V46(_rfc5444_if_config, sock.bindto, "bindto",
192 "-::/0\0" ACL_FIRST_ACCEPT "\0" ACL_DEFAULT_ACCEPT,
193 "Bind RFC5444 socket to an address matching this filter (both IPv4 and IPv6)"),
194 CFG_MAP_NETADDR_V4(_rfc5444_if_config, sock.multicast_v4, "multicast_v4", RFC5444_MANET_MULTICAST_V4_TXT,
195 "ipv4 multicast address of this socket", false, true),
196 CFG_MAP_NETADDR_V6(_rfc5444_if_config, sock.multicast_v6, "multicast_v6", RFC5444_MANET_MULTICAST_V6_TXT,
197 "ipv6 multicast address of this socket", false, true),
198 CFG_MAP_INT32_MINMAX(
199 _rfc5444_if_config, sock.dscp, "dscp", "192", "DSCP field for outgoing UDP protocol traffic", 0, 0, 255),
201 _rfc5444_if_config, sock.rawip, "rawip", "false", "True if a raw IP socket should be used, false to use UDP"),
202 CFG_MAP_INT32_MINMAX(
203 _rfc5444_if_config, sock.ttl_multicast, "multicast_ttl", "1", "TTL value of outgoing multicast traffic", 0, 1, 255),
204 CFG_MAP_CLOCK(_rfc5444_if_config, aggregation_interval, "aggregation_interval", "0.100",
205 "Interval in seconds for message aggregation"),
209 static struct cfg_schema_section _interface_section = {
210 CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
212 .cb_delta_handler = _cb_cfg_interface_changed,
213 .entries = _interface_entries,
214 .entry_count = ARRAYSIZE(_interface_entries),
215 .next_section = &_rfc5444_section,
218 /* rfc5444 handling */
219 static const struct rfc5444_reader _reader_template = {
220 .forward_message = _cb_forward_message,
221 .malloc_addrblock_entry = _alloc_addrblock_entry,
222 .malloc_tlvblock_entry = _alloc_tlvblock_entry,
223 .free_addrblock_entry = _free_addrblock_entry,
224 .free_tlvblock_entry = _free_tlvblock_entry,
226 static const struct rfc5444_writer _writer_template = {
227 .malloc_address_entry = _alloc_address_entry,
228 .malloc_addrtlv_entry = _alloc_addrtlv_entry,
229 .free_address_entry = _free_address_entry,
230 .free_addrtlv_entry = _free_addrtlv_entry,
231 .msg_size = RFC5444_MAX_MESSAGE_SIZE,
232 .addrtlv_size = RFC5444_ADDRTLV_BUFFER,
235 /* rfc5444_printer */
236 static struct autobuf _printer_buffer;
237 static struct rfc5444_print_session _printer_session;
239 static struct rfc5444_reader _printer = {
240 .malloc_addrblock_entry = _alloc_addrblock_entry,
241 .malloc_tlvblock_entry = _alloc_tlvblock_entry,
242 .free_addrblock_entry = _free_addrblock_entry,
243 .free_tlvblock_entry = _free_tlvblock_entry,
246 /* configuration for RFC5444 socket */
247 static uint8_t _incoming_buffer[RFC5444_MAX_PACKET_SIZE];
249 static struct oonf_packet_config _socket_config = {
250 .input_buffer = _incoming_buffer,
251 .input_buffer_length = sizeof(_incoming_buffer),
252 .receive_data = _cb_receive_data,
255 /* tree of active rfc5444 protocols */
256 static struct avl_tree _protocol_tree;
258 /* default protocol */
259 static struct oonf_rfc5444_protocol *_rfc5444_protocol = NULL;
260 static struct oonf_rfc5444_interface *_rfc5444_unicast = NULL;
262 static const struct const_strarray _unicast_bindto_acl_value = STRARRAY_INIT("0.0.0.0\0::");
264 /* subsystem definition */
265 static const char *_dependencies[] = {
266 OONF_CLASS_SUBSYSTEM,
267 OONF_DUPSET_SUBSYSTEM,
268 OONF_PACKET_SUBSYSTEM,
269 OONF_TIMER_SUBSYSTEM,
272 static struct oonf_subsystem _oonf_rfc5444_subsystem = {
273 .name = OONF_RFC5444_SUBSYSTEM,
274 .dependencies = _dependencies,
275 .dependencies_count = ARRAYSIZE(_dependencies),
278 .cfg_section = &_interface_section,
280 DECLARE_OONF_PLUGIN(_oonf_rfc5444_subsystem);
282 /* static blocking of RFC5444 output */
283 static bool _block_output = false;
285 /* additional logging targets */
286 static enum oonf_log_source LOG_RFC5444_R, LOG_RFC5444_W;
289 * Initialize RFC5444 handling system
290 * @return -1 if an error happened, 0 otherwise
294 avl_init(&_protocol_tree, avl_comp_strcasecmp, false);
296 oonf_class_add(&_protocol_memcookie);
297 oonf_class_add(&_target_memcookie);
298 oonf_class_add(&_addrblock_memcookie);
299 oonf_class_add(&_tlvblock_memcookie);
300 oonf_class_add(&_address_memcookie);
301 oonf_class_add(&_addrtlv_memcookie);
303 oonf_timer_add(&_aggregation_timer);
305 _rfc5444_protocol = oonf_rfc5444_add_protocol("rfc5444_iana", true);
306 if (_rfc5444_protocol == NULL) {
311 oonf_class_add(&_interface_memcookie);
312 _rfc5444_unicast = oonf_rfc5444_add_interface(_rfc5444_protocol, NULL, RFC5444_UNICAST_INTERFACE);
313 if (_rfc5444_unicast == NULL) {
318 if (abuf_init(&_printer_buffer)) {
323 memset(&_printer_session, 0, sizeof(_printer_session));
324 _printer_session.output = &_printer_buffer;
326 rfc5444_reader_init(&_printer);
327 rfc5444_print_add(&_printer_session, &_printer);
329 LOG_RFC5444_R = oonf_log_register_source(OONF_RFC5444_SUBSYSTEM "_r");
330 LOG_RFC5444_W = oonf_log_register_source(OONF_RFC5444_SUBSYSTEM "_w");
335 * Cleanup all allocated resources of RFC5444 handling
339 struct oonf_rfc5444_protocol *protocol, *p_it;
340 struct oonf_rfc5444_interface *interf, *i_it;
341 struct oonf_rfc5444_target *target, *t_it;
343 /* cleanup existing instances */
344 avl_for_each_element_safe(&_protocol_tree, protocol, _node, p_it) {
345 avl_for_each_element_safe(&protocol->_interface_tree, interf, _node, i_it) {
346 avl_for_each_element_safe(&interf->_target_tree, target, _node, t_it) {
347 /* always remove target but never remove interface */
348 target->_refcount = 1;
349 interf->_refcount = 2;
350 oonf_rfc5444_remove_target(target);
352 /* always remove interface but never remove protocol */
353 interf->_refcount = 1;
354 protocol->_refcount = 2;
355 oonf_rfc5444_remove_interface(interf, NULL);
357 /* always remove protocol */
358 protocol->_refcount = 1;
359 oonf_rfc5444_remove_protocol(protocol);
362 oonf_timer_remove(&_aggregation_timer);
364 if (_printer_session.output) {
365 rfc5444_print_remove(&_printer_session);
366 rfc5444_reader_cleanup(&_printer);
368 abuf_free(&_printer_buffer);
370 oonf_class_remove(&_protocol_memcookie);
371 oonf_class_remove(&_interface_memcookie);
372 oonf_class_remove(&_target_memcookie);
373 oonf_class_remove(&_tlvblock_memcookie);
374 oonf_class_remove(&_addrblock_memcookie);
375 oonf_class_remove(&_address_memcookie);
376 oonf_class_remove(&_addrtlv_memcookie);
381 * Trigger the creation of a RFC5444 message for a specific interface
382 * @param target interface for outgoing message
383 * @param msgid id of created message
384 * @return return code of rfc5444 writer
387 oonf_rfc5444_send_if(struct oonf_rfc5444_target *target, uint8_t msgid)
392 struct netaddr_str buf;
395 /* check if socket can send data */
396 if (!oonf_rfc5444_is_target_active(target)) {
401 OONF_INFO(LOG_RFC5444, "Create message id %d for protocol %s/target %s on interface %s", msgid,
402 target->interface->protocol->name, netaddr_to_string(&buf, &target->dst), target->interface->name);
404 addr_len = netaddr_get_address_family(&target->dst) == AF_INET ? 4 : 16;
405 return rfc5444_writer_create_message(
406 &target->interface->protocol->writer, msgid, addr_len, _cb_single_target_selector, target);
410 * Trigger the creation of a RFC5444 message for a group of interfaces
411 * @param protocol protocol for outgoing message
412 * @param msgid id of created message
413 * @param addr_len length of address for this message
414 * @param useIf callback to selector for interfaces
415 * @return return code of rfc5444 writer
418 oonf_rfc5444_send_all(
419 struct oonf_rfc5444_protocol *protocol, uint8_t msgid, uint8_t addr_len, rfc5444_writer_targetselector useIf)
422 OONF_INFO(LOG_RFC5444, "Create message id %d", msgid);
424 return rfc5444_writer_create_message(&protocol->writer, msgid, addr_len, _cb_filtered_targets_selector, useIf);
428 * Add a new protocol to the rfc5444 framework
429 * @param name name of protocol, must be an unique identifier
430 * @param fixed_local_port true if the local port must be fixed to the
432 * @return pointer to new protocol instance, NULL if out of memory
434 struct oonf_rfc5444_protocol *
435 oonf_rfc5444_add_protocol(const char *name, bool fixed_local_port) {
436 struct oonf_rfc5444_protocol *protocol;
438 protocol = avl_find_element(&_protocol_tree, name, protocol, _node);
440 protocol = oonf_class_malloc(&_protocol_memcookie);
441 if (protocol == NULL) {
446 strscpy(protocol->name, name, sizeof(protocol->name));
447 protocol->fixed_local_port = fixed_local_port;
449 /* hook into global protocol tree */
450 protocol->_node.key = protocol->name;
451 avl_insert(&_protocol_tree, &protocol->_node);
453 /* initialize rfc5444 reader/writer */
454 memcpy(&protocol->reader, &_reader_template, sizeof(_reader_template));
455 memcpy(&protocol->writer, &_writer_template, sizeof(_writer_template));
456 protocol->writer.msg_buffer = protocol->_msg_buffer;
457 protocol->writer.addrtlv_buffer = protocol->_addrtlv_buffer;
458 rfc5444_reader_init(&protocol->reader);
459 rfc5444_writer_init(&protocol->writer);
461 protocol->writer.message_generation_notifier = _cb_msggen_notifier;
463 /* initialize processing and forwarding set */
464 oonf_duplicate_set_add(&protocol->forwarded_set, OONF_DUPSET_16BIT);
465 oonf_duplicate_set_add(&protocol->processed_set, OONF_DUPSET_16BIT);
467 /* init interface subtree */
468 avl_init(&protocol->_interface_tree, avl_comp_strcasecmp, false);
471 OONF_INFO(LOG_RFC5444, "Add protocol %s (refcount was %d)", name, protocol->_refcount);
473 /* keep track of reference count */
474 protocol->_refcount++;
480 * Remove a protocol instance from the framework
481 * @param protocol pointer to protocol
484 oonf_rfc5444_remove_protocol(struct oonf_rfc5444_protocol *protocol) {
485 struct oonf_rfc5444_interface *interf, *i_it;
487 OONF_INFO(LOG_RFC5444, "Remove protocol %s (refcount was %d)", protocol->name, protocol->_refcount);
489 if (protocol->_refcount > 1) {
490 /* There are still users left for this protocol */
491 protocol->_refcount--;
495 /* free all remaining interfaces */
496 avl_for_each_element_safe(&protocol->_interface_tree, interf, _node, i_it) {
497 oonf_rfc5444_remove_interface(interf, NULL);
500 /* free processing/forwarding set */
501 oonf_duplicate_set_remove(&protocol->forwarded_set);
502 oonf_duplicate_set_remove(&protocol->processed_set);
504 /* free reader, writer and protocol itself */
505 rfc5444_reader_cleanup(&protocol->reader);
506 rfc5444_writer_cleanup(&protocol->writer);
508 avl_remove(&_protocol_tree, &protocol->_node);
509 oonf_class_free(&_protocol_memcookie, protocol);
513 * Set the port of a protocol
514 * @param protocol pointer to protocol instance
515 * @param port port number in host byteorder
516 * @param ip_proto ip protocol number in host byteorder
519 oonf_rfc5444_reconfigure_protocol(struct oonf_rfc5444_protocol *protocol, uint16_t port, int ip_proto) {
520 struct oonf_rfc5444_interface *interf;
523 if (port == protocol->port && ip_proto == protocol->ip_proto) {
527 OONF_INFO(LOG_RFC5444, "Reconfigure protocol %s to port %u and ip-protocol %d", protocol->name, port, ip_proto);
529 /* store protocol port */
530 protocol->port = port;
531 protocol->ip_proto = ip_proto;
533 avl_for_each_element(&protocol->_interface_tree, interf, _node) {
534 oonf_packet_remove_managed(&interf->_socket, true);
535 oonf_packet_add_managed(&interf->_socket);
538 oonf_rfc5444_reconfigure_interface(interf, NULL);
544 * @return default IANA RFC5444 protocol instance
546 struct oonf_rfc5444_protocol *
547 oonf_rfc5444_get_default_protocol(void) {
548 return _rfc5444_protocol;
552 * Add a new interface to a rfc5444 protocol.
553 * @param protocol pointer to protocol instance
554 * @param listener pointer to interface listener, NULL if none
555 * @param name name of interface
556 * @return pointer to rfc5444 interface instance, NULL if out of memory
558 struct oonf_rfc5444_interface *
559 oonf_rfc5444_add_interface(
560 struct oonf_rfc5444_protocol *protocol, struct oonf_rfc5444_interface_listener *listener, const char *name) {
561 struct oonf_rfc5444_interface *interf;
564 interf = oonf_rfc5444_get_interface(protocol, name);
565 if (interf == NULL) {
566 if (os_core_get_random(&rnd, sizeof(rnd))) {
567 OONF_WARN(LOG_RFC5444, "Could not get random data");
571 interf = oonf_class_malloc(&_interface_memcookie);
572 if (interf == NULL) {
577 strscpy(interf->name, name, sizeof(interf->name));
579 /* set protocol reference */
580 interf->protocol = protocol;
582 /* hook into protocol */
583 interf->_node.key = interf->name;
584 avl_insert(&protocol->_interface_tree, &interf->_node);
586 /* initialize target subtree */
587 avl_init(&interf->_target_tree, avl_comp_netaddr, false);
589 /* initialize socket config */
590 memcpy(&interf->_socket.config, &_socket_config, sizeof(_socket_config));
591 interf->_socket.config.user = interf;
592 interf->_socket.cb_settings_change = _cb_interface_changed;
594 /* prevent routing of RFC5444 packets */
595 interf->_socket.config.dont_route = true;
597 /* initialize socket */
598 oonf_packet_add_managed(&interf->_socket);
600 /* initialize message sequence number */
601 protocol->_msg_seqno = rnd;
603 /* initialize listener list */
604 list_init_head(&interf->_listener);
606 /* increase protocol refcount */
607 protocol->_refcount++;
610 OONF_INFO(LOG_RFC5444, "Add interface %s to protocol %s (refcount was %d)", name, protocol->name, interf->_refcount);
612 /* increase reference count */
613 interf->_refcount += 1;
616 /* hookup listener */
617 list_add_tail(&interf->_listener, &listener->_node);
618 listener->interface = interf;
624 * Remove a rfc5444 interface instance
625 * @param interf pointer to interface instance
626 * @param listener pointer to interface listener, NULL if none
629 oonf_rfc5444_remove_interface(struct oonf_rfc5444_interface *interf, struct oonf_rfc5444_interface_listener *listener) {
630 struct oonf_rfc5444_target *target, *t_it;
632 OONF_INFO(LOG_RFC5444, "Remove interface %s from protocol %s (refcount was %d)", interf->name, interf->protocol->name,
635 if (interf->_refcount > 1) {
636 /* still users left for this interface */
641 if (listener != NULL && listener->interface != NULL) {
642 list_remove(&listener->_node);
643 listener->interface = NULL;
646 /* remove all remaining targets */
647 avl_for_each_element_safe(&interf->_target_tree, target, _node, t_it) {
648 _destroy_target(target);
651 /* remove multicast targets */
652 if (interf->multicast4) {
653 _destroy_target(interf->multicast4);
655 if (interf->multicast6) {
656 _destroy_target(interf->multicast6);
659 /* remove from protocol tree */
660 avl_remove(&interf->protocol->_interface_tree, &interf->_node);
662 /* decrease protocol refcount */
663 oonf_rfc5444_remove_protocol(interf->protocol);
666 oonf_packet_remove_managed(&interf->_socket, false);
668 /* cleanup configuration copy */
669 oonf_packet_free_managed_config(&interf->_socket_config);
672 oonf_class_free(&_interface_memcookie, interf);
676 * Reconfigure the parameters of an rfc5444 interface. You cannot reconfigure
677 * the interface name with this command.
678 * @param interf pointer to existing rfc5444 interface
679 * @param config new socket configuration, NULL to just reapply the current
683 oonf_rfc5444_reconfigure_interface(struct oonf_rfc5444_interface *interf, struct oonf_packet_managed_config *config) {
684 struct oonf_rfc5444_target *target, *old;
686 struct netaddr_str buf;
688 if (config != NULL) {
689 /* copy socket configuration */
690 oonf_packet_copy_managed_config(&interf->_socket_config, config);
692 /* overwrite interface name */
693 strscpy(interf->_socket_config.interface, interf->name, sizeof(interf->_socket_config.interface));
696 config = &interf->_socket_config;
699 /* always mesh socket */
700 interf->_socket_config.mesh = true;
703 port = interf->protocol->port;
705 /* set fixed configuration options */
706 if (interf->_socket_config.rawip) {
707 interf->_socket_config.port = 0;
708 interf->_socket_config.multicast_port = 0;
709 interf->_socket_config.protocol = interf->protocol->ip_proto;
712 if (interf->_socket_config.multicast_port == 0) {
713 interf->_socket_config.multicast_port = port;
715 if (interf->protocol->fixed_local_port && interf->_socket_config.port == 0) {
716 interf->_socket_config.port = port;
720 OONF_INFO(LOG_RFC5444, "Reconfigure RFC5444 interface %s to port %u/%u and protocol %d", interf->name,
721 interf->_socket_config.port, interf->_socket_config.multicast_port, interf->_socket_config.protocol);
723 if (strcmp(interf->name, RFC5444_UNICAST_INTERFACE) == 0) {
724 /* unicast interface */
725 netaddr_invalidate(&interf->_socket_config.multicast_v4);
726 netaddr_invalidate(&interf->_socket_config.multicast_v6);
727 interf->_socket_config.port = port;
728 interf->_socket_config.interface[0] = 0;
729 netaddr_acl_from_strarray(&interf->_socket_config.bindto, &_unicast_bindto_acl_value);
733 /* delay configuration apply */
734 OONF_INFO(LOG_RFC5444, " delay configuration, we still lack to protocol port");
738 /* apply socket configuration */
739 oonf_packet_apply_managed(&interf->_socket, &interf->_socket_config);
741 /* handle IPv4 multicast target */
742 if (interf->multicast4) {
743 old = interf->multicast4;
744 interf->multicast4 = NULL;
749 if (netaddr_get_address_family(&config->multicast_v4) != AF_UNSPEC) {
750 target = _create_target(interf, &config->multicast_v4, false);
751 if (target == NULL) {
752 OONF_WARN(LOG_RFC5444, "Could not create multicast target %s for interface %s",
753 netaddr_to_string(&buf, &config->multicast_v4), interf->name);
754 interf->multicast4 = old;
758 interf->multicast4 = target;
762 _destroy_target(old);
765 /* handle IPv6 multicast target */
766 if (interf->multicast6) {
767 old = interf->multicast6;
768 interf->multicast6 = NULL;
773 if (netaddr_get_address_family(&config->multicast_v6) != AF_UNSPEC) {
774 target = _create_target(interf, &config->multicast_v6, false);
775 if (target == NULL) {
776 OONF_WARN(LOG_RFC5444, "Could not create multicast socket %s for interface %s",
777 netaddr_to_string(&buf, &config->multicast_v6), interf->name);
778 interf->multicast6 = old;
782 interf->multicast6 = target;
786 _destroy_target(old);
791 * Set/Reset value to overwrite the configured aggregation
792 * interval of a RFC5444 interface
793 * @param interf RFC5444 interface
794 * @param aggregation new aggregation interval, 0 to reset to
796 * @return old aggregation interval, 0 if configured value was used
799 oonf_rfc5444_interface_set_aggregation(struct oonf_rfc5444_interface *interf, uint64_t aggregation) {
802 old = interf->overwrite_aggregation_interval;
803 interf->overwrite_aggregation_interval = aggregation;
808 * Add an unicast target to a rfc5444 interface
809 * @param interf pointer to interface instance
810 * @param dst pointer to destination IP address
811 * @return pointer to target, NULL if out of memory
813 struct oonf_rfc5444_target *
814 oonf_rfc5444_add_target(struct oonf_rfc5444_interface *interf, struct netaddr *dst) {
815 struct oonf_rfc5444_target *target;
817 struct netaddr_str nbuf;
820 target = avl_find_element(&interf->_target_tree, dst, target, _node);
822 target = _create_target(interf, dst, true);
823 if (target == NULL) {
827 /* hook into interface tree */
828 target->_node.key = &target->dst;
829 avl_insert(&interf->_target_tree, &target->_node);
832 OONF_INFO(LOG_RFC5444, "Add target %s to interface %s on protocol %s (refcount was %d)",
833 netaddr_to_string(&nbuf, dst), interf->name, interf->protocol->name, target->_refcount);
835 /* increase interface refcount */
841 * Removes an unicast target from a rfc5444 interface
842 * @param target pointer to target instance
845 oonf_rfc5444_remove_target(struct oonf_rfc5444_target *target) {
847 struct netaddr_str nbuf;
850 OONF_INFO(LOG_RFC5444, "Remove target %s from interface %s on protocol %s (refcount was %d)",
851 netaddr_to_string(&nbuf, &target->dst), target->interface->name, target->interface->protocol->name,
854 if (target->_refcount > 1) {
855 /* target still in use */
860 /* remove from protocol tree */
861 avl_remove(&target->interface->_target_tree, &target->_node);
863 /* decrease protocol refcount */
864 oonf_rfc5444_remove_interface(target->interface, NULL);
867 _destroy_target(target);
871 * Send a raw RFC5444 packet to a target
872 * @param target target for the packet data
873 * @param ptr pointer to data
874 * @param len length of data
877 oonf_rfc5444_send_target_data(struct oonf_rfc5444_target *target, const void *ptr, size_t len) {
878 union netaddr_socket sock;
879 struct os_interface_listener *interf;
881 interf = oonf_rfc5444_get_core_if_listener(target->interface);
882 netaddr_socket_init(&sock, &target->dst, target->interface->protocol->port, interf->data->index);
884 _print_packet_to_buffer(LOG_RFC5444_W, &sock, target->interface, ptr, len, "Outgoing RFC5444 packet to",
885 "Error while parsing outgoing RFC5444 packet to");
888 OONF_DEBUG(LOG_RFC5444, "Output blocked");
891 if (target == target->interface->multicast4 || target == target->interface->multicast6) {
892 oonf_packet_send_managed_multicast(&target->interface->_socket, ptr, len, netaddr_get_address_family(&target->dst));
895 oonf_packet_send_managed(&target->interface->_socket, &sock, ptr, len);
900 * Send a raw RFC5444 packet through an interface to a destination address
901 * @param interf rfc5444 interface
902 * @param dst destination address for packet
903 * @param ptr pointer to data
904 * @param len length of data
907 oonf_rfc5444_send_interface_data(
908 struct oonf_rfc5444_interface *interf, const struct netaddr *dst, const void *ptr, size_t len) {
909 union netaddr_socket sock;
910 struct os_interface_listener *os_interf;
912 os_interf = oonf_rfc5444_get_core_if_listener(interf);
913 netaddr_socket_init(&sock, dst, interf->protocol->port, os_interf->data->index);
915 _print_packet_to_buffer(LOG_RFC5444_W, &sock, interf, ptr, len, "Outgoing RFC5444 packet to",
916 "Error while parsing outgoing RFC5444 packet to");
919 OONF_DEBUG(LOG_RFC5444, "Output blocked");
923 if (netaddr_is_in_subnet(&NETADDR_IPV4_MULTICAST, dst) || netaddr_is_in_subnet(&NETADDR_IPV6_MULTICAST, dst)) {
924 oonf_packet_send_managed_multicast(&interf->_socket, ptr, len, netaddr_get_address_family(dst));
927 oonf_packet_send_managed(&interf->_socket, &sock, ptr, len);
932 * @param target oonf rfc5444 target
933 * @return local socket corresponding to target destination
935 const union netaddr_socket *
936 oonf_rfc5444_target_get_local_socket(struct oonf_rfc5444_target *target) {
939 family = netaddr_get_address_family(&target->dst);
940 return oonf_rfc5444_interface_get_local_socket(target->interface, family);
944 * @param rfc5444_if oonf rfc5444 interface
945 * @param af_type address family type
946 * @return local socket corresponding to address family
948 const union netaddr_socket *
949 oonf_rfc5444_interface_get_local_socket(struct oonf_rfc5444_interface *rfc5444_if, int af_type) {
950 if (af_type == AF_INET) {
951 return &rfc5444_if->_socket.socket_v4.local_socket;
953 if (af_type == AF_INET6) {
954 return &rfc5444_if->_socket.socket_v6.local_socket;
960 * This function can block all output of the RFC5444 code
961 * @param block true to block everything, false to unblock
964 oonf_rfc5444_block_output(bool block) {
965 _block_output = block;
969 * Create a new rfc5444 target
970 * @param interf rfc5444 interface
971 * @param dst destination ip address
972 * @param unicast true of unicast, false if multicast
973 * @return pointer to target, NULL if out of memory
975 static struct oonf_rfc5444_target *
976 _create_target(struct oonf_rfc5444_interface *interf, struct netaddr *dst, bool unicast) {
977 static struct oonf_rfc5444_target *target;
980 if (os_core_get_random(&rnd, sizeof(rnd))) {
981 OONF_WARN(LOG_RFC5444, "Could not get random data");
985 target = oonf_class_malloc(&_target_memcookie);
986 if (target == NULL) {
990 /* initialize rfc5444 interfaces */
991 target->rfc5444_target.packet_buffer = target->_packet_buffer;
992 target->rfc5444_target.packet_size = RFC5444_MAX_PACKET_SIZE;
993 target->rfc5444_target.addPacketHeader = _cb_add_seqno;
995 target->rfc5444_target.sendPacket = _cb_send_unicast_packet;
998 target->rfc5444_target.sendPacket = _cb_send_multicast_packet;
1000 rfc5444_writer_register_target(&interf->protocol->writer, &target->rfc5444_target);
1002 /* copy socket description */
1003 memcpy(&target->dst, dst, sizeof(target->dst));
1005 /* set interface reference */
1006 target->interface = interf;
1008 /* aggregation timer */
1009 target->_aggregation.class = &_aggregation_timer;
1011 target->_refcount = 1;
1013 /* initialize pktseqno */
1014 target->_pktseqno = rnd;
1020 * Destroy a target and free its resources
1021 * @param target pointer to rfc5444 target
1024 _destroy_target(struct oonf_rfc5444_target *target) {
1025 /* cleanup interface */
1026 rfc5444_writer_unregister_target(&target->interface->protocol->writer, &target->rfc5444_target);
1029 oonf_timer_stop(&target->_aggregation);
1032 oonf_class_free(&_target_memcookie, target);
1036 * Print a rfc5444 packet to the logging system
1037 * @param sock socket the packet is reffering to
1038 * @param interf pointer to rfc5444 interface
1039 * @param ptr pointer to packet
1040 * @param len length of packet
1041 * @param success text prefix for successful printing
1042 * @param error text prefix when error happens during packet parsing
1045 _print_packet_to_buffer(enum oonf_log_source source, union netaddr_socket *sock __attribute__((unused)),
1046 struct oonf_rfc5444_interface *interf __attribute__((unused)), const uint8_t *ptr, size_t len,
1047 const char *success __attribute__((unused)), const char *error __attribute__((unused))) {
1048 enum rfc5444_result result;
1049 struct netaddr_str buf;
1051 if (oonf_log_mask_test(log_global_mask, source, LOG_SEVERITY_DEBUG)) {
1052 abuf_clear(&_printer_buffer);
1053 abuf_hexdump(&_printer_buffer, "", ptr, len);
1055 result = rfc5444_reader_handle_packet(&_printer, ptr, len);
1057 OONF_WARN(source, "%s %s for printing: %s (%d)", error, netaddr_socket_to_string(&buf, sock),
1058 rfc5444_strerror(result), result);
1059 OONF_WARN(source, "packet: %s", abuf_getptr(&_printer_buffer));
1062 OONF_DEBUG(source, "%s %s through %s:", success, netaddr_socket_to_string(&buf, sock), interf->name);
1063 OONF_DEBUG(source, "packet: %s", abuf_getptr(&_printer_buffer));
1069 * Handle incoming packet from a socket
1070 * @param sock pointer to packet socket
1071 * @param from originator of incoming packet
1072 * @param length length of incoming packet
1075 _cb_receive_data(struct oonf_packet_socket *sock, union netaddr_socket *from, void *ptr, size_t length) {
1076 struct oonf_rfc5444_protocol *protocol;
1077 struct oonf_rfc5444_interface *interf;
1078 enum rfc5444_result result;
1079 struct netaddr source_ip;
1080 struct netaddr_str buf;
1082 interf = sock->config.user;
1083 protocol = interf->protocol;
1085 if (netaddr_from_socket(&source_ip, from)) {
1086 OONF_WARN(LOG_RFC5444, "Could not convert socket to address: %s", netaddr_socket_to_string(&buf, from));
1090 protocol->input.src_socket = from;
1091 protocol->input.src_address = &source_ip;
1092 protocol->input.interface = interf;
1094 protocol->input.is_multicast = sock == &interf->_socket.multicast_v4 || sock == &interf->_socket.multicast_v6;
1096 if (strcmp(interf->name, RFC5444_UNICAST_INTERFACE) == 0 &&
1097 (netaddr_is_in_subnet(&NETADDR_IPV4_LINKLOCAL, &source_ip) ||
1098 netaddr_is_in_subnet(&NETADDR_IPV6_LINKLOCAL, &source_ip))) {
1099 OONF_DEBUG(LOG_RFC5444, "Ignore linklocal traffic on generic unicast interface");
1103 _print_packet_to_buffer(LOG_RFC5444_R, from, interf, ptr, length, "Incoming RFC5444 packet from",
1104 "Error while parsing incoming RFC5444 packet from");
1106 result = rfc5444_reader_handle_packet(&protocol->reader, ptr, length);
1108 OONF_WARN(LOG_RFC5444, "Error while parsing incoming packet from %s: %s (%d)", netaddr_socket_to_string(&buf, from),
1109 rfc5444_strerror(result), result);
1110 OONF_WARN_HEX(LOG_RFC5444, ptr, length, "%s", abuf_getptr(&_printer_buffer));
1115 * Callback for sending a multicast packet to a rfc5444 target
1116 * @param writer rfc5444 writer
1117 * @param target rfc5444 target
1118 * @param ptr pointer to outgoing buffer
1119 * @param len length of buffer
1122 _cb_send_multicast_packet(
1123 struct rfc5444_writer *writer __attribute__((unused)), struct rfc5444_writer_target *target, void *ptr, size_t len) {
1124 struct oonf_rfc5444_target *t;
1125 struct os_interface_listener *if_listener;
1126 union netaddr_socket sock;
1128 t = container_of(target, struct oonf_rfc5444_target, rfc5444_target);
1130 if_listener = oonf_rfc5444_get_core_if_listener(t->interface);
1131 netaddr_socket_init(&sock, &t->dst, t->interface->protocol->port, if_listener->data->index);
1133 _print_packet_to_buffer(LOG_RFC5444_W, &sock, t->interface, ptr, len, "Outgoing RFC5444 packet to",
1134 "Error while parsing outgoing RFC5444 packet to");
1136 if (_block_output) {
1137 OONF_DEBUG(LOG_RFC5444, "Output blocked");
1140 oonf_packet_send_managed_multicast(&t->interface->_socket, ptr, len, netaddr_get_address_family(&t->dst));
1144 * Callback for sending an unicast packet to a rfc5444 target
1145 * @param writer rfc5444 writer
1146 * @param target rfc5444 target
1147 * @param ptr pointer to outgoing buffer
1148 * @param len length of buffer
1151 _cb_send_unicast_packet(
1152 struct rfc5444_writer *writer __attribute__((unused)), struct rfc5444_writer_target *target, void *ptr, size_t len) {
1153 struct oonf_rfc5444_target *t;
1154 union netaddr_socket sock;
1155 struct os_interface_listener *interf;
1157 t = container_of(target, struct oonf_rfc5444_target, rfc5444_target);
1159 interf = oonf_rfc5444_get_core_if_listener(t->interface);
1160 netaddr_socket_init(&sock, &t->dst, t->interface->protocol->port, interf->data->index);
1162 _print_packet_to_buffer(LOG_RFC5444_W, &sock, t->interface, ptr, len, "Outgoing RFC5444 packet to",
1163 "Error while parsing outgoing RFC5444 packet to");
1165 if (_block_output) {
1166 OONF_DEBUG(LOG_RFC5444, "Output blocked");
1170 oonf_packet_send_managed(&t->interface->_socket, &sock, ptr, len);
1174 * Handle forwarding of rfc5444 messages
1175 * @param context RFC5444 tlvblock reader context
1176 * @param buffer message to be forwarded
1177 * @param length length of message
1180 _cb_forward_message(struct rfc5444_reader_tlvblock_context *context, const uint8_t *buffer, size_t length) {
1181 struct oonf_rfc5444_protocol *protocol;
1182 enum rfc5444_result result;
1184 /* get protocol to use for forwarding message */
1185 protocol = container_of(context->reader, struct oonf_rfc5444_protocol, reader);
1187 /* forward message */
1188 OONF_INFO(LOG_RFC5444, "Forwarding message type %u", context->msg_type);
1190 result = rfc5444_writer_forward_msg(&protocol->writer, context, buffer, length);
1191 if (result != RFC5444_OKAY && result != RFC5444_NO_MSGCREATOR) {
1192 OONF_WARN(LOG_RFC5444, "Error while forwarding message: %s (%d)", rfc5444_strerror(result), result);
1197 _cb_msggen_notifier(struct rfc5444_writer_target *rfc5444target) {
1198 struct oonf_rfc5444_target *target;
1201 target = container_of(rfc5444target, struct oonf_rfc5444_target, rfc5444_target);
1202 if (!oonf_timer_is_active(&target->_aggregation)) {
1203 interval = target->interface->overwrite_aggregation_interval;
1205 interval = target->interface->aggregation_interval;
1208 /* activate aggregation timer */
1209 oonf_timer_start(&target->_aggregation, target->interface->aggregation_interval);
1214 * Selector for outgoing target
1215 * @param writer rfc5444 writer
1216 * @param target rfc5444 target
1217 * @param ptr custom pointer, contains rfc5444 target
1218 * @return true if target corresponds to selection
1221 _cb_single_target_selector(
1222 struct rfc5444_writer *writer __attribute__((unused)), struct rfc5444_writer_target *target, void *ptr) {
1223 struct oonf_rfc5444_target *t = ptr;
1225 return &t->rfc5444_target == target;
1229 * Selector for outgoing target
1230 * @param writer rfc5444 writer
1231 * @param rfc5444_target rfc5444 target
1232 * @param ptr custom pointer, contains rfc5444 target
1233 * @return true if target corresponds to selection
1236 _cb_filtered_targets_selector(struct rfc5444_writer *writer, struct rfc5444_writer_target *rfc5444_target, void *ptr) {
1237 rfc5444_writer_targetselector userUseIf;
1238 struct oonf_rfc5444_target *target;
1239 #ifdef OONF_LOG_INFO
1240 struct netaddr_str buf;
1244 target = container_of(rfc5444_target, struct oonf_rfc5444_target, rfc5444_target);
1246 /* check if socket can send data */
1247 if (!oonf_rfc5444_is_target_active(target)) {
1251 /* check if user deselected the target */
1252 if (!userUseIf(writer, rfc5444_target, NULL)) {
1256 /* create message */
1257 OONF_INFO(LOG_RFC5444, "Send message to protocol %s/target %s on interface %s", target->interface->protocol->name,
1258 netaddr_to_string(&buf, &target->dst), target->interface->name);
1264 * Internal memory allocation function for addrblock
1265 * @return pointer to cleared addrblock
1267 static struct rfc5444_reader_addrblock_entry *
1268 _alloc_addrblock_entry(void) {
1269 return oonf_class_malloc(&_addrblock_memcookie);
1273 * Internal memory allocation function for rfc5444_reader_tlvblock_entry
1274 * @return pointer to cleared rfc5444_reader_tlvblock_entry
1276 static struct rfc5444_reader_tlvblock_entry *
1277 _alloc_tlvblock_entry(void) {
1278 return oonf_class_malloc(&_tlvblock_memcookie);
1282 * Internal memory allocation function for rfc5444_writer_address
1283 * @return pointer to cleared rfc5444_writer_address
1285 static struct rfc5444_writer_address *
1286 _alloc_address_entry(void) {
1287 return oonf_class_malloc(&_address_memcookie);
1291 * Internal memory allocation function for rfc5444_writer_addrtlv
1292 * @return pointer to cleared rfc5444_writer_addrtlv
1294 static struct rfc5444_writer_addrtlv *
1295 _alloc_addrtlv_entry(void) {
1296 return oonf_class_malloc(&_addrtlv_memcookie);
1300 * Free an addrblock entry
1301 * @param addrblock addressblock to be freed
1304 _free_addrblock_entry(struct rfc5444_reader_addrblock_entry *addrblock) {
1305 oonf_class_free(&_addrblock_memcookie, addrblock);
1309 * Free a tlvblock entry
1310 * @param tlvblock tlvblock to be freed
1313 _free_tlvblock_entry(struct rfc5444_reader_tlvblock_entry *tlvblock) {
1314 oonf_class_free(&_tlvblock_memcookie, tlvblock);
1319 * @param address address to be freed
1322 _free_address_entry(struct rfc5444_writer_address *address) {
1323 oonf_class_free(&_address_memcookie, address);
1327 * Free an address tlv entry
1328 * @param addrtlv address tlv entry to be freed
1331 _free_addrtlv_entry(struct rfc5444_writer_addrtlv *addrtlv) {
1332 oonf_class_free(&_addrtlv_memcookie, addrtlv);
1336 * Callback to add sequence number to outgoing RFC5444 packet
1337 * @param writer pointer to rfc5444 writer
1338 * @param rfc5444_target rfc5444 target where the packet will be sent to
1341 _cb_add_seqno(struct rfc5444_writer *writer, struct rfc5444_writer_target *rfc5444_target) {
1342 struct oonf_rfc5444_target *target;
1345 target = container_of(rfc5444_target, struct oonf_rfc5444_target, rfc5444_target);
1347 seqno = target->_pktseqno_refcount > 0 || target->interface->protocol->_pktseqno_refcount > 0;
1349 rfc5444_writer_set_pkt_header(writer, rfc5444_target, seqno);
1351 target->_pktseqno++;
1352 rfc5444_writer_set_pkt_seqno(writer, rfc5444_target, target->_pktseqno);
1357 * Timer callback for message aggregation
1358 * @param ptr timer instance that fired
1361 _cb_aggregation_event(struct oonf_timer_instance *ptr) {
1362 struct oonf_rfc5444_target *target;
1364 target = container_of(ptr, struct oonf_rfc5444_target, _aggregation);
1366 rfc5444_writer_flush(&target->interface->protocol->writer, &target->rfc5444_target, false);
1370 * Configuration has changed, handle the changes
1373 _cb_cfg_rfc5444_changed(void) {
1374 struct _rfc5444_config config;
1377 memset(&config, 0, sizeof(config));
1378 result = cfg_schema_tobin(&config, _rfc5444_section.post, _rfc5444_entries, ARRAYSIZE(_rfc5444_entries));
1380 OONF_WARN(LOG_RFC5444, "Could not convert " CFG_RFC5444_SECTION " to binary (%d)", -(result + 1));
1385 oonf_rfc5444_reconfigure_protocol(_rfc5444_protocol, config.port, config.ip_proto);
1389 * Configuration has changed, handle the changes
1392 _cb_cfg_interface_changed(void) {
1393 struct _rfc5444_if_config config;
1394 struct oonf_rfc5444_interface *interf;
1396 char ifbuf[IF_NAMESIZE];
1399 ifname = cfg_get_phy_if(ifbuf, _interface_section.section_name);
1401 interf = avl_find_element(&_rfc5444_protocol->_interface_tree, ifname, interf, _node);
1403 if (_interface_section.post == NULL) {
1404 /* this section has been removed */
1406 oonf_rfc5444_remove_interface(interf, NULL);
1408 goto interface_changed_cleanup;
1411 memset(&config, 0, sizeof(config));
1412 result = cfg_schema_tobin(&config, _interface_section.post, _interface_entries, ARRAYSIZE(_interface_entries));
1414 OONF_WARN(LOG_RFC5444, "Could not convert %s '%s' to binary (%d)", _interface_section.type, ifname, -(result + 1));
1415 goto interface_changed_cleanup;
1418 if (_interface_section.pre == NULL) {
1419 interf = oonf_rfc5444_add_interface(_rfc5444_protocol, NULL, ifname);
1420 if (interf == NULL) {
1421 OONF_WARN(LOG_RFC5444, "Could not generate interface '%s' for protocol '%s'", ifname, _rfc5444_protocol->name);
1422 goto interface_changed_cleanup;
1426 oonf_rfc5444_reconfigure_interface(interf, &config.sock);
1427 interf->aggregation_interval = config.aggregation_interval;
1430 interface_changed_cleanup:
1431 oonf_packet_free_managed_config(&config.sock);
1435 * Interface settings of a rfc5444 interface changed
1436 * @param managed managed socket which interface changed
1437 * @param changed true if socket addresses changed
1440 _cb_interface_changed(struct oonf_packet_managed *managed, bool changed) {
1441 struct oonf_rfc5444_interface *interf;
1442 struct oonf_rfc5444_interface_listener *l;
1444 OONF_INFO(LOG_RFC5444, "RFC5444 Interface change event: %s", managed->_managed_config.interface);
1446 interf = container_of(managed, struct oonf_rfc5444_interface, _socket);
1449 oonf_rfc5444_reconfigure_interface(interf, NULL);
1452 list_for_each_element(&interf->_listener, l, _node) {
1453 l->cb_interface_changed(l, changed);