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>
56 clib_socket_tx_add_formatted (clib_socket_t * s, char *fmt, ...)
60 clib_socket_tx_add_va_formatted (s, fmt, &va);
64 /* Return and bind to an unused port. */
66 find_free_port (word sock)
70 for (port = IPPORT_USERRESERVED; port < 1 << 16; port++)
74 memset (&a, 0, sizeof (a)); /* Warnings be gone */
76 a.sin_family = PF_INET;
77 a.sin_addr.s_addr = INADDR_ANY;
78 a.sin_port = htons (port);
80 if (bind (sock, (struct sockaddr *) &a, sizeof (a)) >= 0)
84 return port < 1 << 16 ? port : -1;
87 /* Convert a config string to a struct sockaddr and length for use
88 with bind or connect. */
90 socket_config (char *config,
91 void *addr, socklen_t * addr_len, 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],
165 sa->sin_addr.s_addr = htonl (ip4_default_address);
167 vec_free (host_name);
177 static clib_error_t *
178 default_socket_write (clib_socket_t * s)
180 clib_error_t *err = 0;
187 /* Map standard input to standard output.
188 Typically, fd is a socket for which read/write both work. */
192 tx_len = vec_len (s->tx_buffer);
193 written = write (fd, s->tx_buffer, tx_len);
195 /* Ignore certain errors. */
196 if (written < 0 && !unix_error_is_fatal (errno))
199 /* A "real" error occurred. */
202 err = clib_error_return_unix (0, "write %wd bytes", tx_len);
203 vec_free (s->tx_buffer);
207 /* Reclaim the transmitted part of the tx buffer on successful writes. */
208 else if (written > 0)
210 if (written == tx_len)
211 _vec_len (s->tx_buffer) = 0;
213 vec_delete (s->tx_buffer, written, 0);
216 /* If a non-fatal error occurred AND
217 the buffer is full, then we must free it. */
218 else if (written == 0 && tx_len > 64 * 1024)
220 vec_free (s->tx_buffer);
227 static clib_error_t *
228 default_socket_read (clib_socket_t * sock, int n_bytes)
233 /* RX side of socket is down once end of file is reached. */
234 if (sock->flags & SOCKET_RX_END_OF_FILE)
239 n_bytes = clib_max (n_bytes, 4096);
240 vec_add2 (sock->rx_buffer, buf, n_bytes);
242 if ((n_read = read (fd, buf, n_bytes)) < 0)
246 /* Ignore certain errors. */
247 if (!unix_error_is_fatal (errno))
250 return clib_error_return_unix (0, "read %d bytes", n_bytes);
253 /* Other side closed the socket. */
255 sock->flags |= SOCKET_RX_END_OF_FILE;
258 _vec_len (sock->rx_buffer) += n_read - n_bytes;
263 static clib_error_t *
264 default_socket_close (clib_socket_t * s)
266 if (close (s->fd) < 0)
267 return clib_error_return_unix (0, "close");
272 socket_init_funcs (clib_socket_t * s)
275 s->write_func = default_socket_write;
277 s->read_func = default_socket_read;
279 s->close_func = default_socket_close;
283 clib_socket_init (clib_socket_t * s)
288 struct sockaddr_un su;
290 socklen_t addr_len = 0;
291 clib_error_t *error = 0;
294 error = socket_config (s->config, &addr.sa, &addr_len,
295 (s->flags & SOCKET_IS_SERVER
296 ? INADDR_LOOPBACK : INADDR_ANY));
300 socket_init_funcs (s);
302 s->fd = socket (addr.sa.sa_family, SOCK_STREAM, 0);
305 error = clib_error_return_unix (0, "socket");
310 if (addr.sa.sa_family == PF_INET)
311 port = ((struct sockaddr_in *) &addr)->sin_port;
313 if (s->flags & SOCKET_IS_SERVER)
317 if (addr.sa.sa_family == PF_INET)
321 port = find_free_port (s->fd);
324 error = clib_error_return (0, "no free port");
330 if (addr.sa.sa_family == PF_LOCAL)
331 unlink (((struct sockaddr_un *) &addr)->sun_path);
333 /* Make address available for multiple users. */
336 if (setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof (v)) < 0)
337 clib_unix_warning ("setsockopt SO_REUSEADDR fails");
340 if (need_bind && bind (s->fd, &addr.sa, addr_len) < 0)
342 error = clib_error_return_unix (0, "bind");
346 if (listen (s->fd, 5) < 0)
348 error = clib_error_return_unix (0, "listen");
354 if ((s->flags & SOCKET_NON_BLOCKING_CONNECT)
355 && fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
357 error = clib_error_return_unix (0, "fcntl NONBLOCK");
361 if (connect (s->fd, &addr.sa, addr_len) < 0
362 && !((s->flags & SOCKET_NON_BLOCKING_CONNECT) &&
363 errno == EINPROGRESS))
365 error = clib_error_return_unix (0, "connect");
379 clib_socket_accept (clib_socket_t * server, clib_socket_t * client)
381 clib_error_t *err = 0;
384 memset (client, 0, sizeof (client[0]));
386 /* Accept the new socket connection. */
387 client->fd = accept (server->fd, 0, 0);
389 return clib_error_return_unix (0, "accept");
391 /* Set the new socket to be non-blocking. */
392 if (fcntl (client->fd, F_SETFL, O_NONBLOCK) < 0)
394 err = clib_error_return_unix (0, "fcntl O_NONBLOCK");
399 len = sizeof (client->peer);
400 if (getpeername (client->fd, (struct sockaddr *) &client->peer, &len) < 0)
402 err = clib_error_return_unix (0, "getpeername");
406 client->flags = SOCKET_IS_CLIENT;
408 socket_init_funcs (client);
417 * fd.io coding-style-patch-verification: ON
420 * eval: (c-set-style "gnu")