2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
47 #include <string.h> /* strchr */
49 #include <vppinfra/mem.h>
50 #include <vppinfra/vec.h>
51 #include <vppinfra/socket.h>
52 #include <vppinfra/format.h>
53 #include <vppinfra/error.h>
55 void clib_socket_tx_add_formatted (clib_socket_t * s, char * fmt, ...)
59 clib_socket_tx_add_va_formatted (s, fmt, &va);
63 /* Return and bind to an unused port. */
64 static word find_free_port (word sock)
68 for (port = IPPORT_USERRESERVED; port < 1 << 16; port++)
72 memset(&a, 0, sizeof (a)); /* Warnings be gone */
74 a.sin_family = PF_INET;
75 a.sin_addr.s_addr = INADDR_ANY;
76 a.sin_port = htons (port);
78 if (bind (sock, (struct sockaddr *) &a, sizeof (a)) >= 0)
82 return port < 1 << 16 ? port : -1;
85 /* Convert a config string to a struct sockaddr and length for use
86 with bind or connect. */
88 socket_config (char * config,
91 u32 ip4_default_address)
93 clib_error_t * error = 0;
98 /* Anything that begins with a / is a local PF_LOCAL socket. */
101 struct sockaddr_un * su = addr;
102 su->sun_family = PF_LOCAL;
103 clib_memcpy (&su->sun_path, config,
104 clib_min (sizeof (su->sun_path), 1 + strlen (config)));
105 *addr_len = sizeof (su[0]);
108 /* Hostname or hostname:port or port. */
113 struct sockaddr_in * sa = addr;
121 unformat_init_string (&i, config, strlen (config));
122 if (unformat (&i, "%s:%d", &host_name, &port)
123 || unformat (&i, "%s:0x%x", &host_name, &port))
125 else if (unformat (&i, "%s", &host_name))
128 error = clib_error_return (0, "unknown input `%U'",
129 format_unformat_error, &i);
136 sa->sin_family = PF_INET;
137 *addr_len = sizeof (sa[0]);
139 sa->sin_port = htons (port);
145 struct in_addr host_addr;
147 /* Recognize localhost to avoid host lookup in most common cast. */
148 if (! strcmp (host_name, "localhost"))
149 sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
151 else if (inet_aton (host_name, &host_addr))
152 sa->sin_addr = host_addr;
154 else if (host_name && strlen (host_name) > 0)
156 struct hostent * host = gethostbyname (host_name);
158 error = clib_error_return (0, "unknown host `%s'", config);
160 clib_memcpy (&sa->sin_addr.s_addr, host->h_addr_list[0], host->h_length);
164 sa->sin_addr.s_addr = htonl (ip4_default_address);
166 vec_free (host_name);
176 static clib_error_t *
177 default_socket_write (clib_socket_t * s)
179 clib_error_t * err = 0;
186 /* Map standard input to standard output.
187 Typically, fd is a socket for which read/write both work. */
191 tx_len = vec_len (s->tx_buffer);
192 written = write (fd, s->tx_buffer, tx_len);
194 /* Ignore certain errors. */
195 if (written < 0 && ! unix_error_is_fatal (errno))
198 /* A "real" error occurred. */
201 err = clib_error_return_unix (0, "write %wd bytes", tx_len);
202 vec_free (s->tx_buffer);
206 /* Reclaim the transmitted part of the tx buffer on successful writes. */
207 else if (written > 0)
209 if (written == tx_len)
210 _vec_len (s->tx_buffer) = 0;
212 vec_delete (s->tx_buffer, written, 0);
215 /* If a non-fatal error occurred AND
216 the buffer is full, then we must free it. */
217 else if (written == 0 && tx_len > 64*1024)
219 vec_free (s->tx_buffer);
226 static clib_error_t *
227 default_socket_read (clib_socket_t * sock, int n_bytes)
232 /* RX side of socket is down once end of file is reached. */
233 if (sock->flags & SOCKET_RX_END_OF_FILE)
238 n_bytes = clib_max (n_bytes, 4096);
239 vec_add2 (sock->rx_buffer, buf, n_bytes);
241 if ((n_read = read (fd, buf, n_bytes)) < 0)
245 /* Ignore certain errors. */
246 if (! unix_error_is_fatal (errno))
249 return clib_error_return_unix (0, "read %d bytes", n_bytes);
252 /* Other side closed the socket. */
254 sock->flags |= SOCKET_RX_END_OF_FILE;
257 _vec_len (sock->rx_buffer) += n_read - n_bytes;
262 static clib_error_t * default_socket_close (clib_socket_t * s)
264 if (close (s->fd) < 0)
265 return clib_error_return_unix (0, "close");
269 static void socket_init_funcs (clib_socket_t * s)
272 s->write_func = default_socket_write;
274 s->read_func = default_socket_read;
276 s->close_func = default_socket_close;
280 clib_socket_init (clib_socket_t * s)
284 struct sockaddr_un su;
286 socklen_t addr_len = 0;
287 clib_error_t * error = 0;
290 error = socket_config (s->config, &addr.sa, &addr_len,
291 (s->flags & SOCKET_IS_SERVER
297 socket_init_funcs (s);
299 s->fd = socket (addr.sa.sa_family, SOCK_STREAM, 0);
302 error = clib_error_return_unix (0, "socket");
307 if (addr.sa.sa_family == PF_INET)
308 port = ((struct sockaddr_in *) &addr)->sin_port;
310 if (s->flags & SOCKET_IS_SERVER)
314 if (addr.sa.sa_family == PF_INET)
318 port = find_free_port (s->fd);
321 error = clib_error_return (0, "no free port");
327 if (addr.sa.sa_family == PF_LOCAL)
328 unlink (((struct sockaddr_un *) &addr)->sun_path);
330 /* Make address available for multiple users. */
333 if (setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof (v)) < 0)
334 clib_unix_warning ("setsockopt SO_REUSEADDR fails");
338 && bind (s->fd, &addr.sa, addr_len) < 0)
340 error = clib_error_return_unix (0, "bind");
344 if (listen (s->fd, 5) < 0)
346 error = clib_error_return_unix (0, "listen");
352 if ((s->flags & SOCKET_NON_BLOCKING_CONNECT)
353 && fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
355 error = clib_error_return_unix (0, "fcntl NONBLOCK");
359 if (connect (s->fd, &addr.sa, addr_len) < 0
360 && ! ((s->flags & SOCKET_NON_BLOCKING_CONNECT) &&
361 errno == EINPROGRESS))
363 error = clib_error_return_unix (0, "connect");
376 clib_error_t * clib_socket_accept (clib_socket_t * server, clib_socket_t * client)
378 clib_error_t * err = 0;
381 memset (client, 0, sizeof (client[0]));
383 /* Accept the new socket connection. */
384 client->fd = accept (server->fd, 0, 0);
386 return clib_error_return_unix (0, "accept");
388 /* Set the new socket to be non-blocking. */
389 if (fcntl (client->fd, F_SETFL, O_NONBLOCK) < 0)
391 err = clib_error_return_unix (0, "fcntl O_NONBLOCK");
396 len = sizeof (client->peer);
397 if (getpeername (client->fd, (struct sockaddr *) &client->peer, &len) < 0)
399 err = clib_error_return_unix (0, "getpeername");
403 client->flags = SOCKET_IS_CLIENT;
405 socket_init_funcs (client);