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/libcommon/netaddr.h>
50 #include <oonf/base/oonf_class.h>
51 #include <oonf/base/oonf_layer2.h>
52 #include <oonf/base/oonf_packet_socket.h>
53 #include <oonf/base/oonf_stream_socket.h>
54 #include <oonf/base/oonf_timer.h>
56 #include <oonf/generic/dlep/dlep_iana.h>
57 #include <oonf/generic/dlep/dlep_session.h>
58 #include <oonf/generic/dlep/dlep_writer.h>
59 #include <oonf/generic/dlep/radio/dlep_radio.h>
60 #include <oonf/generic/dlep/radio/dlep_radio_interface.h>
61 #include <oonf/generic/dlep/radio/dlep_radio_internal.h>
62 #include <oonf/generic/dlep/radio/dlep_radio_session.h>
64 static int _cb_incoming_tcp(struct oonf_stream_session *);
65 static void _cb_tcp_lost(struct oonf_stream_session *);
66 static enum oonf_stream_session_state _cb_tcp_receive_data(struct oonf_stream_session *);
67 static void _cb_send_buffer(struct dlep_session *session, int af_family);
68 static void _cb_end_session(struct dlep_session *session);
70 static struct oonf_class _radio_session_class = {
71 .name = "DLEP TCP session",
72 .size = sizeof(struct dlep_radio_session),
76 * Initialize framework for dlep radio sessions
79 dlep_radio_session_init(void) {
80 oonf_class_add(&_radio_session_class);
84 * Cleanup dlep radio session framework
87 dlep_radio_session_cleanup(void) {
88 oonf_class_remove(&_radio_session_class);
92 * Initialize the callbacks for a dlep tcp socket
93 * @param config tcp socket config
96 dlep_radio_session_initialize_tcp_callbacks(struct oonf_stream_config *config) {
97 config->memcookie = &_radio_session_class;
98 config->init_session = _cb_incoming_tcp;
99 config->cleanup_session = _cb_tcp_lost;
100 config->receive_data = _cb_tcp_receive_data;
104 * Remove existing dlep radio session
105 * @param radio_session dlep radio session
108 dlep_radio_remove_session(struct dlep_radio_session *radio_session) {
109 oonf_stream_close(&radio_session->stream);
113 * Callback triggered when a new tcp session is accepted by the local socket
114 * @param tcp_session pointer to tcp session object
118 _cb_incoming_tcp(struct oonf_stream_session *tcp_session) {
119 struct dlep_radio_session *radio_session;
120 struct dlep_radio_if *interface;
121 struct dlep_extension *ext;
123 radio_session = container_of(tcp_session, struct dlep_radio_session, stream);
124 interface = container_of(tcp_session->stream_socket->managed, struct dlep_radio_if, tcp);
126 /* initialize back pointer */
127 radio_session->interface = interface;
129 /* activate session */
130 if (dlep_session_add(&radio_session->session, interface->interf.l2_ifname, interface->interf.session.l2_origin,
131 interface->interf.session.l2_default_origin, &tcp_session->out, true, NULL, LOG_DLEP_RADIO)) {
134 radio_session->session.restrict_signal = DLEP_SESSION_INITIALIZATION;
135 radio_session->session.cb_send_buffer = _cb_send_buffer;
136 radio_session->session.cb_end_session = _cb_end_session;
137 memcpy(&radio_session->session.cfg, &interface->interf.session.cfg, sizeof(radio_session->session.cfg));
139 &radio_session->session.remote_socket, &tcp_session->remote_socket, sizeof(radio_session->session.remote_socket));
141 /* attach to session tree of interface */
142 radio_session->_node.key = &radio_session->stream.remote_socket;
143 avl_insert(&interface->interf.session_tree, &radio_session->_node);
145 /* copy socket information */
147 &radio_session->session.remote_socket, &tcp_session->remote_socket, sizeof(radio_session->session.remote_socket));
149 /* inform all extensions */
150 avl_for_each_element(dlep_extension_get_tree(), ext, _node) {
151 if (ext->cb_session_init_radio) {
152 ext->cb_session_init_radio(&radio_session->session);
160 * Callback when a tcp session is lost and must be closed
161 * @param tcp_session pointer to tcp session object
164 _cb_tcp_lost(struct oonf_stream_session *tcp_session) {
165 struct dlep_radio_session *radio_session;
166 struct dlep_extension *ext;
167 #ifdef OONF_LOG_DEBUG_INFO
168 struct netaddr_str nbuf;
171 radio_session = container_of(tcp_session, struct dlep_radio_session, stream);
173 OONF_DEBUG(LOG_DLEP_RADIO, "Lost tcp session to %s", netaddr_socket_to_string(&nbuf, &tcp_session->remote_socket));
175 avl_for_each_element(dlep_extension_get_tree(), ext, _node) {
176 if (ext->cb_session_cleanup_radio) {
177 ext->cb_session_cleanup_radio(&radio_session->session);
181 /* kill embedded session object */
182 dlep_session_remove(&radio_session->session);
184 /* remove from session tree of interface */
185 avl_remove(&radio_session->interface->interf.session_tree, &radio_session->_node);
189 * Callback to receive data over oonf_stream_socket
190 * @param tcp_session pointer to tcp session
191 * @return tcp session state
193 static enum oonf_stream_session_state
194 _cb_tcp_receive_data(struct oonf_stream_session *tcp_session) {
195 struct dlep_radio_session *radio_session;
197 radio_session = container_of(tcp_session, struct dlep_radio_session, stream);
199 return dlep_session_process_tcp(tcp_session, &radio_session->session);
203 _cb_send_buffer(struct dlep_session *session, int af_family __attribute((unused))) {
204 struct dlep_radio_session *radio_session;
206 if (!abuf_getlen(session->writer.out)) {
210 OONF_DEBUG(session->log_source, "Send buffer %" PRINTF_SIZE_T_SPECIFIER " bytes", abuf_getlen(session->writer.out));
212 /* get pointer to radio interface */
213 radio_session = container_of(session, struct dlep_radio_session, session);
215 oonf_stream_flush(&radio_session->stream);
219 _cb_end_session(struct dlep_session *session) {
220 struct dlep_radio_session *radio_session;
222 /* get pointer to radio interface */
223 radio_session = container_of(session, struct dlep_radio_session, session);
225 dlep_radio_remove_session(radio_session);