mirror of https://github.com/OISF/suricata
build: cbindgen
Rust headers are now generated using cbindgen. If cbindgen is present, they can be generated during dist, otherwise they will be available for builds.pull/4501/head
parent
593da166bb
commit
b573c16dd5
@ -0,0 +1,151 @@
|
||||
# The language to output bindings in
|
||||
#
|
||||
# possible values: "C", "C++"
|
||||
#
|
||||
# default: "C++"
|
||||
language = "C"
|
||||
|
||||
|
||||
# Options for wrapping the contents of the header:
|
||||
|
||||
# An optional string of text to output at the beginning of the generated file
|
||||
# default: doesn't emit anything
|
||||
header = """/* Copyright (C) 2019 Open Information Security Foundation
|
||||
*
|
||||
* You can copy, redistribute or modify this Program under the terms of
|
||||
* the GNU General Public License version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/"""
|
||||
|
||||
# An optional name to use as an include guard
|
||||
# default: doesn't emit an include guard
|
||||
include_guard = "__RUST_BINDINGS_GEN_H_"
|
||||
|
||||
# An optional string of text to output between major sections of the generated
|
||||
# file as a warning against manual editing
|
||||
#
|
||||
# default: doesn't emit anything
|
||||
autogen_warning = "/* DO NOT EDIT This file is autogenerated by cbindgen. Don't modify this manually. */"
|
||||
|
||||
# Whether to include a comment with the version of cbindgen used to generate the file
|
||||
# default: false
|
||||
include_version = true
|
||||
|
||||
# A list of headers to #include (with quotes)
|
||||
# default: []
|
||||
includes = ["rust.h"]
|
||||
|
||||
# The desired length of a line to use when formatting lines
|
||||
# default: 100
|
||||
line_length = 80
|
||||
|
||||
# The amount of spaces to indent by
|
||||
# default: 2
|
||||
tab_width = 4
|
||||
|
||||
# How the generated documentation should be commented.
|
||||
#
|
||||
# possible values:
|
||||
# * "c": /* like this */
|
||||
# * "c99": // like this
|
||||
# * "c++": /// like this
|
||||
# * "doxy": like C, but with leading *'s on each line
|
||||
# * "auto": "c++" if that's the language, "doxy" otherwise
|
||||
#
|
||||
# default: "auto"
|
||||
documentation_style = "doxy"
|
||||
|
||||
|
||||
[export]
|
||||
# A list of additional items to always include in the generated bindings if they're
|
||||
# found but otherwise don't appear to be used by the public API.
|
||||
#
|
||||
# default: []
|
||||
include = ["AppLayerGetTxIterTuple"]
|
||||
|
||||
# A list of items to not include in the generated bindings
|
||||
# default: []
|
||||
exclude = [
|
||||
"AppLayerDecoderEvents",
|
||||
"CLuaState",
|
||||
"DetectEngineState",
|
||||
"Flow",
|
||||
"FileContainer",
|
||||
"JsonT",
|
||||
"IKEV2State",
|
||||
"IKEV2Transaction",
|
||||
"KRB5State",
|
||||
"KRB5Transaction",
|
||||
"NTPState",
|
||||
"NTPTransaction",
|
||||
"SNMPState",
|
||||
"SNMPTransaction",
|
||||
"SuricataContext",
|
||||
"SuricataFileContext",
|
||||
"TFTPState",
|
||||
"TFTPTransaction"
|
||||
]
|
||||
|
||||
# Types of items that we'll generate. If empty, then all types of item are emitted.
|
||||
#
|
||||
# possible items: (TODO: explain these in detail)
|
||||
# * "constants":
|
||||
# * "globals":
|
||||
# * "enums":
|
||||
# * "structs":
|
||||
# * "unions":
|
||||
# * "typedefs":
|
||||
# * "opaque":
|
||||
# * "functions":
|
||||
#
|
||||
# default: []
|
||||
item_types = ["structs","opaque","functions"]
|
||||
|
||||
# Whether applying rules in export.rename prevents export.prefix from applying.
|
||||
#
|
||||
# e.g. given this toml:
|
||||
#
|
||||
# [export]
|
||||
# prefix = "capi_"
|
||||
[export.rename]
|
||||
"DNSState" = "RSDNSState"
|
||||
"DNSTransaction" = "RSDNSTransaction"
|
||||
"JsonT" = "json_t"
|
||||
"CLuaState" = "lua_State"
|
||||
|
||||
#
|
||||
# You get the following results:
|
||||
#
|
||||
# renaming_overrides_prefixing = true:
|
||||
# "MyType" => "my_cool_type"
|
||||
#
|
||||
# renaming_overrides_prefixing = false:
|
||||
# "MyType => capi_my_cool_type"
|
||||
#
|
||||
# default: false
|
||||
renaming_overrides_prefixing = "true"
|
||||
|
||||
[parse]
|
||||
# A black list of crate names that are not allowed to be parsed.
|
||||
# default: []
|
||||
exclude = ["libc"]
|
||||
|
||||
[parse.expand]
|
||||
# A list of feature names that should be used when running `cargo expand`. This
|
||||
# combines with `default_features` like in your `Cargo.toml`. Note that the features
|
||||
# listed here are features for the current crate being built, *not* the crates
|
||||
# being expanded. The crate's `Cargo.toml` must take care of enabling the
|
||||
# appropriate features in its dependencies
|
||||
#
|
||||
# default: []
|
||||
features = ["cbindgen"]
|
||||
@ -1,240 +0,0 @@
|
||||
#! /usr/bin/env python2
|
||||
|
||||
# This script will scan Rust source files looking for extern "C"
|
||||
# functions and generate C header files from them with a filename
|
||||
# based on the Rust filename.
|
||||
#
|
||||
# Usage: From the top suricata source directory:
|
||||
#
|
||||
# ./rust/gen-c-headers.py
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
from io import StringIO
|
||||
|
||||
template = """/* Copyright (C) 2017 Open Information Security Foundation
|
||||
*
|
||||
* You can copy, redistribute or modify this Program under the terms of
|
||||
* the GNU General Public License version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DO NOT EDIT. This file is automatically generated.
|
||||
*/
|
||||
|
||||
#ifndef __%(name)s__
|
||||
#define __%(name)s__
|
||||
|
||||
%(prototypes)s
|
||||
#endif /* ! __%(name)s__ */
|
||||
"""
|
||||
|
||||
# Map of Rust types to C types.
|
||||
type_map = {
|
||||
"bool": "bool",
|
||||
"i8": "int8_t",
|
||||
"i16" :"int16_t",
|
||||
"i32" :"int32_t",
|
||||
"i64" :"int64_t",
|
||||
|
||||
"u8": "uint8_t",
|
||||
"u16" :"uint16_t",
|
||||
"u32" :"uint32_t",
|
||||
"u64" :"uint64_t",
|
||||
|
||||
"std::os::raw::c_void": "void",
|
||||
"c_void": "void",
|
||||
|
||||
"std::os::raw::c_char": "char",
|
||||
"c_char": "char",
|
||||
"std::os::raw::c_int": "int",
|
||||
"c_int": "int",
|
||||
"std::os::raw::int8_t": "int8_t",
|
||||
"std::os::raw::int32_t": "int32_t",
|
||||
|
||||
"std::os::raw::uint8_t": "uint8_t",
|
||||
"std::os::raw::uint16_t": "uint16_t",
|
||||
"std::os::raw::uint32_t": "uint32_t",
|
||||
"std::os::raw::uint64_t": "uint64_t",
|
||||
|
||||
"SuricataContext": "SuricataContext",
|
||||
"SuricataFileContext": "SuricataFileContext",
|
||||
"FileContainer": "FileContainer",
|
||||
"core::Flow": "Flow",
|
||||
"Flow": "Flow",
|
||||
"DNSState": "RSDNSState",
|
||||
"DNSTransaction": "RSDNSTransaction",
|
||||
"NFSState": "NFSState",
|
||||
"NFSTransaction": "NFSTransaction",
|
||||
"NTPState": "NTPState",
|
||||
"NTPTransaction": "NTPTransaction",
|
||||
"TFTPTransaction": "TFTPTransaction",
|
||||
"TFTPState": "TFTPState",
|
||||
"SMBState": "SMBState",
|
||||
"SMBTransaction": "SMBTransaction",
|
||||
"SNMPState": "SNMPState",
|
||||
"SNMPTransaction": "SNMPTransaction",
|
||||
"IKEV2State": "IKEV2State",
|
||||
"IKEV2Transaction": "IKEV2Transaction",
|
||||
"KRB5State": "KRB5State",
|
||||
"KRB5Transaction": "KRB5Transaction",
|
||||
"SIPState": "SIPState",
|
||||
"SIPTransaction": "SIPTransaction",
|
||||
"JsonT": "json_t",
|
||||
"DetectEngineState": "DetectEngineState",
|
||||
"core::DetectEngineState": "DetectEngineState",
|
||||
"core::AppLayerDecoderEvents": "AppLayerDecoderEvents",
|
||||
"AppLayerDecoderEvents": "AppLayerDecoderEvents",
|
||||
"core::AppLayerEventType": "AppLayerEventType",
|
||||
"applayer::AppLayerGetTxIterTuple": "AppLayerGetTxIterTuple",
|
||||
"AppLayerGetTxIterTuple": "AppLayerGetTxIterTuple",
|
||||
"AppLayerEventType": "AppLayerEventType",
|
||||
"CLuaState": "lua_State",
|
||||
"Store": "Store",
|
||||
"AppProto": "AppProto",
|
||||
"DetectDnsOpcode": "void *",
|
||||
}
|
||||
|
||||
def convert_type(rs_type):
|
||||
m = re.match("^[^\s]+$", rs_type)
|
||||
if m:
|
||||
if rs_type in type_map:
|
||||
return type_map[rs_type]
|
||||
|
||||
m = re.match("^(.*)(\s[^\s]+)$", rs_type)
|
||||
if m:
|
||||
mod = m.group(1).strip()
|
||||
rtype = m.group(2).strip()
|
||||
if rtype in type_map:
|
||||
if mod in [
|
||||
"*mut",
|
||||
"* mut",
|
||||
"&mut",
|
||||
"&'static mut",
|
||||
]:
|
||||
return "%s *" % (type_map[rtype])
|
||||
elif mod in [
|
||||
"*const",
|
||||
"* const"]:
|
||||
return "const %s *" % (type_map[rtype])
|
||||
elif mod in [
|
||||
"*mut *const",
|
||||
"*mut*const"]:
|
||||
return "const %s **" % (type_map[rtype])
|
||||
else:
|
||||
raise Exception("Unknown modifier '%s' in '%s'." % (
|
||||
mod, rs_type))
|
||||
else:
|
||||
raise Exception("Unknown type: %s" % (rtype))
|
||||
|
||||
raise Exception("Failed to parse Rust type: %s" % (rs_type))
|
||||
|
||||
def make_output_filename(filename):
|
||||
if filename.startswith("./"):
|
||||
filename = filename[2:]
|
||||
parts = filename.split(os.path.sep)[1:]
|
||||
last = os.path.splitext(parts.pop())[0]
|
||||
outpath = "./gen/c-headers/rust-%s-%s-gen.h" % (
|
||||
"-".join(parts), last)
|
||||
return outpath.replace("--", "-")
|
||||
|
||||
def write_header(fileobj, filename):
|
||||
filename = os.path.basename(filename).replace(
|
||||
"-", "_").replace(".", "_").upper()
|
||||
fileobj.write(file_header % {"name": filename})
|
||||
|
||||
def should_regen(input_filename, output_filename):
|
||||
"""Check if a file should be regenerated. If the output doesn't exist,
|
||||
or the input is newer than the output return True. Otherwise
|
||||
return False.
|
||||
|
||||
"""
|
||||
if not os.path.exists(output_filename):
|
||||
return True
|
||||
if os.stat(input_filename).st_mtime > os.stat(output_filename).st_mtime:
|
||||
return True
|
||||
return False
|
||||
|
||||
def gen_headers(filename):
|
||||
|
||||
output_filename = make_output_filename(filename)
|
||||
|
||||
if not should_regen(filename, output_filename):
|
||||
return
|
||||
|
||||
buf = open(filename, "rb").read().decode("utf-8")
|
||||
writer = StringIO()
|
||||
|
||||
for fn in re.findall(
|
||||
r"^pub (unsafe )?extern \"C\" fn ([A_Za-z0-9_]+)\(([^{]+)?\)"
|
||||
r"(\s+-> ([^{]+))?",
|
||||
buf,
|
||||
re.M | re.DOTALL):
|
||||
|
||||
args = []
|
||||
|
||||
fnName = fn[1]
|
||||
|
||||
for arg in fn[2].split(","):
|
||||
if not arg.strip():
|
||||
continue
|
||||
arg_name, rs_type = arg.split(":", 1)
|
||||
arg_name = arg_name.strip()
|
||||
rs_type = rs_type.strip()
|
||||
c_type = convert_type(rs_type)
|
||||
|
||||
if arg_name != "_":
|
||||
args.append("%s %s" % (c_type, arg_name))
|
||||
else:
|
||||
args.append(c_type)
|
||||
|
||||
if not args:
|
||||
args.append("void")
|
||||
|
||||
retType = fn[4].strip()
|
||||
if retType == "":
|
||||
returns = "void"
|
||||
else:
|
||||
returns = convert_type(retType)
|
||||
|
||||
writer.write(u"%s %s(%s);\n" % (returns, fnName, ", ".join(args)))
|
||||
|
||||
if writer.tell() > 0:
|
||||
print("Writing %s" % (output_filename))
|
||||
if not os.path.exists(os.path.dirname(output_filename)):
|
||||
os.makedirs(os.path.dirname(output_filename))
|
||||
with open(output_filename, "w") as output:
|
||||
output.write(template % {
|
||||
"prototypes": writer.getvalue(),
|
||||
"name": os.path.basename(output_filename).replace(
|
||||
"-", "_").replace(".", "_").upper()
|
||||
})
|
||||
|
||||
def main():
|
||||
|
||||
rust_top = os.path.dirname(sys.argv[0])
|
||||
os.chdir(rust_top)
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk("./src"):
|
||||
for filename in filenames:
|
||||
if filename.endswith(".rs"):
|
||||
path = os.path.join(dirpath, filename)
|
||||
gen_headers(path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@ -0,0 +1,62 @@
|
||||
/* Copyright (C) 2017 Open Information Security Foundation
|
||||
*
|
||||
* You can copy, redistribute or modify this Program under the terms of
|
||||
* the GNU General Public License version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __RUST_CONTEXT_H__
|
||||
#define __RUST_CONTEXT_H__
|
||||
|
||||
#include "detect-engine-state.h" //DetectEngineState
|
||||
#include "app-layer-krb5.h" //KRB5State, KRB5Transaction
|
||||
#include "app-layer-ikev2.h" //IKEV2State, IKEV2Transaction
|
||||
#include "app-layer-ntp.h" //NTPState, NTPTransaction
|
||||
#include "app-layer-snmp.h" //SNMPState, SNMPTransaction
|
||||
#include "app-layer-tftp.h" //TFTPState, TFTPTransaction
|
||||
|
||||
typedef struct SuricataContext_ {
|
||||
SCError (*SCLogMessage)(const SCLogLevel, const char *, const unsigned int,
|
||||
const char *, const SCError, const char *message);
|
||||
void (*DetectEngineStateFree)(DetectEngineState *);
|
||||
void (*AppLayerDecoderEventsSetEventRaw)(AppLayerDecoderEvents **,
|
||||
uint8_t);
|
||||
void (*AppLayerDecoderEventsFreeEvents)(AppLayerDecoderEvents **);
|
||||
|
||||
int (*FileOpenFileWithId)(FileContainer *, const StreamingBufferConfig *,
|
||||
uint32_t track_id, const uint8_t *name, uint16_t name_len,
|
||||
const uint8_t *data, uint32_t data_len, uint16_t flags);
|
||||
int (*FileCloseFileById)(FileContainer *, uint32_t track_id,
|
||||
const uint8_t *data, uint32_t data_len, uint16_t flags);
|
||||
int (*FileAppendDataById)(FileContainer *, uint32_t track_id,
|
||||
const uint8_t *data, uint32_t data_len);
|
||||
int (*FileAppendGAPById)(FileContainer *, uint32_t track_id,
|
||||
const uint8_t *data, uint32_t data_len);
|
||||
void (*FileContainerRecycle)(FileContainer *ffc);
|
||||
void (*FilePrune)(FileContainer *ffc);
|
||||
void (*FileSetTx)(FileContainer *, uint64_t);
|
||||
|
||||
} SuricataContext;
|
||||
|
||||
typedef struct SuricataFileContext_ {
|
||||
|
||||
const StreamingBufferConfig *sbcfg;
|
||||
|
||||
} SuricataFileContext;
|
||||
|
||||
struct _Store;
|
||||
typedef struct _Store Store;
|
||||
|
||||
/** Opaque Rust types. */
|
||||
|
||||
#endif /* !__RUST_CONTEXT_H__ */
|
||||
Loading…
Reference in New Issue