LATER... ei_kerberos_kdc_session_key ...
[wireshark-sm.git] / ui / tap_export_pdu.c
blobca52debe7ba7ec90ef83f2b339bcb885731d9d8d
1 /* tap_export_pdu.c
2 * Routines for exporting PDUs to file
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
13 #include <epan/tap.h>
14 #include <epan/exported_pdu.h>
15 #include <epan/epan_dissect.h>
16 #include <wiretap/wtap.h>
17 #include <wiretap/wtap_opttypes.h>
18 #include <wsutil/os_version_info.h>
19 #include <wsutil/report_message.h>
20 #include "wsutil/version_info.h"
22 #include "tap_export_pdu.h"
24 /* Main entry point to the tap */
25 static tap_packet_status
26 export_pdu_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data, tap_flags_t flags _U_)
28 const exp_pdu_data_t *exp_pdu_data = (const exp_pdu_data_t *)data;
29 exp_pdu_t *exp_pdu_tap_data = (exp_pdu_t *)tapdata;
30 wtap_rec rec;
31 int err;
32 char *err_info;
33 int buffer_len;
34 uint8_t *packet_buf;
35 tap_packet_status status = TAP_PACKET_DONT_REDRAW; /* no GUI, nothing to redraw */
38 * Count this packet.
40 exp_pdu_tap_data->framenum++;
42 memset(&rec, 0, sizeof rec);
43 buffer_len = exp_pdu_data->tvb_captured_length + exp_pdu_data->tlv_buffer_len;
44 packet_buf = (uint8_t *)g_malloc(buffer_len);
46 if(exp_pdu_data->tlv_buffer_len > 0){
47 memcpy(packet_buf, exp_pdu_data->tlv_buffer, exp_pdu_data->tlv_buffer_len);
49 if(exp_pdu_data->tvb_captured_length > 0){
50 tvb_memcpy(exp_pdu_data->pdu_tvb, packet_buf+exp_pdu_data->tlv_buffer_len, 0, exp_pdu_data->tvb_captured_length);
52 rec.rec_type = REC_TYPE_PACKET;
53 rec.presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID|WTAP_HAS_TS;
54 rec.ts.secs = pinfo->abs_ts.secs;
55 rec.ts.nsecs = pinfo->abs_ts.nsecs;
56 rec.rec_header.packet_header.caplen = buffer_len;
57 rec.rec_header.packet_header.len = exp_pdu_data->tvb_reported_length + exp_pdu_data->tlv_buffer_len;
59 rec.rec_header.packet_header.pkt_encap = exp_pdu_tap_data->pkt_encap;
61 /* rec.opt_block is not modified by wtap_dump, but if for some reason the
62 * epan_get_modified_block() or pinfo->rec->block are invalidated,
63 * copying it here does not hurt. (Can invalidation really happen?) */
64 if (pinfo->fd->has_modified_block) {
65 rec.block = epan_get_modified_block(edt->session, pinfo->fd);
66 rec.block_was_modified = true;
67 } else {
68 rec.block = pinfo->rec->block;
71 /* XXX: should the rec.rec_header.packet_header.pseudo_header be set to the pinfo's pseudo-header? */
72 if (!wtap_dump(exp_pdu_tap_data->wdh, &rec, packet_buf, &err, &err_info)) {
73 report_cfile_write_failure(NULL, exp_pdu_tap_data->pathname,
74 err, err_info, exp_pdu_tap_data->framenum,
75 wtap_dump_file_type_subtype(exp_pdu_tap_data->wdh));
76 status = TAP_PACKET_FAILED;
79 g_free(packet_buf);
81 return status;
84 bool
85 exp_pdu_open(exp_pdu_t *exp_pdu_tap_data, char *pathname,
86 int file_type_subtype, int fd, const char *comment,
87 int *err, char **err_info)
89 /* pcapng defs */
90 wtap_block_t shb_hdr;
91 wtap_block_t int_data;
92 wtapng_if_descr_mandatory_t *int_data_mand;
93 GString *os_info_str;
94 size_t opt_len;
95 char *opt_str;
98 * If the file format supports a section block, and the section
99 * block supports comments, create data for it.
101 if (wtap_file_type_subtype_supports_block(file_type_subtype,
102 WTAP_BLOCK_SECTION) != BLOCK_NOT_SUPPORTED &&
103 wtap_file_type_subtype_supports_option(file_type_subtype,
104 WTAP_BLOCK_SECTION,
105 OPT_COMMENT) != OPTION_NOT_SUPPORTED) {
106 os_info_str = g_string_new("");
107 get_os_version_info(os_info_str);
109 shb_hdr = wtap_block_create(WTAP_BLOCK_SECTION);
111 /* options */
112 wtap_block_add_string_option(shb_hdr, OPT_COMMENT, comment, strlen(comment));
115 * UTF-8 string containing the name of the operating system used to
116 * create this section.
118 opt_len = os_info_str->len;
119 opt_str = g_string_free(os_info_str, FALSE);
120 if (opt_str) {
121 wtap_block_add_string_option(shb_hdr, OPT_SHB_OS, opt_str, opt_len);
122 g_free(opt_str);
125 * UTF-8 string containing the name of the application used to create
126 * this section.
128 wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "%s",
129 get_appname_and_version());
131 exp_pdu_tap_data->shb_hdrs = g_array_new(false, false, sizeof(wtap_block_t));
132 g_array_append_val(exp_pdu_tap_data->shb_hdrs, shb_hdr);
133 } else {
134 exp_pdu_tap_data->shb_hdrs = NULL;
138 * Create fake interface information for files that support (meaning
139 * "require") interface information and per-packet interface IDs.
141 if (wtap_file_type_subtype_supports_block(file_type_subtype,
142 WTAP_BLOCK_IF_ID_AND_INFO) != BLOCK_NOT_SUPPORTED) {
143 exp_pdu_tap_data->idb_inf = g_new(wtapng_iface_descriptions_t,1);
144 exp_pdu_tap_data->idb_inf->interface_data = g_array_new(false, false, sizeof(wtap_block_t));
146 /* create the fake interface data */
147 int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
148 int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
149 int_data_mand->wtap_encap = exp_pdu_tap_data->pkt_encap;
150 int_data_mand->time_units_per_second = 1000000000; /* default nanosecond resolution */
151 int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD;
153 wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF, PDU->Export", strlen("Fake IF, PDU->Export"));
154 wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 9);
156 g_array_append_val(exp_pdu_tap_data->idb_inf->interface_data, int_data);
157 } else {
158 exp_pdu_tap_data->idb_inf = NULL;
161 const wtap_dump_params params = {
162 .encap = exp_pdu_tap_data->pkt_encap,
163 .snaplen = WTAP_MAX_PACKET_SIZE_STANDARD,
164 .shb_hdrs = exp_pdu_tap_data->shb_hdrs,
165 .idb_inf = exp_pdu_tap_data->idb_inf,
167 if (fd == 1) {
168 exp_pdu_tap_data->wdh = wtap_dump_open_stdout(file_type_subtype,
169 WTAP_UNCOMPRESSED, &params, err, err_info);
170 } else {
171 exp_pdu_tap_data->wdh = wtap_dump_fdopen(fd, file_type_subtype,
172 WTAP_UNCOMPRESSED, &params, err, err_info);
174 if (exp_pdu_tap_data->wdh == NULL)
175 return false;
177 exp_pdu_tap_data->pathname = pathname;
178 exp_pdu_tap_data->framenum = 0; /* No frames written yet */
179 return true;
182 bool
183 exp_pdu_close(exp_pdu_t *exp_pdu_tap_data, int *err, char **err_info)
185 bool status;
187 status = wtap_dump_close(exp_pdu_tap_data->wdh, NULL, err, err_info);
189 wtap_block_array_free(exp_pdu_tap_data->shb_hdrs);
190 wtap_free_idb_info(exp_pdu_tap_data->idb_inf);
192 remove_tap_listener(exp_pdu_tap_data);
193 return status;
197 char *
198 exp_pdu_pre_open(const char *tap_name, const char *filter, exp_pdu_t *exp_pdu_tap_data)
200 GString *error_string;
202 /* Make sure tap is suitable for exported PDUs */
203 bool found = false;
204 for (GSList *export_pdu_tap_name_list = get_export_pdu_tap_list();
205 export_pdu_tap_name_list != NULL;
206 export_pdu_tap_name_list = g_slist_next(export_pdu_tap_name_list)) {
207 if (strcmp((const char*)(export_pdu_tap_name_list->data), tap_name) == 0) {
208 found = true;
209 break;
212 if (!found) {
213 return g_strdup("unsuitable for PDU export");
216 /* Register this tap listener now */
217 error_string = register_tap_listener(tap_name, /* The name of the tap we want to listen to */
218 exp_pdu_tap_data, /* instance identifier/pointer to a struct holding
219 * all state variables */
220 filter, /* pointer to a filter string */
221 TL_REQUIRES_PROTO_TREE, /* flags for the tap listener */
222 NULL,
223 export_pdu_packet,
224 NULL,
225 NULL);
226 if (error_string != NULL)
227 return g_string_free(error_string, FALSE);
229 exp_pdu_tap_data->pkt_encap = export_pdu_tap_get_encap(tap_name);
231 return NULL;