# define AI_ADDRCONFIG 0
#endif
-static int sockets_debug = 0;
static const int on=1, off=0;
/* used temporarely until all users are converted to QemuOpts */
}
}
-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 "????";
-}
-
-static void inet_print_addrinfo(const char *tag, struct addrinfo *res)
-{
- struct addrinfo *e;
- char uaddr[INET6_ADDRSTRLEN+1];
- char uport[33];
-
- for (e = res; e != NULL; e = e->ai_next) {
- getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
- uaddr,INET6_ADDRSTRLEN,uport,32,
- NI_NUMERICHOST | NI_NUMERICSERV);
- fprintf(stderr,"%s: getaddrinfo: family %s, host %s, port %s\n",
- tag, inet_strfamily(e->ai_family), uaddr, uport);
- }
+ return "unknown";
}
int inet_listen_opts(QemuOpts *opts, int port_offset)
char port[33];
char uaddr[INET6_ADDRSTRLEN+1];
char uport[33];
- int slisten,rc,to,try_next;
+ int slisten, rc, to, port_min, port_max, p;
memset(&ai,0, sizeof(ai));
ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
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;
}
gai_strerror(rc));
return -1;
}
- if (sockets_debug)
- inet_print_addrinfo(__FUNCTION__, res);
/* create socket + bind */
for (e = res; e != NULL; e = e->ai_next) {
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));
}
#endif
- for (;;) {
+ port_min = inet_getport(e);
+ port_max = to ? to + port_offset : port_min;
+ for (p = port_min; p <= port_max; p++) {
+ inet_setport(e, p);
if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
- if (sockets_debug)
- fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
- inet_strfamily(e->ai_family), uaddr, inet_getport(e));
goto listen;
}
- try_next = to && (inet_getport(e) <= to + port_offset);
- if (!try_next || sockets_debug)
+ if (p == port_max) {
fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
inet_strfamily(e->ai_family), uaddr, inet_getport(e),
strerror(errno));
- if (try_next) {
- inet_setport(e, inet_getport(e) + 1);
- continue;
}
- break;
}
closesocket(slisten);
}
gai_strerror(rc));
return -1;
}
- if (sockets_debug)
- inet_print_addrinfo(__FUNCTION__, res);
for (e = res; e != NULL; e = e->ai_next) {
if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
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));
/* connect to peer */
if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {
- if (sockets_debug || NULL == e->ai_next)
+ if (NULL == e->ai_next)
fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
inet_strfamily(e->ai_family),
e->ai_canonname, uaddr, uport, strerror(errno));
closesocket(sock);
continue;
}
- if (sockets_debug)
- fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
- inet_strfamily(e->ai_family),
- e->ai_canonname, uaddr, uport);
freeaddrinfo(res);
return sock;
}
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));
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 = socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
+ 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));
__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)) {
__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)) {
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;
}
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;
goto err;
}
- if (sockets_debug)
- fprintf(stderr, "bind(unix:%s): OK\n", un.sun_path);
return sock;
err:
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;
snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
+ close(sock);
return -1;
}
- if (sockets_debug)
- fprintf(stderr, "connect(unix:%s): OK\n", path);
return sock;
}
if (optstr) {
len = optstr - str;
if (len) {
- path = qemu_malloc(len+1);
+ path = g_malloc(len+1);
snprintf(path, len+1, "%.*s", len, str);
qemu_opt_set(opts, "path", path);
- qemu_free(path);
+ g_free(path);
}
} else {
qemu_opt_set(opts, "path", str);
int unix_listen_opts(QemuOpts *opts)
{
fprintf(stderr, "unix sockets are not available on windows\n");
+ errno = ENOTSUP;
return -1;
}
int unix_connect_opts(QemuOpts *opts)
{
fprintf(stderr, "unix sockets are not available on windows\n");
+ errno = ENOTSUP;
return -1;
}
int unix_listen(const char *path, char *ostr, int olen)
{
fprintf(stderr, "unix sockets are not available on windows\n");
+ errno = ENOTSUP;
return -1;
}
int unix_connect(const char *path)
{
fprintf(stderr, "unix sockets are not available on windows\n");
+ errno = ENOTSUP;
return -1;
}
#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;
+}