]> git.proxmox.com Git - qemu.git/blobdiff - qemu-sockets.c
correctly check ppr priority during interrupt injection]
[qemu.git] / qemu-sockets.c
index ec9777ff19a8501a733517ab2356dfbd0cdc5970..c526324998b07047daec34b209707e2f817d3935 100644 (file)
@@ -30,9 +30,9 @@ static int sockets_debug = 0;
 static const int on=1, off=0;
 
 /* used temporarely until all users are converted to QemuOpts */
-QemuOptsList dummy_opts = {
+static QemuOptsList dummy_opts = {
     .name = "dummy",
-    .head = TAILQ_HEAD_INITIALIZER(dummy_opts.head),
+    .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
     .desc = {
         {
             .name = "path",
@@ -91,14 +91,14 @@ static void inet_setport(struct addrinfo *e, int port)
     }
 }
 
-static const char *inet_strfamily(int family)
+const char *inet_strfamily(int family)
 {
     switch (family) {
     case PF_INET6: return "ipv6";
     case PF_INET:  return "ipv4";
     case PF_UNIX:  return "unix";
     }
-    return "????";
+    return "unknown";
 }
 
 static void inet_print_addrinfo(const char *tag, struct addrinfo *res)
@@ -130,7 +130,8 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
     ai.ai_family = PF_UNSPEC;
     ai.ai_socktype = SOCK_STREAM;
 
-    if (qemu_opt_get(opts, "port") == NULL) {
+    if ((qemu_opt_get(opts, "host") == NULL) ||
+        (qemu_opt_get(opts, "port") == NULL)) {
         fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
         return -1;
     }
@@ -160,7 +161,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
         getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
                        uaddr,INET6_ADDRSTRLEN,uport,32,
                        NI_NUMERICHOST | NI_NUMERICSERV);
-        slisten = socket(e->ai_family, e->ai_socktype, e->ai_protocol);
+        slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
         if (slisten < 0) {
             fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
                     inet_strfamily(e->ai_family), strerror(errno));
@@ -258,7 +259,7 @@ int inet_connect_opts(QemuOpts *opts)
             fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__);
             continue;
         }
-        sock = socket(e->ai_family, e->ai_socktype, e->ai_protocol);
+        sock = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
         if (sock < 0) {
             fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
             inet_strfamily(e->ai_family), strerror(errno));
@@ -286,6 +287,120 @@ int inet_connect_opts(QemuOpts *opts)
     return -1;
 }
 
+int inet_dgram_opts(QemuOpts *opts)
+{
+    struct addrinfo ai, *peer = NULL, *local = NULL;
+    const char *addr;
+    const char *port;
+    char uaddr[INET6_ADDRSTRLEN+1];
+    char uport[33];
+    int sock = -1, rc;
+
+    /* lookup peer addr */
+    memset(&ai,0, sizeof(ai));
+    ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
+    ai.ai_family = PF_UNSPEC;
+    ai.ai_socktype = SOCK_DGRAM;
+
+    addr = qemu_opt_get(opts, "host");
+    port = qemu_opt_get(opts, "port");
+    if (addr == NULL || strlen(addr) == 0) {
+        addr = "localhost";
+    }
+    if (port == NULL || strlen(port) == 0) {
+        fprintf(stderr, "inet_dgram: port not specified\n");
+        return -1;
+    }
+
+    if (qemu_opt_get_bool(opts, "ipv4", 0))
+        ai.ai_family = PF_INET;
+    if (qemu_opt_get_bool(opts, "ipv6", 0))
+        ai.ai_family = PF_INET6;
+
+    if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) {
+        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
+                gai_strerror(rc));
+       return -1;
+    }
+    if (sockets_debug) {
+        fprintf(stderr, "%s: peer (%s:%s)\n", __FUNCTION__, addr, port);
+        inet_print_addrinfo(__FUNCTION__, peer);
+    }
+
+    /* lookup local addr */
+    memset(&ai,0, sizeof(ai));
+    ai.ai_flags = AI_PASSIVE;
+    ai.ai_family = peer->ai_family;
+    ai.ai_socktype = SOCK_DGRAM;
+
+    addr = qemu_opt_get(opts, "localaddr");
+    port = qemu_opt_get(opts, "localport");
+    if (addr == NULL || strlen(addr) == 0) {
+        addr = NULL;
+    }
+    if (!port || strlen(port) == 0)
+        port = "0";
+
+    if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) {
+        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
+                gai_strerror(rc));
+        return -1;
+    }
+    if (sockets_debug) {
+        fprintf(stderr, "%s: local (%s:%s)\n", __FUNCTION__, addr, port);
+        inet_print_addrinfo(__FUNCTION__, local);
+    }
+
+    /* create socket */
+    sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
+    if (sock < 0) {
+        fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
+                inet_strfamily(peer->ai_family), strerror(errno));
+        goto err;
+    }
+    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
+
+    /* bind socket */
+    if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen,
+                    uaddr,INET6_ADDRSTRLEN,uport,32,
+                    NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
+        fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
+        goto err;
+    }
+    if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
+        fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
+                inet_strfamily(local->ai_family), uaddr, inet_getport(local));
+        goto err;
+    }
+
+    /* connect to peer */
+    if (getnameinfo((struct sockaddr*)peer->ai_addr, peer->ai_addrlen,
+                    uaddr, INET6_ADDRSTRLEN, uport, 32,
+                    NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
+        fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
+        goto err;
+    }
+    if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) {
+        fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
+                inet_strfamily(peer->ai_family),
+                peer->ai_canonname, uaddr, uport, strerror(errno));
+        goto err;
+    }
+
+    freeaddrinfo(local);
+    freeaddrinfo(peer);
+    return sock;
+
+err:
+    if (-1 != sock)
+        closesocket(sock);
+    if (local)
+        freeaddrinfo(local);
+    if (peer)
+        freeaddrinfo(peer);
+    return -1;
+}
+
 /* compatibility wrapper */
 static int inet_parse(QemuOpts *opts, const char *str)
 {
@@ -310,7 +425,7 @@ static int inet_parse(QemuOpts *opts, const char *str)
                     __FUNCTION__, str);
             return -1;
         }
-        qemu_opt_set(opts, "ipv6", "yes");
+        qemu_opt_set(opts, "ipv6", "on");
     } else if (qemu_isdigit(str[0])) {
         /* IPv4 addr */
         if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
@@ -318,7 +433,7 @@ static int inet_parse(QemuOpts *opts, const char *str)
                     __FUNCTION__, str);
             return -1;
         }
-        qemu_opt_set(opts, "ipv4", "yes");
+        qemu_opt_set(opts, "ipv4", "on");
     } else {
         /* hostname */
         if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
@@ -336,9 +451,9 @@ static int inet_parse(QemuOpts *opts, const char *str)
     if (h)
         qemu_opt_set(opts, "to", h+4);
     if (strstr(optstr, ",ipv4"))
-        qemu_opt_set(opts, "ipv4", "yes");
+        qemu_opt_set(opts, "ipv4", "on");
     if (strstr(optstr, ",ipv6"))
-        qemu_opt_set(opts, "ipv6", "yes");
+        qemu_opt_set(opts, "ipv6", "on");
     return 0;
 }
 
@@ -391,7 +506,7 @@ int unix_listen_opts(QemuOpts *opts)
     const char *path = qemu_opt_get(opts, "path");
     int sock, fd;
 
-    sock = socket(PF_UNIX, SOCK_STREAM, 0);
+    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
     if (sock < 0) {
         perror("socket(unix)");
         return -1;
@@ -446,7 +561,7 @@ int unix_connect_opts(QemuOpts *opts)
         return -1;
     }
 
-    sock = socket(PF_UNIX, SOCK_STREAM, 0);
+    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
     if (sock < 0) {
         perror("socket(unix)");
         return -1;
@@ -534,3 +649,27 @@ int unix_connect(const char *path)
 }
 
 #endif
+
+#ifdef _WIN32
+static void socket_cleanup(void)
+{
+    WSACleanup();
+}
+#endif
+
+int socket_init(void)
+{
+#ifdef _WIN32
+    WSADATA Data;
+    int ret, err;
+
+    ret = WSAStartup(MAKEWORD(2,2), &Data);
+    if (ret != 0) {
+        err = WSAGetLastError();
+        fprintf(stderr, "WSAStartup: %d\n", err);
+        return -1;
+    }
+    atexit(socket_cleanup);
+#endif
+    return 0;
+}