summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/bgpd.c20
-rw-r--r--usr.sbin/bgpd/bgpd.h20
-rw-r--r--usr.sbin/bgpd/buffer.c29
-rw-r--r--usr.sbin/bgpd/config.c50
-rw-r--r--usr.sbin/bgpd/imsg.c70
-rw-r--r--usr.sbin/bgpd/session.c64
-rw-r--r--usr.sbin/bgpd/session.h3
7 files changed, 188 insertions, 68 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index bce647303fc..3cfcafbd986 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.95 2004/06/06 17:38:10 henning Exp $ */
+/* $OpenBSD: bgpd.c,v 1.96 2004/06/20 17:49:46 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -176,22 +176,24 @@ main(int argc, char *argv[])
log_info("startup");
- if (pipe(pipe_m2s) == -1)
- fatal("pipe");
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_m2s) == -1)
+ fatal("socketpair");
if (fcntl(pipe_m2s[0], F_SETFL, O_NONBLOCK) == -1 ||
fcntl(pipe_m2s[1], F_SETFL, O_NONBLOCK) == -1)
fatal("fcntl");
- if (pipe(pipe_m2r) == -1)
- fatal("pipe");
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_m2r) == -1)
+ fatal("socketpair");
if (fcntl(pipe_m2r[0], F_SETFL, O_NONBLOCK) == -1 ||
fcntl(pipe_m2r[1], F_SETFL, O_NONBLOCK) == -1)
fatal("fcntl");
- if (pipe(pipe_s2r) == -1)
- fatal("pipe");
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_s2r) == -1)
+ fatal("socketpair");
if (fcntl(pipe_s2r[0], F_SETFL, O_NONBLOCK) == -1 ||
fcntl(pipe_s2r[1], F_SETFL, O_NONBLOCK) == -1)
fatal("fcntl");
+ prepare_listeners(&conf);
+
/* fork children */
rde_pid = rde_main(&conf, &net_l, rules_l, &mrt_l, pipe_m2r, pipe_s2r);
io_pid = session_main(&conf, peer_l, &net_l, rules_l, &mrt_l,
@@ -382,6 +384,8 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
return (-1);
}
+ prepare_listeners(conf);
+
if (imsg_compose(&ibuf_se, IMSG_RECONF_CONF, 0,
conf, sizeof(struct bgpd_config)) == -1)
return (-1);
@@ -407,7 +411,7 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
free(r);
}
while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
- if (imsg_compose(&ibuf_se, IMSG_RECONF_LISTENER, 0,
+ if (imsg_compose_fdpass(&ibuf_se, IMSG_RECONF_LISTENER, la->fd,
la, sizeof(struct listen_addr)) == -1)
return (-1);
TAILQ_REMOVE(conf->listen_addrs, la, entry);
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 967c45d1de2..d4d34ada083 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.126 2004/06/06 17:38:10 henning Exp $ */
+/* $OpenBSD: bgpd.h,v 1.127 2004/06/20 17:49:46 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -83,6 +83,7 @@ struct buf {
ssize_t size;
ssize_t wpos;
ssize_t rpos;
+ int fd;
};
struct msgbuf {
@@ -109,6 +110,7 @@ struct bgpd_addr {
};
#define DEFAULT_LISTENER 0x01
+#define LISTENER_LISTENING 0x02
struct listen_addr {
TAILQ_ENTRY(listen_addr) entry;
@@ -238,11 +240,17 @@ struct network {
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
#define MAX_IMSGSIZE 8192
-struct imsgbuf {
+struct imsg_fd {
+ TAILQ_ENTRY(imsg_fd) entry;
int fd;
- pid_t pid;
- struct buf_read r;
- struct msgbuf w;
+};
+
+struct imsgbuf {
+ int fd;
+ pid_t pid;
+ TAILQ_HEAD(fds, imsg_fd) fds;
+ struct buf_read r;
+ struct msgbuf w;
};
enum imsg_type {
@@ -565,11 +573,13 @@ int imsg_read(struct imsgbuf *);
int imsg_get(struct imsgbuf *, struct imsg *);
int imsg_compose(struct imsgbuf *, int, u_int32_t, void *, u_int16_t);
int imsg_compose_pid(struct imsgbuf *, int, pid_t, void *, u_int16_t);
+int imsg_compose_fdpass(struct imsgbuf *, int, int, void *, u_int16_t);
struct buf *imsg_create(struct imsgbuf *, int, u_int32_t, u_int16_t);
struct buf *imsg_create_pid(struct imsgbuf *, int, pid_t, u_int16_t);
int imsg_add(struct buf *, void *, u_int16_t);
int imsg_close(struct imsgbuf *, struct buf *);
void imsg_free(struct imsg *);
+int imsg_get_fd(struct imsgbuf *);
/* kroute.c */
int kr_init(int);
diff --git a/usr.sbin/bgpd/buffer.c b/usr.sbin/bgpd/buffer.c
index 4d91dc05434..087cc0e4f69 100644
--- a/usr.sbin/bgpd/buffer.c
+++ b/usr.sbin/bgpd/buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: buffer.c,v 1.18 2004/04/29 19:56:04 deraadt Exp $ */
+/* $OpenBSD: buffer.c,v 1.19 2004/06/20 17:49:46 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -45,6 +45,7 @@ buf_open(ssize_t len)
return (NULL);
}
buf->size = len;
+ buf->fd = -1;
return (buf);
}
@@ -142,17 +143,36 @@ msgbuf_write(struct msgbuf *msgbuf)
struct buf *buf, *next;
int i = 0;
ssize_t n;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ char cmsgbuf[CMSG_SPACE(sizeof(int))];
bzero(&iov, sizeof(iov));
+ bzero(&msg, sizeof(msg));
TAILQ_FOREACH(buf, &msgbuf->bufs, entries) {
if (i >= IOV_MAX)
break;
iov[i].iov_base = buf->buf + buf->rpos;
iov[i].iov_len = buf->size - buf->rpos;
i++;
+ if (buf->fd != -1)
+ break;
+ }
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = i;
+
+ if (buf != NULL && buf->fd != -1) {
+ msg.msg_control = (caddr_t)cmsgbuf;
+ msg.msg_controllen = CMSG_LEN(sizeof(int));
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ *(int *)CMSG_DATA(cmsg) = buf->fd;
}
- if ((n = writev(msgbuf->fd, iov, i)) == -1) {
+ if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
if (errno == EAGAIN) /* cannot write immediately */
return (0);
else
@@ -164,6 +184,11 @@ msgbuf_write(struct msgbuf *msgbuf)
return (-2);
}
+ if (buf != NULL && buf->fd != -1) {
+ shutdown(buf->fd, SHUT_RDWR);
+ close(buf->fd);
+ }
+
for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
buf = next) {
next = TAILQ_NEXT(buf, entries);
diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c
index 151f1f515a7..b5f67b8e951 100644
--- a/usr.sbin/bgpd/config.c
+++ b/usr.sbin/bgpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.38 2004/06/06 17:38:10 henning Exp $ */
+/* $OpenBSD: config.c,v 1.39 2004/06/20 17:49:46 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -224,3 +224,51 @@ host_v6(const char *s, struct bgpd_addr *h)
return (0);
}
+
+void
+prepare_listeners(struct bgpd_config *conf)
+{
+ struct listen_addr *la;
+ int opt = 1;
+
+ if (TAILQ_EMPTY(conf->listen_addrs)) {
+ if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
+ fatal("setup_listeners calloc");
+ la->fd = -1;
+ la->flags = DEFAULT_LISTENER;
+ la->sa.ss_len = sizeof(struct sockaddr_in);
+ ((struct sockaddr_in *)&la->sa)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&la->sa)->sin_addr.s_addr =
+ htonl(INADDR_ANY);
+ ((struct sockaddr_in *)&la->sa)->sin_port = htons(BGP_PORT);
+ TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
+
+ if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
+ fatal("setup_listeners calloc");
+ la->fd = -1;
+ la->flags = DEFAULT_LISTENER;
+ la->sa.ss_len = sizeof(struct sockaddr_in6);
+ ((struct sockaddr_in6 *)&la->sa)->sin6_family = AF_INET6;
+ ((struct sockaddr_in6 *)&la->sa)->sin6_port = htons(BGP_PORT);
+ TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
+ }
+
+ TAILQ_FOREACH(la, conf->listen_addrs, entry) {
+ if ((la->fd = socket(la->sa.ss_family, SOCK_STREAM,
+ IPPROTO_TCP)) == -1)
+ fatal("socket");
+
+ opt = 1;
+ if (setsockopt(la->fd, SOL_SOCKET, SO_REUSEPORT,
+ &opt, sizeof(opt)) == -1)
+ fatal("setsockopt SO_REUSEPORT");
+
+ if (bind(la->fd, (struct sockaddr *)&la->sa, la->sa.ss_len) ==
+ -1) {
+ log_warn("cannot bind to %s",
+ log_sockaddr((struct sockaddr *)&la->sa));
+ close(la->fd);
+ la->fd = -1;
+ }
+ }
+}
diff --git a/usr.sbin/bgpd/imsg.c b/usr.sbin/bgpd/imsg.c
index eb81ad58b7b..20738c25058 100644
--- a/usr.sbin/bgpd/imsg.c
+++ b/usr.sbin/bgpd/imsg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: imsg.c,v 1.25 2004/04/29 19:56:04 deraadt Exp $ */
+/* $OpenBSD: imsg.c,v 1.26 2004/06/20 17:49:46 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -17,6 +17,7 @@
*/
#include <sys/types.h>
+#include <sys/uio.h>
#include <errno.h>
#include <stdlib.h>
@@ -26,7 +27,7 @@
#include "bgpd.h"
int imsg_compose_core(struct imsgbuf *, int, u_int32_t, void *,
- u_int16_t, pid_t);
+ u_int16_t, pid_t, int);
struct buf *imsg_create_core(struct imsgbuf *, int, u_int32_t, u_int16_t,
pid_t);
@@ -38,15 +39,29 @@ imsg_init(struct imsgbuf *ibuf, int fd)
ibuf->fd = fd;
ibuf->w.fd = fd;
ibuf->pid = getpid();
+ TAILQ_INIT(&ibuf->fds);
}
int
imsg_read(struct imsgbuf *ibuf)
{
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ char cmsgbuf[CMSG_SPACE(sizeof(int))];
+ struct iovec iov;
ssize_t n;
+ int fd;
+ struct imsg_fd *ifd;
- if ((n = read(ibuf->fd, ibuf->r.buf + ibuf->r.wpos,
- sizeof(ibuf->r.buf) - ibuf->r.wpos)) == -1) {
+ bzero(&msg, sizeof(msg));
+ iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
+ iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = sizeof(cmsgbuf);
+
+ if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
if (errno != EINTR && errno != EAGAIN) {
log_warn("imsg_read: pipe read error");
return (-1);
@@ -56,6 +71,19 @@ imsg_read(struct imsgbuf *ibuf)
ibuf->r.wpos += n;
+ if ((cmsg = CMSG_FIRSTHDR(&msg)) != NULL) {
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_RIGHTS) {
+ fd = (*(int *)CMSG_DATA(cmsg));
+ if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
+ fatal("imsg_read calloc");
+ ifd->fd = fd;
+ TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry);
+ } else
+ log_warn("imsg_read: got unexpected ctl data lvel %d"
+ "type %d", cmsg->cmsg_level, cmsg->cmsg_type);
+ }
+
return (n);
}
@@ -98,21 +126,29 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
int
imsg_compose(struct imsgbuf *ibuf, int type, u_int32_t peerid, void *data,
- u_int16_t dlen)
+ u_int16_t datalen)
{
- return (imsg_compose_core(ibuf, type, peerid, data, dlen, ibuf->pid));
+ return (imsg_compose_core(ibuf, type, peerid, data, datalen,
+ ibuf->pid, -1));
}
int
imsg_compose_pid(struct imsgbuf *ibuf, int type, pid_t pid, void *data,
u_int16_t datalen)
{
- return (imsg_compose_core(ibuf, type, 0, data, datalen, pid));
+ return (imsg_compose_core(ibuf, type, 0, data, datalen, pid, -1));
+}
+
+int
+imsg_compose_fdpass(struct imsgbuf *ibuf, int type, int fd, void *data,
+ u_int16_t datalen)
+{
+ return (imsg_compose_core(ibuf, type, 0, data, datalen, ibuf->pid, fd));
}
int
imsg_compose_core(struct imsgbuf *ibuf, int type, u_int32_t peerid, void *data,
- u_int16_t datalen, pid_t pid)
+ u_int16_t datalen, pid_t pid, int fd)
{
struct buf *wbuf;
struct imsg_hdr hdr;
@@ -139,6 +175,8 @@ imsg_compose_core(struct imsgbuf *ibuf, int type, u_int32_t peerid, void *data,
return (-1);
}
+ wbuf->fd = fd;
+
if ((n = buf_close(&ibuf->w, wbuf)) < 0) {
log_warnx("imsg_compose: buf_add error");
buf_free(wbuf);
@@ -213,3 +251,19 @@ imsg_free(struct imsg *imsg)
{
free(imsg->data);
}
+
+int
+imsg_get_fd(struct imsgbuf *ibuf)
+{
+ int fd;
+ struct imsg_fd *ifd;
+
+ if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
+ return (-1);
+
+ fd = ifd->fd;
+ TAILQ_REMOVE(&ibuf->fds, ifd, entry);
+ free(ifd);
+
+ return(fd);
+}
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index eee00b97f3d..1434556ade9 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.174 2004/06/09 13:01:44 henning Exp $ */
+/* $OpenBSD: session.c,v 1.175 2004/06/20 17:49:46 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -114,38 +114,18 @@ setup_listeners(u_int *la_cnt)
struct listen_addr *la;
u_int cnt = 0;
- if (TAILQ_EMPTY(conf->listen_addrs)) {
- if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
- fatal("setup_listeners calloc");
- la->fd = -1;
- la->flags = DEFAULT_LISTENER;
- la->sa.ss_len = sizeof(struct sockaddr_in);
- ((struct sockaddr_in *)&la->sa)->sin_family = AF_INET;
- ((struct sockaddr_in *)&la->sa)->sin_addr.s_addr =
- htonl(INADDR_ANY);
- ((struct sockaddr_in *)&la->sa)->sin_port = htons(BGP_PORT);
- TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
-
- if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
- fatal("setup_listeners calloc");
- la->fd = -1;
- la->flags = DEFAULT_LISTENER;
- la->sa.ss_len = sizeof(struct sockaddr_in6);
- ((struct sockaddr_in6 *)&la->sa)->sin6_family = AF_INET6;
- ((struct sockaddr_in6 *)&la->sa)->sin6_port = htons(BGP_PORT);
- TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
- }
-
TAILQ_FOREACH(la, conf->listen_addrs, entry) {
la->reconf = RECONF_NONE;
cnt++;
- if (la->fd != -1)
+ if (la->flags & LISTENER_LISTENING)
continue;
- if ((la->fd = socket(la->sa.ss_family, SOCK_STREAM,
- IPPROTO_TCP)) == -1)
- fatal("socket");
+ if (la->fd == -1) {
+ log_warn("cannot establish listener on %s: invalid fd",
+ log_sockaddr((struct sockaddr *)&la->sa));
+ continue;
+ }
opt = 1;
if (setsockopt(la->fd, IPPROTO_TCP, TCP_MD5SIG,
@@ -157,18 +137,6 @@ setup_listeners(u_int *la_cnt)
fatal("setsockopt TCP_MD5SIG");
}
- if (bind(la->fd, (struct sockaddr *)&la->sa, la->sa.ss_len) ==
- -1) {
- if (errno == EACCES) {
- log_warnx("can't establish listener on %s",
- log_sockaddr((struct sockaddr *)&la->sa));
- close(la->fd);
- la->fd = -1;
- return (-1);
- } else
- fatal("bind");
- }
-
session_socket_blockmode(la->fd, BM_NONBLOCK);
if (listen(la->fd, MAX_BACKLOG)) {
@@ -176,6 +144,8 @@ setup_listeners(u_int *la_cnt)
fatal("listen");
}
+ la->flags |= LISTENER_LISTENING;
+
log_info("listening on %s",
log_sockaddr((struct sockaddr *)&la->sa));
}
@@ -234,9 +204,6 @@ session_main(struct bgpd_config *config, struct peer *cpeers,
setproctitle("session engine");
bgpd_process = PROC_SE;
- listener_cnt = 0;
- setup_listeners(&listener_cnt);
-
if (pfkey_init(&sysdep) == -1)
fatalx("pfkey setup failed");
@@ -247,6 +214,9 @@ session_main(struct bgpd_config *config, struct peer *cpeers,
endpwent();
+ listener_cnt = 0;
+ setup_listeners(&listener_cnt);
+
signal(SIGTERM, session_sighdlr);
signal(SIGINT, session_sighdlr);
signal(SIGPIPE, SIG_IGN);
@@ -2066,18 +2036,25 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
break;
}
+ if ((nla->fd = imsg_get_fd(ibuf)) == -1)
+ log_warnx("expected to receive fd for %s "
+ "but didn't receive any",
+ log_sockaddr((struct sockaddr *)&la->sa));
+
if (la == NULL) {
la = calloc(1, sizeof(struct listen_addr));
if (la == NULL)
fatal(NULL);
memcpy(&la->sa, &nla->sa, sizeof(la->sa));
- la->fd = nla->fd;
la->flags = nla->flags;
+ la->fd = nla->fd;
la->reconf = RECONF_REINIT;
TAILQ_INSERT_TAIL(nconf->listen_addrs, la,
entry);
} else {
la->reconf = RECONF_KEEP;
+ shutdown(nla->fd, SHUT_RDWR);
+ close(nla->fd);
}
break;
case IMSG_RECONF_DONE:
@@ -2118,6 +2095,7 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
(struct sockaddr *)&la->sa));
TAILQ_REMOVE(conf->listen_addrs, la,
entry);
+ shutdown(la->fd, SHUT_RDWR);
close(la->fd);
free(la);
}
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index d224198c37a..61a5a4d8951 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.55 2004/06/09 13:01:44 henning Exp $ */
+/* $OpenBSD: session.h,v 1.56 2004/06/20 17:49:46 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -210,6 +210,7 @@ int parse_config(char *, struct bgpd_config *, struct mrt_head *,
/* config.c */
int merge_config(struct bgpd_config *, struct bgpd_config *,
struct peer *, struct listen_addrs *);
+void prepare_listeners(struct bgpd_config *);
/* rde.c */
int rde_main(struct bgpd_config *, struct network_head *,