/* Active and passive stream classes. */
extern const struct stream_class tcp_stream_class;
extern const struct pstream_class ptcp_pstream_class;
+#ifndef _WIN32
extern const struct stream_class unix_stream_class;
extern const struct pstream_class punix_pstream_class;
+#else
+extern const struct stream_class windows_stream_class;
+extern const struct pstream_class pwindows_pstream_class;
+#endif
#ifdef HAVE_OPENSSL
extern const struct stream_class ssl_stream_class;
extern const struct pstream_class pssl_pstream_class;
NULL, /* run_wait */
NULL, /* wait */
};
+
+#ifdef _WIN32
+static int
+windows_open(const char *name, char *suffix, struct stream **streamp,
+ uint8_t dscp)
+{
+ int error, port;
+ FILE *file;
+ char *suffix_new, *path;
+
+ /* If the path does not contain a ':', assume it is relative to
+ * OVS_RUNDIR. */
+ if (!strchr(suffix, ':')) {
+ path = xasprintf("%s/%s", ovs_rundir(), suffix);
+ } else {
+ path = strdup(suffix);
+ }
+
+ file = fopen(path, "r");
+ if (!file) {
+ error = errno;
+ VLOG_DBG("%s: could not open %s (%s)", name, suffix,
+ ovs_strerror(error));
+ return error;
+ }
+
+ error = fscanf(file, "%d", &port);
+ if (error != 1) {
+ VLOG_ERR("failed to read port from %s", suffix);
+ fclose(file);
+ return EINVAL;
+ }
+ fclose(file);
+
+ suffix_new = xasprintf("127.0.0.1:%d", port);
+
+ error = tcp_open(name, suffix_new, streamp, dscp);
+
+ free(suffix_new);
+ free(path);
+ return error;
+}
+
+const struct stream_class windows_stream_class = {
+ "unix", /* name */
+ false, /* needs_probes */
+ windows_open, /* open */
+ NULL, /* close */
+ NULL, /* connect */
+ NULL, /* recv */
+ NULL, /* send */
+ NULL, /* run */
+ NULL, /* run_wait */
+ NULL, /* wait */
+};
+#endif
\f
/* Passive TCP. */
NULL,
};
+#ifdef _WIN32
+static int
+pwindows_open(const char *name OVS_UNUSED, char *suffix,
+ struct pstream **pstreamp, uint8_t dscp)
+{
+ int error;
+ char *suffix_new, *path;
+ FILE *file;
+ struct pstream *listener;
+
+ suffix_new = xstrdup("0:127.0.0.1");
+ error = ptcp_open(name, suffix_new, pstreamp, dscp);
+ if (error) {
+ goto exit;
+ }
+ listener = *pstreamp;
+
+ /* If the path does not contain a ':', assume it is relative to
+ * OVS_RUNDIR. */
+ if (!strchr(suffix, ':')) {
+ path = xasprintf("%s/%s", ovs_rundir(), suffix);
+ } else {
+ path = strdup(suffix);
+ }
+
+ file = fopen(path, "w");
+ if (!file) {
+ error = errno;
+ VLOG_DBG("could not open %s (%s)", path, ovs_strerror(error));
+ goto exit;
+ }
+
+ fprintf(file, "%d\n", ntohs(listener->bound_port));
+ if (fflush(file) == EOF) {
+ error = EIO;
+ VLOG_ERR("write failed for %s", path);
+ fclose(file);
+ goto exit;
+ }
+ fclose(file);
+ free(path);
+
+exit:
+ free(suffix_new);
+ return error;
+}
+
+const struct pstream_class pwindows_pstream_class = {
+ "punix",
+ false,
+ pwindows_open,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+#endif
&tcp_stream_class,
#ifndef _WIN32
&unix_stream_class,
+#else
+ &windows_stream_class,
#endif
#ifdef HAVE_OPENSSL
&ssl_stream_class,
&ptcp_pstream_class,
#ifndef _WIN32
&punix_pstream_class,
+#else
+ &pwindows_pstream_class,
#endif
#ifdef HAVE_OPENSSL
&pssl_pstream_class,
{
struct unixctl_server *server;
struct pstream *listener;
- char *punix_path, *abs_path = NULL;
+ char *punix_path;
int error;
-#ifdef _WIN32
- FILE *file;
-#endif
*serverp = NULL;
if (path && !strcmp(path, "none")) {
return 0;
}
-#ifndef _WIN32
if (path) {
+ char *abs_path;
+#ifndef _WIN32
abs_path = abs_file_name(ovs_rundir(), path);
+#else
+ abs_path = strdup(path);
+#endif
punix_path = xasprintf("punix:%s", abs_path);
+ free(abs_path);
} else {
+#ifndef _WIN32
punix_path = xasprintf("punix:%s/%s.%ld.ctl", ovs_rundir(),
program_name, (long int) getpid());
- }
#else
- punix_path = xstrdup("ptcp:0:127.0.0.1");
+ punix_path = xasprintf("punix:%s/%s.ctl", ovs_rundir(), program_name);
#endif
+ }
error = pstream_open(punix_path, &listener, 0);
if (error) {
goto exit;
}
-#ifdef _WIN32
- if (path) {
- abs_path = xstrdup(path);
- } else {
- abs_path = xasprintf("%s/%s.ctl", ovs_rundir(), program_name);
- }
-
- file = fopen(abs_path, "w");
- if (!file) {
- error = errno;
- ovs_error(error, "could not open %s", abs_path);
- goto exit;
- }
-
- fprintf(file, "%d\n", ntohs(listener->bound_port));
- if (fflush(file) == EOF) {
- error = EIO;
- ovs_error(error, "write failed for %s", abs_path);
- fclose(file);
- goto exit;
- }
- fclose(file);
-#endif
-
unixctl_command_register("help", "", 0, 0, unixctl_help, NULL);
unixctl_command_register("version", "", 0, 0, unixctl_version, NULL);
*serverp = server;
exit:
- if (abs_path) {
- free(abs_path);
- }
free(punix_path);
return error;
}
char *abs_path, *unix_path;
struct stream *stream;
int error;
-#ifdef _WIN32
- FILE *file;
- int port;
+#ifdef _WIN32
abs_path = strdup(path);
- file = fopen(abs_path, "r");
- if (!file) {
- int error = errno;
- ovs_error(error, "could not open %s", abs_path);
- free(abs_path);
- return error;
- }
-
- error = fscanf(file, "%d", &port);
- if (error != 1) {
- ovs_error(errno, "failed to read port from %s", abs_path);
- free(abs_path);
- return EINVAL;
- }
- fclose(file);
-
- unix_path = xasprintf("tcp:127.0.0.1:%d", port);
#else
abs_path = abs_file_name(ovs_rundir(), path);
- unix_path = xasprintf("unix:%s", abs_path);
#endif
+ unix_path = xasprintf("unix:%s", abs_path);
*client = NULL;
value.
.TP
\fBunix:\fIfile\fR
-The Unix domain server socket named \fIfile\fR.
+On POSIX, a Unix domain server socket named \fIfile\fR.
+.IP
+On Windows, a localhost TCP port written in \fIfile\fR.
square brackets, e.g.: \fBtcp:[::1]:6632\fR.
.
.IP "\fBunix:\fIfile\fR"
-Connect to the Unix domain server socket named \fIfile\fR.
+On POSIX, connect to the Unix domain server socket named \fIfile\fR.
+.IP
+On Windows, connect to a localhost TCP port whose value is written in
+\fIfile\fR.
\fBptcp:6632:[::1]\fR.
.
.IP "\fBpunix:\fIfile\fR"
-Listen on the Unix domain server socket named \fIfile\fR for a
+On POSIX, listen on the Unix domain server socket named \fIfile\fR for a
connection.
+.IP
+On Windows, listen on a kernel chosen TCP port on the localhost. The kernel
+chosen TCP port value is written in \fIfile\fR.