]> git.proxmox.com Git - mirror_qemu.git/blame - net/dump.c
net: convert socket to NetClientInfo
[mirror_qemu.git] / net / dump.c
CommitLineData
1abecf77
MM
1/*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include "dump.h"
26#include "qemu-common.h"
27#include "sysemu.h"
28#include "qemu-log.h"
29
30typedef struct DumpState {
31 VLANClientState *pcap_vc;
32 int fd;
33 int pcap_caplen;
34} DumpState;
35
36#define PCAP_MAGIC 0xa1b2c3d4
37
38struct pcap_file_hdr {
39 uint32_t magic;
40 uint16_t version_major;
41 uint16_t version_minor;
42 int32_t thiszone;
43 uint32_t sigfigs;
44 uint32_t snaplen;
45 uint32_t linktype;
46};
47
48struct pcap_sf_pkthdr {
49 struct {
50 int32_t tv_sec;
51 int32_t tv_usec;
52 } ts;
53 uint32_t caplen;
54 uint32_t len;
55};
56
57static ssize_t dump_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
58{
59 DumpState *s = vc->opaque;
60 struct pcap_sf_pkthdr hdr;
61 int64_t ts;
62 int caplen;
63
64 /* Early return in case of previous error. */
65 if (s->fd < 0) {
66 return size;
67 }
68
69 ts = muldiv64(qemu_get_clock(vm_clock), 1000000, get_ticks_per_sec());
70 caplen = size > s->pcap_caplen ? s->pcap_caplen : size;
71
72 hdr.ts.tv_sec = ts / 1000000;
73 hdr.ts.tv_usec = ts % 1000000;
74 hdr.caplen = caplen;
75 hdr.len = size;
76 if (write(s->fd, &hdr, sizeof(hdr)) != sizeof(hdr) ||
77 write(s->fd, buf, caplen) != caplen) {
78 qemu_log("-net dump write error - stop dump\n");
79 close(s->fd);
80 s->fd = -1;
81 }
82
83 return size;
84}
85
86static void net_dump_cleanup(VLANClientState *vc)
87{
88 DumpState *s = vc->opaque;
89
90 close(s->fd);
91 qemu_free(s);
92}
93
94static int net_dump_init(VLANState *vlan, const char *device,
95 const char *name, const char *filename, int len)
96{
97 struct pcap_file_hdr hdr;
98 DumpState *s;
99
100 s = qemu_malloc(sizeof(DumpState));
101
102 s->fd = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644);
103 if (s->fd < 0) {
104 qemu_error("-net dump: can't open %s\n", filename);
105 return -1;
106 }
107
108 s->pcap_caplen = len;
109
110 hdr.magic = PCAP_MAGIC;
111 hdr.version_major = 2;
112 hdr.version_minor = 4;
113 hdr.thiszone = 0;
114 hdr.sigfigs = 0;
115 hdr.snaplen = s->pcap_caplen;
116 hdr.linktype = 1;
117
118 if (write(s->fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
119 qemu_error("-net dump write error: %s\n", strerror(errno));
120 close(s->fd);
121 qemu_free(s);
122 return -1;
123 }
124
125 s->pcap_vc = qemu_new_vlan_client(NET_CLIENT_TYPE_DUMP,
126 vlan, NULL, device, name, NULL,
127 dump_receive, NULL, NULL,
128 net_dump_cleanup, s);
129 snprintf(s->pcap_vc->info_str, sizeof(s->pcap_vc->info_str),
130 "dump to %s (len=%d)", filename, len);
131 return 0;
132}
133
134int net_init_dump(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
135{
136 int len;
137 const char *file;
138 char def_file[128];
139
140 assert(vlan);
141
142 file = qemu_opt_get(opts, "file");
143 if (!file) {
144 snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", vlan->id);
145 file = def_file;
146 }
147
148 len = qemu_opt_get_size(opts, "len", 65536);
149
150 return net_dump_init(vlan, "dump", name, file, len);
151}