3 Retrieve a packet from a ethereal/tethereal core file
4 and save it in a packet-capture file.
21 re_frame = re.compile(r"^#(?P<num>\d+) ")
22 re_func1 = re.compile(r"^#\d+\s+(?P<func>\w+) \(")
23 re_func2 = re.compile(r"^#\d+\s+0x[A-Fa-f\d]+ in (?P<func>\w+) \(")
25 def __init__(self, lines):
27 # In order; each item is the function name.
29 found_non_bt_frame = 0
33 m = self.re_frame.search(line)
35 # Skip the first frame that gdb shows,
36 # which is not part of the backtrace.
37 if not found_non_bt_frame:
38 found_non_bt_frame = 1
41 # Get the frame number and make sure it's
42 # what we expect it should be.
43 frame_num = int(m.group("num"))
44 if frame_num != frame_will_be:
45 sys.exit("Found frame %d instead of %d" % \
46 (frame_num, frame_will_be))
48 # Find the function name. XXX - need to handle '???'
49 n = self.re_func1.search(line)
51 n = self.re_func2.search(line)
54 func = n.group("func")
56 sys.exit("Function name not found in %s" % (line,))
59 self.frames.append(func)
66 def HasFunction(self, func):
67 return func in self.frames
69 def Frame(self, func):
70 return self.frames.index(func)
73 # Some values from wiretap; wiretap should be a shared
74 # libray and a Python module should be created for it so
75 # this program could just write a libpcap file directly.
76 WTAP_ENCAP_PER_PACKET = -1
77 WTAP_ENCAP_UNKNOWN = 0
78 WTAP_ENCAP_ETHERNET = 1
79 WTAP_ENCAP_TOKEN_RING = 2
83 WTAP_ENCAP_FDDI_BITSWAPPED = 6
86 WTAP_ENCAP_ATM_RFC1483 = 9
87 WTAP_ENCAP_LINUX_ATM_CLIP = 10
89 WTAP_ENCAP_ATM_SNIFFER = 12
91 WTAP_ENCAP_ASCEND = 14
94 WTAP_ENCAP_PPP_WITH_PHDR = 17
95 WTAP_ENCAP_IEEE_802_11 = 18
97 WTAP_ENCAP_FRELAY = 20
99 WTAP_ENCAP_CISCO_IOS = 22
100 WTAP_ENCAP_LOCALTALK = 23
101 WTAP_ENCAP_PRISM_HEADER = 24
102 WTAP_ENCAP_PFLOG = 25
103 WTAP_ENCAP_AIROPEEK = 26
104 WTAP_ENCAP_HHDLC = 27
105 # last WTAP_ENCAP_ value + 1
106 WTAP_NUM_ENCAP_TYPES = 28
110 WTAP_ENCAP_ETHERNET : 1,
111 WTAP_ENCAP_TOKEN_RING : 6,
112 WTAP_ENCAP_ARCNET : 7,
115 WTAP_ENCAP_FDDI_BITSWAPPED : 10,
116 WTAP_ENCAP_FDDI : 10,
117 WTAP_ENCAP_ATM_RFC1483 : 11,
118 WTAP_ENCAP_RAW_IP : 12,
119 WTAP_ENCAP_LINUX_ATM_CLIP : 16, # or 18, or 19...
120 WTAP_ENCAP_CHDLC : 104,
121 WTAP_ENCAP_IEEE_802_11 : 105,
122 WTAP_ENCAP_SLL : 113,
123 WTAP_ENCAP_LOCALTALK : 114,
124 WTAP_ENCAP_PFLOG : 117,
125 WTAP_ENCAP_CISCO_IOS : 118,
126 WTAP_ENCAP_PRISM_HEADER : 119,
127 WTAP_ENCAP_HHDLC : 121,
132 WTAP_ENCAP_UNKNOWN : "Unknown",
133 WTAP_ENCAP_ETHERNET : "Ethernet",
134 WTAP_ENCAP_TOKEN_RING : "Token-Ring",
135 WTAP_ENCAP_SLIP : "SLIP",
136 WTAP_ENCAP_PPP : "PPP",
137 WTAP_ENCAP_FDDI : "FDDI",
138 WTAP_ENCAP_FDDI_BITSWAPPED : "FDDI (Bitswapped)",
139 WTAP_ENCAP_RAW_IP : "Raw IP",
140 WTAP_ENCAP_ARCNET : "ARCNET",
141 WTAP_ENCAP_ATM_RFC1483 : "ATM RFC1483",
142 WTAP_ENCAP_LINUX_ATM_CLIP : "Linux ATM CLIP",
143 WTAP_ENCAP_LAPB : "LAPB",
144 WTAP_ENCAP_ATM_SNIFFER : "ATM Sniffer",
145 WTAP_ENCAP_NULL : "Null",
146 WTAP_ENCAP_ASCEND : "Ascend",
147 WTAP_ENCAP_LAPD : "LAPD",
148 WTAP_ENCAP_V120 : "V.120",
149 WTAP_ENCAP_PPP_WITH_PHDR : "PPP (with PHDR)",
150 WTAP_ENCAP_IEEE_802_11 : "IEEE 802.11",
151 WTAP_ENCAP_SLL : "SLL",
152 WTAP_ENCAP_FRELAY : "Frame Relay",
153 WTAP_ENCAP_CHDLC : "Cisco HDLC",
154 WTAP_ENCAP_CISCO_IOS : "Cisco IOS",
155 WTAP_ENCAP_LOCALTALK : "LocalTalk",
156 WTAP_ENCAP_PRISM_HEADER : "Prism Header",
157 WTAP_ENCAP_PFLOG : "PFLog",
158 WTAP_ENCAP_AIROPEEK : "AiroPeek",
159 WTAP_ENCAP_HHDLC : "HHDLC",
162 def wtap_to_pcap(wtap):
163 if not wtap_to_pcap_map.has_key(wtap):
164 sys.exit("Don't know how to convert wiretap encoding %d to libpcap." % \
167 return wtap_to_pcap_map[wtap]
170 def run_gdb(*commands):
171 if len(commands) == 0:
174 # Create a temporary file
175 fname = tempfile.mktemp()
177 fh = open(fname, "w")
179 sys.exit("Cannot open %s for writing: %s" % (fname, err))
181 # Put the commands in it
194 sys.exit("Cannot close %s: %s" % (fname, err))
198 cmd = "gdb --nw --quiet --command=%s %s %s" % (fname, exec_file, core_file)
200 print "Invoking %s" % (cmd,)
208 sys.exit("Cannot run gdb: %s" % (err,))
211 result = pipe.readlines()
218 sys.exit("gdb returned an exit value of %s" % (error,))
221 # Remove the temp file and return the results
228 def get_value_from_frame(frame_num, variable, fmt=""):
231 cmds.append("up %d" % (frame_num,))
233 cmds.append("print %s %s" % (fmt, variable))
234 lines = apply(run_gdb, cmds)
236 LOOKING_FOR_START = 0
238 state = LOOKING_FOR_START
246 if state == LOOKING_FOR_START:
250 if line[0:4] == "$1 =":
252 state = READING_VALUE
254 elif state == READING_VALUE:
259 def get_int_from_frame(frame_num, variable):
260 text = get_value_from_frame(frame_num, variable)
264 sys.exit("Could not convert '%s' to integer." % (text,))
268 def get_byte_array_from_frame(frame_num, variable, length):
271 cmds.append("up %d" % (frame_num,))
273 cmds.append("print %s" % (variable,))
274 cmds.append("x/%dxb %s" % (length, variable))
275 lines = apply(run_gdb, cmds)
281 LOOKING_FOR_START = 0
283 state = LOOKING_FOR_START
286 if state == LOOKING_FOR_START:
289 elif line[0:3] == "$1 ":
293 fields = line.split('\t')
294 if fields[0][-1] != ":":
295 print "Failed to parse byte array from gdb:"
299 for field in fields[1:]:
307 def make_cap_file(pkt_data, lnk_t):
309 pcap_lnk_t = wtap_to_pcap(lnk_t)
311 # Create a temporary file
312 fname = tempfile.mktemp()
314 fh = open(fname, "w")
316 sys.exit("Cannot open %s for writing: %s" % (fname, err))
320 # Put the hex dump in it
323 for byte in pkt_data:
324 if (offset % BYTES_IN_ROW) == 0:
325 print >> fh, "\n%08X " % (offset,),
326 print "\n%08X " % (offset,),
328 print >> fh, "%02X " % (byte,),
329 print "%02X " % (byte,),
342 sys.exit("Cannot close %s: %s" % (fname, err))
346 cmd = "text2pcap -q -l %s %s %s" % (pcap_lnk_t, fname, output_file)
347 # print "Command is %s" % (cmd,)
349 retval = os.system(cmd)
355 sys.exit("Cannot run text2pcap: %s" % (err,))
357 # Remove the temp file
364 print "%s created with %d bytes in packet, and %s encoding." % \
365 (output_file, len(pkt_data), wtap_name[lnk_t])
367 sys.exit("text2pcap did not run succesfully.")
372 def try_frame(func_text, cap_len_text, lnk_t_text, data_text):
375 bt_text = run_gdb("bt")
376 bt = BackTrace(bt_text)
377 if not bt.HasFunction(func_text):
378 print "%s() not found in backtrace." % (func_text,)
381 print "%s() found in backtrace." % (func_text,)
383 # Figure out where the call to epan_dissect_run is.
384 frame_num = bt.Frame(func_text)
386 # Get the capture length
387 cap_len = get_int_from_frame(frame_num, cap_len_text)
389 # Get the encoding type
390 lnk_t = get_int_from_frame(frame_num, lnk_t_text)
392 # Get the packet data
393 pkt_data = get_byte_array_from_frame(frame_num, data_text, cap_len)
396 print "Length=%d" % (cap_len,)
397 print "Encoding=%d" % (lnk_t,)
398 print "Data (%d bytes) = %s" % (len(pkt_data), pkt_data)
399 make_cap_file(pkt_data, lnk_t)
403 if try_frame("epan_dissect_run",
404 "fd->cap_len", "fd->lnk_t", "data"):
406 elif try_frame("add_packet_to_packet_list",
407 "fdata->cap_len", "fdata->lnk_t", "buf"):
410 sys.exit("A packet cannot be pulled from this core.")
414 print "pkt-from-core.py [-v] -w capture_file executable-file (core-file or process-id)"
416 print "\tGiven an executable file and a core file, this tool"
417 print "\tuses gdb to retrieve the packet that was being dissected"
418 print "\tat the time ethereal/tethereal stopped running. The packet"
419 print "\tis saved in the capture_file specified by the -w option."
421 print "\t-v : verbose"
433 opts, args = getopt.getopt(sys.argv[1:], optstring)
437 for opt, arg in opts:
447 if output_file == None:
458 if __name__ == '__main__':