zeek/scripts/base/utils/json.bro
Johanna Amann dbc51371cb Rewrite big parts of the Openflow framework.
The API now does not follow the openflow specification quite as closely,
however I think it is much more usable. Furthermore, the Ryu plugin was
basically completely rewritten and is now more usable for general flow
manipulation.

This also adds a debug mode that just outputs the json fragments that
would be sent to ryu. At the moment, Ryu still assumes that every
request that it receives succeeds - it is not possible to get an error
message from the controller. Instead, one has to check if a flow was
added by doing a second REST request. Which seems unnecessary, and also
requires complete json parsing functionality. Hence we are not doing
that at the moment.

The alternative would be to use an external script for the actual
add-and-check-operation.
2015-04-07 15:37:46 -07:00

103 lines
2.5 KiB
Text

##! Functions to assist with generating JSON data from Bro data scructures.
# We might want to implement this in core somtime, this looks... hacky at best.
@load base/utils/strings
## A function to convert arbitrary Bro data into a JSON string.
##
## v: The value to convert to JSON. Typically a record.
##
## only_loggable: If the v value is a record this will only cause
## fields with the &log attribute to be included in the JSON.
##
## returns: a JSON formatted string.
function to_json(v: any, only_loggable: bool &default=F, field_escape_pattern: pattern &default=/^_/): string
{
local tn = type_name(v);
switch ( tn )
{
case "type":
return "";
case "string":
return cat("\"", gsub(gsub(clean(v), /\\/, "\\\\"), /\"/, "\\\""), "\"");
case "port":
return cat(port_to_count(to_port(cat(v))));
case "addr":
return cat("\"", v, "\"");
case "int":
fallthrough;
case "count":
fallthrough;
case "time":
fallthrough;
case "double":
fallthrough;
case "bool":
fallthrough;
case "enum":
return cat(v);
default:
break;
}
if ( /^record/ in tn )
{
local rec_parts: string_vec = vector();
local ft = record_fields(v);
for ( field in ft )
{
local field_desc = ft[field];
# replace the escape pattern in the field.
if( field_escape_pattern in field )
field = cat(sub(field, field_escape_pattern, ""));
if ( field_desc?$value && (!only_loggable || field_desc$log) )
{
local onepart = cat("\"", field, "\": ", to_json(field_desc$value, only_loggable));
rec_parts[|rec_parts|] = onepart;
}
}
return cat("{", join_string_vec(rec_parts, ", "), "}");
}
# None of the following are supported.
else if ( /^set/ in tn )
{
local set_parts: string_vec = vector();
local sa: set[bool] = v;
for ( sv in sa )
{
set_parts[|set_parts|] = to_json(sv, only_loggable);
}
return cat("[", join_string_vec(set_parts, ", "), "]");
}
else if ( /^table/ in tn )
{
local tab_parts: vector of string = vector();
local ta: table[bool] of any = v;
for ( ti in ta )
{
local ts = to_json(ti);
local if_quotes = (ts[0] == "\"") ? "" : "\"";
tab_parts[|tab_parts|] = cat(if_quotes, ts, if_quotes, ": ", to_json(ta[ti], only_loggable));
}
return cat("{", join_string_vec(tab_parts, ", "), "}");
}
else if ( /^vector/ in tn )
{
local vec_parts: string_vec = vector();
local va: vector of any = v;
for ( vi in va )
{
vec_parts[|vec_parts|] = to_json(va[vi], only_loggable);
}
return cat("[", join_string_vec(vec_parts, ", "), "]");
}
return "\"\"";
}