diff options
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.c | 21 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 19 | ||||
-rw-r--r-- | usr.sbin/bgpd/kroute.c | 118 |
4 files changed, 157 insertions, 5 deletions
diff --git a/usr.sbin/bgpd/Makefile b/usr.sbin/bgpd/Makefile index bf03b5cb008..70045b2d75d 100644 --- a/usr.sbin/bgpd/Makefile +++ b/usr.sbin/bgpd/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.5 2003/12/22 00:10:33 henning Exp $ +# $OpenBSD: Makefile,v 1.6 2003/12/22 15:22:13 henning Exp $ 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 + rde.c rde_rib.c rde_decide.c rde_prefix.c mrt.c kroute.c CFLAGS+= -Wall CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CLFAGS+= -Wmissing-declarations -Wredundant-decls diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c index ef65fbb75fb..5c4660f0f48 100644 --- a/usr.sbin/bgpd/bgpd.c +++ b/usr.sbin/bgpd/bgpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.c,v 1.17 2003/12/22 15:11:45 henning Exp $ */ +/* $OpenBSD: bgpd.c,v 1.18 2003/12/22 15:22:13 henning Exp $ */ /* * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> @@ -41,6 +41,7 @@ int reconfigure(char *, struct bgpd_config *, struct mrt_config *); int dispatch_imsg(struct imsgbuf *, int, struct mrt_config *); int mrtfd = -1; +int rfd = -1; volatile sig_atomic_t mrtdump = 0; volatile sig_atomic_t quit = 0; volatile sig_atomic_t reconfig = 0; @@ -191,6 +192,7 @@ main(int argc, char *argv[]) imsg_init(&ibuf_se, pipe_m2s[0]); imsg_init(&ibuf_rde, pipe_m2r[0]); + rfd = kroute_init(); while (quit == 0) { pfd[PFD_PIPE_SESSION].fd = ibuf_se.sock; @@ -331,6 +333,23 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx, struct mrt_config *conf) break; } break; + case IMSG_KROUTE_ADD: + if (idx != PFD_PIPE_ROUTE) + fatal("route request not from RDE", 0); + if (kroute_add(rfd, imsg.data)) + fatal("kroute bytes left", 0); + break; + case IMSG_KROUTE_CHANGE: + if (idx != PFD_PIPE_ROUTE) + fatal("route request not from RDE", 0); + if (kroute_change(rfd, imsg.data)) + fatal("kroute bytes left", 0); + case IMSG_KROUTE_DELETE: + if (idx != PFD_PIPE_ROUTE) + fatal("route request not from RDE", 0); + if (kroute_delete(rfd, imsg.data)) + fatal("kroute bytes left", 0); + break; default: break; } diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 486928421f8..bc3d22f26c7 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.12 2003/12/22 15:07:05 henning Exp $ */ +/* $OpenBSD: bgpd.h,v 1.13 2003/12/22 15:22:13 henning Exp $ */ /* * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> @@ -207,7 +207,10 @@ enum imsg_type { IMSG_SESSION_DOWN, IMSG_MRT_REQ, IMSG_MRT_MSG, - IMSG_MRT_END + IMSG_MRT_END, + IMSG_KROUTE_ADD, + IMSG_KROUTE_CHANGE, + IMSG_KROUTE_DELETE }; struct imsg_hdr { @@ -236,6 +239,12 @@ enum suberr_update { ERR_UPD_ASPATH }; +struct kroute { + in_addr_t prefix; + u_int8_t prefixlen; + in_addr_t nexthop; +}; + /* prototypes */ /* session.c */ int session_main(struct bgpd_config *, int[2], int[2]); @@ -284,4 +293,10 @@ int rde_main(struct bgpd_config *, int[2], int[2]); /* mrt.c */ int mrt_mergeconfig(struct mrt_config *, struct mrt_config *); +/* kroute.c */ +int kroute_init(void); +int kroute_add(int, struct kroute *); +int kroute_change(int, struct kroute *); +int kroute_delete(int, struct kroute *); + #endif /* __BGPD_H__ */ diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c new file mode 100644 index 00000000000..1c8ba683e0b --- /dev/null +++ b/usr.sbin/bgpd/kroute.c @@ -0,0 +1,118 @@ +/* $OpenBSD: kroute.c,v 1.1 2003/12/22 15:22:13 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 <netinet/in.h> +#include <arpa/inet.h> +#include <net/route.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "bgpd.h" + +int kroute_msg(int, int, struct kroute *); + +u_int32_t rtseq = 1; + +int +kroute_init(void) +{ + int s, opt; + + if ((s = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) + fatal("route socket", errno); + + if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) + fatal(NULL, errno); + + /* not intrested in my own messages */ + if (setsockopt(s, SOL_SOCKET, SO_USELOOPBACK, &opt, sizeof(opt)) == -1) + fatal("route setsockopt", errno); + + return (s); +} + +int +kroute_msg(int fd, int action, struct kroute *kroute) +{ + struct { + struct rt_msghdr hdr; + struct sockaddr_in prefix; + struct sockaddr_in nexthop; + struct sockaddr_in mask; + } r; + ssize_t n; + + r.hdr.rtm_msglen = sizeof(r); + r.hdr.rtm_version = RTM_VERSION; + r.hdr.rtm_type = action; + r.hdr.rtm_flags = RTF_GATEWAY|RTF_MASK; /* XXX */ + r.hdr.rtm_seq = rtseq++; /* overflow doesn't matter */ + r.hdr.rtm_addrs = RTA_DST|RTA_GATEWAY|RTA_NETMASK; + r.prefix.sin_family = AF_INET; + r.prefix.sin_addr.s_addr = kroute->prefix; + r.nexthop.sin_family = AF_INET; + r.nexthop.sin_addr.s_addr = kroute->nexthop; + r.mask.sin_family = AF_INET; + r.mask.sin_addr.s_addr = htonl(0xffffffff << (32 - kroute->prefixlen)); + +retry: + if ((n = write(fd, &r, sizeof(r))) == -1) { + if (errno == ESRCH) { + if (r.hdr.rtm_type == RTM_CHANGE) { + r.hdr.rtm_type = RTM_ADD; + goto retry; + } else if (r.hdr.rtm_type == RTM_DELETE) { + logit(LOG_INFO, "route vanished before delete"); + return (0); + } + } else { + logit(LOG_INFO, "kroute_msg", strerror(errno)); + return (-1); + } + } + if (n == sizeof(r)) + return (0); + + /* XXX we could not write everything... bad bad bad. cope. */ + return (n); +} + +int +kroute_add(int fd, struct kroute *kroute) +{ + return (kroute_msg(fd, RTM_ADD, kroute)); +} + +int +kroute_change(int fd, struct kroute *kroute) +{ + return (kroute_msg(fd, RTM_CHANGE, kroute)); +} + +int +kroute_delete(int fd, struct kroute *kroute) +{ + return (kroute_msg(fd, RTM_DELETE, kroute)); +} |