mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +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 */
|
int subtype; /* Socket subtype */
|
||||||
void *data; /* User data */
|
void *data; /* User data */
|
||||||
ip_addr saddr, daddr; /* IPA_NONE = unspecified */
|
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) */
|
uint sport, dport; /* 0 = unspecified (for IP: protocol type) */
|
||||||
int tos; /* TOS / traffic class, -1 = default */
|
int tos; /* TOS / traffic class, -1 = default */
|
||||||
int priority; /* Local socket priority, -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_ipv4(sock *s); /* True if socket is IPv4 */
|
||||||
int sk_is_ipv6(sock *s); /* True if socket is IPv6 */
|
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)
|
static inline int sk_tx_buffer_empty(sock *sk)
|
||||||
{ return sk->tbuf == sk->tpos; }
|
{ 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_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_ipv6_checksum(sock *s, int offset);
|
||||||
int sk_set_icmp6_filter(sock *s, int p1, int p2);
|
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);
|
void sk_log_error(sock *s, const char *p);
|
||||||
|
|
||||||
byte * sk_rx_buffer(sock *s, int *len); /* Temporary */
|
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_UDP 3 /* ? ? ? ? ? ? ? */
|
||||||
#define SK_IP 5 /* ? - ? * ? ? ? */
|
#define SK_IP 5 /* ? - ? * ? ? ? */
|
||||||
#define SK_MAGIC 7 /* Internal use by sysdep code */
|
#define SK_MAGIC 7 /* Internal use by sysdep code */
|
||||||
#define SK_UNIX_PASSIVE 8
|
#define SK_UNIX_PASSIVE 8 /* - - * - - - - DA = host */
|
||||||
#define SK_UNIX 9
|
#define SK_UNIX_ACTIVE 9 /* - - * - - - - DA = host */
|
||||||
#define SK_SSH_ACTIVE 10 /* - - * * - ? - DA = host */
|
#define SK_UNIX 10
|
||||||
#define SK_SSH 11
|
#define SK_SSH_ACTIVE 11 /* - - * * - ? - DA = host */
|
||||||
|
#define SK_SSH 12
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Socket subtypes
|
* 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
|
* 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
|
* available in some corner cases). The first way is used when SKF_BIND is
|
||||||
* specified, the second way is used otherwise.
|
* 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
|
#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);
|
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
|
* sk_join_group - join multicast group for given socket
|
||||||
* @s: socket
|
* @s: socket
|
||||||
@ -866,7 +881,7 @@ static void
|
|||||||
sk_dump(resource *r)
|
sk_dump(resource *r)
|
||||||
{
|
{
|
||||||
sock *s = (sock *) 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",
|
debug("(%s, ud=%p, sa=%I, sp=%d, da=%I, dp=%d, tos=%d, ttl=%d, if=%s)\n",
|
||||||
sk_type_names[s->type],
|
sk_type_names[s->type],
|
||||||
@ -923,6 +938,12 @@ sk_setup(sock *s)
|
|||||||
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
||||||
ERR("O_NONBLOCK");
|
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)
|
if (!s->af)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1045,6 +1066,14 @@ sk_tcp_connected(sock *s)
|
|||||||
s->tx_hook(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
|
#ifdef HAVE_LIBSSH
|
||||||
static void
|
static void
|
||||||
sk_ssh_connected(sock *s)
|
sk_ssh_connected(sock *s)
|
||||||
@ -1070,6 +1099,7 @@ sk_passive_connected(sock *s, int type)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do not copy UNIX address in s->host. */
|
||||||
sock *t = sk_new(s->pool);
|
sock *t = sk_new(s->pool);
|
||||||
t->type = type;
|
t->type = type;
|
||||||
t->data = s->data;
|
t->data = s->data;
|
||||||
@ -1327,6 +1357,9 @@ sk_open(sock *s)
|
|||||||
int bind_port = 0;
|
int bind_port = 0;
|
||||||
ip_addr bind_addr = IPA_NONE;
|
ip_addr bind_addr = IPA_NONE;
|
||||||
sockaddr sa;
|
sockaddr sa;
|
||||||
|
struct sockaddr_un un;
|
||||||
|
struct sockaddr *addr;
|
||||||
|
socklen_t len;
|
||||||
|
|
||||||
if (s->type <= SK_IP)
|
if (s->type <= SK_IP)
|
||||||
{
|
{
|
||||||
@ -1399,6 +1432,15 @@ sk_open(sock *s)
|
|||||||
fd = s->fd;
|
fd = s->fd;
|
||||||
break;
|
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:
|
default:
|
||||||
bug("sk_open() called for invalid sock type %d", s->type);
|
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)
|
if (sk_set_freebind(s) < 0)
|
||||||
log(L_WARN "Socket error: %s%#m", s->err);
|
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);
|
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");
|
ERR2("bind");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1464,6 +1519,21 @@ sk_open(sock *s)
|
|||||||
ERR2("listen");
|
ERR2("listen");
|
||||||
break;
|
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_SSH_ACTIVE:
|
||||||
case SK_MAGIC:
|
case SK_MAGIC:
|
||||||
break;
|
break;
|
||||||
@ -1483,38 +1553,6 @@ err:
|
|||||||
return -1;
|
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
|
static void
|
||||||
sk_reloop_hook(void *_vs)
|
sk_reloop_hook(void *_vs)
|
||||||
{
|
{
|
||||||
@ -1971,6 +2009,20 @@ sk_write_noflush(sock *s)
|
|||||||
return 0;
|
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
|
#ifdef HAVE_LIBSSH
|
||||||
case SK_SSH_ACTIVE:
|
case SK_SSH_ACTIVE:
|
||||||
{
|
{
|
||||||
@ -2017,6 +2069,9 @@ int sk_is_ipv4(sock *s)
|
|||||||
int sk_is_ipv6(sock *s)
|
int sk_is_ipv6(sock *s)
|
||||||
{ return s->af == AF_INET6; }
|
{ return s->af == AF_INET6; }
|
||||||
|
|
||||||
|
int sk_is_unix(sock *s)
|
||||||
|
{ return s->af == AF_UNIX; }
|
||||||
|
|
||||||
void
|
void
|
||||||
sk_err(sock *s, int revents)
|
sk_err(sock *s, int revents)
|
||||||
{
|
{
|
||||||
|
@ -515,6 +515,7 @@ cli_init_unix(uid_t use_uid, gid_t use_gid)
|
|||||||
cli_init();
|
cli_init();
|
||||||
s = cli_sk = sk_new(cli_pool);
|
s = cli_sk = sk_new(cli_pool);
|
||||||
s->type = SK_UNIX_PASSIVE;
|
s->type = SK_UNIX_PASSIVE;
|
||||||
|
s->host = path_control_socket;
|
||||||
s->rx_hook = cli_connect;
|
s->rx_hook = cli_connect;
|
||||||
s->err_hook = cli_connect_err;
|
s->err_hook = cli_connect_err;
|
||||||
s->rbsize = 1024;
|
s->rbsize = 1024;
|
||||||
@ -523,7 +524,7 @@ cli_init_unix(uid_t use_uid, gid_t use_gid)
|
|||||||
/* Return value intentionally ignored */
|
/* Return value intentionally ignored */
|
||||||
unlink(path_control_socket);
|
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);
|
die("Cannot create control socket %s: %m", path_control_socket);
|
||||||
|
|
||||||
if (use_uid || use_gid)
|
if (use_uid || use_gid)
|
||||||
|
@ -53,7 +53,6 @@ typedef struct sockaddr_bird {
|
|||||||
} sockaddr;
|
} sockaddr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This is sloppy hack, it should be detected by configure script */
|
/* This is sloppy hack, it should be detected by configure script */
|
||||||
/* Linux systems have it defined so this is definition for BSD systems */
|
/* Linux systems have it defined so this is definition for BSD systems */
|
||||||
#ifndef s6_addr32
|
#ifndef s6_addr32
|
||||||
@ -107,7 +106,6 @@ extern volatile sig_atomic_t async_shutdown_flag;
|
|||||||
void io_init(void);
|
void io_init(void);
|
||||||
void io_loop(void);
|
void io_loop(void);
|
||||||
void io_log_dump(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);
|
struct rfile *rf_open(struct pool *, const char *name, const char *mode);
|
||||||
void *rf_file(struct rfile *f);
|
void *rf_file(struct rfile *f);
|
||||||
int rf_fileno(struct rfile *f);
|
int rf_fileno(struct rfile *f);
|
||||||
|
Loading…
Reference in New Issue
Block a user