2 #define _GNU_SOURCE // accept4() 11 #include <sys/socket.h> 12 #include <sys/types.h> 61 #define LIBSOCKET_BACKLOG 128 63 #define LIBSOCKET_STREAM 1 64 #define LIBSOCKET_DGRAM 2 66 #define LIBSOCKET_READ 1 67 #define LIBSOCKET_WRITE 2 69 #define debug_write(str) \ 71 int verbose_errno_save = errno; \ 72 write(2, str, strlen(str)); \ 73 errno = verbose_errno_save; \ 93 if (return_value < 0) {
95 errbuf = strerror(errno);
104 static int set_unix_socket_path(
struct sockaddr_un* saddr,
const char* path_or_name) {
105 memset(&saddr->sun_path, 0,
sizeof(saddr->sun_path));
106 if (path_or_name[0] != 0) {
107 strncpy(saddr->sun_path, path_or_name,
sizeof(saddr->sun_path) - 1);
111 if (path_or_name[1] == 0) {
114 debug_write(
"set_unix_socket_path: Socket address is too many 0s\n");
118 size_t max_len = 1 + strlen(path_or_name+1);
119 if (max_len >
sizeof(saddr->sun_path) - 1) {
121 debug_write(
"set_unix_socket_path: Abstract socket address is too long\n");
123 errno = ENAMETOOLONG;
126 memcpy(saddr->sun_path, path_or_name, max_len);
144 struct sockaddr_un saddr;
147 if (path == NULL)
return -1;
149 if (-1 ==
check_error(sfd = socket(AF_UNIX, SOCK_STREAM | flags, 0)))
152 memset(&saddr, 0,
sizeof(
struct sockaddr_un));
154 if (strlen(path) > (
sizeof(saddr.sun_path) - 1)) {
157 "create_unix_stream_socket: UNIX socket destination path too " 163 saddr.sun_family = AF_UNIX;
164 if (-1 ==
check_error(set_unix_socket_path(&saddr, path)))
166 size_t pathlen = strlen(saddr.sun_path);
168 pathlen =
sizeof(saddr.sun_path);
172 connect(sfd, (
struct sockaddr*)&saddr,
173 sizeof(saddr.sun_family) + pathlen))) {
193 struct sockaddr_un saddr;
195 if (-1 ==
check_error(sfd = socket(AF_UNIX, SOCK_DGRAM | flags, 0)))
198 memset(&saddr, 0,
sizeof(
struct sockaddr_un));
200 if (bind_path != NULL) {
201 if ((retval = unlink(bind_path)) == -1 &&
208 if (strlen(bind_path) > (
sizeof(saddr.sun_path) - 1)) {
211 "create_unix_dgram_socket: UNIX socket path too long\n");
216 saddr.sun_family = AF_UNIX;
217 if (-1 ==
check_error(set_unix_socket_path(&saddr, bind_path)))
220 size_t pathlen = strlen(saddr.sun_path);
222 pathlen =
sizeof(saddr.sun_path);
224 bind(sfd, (
struct sockaddr*)&saddr,
225 sizeof(saddr.sun_family) + pathlen);
244 struct sockaddr_un new_addr;
245 struct sockaddr deconnect;
247 if (sfd < 0)
return -1;
250 memset(&deconnect, 0,
sizeof(
struct sockaddr));
252 deconnect.sa_family = AF_UNSPEC;
254 if (
check_error(connect(sfd, &deconnect,
sizeof(
struct sockaddr))))
260 memset(&new_addr, 0,
sizeof(
struct sockaddr_un));
262 new_addr.sun_family = AF_UNIX;
264 if (strlen(path) >
sizeof(new_addr.sun_path) - 1) {
266 debug_write(
"connect_unix_dgram_socket: Path too long\n");
271 if (-1 ==
check_error(set_unix_socket_path(&new_addr, path))) {
275 size_t pathlen = strlen(new_addr.sun_path);
277 pathlen =
sizeof(new_addr.sun_path);
280 sfd, (
struct sockaddr*)&new_addr,
281 sizeof(new_addr.sun_family) + pathlen)))
298 if (sfd < 0)
return -1;
320 if (sfd < 0)
return -1;
322 if ((method != LIBSOCKET_READ) && (method != LIBSOCKET_WRITE) &&
323 (method != (LIBSOCKET_READ | LIBSOCKET_WRITE)))
326 if (method & LIBSOCKET_READ)
328 if (-1 ==
check_error(shutdown(sfd, SHUT_RD)))
return -1;
331 if (method & LIBSOCKET_WRITE)
333 if (-1 ==
check_error(shutdown(sfd, SHUT_WR)))
return -1;
354 struct sockaddr_un saddr;
355 int sfd, type, retval;
357 if (path == NULL)
return -1;
359 if (strlen(path) > (
sizeof(saddr.sun_path) - 1)) {
361 debug_write(
"create_unix_server_socket: Path too long\n");
367 case LIBSOCKET_STREAM:
370 case LIBSOCKET_DGRAM:
377 if (-1 ==
check_error(sfd = socket(AF_UNIX, type | flags, 0)))
return -1;
379 if ((retval = unlink(path)) == -1 &&
386 memset(&saddr, 0,
sizeof(
struct sockaddr_un));
388 saddr.sun_family = AF_UNIX;
390 if (-1 ==
check_error(set_unix_socket_path(&saddr, path)))
393 size_t pathlen = strlen(saddr.sun_path);
395 pathlen =
sizeof(saddr.sun_path);
399 sizeof(saddr.sun_family) + pathlen)))
402 if (type == SOCK_STREAM) {
403 if (-1 ==
check_error(listen(sfd, LIBSOCKET_BACKLOG)))
return -1;
422 if (sfd < 0)
return -1;
424 if (-1 ==
check_error(cfd = accept4(sfd, 0, 0, flags)))
return -1;
426 if (-1 ==
check_error(cfd = accept(sfd, 0, 0)))
return -1;
445 size_t from_size,
int recvfrom_flags) {
447 socklen_t socksize =
sizeof(
struct sockaddr_un);
448 struct sockaddr_un saddr;
450 memset(buf, 0, size);
451 memset(from, 0, from_size);
454 check_error(bytes = recvfrom(sfd, buf, size, recvfrom_flags,
455 (
struct sockaddr*)&saddr, &socksize)))
458 if (from != NULL && from_size > 0) {
459 memcpy(from, saddr.sun_path,
460 from_size <
sizeof(saddr.sun_path) ? from_size
461 :
sizeof(saddr.sun_path));
480 const char* path,
int sendto_flags) {
482 struct sockaddr_un saddr;
484 if (strlen(path) >
sizeof(saddr.sun_path) - 1) {
487 "sendto_unix_dgram_socket: UNIX destination socket path too " 493 memset(&saddr, 0,
sizeof(
struct sockaddr_un));
495 saddr.sun_family = AF_UNIX;
496 if (-1 ==
check_error(set_unix_socket_path(&saddr, path)))
499 if (-1 ==
check_error(bytes = sendto(sfd, buf, size, sendto_flags,
500 (
struct sockaddr*)&saddr,
501 sizeof(
struct sockaddr_un))))
static signed int check_error(int return_value)
Checks return value for error.
int accept_unix_stream_socket(int sfd, int flags)
Accept connections on a passive UNIX socket.
int create_unix_dgram_socket(const char *bind_path, int flags)
Create a UNIX DGRAM socket.
int connect_unix_dgram_socket(int sfd, const char *path)
Connect a datagram socket.
ssize_t recvfrom_unix_dgram_socket(int sfd, void *buf, size_t size, char *from, size_t from_size, int recvfrom_flags)
Receive datagram from another UNIX socket.
int create_unix_stream_socket(const char *path, int flags)
Create and connect a new UNIX STREAM socket.
int shutdown_unix_stream_socket(int sfd, int method)
Shut a socket down.
int destroy_unix_socket(int sfd)
Close a socket.
ssize_t sendto_unix_dgram_socket(int sfd, const void *buf, size_t size, const char *path, int sendto_flags)
Send datagram to socket.
int create_unix_server_socket(const char *path, int socktype, int flags)
Create a passive UNIX socket.