struct nbd_reply reply;
int is_unix;
- char *host_spec;
+ char *unix_path;
+
+ InetSocketAddress *inet_addr;
+
char *export_name; /* An NBD server may export several devices */
} BDRVNBDState;
ret = -EINVAL;
goto out;
}
- s->host_spec = g_strdup(qp->p[0].value);
+ s->unix_path = g_strdup(qp->p[0].value);
} else {
/* nbd[+tcp]://host:port/export */
if (!uri->server) {
if (!uri->port) {
uri->port = NBD_DEFAULT_PORT;
}
- s->host_spec = g_strdup_printf("%s:%d", uri->server, uri->port);
+
+ s->inet_addr = g_new0(InetSocketAddress, 1);
+ *s->inet_addr = (InetSocketAddress) {
+ .host = g_strdup(uri->server),
+ .port = g_strdup_printf("%d", uri->port),
+ };
}
out:
const char *host_spec;
const char *unixpath;
int err = -EINVAL;
+ Error *local_err = NULL;
if (strstr(filename, "://")) {
return nbd_parse_uri(s, filename);
/* are we a UNIX or TCP socket? */
if (strstart(host_spec, "unix:", &unixpath)) {
s->is_unix = true;
- s->host_spec = g_strdup(unixpath);
+ s->unix_path = g_strdup(unixpath);
} else {
s->is_unix = false;
- s->host_spec = g_strdup(host_spec);
+ s->inet_addr = inet_parse(host_spec, &local_err);
+ if (local_err != NULL) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ goto out;
+ }
}
err = 0;
g_free(file);
if (err != 0) {
g_free(s->export_name);
- g_free(s->host_spec);
+ g_free(s->unix_path);
+ qapi_free_InetSocketAddress(s->inet_addr);
}
return err;
}
size_t blocksize;
if (s->is_unix) {
- sock = unix_socket_outgoing(s->host_spec);
+ sock = unix_socket_outgoing(s->unix_path);
} else {
- sock = tcp_socket_outgoing_spec(s->host_spec);
+ QemuOpts *opts = qemu_opts_create_nofail(&socket_optslist);
+
+ qemu_opt_set(opts, "host", s->inet_addr->host);
+ qemu_opt_set(opts, "port", s->inet_addr->port);
+ if (s->inet_addr->has_to) {
+ qemu_opt_set_number(opts, "to", s->inet_addr->to);
+ }
+ if (s->inet_addr->has_ipv4) {
+ qemu_opt_set_number(opts, "ipv4", s->inet_addr->ipv4);
+ }
+ if (s->inet_addr->has_ipv6) {
+ qemu_opt_set_number(opts, "ipv6", s->inet_addr->ipv6);
+ }
+
+ sock = tcp_socket_outgoing_opts(opts);
+ qemu_opts_del(opts);
}
/* Failed to establish connection */
{
BDRVNBDState *s = bs->opaque;
g_free(s->export_name);
- g_free(s->host_spec);
+ g_free(s->unix_path);
+ qapi_free_InetSocketAddress(s->inet_addr);
nbd_teardown_connection(bs);
}
return fd;
}
+int tcp_socket_outgoing_opts(QemuOpts *opts)
+{
+ Error *local_err = NULL;
+ int fd = inet_connect_opts(opts, &local_err, NULL, NULL);
+ if (local_err != NULL) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ }
+
+ return fd;
+}
+
int tcp_socket_incoming(const char *address, uint16_t port)
{
char address_and_port[128];
}
/* compatibility wrapper */
-static InetSocketAddress *inet_parse(const char *str, Error **errp)
+InetSocketAddress *inet_parse(const char *str, Error **errp)
{
InetSocketAddress *addr;
const char *optstr, *h;
return NULL;
}
-static void inet_addr_to_opts(QemuOpts *opts, InetSocketAddress *addr)
+static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr)
{
bool ipv4 = addr->ipv4 || !addr->has_ipv4;
bool ipv6 = addr->ipv6 || !addr->has_ipv6;
addr = inet_parse(str, errp);
if (addr != NULL) {
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
inet_addr_to_opts(opts, addr);
qapi_free_InetSocketAddress(addr);
sock = inet_connect_opts(opts, errp, NULL, NULL);