VirtualBox

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

Last change on this file since 37198 was 35346, checked in by vboxsync, 14 years ago

VMM reorg: Moving the public include files from include/VBox to include/VBox/vmm.

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