netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / lib / stream-tcp.c
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2012, 2013, 2014, 2015 Nicira, Inc.
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>
23 #include <netdb.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/socket.h>
27 #include <unistd.h>
28 #include "dynamic-string.h"
29 #include "packets.h"
30 #include "socket-util.h"
31 #include "util.h"
32 #include "stream-provider.h"
33 #include "stream-fd.h"
34 #include "openvswitch/vlog.h"
35
36 VLOG_DEFINE_THIS_MODULE(stream_tcp);
37
38 /* Active TCP. */
39
40 static int
41 new_tcp_stream(const char *name, int fd, int connect_status,
42                struct stream **streamp)
43 {
44     if (connect_status == 0) {
45         setsockopt_tcp_nodelay(fd);
46     }
47
48     return new_fd_stream(name, fd, connect_status, AF_INET, streamp);
49 }
50
51 static int
52 tcp_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp)
53 {
54     int fd, error;
55
56     error = inet_open_active(SOCK_STREAM, suffix, 0, NULL, &fd, dscp);
57     if (fd >= 0) {
58         return new_tcp_stream(name, fd, error, streamp);
59     } else {
60         VLOG_ERR("%s: connect: %s", name, ovs_strerror(error));
61         return error;
62     }
63 }
64
65 const struct stream_class tcp_stream_class = {
66     "tcp",                      /* name */
67     true,                       /* needs_probes */
68     tcp_open,                   /* open */
69     NULL,                       /* close */
70     NULL,                       /* connect */
71     NULL,                       /* recv */
72     NULL,                       /* send */
73     NULL,                       /* run */
74     NULL,                       /* run_wait */
75     NULL,                       /* wait */
76 };
77
78 #ifdef _WIN32
79 #include "dirs.h"
80
81 static int
82 windows_open(const char *name, char *suffix, struct stream **streamp,
83              uint8_t dscp)
84 {
85     int error, port;
86     FILE *file;
87     char *suffix_new, *path;
88
89     /* If the path does not contain a ':', assume it is relative to
90      * OVS_RUNDIR. */
91     if (!strchr(suffix, ':')) {
92         path = xasprintf("%s/%s", ovs_rundir(), suffix);
93     } else {
94         path = xstrdup(suffix);
95     }
96
97     file = fopen(path, "r");
98     if (!file) {
99         error = errno;
100         VLOG_DBG("%s: could not open %s (%s)", name, suffix,
101                  ovs_strerror(error));
102         return error;
103     }
104
105     error = fscanf(file, "%d", &port);
106     if (error != 1) {
107         VLOG_ERR("failed to read port from %s", suffix);
108         fclose(file);
109         return EINVAL;
110     }
111     fclose(file);
112
113     suffix_new = xasprintf("127.0.0.1:%d", port);
114
115     error = tcp_open(name, suffix_new, streamp, dscp);
116
117     free(suffix_new);
118     free(path);
119     return error;
120 }
121
122 const struct stream_class windows_stream_class = {
123     "unix",                     /* name */
124     false,                      /* needs_probes */
125     windows_open,                  /* open */
126     NULL,                       /* close */
127     NULL,                       /* connect */
128     NULL,                       /* recv */
129     NULL,                       /* send */
130     NULL,                       /* run */
131     NULL,                       /* run_wait */
132     NULL,                       /* wait */
133 };
134 #endif
135 \f
136 /* Passive TCP. */
137
138 static int ptcp_accept(int fd, const struct sockaddr_storage *,
139                        size_t, struct stream **streamp);
140
141 static int
142 new_pstream(char *suffix, const char *name, struct pstream **pstreamp,
143             int dscp, char *unlink_path, bool kernel_print_port)
144 {
145     char bound_name[SS_NTOP_BUFSIZE + 16];
146     char addrbuf[SS_NTOP_BUFSIZE];
147     struct sockaddr_storage ss;
148     int error;
149     uint16_t port;
150     int fd;
151     char *conn_name = CONST_CAST(char *, name);
152
153     fd = inet_open_passive(SOCK_STREAM, suffix, -1, &ss, dscp,
154                            kernel_print_port);
155     if (fd < 0) {
156         return -fd;
157     }
158
159     port = ss_get_port(&ss);
160     if (!conn_name) {
161         snprintf(bound_name, sizeof bound_name, "ptcp:%"PRIu16":%s",
162                  port, ss_format_address(&ss, addrbuf, sizeof addrbuf));
163         conn_name = bound_name;
164     }
165
166     error = new_fd_pstream(conn_name, fd, ptcp_accept, unlink_path, pstreamp);
167     if (!error) {
168         pstream_set_bound_port(*pstreamp, htons(port));
169     }
170     return error;
171 }
172
173 static int
174 ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
175           uint8_t dscp)
176 {
177     return new_pstream(suffix, NULL, pstreamp, dscp, NULL, true);
178 }
179
180 static int
181 ptcp_accept(int fd, const struct sockaddr_storage *ss,
182             size_t ss_len OVS_UNUSED, struct stream **streamp)
183 {
184     char name[SS_NTOP_BUFSIZE + 16];
185     char addrbuf[SS_NTOP_BUFSIZE];
186
187     snprintf(name, sizeof name, "tcp:%s:%"PRIu16,
188              ss_format_address(ss, addrbuf, sizeof addrbuf),
189              ss_get_port(ss));
190     return new_tcp_stream(name, fd, 0, streamp);
191 }
192
193 const struct pstream_class ptcp_pstream_class = {
194     "ptcp",
195     true,
196     ptcp_open,
197     NULL,
198     NULL,
199     NULL,
200 };
201
202 #ifdef _WIN32
203 static int
204 pwindows_open(const char *name, char *suffix, struct pstream **pstreamp,
205               uint8_t dscp)
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");
213
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 {
219         path = xstrdup(suffix);
220     }
221
222     error = new_pstream(suffix_new, name, pstreamp, dscp, path, false);
223     if (error) {
224         goto exit;
225     }
226     listener = *pstreamp;
227
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);
243
244 exit:
245     free(suffix_new);
246     return error;
247 }
248
249 const struct pstream_class pwindows_pstream_class = {
250     "punix",
251     false,
252     pwindows_open,
253     NULL,
254     NULL,
255     NULL,
256 };
257 #endif