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++)
76 memset (&a, 0,
sizeof (a));
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;
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);
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));
330 size = recvmsg (s->fd, &mh, 0);
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);
369 if (!s->sendmsg_func)
371 if (!s->recvmsg_func)
381 struct sockaddr_un su;
383 socklen_t addr_len = 0;
390 ? INADDR_LOOPBACK : INADDR_ANY));
397 SOCK_SEQPACKET : SOCK_STREAM;
399 s->fd = socket (addr.sa.sa_family, socket_type, 0);
408 if (addr.sa.sa_family == PF_INET)
409 port = ((
struct sockaddr_in *) &addr)->sin_port;
415 if (addr.sa.sa_family == PF_INET)
429 if (addr.sa.sa_family == PF_LOCAL)
430 unlink (((
struct sockaddr_un *) &addr)->sun_path);
435 if (setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof (v)) < 0)
442 if (setsockopt (s->fd, SOL_SOCKET, SO_PASSCRED, &x, sizeof (x)) < 0)
445 "fd %d, '%s')", s->fd,
451 if (need_bind && bind (s->fd, &addr.sa, addr_len) < 0)
458 if (listen (s->fd, 5) < 0)
464 if (addr.sa.sa_family == PF_LOCAL
467 struct stat st = { 0 };
468 if (stat (((
struct sockaddr_un *) &addr)->sun_path, &st) < 0)
474 st.st_mode |= S_IWGRP;
475 if (chmod (((
struct sockaddr_un *) &addr)->sun_path, st.st_mode) <
480 s->fd, s->config, st.st_mode);
488 && fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
495 if (connect (s->fd, &addr.sa, addr_len) < 0
497 errno == EINPROGRESS))
519 memset (client, 0,
sizeof (client[0]));
522 client->fd = accept (server->fd, 0, 0);
525 server->fd, server->config);
528 if (fcntl (client->fd, F_SETFL, O_NONBLOCK) < 0)
536 len =
sizeof (client->peer);
537 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
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)
static void socket_init_funcs(clib_socket_t *s)
#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 clib_memcpy(a, b, c)
#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,...)