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