0f213a84f6ee1589437271b26e91cf0fbb40bd2b
[oonf.git] / src-plugins / generic / dlep / radio / dlep_radio.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 "common/avl.h"
50 #include "common/avl_comp.h"
51 #include "common/common_types.h"
52 #include "common/netaddr.h"
53
54 #include "config/cfg_schema.h"
55 #include "core/oonf_subsystem.h"
56 #include "subsystems/oonf_class.h"
57 #include "subsystems/oonf_layer2.h"
58 #include "subsystems/oonf_packet_socket.h"
59 #include "subsystems/oonf_stream_socket.h"
60 #include "subsystems/oonf_timer.h"
61
62 #include "dlep/dlep_iana.h"
63 #include "dlep/dlep_writer.h"
64 #include "dlep/radio/dlep_radio.h"
65 #include "dlep/radio/dlep_radio_interface.h"
66 #include "dlep/radio/dlep_radio_internal.h"
67
68 /* prototypes */
69 static void _early_cfg_init(void);
70 static int _init(void);
71 static void _cleanup(void);
72 static void _initiate_shutdown(void);
73
74 static void _cb_config_changed(void);
75
76 /* configuration */
77 static struct cfg_schema_entry _radio_entries[] = {
78   CFG_MAP_STRING_ARRAY(dlep_radio_if, interf.udp_config.interface, "datapath_if", "",
79     "Name of interface to talk to dlep router (default is section name)", IF_NAMESIZE),
80
81   CFG_MAP_STRING(dlep_radio_if, interf.session.cfg.peer_type, "peer_type", "OONF DLEP Radio",
82     "Identification string of DLEP radio endpoint"),
83
84   CFG_MAP_NETADDR_V4(dlep_radio_if, interf.udp_config.multicast_v4, "discovery_mc_v4",
85     DLEP_WELL_KNOWN_MULTICAST_ADDRESS, "IPv4 address to send discovery UDP packet to", false, false),
86   CFG_MAP_NETADDR_V6(dlep_radio_if, interf.udp_config.multicast_v6, "discovery_mc_v6",
87     DLEP_WELL_KNOWN_MULTICAST_ADDRESS_6, "IPv6 address to send discovery UDP packet to", false, false),
88   CFG_MAP_INT32_MINMAX(dlep_radio_if, interf.udp_config.port, "discovery_port", DLEP_WELL_KNOWN_MULTICAST_PORT_TXT,
89     "UDP port for discovery packets", 0, 1, 65535),
90   CFG_MAP_ACL_V46(dlep_radio_if, interf.udp_config.bindto, "discovery_bindto", "fe80::/10",
91     "Filter to determine the binding of the UDP discovery socket"),
92
93   CFG_MAP_INT32_MINMAX(dlep_radio_if, tcp_config.port, "session_port", DLEP_WELL_KNOWN_SESSION_PORT_TXT,
94     "Server port for DLEP tcp sessions", 0, 1, 65535),
95   CFG_MAP_ACL_V46(dlep_radio_if, tcp_config.bindto, "session_bindto", "224.0.0.1\0fe80::/10",
96     "Filter to determine the binding of the TCP server socket"),
97   CFG_MAP_CLOCK_MINMAX(dlep_radio_if, interf.session.cfg.heartbeat_interval, "heartbeat_interval", "1.000",
98     "Interval in seconds between two heartbeat signals", 1000, 65535 * 1000),
99
100   CFG_MAP_BOOL(dlep_radio_if, interf.single_session, "single_session", "true", "Connect only to a single router"),
101
102   CFG_MAP_BOOL(dlep_radio_if, interf.session.cfg.send_proxied, "proxied", "true",
103     "Report 802.11s proxied mac address for neighbors"),
104   CFG_MAP_BOOL(dlep_radio_if, interf.session.cfg.send_neighbors, "not_proxied", "false", "Report direct neighbors"),
105 };
106
107 static struct cfg_schema_section _radio_section = {
108   .type = OONF_DLEP_RADIO_SUBSYSTEM,
109   .mode = CFG_SSMODE_NAMED,
110
111   .help = "name of the layer2 interface DLEP radio will take its data from",
112
113   .cb_delta_handler = _cb_config_changed,
114
115   .entries = _radio_entries,
116   .entry_count = ARRAYSIZE(_radio_entries),
117 };
118
119 /* subsystem declaration */
120 static const char *_dependencies[] = {
121   OONF_CLASS_SUBSYSTEM,
122   OONF_LAYER2_SUBSYSTEM,
123   OONF_PACKET_SUBSYSTEM,
124   OONF_STREAM_SUBSYSTEM,
125   OONF_TIMER_SUBSYSTEM,
126 };
127 static struct oonf_subsystem _dlep_radio_subsystem = {
128   .name = OONF_DLEP_RADIO_SUBSYSTEM,
129   .dependencies = _dependencies,
130   .dependencies_count = ARRAYSIZE(_dependencies),
131   .descr = "OONF DLEP radio plugin",
132   .author = "Henning Rogge",
133
134   .cfg_section = &_radio_section,
135
136   .early_cfg_init = _early_cfg_init,
137   .init = _init,
138   .initiate_shutdown = _initiate_shutdown,
139   .cleanup = _cleanup,
140 };
141 DECLARE_OONF_PLUGIN(_dlep_radio_subsystem);
142
143 /* logging */
144 enum oonf_log_source LOG_DLEP_RADIO;
145
146 static void
147 _early_cfg_init(void) {
148   LOG_DLEP_RADIO = _dlep_radio_subsystem.logging;
149 }
150
151 /**
152  * Plugin constructor for dlep radio
153  * @return -1 if an error happened, 0 otherwise
154  */
155 static int
156 _init(void) {
157   dlep_radio_interface_init();
158   return 0;
159 }
160
161 /**
162  * Send a clean Peer Terminate before we drop the session to shutdown
163  */
164 static void
165 _initiate_shutdown(void) {
166   dlep_radio_terminate_all_sessions();
167 }
168
169 /**
170  * Plugin destructor for dlep radio
171  */
172 static void
173 _cleanup(void) {
174   dlep_radio_interface_cleanup();
175 }
176
177 /**
178  * Callback for configuration changes
179  */
180 static void
181 _cb_config_changed(void) {
182   struct dlep_radio_if *interface;
183   const char *ifname;
184   char ifbuf[IF_NAMESIZE];
185   int error;
186
187   ifname = cfg_get_phy_if(ifbuf, _radio_section.section_name);
188
189   if (!_radio_section.post) {
190     /* remove old interface object */
191     interface = dlep_radio_get_by_layer2_if(ifname);
192     if (interface) {
193       dlep_radio_remove_interface(interface);
194     }
195     return;
196   }
197
198   /* get interface object or create one */
199   interface = dlep_radio_add_interface(ifname);
200   if (!interface) {
201     return;
202   }
203
204   /* read configuration */
205   error = cfg_schema_tobin(interface, _radio_section.post, _radio_entries, ARRAYSIZE(_radio_entries));
206   if (error) {
207     OONF_WARN(LOG_DLEP_RADIO, "Could not convert " OONF_DLEP_RADIO_SUBSYSTEM " config to bin (%d)", error);
208     return;
209   }
210
211   if (!interface->interf.udp_config.interface[0]) {
212     strscpy(interface->interf.udp_config.interface, ifname, IF_NAMESIZE);
213   }
214   else {
215     cfg_get_phy_if(interface->interf.udp_config.interface, interface->interf.udp_config.interface);
216   }
217   /* apply interface name also to TCP socket */
218   strscpy(interface->tcp_config.interface, interface->interf.udp_config.interface, IF_NAMESIZE);
219
220   /* apply settings */
221   dlep_radio_apply_interface_settings(interface);
222 }