41 #include <sys/types.h> 42 #include <sys/socket.h> 45 #include <netinet/in.h> 46 #include <arpa/inet.h> 72 for (port = IPPORT_USERRESERVED; port < 1 << 16; port++)
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;
93 void *
addr, socklen_t * addr_len,
u32 ip4_default_address)
101 if (config[0] ==
'/')
103 struct sockaddr_un *su =
addr;
104 su->sun_family = PF_LOCAL;
106 clib_min (
sizeof (su->sun_path), 1 + strlen (config)));
107 *addr_len =
sizeof (su[0]);
115 struct sockaddr_in *sa =
addr;
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))
138 sa->sin_family = PF_INET;
139 *addr_len =
sizeof (sa[0]);
141 sa->sin_port = htons (port);
147 struct in_addr host_addr;
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);
162 clib_memcpy (&sa->sin_addr.s_addr, host->h_addr_list[0],
167 sa->sin_addr.s_addr = htonl (ip4_default_address);
194 tx_len =
vec_len (s->tx_buffer);
195 written = write (fd, s->tx_buffer, tx_len);
205 tx_len, s->fd, s->config);
211 else if (written > 0)
213 if (written == tx_len)
214 _vec_len (s->tx_buffer) = 0;
221 else if (written == 0 && tx_len > 64 * 1024)
243 vec_add2 (sock->rx_buffer, buf, n_bytes);
245 if ((n_read = read (fd, buf, n_bytes)) < 0)
254 n_bytes, sock->fd, sock->config);
262 _vec_len (sock->rx_buffer) += n_read - n_bytes;
270 if (close (s->fd) < 0)
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;
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);
310 int fds[],
int num_fds)
313 char ctl[CMSG_SPACE (
sizeof (
int) * num_fds) +
314 CMSG_SPACE (
sizeof (
struct ucred))];
315 struct ucred *cr = 0;
317 char ctl[CMSG_SPACE (
sizeof (
int) * num_fds)];
319 struct msghdr mh = { 0 };
322 struct cmsghdr *cmsg;
324 iov[0].iov_base = msg;
325 iov[0].iov_len = msglen;
328 mh.msg_control = ctl;
329 mh.msg_controllen =
sizeof (ctl);
334 size = recvmsg (s->fd, &mh, 0);
342 cmsg = CMSG_FIRSTHDR (&mh);
345 if (cmsg->cmsg_level == SOL_SOCKET)
348 if (cmsg->cmsg_type == SCM_CREDENTIALS)
350 cr = (
struct ucred *) CMSG_DATA (cmsg);
357 if (cmsg->cmsg_type == SCM_RIGHTS)
360 num_fds *
sizeof (
int));
363 cmsg = CMSG_NXTHDR (&mh, cmsg);
377 if (!s->sendmsg_func)
379 if (!s->recvmsg_func)
389 struct sockaddr_un su;
391 socklen_t addr_len = 0;
398 ? INADDR_LOOPBACK : INADDR_ANY));
405 SOCK_SEQPACKET : SOCK_STREAM;
407 s->fd = socket (addr.sa.sa_family, socket_type, 0);
416 if (addr.sa.sa_family == PF_INET)
417 port = ((
struct sockaddr_in *) &addr)->sin_port;
423 if (addr.sa.sa_family == PF_INET)
437 if (addr.sa.sa_family == PF_LOCAL)
438 unlink (((
struct sockaddr_un *) &addr)->sun_path);
443 if (setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof (v)) < 0)
451 if (setsockopt (s->fd, SOL_SOCKET, SO_PASSCRED, &x, sizeof (x)) < 0)
454 "fd %d, '%s')", s->fd,
461 if (need_bind && bind (s->fd, &addr.sa, addr_len) < 0)
468 if (listen (s->fd, 5) < 0)
474 if (addr.sa.sa_family == PF_LOCAL
477 struct stat st = { 0 };
478 if (stat (((
struct sockaddr_un *) &addr)->sun_path, &st) < 0)
484 st.st_mode |= S_IWGRP;
485 if (chmod (((
struct sockaddr_un *) &addr)->sun_path, st.st_mode) <
490 s->fd, s->config, st.st_mode);
498 && fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
505 if (connect (s->fd, &addr.sa, addr_len) < 0
507 errno == EINPROGRESS))
532 client->fd = accept (server->fd, 0, 0);
535 server->fd, server->config);
538 if (fcntl (client->fd, F_SETFL, O_NONBLOCK) < 0)
546 len =
sizeof (client->peer);
547 if (getpeername (client->fd, (
struct sockaddr *) &client->peer, &len) < 0)
static clib_error_t * default_socket_close(clib_socket_t *s)
static clib_error_t * default_socket_read(clib_socket_t *sock, int n_bytes)
#define CLIB_SOCKET_F_NON_BLOCKING_CONNECT
Optimized string handling code, including c11-compliant "safe C library" variants.
#define clib_memcpy_fast(a, b, c)
static clib_error_t * socket_config(char *config, void *addr, socklen_t *addr_len, u32 ip4_default_address)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
clib_error_t * clib_socket_init(clib_socket_t *s)
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
static void socket_init_funcs(clib_socket_t *s)
#define clib_memcpy(d, s, n)
#define CLIB_SOCKET_F_IS_SERVER
#define clib_error_return(e, args...)
static clib_error_t * default_socket_sendmsg(clib_socket_t *s, void *msg, int msglen, int fds[], int num_fds)
static clib_error_t * default_socket_recvmsg(clib_socket_t *s, void *msg, int msglen, int fds[], int num_fds)
clib_error_t * clib_socket_accept(clib_socket_t *server, clib_socket_t *client)
#define clib_error_return_unix(e, args...)
static void clib_socket_tx_add_va_formatted(clib_socket_t *s, char *fmt, va_list *va)
#define CLIB_SOCKET_F_RX_END_OF_FILE
#define vec_free(V)
Free vector's memory (no header).
#define vec_delete(V, N, M)
Delete N elements starting at element M.
static word unix_error_is_fatal(word error)
static word find_free_port(word sock)
#define CLIB_SOCKET_F_IS_CLIENT
struct _socket_t clib_socket_t
#define CLIB_SOCKET_F_SEQPACKET
static clib_error_t * default_socket_write(clib_socket_t *s)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define CLIB_SOCKET_F_PASSCRED
#define clib_unix_warning(format, args...)
#define CLIB_SOCKET_F_ALLOW_GROUP_WRITE
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
void clib_socket_tx_add_formatted(clib_socket_t *s, char *fmt,...)