a751fd1c2a98928cb3337caf7677353e57436fa9
[oonf.git] / src / generic / dlep / router / dlep_router.c
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 #include <errno.h>
47 #include <unistd.h>
48
49 #include <oonf/libcommon/avl.h>
50 #include <oonf/libcommon/avl_comp.h>
51 #include <oonf/oonf.h>
52 #include <oonf/libcommon/netaddr.h>
53
54 #include <oonf/libconfig/cfg_schema.h>
55 #include <oonf/libcore/oonf_subsystem.h>
56 #include <oonf/subsystems/oonf_class.h>
57 #include <oonf/subsystems/oonf_layer2.h>
58 #include <oonf/subsystems/oonf_packet_socket.h>
59 #include <oonf/subsystems/oonf_stream_socket.h>
60 #include <oonf/subsystems/oonf_timer.h>
61
62 #include <oonf/generic/dlep/dlep_iana.h>
63 #include <oonf/generic/dlep/dlep_session.h>
64 #include <oonf/generic/dlep/router/dlep_router.h>
65 #include <oonf/generic/dlep/router/dlep_router_interface.h>
66
67 /* prototypes */
68 static void _early_cfg_init(void);
69 static int _init(void);
70 static void _initiate_shutdown(void);
71 static void _cleanup(void);
72
73 static void _cb_config_changed(void);
74
75 /* configuration */
76 static const char *_UDP_MODE[] = {
77   [DLEP_IF_UDP_NONE] = DLEP_IF_UDP_NONE_STR,
78   [DLEP_IF_UDP_SINGLE_SESSION] = DLEP_IF_UDP_SINGLE_SESSION_STR,
79   [DLEP_IF_UDP_ALWAYS] = DLEP_IF_UDP_ALWAYS_STR,
80 };
81
82 static struct cfg_schema_entry _router_entries[] = {
83   CFG_MAP_STRING(dlep_router_if, interf.session.cfg.peer_type, "peer_type", "OONF DLEP Router",
84     "Identification string of DLEP router endpoint"),
85
86   CFG_MAP_NETADDR_V4(dlep_router_if, interf.udp_config.multicast_v4, "discovery_mc_v4",
87     DLEP_WELL_KNOWN_MULTICAST_ADDRESS, "IPv4 address to send discovery UDP packet to", false, false),
88   CFG_MAP_NETADDR_V6(dlep_router_if, interf.udp_config.multicast_v6, "discovery_mc_v6",
89     DLEP_WELL_KNOWN_MULTICAST_ADDRESS_6, "IPv6 address to send discovery UDP packet to", false, false),
90   CFG_MAP_INT32_MINMAX(dlep_router_if, interf.udp_config.multicast_port, "discovery_port",
91     DLEP_WELL_KNOWN_MULTICAST_PORT_TXT, "UDP port for discovery packets", 0, 1, 65535),
92
93   CFG_MAP_ACL_V46(dlep_router_if, interf.udp_config.bindto, "discovery_bindto", "224.0.0.1\0fe80::/10",
94     "Filter to determine the binding of the UDP discovery socket"),
95
96   CFG_MAP_CLOCK_MIN(dlep_router_if, interf.session.cfg.discovery_interval, "discovery_interval", "1.000",
97     "Interval in seconds between two discovery beacons", 1000),
98   CFG_MAP_CLOCK_MINMAX(dlep_router_if, interf.session.cfg.heartbeat_interval, "heartbeat_interval", "1.000",
99     "Interval in seconds between two heartbeat signals", 1000, 65535000),
100
101   CFG_MAP_CHOICE(dlep_router_if, interf.udp_mode, "udp_mode", DLEP_IF_UDP_SINGLE_SESSION_STR,
102     "Determines the UDP behavior of the router. 'none' never sends/processes UDP, 'single_session' only does"
103     " if no DLEP session is active and 'always' always sends/processes UDP and allows multiple sessions",
104     _UDP_MODE),
105
106   CFG_MAP_STRING_ARRAY(dlep_router_if, interf.udp_config.interface, "datapath_if", "",
107     "Overwrite datapath interface for incoming dlep traffic, used for"
108     " receiving DLEP data through out-of-band channel.",
109     IF_NAMESIZE),
110
111   CFG_MAP_NETADDR_V46(dlep_router_if, connect_to_addr, "connect_to", "-",
112     "IP to directly connect to a known DLEP radio TCP socket", false, true),
113   CFG_MAP_INT32_MINMAX(dlep_router_if, connect_to_port, "connect_to_port", DLEP_WELL_KNOWN_SESSION_PORT_TXT,
114     "TCP port to directly connect to a known DLEP radio TCP socket", 0, 1, 65535),
115 };
116
117 static struct cfg_schema_section _router_section = {
118   .type = OONF_DLEP_ROUTER_SUBSYSTEM,
119   .mode = CFG_SSMODE_NAMED,
120
121   .help = "name of the layer2 interface DLEP router will put its data into",
122
123   .cb_delta_handler = _cb_config_changed,
124
125   .entries = _router_entries,
126   .entry_count = ARRAYSIZE(_router_entries),
127 };
128
129 /* plugin declaration */
130 static const char *_dependencies[] = {
131   OONF_CLASS_SUBSYSTEM,
132   OONF_LAYER2_SUBSYSTEM,
133   OONF_PACKET_SUBSYSTEM,
134   OONF_STREAM_SUBSYSTEM,
135   OONF_TIMER_SUBSYSTEM,
136 };
137 static struct oonf_subsystem _dlep_router_subsystem = {
138   .name = OONF_DLEP_ROUTER_SUBSYSTEM,
139   .dependencies = _dependencies,
140   .dependencies_count = ARRAYSIZE(_dependencies),
141   .descr = "OONF DLEP router plugin",
142   .author = "Henning Rogge",
143
144   .cfg_section = &_router_section,
145
146   .early_cfg_init = _early_cfg_init,
147   .init = _init,
148   .initiate_shutdown = _initiate_shutdown,
149   .cleanup = _cleanup,
150 };
151 DECLARE_OONF_PLUGIN(_dlep_router_subsystem);
152
153 enum oonf_log_source LOG_DLEP_ROUTER;
154
155 static void
156 _early_cfg_init(void) {
157   LOG_DLEP_ROUTER = _dlep_router_subsystem.logging;
158 }
159
160 /**
161  * Plugin constructor for dlep router
162  * @return -1 if an error happened, 0 otherwise
163  */
164 static int
165 _init(void) {
166   dlep_router_interface_init();
167   return 0;
168 }
169
170 /**
171  * Send a clean Peer Terminate before we drop the session to shutdown
172  */
173 static void
174 _initiate_shutdown(void) {
175   dlep_router_terminate_all_sessions();
176 }
177
178 /**
179  * Plugin destructor for dlep router
180  */
181 static void
182 _cleanup(void) {
183   dlep_router_interface_cleanup();
184 }
185
186 /**
187  * Callback for configuration changes
188  */
189 static void
190 _cb_config_changed(void) {
191   struct dlep_router_if *interface;
192   const char *ifname;
193   char ifbuf[IF_NAMESIZE];
194
195   ifname = cfg_get_phy_if(ifbuf, _router_section.section_name);
196
197   if (!_router_section.post) {
198     /* remove old session object */
199     interface = dlep_router_get_by_layer2_if(ifname);
200     if (interface) {
201       dlep_router_remove_interface(interface);
202     }
203     return;
204   }
205
206   /* get session object or create one */
207   interface = dlep_router_add_interface(ifname);
208   if (!interface) {
209     return;
210   }
211
212   /* read configuration */
213   if (cfg_schema_tobin(interface, _router_section.post, _router_entries, ARRAYSIZE(_router_entries))) {
214     OONF_WARN(LOG_DLEP_ROUTER, "Could not convert " OONF_DLEP_ROUTER_SUBSYSTEM " config to bin");
215     return;
216   }
217
218   /* use section name as default for datapath interface */
219   if (!interface->interf.udp_config.interface[0]) {
220     strscpy(interface->interf.udp_config.interface, _router_section.section_name,
221       sizeof(interface->interf.udp_config.interface));
222   }
223   else {
224     cfg_get_phy_if(interface->interf.udp_config.interface, interface->interf.udp_config.interface);
225   }
226
227   /* apply settings */
228   dlep_router_apply_interface_settings(interface);
229 }