1*854ee02bSLaurent Vivier /* 2*854ee02bSLaurent Vivier * passt network backend 3*854ee02bSLaurent Vivier * 4*854ee02bSLaurent Vivier * Copyright Red Hat 5*854ee02bSLaurent Vivier * 6*854ee02bSLaurent Vivier * SPDX-License-Identifier: GPL-2.0-or-later 7*854ee02bSLaurent Vivier */ 8*854ee02bSLaurent Vivier #include "qemu/osdep.h" 9*854ee02bSLaurent Vivier #include <glib/gstdio.h> 10*854ee02bSLaurent Vivier #include <gio/gio.h> 11*854ee02bSLaurent Vivier #include "net/net.h" 12*854ee02bSLaurent Vivier #include "clients.h" 13*854ee02bSLaurent Vivier #include "qapi/error.h" 14*854ee02bSLaurent Vivier #include "io/net-listener.h" 15*854ee02bSLaurent Vivier #include "stream_data.h" 16*854ee02bSLaurent Vivier 17*854ee02bSLaurent Vivier typedef struct NetPasstState { 18*854ee02bSLaurent Vivier NetStreamData data; 19*854ee02bSLaurent Vivier GPtrArray *args; 20*854ee02bSLaurent Vivier gchar *pidfile; 21*854ee02bSLaurent Vivier pid_t pid; 22*854ee02bSLaurent Vivier } NetPasstState; 23*854ee02bSLaurent Vivier 24*854ee02bSLaurent Vivier static int net_passt_stream_start(NetPasstState *s, Error **errp); 25*854ee02bSLaurent Vivier 26*854ee02bSLaurent Vivier static void net_passt_cleanup(NetClientState *nc) 27*854ee02bSLaurent Vivier { 28*854ee02bSLaurent Vivier NetPasstState *s = DO_UPCAST(NetPasstState, data.nc, nc); 29*854ee02bSLaurent Vivier 30*854ee02bSLaurent Vivier kill(s->pid, SIGTERM); 31*854ee02bSLaurent Vivier g_remove(s->pidfile); 32*854ee02bSLaurent Vivier g_free(s->pidfile); 33*854ee02bSLaurent Vivier g_ptr_array_free(s->args, TRUE); 34*854ee02bSLaurent Vivier } 35*854ee02bSLaurent Vivier 36*854ee02bSLaurent Vivier static ssize_t net_passt_receive(NetClientState *nc, const uint8_t *buf, 37*854ee02bSLaurent Vivier size_t size) 38*854ee02bSLaurent Vivier { 39*854ee02bSLaurent Vivier NetStreamData *d = DO_UPCAST(NetStreamData, nc, nc); 40*854ee02bSLaurent Vivier 41*854ee02bSLaurent Vivier return net_stream_data_receive(d, buf, size); 42*854ee02bSLaurent Vivier } 43*854ee02bSLaurent Vivier 44*854ee02bSLaurent Vivier static gboolean net_passt_send(QIOChannel *ioc, GIOCondition condition, 45*854ee02bSLaurent Vivier gpointer data) 46*854ee02bSLaurent Vivier { 47*854ee02bSLaurent Vivier if (net_stream_data_send(ioc, condition, data) == G_SOURCE_REMOVE) { 48*854ee02bSLaurent Vivier NetPasstState *s = DO_UPCAST(NetPasstState, data, data); 49*854ee02bSLaurent Vivier Error *error; 50*854ee02bSLaurent Vivier 51*854ee02bSLaurent Vivier /* we need to restart passt */ 52*854ee02bSLaurent Vivier kill(s->pid, SIGTERM); 53*854ee02bSLaurent Vivier if (net_passt_stream_start(s, &error) == -1) { 54*854ee02bSLaurent Vivier error_report_err(error); 55*854ee02bSLaurent Vivier } 56*854ee02bSLaurent Vivier 57*854ee02bSLaurent Vivier return G_SOURCE_REMOVE; 58*854ee02bSLaurent Vivier } 59*854ee02bSLaurent Vivier 60*854ee02bSLaurent Vivier return G_SOURCE_CONTINUE; 61*854ee02bSLaurent Vivier } 62*854ee02bSLaurent Vivier 63*854ee02bSLaurent Vivier static NetClientInfo net_passt_info = { 64*854ee02bSLaurent Vivier .type = NET_CLIENT_DRIVER_PASST, 65*854ee02bSLaurent Vivier .size = sizeof(NetPasstState), 66*854ee02bSLaurent Vivier .receive = net_passt_receive, 67*854ee02bSLaurent Vivier .cleanup = net_passt_cleanup, 68*854ee02bSLaurent Vivier }; 69*854ee02bSLaurent Vivier 70*854ee02bSLaurent Vivier static void net_passt_client_connected(QIOTask *task, gpointer opaque) 71*854ee02bSLaurent Vivier { 72*854ee02bSLaurent Vivier NetPasstState *s = opaque; 73*854ee02bSLaurent Vivier 74*854ee02bSLaurent Vivier if (net_stream_data_client_connected(task, &s->data) == 0) { 75*854ee02bSLaurent Vivier qemu_set_info_str(&s->data.nc, "stream,connected to pid %d", s->pid); 76*854ee02bSLaurent Vivier } 77*854ee02bSLaurent Vivier } 78*854ee02bSLaurent Vivier 79*854ee02bSLaurent Vivier static int net_passt_start_daemon(NetPasstState *s, int sock, Error **errp) 80*854ee02bSLaurent Vivier { 81*854ee02bSLaurent Vivier g_autoptr(GSubprocess) daemon = NULL; 82*854ee02bSLaurent Vivier g_autofree gchar *contents = NULL; 83*854ee02bSLaurent Vivier g_autoptr(GError) error = NULL; 84*854ee02bSLaurent Vivier GSubprocessLauncher *launcher; 85*854ee02bSLaurent Vivier 86*854ee02bSLaurent Vivier qemu_set_info_str(&s->data.nc, "launching passt"); 87*854ee02bSLaurent Vivier 88*854ee02bSLaurent Vivier launcher = g_subprocess_launcher_new(G_SUBPROCESS_FLAGS_NONE); 89*854ee02bSLaurent Vivier g_subprocess_launcher_take_fd(launcher, sock, 3); 90*854ee02bSLaurent Vivier 91*854ee02bSLaurent Vivier daemon = g_subprocess_launcher_spawnv(launcher, 92*854ee02bSLaurent Vivier (const gchar *const *)s->args->pdata, 93*854ee02bSLaurent Vivier &error); 94*854ee02bSLaurent Vivier g_object_unref(launcher); 95*854ee02bSLaurent Vivier 96*854ee02bSLaurent Vivier if (!daemon) { 97*854ee02bSLaurent Vivier error_setg(errp, "Error creating daemon: %s", error->message); 98*854ee02bSLaurent Vivier return -1; 99*854ee02bSLaurent Vivier } 100*854ee02bSLaurent Vivier 101*854ee02bSLaurent Vivier if (!g_subprocess_wait(daemon, NULL, &error)) { 102*854ee02bSLaurent Vivier error_setg(errp, "Error waiting for daemon: %s", error->message); 103*854ee02bSLaurent Vivier return -1; 104*854ee02bSLaurent Vivier } 105*854ee02bSLaurent Vivier 106*854ee02bSLaurent Vivier if (g_subprocess_get_if_exited(daemon) && 107*854ee02bSLaurent Vivier g_subprocess_get_exit_status(daemon)) { 108*854ee02bSLaurent Vivier return -1; 109*854ee02bSLaurent Vivier } 110*854ee02bSLaurent Vivier 111*854ee02bSLaurent Vivier if (!g_file_get_contents(s->pidfile, &contents, NULL, &error)) { 112*854ee02bSLaurent Vivier error_setg(errp, "Cannot read passt pid: %s", error->message); 113*854ee02bSLaurent Vivier return -1; 114*854ee02bSLaurent Vivier } 115*854ee02bSLaurent Vivier 116*854ee02bSLaurent Vivier s->pid = (pid_t)g_ascii_strtoll(contents, NULL, 10); 117*854ee02bSLaurent Vivier if (s->pid <= 0) { 118*854ee02bSLaurent Vivier error_setg(errp, "File '%s' did not contain a valid PID.", s->pidfile); 119*854ee02bSLaurent Vivier return -1; 120*854ee02bSLaurent Vivier } 121*854ee02bSLaurent Vivier 122*854ee02bSLaurent Vivier return 0; 123*854ee02bSLaurent Vivier } 124*854ee02bSLaurent Vivier 125*854ee02bSLaurent Vivier static int net_passt_stream_start(NetPasstState *s, Error **errp) 126*854ee02bSLaurent Vivier { 127*854ee02bSLaurent Vivier QIOChannelSocket *sioc; 128*854ee02bSLaurent Vivier SocketAddress *addr; 129*854ee02bSLaurent Vivier int sv[2]; 130*854ee02bSLaurent Vivier 131*854ee02bSLaurent Vivier if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { 132*854ee02bSLaurent Vivier error_setg_errno(errp, errno, "socketpair() failed"); 133*854ee02bSLaurent Vivier return -1; 134*854ee02bSLaurent Vivier } 135*854ee02bSLaurent Vivier 136*854ee02bSLaurent Vivier /* connect to passt */ 137*854ee02bSLaurent Vivier qemu_set_info_str(&s->data.nc, "connecting to passt"); 138*854ee02bSLaurent Vivier 139*854ee02bSLaurent Vivier /* create socket channel */ 140*854ee02bSLaurent Vivier sioc = qio_channel_socket_new(); 141*854ee02bSLaurent Vivier s->data.ioc = QIO_CHANNEL(sioc); 142*854ee02bSLaurent Vivier s->data.nc.link_down = true; 143*854ee02bSLaurent Vivier s->data.send = net_passt_send; 144*854ee02bSLaurent Vivier 145*854ee02bSLaurent Vivier addr = g_new0(SocketAddress, 1); 146*854ee02bSLaurent Vivier addr->type = SOCKET_ADDRESS_TYPE_FD; 147*854ee02bSLaurent Vivier addr->u.fd.str = g_strdup_printf("%d", sv[0]); 148*854ee02bSLaurent Vivier 149*854ee02bSLaurent Vivier qio_channel_socket_connect_async(sioc, addr, 150*854ee02bSLaurent Vivier net_passt_client_connected, s, 151*854ee02bSLaurent Vivier NULL, NULL); 152*854ee02bSLaurent Vivier 153*854ee02bSLaurent Vivier qapi_free_SocketAddress(addr); 154*854ee02bSLaurent Vivier 155*854ee02bSLaurent Vivier /* start passt */ 156*854ee02bSLaurent Vivier if (net_passt_start_daemon(s, sv[1], errp) == -1) { 157*854ee02bSLaurent Vivier close(sv[0]); 158*854ee02bSLaurent Vivier close(sv[1]); 159*854ee02bSLaurent Vivier return -1; 160*854ee02bSLaurent Vivier } 161*854ee02bSLaurent Vivier close(sv[1]); 162*854ee02bSLaurent Vivier 163*854ee02bSLaurent Vivier return 0; 164*854ee02bSLaurent Vivier } 165*854ee02bSLaurent Vivier 166*854ee02bSLaurent Vivier static GPtrArray *net_passt_decode_args(const NetDevPasstOptions *passt, 167*854ee02bSLaurent Vivier gchar *pidfile, Error **errp) 168*854ee02bSLaurent Vivier { 169*854ee02bSLaurent Vivier GPtrArray *args = g_ptr_array_new_with_free_func(g_free); 170*854ee02bSLaurent Vivier 171*854ee02bSLaurent Vivier if (passt->path) { 172*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->path)); 173*854ee02bSLaurent Vivier } else { 174*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("passt")); 175*854ee02bSLaurent Vivier } 176*854ee02bSLaurent Vivier 177*854ee02bSLaurent Vivier /* by default, be quiet */ 178*854ee02bSLaurent Vivier if (!passt->has_quiet || passt->quiet) { 179*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--quiet")); 180*854ee02bSLaurent Vivier } 181*854ee02bSLaurent Vivier 182*854ee02bSLaurent Vivier if (passt->has_mtu) { 183*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--mtu")); 184*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup_printf("%"PRId64, passt->mtu)); 185*854ee02bSLaurent Vivier } 186*854ee02bSLaurent Vivier 187*854ee02bSLaurent Vivier if (passt->address) { 188*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--address")); 189*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->address)); 190*854ee02bSLaurent Vivier } 191*854ee02bSLaurent Vivier 192*854ee02bSLaurent Vivier if (passt->netmask) { 193*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--netmask")); 194*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->netmask)); 195*854ee02bSLaurent Vivier } 196*854ee02bSLaurent Vivier 197*854ee02bSLaurent Vivier if (passt->mac) { 198*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--mac-addr")); 199*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->mac)); 200*854ee02bSLaurent Vivier } 201*854ee02bSLaurent Vivier 202*854ee02bSLaurent Vivier if (passt->gateway) { 203*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--gateway")); 204*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->gateway)); 205*854ee02bSLaurent Vivier } 206*854ee02bSLaurent Vivier 207*854ee02bSLaurent Vivier if (passt->interface) { 208*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--interface")); 209*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->interface)); 210*854ee02bSLaurent Vivier } 211*854ee02bSLaurent Vivier 212*854ee02bSLaurent Vivier if (passt->outbound) { 213*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--outbound")); 214*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->outbound)); 215*854ee02bSLaurent Vivier } 216*854ee02bSLaurent Vivier 217*854ee02bSLaurent Vivier if (passt->outbound_if4) { 218*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--outbound-if4")); 219*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->outbound_if4)); 220*854ee02bSLaurent Vivier } 221*854ee02bSLaurent Vivier 222*854ee02bSLaurent Vivier if (passt->outbound_if6) { 223*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--outbound-if6")); 224*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->outbound_if6)); 225*854ee02bSLaurent Vivier } 226*854ee02bSLaurent Vivier 227*854ee02bSLaurent Vivier if (passt->dns) { 228*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--dns")); 229*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->dns)); 230*854ee02bSLaurent Vivier } 231*854ee02bSLaurent Vivier if (passt->fqdn) { 232*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--fqdn")); 233*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->fqdn)); 234*854ee02bSLaurent Vivier } 235*854ee02bSLaurent Vivier 236*854ee02bSLaurent Vivier if (passt->has_dhcp_dns && !passt->dhcp_dns) { 237*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--no-dhcp-dns")); 238*854ee02bSLaurent Vivier } 239*854ee02bSLaurent Vivier 240*854ee02bSLaurent Vivier if (passt->has_dhcp_search && !passt->dhcp_search) { 241*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--no-dhcp-search")); 242*854ee02bSLaurent Vivier } 243*854ee02bSLaurent Vivier 244*854ee02bSLaurent Vivier if (passt->map_host_loopback) { 245*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--map-host-loopback")); 246*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->map_host_loopback)); 247*854ee02bSLaurent Vivier } 248*854ee02bSLaurent Vivier 249*854ee02bSLaurent Vivier if (passt->map_guest_addr) { 250*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--map-guest-addr")); 251*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->map_guest_addr)); 252*854ee02bSLaurent Vivier } 253*854ee02bSLaurent Vivier 254*854ee02bSLaurent Vivier if (passt->dns_forward) { 255*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--dns-forward")); 256*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->dns_forward)); 257*854ee02bSLaurent Vivier } 258*854ee02bSLaurent Vivier 259*854ee02bSLaurent Vivier if (passt->dns_host) { 260*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--dns-host")); 261*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(passt->dns_host)); 262*854ee02bSLaurent Vivier } 263*854ee02bSLaurent Vivier 264*854ee02bSLaurent Vivier if (passt->has_tcp && !passt->tcp) { 265*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--no-tcp")); 266*854ee02bSLaurent Vivier } 267*854ee02bSLaurent Vivier 268*854ee02bSLaurent Vivier if (passt->has_udp && !passt->udp) { 269*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--no-udp")); 270*854ee02bSLaurent Vivier } 271*854ee02bSLaurent Vivier 272*854ee02bSLaurent Vivier if (passt->has_icmp && !passt->icmp) { 273*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--no-icmp")); 274*854ee02bSLaurent Vivier } 275*854ee02bSLaurent Vivier 276*854ee02bSLaurent Vivier if (passt->has_dhcp && !passt->dhcp) { 277*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--no-dhcp")); 278*854ee02bSLaurent Vivier } 279*854ee02bSLaurent Vivier 280*854ee02bSLaurent Vivier if (passt->has_ndp && !passt->ndp) { 281*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--no-ndp")); 282*854ee02bSLaurent Vivier } 283*854ee02bSLaurent Vivier if (passt->has_dhcpv6 && !passt->dhcpv6) { 284*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--no-dhcpv6")); 285*854ee02bSLaurent Vivier } 286*854ee02bSLaurent Vivier 287*854ee02bSLaurent Vivier if (passt->has_ra && !passt->ra) { 288*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--no-ra")); 289*854ee02bSLaurent Vivier } 290*854ee02bSLaurent Vivier 291*854ee02bSLaurent Vivier if (passt->has_freebind && passt->freebind) { 292*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--freebind")); 293*854ee02bSLaurent Vivier } 294*854ee02bSLaurent Vivier 295*854ee02bSLaurent Vivier if (passt->has_ipv4 && !passt->ipv4) { 296*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--ipv6-only")); 297*854ee02bSLaurent Vivier } 298*854ee02bSLaurent Vivier 299*854ee02bSLaurent Vivier if (passt->has_ipv6 && !passt->ipv6) { 300*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--ipv4-only")); 301*854ee02bSLaurent Vivier } 302*854ee02bSLaurent Vivier 303*854ee02bSLaurent Vivier if (passt->has_search && passt->search) { 304*854ee02bSLaurent Vivier const StringList *list = passt->search; 305*854ee02bSLaurent Vivier GString *domains = g_string_new(list->value->str); 306*854ee02bSLaurent Vivier 307*854ee02bSLaurent Vivier list = list->next; 308*854ee02bSLaurent Vivier while (list) { 309*854ee02bSLaurent Vivier g_string_append(domains, " "); 310*854ee02bSLaurent Vivier g_string_append(domains, list->value->str); 311*854ee02bSLaurent Vivier list = list->next; 312*854ee02bSLaurent Vivier } 313*854ee02bSLaurent Vivier 314*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--search")); 315*854ee02bSLaurent Vivier g_ptr_array_add(args, g_string_free(domains, FALSE)); 316*854ee02bSLaurent Vivier } 317*854ee02bSLaurent Vivier 318*854ee02bSLaurent Vivier if (passt->has_tcp_ports && passt->tcp_ports) { 319*854ee02bSLaurent Vivier const StringList *list = passt->tcp_ports; 320*854ee02bSLaurent Vivier GString *tcp_ports = g_string_new(list->value->str); 321*854ee02bSLaurent Vivier 322*854ee02bSLaurent Vivier list = list->next; 323*854ee02bSLaurent Vivier while (list) { 324*854ee02bSLaurent Vivier g_string_append(tcp_ports, ","); 325*854ee02bSLaurent Vivier g_string_append(tcp_ports, list->value->str); 326*854ee02bSLaurent Vivier list = list->next; 327*854ee02bSLaurent Vivier } 328*854ee02bSLaurent Vivier 329*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--tcp-ports")); 330*854ee02bSLaurent Vivier g_ptr_array_add(args, g_string_free(tcp_ports, FALSE)); 331*854ee02bSLaurent Vivier } 332*854ee02bSLaurent Vivier 333*854ee02bSLaurent Vivier if (passt->has_udp_ports && passt->udp_ports) { 334*854ee02bSLaurent Vivier const StringList *list = passt->udp_ports; 335*854ee02bSLaurent Vivier GString *udp_ports = g_string_new(list->value->str); 336*854ee02bSLaurent Vivier 337*854ee02bSLaurent Vivier list = list->next; 338*854ee02bSLaurent Vivier while (list) { 339*854ee02bSLaurent Vivier g_string_append(udp_ports, ","); 340*854ee02bSLaurent Vivier g_string_append(udp_ports, list->value->str); 341*854ee02bSLaurent Vivier list = list->next; 342*854ee02bSLaurent Vivier } 343*854ee02bSLaurent Vivier 344*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--udp-ports")); 345*854ee02bSLaurent Vivier g_ptr_array_add(args, g_string_free(udp_ports, FALSE)); 346*854ee02bSLaurent Vivier } 347*854ee02bSLaurent Vivier 348*854ee02bSLaurent Vivier if (passt->has_param && passt->param) { 349*854ee02bSLaurent Vivier const StringList *list = passt->param; 350*854ee02bSLaurent Vivier 351*854ee02bSLaurent Vivier while (list) { 352*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(list->value->str)); 353*854ee02bSLaurent Vivier list = list->next; 354*854ee02bSLaurent Vivier } 355*854ee02bSLaurent Vivier } 356*854ee02bSLaurent Vivier 357*854ee02bSLaurent Vivier /* provide a pid file to be able to kil passt on exit */ 358*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--pid")); 359*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup(pidfile)); 360*854ee02bSLaurent Vivier 361*854ee02bSLaurent Vivier /* g_subprocess_launcher_take_fd() will set the socket on fd 3 */ 362*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("--fd")); 363*854ee02bSLaurent Vivier g_ptr_array_add(args, g_strdup("3")); 364*854ee02bSLaurent Vivier 365*854ee02bSLaurent Vivier g_ptr_array_add(args, NULL); 366*854ee02bSLaurent Vivier 367*854ee02bSLaurent Vivier return args; 368*854ee02bSLaurent Vivier } 369*854ee02bSLaurent Vivier 370*854ee02bSLaurent Vivier int net_init_passt(const Netdev *netdev, const char *name, 371*854ee02bSLaurent Vivier NetClientState *peer, Error **errp) 372*854ee02bSLaurent Vivier { 373*854ee02bSLaurent Vivier g_autoptr(GError) error = NULL; 374*854ee02bSLaurent Vivier NetClientState *nc; 375*854ee02bSLaurent Vivier NetPasstState *s; 376*854ee02bSLaurent Vivier GPtrArray *args; 377*854ee02bSLaurent Vivier gchar *pidfile; 378*854ee02bSLaurent Vivier int pidfd; 379*854ee02bSLaurent Vivier 380*854ee02bSLaurent Vivier assert(netdev->type == NET_CLIENT_DRIVER_PASST); 381*854ee02bSLaurent Vivier 382*854ee02bSLaurent Vivier pidfd = g_file_open_tmp("passt-XXXXXX.pid", &pidfile, &error); 383*854ee02bSLaurent Vivier if (pidfd == -1) { 384*854ee02bSLaurent Vivier error_setg(errp, "Failed to create temporary file: %s", error->message); 385*854ee02bSLaurent Vivier return -1; 386*854ee02bSLaurent Vivier } 387*854ee02bSLaurent Vivier close(pidfd); 388*854ee02bSLaurent Vivier 389*854ee02bSLaurent Vivier args = net_passt_decode_args(&netdev->u.passt, pidfile, errp); 390*854ee02bSLaurent Vivier if (args == NULL) { 391*854ee02bSLaurent Vivier g_free(pidfile); 392*854ee02bSLaurent Vivier return -1; 393*854ee02bSLaurent Vivier } 394*854ee02bSLaurent Vivier 395*854ee02bSLaurent Vivier nc = qemu_new_net_client(&net_passt_info, peer, "passt", name); 396*854ee02bSLaurent Vivier s = DO_UPCAST(NetPasstState, data.nc, nc); 397*854ee02bSLaurent Vivier 398*854ee02bSLaurent Vivier s->args = args; 399*854ee02bSLaurent Vivier s->pidfile = pidfile; 400*854ee02bSLaurent Vivier 401*854ee02bSLaurent Vivier if (net_passt_stream_start(s, errp) == -1) { 402*854ee02bSLaurent Vivier qemu_del_net_client(nc); 403*854ee02bSLaurent Vivier return -1; 404*854ee02bSLaurent Vivier } 405*854ee02bSLaurent Vivier 406*854ee02bSLaurent Vivier return 0; 407*854ee02bSLaurent Vivier } 408