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 <string.h> /* strchr */
41 #include <sys/types.h>
42 #include <sys/socket.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
51 #include <vppinfra/mem.h>
52 #include <vppinfra/vec.h>
53 #include <vppinfra/socket.h>
54 #include <vppinfra/format.h>
55 #include <vppinfra/error.h>
58 clib_socket_tx_add_formatted (clib_socket_t * s, char *fmt, ...)
62 clib_socket_tx_add_va_formatted (s, fmt, &va);
66 /* Return and bind to an unused port. */
68 find_free_port (word sock)
72 for (port = IPPORT_USERRESERVED; port < 1 << 16; port++)
76 memset (&a, 0, sizeof (a)); /* Warnings be gone */
78 a.sin_family = PF_INET;
79 a.sin_addr.s_addr = INADDR_ANY;
80 a.sin_port = htons (port);
82 if (bind (sock, (struct sockaddr *) &a, sizeof (a)) >= 0)
86 return port < 1 << 16 ? port : -1;
89 /* Convert a config string to a struct sockaddr and length for use
90 with bind or connect. */
92 socket_config (char *config,
93 void *addr, socklen_t * addr_len, u32 ip4_default_address)
95 clib_error_t *error = 0;
100 /* Anything that begins with a / is a local PF_LOCAL socket. */
101 if (config[0] == '/')
103 struct sockaddr_un *su = addr;
104 su->sun_family = PF_LOCAL;
105 clib_memcpy (&su->sun_path, config,
106 clib_min (sizeof (su->sun_path), 1 + strlen (config)));
107 *addr_len = sizeof (su[0]);
110 /* Hostname or hostname:port or port. */
115 struct sockaddr_in *sa = addr;
123 unformat_init_string (&i, config, strlen (config));
124 if (unformat (&i, "%s:%d", &host_name, &port)
125 || unformat (&i, "%s:0x%x", &host_name, &port))
127 else if (unformat (&i, "%s", &host_name))
130 error = clib_error_return (0, "unknown input `%U'",
131 format_unformat_error, &i);
138 sa->sin_family = PF_INET;
139 *addr_len = sizeof (sa[0]);
141 sa->sin_port = htons (port);
147 struct in_addr host_addr;
149 /* Recognize localhost to avoid host lookup in most common cast. */
150 if (!strcmp (host_name, "localhost"))
151 sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
153 else if (inet_aton (host_name, &host_addr))
154 sa->sin_addr = host_addr;
156 else if (host_name && strlen (host_name) > 0)
158 struct hostent *host = gethostbyname (host_name);
160 error = clib_error_return (0, "unknown host `%s'", config);
162 clib_memcpy (&sa->sin_addr.s_addr, host->h_addr_list[0],
167 sa->sin_addr.s_addr = htonl (ip4_default_address);
169 vec_free (host_name);
179 static clib_error_t *
180 default_socket_write (clib_socket_t * s)
182 clib_error_t *err = 0;
189 /* Map standard input to standard output.
190 Typically, fd is a socket for which read/write both work. */
194 tx_len = vec_len (s->tx_buffer);
195 written = write (fd, s->tx_buffer, tx_len);
197 /* Ignore certain errors. */
198 if (written < 0 && !unix_error_is_fatal (errno))
201 /* A "real" error occurred. */
204 err = clib_error_return_unix (0, "write %wd bytes (fd %d, '%s')",
205 tx_len, s->fd, s->config);
206 vec_free (s->tx_buffer);
210 /* Reclaim the transmitted part of the tx buffer on successful writes. */
211 else if (written > 0)
213 if (written == tx_len)
214 _vec_len (s->tx_buffer) = 0;
216 vec_delete (s->tx_buffer, written, 0);
219 /* If a non-fatal error occurred AND
220 the buffer is full, then we must free it. */
221 else if (written == 0 && tx_len > 64 * 1024)
223 vec_free (s->tx_buffer);
230 static clib_error_t *
231 default_socket_read (clib_socket_t * sock, int n_bytes)
236 /* RX side of socket is down once end of file is reached. */
237 if (sock->flags & CLIB_SOCKET_F_RX_END_OF_FILE)
242 n_bytes = clib_max (n_bytes, 4096);
243 vec_add2 (sock->rx_buffer, buf, n_bytes);
245 if ((n_read = read (fd, buf, n_bytes)) < 0)
249 /* Ignore certain errors. */
250 if (!unix_error_is_fatal (errno))
253 return clib_error_return_unix (0, "read %d bytes (fd %d, '%s')",
254 n_bytes, sock->fd, sock->config);
257 /* Other side closed the socket. */
259 sock->flags |= CLIB_SOCKET_F_RX_END_OF_FILE;
262 _vec_len (sock->rx_buffer) += n_read - n_bytes;
267 static clib_error_t *
268 default_socket_close (clib_socket_t * s)
270 if (close (s->fd) < 0)
271 return clib_error_return_unix (0, "close (fd %d, %s)", s->fd, s->config);
275 static clib_error_t *
276 default_socket_sendmsg (clib_socket_t * s, void *msg, int msglen,
277 int fds[], int num_fds)
279 struct msghdr mh = { 0 };
281 char ctl[CMSG_SPACE (sizeof (int)) * num_fds];
284 iov[0].iov_base = msg;
285 iov[0].iov_len = msglen;
291 struct cmsghdr *cmsg;
292 memset (&ctl, 0, sizeof (ctl));
293 mh.msg_control = ctl;
294 mh.msg_controllen = sizeof (ctl);
295 cmsg = CMSG_FIRSTHDR (&mh);
296 cmsg->cmsg_len = CMSG_LEN (sizeof (int) * num_fds);
297 cmsg->cmsg_level = SOL_SOCKET;
298 cmsg->cmsg_type = SCM_RIGHTS;
299 memcpy (CMSG_DATA (cmsg), fds, sizeof (int) * num_fds);
301 rv = sendmsg (s->fd, &mh, 0);
303 return clib_error_return_unix (0, "sendmsg");
308 static clib_error_t *
309 default_socket_recvmsg (clib_socket_t * s, void *msg, int msglen,
310 int fds[], int num_fds)
312 char ctl[CMSG_SPACE (sizeof (int) * num_fds) +
313 CMSG_SPACE (sizeof (struct ucred))];
314 struct msghdr mh = { 0 };
317 struct ucred *cr = 0;
318 struct cmsghdr *cmsg;
320 iov[0].iov_base = msg;
321 iov[0].iov_len = msglen;
324 mh.msg_control = ctl;
325 mh.msg_controllen = sizeof (ctl);
327 memset (ctl, 0, sizeof (ctl));
329 /* receive the incoming message */
330 size = recvmsg (s->fd, &mh, 0);
333 return (size == 0) ? clib_error_return (0, "disconnected") :
334 clib_error_return_unix (0, "recvmsg: malformed message (fd %d, '%s')",
338 cmsg = CMSG_FIRSTHDR (&mh);
341 if (cmsg->cmsg_level == SOL_SOCKET)
343 if (cmsg->cmsg_type == SCM_CREDENTIALS)
345 cr = (struct ucred *) CMSG_DATA (cmsg);
350 else if (cmsg->cmsg_type == SCM_RIGHTS)
352 clib_memcpy (fds, CMSG_DATA (cmsg), num_fds * sizeof (int));
355 cmsg = CMSG_NXTHDR (&mh, cmsg);
361 socket_init_funcs (clib_socket_t * s)
364 s->write_func = default_socket_write;
366 s->read_func = default_socket_read;
368 s->close_func = default_socket_close;
369 if (!s->sendmsg_func)
370 s->sendmsg_func = default_socket_sendmsg;
371 if (!s->recvmsg_func)
372 s->recvmsg_func = default_socket_recvmsg;
376 clib_socket_init (clib_socket_t * s)
381 struct sockaddr_un su;
383 socklen_t addr_len = 0;
385 clib_error_t *error = 0;
388 error = socket_config (s->config, &addr.sa, &addr_len,
389 (s->flags & CLIB_SOCKET_F_IS_SERVER
390 ? INADDR_LOOPBACK : INADDR_ANY));
394 socket_init_funcs (s);
396 socket_type = s->flags & CLIB_SOCKET_F_SEQPACKET ?
397 SOCK_SEQPACKET : SOCK_STREAM;
399 s->fd = socket (addr.sa.sa_family, socket_type, 0);
402 error = clib_error_return_unix (0, "socket (fd %d, '%s')",
408 if (addr.sa.sa_family == PF_INET)
409 port = ((struct sockaddr_in *) &addr)->sin_port;
411 if (s->flags & CLIB_SOCKET_F_IS_SERVER)
415 if (addr.sa.sa_family == PF_INET)
419 port = find_free_port (s->fd);
422 error = clib_error_return (0, "no free port (fd %d, '%s')",
429 if (addr.sa.sa_family == PF_LOCAL)
430 unlink (((struct sockaddr_un *) &addr)->sun_path);
432 /* Make address available for multiple users. */
435 if (setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof (v)) < 0)
436 clib_unix_warning ("setsockopt SO_REUSEADDR fails");
439 if (addr.sa.sa_family == PF_LOCAL && s->flags & CLIB_SOCKET_F_PASSCRED)
442 if (setsockopt (s->fd, SOL_SOCKET, SO_PASSCRED, &x, sizeof (x)) < 0)
444 error = clib_error_return_unix (0, "setsockopt (SO_PASSCRED, "
445 "fd %d, '%s')", s->fd,
451 if (need_bind && bind (s->fd, &addr.sa, addr_len) < 0)
453 error = clib_error_return_unix (0, "bind (fd %d, '%s')",
458 if (listen (s->fd, 5) < 0)
460 error = clib_error_return_unix (0, "listen (fd %d, '%s')",
464 if (addr.sa.sa_family == PF_LOCAL
465 && s->flags & CLIB_SOCKET_F_ALLOW_GROUP_WRITE)
467 struct stat st = { 0 };
468 if (stat (((struct sockaddr_un *) &addr)->sun_path, &st) < 0)
470 error = clib_error_return_unix (0, "stat (fd %d, '%s')",
474 st.st_mode |= S_IWGRP;
475 if (chmod (((struct sockaddr_un *) &addr)->sun_path, st.st_mode) <
479 clib_error_return_unix (0, "chmod (fd %d, '%s', mode %o)",
480 s->fd, s->config, st.st_mode);
487 if ((s->flags & CLIB_SOCKET_F_NON_BLOCKING_CONNECT)
488 && fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
490 error = clib_error_return_unix (0, "fcntl NONBLOCK (fd %d, '%s')",
495 if (connect (s->fd, &addr.sa, addr_len) < 0
496 && !((s->flags & CLIB_SOCKET_F_NON_BLOCKING_CONNECT) &&
497 errno == EINPROGRESS))
499 error = clib_error_return_unix (0, "connect (fd %d, '%s')",
514 clib_socket_accept (clib_socket_t * server, clib_socket_t * client)
516 clib_error_t *err = 0;
519 memset (client, 0, sizeof (client[0]));
521 /* Accept the new socket connection. */
522 client->fd = accept (server->fd, 0, 0);
524 return clib_error_return_unix (0, "accept (fd %d, '%s')",
525 server->fd, server->config);
527 /* Set the new socket to be non-blocking. */
528 if (fcntl (client->fd, F_SETFL, O_NONBLOCK) < 0)
530 err = clib_error_return_unix (0, "fcntl O_NONBLOCK (fd %d)",
536 len = sizeof (client->peer);
537 if (getpeername (client->fd, (struct sockaddr *) &client->peer, &len) < 0)
539 err = clib_error_return_unix (0, "getpeername (fd %d)", client->fd);
543 client->flags = CLIB_SOCKET_F_IS_CLIENT;
545 socket_init_funcs (client);
554 * fd.io coding-style-patch-verification: ON
557 * eval: (c-set-style "gnu")