|
Packit |
a94d48 |
/*
|
|
Packit |
a94d48 |
* $Id: ud_socket.c,v 1.6 2009/04/22 18:22:28 thockin Exp $
|
|
Packit |
a94d48 |
* A few routines for handling UNIX domain sockets
|
|
Packit |
a94d48 |
*/
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
a94d48 |
#include <config.h>
|
|
Packit |
a94d48 |
#endif
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
#include <stdio.h>
|
|
Packit |
a94d48 |
#include <stdlib.h>
|
|
Packit |
a94d48 |
#include <unistd.h>
|
|
Packit |
a94d48 |
#include <errno.h>
|
|
Packit |
a94d48 |
#include <string.h>
|
|
Packit |
a94d48 |
#include <sys/types.h>
|
|
Packit |
a94d48 |
#include <sys/stat.h>
|
|
Packit |
a94d48 |
#include <sys/socket.h>
|
|
Packit |
a94d48 |
#include <sys/un.h>
|
|
Packit |
a94d48 |
#include <fcntl.h>
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
#include "acpid.h"
|
|
Packit |
a94d48 |
#include "log.h"
|
|
Packit |
a94d48 |
#include "ud_socket.h"
|
|
Packit |
a94d48 |
#include "libc_compat.h"
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
int
|
|
Packit |
a94d48 |
ud_create_socket(const char *name, mode_t socketmode)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
int fd;
|
|
Packit |
a94d48 |
int r;
|
|
Packit |
a94d48 |
struct sockaddr_un uds_addr;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
if (strnlen(name, sizeof(uds_addr.sun_path)) >
|
|
Packit |
a94d48 |
sizeof(uds_addr.sun_path) - 1) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "ud_create_socket(): "
|
|
Packit |
a94d48 |
"socket filename longer than %zu characters: %s",
|
|
Packit |
a94d48 |
sizeof(uds_addr.sun_path) - 1, name);
|
|
Packit |
a94d48 |
errno = EINVAL;
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* JIC */
|
|
Packit |
a94d48 |
unlink(name);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
|
|
Packit |
a94d48 |
if (fd < 0) {
|
|
Packit |
a94d48 |
return fd;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* Clear the umask to guarantee predictable results from fchmod(). */
|
|
Packit |
a94d48 |
umask(0);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
if (fchmod(fd, socketmode) < 0) {
|
|
Packit |
a94d48 |
close(fd);
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "fchmod() on socket %s: %s",
|
|
Packit |
a94d48 |
name, strerror(errno));
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* setup address struct */
|
|
Packit |
a94d48 |
memset(&uds_addr, 0, sizeof(uds_addr));
|
|
Packit |
a94d48 |
uds_addr.sun_family = AF_UNIX;
|
|
Packit |
a94d48 |
strncpy(uds_addr.sun_path, name, sizeof(uds_addr.sun_path) - 1);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* bind it to the socket */
|
|
Packit |
a94d48 |
r = bind(fd, (struct sockaddr *)&uds_addr, sizeof(uds_addr));
|
|
Packit |
a94d48 |
if (r < 0) {
|
|
Packit |
a94d48 |
close (fd);
|
|
Packit |
a94d48 |
return r;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* listen - allow 10 to queue */
|
|
Packit |
a94d48 |
r = listen(fd, 10);
|
|
Packit |
a94d48 |
if (r < 0) {
|
|
Packit |
a94d48 |
close(fd);
|
|
Packit |
a94d48 |
return r;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
return fd;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
int
|
|
Packit |
a94d48 |
ud_accept(int listenfd, struct ucred *cred)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
while (1) {
|
|
Packit |
a94d48 |
int newsock = 0;
|
|
Packit |
a94d48 |
struct sockaddr_un cliaddr;
|
|
Packit |
a94d48 |
socklen_t len = sizeof(struct sockaddr_un);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
newsock = TEMP_FAILURE_RETRY (accept4(listenfd, (struct sockaddr *)&cliaddr, &len, SOCK_CLOEXEC|SOCK_NONBLOCK));
|
|
Packit |
a94d48 |
if (newsock < 0) {
|
|
Packit |
a94d48 |
return newsock;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
if (cred) {
|
|
Packit |
a94d48 |
len = sizeof(struct ucred);
|
|
Packit |
a94d48 |
getsockopt(newsock,SOL_SOCKET,SO_PEERCRED,cred,&len;;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
return newsock;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
int
|
|
Packit |
a94d48 |
ud_connect(const char *name)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
int fd;
|
|
Packit |
a94d48 |
int r;
|
|
Packit |
a94d48 |
struct sockaddr_un addr;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
if (strnlen(name, sizeof(addr.sun_path)) > sizeof(addr.sun_path) - 1) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "ud_connect(): "
|
|
Packit |
a94d48 |
"socket filename longer than %zu characters: %s",
|
|
Packit |
a94d48 |
sizeof(addr.sun_path) - 1, name);
|
|
Packit |
a94d48 |
errno = EINVAL;
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
|
Packit |
a94d48 |
if (fd < 0) {
|
|
Packit |
a94d48 |
return fd;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
memset(&addr, 0, sizeof(addr));
|
|
Packit |
a94d48 |
addr.sun_family = AF_UNIX;
|
|
Packit |
a94d48 |
sprintf(addr.sun_path, "%s", name);
|
|
Packit |
a94d48 |
/* safer: */
|
|
Packit |
a94d48 |
/*strncpy(addr.sun_path, name, sizeof(addr.sun_path) - 1);*/
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
r = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
|
|
Packit |
a94d48 |
if (r < 0) {
|
|
Packit |
a94d48 |
close(fd);
|
|
Packit |
a94d48 |
return r;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
return fd;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
int
|
|
Packit |
a94d48 |
ud_get_peercred(int fd, struct ucred *cred)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
socklen_t len = sizeof(struct ucred);
|
|
Packit |
a94d48 |
getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &len;;
|
|
Packit |
a94d48 |
return 0;
|
|
Packit |
a94d48 |
}
|