From e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 22:34:10 +0200 Subject: Adding upstream version 4.2.2. Signed-off-by: Daniel Baumann --- tools/make-enterprises.py | 196 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100755 tools/make-enterprises.py (limited to 'tools/make-enterprises.py') diff --git a/tools/make-enterprises.py b/tools/make-enterprises.py new file mode 100755 index 00000000..1b2b2d0d --- /dev/null +++ b/tools/make-enterprises.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +# create the enterprises.c file from +# https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers +# or an offline copy +# +# Copyright 2022 by Moshe Kaplan +# Based on make-sminmpec.pl by Gerald Combs +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 2004 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import argparse +import re +import urllib.request + + +ENTERPRISES_CFILE = os.path.join('epan', 'enterprises.c') + +ENTERPRISE_NUMBERS_URL = "https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers" + +DECIMAL_PATTERN = r"^(\d+)" +# up to three spaces because of formatting errors in the source +ORGANIZATION_PATTERN = r"^ ?(\S.*)" +FORMERLY_PATTERN = r" \(((formerly|previously) .*)\)" + + +LOOKUP_FUNCTION = r""" +const char* global_enterprises_lookup(uint32_t value) +{ + if (value > table.max_idx) { + return NULL; + } + else return table.values[value]; +} +""" + +DUMP_FUNCTION = r""" +void global_enterprises_dump(FILE *fp) +{ + for (size_t idx = 0; idx <= table.max_idx; idx++) { + if (table.values[idx] != NULL) { + fprintf(fp, "%zu\t%s\n", idx, table.values[idx]); + } + } +} +""" + +# This intermediate format is no longer written to a file - returned as string +def generate_enterprise_entries(file_content): + # We only care about the "Decimal" and "Organization", + # not the contact or email + org_lines = [] + last_updated = "" + end_seen = False + for line in file_content.splitlines(): + decimal_match = re.match(DECIMAL_PATTERN, line) + if decimal_match: + decimal = decimal_match.group(0) + elif re.match(ORGANIZATION_PATTERN, line): + organization = line.strip() + if organization.lower() == "unassigned": + continue + organization = re.sub(FORMERLY_PATTERN, r"\t# \1", organization) + org_lines += [decimal + "\t" + organization] + elif "last updated" in line.lower(): + last_updated = line + elif "end of document" in line.lower(): + end_seen = True + + if not end_seen: + raise Exception('"End of Document" not found. Truncated source file?') + + last_updated_line = "/* " + last_updated + " */\n\n" + output = "\n".join(org_lines) + "\n" + return (output,last_updated_line) + +class CFile: + def __init__(self, filename, last_updated_line): + self.filename = filename + self.f = open(filename, 'w') + self.mappings = {} + self.highest_num = 0 + + # Write file header + self.f.write('/* ' + os.path.basename(self.filename) + '\n') + self.f.write(' *\n') + self.f.write(' * Wireshark - Network traffic analyzer\n') + self.f.write(' * By Gerald Combs \n') + self.f.write(' * Copyright 1998 Gerald Combs\n') + self.f.write(' *\n') + self.f.write(' * Do not edit - this file is automatically generated\n') + self.f.write(' * SPDX-License-Identifier: GPL-2.0-or-later\n') + self.f.write(' */\n\n') + self.f.write(last_updated_line) + + # Include header files + self.f.write('#include "config.h"\n\n') + self.f.write('#include \n') + self.f.write('#include "enterprises.h"\n') + self.f.write('\n\n') + + def __del__(self): + self.f.write('typedef struct\n') + self.f.write('{\n') + self.f.write(' uint32_t max_idx;\n') + self.f.write(' const char* values[' + str(self.highest_num+1) + '];\n') + self.f.write('} global_enterprises_table_t;\n\n') + + # Write static table + self.f.write('static global_enterprises_table_t table =\n') + self.f.write('{\n') + # Largest index + self.f.write(' ' + str(self.highest_num) + ',\n') + self.f.write(' {\n') + # Entries (read from dict) + for n in range(0, self.highest_num+1): + if n not in self.mappings: + # There are some gaps, write a NULL entry so can lookup by index + line = ' NULL' + else: + line = ' "' + self.mappings[n] + '"' + # Add coma. + if n < self.highest_num: + line += ',' + # Add number as aligned comment. + line += ' '*(90-len(line)) + '// ' + str(n) + + self.f.write(line+'\n') + + # End of array + self.f.write(' }\n') + # End of struct + self.f.write('};\n') + print('Re-generated', self.filename) + + # Lookup function + self.f.write(LOOKUP_FUNCTION) + + # Dump function + self.f.write(DUMP_FUNCTION) + + # Add an individual mapping to the function + def addMapping(self, num, name): + # Handle some escapings + name = name.replace('\\', '\\\\') + name = name.replace('"', '""') + + # Record. + self.mappings[num] = name + self.highest_num = num if num>self.highest_num else self.highest_num + + + +def main(): + parser = argparse.ArgumentParser(description="Create the {} file.".format(ENTERPRISES_CFILE)) + parser.add_argument('--infile') + parser.add_argument('outfile', nargs='?', default=ENTERPRISES_CFILE) + parsed_args = parser.parse_args() + + # Read data from file or webpage + if parsed_args.infile: + with open(parsed_args.infile, encoding='utf-8') as fh: + data = fh.read() + else: + with urllib.request.urlopen(ENTERPRISE_NUMBERS_URL) as f: + if f.status != 200: + raise Exception("request for " + ENTERPRISE_NUMBERS_URL + " failed with result code " + f.status) + data = f.read().decode('utf-8') + + # Find bits we need and generate enterprise entries + enterprises_content,last_updated_line = generate_enterprise_entries(data) + + # Now write to a C file the contents (which is faster than parsing the global file at runtime). + c_file = CFile(parsed_args.outfile, last_updated_line) + + mapping_re = re.compile(r'^(\d+)\s+(.*)$') + for line in enterprises_content.splitlines(): + match = mapping_re.match(line) + if match: + num, name = match.group(1), match.group(2) + # Strip any comments and/or trailing whitespace + idx = name.find('#') + if idx != -1: + name = name[0:idx] + name = name.rstrip() + # Add + c_file.addMapping(int(num), name) + + + +if __name__ == "__main__": + main() -- cgit v1.2.3