diff options
-rw-r--r-- | usr.sbin/bgpctl/bgpctl.c | 5 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 84 | ||||
-rw-r--r-- | usr.sbin/bgpd/buffer.c | 23 | ||||
-rw-r--r-- | usr.sbin/bgpd/imsg.c | 109 | ||||
-rw-r--r-- | usr.sbin/bgpd/imsg.h | 105 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 11 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 10 |
7 files changed, 197 insertions, 150 deletions
diff --git a/usr.sbin/bgpctl/bgpctl.c b/usr.sbin/bgpctl/bgpctl.c index d4cfb962c64..b11a072ff4a 100644 --- a/usr.sbin/bgpctl/bgpctl.c +++ b/usr.sbin/bgpctl/bgpctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpctl.c,v 1.141 2009/06/06 06:05:41 claudio Exp $ */ +/* $OpenBSD: bgpctl.c,v 1.142 2009/06/06 06:33:15 eric Exp $ */ /* * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> @@ -174,8 +174,7 @@ main(int argc, char *argv[]) -1 || imsg_add(msg, &res->af, sizeof(res->af)) == -1) errx(1, "imsg_add failure"); - if (imsg_close(ibuf, msg) < 0) - errx(1, "imsg_close error"); + imsg_close(ibuf, msg); } else imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, &res->addr, sizeof(res->addr)); diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 970e6a686df..3eab2ca44b6 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.236 2009/06/06 06:04:10 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.237 2009/06/06 06:33:15 eric Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -30,6 +30,8 @@ #include <poll.h> #include <stdarg.h> +#include "imsg.h" + #define BGP_VERSION 4 #define BGP_PORT 179 #define CONFFILE "/etc/bgpd.conf" @@ -107,22 +109,6 @@ enum reconf_action { RECONF_DELETE }; -struct buf { - TAILQ_ENTRY(buf) entry; - u_char *buf; - size_t size; - size_t max; - size_t wpos; - size_t rpos; - int fd; -}; - -struct msgbuf { - TAILQ_HEAD(, buf) bufs; - u_int32_t queued; - int fd; -}; - struct bgpd_addr { sa_family_t af; union { @@ -175,12 +161,6 @@ struct bgpd_config { u_int16_t connectretry; }; -struct buf_read { - u_char buf[READ_BUF_SIZE]; - u_char *rptr; - size_t wpos; -}; - enum announce_type { ANNOUNCE_UNDEF, ANNOUNCE_SELF, @@ -285,24 +265,6 @@ struct network { TAILQ_ENTRY(network) entry; }; -/* ipc messages */ - -#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) -#define MAX_IMSGSIZE 8192 - -struct imsg_fd { - TAILQ_ENTRY(imsg_fd) entry; - int fd; -}; - -struct imsgbuf { - TAILQ_HEAD(fds, imsg_fd) fds; - struct buf_read r; - struct msgbuf w; - int fd; - pid_t pid; -}; - enum imsg_type { IMSG_NONE, IMSG_RECONF_CONF, @@ -363,18 +325,6 @@ enum imsg_type { IMSG_DEMOTE }; -struct imsg_hdr { - u_int32_t peerid; - pid_t pid; - enum imsg_type type; - u_int16_t len; -}; - -struct imsg { - struct imsg_hdr hdr; - void *data; -}; - struct demote_msg { char demote_group[IFNAMSIZ]; int level; @@ -756,21 +706,6 @@ void send_imsg_session(int, pid_t, void *, u_int16_t); int bgpd_redistribute(int, struct kroute *, struct kroute6 *); int bgpd_filternexthop(struct kroute *, struct kroute6 *); -/* buffer.c */ -struct buf *buf_open(size_t); -struct buf *buf_dynamic(size_t, size_t); -int buf_add(struct buf *, const void *, size_t); -void *buf_reserve(struct buf *, size_t); -void *buf_seek(struct buf *, size_t, size_t); -size_t buf_size(struct buf *); -size_t buf_left(struct buf *); -int buf_close(struct msgbuf *, struct buf *); -int buf_write(struct msgbuf *); -void buf_free(struct buf *); -void msgbuf_init(struct msgbuf *); -void msgbuf_clear(struct msgbuf *); -int msgbuf_write(struct msgbuf *); - /* log.c */ void log_init(int); void vlog(int, const char *, va_list); @@ -789,19 +724,6 @@ int cmdline_symset(char *); /* config.c */ int host(const char *, struct bgpd_addr *, u_int8_t *); -/* imsg.c */ -void imsg_init(struct imsgbuf *, int); -int imsg_read(struct imsgbuf *); -int imsg_get(struct imsgbuf *, struct imsg *); -int imsg_compose(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t, int, - const void *, u_int16_t); -struct buf *imsg_create(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t, - u_int16_t); -int imsg_add(struct buf *, const 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, u_int); int kr_change(struct kroute_label *); diff --git a/usr.sbin/bgpd/buffer.c b/usr.sbin/bgpd/buffer.c index a4063c3ed07..a4b9e9d1b6f 100644 --- a/usr.sbin/bgpd/buffer.c +++ b/usr.sbin/bgpd/buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.c,v 1.42 2009/03/13 06:25:04 claudio Exp $ */ +/* $OpenBSD: buffer.c,v 1.43 2009/06/06 06:33:15 eric Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -16,17 +16,17 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/types.h> +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/socket.h> #include <sys/uio.h> #include <errno.h> -#include <limits.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include "bgpd.h" +#include "imsg.h" int buf_realloc(struct buf *, size_t); void buf_enqueue(struct msgbuf *, struct buf *); @@ -134,13 +134,10 @@ buf_left(struct buf *buf) return (buf->max - buf->wpos); } -int +void buf_close(struct msgbuf *msgbuf, struct buf *buf) { - /* truncate buffer to the correct length before queuing */ - buf->size = buf->wpos; buf_enqueue(msgbuf, buf); - return (1); } int @@ -223,7 +220,7 @@ msgbuf_write(struct msgbuf *msgbuf) struct cmsghdr *cmsg; union { struct cmsghdr hdr; - char buf[CMSG_SPACE(sizeof(int))]; + char buf[CMSG_SPACE(sizeof(int))]; } cmsgbuf; bzero(&iov, sizeof(iov)); @@ -232,7 +229,7 @@ msgbuf_write(struct msgbuf *msgbuf) if (i >= IOV_MAX) break; iov[i].iov_base = buf->buf + buf->rpos; - iov[i].iov_len = buf->size - buf->rpos; + iov[i].iov_len = buf->wpos - buf->rpos; i++; if (buf->fd != -1) break; @@ -276,8 +273,8 @@ msgbuf_write(struct msgbuf *msgbuf) for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; buf = next) { next = TAILQ_NEXT(buf, entry); - if (buf->rpos + n >= buf->size) { - n -= buf->size - buf->rpos; + if (buf->rpos + n >= buf->wpos) { + n -= buf->wpos - buf->rpos; buf_dequeue(msgbuf, buf); } else { buf->rpos += n; diff --git a/usr.sbin/bgpd/imsg.c b/usr.sbin/bgpd/imsg.c index 1e8255b130e..57d836f5a2a 100644 --- a/usr.sbin/bgpd/imsg.c +++ b/usr.sbin/bgpd/imsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.c,v 1.42 2008/03/24 16:11:02 deraadt Exp $ */ +/* $OpenBSD: imsg.c,v 1.43 2009/06/06 06:33:15 eric Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -16,7 +16,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/types.h> +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/socket.h> #include <sys/uio.h> #include <errno.h> @@ -24,7 +26,7 @@ #include <string.h> #include <unistd.h> -#include "bgpd.h" +#include "imsg.h" void imsg_init(struct imsgbuf *ibuf, int fd) @@ -37,14 +39,14 @@ imsg_init(struct imsgbuf *ibuf, int fd) TAILQ_INIT(&ibuf->fds); } -int +ssize_t imsg_read(struct imsgbuf *ibuf) { struct msghdr msg; struct cmsghdr *cmsg; union { struct cmsghdr hdr; - char buf[CMSG_SPACE(sizeof(int) * 16)]; + char buf[CMSG_SPACE(sizeof(int) * 16)]; } cmsgbuf; struct iovec iov; ssize_t n; @@ -52,6 +54,7 @@ imsg_read(struct imsgbuf *ibuf) struct imsg_fd *ifd; 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; @@ -61,7 +64,6 @@ imsg_read(struct imsgbuf *ibuf) if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { if (errno != EINTR && errno != EAGAIN) { - log_warn("imsg_read: pipe read error"); return (-1); } return (-2); @@ -74,19 +76,20 @@ imsg_read(struct imsgbuf *ibuf) 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"); + if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) { + /* XXX: this return can leak */ + return (-1); + } ifd->fd = fd; TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry); - } else - log_warn("imsg_read: got unexpected ctl data level %d " - "type %d", cmsg->cmsg_level, cmsg->cmsg_type); + } + /* we do not handle other ctl data level */ } return (n); } -int +ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) { size_t av, left, datalen; @@ -99,8 +102,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); if (imsg->hdr.len < IMSG_HEADER_SIZE || imsg->hdr.len > MAX_IMSGSIZE) { - log_warnx("imsg_get: imsg hdr len %u out of bounds, type=%u", - imsg->hdr.len, imsg->hdr.type); + errno = ERANGE; return (-1); } if (imsg->hdr.len > av) @@ -108,7 +110,6 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) datalen = imsg->hdr.len - IMSG_HEADER_SIZE; ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE; if ((imsg->data = malloc(datalen)) == NULL) { - log_warn("imsg_get"); return (-1); } memcpy(imsg->data, ibuf->r.rptr, datalen); @@ -124,11 +125,10 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) } int -imsg_compose(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, - pid_t pid, int fd, const void *data, u_int16_t datalen) +imsg_compose(struct imsgbuf *ibuf, u_int16_t type, u_int32_t peerid, + pid_t pid, int fd, void *data, u_int16_t datalen) { struct buf *wbuf; - int n; if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) return (-1); @@ -138,33 +138,54 @@ imsg_compose(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, wbuf->fd = fd; - if ((n = imsg_close(ibuf, wbuf)) < 0) + imsg_close(ibuf, wbuf); + + return (1); +} + +int +imsg_composev(struct imsgbuf *ibuf, u_int16_t type, u_int32_t peerid, + pid_t pid, int fd, const struct iovec *iov, int iovcnt) +{ + struct buf *wbuf; + int i, datalen = 0; + + for (i = 0; i < iovcnt; i++) + datalen += iov[i].iov_len; + + if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) return (-1); - return (n); + for (i = 0; i < iovcnt; i++) + if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1) + return (-1); + + wbuf->fd = fd; + + imsg_close(ibuf, wbuf); + + return (1); } +/* ARGSUSED */ struct buf * -imsg_create(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, +imsg_create(struct imsgbuf *ibuf, u_int16_t type, u_int32_t peerid, pid_t pid, u_int16_t datalen) { struct buf *wbuf; struct imsg_hdr hdr; - if (datalen > MAX_IMSGSIZE - IMSG_HEADER_SIZE) { - log_warnx("imsg_create: len %u > MAX_IMSGSIZE; " - "type %u peerid %lu", datalen + IMSG_HEADER_SIZE, - type, peerid); + datalen += IMSG_HEADER_SIZE; + if (datalen > MAX_IMSGSIZE) { + errno = ERANGE; return (NULL); } - hdr.len = datalen + IMSG_HEADER_SIZE; hdr.type = type; hdr.peerid = peerid; if ((hdr.pid = pid) == 0) hdr.pid = ibuf->pid; - if ((wbuf = buf_open(hdr.len)) == NULL) { - log_warn("imsg_create: buf_open"); + if ((wbuf = buf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) { return (NULL); } if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1) @@ -174,28 +195,24 @@ imsg_create(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, } int -imsg_add(struct buf *msg, const void *data, u_int16_t datalen) +imsg_add(struct buf *msg, void *data, u_int16_t datalen) { if (datalen) if (buf_add(msg, data, datalen) == -1) { - log_warnx("imsg_add: buf_add error"); buf_free(msg); return (-1); } return (datalen); } -int +void imsg_close(struct imsgbuf *ibuf, struct buf *msg) { - int n; + struct imsg_hdr *hdr; - if ((n = buf_close(&ibuf->w, msg)) < 0) { - log_warnx("imsg_close: buf_close error"); - buf_free(msg); - return (-1); - } - return (n); + hdr = (struct imsg_hdr *)msg->buf; + hdr->len = (u_int16_t)msg->wpos; + buf_close(&ibuf->w, msg); } void @@ -219,3 +236,19 @@ imsg_get_fd(struct imsgbuf *ibuf) return (fd); } + +int +imsg_flush(struct imsgbuf *ibuf) +{ + while (ibuf->w.queued) + if (msgbuf_write(&ibuf->w) < 0) + return (-1); + return (0); +} + +void +imsg_clear(struct imsgbuf *ibuf) +{ + while (ibuf->w.queued) + msgbuf_clear(&ibuf->w); +} diff --git a/usr.sbin/bgpd/imsg.h b/usr.sbin/bgpd/imsg.h new file mode 100644 index 00000000000..1fb4548d993 --- /dev/null +++ b/usr.sbin/bgpd/imsg.h @@ -0,0 +1,105 @@ +/* $OpenBSD: imsg.h,v 1.1 2009/06/06 06:33:15 eric Exp $ */ + +/* + * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> + * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org> + * Copyright (c) 2003, 2004 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/tree.h> + +#define READ_BUF_SIZE 65535 +#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) +#define MAX_IMSGSIZE 16384 + +struct buf { + TAILQ_ENTRY(buf) entry; + u_char *buf; + size_t size; + size_t max; + size_t wpos; + size_t rpos; + int fd; +}; + +struct msgbuf { + TAILQ_HEAD(, buf) bufs; + u_int32_t queued; + int fd; +}; + +struct buf_read { + u_char buf[READ_BUF_SIZE]; + u_char *rptr; + size_t wpos; +}; + +struct imsg_fd { + TAILQ_ENTRY(imsg_fd) entry; + int fd; +}; + +struct imsgbuf { + TAILQ_HEAD(, imsg_fd) fds; + struct buf_read r; + struct msgbuf w; + int fd; + pid_t pid; +}; + +struct imsg_hdr { + u_int16_t type; + u_int16_t len; + u_int32_t peerid; + pid_t pid; +}; + +struct imsg { + struct imsg_hdr hdr; + void *data; +}; + + +/* buffer.c */ +struct buf *buf_open(size_t); +struct buf *buf_dynamic(size_t, size_t); +int buf_add(struct buf *, const void *, size_t); +void *buf_reserve(struct buf *, size_t); +void *buf_seek(struct buf *, size_t, size_t); +size_t buf_size(struct buf *); +size_t buf_left(struct buf *); +void buf_close(struct msgbuf *, struct buf *); +int buf_write(struct msgbuf *); +void buf_free(struct buf *); +void msgbuf_init(struct msgbuf *); +void msgbuf_clear(struct msgbuf *); +int msgbuf_write(struct msgbuf *); + +/* imsg.c */ +void imsg_init(struct imsgbuf *, int); +ssize_t imsg_read(struct imsgbuf *); +ssize_t imsg_get(struct imsgbuf *, struct imsg *); +int imsg_compose(struct imsgbuf *, u_int16_t, u_int32_t, pid_t, + int, void *, u_int16_t); +int imsg_composev(struct imsgbuf *, u_int16_t, u_int32_t, pid_t, + int, const struct iovec *, int); +struct buf *imsg_create(struct imsgbuf *, u_int16_t, u_int32_t, pid_t, + u_int16_t); +int imsg_add(struct buf *, void *, u_int16_t); +void imsg_close(struct imsgbuf *, struct buf *); +void imsg_free(struct imsg *); +int imsg_get_fd(struct imsgbuf *); +int imsg_flush(struct imsgbuf *); +void imsg_clear(struct imsgbuf *); diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index a236878850f..4af77019645 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.258 2009/06/06 06:04:10 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.259 2009/06/06 06:33:15 eric Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -1563,8 +1563,7 @@ rde_update_err(struct rde_peer *peer, u_int8_t error, u_int8_t suberr, imsg_add(wbuf, &suberr, sizeof(suberr)) == -1 || imsg_add(wbuf, data, size) == -1) fatal("imsg_add error"); - if (imsg_close(ibuf_se, wbuf) == -1) - fatal("imsg_close error"); + imsg_close(ibuf_se, wbuf); peer->state = PEER_ERR; } @@ -1765,8 +1764,7 @@ rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) imsg_add(wbuf, aspath_dump(asp->aspath), rib.aspath_len) == -1) return; - if (imsg_close(ibuf_se_ctl, wbuf) == -1) - return; + imsg_close(ibuf_se_ctl, wbuf); if (flags & F_CTL_DETAIL) for (l = 0; l < asp->others_len; l++) { @@ -1785,8 +1783,7 @@ rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) buf_free(wbuf); return; } - if (imsg_close(ibuf_se_ctl, wbuf) == -1) - return; + imsg_close(ibuf_se_ctl, wbuf); } } diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index c43f7be159d..c8bd5e36c2d 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.291 2009/06/04 04:46:42 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.292 2009/06/06 06:33:15 eric Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -1329,13 +1329,7 @@ session_sendmsg(struct bgp_msg *msg, struct peer *p) mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p); } - if (buf_close(&p->wbuf, msg->buf) == -1) { - log_peer_warn(&p->conf, "session_sendmsg buf_close"); - buf_free(msg->buf); - free(msg); - return (-1); - } - + buf_close(&p->wbuf, msg->buf); free(msg); return (0); } |