]> git.proxmox.com Git - mirror_ovs.git/blame - lib/stream-tcp.c
lib: Expose struct ovs_list definition in <openvswitch/list.h>
[mirror_ovs.git] / lib / stream-tcp.c
CommitLineData
c34b65c7 1/*
e731d71b 2 * Copyright (c) 2008, 2009, 2010, 2012, 2013, 2014 Nicira, Inc.
c34b65c7
BP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <config.h>
18#include "stream.h"
19#include <errno.h>
20#include <inttypes.h>
21#include <sys/types.h>
22#include <netinet/in.h>
e731d71b 23#include <netdb.h>
c34b65c7
BP
24#include <stdlib.h>
25#include <string.h>
3762274e 26#include <sys/socket.h>
c34b65c7 27#include <unistd.h>
e731d71b 28#include "dynamic-string.h"
c34b65c7
BP
29#include "packets.h"
30#include "socket-util.h"
31#include "util.h"
32#include "stream-provider.h"
33#include "stream-fd.h"
c34b65c7 34#include "vlog.h"
5136ce49 35
d98e6007 36VLOG_DEFINE_THIS_MODULE(stream_tcp);
c34b65c7
BP
37
38/* Active TCP. */
39
40static int
41new_tcp_stream(const char *name, int fd, int connect_status,
a8d81967 42 struct stream **streamp)
c34b65c7 43{
b7cefbf7
GS
44 if (connect_status == 0) {
45 setsockopt_tcp_nodelay(fd);
c34b65c7
BP
46 }
47
b7cefbf7 48 return new_fd_stream(name, fd, connect_status, AF_INET, streamp);
c34b65c7
BP
49}
50
51static int
f125905c 52tcp_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp)
c34b65c7 53{
c34b65c7
BP
54 int fd, error;
55
a8d81967 56 error = inet_open_active(SOCK_STREAM, suffix, 0, NULL, &fd, dscp);
c34b65c7 57 if (fd >= 0) {
a8d81967 58 return new_tcp_stream(name, fd, error, streamp);
c34b65c7 59 } else {
10a89ef0 60 VLOG_ERR("%s: connect: %s", name, ovs_strerror(error));
c34b65c7
BP
61 return error;
62 }
63}
64
da327b18 65const struct stream_class tcp_stream_class = {
c34b65c7 66 "tcp", /* name */
f1936eb6 67 true, /* needs_probes */
c34b65c7
BP
68 tcp_open, /* open */
69 NULL, /* close */
70 NULL, /* connect */
71 NULL, /* recv */
72 NULL, /* send */
539e96f6
BP
73 NULL, /* run */
74 NULL, /* run_wait */
c34b65c7
BP
75 NULL, /* wait */
76};
e3f512b0
GS
77
78#ifdef _WIN32
79static int
80windows_open(const char *name, char *suffix, struct stream **streamp,
81 uint8_t dscp)
82{
83 int error, port;
84 FILE *file;
85 char *suffix_new, *path;
86
87 /* If the path does not contain a ':', assume it is relative to
88 * OVS_RUNDIR. */
89 if (!strchr(suffix, ':')) {
90 path = xasprintf("%s/%s", ovs_rundir(), suffix);
91 } else {
13a233f7 92 path = xstrdup(suffix);
e3f512b0
GS
93 }
94
95 file = fopen(path, "r");
96 if (!file) {
97 error = errno;
98 VLOG_DBG("%s: could not open %s (%s)", name, suffix,
99 ovs_strerror(error));
100 return error;
101 }
102
103 error = fscanf(file, "%d", &port);
104 if (error != 1) {
105 VLOG_ERR("failed to read port from %s", suffix);
106 fclose(file);
107 return EINVAL;
108 }
109 fclose(file);
110
111 suffix_new = xasprintf("127.0.0.1:%d", port);
112
113 error = tcp_open(name, suffix_new, streamp, dscp);
114
115 free(suffix_new);
116 free(path);
117 return error;
118}
119
120const struct stream_class windows_stream_class = {
121 "unix", /* name */
122 false, /* needs_probes */
123 windows_open, /* open */
124 NULL, /* close */
125 NULL, /* connect */
126 NULL, /* recv */
127 NULL, /* send */
128 NULL, /* run */
129 NULL, /* run_wait */
130 NULL, /* wait */
131};
132#endif
c34b65c7
BP
133\f
134/* Passive TCP. */
135
e731d71b
AS
136static int ptcp_accept(int fd, const struct sockaddr_storage *,
137 size_t, struct stream **streamp);
c34b65c7
BP
138
139static int
01420a2c
GS
140new_pstream(char *suffix, const char *name, struct pstream **pstreamp,
141 int dscp, char *unlink_path, bool kernel_print_port)
c34b65c7 142{
e731d71b
AS
143 char bound_name[SS_NTOP_BUFSIZE + 16];
144 char addrbuf[SS_NTOP_BUFSIZE];
145 struct sockaddr_storage ss;
798e1352 146 int error;
b52ecd96 147 uint16_t port;
c34b65c7 148 int fd;
01420a2c 149 char *conn_name = CONST_CAST(char *, name);
c34b65c7 150
b52ecd96
GS
151 fd = inet_open_passive(SOCK_STREAM, suffix, -1, &ss, dscp,
152 kernel_print_port);
c34b65c7
BP
153 if (fd < 0) {
154 return -fd;
c34b65c7 155 }
42967038 156
e731d71b 157 port = ss_get_port(&ss);
01420a2c
GS
158 if (!conn_name) {
159 snprintf(bound_name, sizeof bound_name, "ptcp:%"PRIu16":%s",
160 port, ss_format_address(&ss, addrbuf, sizeof addrbuf));
161 conn_name = bound_name;
162 }
e731d71b 163
01420a2c 164 error = new_fd_pstream(conn_name, fd, ptcp_accept, set_dscp, unlink_path,
798e1352
BP
165 pstreamp);
166 if (!error) {
e731d71b 167 pstream_set_bound_port(*pstreamp, htons(port));
798e1352
BP
168 }
169 return error;
c34b65c7
BP
170}
171
b52ecd96
GS
172static int
173ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
174 uint8_t dscp)
175{
01420a2c 176 return new_pstream(suffix, NULL, pstreamp, dscp, NULL, true);
b52ecd96
GS
177}
178
c34b65c7 179static int
e731d71b
AS
180ptcp_accept(int fd, const struct sockaddr_storage *ss,
181 size_t ss_len OVS_UNUSED, struct stream **streamp)
c34b65c7 182{
e731d71b
AS
183 char name[SS_NTOP_BUFSIZE + 16];
184 char addrbuf[SS_NTOP_BUFSIZE];
c34b65c7 185
e731d71b
AS
186 snprintf(name, sizeof name, "tcp:%s:%"PRIu16,
187 ss_format_address(ss, addrbuf, sizeof addrbuf),
188 ss_get_port(ss));
a8d81967 189 return new_tcp_stream(name, fd, 0, streamp);
c34b65c7
BP
190}
191
da327b18 192const struct pstream_class ptcp_pstream_class = {
c34b65c7 193 "ptcp",
f1936eb6 194 true,
c34b65c7
BP
195 ptcp_open,
196 NULL,
197 NULL,
f89b7ce5
IY
198 NULL,
199 NULL,
c34b65c7
BP
200};
201
e3f512b0
GS
202#ifdef _WIN32
203static int
01420a2c
GS
204pwindows_open(const char *name, char *suffix, struct pstream **pstreamp,
205 uint8_t dscp)
e3f512b0
GS
206{
207 int error;
208 char *suffix_new, *path;
209 FILE *file;
210 struct pstream *listener;
211
212 suffix_new = xstrdup("0:127.0.0.1");
b52ecd96 213
e3f512b0
GS
214 /* If the path does not contain a ':', assume it is relative to
215 * OVS_RUNDIR. */
216 if (!strchr(suffix, ':')) {
217 path = xasprintf("%s/%s", ovs_rundir(), suffix);
218 } else {
13a233f7 219 path = xstrdup(suffix);
e3f512b0
GS
220 }
221
01420a2c 222 error = new_pstream(suffix_new, name, pstreamp, dscp, path, false);
3021f5af
GS
223 if (error) {
224 goto exit;
225 }
226 listener = *pstreamp;
227
e3f512b0
GS
228 file = fopen(path, "w");
229 if (!file) {
230 error = errno;
231 VLOG_DBG("could not open %s (%s)", path, ovs_strerror(error));
232 goto exit;
233 }
234
235 fprintf(file, "%d\n", ntohs(listener->bound_port));
236 if (fflush(file) == EOF) {
237 error = EIO;
238 VLOG_ERR("write failed for %s", path);
239 fclose(file);
240 goto exit;
241 }
242 fclose(file);
e3f512b0
GS
243
244exit:
245 free(suffix_new);
246 return error;
247}
248
249const struct pstream_class pwindows_pstream_class = {
250 "punix",
251 false,
252 pwindows_open,
253 NULL,
254 NULL,
255 NULL,
256 NULL,
257};
258#endif