summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/socket.h3
-rw-r--r--sysdep/unix/io.c108
-rw-r--r--sysdep/unix/unix.h3
3 files changed, 84 insertions, 30 deletions
diff --git a/lib/socket.h b/lib/socket.h
index e6229f70..65ba9a20 100644
--- a/lib/socket.h
+++ b/lib/socket.h
@@ -64,6 +64,9 @@ sk_send_buffer_empty(sock *sk)
#define SK_IP 5 /* ? - - * - ? ? */
#define SK_IP_MC 6 /* ? - * * * * - */
#define SK_MAGIC 7 /* Internal use by sysdep code */
+#define SK_UNIX_PASSIVE 8
+#define SK_UNIX 9
+#define SK_DELETED 10 /* Set to this if you want to delete socket from err_hook */
/*
* Multicast sockets are slightly different from the other ones:
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 943a6a72..aef348ce 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -13,6 +13,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
+#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
@@ -285,7 +286,7 @@ static void
sk_dump(resource *r)
{
sock *s = (sock *) r;
- static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", "UDP/MC", "IP", "IP/MC", "MAGIC" };
+ static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", "UDP/MC", "IP", "IP/MC", "MAGIC", "UNIX<", "UNIX", "DEL!" };
debug("(%s, ud=%p, sa=%08x, sp=%d, da=%08x, dp=%d, tos=%d, ttl=%d, if=%s)\n",
sk_type_names[s->type],
@@ -398,6 +399,8 @@ sk_setup(sock *s)
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
ERR("fcntl(O_NONBLOCK)");
+ if (s->type == SK_UNIX)
+ return NULL;
#ifdef IPV6
if (s->ttl >= 0 && s->type != SK_UDP_MC && s->type != SK_IP_MC &&
setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
@@ -431,7 +434,7 @@ sk_alloc_bufs(sock *s)
s->tpos = s->ttx = s->tbuf;
}
-void
+static void
sk_tcp_connected(sock *s)
{
s->rx_hook(s, 0);
@@ -439,6 +442,35 @@ sk_tcp_connected(sock *s)
sk_alloc_bufs(s);
}
+static int
+sk_passive_connected(sock *s, struct sockaddr *sa, int al, int type)
+{
+ int fd = accept(s->fd, sa, &al);
+ if (fd >= 0)
+ {
+ sock *t = sk_new(s->pool);
+ char *err;
+ t->type = type;
+ t->fd = fd;
+ add_tail(&sock_list, &t->n);
+ s->rx_hook(t, 0);
+ if (err = sk_setup(t))
+ {
+ log(L_ERR "Incoming connection: %s: %m", err);
+ s->err_hook(s, errno);
+ return 0;
+ }
+ sk_alloc_bufs(t);
+ return 1;
+ }
+ else if (errno != EINTR && errno != EAGAIN)
+ {
+ log(L_ERR "accept: %m");
+ s->err_hook(s, errno);
+ }
+ return 0;
+}
+
int
sk_open(sock *s)
{
@@ -627,6 +659,37 @@ bad:
return -1;
}
+int
+sk_open_unix(sock *s, char *name)
+{
+ int fd;
+ struct sockaddr_un sa;
+ char *err;
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0)
+ die("sk_open_unix: socket: %m");
+ s->fd = fd;
+ if (err = sk_setup(s))
+ goto bad;
+ unlink(name);
+ sa.sun_family = AF_UNIX;
+ strcpy(sa.sun_path, name);
+ if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
+ ERR("bind");
+ if (listen(fd, 8))
+ ERR("listen");
+ sk_alloc_bufs(s);
+ add_tail(&sock_list, &s->n);
+ return 0;
+
+bad:
+ log(L_ERR "sk_open_unix: %s: %m", err);
+ close(fd);
+ s->fd = -1;
+ return -1;
+}
+
static int
sk_maybe_write(sock *s)
{
@@ -636,6 +699,7 @@ sk_maybe_write(sock *s)
{
case SK_TCP:
case SK_MAGIC:
+ case SK_UNIX:
while (s->ttx != s->tpos)
{
e = write(s->fd, s->ttx, s->tpos - s->ttx);
@@ -723,33 +787,15 @@ sk_read(sock *s)
case SK_TCP_PASSIVE:
{
sockaddr sa;
- int al = sizeof(sa);
- int fd = accept(s->fd, (struct sockaddr *) &sa, &al);
- if (fd >= 0)
- {
- sock *t = sk_new(s->pool);
- char *err;
- t->type = SK_TCP;
- t->fd = fd;
- add_tail(&sock_list, &t->n);
- s->rx_hook(t, 0);
- if (err = sk_setup(t))
- {
- log(L_ERR "Incoming connection: %s: %m", err);
- s->err_hook(s, errno);
- return 0;
- }
- sk_alloc_bufs(t);
- return 1;
- }
- else if (errno != EINTR && errno != EAGAIN)
- {
- log(L_ERR "accept: %m");
- s->err_hook(s, errno);
- }
- return 0;
+ return sk_passive_connected(s, (struct sockaddr *) &sa, sizeof(sa), SK_TCP);
+ }
+ case SK_UNIX_PASSIVE:
+ {
+ struct sockaddr_un sa;
+ return sk_passive_connected(s, (struct sockaddr *) &sa, sizeof(sa), SK_UNIX);
}
case SK_TCP:
+ case SK_UNIX:
{
int c = read(s->fd, s->rpos, s->rbuf + s->rbsize - s->rpos);
@@ -850,7 +896,7 @@ io_loop(void)
time_t tout;
int hi;
sock *s;
- node *n;
+ node *n, *p;
/* FIXME: Use poll() if available */
@@ -925,7 +971,7 @@ io_loop(void)
}
if (hi)
{
- WALK_LIST(n, sock_list)
+ WALK_LIST_DELSAFE(n, p, sock_list)
{
s = SKIP_BACK(sock, n, n);
if (FD_ISSET(s->fd, &rd))
@@ -934,11 +980,13 @@ io_loop(void)
while (sk_read(s))
;
}
- if (FD_ISSET(s->fd, &wr))
+ if (s->type != SK_DELETED && FD_ISSET(s->fd, &wr))
{
FD_CLR(s->fd, &wr);
sk_write(s);
}
+ if (s->type == SK_DELETED)
+ rfree(s);
}
}
}
diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h
index e3c9708d..ab724d19 100644
--- a/sysdep/unix/unix.h
+++ b/sysdep/unix/unix.h
@@ -31,10 +31,13 @@ typedef struct sockaddr_in6 sockaddr;
typedef struct sockaddr_in sockaddr;
#endif
+struct birdsock;
+
void io_init(void);
void io_loop(void);
void fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port);
void get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port);
+int sk_open_unix(struct birdsock *s, char *name);
/* krt.c bits */