8cc9b8cd84a03e2ba0227e7195bdc7d2d708f13d
[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 const char *_UDP_MODE[] = {
78   [DLEP_IF_UDP_NONE] = DLEP_IF_UDP_NONE_STR,
79   [DLEP_IF_UDP_SINGLE_SESSION] = DLEP_IF_UDP_SINGLE_SESSION_STR,
80   [DLEP_IF_UDP_ALWAYS] = DLEP_IF_UDP_ALWAYS_STR,
81 };
82
83 static struct cfg_schema_entry _radio_entries[] = {
84   CFG_MAP_STRING_ARRAY(dlep_radio_if, interf.udp_config.interface, "datapath_if", "",
85     "Name of interface to talk to dlep router (default is section name)", IF_NAMESIZE),
86
87   CFG_MAP_STRING(dlep_radio_if, interf.session.cfg.peer_type, "peer_type", "OONF DLEP Radio",
88     "Identification string of DLEP radio endpoint"),
89
90   CFG_MAP_NETADDR_V4(dlep_radio_if, interf.udp_config.multicast_v4, "discovery_mc_v4",
91     DLEP_WELL_KNOWN_MULTICAST_ADDRESS, "IPv4 address to send discovery UDP packet to", false, false),
92   CFG_MAP_NETADDR_V6(dlep_radio_if, interf.udp_config.multicast_v6, "discovery_mc_v6",
93     DLEP_WELL_KNOWN_MULTICAST_ADDRESS_6, "IPv6 address to send discovery UDP packet to", false, false),
94   CFG_MAP_INT32_MINMAX(dlep_radio_if, interf.udp_config.port, "discovery_port", DLEP_WELL_KNOWN_MULTICAST_PORT_TXT,
95     "UDP port for discovery packets", 0, 1, 65535),
96   CFG_MAP_ACL_V46(dlep_radio_if, interf.udp_config.bindto, "discovery_bindto", "fe80::/10",
97     "Filter to determine the binding of the UDP discovery socket"),
98
99   CFG_MAP_INT32_MINMAX(dlep_radio_if, tcp_config.port, "session_port", DLEP_WELL_KNOWN_SESSION_PORT_TXT,
100     "Server port for DLEP tcp sessions", 0, 1, 65535),
101   CFG_MAP_ACL_V46(dlep_radio_if, tcp_config.bindto, "session_bindto", "169.254.0.0/16\0fe80::/10",
102     "Filter to determine the binding of the TCP server socket"),
103   CFG_MAP_CLOCK_MINMAX(dlep_radio_if, interf.session.cfg.heartbeat_interval, "heartbeat_interval", "1.000",
104     "Interval in seconds between two heartbeat signals", 1000, 65535 * 1000),
105
106   CFG_MAP_CHOICE(dlep_radio_if, interf.udp_mode, "udp_mode", DLEP_IF_UDP_SINGLE_SESSION_STR,
107     "Determines the UDP behavior of the radio. 'none' never sends/processes UDP, 'single_session' only does"
108     " if no DLEP session is active and 'always' always sends/processes UDP and allows multiple sessions",
109     _UDP_MODE),
110
111   CFG_MAP_BOOL(dlep_radio_if, interf.session.cfg.send_proxied, "proxied", "true",
112     "Report 802.11s proxied mac address for neighbors"),
113   CFG_MAP_BOOL(dlep_radio_if, interf.session.cfg.send_neighbors, "not_proxied", "false", "Report direct neighbors"),
114 };
115
116 static struct cfg_schema_section _radio_section = {
117   .type = OONF_DLEP_RADIO_SUBSYSTEM,
118   .mode = CFG_SSMODE_NAMED,
119
120   .help = "name of the layer2 interface DLEP radio will take its data from",
121
122   .cb_delta_handler = _cb_config_changed,
123
124   .entries = _radio_entries,
125   .entry_count = ARRAYSIZE(_radio_entries),
126 };
127
128 /* subsystem declaration */
129 static const char *_dependencies[] = {
130   OONF_CLASS_SUBSYSTEM,
131   OONF_LAYER2_SUBSYSTEM,
132   OONF_PACKET_SUBSYSTEM,
133   OONF_STREAM_SUBSYSTEM,
134   OONF_TIMER_SUBSYSTEM,
135 };
136 static struct oonf_subsystem _dlep_radio_subsystem = {
137   .name = OONF_DLEP_RADIO_SUBSYSTEM,
138   .dependencies = _dependencies,
139   .dependencies_count = ARRAYSIZE(_dependencies),
140   .descr = "OONF DLEP radio plugin",
141   .author = "Henning Rogge",
142
143   .cfg_section = &_radio_section,
144
145   .early_cfg_init = _early_cfg_init,
146   .init = _init,
147   .initiate_shutdown = _initiate_shutdown,
148   .cleanup = _cleanup,
149 };
150 DECLARE_OONF_PLUGIN(_dlep_radio_subsystem);
151
152 /* logging */
153 enum oonf_log_source LOG_DLEP_RADIO;
154
155 static void
156 _early_cfg_init(void) {
157   LOG_DLEP_RADIO = _dlep_radio_subsystem.logging;
158 }
159
160 /**
161  * Plugin constructor for dlep radio
162  * @return -1 if an error happened, 0 otherwise
163  */
164 static int
165 _init(void) {
166   dlep_radio_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_radio_terminate_all_sessions();
176 }
177
178 /**
179  * Plugin destructor for dlep radio
180  */
181 static void
182 _cleanup(void) {
183   dlep_radio_interface_cleanup();
184 }
185
186 /**
187  * Callback for configuration changes
188  */
189 static void
190 _cb_config_changed(void) {
191   struct dlep_radio_if *interface;
192   const char *ifname;
193   char ifbuf[IF_NAMESIZE];
194   int error;
195
196   ifname = cfg_get_phy_if(ifbuf, _radio_section.section_name);
197
198   if (!_radio_section.post) {
199     /* remove old interface object */
200     interface = dlep_radio_get_by_layer2_if(ifname);
201     if (interface) {
202       dlep_radio_remove_interface(interface);
203     }
204     return;
205   }
206
207   /* get interface object or create one */
208   interface = dlep_radio_add_interface(ifname);
209   if (!interface) {
210     return;
211   }
212
213   /* read configuration */
214   error = cfg_schema_tobin(interface, _radio_section.post, _radio_entries, ARRAYSIZE(_radio_entries));
215   if (error) {
216     OONF_WARN(LOG_DLEP_RADIO, "Could not convert " OONF_DLEP_RADIO_SUBSYSTEM " config to bin (%d)", error);
217     return;
218   }
219
220   if (!interface->interf.udp_config.interface[0]) {
221     strscpy(interface->interf.udp_config.interface, ifname, IF_NAMESIZE);
222   }
223   else {
224     cfg_get_phy_if(interface->interf.udp_config.interface, interface->interf.udp_config.interface);
225   }
226   /* apply interface name also to TCP socket */
227   strscpy(interface->tcp_config.interface, interface->interf.udp_config.interface, IF_NAMESIZE);
228
229   /* apply settings */
230   dlep_radio_apply_interface_settings(interface);
231 }