2 * The olsr.org Optimized Link-State Routing daemon (olsrd)
4 * (c) by the OLSR project
6 * See our Git repository to find out who worked on this file
7 * and thus is a copyright holder on it.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
21 * * Neither the name of olsr.org, olsrd nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
38 * Visit http://www.olsr.org for more information.
40 * If you find this software useful feel free to make a donation
41 * to the project. For more information see the website or contact
42 * the copyright holders.
46 #include "olsrd_netjson.h"
50 #include "olsrd_netjson_helpers.h"
51 #include "olsrd_plugin.h"
52 #include "info/info_types.h"
53 #include "info/http_headers.h"
54 #include "info/json_helpers.h"
55 #include "common/avl.h"
57 #include "builddata.h"
58 #include "routing_table.h"
62 #define NETJSON_PROTOCOL "olsrv1"
64 static struct json_session json_session;
66 unsigned long long get_supported_commands_mask(void) {
67 return SIW_NETJSON & ~(SIW_NETJSON_DEVICE_CONFIGURATION | SIW_NETJSON_DEVICE_MONITORING);
70 bool isCommand(const char *str, unsigned long long siw) {
71 const char * cmd = NULL;
73 case SIW_NETJSON_NETWORK_ROUTES:
74 cmd = "/NetworkRoutes";
77 case SIW_NETJSON_NETWORK_GRAPH:
78 cmd = "/NetworkGraph";
81 case SIW_NETJSON_NETWORK_COLLECTION:
82 cmd = "/NetworkCollection";
89 return !strcmp(str, cmd);
92 const char * determine_mime_type(unsigned int send_what __attribute__((unused))) {
93 return "application/json; charset=utf-8";
96 void output_start(struct autobuf *abuf) {
97 /* global variables for tracking when to put a comma in for JSON */
98 abuf_json_reset_entry_number_and_depth(&json_session, pretty);
99 abuf_json_mark_output(&json_session, true, abuf);
102 void output_end(struct autobuf *abuf) {
103 abuf_json_mark_output(&json_session, false, abuf);
104 abuf_puts(abuf, "\n");
105 abuf_json_reset_entry_number_and_depth(&json_session, pretty);
108 void output_error(struct autobuf *abuf, unsigned int status, const char * req __attribute__((unused)), bool http_headers) {
109 if (http_headers || (status == INFO_HTTP_OK)) {
113 /* !http_headers && !INFO_HTTP_OK */
117 if (status == INFO_HTTP_NOCONTENT) {
120 abuf_json_string(&json_session, abuf, "error", httpStatusToReply(status));
126 void ipc_print_network_routes(struct autobuf *abuf) {
130 abuf_json_string(&json_session, abuf, "type", "NetworkRoutes");
131 abuf_json_string(&json_session, abuf, "protocol", NETJSON_PROTOCOL);
132 abuf_json_string(&json_session, abuf, "version", release_version);
133 abuf_json_string(&json_session, abuf, "metric", olsr_cnf->lq_algorithm);
136 abuf_json_string(&json_session, abuf, "revision", olsrd_version);
138 abuf_json_ip_address(&json_session, abuf, "router_id", &olsr_cnf->main_addr);
140 /* Walk the route table */
141 abuf_json_mark_object(&json_session, true, true, abuf, "routes");
142 OLSR_FOR_ALL_RT_ENTRIES(rt) {
144 struct lqtextbuffer lqbuf;
146 abuf_json_mark_array_entry(&json_session, true, abuf);
148 abuf_json_prefix(&json_session, abuf, "destination", &rt->rt_dst);
149 abuf_json_ip_address(&json_session, abuf, "next", &rt->rt_best->rtp_nexthop.gateway);
150 abuf_json_string(&json_session, abuf, "device", if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
151 abuf_json_float(&json_session, abuf, "cost", get_linkcost_scaled(rt->rt_best->rtp_metric.cost, true));
154 abuf_json_string(&json_session, abuf, "cost_text", get_linkcost_text(rt->rt_best->rtp_metric.cost, true, &lqbuf));
157 abuf_json_mark_array_entry(&json_session, false, abuf);
159 } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
160 abuf_json_mark_object(&json_session, false, true, abuf, NULL);
163 void ipc_print_network_graph(struct autobuf *abuf) {
164 struct avl_tree nodes;
165 struct mid_entry mid_self;
166 struct node_entry * node_self;
167 struct tc_entry * tc;
168 struct link_entry * link_entry;
169 struct neighbor_entry * neighbor;
172 avl_init(&nodes, (olsr_cnf->ip_version == AF_INET) ? avl_comp_ipv4 : avl_comp_ipv6);
175 abuf_json_string(&json_session, abuf, "type", "NetworkGraph");
176 abuf_json_string(&json_session, abuf, "protocol", NETJSON_PROTOCOL);
177 abuf_json_string(&json_session, abuf, "version", release_version);
178 abuf_json_string(&json_session, abuf, "metric", olsr_cnf->lq_algorithm);
181 abuf_json_string(&json_session, abuf, "revision", olsrd_version);
183 abuf_json_ip_address(&json_session, abuf, "router_id", &olsr_cnf->main_addr);
191 node_self = netjson_constructMidSelf(&mid_self);
192 netjson_midIntoNodesTree(&nodes, &mid_self);
195 for (idx = 0; idx < HASHSIZE; idx++) {
196 struct mid_entry * entry = mid_set[idx].next;
197 while (entry != &mid_set[idx]) {
198 netjson_midIntoNodesTree(&nodes, entry);
204 OLSR_FOR_ALL_TC_ENTRIES(tc) {
205 struct tc_edge_entry *tc_edge;
206 netjson_tcIntoNodesTree(&nodes, tc);
207 OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
208 netjson_tcEdgeIntoNodesTree(&nodes, tc_edge);
209 } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
210 } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
213 OLSR_FOR_ALL_LINK_ENTRIES(link_entry) {
214 netjson_linkIntoNodesTree(&nodes, link_entry, &link_entry->local_iface_addr);
215 netjson_linkIntoNodesTree(&nodes, link_entry, &link_entry->neighbor_iface_addr);
216 } OLSR_FOR_ALL_LINK_ENTRIES_END(link_entry);
219 OLSR_FOR_ALL_NBR_ENTRIES(neighbor) {
220 netjson_neighborIntoNodesTree(&nodes, neighbor);
221 } OLSR_FOR_ALL_NBR_ENTRIES_END(neighbor);
227 abuf_json_mark_object(&json_session, true, true, abuf, "nodes");
228 while (nodes.count > 0) {
229 struct avl_node *node = avl_walk_first(&nodes);
230 struct node_entry *node_entry = avlnode2node(node);
232 if (!node_entry->isAlias) {
233 abuf_json_mark_array_entry(&json_session, true, abuf);
236 abuf_json_ip_address(&json_session, abuf, "id", node->key);
240 if (node_entry->mid) {
241 struct mid_address * alias = node_entry->mid->aliases;
243 abuf_json_mark_object(&json_session, true, true, abuf, "local_addresses");
245 abuf_json_ip_address(&json_session, abuf, NULL, &alias->alias);
246 alias = alias->next_alias;
248 abuf_json_mark_object(&json_session, false, true, abuf, NULL);
250 } else if (node_entry->tc) {
251 /* no local_addresses */
252 } else if (node_entry->tc_edge) {
253 /* no local_addresses */
254 } else if (node_entry->link) {
255 /* no local_addresses */
256 } else if (node_entry->neighbor) {
257 /* no local_addresses */
261 abuf_json_mark_array_entry(&json_session, false, abuf);
264 if (node_entry->mid && (node_entry == node_self)) {
265 netjson_cleanup_mid_self(node_self);
268 avl_delete(&nodes, node);
271 abuf_json_mark_object(&json_session, false, true, abuf, NULL);
277 abuf_json_mark_object(&json_session, true, true, abuf, "links");
279 OLSR_FOR_ALL_LINK_ENTRIES(link_entry) {
280 struct lqtextbuffer lqbuf;
281 int link_status = lookup_link_status(link_entry);
283 if ((link_status != ASYM_LINK) && (link_status != SYM_LINK)) {
288 * link from node to neighbor
290 if (link_status == SYM_LINK) {
291 abuf_json_mark_array_entry(&json_session, true, abuf);
294 abuf_json_ip_address(&json_session, abuf, "source", &link_entry->local_iface_addr);
295 abuf_json_ip_address(&json_session, abuf, "target", &link_entry->neighbor_iface_addr);
296 abuf_json_float(&json_session, abuf, "cost", get_linkcost_scaled(link_entry->linkcost, false));
299 abuf_json_string(&json_session, abuf, "cost_text", get_linkcost_text(link_entry->linkcost, false, &lqbuf));
302 abuf_json_mark_array_entry(&json_session, false, abuf);
306 * link from neighbor to node
308 abuf_json_mark_array_entry(&json_session, true, abuf);
311 abuf_json_ip_address(&json_session, abuf, "source", &link_entry->neighbor_iface_addr);
312 abuf_json_ip_address(&json_session, abuf, "target", &link_entry->local_iface_addr);
313 abuf_json_float(&json_session, abuf, "cost", get_linkcost_scaled(link_entry->linkcost, false));
316 abuf_json_string(&json_session, abuf, "cost_text", get_linkcost_text(link_entry->linkcost, false, &lqbuf));
319 abuf_json_mark_array_entry(&json_session, false, abuf);
320 } OLSR_FOR_ALL_LINK_ENTRIES_END(my_link);
322 OLSR_FOR_ALL_TC_ENTRIES(tc) {
323 struct tc_edge_entry *tc_edge;
324 OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
325 struct lqtextbuffer lqbuf;
327 if (ipequal(&olsr_cnf->main_addr, &tc->addr)) {
331 abuf_json_mark_array_entry(&json_session, true, abuf);
334 abuf_json_ip_address(&json_session, abuf, "source", &tc->addr);
335 abuf_json_ip_address(&json_session, abuf, "target", &tc_edge->T_dest_addr);
336 abuf_json_float(&json_session, abuf, "cost", get_linkcost_scaled(tc_edge->cost, false));
339 abuf_json_string(&json_session, abuf, "cost_text", get_linkcost_text(tc_edge->cost, false, &lqbuf));
342 abuf_json_mark_array_entry(&json_session, false, abuf);
343 } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
344 } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
346 abuf_json_mark_object(&json_session, false, true, abuf, NULL);
349 void ipc_print_network_collection(struct autobuf *abuf) {
351 abuf_json_string(&json_session, abuf, "type", "NetworkCollection");
353 abuf_json_mark_object(&json_session, true, true, abuf, "collection");
355 abuf_json_mark_array_entry(&json_session, true, abuf);
356 ipc_print_network_routes(abuf);
357 abuf_json_mark_array_entry(&json_session, false, abuf);
359 abuf_json_mark_array_entry(&json_session, true, abuf);
360 ipc_print_network_graph(abuf);
361 abuf_json_mark_array_entry(&json_session, false, abuf);
363 abuf_json_mark_object(&json_session, false, true, abuf, NULL);