1 /* 2 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 3 * Copyright (c) 2016 FUJITSU LIMITED 4 * Copyright (c) 2016 Intel Corporation 5 * 6 * Author: Zhang Chen <zhangchen.fnst@cn.fujitsu.com> 7 * 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. 10 */ 11 12 #include "qemu/osdep.h" 13 #include "net/filter.h" 14 #include "net/net.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" 22 #include "trace.h" 23 #include "sysemu/char.h" 24 #include "qemu/iov.h" 25 #include "qemu/sockets.h" 26 27 #define FILTER_MIRROR(obj) \ 28 OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_MIRROR) 29 30 #define FILTER_REDIRECTOR(obj) \ 31 OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_REDIRECTOR) 32 33 #define TYPE_FILTER_MIRROR "filter-mirror" 34 #define TYPE_FILTER_REDIRECTOR "filter-redirector" 35 #define REDIRECTOR_MAX_LEN NET_BUFSIZE 36 37 typedef struct MirrorState { 38 NetFilterState parent_obj; 39 char *indev; 40 char *outdev; 41 CharDriverState *chr_in; 42 CharDriverState *chr_out; 43 int state; /* 0 = getting length, 1 = getting data */ 44 unsigned int index; 45 unsigned int packet_len; 46 uint8_t buf[REDIRECTOR_MAX_LEN]; 47 } MirrorState; 48 49 static int filter_mirror_send(CharDriverState *chr_out, 50 const struct iovec *iov, 51 int iovcnt) 52 { 53 int ret = 0; 54 ssize_t size = 0; 55 uint32_t len = 0; 56 char *buf; 57 58 size = iov_size(iov, iovcnt); 59 if (!size) { 60 return 0; 61 } 62 63 len = htonl(size); 64 ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)&len, sizeof(len)); 65 if (ret != sizeof(len)) { 66 goto err; 67 } 68 69 buf = g_malloc(size); 70 iov_to_buf(iov, iovcnt, 0, buf, size); 71 ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)buf, size); 72 g_free(buf); 73 if (ret != size) { 74 goto err; 75 } 76 77 return 0; 78 79 err: 80 return ret < 0 ? ret : -EIO; 81 } 82 83 static void 84 redirector_to_filter(NetFilterState *nf, const uint8_t *buf, int len) 85 { 86 struct iovec iov = { 87 .iov_base = (void *)buf, 88 .iov_len = len, 89 }; 90 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); 94 } 95 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); 99 } 100 } 101 102 static int redirector_chr_can_read(void *opaque) 103 { 104 return REDIRECTOR_MAX_LEN; 105 } 106 107 static void redirector_chr_read(void *opaque, const uint8_t *buf, int size) 108 { 109 NetFilterState *nf = opaque; 110 MirrorState *s = FILTER_REDIRECTOR(nf); 111 unsigned int l; 112 113 while (size > 0) { 114 /* reassemble a packet from the network */ 115 switch (s->state) { /* 0 = getting length, 1 = getting data */ 116 case 0: 117 l = 4 - s->index; 118 if (l > size) { 119 l = size; 120 } 121 memcpy(s->buf + s->index, buf, l); 122 buf += l; 123 size -= l; 124 s->index += l; 125 if (s->index == 4) { 126 /* got length */ 127 s->packet_len = ntohl(*(uint32_t *)s->buf); 128 s->index = 0; 129 s->state = 1; 130 } 131 break; 132 case 1: 133 l = s->packet_len - s->index; 134 if (l > size) { 135 l = size; 136 } 137 if (s->index + l <= sizeof(s->buf)) { 138 memcpy(s->buf + s->index, buf, l); 139 } else { 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); 143 return; 144 } 145 146 s->index += l; 147 buf += l; 148 size -= l; 149 if (s->index >= s->packet_len) { 150 s->index = 0; 151 s->state = 0; 152 redirector_to_filter(nf, s->buf, s->packet_len); 153 } 154 break; 155 } 156 } 157 } 158 159 static void redirector_chr_event(void *opaque, int event) 160 { 161 NetFilterState *nf = opaque; 162 MirrorState *s = FILTER_REDIRECTOR(nf); 163 164 switch (event) { 165 case CHR_EVENT_CLOSED: 166 qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL); 167 break; 168 default: 169 break; 170 } 171 } 172 173 static ssize_t filter_mirror_receive_iov(NetFilterState *nf, 174 NetClientState *sender, 175 unsigned flags, 176 const struct iovec *iov, 177 int iovcnt, 178 NetPacketSent *sent_cb) 179 { 180 MirrorState *s = FILTER_MIRROR(nf); 181 int ret; 182 183 ret = filter_mirror_send(s->chr_out, iov, iovcnt); 184 if (ret) { 185 error_report("filter_mirror_send failed(%s)", strerror(-ret)); 186 } 187 188 /* 189 * we don't hope this error interrupt the normal 190 * path of net packet, so we always return zero. 191 */ 192 return 0; 193 } 194 195 static ssize_t filter_redirector_receive_iov(NetFilterState *nf, 196 NetClientState *sender, 197 unsigned flags, 198 const struct iovec *iov, 199 int iovcnt, 200 NetPacketSent *sent_cb) 201 { 202 MirrorState *s = FILTER_REDIRECTOR(nf); 203 int ret; 204 205 if (s->chr_out) { 206 ret = filter_mirror_send(s->chr_out, iov, iovcnt); 207 if (ret) { 208 error_report("filter_mirror_send failed(%s)", strerror(-ret)); 209 } 210 return iov_size(iov, iovcnt); 211 } else { 212 return 0; 213 } 214 } 215 216 static void filter_mirror_cleanup(NetFilterState *nf) 217 { 218 MirrorState *s = FILTER_MIRROR(nf); 219 220 if (s->chr_out) { 221 qemu_chr_fe_release(s->chr_out); 222 } 223 } 224 225 static void filter_redirector_cleanup(NetFilterState *nf) 226 { 227 MirrorState *s = FILTER_REDIRECTOR(nf); 228 229 if (s->chr_in) { 230 qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL); 231 qemu_chr_fe_release(s->chr_in); 232 } 233 if (s->chr_out) { 234 qemu_chr_fe_release(s->chr_out); 235 } 236 } 237 238 static void filter_mirror_setup(NetFilterState *nf, Error **errp) 239 { 240 MirrorState *s = FILTER_MIRROR(nf); 241 242 if (!s->outdev) { 243 error_setg(errp, "filter filter mirror needs 'outdev' " 244 "property set"); 245 return; 246 } 247 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); 252 return; 253 } 254 255 if (qemu_chr_fe_claim(s->chr_out) != 0) { 256 error_setg(errp, QERR_DEVICE_IN_USE, s->outdev); 257 return; 258 } 259 } 260 261 static void filter_redirector_setup(NetFilterState *nf, Error **errp) 262 { 263 MirrorState *s = FILTER_REDIRECTOR(nf); 264 265 if (!s->indev && !s->outdev) { 266 error_setg(errp, "filter redirector needs 'indev' or " 267 "'outdev' at least one property set"); 268 return; 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"); 273 return; 274 } 275 } 276 277 s->state = s->index = 0; 278 279 if (s->indev) { 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); 284 return; 285 } 286 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); 290 } 291 292 if (s->outdev) { 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); 297 return; 298 } 299 qemu_chr_fe_claim_no_fail(s->chr_out); 300 } 301 } 302 303 static void filter_mirror_class_init(ObjectClass *oc, void *data) 304 { 305 NetFilterClass *nfc = NETFILTER_CLASS(oc); 306 307 nfc->setup = filter_mirror_setup; 308 nfc->cleanup = filter_mirror_cleanup; 309 nfc->receive_iov = filter_mirror_receive_iov; 310 } 311 312 static void filter_redirector_class_init(ObjectClass *oc, void *data) 313 { 314 NetFilterClass *nfc = NETFILTER_CLASS(oc); 315 316 nfc->setup = filter_redirector_setup; 317 nfc->cleanup = filter_redirector_cleanup; 318 nfc->receive_iov = filter_redirector_receive_iov; 319 } 320 321 static char *filter_redirector_get_indev(Object *obj, Error **errp) 322 { 323 MirrorState *s = FILTER_REDIRECTOR(obj); 324 325 return g_strdup(s->indev); 326 } 327 328 static void 329 filter_redirector_set_indev(Object *obj, const char *value, Error **errp) 330 { 331 MirrorState *s = FILTER_REDIRECTOR(obj); 332 333 g_free(s->indev); 334 s->indev = g_strdup(value); 335 } 336 337 static char *filter_mirror_get_outdev(Object *obj, Error **errp) 338 { 339 MirrorState *s = FILTER_MIRROR(obj); 340 341 return g_strdup(s->outdev); 342 } 343 344 static void 345 filter_mirror_set_outdev(Object *obj, const char *value, Error **errp) 346 { 347 MirrorState *s = FILTER_MIRROR(obj); 348 349 g_free(s->outdev); 350 s->outdev = g_strdup(value); 351 if (!s->outdev) { 352 error_setg(errp, "filter filter mirror needs 'outdev' " 353 "property set"); 354 return; 355 } 356 } 357 358 static char *filter_redirector_get_outdev(Object *obj, Error **errp) 359 { 360 MirrorState *s = FILTER_REDIRECTOR(obj); 361 362 return g_strdup(s->outdev); 363 } 364 365 static void 366 filter_redirector_set_outdev(Object *obj, const char *value, Error **errp) 367 { 368 MirrorState *s = FILTER_REDIRECTOR(obj); 369 370 g_free(s->outdev); 371 s->outdev = g_strdup(value); 372 } 373 374 static void filter_mirror_init(Object *obj) 375 { 376 object_property_add_str(obj, "outdev", filter_mirror_get_outdev, 377 filter_mirror_set_outdev, NULL); 378 } 379 380 static void filter_redirector_init(Object *obj) 381 { 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); 386 } 387 388 static void filter_mirror_fini(Object *obj) 389 { 390 MirrorState *s = FILTER_MIRROR(obj); 391 392 g_free(s->outdev); 393 } 394 395 static void filter_redirector_fini(Object *obj) 396 { 397 MirrorState *s = FILTER_REDIRECTOR(obj); 398 399 g_free(s->indev); 400 g_free(s->outdev); 401 } 402 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), 410 }; 411 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), 419 }; 420 421 static void register_types(void) 422 { 423 type_register_static(&filter_mirror_info); 424 type_register_static(&filter_redirector_info); 425 } 426 427 type_init(register_types); 428