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
;
46 static int filter_mirror_send(CharBackend
*chr_out
,
47 const struct iovec
*iov
,
55 size
= iov_size(iov
, iovcnt
);
61 ret
= qemu_chr_fe_write_all(chr_out
, (uint8_t *)&len
, sizeof(len
));
62 if (ret
!= sizeof(len
)) {
67 iov_to_buf(iov
, iovcnt
, 0, buf
, size
);
68 ret
= qemu_chr_fe_write_all(chr_out
, (uint8_t *)buf
, size
);
77 return ret
< 0 ? ret
: -EIO
;
81 redirector_to_filter(NetFilterState
*nf
, const uint8_t *buf
, int len
)
84 .iov_base
= (void *)buf
,
88 if (nf
->direction
== NET_FILTER_DIRECTION_ALL
||
89 nf
->direction
== NET_FILTER_DIRECTION_TX
) {
90 qemu_netfilter_pass_to_next(nf
->netdev
, 0, &iov
, 1, nf
);
93 if (nf
->direction
== NET_FILTER_DIRECTION_ALL
||
94 nf
->direction
== NET_FILTER_DIRECTION_RX
) {
95 qemu_netfilter_pass_to_next(nf
->netdev
->peer
, 0, &iov
, 1, nf
);
99 static int redirector_chr_can_read(void *opaque
)
101 return REDIRECTOR_MAX_LEN
;
104 static void redirector_chr_read(void *opaque
, const uint8_t *buf
, int size
)
106 NetFilterState
*nf
= opaque
;
107 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
110 ret
= net_fill_rstate(&s
->rs
, buf
, size
);
113 qemu_chr_fe_set_handlers(&s
->chr_in
, NULL
, NULL
, NULL
, NULL
, NULL
);
117 static void redirector_chr_event(void *opaque
, int event
)
119 NetFilterState
*nf
= opaque
;
120 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
123 case CHR_EVENT_CLOSED
:
124 qemu_chr_fe_set_handlers(&s
->chr_in
, NULL
, NULL
, NULL
, NULL
, NULL
);
131 static ssize_t
filter_mirror_receive_iov(NetFilterState
*nf
,
132 NetClientState
*sender
,
134 const struct iovec
*iov
,
136 NetPacketSent
*sent_cb
)
138 MirrorState
*s
= FILTER_MIRROR(nf
);
141 ret
= filter_mirror_send(&s
->chr_out
, iov
, iovcnt
);
143 error_report("filter_mirror_send failed(%s)", strerror(-ret
));
147 * we don't hope this error interrupt the normal
148 * path of net packet, so we always return zero.
153 static ssize_t
filter_redirector_receive_iov(NetFilterState
*nf
,
154 NetClientState
*sender
,
156 const struct iovec
*iov
,
158 NetPacketSent
*sent_cb
)
160 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
163 if (qemu_chr_fe_get_driver(&s
->chr_out
)) {
164 ret
= filter_mirror_send(&s
->chr_out
, iov
, iovcnt
);
166 error_report("filter_mirror_send failed(%s)", strerror(-ret
));
168 return iov_size(iov
, iovcnt
);
174 static void filter_mirror_cleanup(NetFilterState
*nf
)
176 MirrorState
*s
= FILTER_MIRROR(nf
);
178 qemu_chr_fe_deinit(&s
->chr_out
);
181 static void filter_redirector_cleanup(NetFilterState
*nf
)
183 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
185 qemu_chr_fe_deinit(&s
->chr_in
);
186 qemu_chr_fe_deinit(&s
->chr_out
);
189 static void filter_mirror_setup(NetFilterState
*nf
, Error
**errp
)
191 MirrorState
*s
= FILTER_MIRROR(nf
);
192 CharDriverState
*chr
;
195 error_setg(errp
, "filter mirror needs 'outdev' "
200 chr
= qemu_chr_find(s
->outdev
);
202 error_set(errp
, ERROR_CLASS_DEVICE_NOT_FOUND
,
203 "Device '%s' not found", s
->outdev
);
207 qemu_chr_fe_init(&s
->chr_out
, chr
, errp
);
210 static void redirector_rs_finalize(SocketReadState
*rs
)
212 MirrorState
*s
= container_of(rs
, MirrorState
, rs
);
213 NetFilterState
*nf
= NETFILTER(s
);
215 redirector_to_filter(nf
, rs
->buf
, rs
->packet_len
);
218 static void filter_redirector_setup(NetFilterState
*nf
, Error
**errp
)
220 MirrorState
*s
= FILTER_REDIRECTOR(nf
);
221 CharDriverState
*chr
;
223 if (!s
->indev
&& !s
->outdev
) {
224 error_setg(errp
, "filter redirector needs 'indev' or "
225 "'outdev' at least one property set");
227 } else if (s
->indev
&& s
->outdev
) {
228 if (!strcmp(s
->indev
, s
->outdev
)) {
229 error_setg(errp
, "'indev' and 'outdev' could not be same "
230 "for filter redirector");
235 net_socket_rs_init(&s
->rs
, redirector_rs_finalize
);
238 chr
= qemu_chr_find(s
->indev
);
240 error_set(errp
, ERROR_CLASS_DEVICE_NOT_FOUND
,
241 "IN Device '%s' not found", s
->indev
);
245 if (!qemu_chr_fe_init(&s
->chr_in
, chr
, errp
)) {
249 qemu_chr_fe_set_handlers(&s
->chr_in
, redirector_chr_can_read
,
250 redirector_chr_read
, redirector_chr_event
,
255 chr
= qemu_chr_find(s
->outdev
);
257 error_set(errp
, ERROR_CLASS_DEVICE_NOT_FOUND
,
258 "OUT Device '%s' not found", s
->outdev
);
261 if (!qemu_chr_fe_init(&s
->chr_out
, chr
, errp
)) {
267 static void filter_mirror_class_init(ObjectClass
*oc
, void *data
)
269 NetFilterClass
*nfc
= NETFILTER_CLASS(oc
);
271 nfc
->setup
= filter_mirror_setup
;
272 nfc
->cleanup
= filter_mirror_cleanup
;
273 nfc
->receive_iov
= filter_mirror_receive_iov
;
276 static void filter_redirector_class_init(ObjectClass
*oc
, void *data
)
278 NetFilterClass
*nfc
= NETFILTER_CLASS(oc
);
280 nfc
->setup
= filter_redirector_setup
;
281 nfc
->cleanup
= filter_redirector_cleanup
;
282 nfc
->receive_iov
= filter_redirector_receive_iov
;
285 static char *filter_redirector_get_indev(Object
*obj
, Error
**errp
)
287 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
289 return g_strdup(s
->indev
);
293 filter_redirector_set_indev(Object
*obj
, const char *value
, Error
**errp
)
295 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
298 s
->indev
= g_strdup(value
);
301 static char *filter_mirror_get_outdev(Object
*obj
, Error
**errp
)
303 MirrorState
*s
= FILTER_MIRROR(obj
);
305 return g_strdup(s
->outdev
);
309 filter_mirror_set_outdev(Object
*obj
, const char *value
, Error
**errp
)
311 MirrorState
*s
= FILTER_MIRROR(obj
);
314 s
->outdev
= g_strdup(value
);
316 error_setg(errp
, "filter mirror needs 'outdev' "
322 static char *filter_redirector_get_outdev(Object
*obj
, Error
**errp
)
324 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
326 return g_strdup(s
->outdev
);
330 filter_redirector_set_outdev(Object
*obj
, const char *value
, Error
**errp
)
332 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
335 s
->outdev
= g_strdup(value
);
338 static void filter_mirror_init(Object
*obj
)
340 object_property_add_str(obj
, "outdev", filter_mirror_get_outdev
,
341 filter_mirror_set_outdev
, NULL
);
344 static void filter_redirector_init(Object
*obj
)
346 object_property_add_str(obj
, "indev", filter_redirector_get_indev
,
347 filter_redirector_set_indev
, NULL
);
348 object_property_add_str(obj
, "outdev", filter_redirector_get_outdev
,
349 filter_redirector_set_outdev
, NULL
);
352 static void filter_mirror_fini(Object
*obj
)
354 MirrorState
*s
= FILTER_MIRROR(obj
);
359 static void filter_redirector_fini(Object
*obj
)
361 MirrorState
*s
= FILTER_REDIRECTOR(obj
);
367 static const TypeInfo filter_redirector_info
= {
368 .name
= TYPE_FILTER_REDIRECTOR
,
369 .parent
= TYPE_NETFILTER
,
370 .class_init
= filter_redirector_class_init
,
371 .instance_init
= filter_redirector_init
,
372 .instance_finalize
= filter_redirector_fini
,
373 .instance_size
= sizeof(MirrorState
),
376 static const TypeInfo filter_mirror_info
= {
377 .name
= TYPE_FILTER_MIRROR
,
378 .parent
= TYPE_NETFILTER
,
379 .class_init
= filter_mirror_class_init
,
380 .instance_init
= filter_mirror_init
,
381 .instance_finalize
= filter_mirror_fini
,
382 .instance_size
= sizeof(MirrorState
),
385 static void register_types(void)
387 type_register_static(&filter_mirror_info
);
388 type_register_static(&filter_redirector_info
);
391 type_init(register_types
);