summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2004-01-01 23:46:48 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2004-01-01 23:46:48 +0000
commit4e446d5117aca066229a6eea302910120954f524 (patch)
tree4d69a449c6974ead1261a8a0dd5f6016b7252b2b /usr.sbin
parente739f0ace9d26fdcc465c4a0677813ff7e940037 (diff)
listen on a AF_LOCAL socket for imsgs too.
only implemented type yet is IMSG_CTL_SHOW_NEIGHBOR which sends back the struct peer for all neighbors. will be used by bgpdctl
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bgpd/Makefile9
-rw-r--r--usr.sbin/bgpd/bgpd.c9
-rw-r--r--usr.sbin/bgpd/bgpd.h16
-rw-r--r--usr.sbin/bgpd/control.c193
-rw-r--r--usr.sbin/bgpd/imsg.c4
-rw-r--r--usr.sbin/bgpd/session.c44
-rw-r--r--usr.sbin/bgpd/session.h18
7 files changed, 270 insertions, 23 deletions
diff --git a/usr.sbin/bgpd/Makefile b/usr.sbin/bgpd/Makefile
index 90523deb1e3..420ab7c4879 100644
--- a/usr.sbin/bgpd/Makefile
+++ b/usr.sbin/bgpd/Makefile
@@ -1,8 +1,11 @@
-# $OpenBSD: Makefile,v 1.7 2003/12/23 17:06:32 henning Exp $
+# $OpenBSD: Makefile,v 1.8 2004/01/01 23:46:47 henning Exp $
+
+.PATH: ${.CURDIR}/..
PROG= bgpd
SRCS= bgpd.c buffer.c session.c log.c parse.y config.c imsg.c \
- rde.c rde_rib.c rde_decide.c rde_prefix.c mrt.c kroute.c
+ rde.c rde_rib.c rde_decide.c rde_prefix.c mrt.c kroute.c \
+ control.c
CFLAGS+= -Wall
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CLFAGS+= -Wmissing-declarations -Wredundant-decls
@@ -11,6 +14,4 @@ CFLAGS+= -Wsign-compare
YFLAGS=
MAN= bgpd.8 bgpd.conf.5
-CFLAGS+= -Wall
-
.include <bsd.prog.mk>
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index 370d8948948..916db012358 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.48 2004/01/01 23:09:08 henning Exp $ */
+/* $OpenBSD: bgpd.c,v 1.49 2004/01/01 23:46:47 henning Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -95,7 +95,7 @@ main(int argc, char *argv[])
pid_t io_pid = 0, rde_pid = 0;
char *conffile;
int debug = 0;
- int ch, i, j, n, nfds;
+ int ch, i, j, n, nfds, csock;
int pipe_m2s[2];
int pipe_m2r[2];
int pipe_s2r[2];
@@ -171,6 +171,9 @@ main(int argc, char *argv[])
fcntl(pipe_s2r[1], F_SETFL, O_NONBLOCK) == -1)
fatal("fcntl");
+ if ((csock = control_init()) == -1)
+ fatalx("control socket setup failed");
+
/* fork children */
rde_pid = rde_main(&conf, pipe_m2r, pipe_s2r);
io_pid = session_main(&conf, pipe_m2s, pipe_s2r);
@@ -188,6 +191,7 @@ main(int argc, char *argv[])
close(pipe_m2r[1]);
close(pipe_s2r[0]);
close(pipe_s2r[1]);
+ close(csock);
imsg_init(&ibuf_se, pipe_m2s[0]);
imsg_init(&ibuf_rde, pipe_m2r[0]);
@@ -289,6 +293,7 @@ main(int argc, char *argv[])
i = waitpid(-1, NULL, WNOHANG);
} while (i > 0 || (i == -1 && errno == EINTR));
+ control_cleanup();
kroute_shutdown();
logit(LOG_CRIT, "Terminating");
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 8e766659d9e..0c6f5470fc9 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.45 2004/01/01 23:09:08 henning Exp $ */
+/* $OpenBSD: bgpd.h,v 1.46 2004/01/01 23:46:47 henning Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -23,6 +23,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <poll.h>
#include <stdarg.h>
#include <syslog.h>
@@ -85,6 +86,11 @@ enum reconf_action {
RECONF_DELETE
};
+enum blockmodes {
+ BM_NORMAL,
+ BM_NONBLOCK
+};
+
struct buf {
TAILQ_ENTRY(buf) entries;
u_char *buf;
@@ -209,7 +215,8 @@ enum imsg_type {
IMSG_KROUTE_DELETE,
IMSG_NEXTHOP_ADD,
IMSG_NEXTHOP_REMOVE,
- IMSG_NEXTHOP_UPDATE
+ IMSG_NEXTHOP_UPDATE,
+ IMSG_CTL_SHOW_NEIGHBOR
};
struct imsg_hdr {
@@ -256,6 +263,7 @@ struct kroute_nexthop {
void send_nexthop_update(struct kroute_nexthop *);
/* session.c */
+void session_socket_blockmode(int, enum blockmodes);
int session_main(struct bgpd_config *, int[2], int[2]);
/* buffer.c */
@@ -316,4 +324,8 @@ int kroute_dispatch_msg(void);
int kroute_nexthop_add(in_addr_t);
void kroute_nexthop_delete(in_addr_t);
+/* control.c */
+int control_init(void);
+void control_cleanup(void);
+
#endif /* __BGPD_H__ */
diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c
new file mode 100644
index 00000000000..75153ad677a
--- /dev/null
+++ b/usr.sbin/bgpd/control.c
@@ -0,0 +1,193 @@
+/* $OpenBSD: control.c,v 1.1 2004/01/01 23:46:47 henning Exp $ */
+
+/*
+ * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bgpd.h"
+#include "bgpdctl.h"
+#include "session.h"
+
+#define CONTROL_BACKLOG 5
+
+struct {
+ int fd;
+} control_state;
+
+struct ctl_conn *control_connbyfd(int);
+
+int
+control_init(void)
+{
+ struct sockaddr_un sun;
+ int fd;
+
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ log_err("control_init: socket");
+ return (-1);
+ }
+
+ bzero(&sun, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strlcpy(sun.sun_path, SOCKET_NAME, sizeof(sun.sun_path));
+ if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
+ log_err("control_init: bind: %s", SOCKET_NAME);
+ return (-1);
+ }
+
+ control_state.fd = fd;
+
+ return (fd);
+}
+
+int
+control_listen(void)
+{
+ if (listen(control_state.fd, CONTROL_BACKLOG) == -1) {
+ log_err("control_listen: listen");
+ return (-1);
+ }
+
+ return (control_state.fd);
+}
+
+void
+control_shutdown(void)
+{
+ close(control_state.fd);
+}
+
+void
+control_cleanup(void)
+{
+ unlink(SOCKET_NAME);
+}
+
+void
+control_accept(int listenfd)
+{
+ int connfd;
+ socklen_t len;
+ struct sockaddr_un sun;
+ uid_t uid;
+ gid_t gid;
+ struct ctl_conn *ctl_conn;
+
+ len = sizeof(sun);
+ if ((connfd = accept(listenfd,
+ (struct sockaddr *)&sun, &len)) == -1) {
+ if (errno == EWOULDBLOCK || errno == EINTR)
+ return;
+ else
+ log_err("session_control_accept");
+ }
+
+ if (getpeereid(connfd, &uid, &gid) == -1) {
+ log_err("session_control_accept");
+ return;
+ }
+
+ if (uid) {
+ log_err("Connection to control socket with uid %ld", uid);
+ return;
+ }
+
+ if ((ctl_conn = malloc(sizeof(struct ctl_conn))) == NULL) {
+ log_err("session_control_accept");
+ return;
+ }
+
+ imsg_init(&ctl_conn->ibuf, connfd);
+
+ TAILQ_INSERT_TAIL(&ctl_conns, ctl_conn, entries);
+}
+
+struct ctl_conn *
+control_connbyfd(int fd)
+{
+ struct ctl_conn *c;
+
+ for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->ibuf.sock != fd;
+ c = TAILQ_NEXT(c, entries))
+ ; /* nothing */
+
+ return (c);
+}
+
+void
+control_close(int fd)
+{
+ struct ctl_conn *c;
+
+ if ((c = control_connbyfd(fd)) == NULL) {
+ log_err("control_close: fd %d: not found", fd);
+ return;
+ }
+
+ TAILQ_REMOVE(&ctl_conns, c, entries);
+
+ close(c->ibuf.sock);
+ free(c);
+}
+
+int
+control_dispatch_msg(struct pollfd *pfd, int i)
+{
+ struct imsg imsg;
+ struct ctl_conn *c;
+ int n;
+ struct peer *p;
+
+ if ((c = control_connbyfd(pfd->fd)) == NULL) {
+ log_err("control_dispatch_msg: fd %d: not found", pfd->fd);
+ return (0);
+ }
+
+ if (imsg_read(&c->ibuf) == -1) {
+ control_close(pfd->fd);
+ return (1);
+ }
+
+ for (;;) {
+ if ((n = imsg_get(&c->ibuf, &imsg)) == -1) {
+ control_close(pfd->fd);
+ return (1);
+ }
+
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_CTL_SHOW_NEIGHBOR:
+ for (p = conf->peers; p != NULL; p = p->next)
+ imsg_compose(&c->ibuf, IMSG_CTL_SHOW_NEIGHBOR,
+ 0, p, sizeof(struct peer));
+ break;
+ default:
+ break;
+ }
+ imsg_free(&imsg);
+ }
+
+ return (0);
+}
diff --git a/usr.sbin/bgpd/imsg.c b/usr.sbin/bgpd/imsg.c
index f59a35eeda7..1d2a8d4abab 100644
--- a/usr.sbin/bgpd/imsg.c
+++ b/usr.sbin/bgpd/imsg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: imsg.c,v 1.16 2004/01/01 23:40:25 henning Exp $ */
+/* $OpenBSD: imsg.c,v 1.17 2004/01/01 23:46:47 henning Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -63,7 +63,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
ssize_t datalen = 0;
size_t av, left;
- av = ibuf->r.wpos;
+ av = ibuf->r.wpos;
if (IMSG_HEADER_SIZE > av)
return (0);
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index 1bc5f7b08a8..6efc3ad2643 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.53 2004/01/01 23:09:09 henning Exp $ */
+/* $OpenBSD: session.c,v 1.54 2004/01/01 23:46:47 henning Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -22,6 +22,7 @@
#include <sys/mman.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@@ -45,12 +46,8 @@
#define PFD_LISTEN 0
#define PFD_PIPE_MAIN 1
#define PFD_PIPE_ROUTE 2
-#define PFD_PEERS_START 3
-
-enum blockmodes {
- BM_NORMAL,
- BM_NONBLOCK
-};
+#define PFD_SOCK_CTL 3
+#define PFD_PEERS_START 4
void session_sighdlr(int);
int setup_listener(void);
@@ -64,7 +61,6 @@ void session_close_connection(struct peer *);
void session_terminate(void);
void change_state(struct peer *, enum session_state, enum session_events);
int session_setup_socket(struct peer *);
-void session_socket_blockmode(int, enum blockmodes);
void session_accept(int);
int session_connect(struct peer *);
void session_open(struct peer *);
@@ -84,10 +80,11 @@ void session_down(struct peer *);
struct peer *getpeerbyip(in_addr_t);
-struct bgpd_config *conf = NULL, *nconf = NULL;
+struct bgpd_config *nconf = NULL;
volatile sig_atomic_t session_quit = 0;
int pending_reconf = 0;
int sock = -1;
+int csock = -1;
struct imsgbuf ibuf_rde;
struct imsgbuf ibuf_main;
@@ -132,12 +129,13 @@ setup_listener(void)
int
session_main(struct bgpd_config *config, int pipe_m2s[2], int pipe_s2r[2])
{
- int nfds, i, j, timeout;
+ int nfds, i, j, timeout, npeers;
pid_t pid;
time_t nextaction;
struct passwd *pw;
struct peer *p, *peers[OPEN_MAX], *last, *next;
struct pollfd pfd[OPEN_MAX];
+ struct ctl_conn *ctl_conn;
conf = config;
@@ -177,6 +175,8 @@ session_main(struct bgpd_config *config, int pipe_m2s[2], int pipe_s2r[2])
init_conf(conf);
imsg_init(&ibuf_rde, pipe_s2r[0]);
imsg_init(&ibuf_main, pipe_m2s[1]);
+ TAILQ_INIT(&ctl_conns);
+ csock = control_listen();
init_peers();
while (session_quit == 0) {
@@ -189,6 +189,8 @@ session_main(struct bgpd_config *config, int pipe_m2s[2], int pipe_s2r[2])
pfd[PFD_PIPE_ROUTE].events = POLLIN;
if (ibuf_rde.w.queued > 0)
pfd[PFD_PIPE_ROUTE].events |= POLLOUT;
+ pfd[PFD_SOCK_CTL].fd = csock;
+ pfd[PFD_SOCK_CTL].events = POLLIN;
nextaction = time(NULL) + 240; /* loop every 240s at least */
i = PFD_PEERS_START;
@@ -256,6 +258,16 @@ session_main(struct bgpd_config *config, int pipe_m2s[2], int pipe_s2r[2])
}
}
+ npeers = i;
+
+ TAILQ_FOREACH(ctl_conn, &ctl_conns, entries) {
+ pfd[i].fd = ctl_conn->ibuf.sock;
+ pfd[i].events = POLLIN;
+ if (ctl_conn->ibuf.w.queued > 0)
+ pfd[i].events |= POLLOUT;
+ i++;
+ }
+
timeout = nextaction - time(NULL);
if (timeout < 0)
timeout = 0;
@@ -282,11 +294,19 @@ session_main(struct bgpd_config *config, int pipe_m2s[2], int pipe_s2r[2])
session_dispatch_imsg(&ibuf_rde, PFD_PIPE_ROUTE);
}
- for (j = PFD_PEERS_START; nfds > 0 && j < i; j++) {
- nfds -= session_dispatch_msg(&pfd[j], peers[j]);
+ if (nfds > 0 && pfd[PFD_SOCK_CTL].revents & POLLIN) {
+ nfds--;
+ control_accept(csock);
}
+
+ for (j = PFD_PEERS_START; nfds > 0 && j < npeers; j++)
+ nfds -= session_dispatch_msg(&pfd[j], peers[j]);
+
+ for (; nfds > 0 && j < i; j++)
+ nfds -= control_dispatch_msg(&pfd[j], j);
}
+ control_shutdown();
logit(LOG_INFO, "session engine exiting");
_exit(0);
}
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index fb25cf017de..ef99c5a85c1 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.2 2003/12/19 21:07:05 henning Exp $ */
+/* $OpenBSD: session.h,v 1.3 2004/01/01 23:46:47 henning Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -75,3 +75,19 @@ struct msg_open {
u_int32_t bgpid;
u_int8_t optparamlen;
};
+
+struct ctl_conn {
+ TAILQ_ENTRY(ctl_conn) entries;
+ struct imsgbuf ibuf;
+};
+
+TAILQ_HEAD(ctl_conns, ctl_conn) ctl_conns;
+
+struct bgpd_config *conf;
+
+/* control.c */
+int control_listen(void);
+void control_shutdown(void);
+int control_dispatch_msg(struct pollfd *, int);
+void control_accept(int);
+void control_close(int);