diff options
Diffstat (limited to 'usr.sbin/ripd')
-rw-r--r-- | usr.sbin/ripd/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/ripd/carp.c | 181 | ||||
-rw-r--r-- | usr.sbin/ripd/interface.c | 13 | ||||
-rw-r--r-- | usr.sbin/ripd/parse.y | 28 | ||||
-rw-r--r-- | usr.sbin/ripd/ripd.c | 22 | ||||
-rw-r--r-- | usr.sbin/ripd/ripd.conf.5 | 12 | ||||
-rw-r--r-- | usr.sbin/ripd/ripd.h | 18 | ||||
-rw-r--r-- | usr.sbin/ripd/ripe.c | 22 | ||||
-rw-r--r-- | usr.sbin/ripd/ripe.h | 3 |
9 files changed, 283 insertions, 20 deletions
diff --git a/usr.sbin/ripd/Makefile b/usr.sbin/ripd/Makefile index 9a7539f747a..56a271e957d 100644 --- a/usr.sbin/ripd/Makefile +++ b/usr.sbin/ripd/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.3 2007/01/08 13:01:10 claudio Exp $ +# $OpenBSD: Makefile,v 1.4 2008/12/17 14:19:39 michele Exp $ PROG= ripd -SRCS= auth.c buffer.c control.c imsg.c interface.c kroute.c \ +SRCS= auth.c buffer.c carp.c control.c imsg.c interface.c kroute.c \ log.c message.c name2id.c neighbor.c packet.c parse.y \ printconf.c rde.c rde_rib.c ripe.c ripd.c diff --git a/usr.sbin/ripd/carp.c b/usr.sbin/ripd/carp.c new file mode 100644 index 00000000000..fb832ea5ffe --- /dev/null +++ b/usr.sbin/ripd/carp.c @@ -0,0 +1,181 @@ +/* $OpenBSD: carp.c,v 1.1 2008/12/17 14:19:39 michele Exp $ */ + +/* + * Copyright (c) 2006 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/ioctl.h> +#include <net/if.h> + +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include "ripd.h" +#include "log.h" + +struct carpgroup { + TAILQ_ENTRY(carpgroup) entry; + char *group; + int do_demote; + int changed_by; +}; + +TAILQ_HEAD(carpgroups, carpgroup) carpgroups = + TAILQ_HEAD_INITIALIZER(carpgroups); + +struct carpgroup *carp_group_find(char *group); +int carp_demote_ioctl(char *, int); + +struct carpgroup * +carp_group_find(char *group) +{ + struct carpgroup *c; + + TAILQ_FOREACH(c, &carpgroups, entry) + if (!strcmp(c->group, group)) + return (c); + + return (NULL); +} + +int +carp_demote_init(char *group, int force) +{ + struct carpgroup *c; + int level; + + if ((c = carp_group_find(group)) == NULL) { + if ((c = calloc(1, sizeof(struct carpgroup))) == NULL) { + log_warn("carp_demote_init calloc"); + return (-1); + } + if ((c->group = strdup(group)) == NULL) { + log_warn("carp_demote_init strdup"); + free(c); + return (-1); + } + + /* only demote if this group already is demoted */ + if ((level = carp_demote_get(group)) == -1) + return (-1); + if (level > 0 || force) + c->do_demote = 1; + + TAILQ_INSERT_TAIL(&carpgroups, c, entry); + } + + return (0); +} + +void +carp_demote_shutdown(void) +{ + struct carpgroup *c; + + while ((c = TAILQ_FIRST(&carpgroups)) != NULL) { + TAILQ_REMOVE(&carpgroups, c, entry); + for (; c->changed_by > 0; c->changed_by--) + if (c->do_demote) + carp_demote_ioctl(c->group, -1); + + free(c->group); + free(c); + } +} + +int +carp_demote_get(char *group) +{ + int s; + struct ifgroupreq ifgr; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + log_warn("carp_demote_get: socket"); + return (-1); + } + + bzero(&ifgr, sizeof(ifgr)); + strlcpy(ifgr.ifgr_name, group, sizeof(ifgr.ifgr_name)); + + if (ioctl(s, SIOCGIFGATTR, (caddr_t)&ifgr) == -1) { + if (errno == ENOENT) + log_warnx("group \"%s\" does not exist", group); + else + log_warn("carp_demote_get: ioctl"); + close(s); + return (-1); + } + + close(s); + return ((int)ifgr.ifgr_attrib.ifg_carp_demoted); +} + +int +carp_demote_set(char *group, int demote) +{ + struct carpgroup *c; + + if ((c = carp_group_find(group)) == NULL) { + log_warnx("carp_group_find for %s returned NULL?!", group); + return (-1); + } + + if (c->changed_by + demote < 0) { + log_warnx("carp_demote_set: changed_by + demote < 0"); + return (-1); + } + + if (c->do_demote && carp_demote_ioctl(group, demote) == -1) + return (-1); + + c->changed_by += demote; + + /* enable demotion when we return to 0, i. e. all sessions up */ + if (demote < 0 && c->changed_by == 0) + c->do_demote = 1; + + return (0); +} + +int +carp_demote_ioctl(char *group, int demote) +{ + int s, res; + struct ifgroupreq ifgr; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + log_warn("carp_demote_get: socket"); + return (-1); + } + + bzero(&ifgr, sizeof(ifgr)); + strlcpy(ifgr.ifgr_name, group, sizeof(ifgr.ifgr_name)); + ifgr.ifgr_attrib.ifg_carp_demoted = demote; + + if ((res = ioctl(s, SIOCSIFGATTR, (caddr_t)&ifgr)) == -1) + log_warn("unable to %s the demote state " + "of group '%s'", (demote > 0) ? "increment" : "decrement", + group); + else + log_info("%s the demote state of group '%s'", + (demote > 0) ? "incremented" : "decremented", group); + + close(s); + return (res); +} diff --git a/usr.sbin/ripd/interface.c b/usr.sbin/ripd/interface.c index dd2a242e6e1..a22fc97c90d 100644 --- a/usr.sbin/ripd/interface.c +++ b/usr.sbin/ripd/interface.c @@ -1,4 +1,4 @@ -/* $OpenBSD: interface.c,v 1.5 2007/10/24 19:50:33 claudio Exp $ */ +/* $OpenBSD: interface.c,v 1.6 2008/12/17 14:19:39 michele Exp $ */ /* * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> @@ -74,6 +74,8 @@ if_init(struct ripd_conf *xconf, struct iface *iface) { /* XXX as in ospfd I would like to kill that. This is a design error */ iface->fd = xconf->rip_socket; + + ripe_demote_iface(iface, 0); } int @@ -122,6 +124,11 @@ if_fsm(struct iface *iface, enum iface_event event) if (new_state != 0) iface->state = new_state; + if (old_state == IF_STA_ACTIVE && iface->state == IF_STA_DOWN) + ripe_demote_iface(iface, 0); + if (old_state & IF_STA_DOWN && iface->state == IF_STA_ACTIVE) + ripe_demote_iface(iface, 1); + log_debug("if_fsm: event '%s' resulted in action '%s' and changing " "state for interface %s from '%s' to '%s'", if_event_name(event), if_action_name(iface_fsm[i].action), @@ -440,6 +447,10 @@ if_del(struct iface *iface) log_debug("if_del: interface %s", iface->name); + /* revert the demotion when the interface is deleted */ + if (iface->state == IF_STA_DOWN) + ripe_demote_iface(iface, 1); + /* clear lists etc */ while ((nbr = LIST_FIRST(&iface->nbr_list)) != NULL) nbr_act_del(nbr); diff --git a/usr.sbin/ripd/parse.y b/usr.sbin/ripd/parse.y index bd23cafbdbc..92cd5e96927 100644 --- a/usr.sbin/ripd/parse.y +++ b/usr.sbin/ripd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.20 2008/10/17 13:02:55 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.21 2008/12/17 14:19:39 michele Exp $ */ /* * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> @@ -106,6 +106,7 @@ typedef struct { %token INTERFACE RTLABEL %token COST PASSIVE %token YES NO +%token DEMOTE %token ERROR %token <v.string> STRING %token <v.number> NUMBER @@ -343,12 +344,28 @@ interface_block : '{' optnl interfaceopts_l '}' | '{' optnl '}' ; -interfaceopts_l : interfaceopts_l interfaceoptsl - | interfaceoptsl +interfaceopts_l : interfaceopts_l interfaceoptsl nl + | interfaceoptsl optnl ; -interfaceoptsl : PASSIVE nl { iface->passive = 1; } - | defaults nl +interfaceoptsl : PASSIVE { iface->passive = 1; } + | DEMOTE STRING { + if (strlcpy(iface->demote_group, $2, + sizeof(iface->demote_group)) >= + sizeof(iface->demote_group)) { + yyerror("demote group name \"%s\" too long"); + free($2); + YYERROR; + } + free($2); + if (carp_demote_init(iface->demote_group, + conf->opts & RIPD_OPT_FORCE_DEMOTE) == -1) { + yyerror("error initializing group \"%s\"", + iface->demote_group); + YYERROR; + } + } + | defaults ; %% @@ -387,6 +404,7 @@ lookup(char *s) {"auth-md-keyid", AUTHMDKEYID}, {"auth-type", AUTHTYPE}, {"cost", COST}, + {"demote", DEMOTE}, {"fib-update", FIBUPDATE}, {"interface", INTERFACE}, {"no", NO}, diff --git a/usr.sbin/ripd/ripd.c b/usr.sbin/ripd/ripd.c index 05574b60d71..57f5b5c8f34 100644 --- a/usr.sbin/ripd/ripd.c +++ b/usr.sbin/ripd/ripd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ripd.c,v 1.10 2008/08/05 06:51:12 claudio Exp $ */ +/* $OpenBSD: ripd.c,v 1.11 2008/12/17 14:19:39 michele Exp $ */ /* * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> @@ -131,8 +131,11 @@ main(int argc, char *argv[]) log_init(1); /* log to stderr until daemonized */ - while ((ch = getopt(argc, argv, "dD:f:nv")) != -1) { + while ((ch = getopt(argc, argv, "cdD:f:nv")) != -1) { switch (ch) { + case 'c': + opts |= RIPD_OPT_FORCE_DEMOTE; + break; case 'd': debug = 1; break; @@ -335,10 +338,11 @@ check_child(pid_t pid, const char *pname) void main_dispatch_ripe(int fd, short event, void *bula) { - struct imsgbuf *ibuf = bula; - struct imsg imsg; - ssize_t n; - int shut = 0; + struct imsgbuf *ibuf = bula; + struct imsg imsg; + struct demote_msg dmsg; + ssize_t n; + int shut = 0; switch (event) { case EV_READ: @@ -385,6 +389,12 @@ main_dispatch_ripe(int fd, short event, void *bula) else log_warnx("IFINFO request with wrong len"); break; + case IMSG_DEMOTE: + if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(dmsg)) + fatalx("invalid size of OE request"); + memcpy(&dmsg, imsg.data, sizeof(dmsg)); + carp_demote_set(dmsg.demote_group, dmsg.level); + break; default: log_debug("main_dispatch_ripe: error handling imsg %d", imsg.hdr.type); diff --git a/usr.sbin/ripd/ripd.conf.5 b/usr.sbin/ripd/ripd.conf.5 index 328fe0eea6c..f379b409814 100644 --- a/usr.sbin/ripd/ripd.conf.5 +++ b/usr.sbin/ripd/ripd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ripd.conf.5,v 1.7 2008/01/31 20:00:08 jmc Exp $ +.\" $OpenBSD: ripd.conf.5,v 1.8 2008/12/17 14:19:39 michele Exp $ .\" .\" Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> .\" Copyright (c) 2005, 2006 Esben Norby <norby@openbsd.org> @@ -18,7 +18,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 31 2008 $ +.Dd $Mdocdate: December 17 2008 $ .Dt RIPD.CONF 5 .Os .Sh NAME @@ -194,6 +194,14 @@ The default is .Ic none . Simple authentication uses a plaintext password, up to 16 characters. Crypt authentication uses an MD5 hash. +.It Ic demote Ar group +Increase the +.Xr carp 4 +demotion counter by 1 on the given interface group, usually +.Ar carp , +when the interface state is going down. +The demotion counter will be decreased when the interface +state is active again. .It Ic cost Ar number Cost of the network connected through this interface. Values must be between 1 and 16, inclusive. diff --git a/usr.sbin/ripd/ripd.h b/usr.sbin/ripd/ripd.h index 5dcf57a965b..f14fe7d8b31 100644 --- a/usr.sbin/ripd/ripd.h +++ b/usr.sbin/ripd/ripd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ripd.h,v 1.10 2007/10/24 20:16:49 claudio Exp $ */ +/* $OpenBSD: ripd.h,v 1.11 2008/12/17 14:19:39 michele Exp $ */ /* * Copyright (c) 2004 Esben Norby <norby@openbsd.org> @@ -128,7 +128,8 @@ enum imsg_type { IMSG_FULL_REQUEST, IMSG_REQUEST_ADD, IMSG_SEND_REQUEST, - IMSG_SEND_TRIGGERED_UPDATE + IMSG_SEND_TRIGGERED_UPDATE, + IMSG_DEMOTE }; struct imsg_hdr { @@ -205,6 +206,7 @@ struct iface { LIST_HEAD(, nbr) nbr_list; LIST_HEAD(, nbr_failed) failed_nbr_list; char name[IF_NAMESIZE]; + char demote_group[IFNAMSIZ]; u_int8_t auth_key[MAX_SIMPLE_AUTH_LEN]; struct in_addr addr; struct in_addr dst; @@ -275,6 +277,7 @@ struct ripd_conf { #define RIPD_OPT_VERBOSE 0x00000001 #define RIPD_OPT_VERBOSE2 0x00000002 #define RIPD_OPT_NOACTION 0x00000004 +#define RIPD_OPT_FORCE_DEMOTE 0x00000008 int flags; int options; int rip_socket; @@ -345,6 +348,11 @@ struct ctl_nbr { int iface_state; }; +struct demote_msg { + char demote_group[IF_NAMESIZE]; + int level; +}; + int kif_init(void); int kr_init(int); int kr_change(struct kroute *); @@ -381,6 +389,12 @@ void msgbuf_init(struct msgbuf *); void msgbuf_clear(struct msgbuf *); int msgbuf_write(struct msgbuf *); +/* carp.c */ +int carp_demote_init(char *, int); +void carp_demote_shutdown(void); +int carp_demote_get(char *); +int carp_demote_set(char *, int); + /* imsg.c */ void imsg_init(struct imsgbuf *, int, void (*)(int, short, void *)); ssize_t imsg_read(struct imsgbuf *); diff --git a/usr.sbin/ripd/ripe.c b/usr.sbin/ripd/ripe.c index 93c594aced6..7b30822b3b7 100644 --- a/usr.sbin/ripd/ripe.c +++ b/usr.sbin/ripd/ripe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ripe.c,v 1.7 2008/11/23 13:09:31 michele Exp $ */ +/* $OpenBSD: ripe.c,v 1.8 2008/12/17 14:19:39 michele Exp $ */ /* * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> @@ -525,3 +525,23 @@ ripe_nbr_ctl(struct ctl_conn *c) imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, NULL, 0); } + +void +ripe_demote_iface(struct iface *iface, int active) +{ + struct demote_msg dmsg; + + if (ripd_process != PROC_RIP_ENGINE || + iface->demote_group[0] == '\0') + return; + + bzero(&dmsg, sizeof(dmsg)); + strlcpy(dmsg.demote_group, iface->demote_group, + sizeof(dmsg.demote_group)); + if (active) + dmsg.level = -1; + else + dmsg.level = 1; + + ripe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg)); +} diff --git a/usr.sbin/ripd/ripe.h b/usr.sbin/ripd/ripe.h index 30487d975ec..7514d6baad9 100644 --- a/usr.sbin/ripd/ripe.h +++ b/usr.sbin/ripd/ripe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ripe.h,v 1.8 2007/10/24 20:52:50 claudio Exp $ */ +/* $OpenBSD: ripe.h,v 1.9 2008/12/17 14:19:39 michele Exp $ */ /* * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> @@ -115,6 +115,7 @@ void ripe_dispatch_main(int, short, void *); void ripe_dispatch_rde(int, short, void *); void ripe_iface_ctl(struct ctl_conn *, unsigned int); void ripe_nbr_ctl(struct ctl_conn *); +void ripe_demote_iface(struct iface *, int); /* auth.c */ int auth_validate(u_int8_t **, u_int16_t *, struct iface *, struct nbr *, |