Revision 3a75e74c net/socket.c
b/net/socket.c | ||
---|---|---|
149 | 149 |
qemu_send_packet(&s->nc, s->buf, size); |
150 | 150 |
} |
151 | 151 |
|
152 |
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) |
|
152 |
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
|
|
153 | 153 |
{ |
154 | 154 |
struct ip_mreq imr; |
155 | 155 |
int fd; |
... | ... | |
183 | 183 |
|
184 | 184 |
/* Add host to multicast group */ |
185 | 185 |
imr.imr_multiaddr = mcastaddr->sin_addr; |
186 |
imr.imr_interface.s_addr = htonl(INADDR_ANY); |
|
186 |
if (localaddr) { |
|
187 |
imr.imr_interface = *localaddr; |
|
188 |
} else { |
|
189 |
imr.imr_interface.s_addr = htonl(INADDR_ANY); |
|
190 |
} |
|
187 | 191 |
|
188 | 192 |
ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, |
189 | 193 |
(const char *)&imr, sizeof(struct ip_mreq)); |
... | ... | |
201 | 205 |
goto fail; |
202 | 206 |
} |
203 | 207 |
|
208 |
/* If a bind address is given, only send packets from that address */ |
|
209 |
if (localaddr != NULL) { |
|
210 |
ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr)); |
|
211 |
if (ret < 0) { |
|
212 |
perror("setsockopt(IP_MULTICAST_IF)"); |
|
213 |
goto fail; |
|
214 |
} |
|
215 |
} |
|
216 |
|
|
204 | 217 |
socket_set_nonblock(fd); |
205 | 218 |
return fd; |
206 | 219 |
fail: |
... | ... | |
248 | 261 |
return NULL; |
249 | 262 |
} |
250 | 263 |
/* clone dgram socket */ |
251 |
newfd = net_socket_mcast_create(&saddr); |
|
264 |
newfd = net_socket_mcast_create(&saddr, NULL);
|
|
252 | 265 |
if (newfd < 0) { |
253 | 266 |
/* error already reported by net_socket_mcast_create() */ |
254 | 267 |
close(fd); |
... | ... | |
468 | 481 |
static int net_socket_mcast_init(VLANState *vlan, |
469 | 482 |
const char *model, |
470 | 483 |
const char *name, |
471 |
const char *host_str) |
|
484 |
const char *host_str, |
|
485 |
const char *localaddr_str) |
|
472 | 486 |
{ |
473 | 487 |
NetSocketState *s; |
474 | 488 |
int fd; |
475 | 489 |
struct sockaddr_in saddr; |
490 |
struct in_addr localaddr, *param_localaddr; |
|
476 | 491 |
|
477 | 492 |
if (parse_host_port(&saddr, host_str) < 0) |
478 | 493 |
return -1; |
479 | 494 |
|
495 |
if (localaddr_str != NULL) { |
|
496 |
if (inet_aton(localaddr_str, &localaddr) == 0) |
|
497 |
return -1; |
|
498 |
param_localaddr = &localaddr; |
|
499 |
} else { |
|
500 |
param_localaddr = NULL; |
|
501 |
} |
|
480 | 502 |
|
481 |
fd = net_socket_mcast_create(&saddr); |
|
503 |
fd = net_socket_mcast_create(&saddr, param_localaddr);
|
|
482 | 504 |
if (fd < 0) |
483 | 505 |
return -1; |
484 | 506 |
|
... | ... | |
505 | 527 |
|
506 | 528 |
if (qemu_opt_get(opts, "listen") || |
507 | 529 |
qemu_opt_get(opts, "connect") || |
508 |
qemu_opt_get(opts, "mcast")) { |
|
509 |
error_report("listen=, connect= and mcast= is invalid with fd="); |
|
530 |
qemu_opt_get(opts, "mcast") || |
|
531 |
qemu_opt_get(opts, "localaddr")) { |
|
532 |
error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n"); |
|
510 | 533 |
return -1; |
511 | 534 |
} |
512 | 535 |
|
... | ... | |
524 | 547 |
|
525 | 548 |
if (qemu_opt_get(opts, "fd") || |
526 | 549 |
qemu_opt_get(opts, "connect") || |
527 |
qemu_opt_get(opts, "mcast")) { |
|
528 |
error_report("fd=, connect= and mcast= is invalid with listen="); |
|
550 |
qemu_opt_get(opts, "mcast") || |
|
551 |
qemu_opt_get(opts, "localaddr")) { |
|
552 |
error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n"); |
|
529 | 553 |
return -1; |
530 | 554 |
} |
531 | 555 |
|
... | ... | |
539 | 563 |
|
540 | 564 |
if (qemu_opt_get(opts, "fd") || |
541 | 565 |
qemu_opt_get(opts, "listen") || |
542 |
qemu_opt_get(opts, "mcast")) { |
|
543 |
error_report("fd=, listen= and mcast= is invalid with connect="); |
|
566 |
qemu_opt_get(opts, "mcast") || |
|
567 |
qemu_opt_get(opts, "localaddr")) { |
|
568 |
error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n"); |
|
544 | 569 |
return -1; |
545 | 570 |
} |
546 | 571 |
|
... | ... | |
550 | 575 |
return -1; |
551 | 576 |
} |
552 | 577 |
} else if (qemu_opt_get(opts, "mcast")) { |
553 |
const char *mcast; |
|
578 |
const char *mcast, *localaddr;
|
|
554 | 579 |
|
555 | 580 |
if (qemu_opt_get(opts, "fd") || |
556 | 581 |
qemu_opt_get(opts, "connect") || |
... | ... | |
560 | 585 |
} |
561 | 586 |
|
562 | 587 |
mcast = qemu_opt_get(opts, "mcast"); |
588 |
localaddr = qemu_opt_get(opts, "localaddr"); |
|
563 | 589 |
|
564 |
if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) { |
|
590 |
if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) {
|
|
565 | 591 |
return -1; |
566 | 592 |
} |
567 | 593 |
} else { |
Also available in: Unified diff