1#!/usr/bin/env python3 2# 3# Copyright 2019, Dario Lombardo <lomato@gmail.com> 4# 5# Wireshark - Network traffic analyzer 6# By Gerald Combs <gerald@wireshark.org> 7# Copyright 1998 Gerald Combs 8# 9# SPDX-License-Identifier: GPL-2.0-or-later 10# 11# This script generates a Wireshark skeleton dissector, based on the example in the doc/ directory. 12# 13# Example usage: 14# 15# generate-dissector.py --name "My Self" --email "myself@example.com" --protoname "The dumb protocol" 16# --protoshortname DUMB --protoabbrev dumb --license GPL-2.0-or-later --years "2019-2020" 17# 18 19import argparse 20from datetime import datetime 21import os 22 23 24parser = argparse.ArgumentParser(description='The Wireshark Dissector Generator') 25parser.add_argument("--name", help="The author of the dissector", required=True) 26parser.add_argument("--email", help="The email address of the author", required=True) 27parser.add_argument("--protoname", help="The name of the protocol", required=True) 28parser.add_argument("--protoshortname", help="The protocol short name", required=True) 29parser.add_argument("--protoabbrev", help="The protocol abbreviation", required=True) 30parser.add_argument("--license", help="The license for this dissector (please use a SPDX-License-Identifier). If omitted, GPL-2.0-or-later will be used") 31parser.add_argument("--years", help="Years of validity for the license. If omitted, the current year will be used") 32parser.add_argument("-f", "--force", action='store_true', help="Force overwriting the dissector file if it already exists") 33 34 35def wsdir(): 36 return os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) 37 38 39def output_file(args): 40 return os.path.join(wsdir(), "epan/dissectors/packet-" + args.protoabbrev + ".c") 41 42 43def read_skeleton(): 44 skeletonfile = os.path.join(wsdir(), "doc/packet-PROTOABBREV.c") 45 print("Reading skeleton file: " + skeletonfile) 46 return open(skeletonfile).read() 47 48 49def replace_fields(buffer, args): 50 print("Replacing fields in skeleton") 51 output = buffer\ 52 .replace("YOUR_NAME", args.name)\ 53 .replace("YOUR_EMAIL_ADDRESS", args.email)\ 54 .replace("PROTONAME", args.protoname)\ 55 .replace("PROTOSHORTNAME", args.protoshortname)\ 56 .replace("PROTOABBREV", args.protoabbrev)\ 57 .replace("FIELDNAME", "Sample Field")\ 58 .replace("FIELDABBREV", "sample_field")\ 59 .replace("FT_FIELDTYPE", "FT_STRING")\ 60 .replace("FIELDDISPLAY", "BASE_NONE")\ 61 .replace("FIELDCONVERT", "NULL")\ 62 .replace("BITMASK", "0x0")\ 63 .replace("FIELDDESCR", "NULL")\ 64 .replace("MAX_NEEDED_FOR_HEURISTICS", "1")\ 65 .replace("TEST_HEURISTICS_FAIL", "0")\ 66 .replace("ENC_xxx", "ENC_NA")\ 67 .replace("EXPERTABBREV", "expert")\ 68 .replace("PI_GROUP", "PI_PROTOCOL")\ 69 .replace("PI_SEVERITY", "PI_ERROR")\ 70 .replace("TEST_EXPERT_condition", "0")\ 71 .replace("const char *subtree", "\"\"") 72 73 if args.license: 74 output = output.replace("LICENSE", args.license) 75 else: 76 output = output.replace("LICENSE", "GPL-2.0-or-later") 77 78 if args.years: 79 output = output.replace("YEARS", args.years) 80 else: 81 output = output.replace("YEARS", str(datetime.now().year)) 82 83 return output 84 85 86def write_dissector(buffer, args): 87 ofile = output_file(args) 88 if os.path.isfile(ofile) and not args.force: 89 raise Exception("The file " + ofile + " already exists. You're likely overwriting an existing dissector.") 90 print("Writing output file: " + ofile) 91 return open(ofile, "w").write(buffer) 92 93 94def patch_makefile(args): 95 cmakefile = os.path.join(wsdir(), "epan/dissectors/CMakeLists.txt") 96 print("Patching makefile: " + cmakefile) 97 output = "" 98 patchline = "${CMAKE_CURRENT_SOURCE_DIR}/packet-" + args.protoabbrev + ".c" 99 in_group = False 100 patched = False 101 for line in open(cmakefile): 102 line_strip = line.strip() 103 if in_group and line_strip == ")": 104 in_group = False 105 if in_group and not patched and line_strip > patchline: 106 output += "\t" + patchline + "\n" 107 patched = True 108 if line_strip == "set(DISSECTOR_SRC": 109 in_group = True 110 if line_strip != patchline: 111 output += line 112 open(cmakefile, "w").write(output) 113 114 115def print_header(): 116 print("") 117 print("**************************************************") 118 print("* Wireshark skeleton dissector generator *") 119 print("* *") 120 print("* Generate a new dissector for your protocol *") 121 print("* starting from the skeleton provided in the *") 122 print("* doc directory. *") 123 print("* *") 124 print("* Copyright 2019 Dario Lombardo *") 125 print("**************************************************") 126 print("") 127 128 129def print_trailer(args): 130 print("") 131 print("The skeleton for the dissector of the " + args.protoshortname + " protocol has been generated.") 132 print("Please review/extend it to match your specific criterias.") 133 print("") 134 135 136if __name__ == '__main__': 137 print_header() 138 args = parser.parse_args() 139 buffer = replace_fields(read_skeleton(), args) 140 write_dissector(buffer, args) 141 patch_makefile(args) 142 print_trailer(args) 143