mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
IO: Changes in socket API
Support for active UNIX sockets is added. UNIX socket are now created with sk_open. The socket name/path is passes in host, the same way as SSH address.
This commit is contained in:
parent
373b343e0c
commit
a059c2c6ff
17
lib/socket.h
17
lib/socket.h
@ -44,7 +44,7 @@ typedef struct birdsock {
|
||||
int subtype; /* Socket subtype */
|
||||
void *data; /* User data */
|
||||
ip_addr saddr, daddr; /* IPA_NONE = unspecified */
|
||||
const char *host; /* Alternative to daddr, NULL = unspecified */
|
||||
const char *host; /* Alternative to daddr especially for UNIX sockets, NULL = unspecified */
|
||||
uint sport, dport; /* 0 = unspecified (for IP: protocol type) */
|
||||
int tos; /* TOS / traffic class, -1 = default */
|
||||
int priority; /* Local socket priority, -1 = default */
|
||||
@ -98,6 +98,7 @@ void sk_dump_all(void);
|
||||
|
||||
int sk_is_ipv4(sock *s); /* True if socket is IPv4 */
|
||||
int sk_is_ipv6(sock *s); /* True if socket is IPv6 */
|
||||
int sk_is_unix(sock *s); /* True if socket is UNIX socket */
|
||||
|
||||
static inline int sk_tx_buffer_empty(sock *sk)
|
||||
{ return sk->tbuf == sk->tpos; }
|
||||
@ -111,6 +112,7 @@ int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given sock
|
||||
int sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int setkey);
|
||||
int sk_set_ipv6_checksum(sock *s, int offset);
|
||||
int sk_set_icmp6_filter(sock *s, int p1, int p2);
|
||||
int sk_check_unix(const char *path);
|
||||
void sk_log_error(sock *s, const char *p);
|
||||
|
||||
byte * sk_rx_buffer(sock *s, int *len); /* Temporary */
|
||||
@ -143,10 +145,11 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shou
|
||||
#define SK_UDP 3 /* ? ? ? ? ? ? ? */
|
||||
#define SK_IP 5 /* ? - ? * ? ? ? */
|
||||
#define SK_MAGIC 7 /* Internal use by sysdep code */
|
||||
#define SK_UNIX_PASSIVE 8
|
||||
#define SK_UNIX 9
|
||||
#define SK_SSH_ACTIVE 10 /* - - * * - ? - DA = host */
|
||||
#define SK_SSH 11
|
||||
#define SK_UNIX_PASSIVE 8 /* - - * - - - - DA = host */
|
||||
#define SK_UNIX_ACTIVE 9 /* - - * - - - - DA = host */
|
||||
#define SK_UNIX 10
|
||||
#define SK_SSH_ACTIVE 11 /* - - * * - ? - DA = host */
|
||||
#define SK_SSH 12
|
||||
|
||||
/*
|
||||
* Socket subtypes
|
||||
@ -177,6 +180,10 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shou
|
||||
* per-packet basis using platform dependent options (but these are not
|
||||
* available in some corner cases). The first way is used when SKF_BIND is
|
||||
* specified, the second way is used otherwise.
|
||||
*
|
||||
* For UNIX sockets (SK_UNIX_PASSIVE, SK_UNIX_ACTIVE), path is passed in host
|
||||
* string. If the path does not fit into the sockaddr_un sun_path array, the
|
||||
* sk_open will fail. One can check path length with sk_check_unix.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
123
sysdep/unix/io.c
123
sysdep/unix/io.c
@ -536,6 +536,21 @@ sk_setup_multicast(sock *s)
|
||||
return sk_setup_multicast6(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* sk_check_unix - check path length
|
||||
* @path: filesystem path
|
||||
*
|
||||
* Check if path fits into the sockaddr_un sun_path array.
|
||||
*
|
||||
* Result: 0 for success, -1 for an error.
|
||||
*/
|
||||
|
||||
int
|
||||
sk_check_unix(const char *path)
|
||||
{
|
||||
return -(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path));
|
||||
}
|
||||
|
||||
/**
|
||||
* sk_join_group - join multicast group for given socket
|
||||
* @s: socket
|
||||
@ -866,7 +881,7 @@ static void
|
||||
sk_dump(resource *r)
|
||||
{
|
||||
sock *s = (sock *) r;
|
||||
static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", NULL, "IP", NULL, "MAGIC", "UNIX<", "UNIX", "SSH>", "SSH", "DEL!" };
|
||||
static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", NULL, "IP", NULL, "MAGIC", "UNIX<", "UNIX>", "UNIX", "SSH>", "SSH", "DEL!" };
|
||||
|
||||
debug("(%s, ud=%p, sa=%I, sp=%d, da=%I, dp=%d, tos=%d, ttl=%d, if=%s)\n",
|
||||
sk_type_names[s->type],
|
||||
@ -923,6 +938,12 @@ sk_setup(sock *s)
|
||||
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
||||
ERR("O_NONBLOCK");
|
||||
|
||||
if (s->type == SK_UNIX_ACTIVE || s->type == SK_UNIX_PASSIVE)
|
||||
return sk_check_unix(s->host);
|
||||
|
||||
if (s->type == SK_UNIX)
|
||||
return 0;
|
||||
|
||||
if (!s->af)
|
||||
return 0;
|
||||
|
||||
@ -1045,6 +1066,14 @@ sk_tcp_connected(sock *s)
|
||||
s->tx_hook(s);
|
||||
}
|
||||
|
||||
static void
|
||||
sk_unix_connected(sock *s)
|
||||
{
|
||||
s->type = SK_UNIX;
|
||||
sk_alloc_bufs(s);
|
||||
s->tx_hook(s);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBSSH
|
||||
static void
|
||||
sk_ssh_connected(sock *s)
|
||||
@ -1070,6 +1099,7 @@ sk_passive_connected(sock *s, int type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do not copy UNIX address in s->host. */
|
||||
sock *t = sk_new(s->pool);
|
||||
t->type = type;
|
||||
t->data = s->data;
|
||||
@ -1327,6 +1357,9 @@ sk_open(sock *s)
|
||||
int bind_port = 0;
|
||||
ip_addr bind_addr = IPA_NONE;
|
||||
sockaddr sa;
|
||||
struct sockaddr_un un;
|
||||
struct sockaddr *addr;
|
||||
socklen_t len;
|
||||
|
||||
if (s->type <= SK_IP)
|
||||
{
|
||||
@ -1399,6 +1432,15 @@ sk_open(sock *s)
|
||||
fd = s->fd;
|
||||
break;
|
||||
|
||||
case SK_UNIX_ACTIVE:
|
||||
s->ttx = "";
|
||||
/* Fall thru */
|
||||
case SK_UNIX_PASSIVE:
|
||||
af = AF_UNIX;
|
||||
fd = socket(af, SOCK_STREAM, 0);
|
||||
do_bind = s->type == SK_UNIX_PASSIVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
bug("sk_open() called for invalid sock type %d", s->type);
|
||||
}
|
||||
@ -1439,8 +1481,21 @@ sk_open(sock *s)
|
||||
if (sk_set_freebind(s) < 0)
|
||||
log(L_WARN "Socket error: %s%#m", s->err);
|
||||
|
||||
if (s->type == SK_UNIX_PASSIVE)
|
||||
{
|
||||
un.sun_family = AF_UNIX;
|
||||
strcpy(un.sun_path, s->host);
|
||||
addr = (struct sockaddr *) &un;
|
||||
len = SUN_LEN(&un);
|
||||
}
|
||||
else
|
||||
{
|
||||
sockaddr_fill(&sa, s->af, bind_addr, s->iface, bind_port);
|
||||
if (bind(fd, &sa.sa, SA_LEN(sa)) < 0)
|
||||
addr = &sa.sa;
|
||||
len = SA_LEN(sa);
|
||||
}
|
||||
|
||||
if (bind(fd, addr, len) < 0)
|
||||
ERR2("bind");
|
||||
}
|
||||
|
||||
@ -1464,6 +1519,21 @@ sk_open(sock *s)
|
||||
ERR2("listen");
|
||||
break;
|
||||
|
||||
case SK_UNIX_ACTIVE:
|
||||
un.sun_family = AF_UNIX;
|
||||
strcpy(un.sun_path, s->host);
|
||||
|
||||
if (connect(s->fd, (struct sockaddr *) &un, SUN_LEN(&un)) >= 0)
|
||||
sk_unix_connected(s);
|
||||
else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)
|
||||
ERR2("connect");
|
||||
break;
|
||||
|
||||
case SK_UNIX_PASSIVE:
|
||||
if (listen(fd, 8) < 0)
|
||||
ERR2("listen");
|
||||
break;
|
||||
|
||||
case SK_SSH_ACTIVE:
|
||||
case SK_MAGIC:
|
||||
break;
|
||||
@ -1483,38 +1553,6 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sk_open_unix(sock *s, char *name)
|
||||
{
|
||||
struct sockaddr_un sa;
|
||||
int fd;
|
||||
|
||||
/* We are sloppy during error (leak fd and not set s->err), but we die anyway */
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
||||
return -1;
|
||||
|
||||
/* Path length checked in test_old_bird() but we may need unix sockets for other reasons in future */
|
||||
ASSERT_DIE(strlen(name) < sizeof(sa.sun_path));
|
||||
|
||||
sa.sun_family = AF_UNIX;
|
||||
strcpy(sa.sun_path, name);
|
||||
|
||||
if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) < 0)
|
||||
return -1;
|
||||
|
||||
if (listen(fd, 8) < 0)
|
||||
return -1;
|
||||
|
||||
s->fd = fd;
|
||||
sk_insert(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sk_reloop_hook(void *_vs)
|
||||
{
|
||||
@ -1971,6 +2009,20 @@ sk_write_noflush(sock *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SK_UNIX_ACTIVE:
|
||||
{
|
||||
struct sockaddr_un un;
|
||||
un.sun_family = AF_UNIX;
|
||||
strcpy(un.sun_path, s->host);
|
||||
|
||||
if (connect(s->fd, (struct sockaddr *) &un, SUN_LEN(&un)) >= 0 || errno == EISCONN)
|
||||
sk_unix_connected(s);
|
||||
else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)
|
||||
s->err_hook(s, errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBSSH
|
||||
case SK_SSH_ACTIVE:
|
||||
{
|
||||
@ -2017,6 +2069,9 @@ int sk_is_ipv4(sock *s)
|
||||
int sk_is_ipv6(sock *s)
|
||||
{ return s->af == AF_INET6; }
|
||||
|
||||
int sk_is_unix(sock *s)
|
||||
{ return s->af == AF_UNIX; }
|
||||
|
||||
void
|
||||
sk_err(sock *s, int revents)
|
||||
{
|
||||
|
@ -515,6 +515,7 @@ cli_init_unix(uid_t use_uid, gid_t use_gid)
|
||||
cli_init();
|
||||
s = cli_sk = sk_new(cli_pool);
|
||||
s->type = SK_UNIX_PASSIVE;
|
||||
s->host = path_control_socket;
|
||||
s->rx_hook = cli_connect;
|
||||
s->err_hook = cli_connect_err;
|
||||
s->rbsize = 1024;
|
||||
@ -523,7 +524,7 @@ cli_init_unix(uid_t use_uid, gid_t use_gid)
|
||||
/* Return value intentionally ignored */
|
||||
unlink(path_control_socket);
|
||||
|
||||
if (sk_open_unix(s, path_control_socket) < 0)
|
||||
if (sk_open(s) < 0)
|
||||
die("Cannot create control socket %s: %m", path_control_socket);
|
||||
|
||||
if (use_uid || use_gid)
|
||||
|
@ -53,7 +53,6 @@ typedef struct sockaddr_bird {
|
||||
} sockaddr;
|
||||
|
||||
|
||||
|
||||
/* This is sloppy hack, it should be detected by configure script */
|
||||
/* Linux systems have it defined so this is definition for BSD systems */
|
||||
#ifndef s6_addr32
|
||||
@ -107,7 +106,6 @@ extern volatile sig_atomic_t async_shutdown_flag;
|
||||
void io_init(void);
|
||||
void io_loop(void);
|
||||
void io_log_dump(void);
|
||||
int sk_open_unix(struct birdsock *s, char *name);
|
||||
struct rfile *rf_open(struct pool *, const char *name, const char *mode);
|
||||
void *rf_file(struct rfile *f);
|
||||
int rf_fileno(struct rfile *f);
|
||||
|
Loading…
Reference in New Issue
Block a user