2 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
3 * Copyright (c) 2016 FUJITSU LIMITED
4 * Copyright (c) 2016 Intel Corporation
6 * Author: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
8 * This work is licensed under the terms of the GNU GPL, version 2 or
9 * later. See the COPYING file in the top-level directory.
12 #include "qemu/osdep.h"
13 #include "net/filter.h"
15 #include "qemu-common.h"
16 #include "qapi/error.h"
17 #include "qapi/qmp/qerror.h"
18 #include "qapi-visit.h"
19 #include "qom/object.h"
20 #include "qemu/main-loop.h"
21 #include "qemu/error-report.h"
23 #include "sysemu/char.h"
25 #include "qemu/sockets.h"
27 #define FILTER_MIRROR(obj) \
28 OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_MIRROR)
30 #define FILTER_REDIRECTOR(obj) \
31 OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_REDIRECTOR)
33 #define TYPE_FILTER_MIRROR "filter-mirror"
34 #define TYPE_FILTER_REDIRECTOR "filter-redirector"
35 #define REDIRECTOR_MAX_LEN NET_BUFSIZE
37 typedef struct MirrorState
{
38 NetFilterState parent_obj
;
41 CharDriverState
*chr_in
;
42 CharDriverState
*chr_out
;
43 int state
; /* 0 = getting length, 1 = getting data */
45 unsigned int packet_len
;
46 uint8_t buf
[REDIRECTOR_MAX_LEN
];
49 static int filter_mirror_send(CharDriverState
*chr_out
,
50 const struct iovec
*iov
,
58 size
= iov_size(iov
, iovcnt
);
64 ret
= qemu_chr_fe_write_all(chr_out
, (uint8_t *)&len
, sizeof(len
));
65 if (ret
!= sizeof(len
)) {
70 iov_to_buf(iov
, iovcnt
, 0, buf
, size
);
71 ret
= qemu_chr_fe_write_all(chr_out
, (uint8_t *)buf
, size
);
80 return ret
< 0 ? ret
: -EIO
;
84 redirector_to_filter(NetFilterState
*nf
, const uint8_t *buf
, int len
)
87 .iov_base
= (void *)buf
,
91 if (nf
->direction
== NET_FILTER_DIRECTION_ALL
||
92 nf
->direction
== NET_FILTER_DIRECTION_TX
) {
93 qemu_netfilter_pass_to_next(nf
->netdev
, 0, &iov
, 1, nf
);
96 if (nf
->direction
== NET_FILTER_DIRECTION_ALL
||
97 nf
->direction
== NET_FILTER_DIRECTION_RX
) {
98 qemu_netfilter_pass_to_next(nf
->netdev
->peer
, 0, &iov
, 1, nf
);
102 static int redirector_chr_can_read(void *opaque
)
104 return REDIRECTOR_MAX_LEN
;
107 static void redirector_chr_read(void *opaque
, const uint8_t *buf
, int size
)
109 NetFilterState
*nf
= opaque
;
110 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
114 /* reassemble a packet from the network */
115 switch (s
->state
) { /* 0 = getting length, 1 = getting data */
121 memcpy(s
->buf
+ s
->index
, buf
, l
);
127 s
->packet_len
= ntohl(*(uint32_t *)s
->buf
);
133 l
= s
->packet_len
- s
->index
;
137 if (s
->index
+ l
<= sizeof(s
->buf
)) {
138 memcpy(s
->buf
+ s
->index
, buf
, l
);
140 error_report("serious error: oversized packet received.");
141 s
->index
= s
->state
= 0;
142 qemu_chr_add_handlers(s
->chr_in
, NULL
, NULL
, NULL
, NULL
);
149 if (s
->index
>= s
->packet_len
) {
152 redirector_to_filter(nf
, s
->buf
, s
->packet_len
);
159 static void redirector_chr_event(void *opaque
, int event
)
161 NetFilterState
*nf
= opaque
;
162 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
165 case CHR_EVENT_CLOSED
:
166 qemu_chr_add_handlers(s
->chr_in
, NULL
, NULL
, NULL
, NULL
);
173 static ssize_t
filter_mirror_receive_iov(NetFilterState
*nf
,
174 NetClientState
*sender
,
176 const struct iovec
*iov
,
178 NetPacketSent
*sent_cb
)
180 MirrorState
*s
= FILTER_MIRROR(nf
);
183 ret
= filter_mirror_send(s
->chr_out
, iov
, iovcnt
);
185 error_report("filter_mirror_send failed(%s)", strerror(-ret
));
189 * we don't hope this error interrupt the normal
190 * path of net packet, so we always return zero.
195 static ssize_t
filter_redirector_receive_iov(NetFilterState
*nf
,
196 NetClientState
*sender
,
198 const struct iovec
*iov
,
200 NetPacketSent
*sent_cb
)
202 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
206 ret
= filter_mirror_send(s
->chr_out
, iov
, iovcnt
);
208 error_report("filter_mirror_send failed(%s)", strerror(-ret
));
210 return iov_size(iov
, iovcnt
);
216 static void filter_mirror_cleanup(NetFilterState
*nf
)
218 MirrorState
*s
= FILTER_MIRROR(nf
);
221 qemu_chr_fe_release(s
->chr_out
);
225 static void filter_redirector_cleanup(NetFilterState
*nf
)
227 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
230 qemu_chr_add_handlers(s
->chr_in
, NULL
, NULL
, NULL
, NULL
);
231 qemu_chr_fe_release(s
->chr_in
);
234 qemu_chr_fe_release(s
->chr_out
);
238 static void filter_mirror_setup(NetFilterState
*nf
, Error
**errp
)
240 MirrorState
*s
= FILTER_MIRROR(nf
);
243 error_setg(errp
, "filter filter mirror needs 'outdev' "
248 s
->chr_out
= qemu_chr_find(s
->outdev
);
249 if (s
->chr_out
== NULL
) {
250 error_set(errp
, ERROR_CLASS_DEVICE_NOT_FOUND
,
251 "Device '%s' not found", s
->outdev
);
255 if (qemu_chr_fe_claim(s
->chr_out
) != 0) {
256 error_setg(errp
, QERR_DEVICE_IN_USE
, s
->outdev
);
261 static void filter_redirector_setup(NetFilterState
*nf
, Error
**errp
)
263 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
265 if (!s
->indev
&& !s
->outdev
) {
266 error_setg(errp
, "filter redirector needs 'indev' or "
267 "'outdev' at least one property set");
269 } else if (s
->indev
&& s
->outdev
) {
270 if (!strcmp(s
->indev
, s
->outdev
)) {
271 error_setg(errp
, "'indev' and 'outdev' could not be same "
272 "for filter redirector");
277 s
->state
= s
->index
= 0;
280 s
->chr_in
= qemu_chr_find(s
->indev
);
281 if (s
->chr_in
== NULL
) {
282 error_set(errp
, ERROR_CLASS_DEVICE_NOT_FOUND
,
283 "IN Device '%s' not found", s
->indev
);
287 qemu_chr_fe_claim_no_fail(s
->chr_in
);
288 qemu_chr_add_handlers(s
->chr_in
, redirector_chr_can_read
,
289 redirector_chr_read
, redirector_chr_event
, nf
);
293 s
->chr_out
= qemu_chr_find(s
->outdev
);
294 if (s
->chr_out
== NULL
) {
295 error_set(errp
, ERROR_CLASS_DEVICE_NOT_FOUND
,
296 "OUT Device '%s' not found", s
->outdev
);
299 qemu_chr_fe_claim_no_fail(s
->chr_out
);
303 static void filter_mirror_class_init(ObjectClass
*oc
, void *data
)
305 NetFilterClass
*nfc
= NETFILTER_CLASS(oc
);
307 nfc
->setup
= filter_mirror_setup
;
308 nfc
->cleanup
= filter_mirror_cleanup
;
309 nfc
->receive_iov
= filter_mirror_receive_iov
;
312 static void filter_redirector_class_init(ObjectClass
*oc
, void *data
)
314 NetFilterClass
*nfc
= NETFILTER_CLASS(oc
);
316 nfc
->setup
= filter_redirector_setup
;
317 nfc
->cleanup
= filter_redirector_cleanup
;
318 nfc
->receive_iov
= filter_redirector_receive_iov
;
321 static char *filter_redirector_get_indev(Object
*obj
, Error
**errp
)
323 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
325 return g_strdup(s
->indev
);
329 filter_redirector_set_indev(Object
*obj
, const char *value
, Error
**errp
)
331 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
334 s
->indev
= g_strdup(value
);
337 static char *filter_mirror_get_outdev(Object
*obj
, Error
**errp
)
339 MirrorState
*s
= FILTER_MIRROR(obj
);
341 return g_strdup(s
->outdev
);
345 filter_mirror_set_outdev(Object
*obj
, const char *value
, Error
**errp
)
347 MirrorState
*s
= FILTER_MIRROR(obj
);
350 s
->outdev
= g_strdup(value
);
352 error_setg(errp
, "filter filter mirror needs 'outdev' "
358 static char *filter_redirector_get_outdev(Object
*obj
, Error
**errp
)
360 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
362 return g_strdup(s
->outdev
);
366 filter_redirector_set_outdev(Object
*obj
, const char *value
, Error
**errp
)
368 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
371 s
->outdev
= g_strdup(value
);
374 static void filter_mirror_init(Object
*obj
)
376 object_property_add_str(obj
, "outdev", filter_mirror_get_outdev
,
377 filter_mirror_set_outdev
, NULL
);
380 static void filter_redirector_init(Object
*obj
)
382 object_property_add_str(obj
, "indev", filter_redirector_get_indev
,
383 filter_redirector_set_indev
, NULL
);
384 object_property_add_str(obj
, "outdev", filter_redirector_get_outdev
,
385 filter_redirector_set_outdev
, NULL
);
388 static void filter_mirror_fini(Object
*obj
)
390 MirrorState
*s
= FILTER_MIRROR(obj
);
395 static void filter_redirector_fini(Object
*obj
)
397 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
403 static const TypeInfo filter_redirector_info
= {
404 .name
= TYPE_FILTER_REDIRECTOR
,
405 .parent
= TYPE_NETFILTER
,
406 .class_init
= filter_redirector_class_init
,
407 .instance_init
= filter_redirector_init
,
408 .instance_finalize
= filter_redirector_fini
,
409 .instance_size
= sizeof(MirrorState
),
412 static const TypeInfo filter_mirror_info
= {
413 .name
= TYPE_FILTER_MIRROR
,
414 .parent
= TYPE_NETFILTER
,
415 .class_init
= filter_mirror_class_init
,
416 .instance_init
= filter_mirror_init
,
417 .instance_finalize
= filter_mirror_fini
,
418 .instance_size
= sizeof(MirrorState
),
421 static void register_types(void)
423 type_register_static(&filter_mirror_info
);
424 type_register_static(&filter_redirector_info
);
427 type_init(register_types
);