VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/Pcap.cpp

Last change on this file was 106061, checked in by vboxsync, 7 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
Line 
1/* $Id: Pcap.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Helpers for writing libpcap files.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include "Pcap.h"
33
34#include <iprt/file.h>
35#include <iprt/stream.h>
36#include <iprt/time.h>
37#include <iprt/errcore.h>
38#include <VBox/vmm/pdmnetinline.h>
39
40
41/*********************************************************************************************************************************
42* Structures and Typedefs *
43*********************************************************************************************************************************/
44
45/* "libpcap" magic */
46#define PCAP_MAGIC 0xa1b2c3d4
47
48/* "libpcap" file header (minus magic number). */
49struct pcap_hdr
50{
51 uint16_t version_major; /* major version number = 2 */
52 uint16_t version_minor; /* minor version number = 4 */
53 int32_t thiszone; /* GMT to local correction = 0 */
54 uint32_t sigfigs; /* accuracy of timestamps = 0 */
55 uint32_t snaplen; /* max length of captured packets, in octets = 0xffff */
56 uint32_t network; /* data link type = 01 */
57};
58
59/* "libpcap" record header. */
60struct pcaprec_hdr
61{
62 uint32_t ts_sec; /* timestamp seconds */
63 uint32_t ts_usec; /* timestamp microseconds */
64 uint32_t incl_len; /* number of octets of packet saved in file */
65 uint32_t orig_len; /* actual length of packet */
66};
67
68struct pcaprec_hdr_init
69{
70 uint32_t u32Magic;
71 struct pcap_hdr pcap;
72};
73
74
75/*********************************************************************************************************************************
76* Global Variables *
77*********************************************************************************************************************************/
78static pcaprec_hdr_init const s_Hdr =
79{
80 PCAP_MAGIC,
81 { 2, 4, 0, 0, 0xffff, 1 },
82};
83
84static const char s_szDummyData[] = { 0, 0, 0, 0 };
85
86/**
87 * Internal helper.
88 */
89static void pcapCalcHeader(struct pcaprec_hdr *pHdr, uint64_t StartNanoTS, size_t cbFrame, size_t cbMax)
90{
91 uint64_t u64TS = RTTimeNanoTS() - StartNanoTS;
92 pHdr->ts_sec = (uint32_t)(u64TS / 1000000000);
93 pHdr->ts_usec = (uint32_t)((u64TS / 1000) % 1000000);
94 pHdr->incl_len = (uint32_t)RT_MIN(cbFrame, cbMax);
95 pHdr->orig_len = (uint32_t)cbFrame;
96}
97
98
99/**
100 * Internal helper.
101 */
102static void pcapUpdateHeader(struct pcaprec_hdr *pHdr, size_t cbFrame, size_t cbMax)
103{
104 pHdr->incl_len = (uint32_t)RT_MIN(cbFrame, cbMax);
105 pHdr->orig_len = (uint32_t)cbFrame;
106}
107
108
109/**
110 * Writes the stream header.
111 *
112 * @returns IPRT status code, @see RTStrmWrite.
113 *
114 * @param pStream The stream handle.
115 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
116 */
117int PcapStreamHdr(PRTSTREAM pStream, uint64_t StartNanoTS)
118{
119 int rc1 = RTStrmWrite(pStream, &s_Hdr, sizeof(s_Hdr));
120 int rc2 = PcapStreamFrame(pStream, StartNanoTS, s_szDummyData, 60, sizeof(s_szDummyData));
121 return RT_SUCCESS(rc1) ? rc2 : rc1;
122}
123
124
125/**
126 * Writes a frame to a stream.
127 *
128 * @returns IPRT status code, @see RTStrmWrite.
129 *
130 * @param pStream The stream handle.
131 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
132 * @param pvFrame The start of the frame.
133 * @param cbFrame The size of the frame.
134 * @param cbMax The max number of bytes to include in the file.
135 */
136int PcapStreamFrame(PRTSTREAM pStream, uint64_t StartNanoTS, const void *pvFrame, size_t cbFrame, size_t cbMax)
137{
138 struct pcaprec_hdr Hdr;
139 pcapCalcHeader(&Hdr, StartNanoTS, cbFrame, cbMax);
140 int rc1 = RTStrmWrite(pStream, &Hdr, sizeof(Hdr));
141 int rc2 = RTStrmWrite(pStream, pvFrame, Hdr.incl_len);
142 return RT_SUCCESS(rc1) ? rc2 : rc1;
143}
144
145
146/**
147 * Writes a GSO frame to a stream.
148 *
149 * @returns IPRT status code, @see RTStrmWrite.
150 *
151 * @param pStream The stream handle.
152 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
153 * @param pGso Pointer to the GSO context.
154 * @param pvFrame The start of the GSO frame.
155 * @param cbFrame The size of the GSO frame.
156 * @param cbSegMax The max number of bytes to include in the file for
157 * each segment.
158 */
159int PcapStreamGsoFrame(PRTSTREAM pStream, uint64_t StartNanoTS, PCPDMNETWORKGSO pGso,
160 const void *pvFrame, size_t cbFrame, size_t cbSegMax)
161{
162 struct pcaprec_hdr Hdr;
163 pcapCalcHeader(&Hdr, StartNanoTS, 0, 0);
164
165 uint8_t const *pbFrame = (uint8_t const *)pvFrame;
166 uint8_t abHdrs[256];
167 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame);
168 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
169 {
170 uint32_t cbSegPayload, cbHdrs;
171 uint32_t offSegPayload = PDMNetGsoCarveSegment(pGso, pbFrame, cbFrame, iSeg, cSegs, abHdrs, &cbHdrs, &cbSegPayload);
172
173 pcapUpdateHeader(&Hdr, cbHdrs + cbSegPayload, cbSegMax);
174 int rc = RTStrmWrite(pStream, &Hdr, sizeof(Hdr));
175 if (RT_FAILURE(rc))
176 return rc;
177
178 rc = RTStrmWrite(pStream, abHdrs, RT_MIN(Hdr.incl_len, cbHdrs));
179 if (RT_SUCCESS(rc) && Hdr.incl_len > cbHdrs)
180 rc = RTStrmWrite(pStream, pbFrame + offSegPayload, Hdr.incl_len - cbHdrs);
181 if (RT_FAILURE(rc))
182 return rc;
183 }
184
185 return VINF_SUCCESS;
186}
187
188
189/**
190 * Writes the file header.
191 *
192 * @returns IPRT status code, @see RTFileWrite.
193 *
194 * @param File The file handle.
195 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
196 */
197int PcapFileHdr(RTFILE File, uint64_t StartNanoTS)
198{
199 int rc1 = RTFileWrite(File, &s_Hdr, sizeof(s_Hdr), NULL);
200 int rc2 = PcapFileFrame(File, StartNanoTS, s_szDummyData, 60, sizeof(s_szDummyData));
201 return RT_SUCCESS(rc1) ? rc2 : rc1;
202}
203
204
205/**
206 * Writes a frame to a file.
207 *
208 * @returns IPRT status code, @see RTFileWrite.
209 *
210 * @param File The file handle.
211 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
212 * @param pvFrame The start of the frame.
213 * @param cbFrame The size of the frame.
214 * @param cbMax The max number of bytes to include in the file.
215 */
216int PcapFileFrame(RTFILE File, uint64_t StartNanoTS, const void *pvFrame, size_t cbFrame, size_t cbMax)
217{
218 struct pcaprec_hdr Hdr;
219 pcapCalcHeader(&Hdr, StartNanoTS, cbFrame, cbMax);
220 int rc1 = RTFileWrite(File, &Hdr, sizeof(Hdr), NULL);
221 int rc2 = RTFileWrite(File, pvFrame, Hdr.incl_len, NULL);
222 return RT_SUCCESS(rc1) ? rc2 : rc1;
223}
224
225
226/**
227 * Writes a GSO frame to a file.
228 *
229 * @returns IPRT status code, @see RTFileWrite.
230 *
231 * @param File The file handle.
232 * @param StartNanoTS What to subtract from the RTTimeNanoTS output.
233 * @param pGso Pointer to the GSO context.
234 * @param pvFrame The start of the GSO frame.
235 * @param cbFrame The size of the GSO frame.
236 * @param cbSegMax The max number of bytes to include in the file for
237 * each segment.
238 */
239int PcapFileGsoFrame(RTFILE File, uint64_t StartNanoTS, PCPDMNETWORKGSO pGso,
240 const void *pvFrame, size_t cbFrame, size_t cbSegMax)
241{
242 struct pcaprec_hdr Hdr;
243 pcapCalcHeader(&Hdr, StartNanoTS, 0, 0);
244
245 uint8_t const *pbFrame = (uint8_t const *)pvFrame;
246 uint8_t abHdrs[256];
247 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame);
248 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
249 {
250 uint32_t cbSegPayload, cbHdrs;
251 uint32_t offSegPayload = PDMNetGsoCarveSegment(pGso, pbFrame, cbFrame, iSeg, cSegs, abHdrs, &cbHdrs, &cbSegPayload);
252
253 pcapUpdateHeader(&Hdr, cbHdrs + cbSegPayload, cbSegMax);
254 int rc = RTFileWrite(File, &Hdr, sizeof(Hdr), NULL);
255 if (RT_FAILURE(rc))
256 return rc;
257
258 rc = RTFileWrite(File, abHdrs, RT_MIN(Hdr.incl_len, cbHdrs), NULL);
259 if (RT_SUCCESS(rc) && Hdr.incl_len > cbHdrs)
260 rc = RTFileWrite(File, pbFrame + offSegPayload, Hdr.incl_len - cbHdrs, NULL);
261 if (RT_FAILURE(rc))
262 return rc;
263 }
264
265 return VINF_SUCCESS;
266}
267
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette