summaryrefslogtreecommitdiff
path: root/usr.sbin/ripd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/ripd')
-rw-r--r--usr.sbin/ripd/Makefile4
-rw-r--r--usr.sbin/ripd/carp.c181
-rw-r--r--usr.sbin/ripd/interface.c13
-rw-r--r--usr.sbin/ripd/parse.y28
-rw-r--r--usr.sbin/ripd/ripd.c22
-rw-r--r--usr.sbin/ripd/ripd.conf.512
-rw-r--r--usr.sbin/ripd/ripd.h18
-rw-r--r--usr.sbin/ripd/ripe.c22
-rw-r--r--usr.sbin/ripd/ripe.h3
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 *,