VirtualBox

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

Last change on this file since 78229 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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