summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bgpd/bgpd.c46
-rw-r--r--usr.sbin/bgpd/bgpd.h15
-rw-r--r--usr.sbin/bgpd/parse.y25
-rw-r--r--usr.sbin/bgpd/rde.c81
-rw-r--r--usr.sbin/bgpd/rde.h18
-rw-r--r--usr.sbin/bgpd/rde_decide.c17
-rw-r--r--usr.sbin/bgpd/rde_rib.c65
-rw-r--r--usr.sbin/bgpd/session.h7
8 files changed, 220 insertions, 54 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index 39a8e73eab8..8bb50430b39 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.67 2004/01/17 18:05:46 henning Exp $ */
+/* $OpenBSD: bgpd.c,v 1.68 2004/01/17 19:35:35 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -93,7 +93,9 @@ main(int argc, char *argv[])
{
struct bgpd_config conf;
struct peer *peer_l, *p, *next;
- struct mrt_head mrtconf;
+ struct mrt_head mrt_l;
+ struct network_head net_l;
+ struct network *net;
struct mrt *(mrt[POLL_MAX]);
struct pollfd pfd[POLL_MAX];
pid_t io_pid = 0, rde_pid = 0, pid;
@@ -110,7 +112,8 @@ main(int argc, char *argv[])
log_init(1); /* log to stderr until daemonized */
bzero(&conf, sizeof(conf));
- LIST_INIT(&mrtconf);
+ LIST_INIT(&mrt_l);
+ TAILQ_INIT(&net_l);
peer_l = NULL;
while ((ch = getopt(argc, argv, "dD:f:nv")) != -1) {
@@ -141,7 +144,7 @@ main(int argc, char *argv[])
}
}
- if (parse_config(conffile, &conf, &mrtconf, &peer_l))
+ if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l))
exit(1);
if (conf.opts & BGPD_OPT_NOACTION) {
@@ -179,7 +182,7 @@ main(int argc, char *argv[])
fatalx("control socket setup failed");
/* fork children */
- rde_pid = rde_main(&conf, peer_l, pipe_m2r, pipe_s2r);
+ rde_pid = rde_main(&conf, peer_l, &net_l, pipe_m2r, pipe_s2r);
io_pid = session_main(&conf, peer_l, pipe_m2s, pipe_s2r);
setproctitle("parent");
@@ -207,6 +210,11 @@ main(int argc, char *argv[])
next = p->next;
free(p);
}
+ for (net = TAILQ_FIRST(&net_l); net != TAILQ_END(&net_l);
+ net = TAILQ_FIRST(&net_l)) {
+ TAILQ_REMOVE(&net_l, net, network_l);
+ free(net);
+ }
while (quit == 0) {
pfd[PFD_PIPE_SESSION].fd = ibuf_se.sock;
@@ -220,7 +228,7 @@ main(int argc, char *argv[])
pfd[PFD_SOCK_ROUTE].fd = rfd;
pfd[PFD_SOCK_ROUTE].events = POLLIN;
i = PFD_MRT_START;
- i = mrt_select(&mrtconf, pfd, mrt, i, POLL_MAX, &timeout);
+ i = mrt_select(&mrt_l, pfd, mrt, i, POLL_MAX, &timeout);
if ((nfds = poll(pfd, i, INFTIM)) == -1)
if (errno != EINTR) {
@@ -243,14 +251,14 @@ main(int argc, char *argv[])
if (nfds > 0 && pfd[PFD_PIPE_SESSION].revents & POLLIN) {
nfds--;
if (dispatch_imsg(&ibuf_se, PFD_PIPE_SESSION,
- &mrtconf) == -1)
+ &mrt_l) == -1)
quit = 1;
}
if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLIN) {
nfds--;
if (dispatch_imsg(&ibuf_rde, PFD_PIPE_ROUTE,
- &mrtconf) == -1)
+ &mrt_l) == -1)
quit = 1;
}
@@ -270,7 +278,7 @@ main(int argc, char *argv[])
if (reconfig) {
logit(LOG_CRIT, "rereading config");
- reconfigure(conffile, &conf, &mrtconf, peer_l);
+ reconfigure(conffile, &conf, &mrt_l, peer_l);
reconfig = 0;
}
@@ -283,7 +291,7 @@ main(int argc, char *argv[])
}
if (mrtdump == 1) {
- mrt_handler(&mrtconf);
+ mrt_handler(&mrt_l);
mrtdump = 0;
}
}
@@ -328,12 +336,14 @@ check_child(pid_t pid, const char *pname)
}
int
-reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrtc,
+reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
struct peer *peer_l)
{
+ struct network_head net_l;
+ struct network *n;
struct peer *p, *next;
- if (parse_config(conffile, conf, mrtc, &peer_l)) {
+ if (parse_config(conffile, conf, mrt_l, &peer_l, &net_l)) {
logit(LOG_CRIT, "config file %s has errors, not reloading",
conffile);
return (-1);
@@ -355,6 +365,14 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrtc,
return (-1);
free(p);
}
+ for (n = TAILQ_FIRST(&net_l); n != TAILQ_END(&net_l);
+ n = TAILQ_FIRST(&net_l)) {
+ if (imsg_compose(&ibuf_rde, IMSG_RECONF_NETWORK, 0,
+ &n->net, sizeof(struct network_config)) == -1)
+ return (-1);
+ TAILQ_REMOVE(&net_l, n, network_l);
+ free(n);
+ }
if (imsg_compose(&ibuf_se, IMSG_RECONF_DONE, 0, NULL, 0) == -1 ||
imsg_compose(&ibuf_rde, IMSG_RECONF_DONE, 0, NULL, 0) == -1)
return (-1);
@@ -363,7 +381,7 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrtc,
}
int
-dispatch_imsg(struct imsgbuf *ibuf, int idx, struct mrt_head *mrtc)
+dispatch_imsg(struct imsgbuf *ibuf, int idx, struct mrt_head *mrt_l)
{
struct imsg imsg;
int n;
@@ -386,7 +404,7 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx, struct mrt_head *mrtc)
switch (imsg.hdr.type) {
case IMSG_MRT_MSG:
case IMSG_MRT_END:
- if (mrt_queue(mrtc, &imsg) == -1)
+ if (mrt_queue(mrt_l, &imsg) == -1)
logit(LOG_CRIT, "mrt_queue failed.");
break;
case IMSG_KROUTE_CHANGE:
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 89e6259eeb5..419d900cea9 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.70 2004/01/17 18:27:19 henning Exp $ */
+/* $OpenBSD: bgpd.h,v 1.71 2004/01/17 19:35:36 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -140,6 +140,18 @@ struct peer_config {
enum reconf_action reconf_action;
};
+struct network_config {
+ struct bgpd_addr prefix;
+ u_int8_t prefixlen;
+};
+
+TAILQ_HEAD(network_head, network);
+
+struct network {
+ struct network_config net;
+ TAILQ_ENTRY(network) network_l;
+};
+
/* ipc messages */
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
@@ -156,6 +168,7 @@ enum imsg_type {
IMSG_NONE,
IMSG_RECONF_CONF,
IMSG_RECONF_PEER,
+ IMSG_RECONF_NETWORK,
IMSG_RECONF_DONE,
IMSG_UPDATE,
IMSG_UPDATE_ERR,
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index 2044a418090..16a797bb886 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.35 2004/01/17 19:15:07 henning Exp $ */
+/* $OpenBSD: parse.y,v 1.36 2004/01/17 19:35:36 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -38,6 +38,7 @@
static struct bgpd_config *conf;
static struct mrt_head *mrtconf;
+static struct network_head *netconf;
static struct peer *peer_l;
static struct peer *curpeer;
static struct peer *curgroup;
@@ -87,7 +88,7 @@ typedef struct {
%token SET
%token AS ROUTERID HOLDTIME YMIN LISTEN ON NO FIBUPDATE
-%token GROUP NEIGHBOR
+%token GROUP NEIGHBOR NETWORK
%token REMOTEAS DESCR LOCALADDR MULTIHOP PASSIVE MAXPREFIX ANNOUNCE
%token ERROR
%token DUMP MSG IN TABLE
@@ -197,8 +198,21 @@ conf_main : AS number {
if (add_mrtconfig(MRT_TABLE_DUMP, $3, $4) == -1)
YYERROR;
}
+ | NETWORK address '/' number {
+ struct network *n;
-;
+ if ((n = calloc(1, sizeof(struct network))) == NULL)
+ fatal("new_network");
+ n->net.prefix.af = AF_INET;
+ n->net.prefix.v4 = $2;
+ if ($4 > 32) {
+ yyerror("invalid netmask");
+ YYERROR;
+ }
+ n->net.prefixlen = $4;
+ TAILQ_INSERT_TAIL(netconf, n, network_l);
+ }
+ ;
address : STRING {
int n;
@@ -385,6 +399,7 @@ lookup(char *s)
{ "msg", MSG},
{ "multihop", MULTIHOP},
{ "neighbor", NEIGHBOR},
+ { "network", NETWORK},
{ "on", ON},
{ "passive", PASSIVE},
{ "remote-as", REMOTEAS},
@@ -599,7 +614,7 @@ top:
int
parse_config(char *filename, struct bgpd_config *xconf,
- struct mrt_head *xmconf, struct peer **xpeers)
+ struct mrt_head *xmconf, struct peer **xpeers, struct network_head* nc)
{
struct sym *sym, *next;
@@ -608,6 +623,8 @@ parse_config(char *filename, struct bgpd_config *xconf,
if ((mrtconf = calloc(1, sizeof(struct mrt_head))) == NULL)
fatal(NULL);
LIST_INIT(mrtconf);
+ netconf = nc;
+ TAILQ_INIT(netconf);
peer_l = NULL;
curpeer = NULL;
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 4faa851c14c..082f67df21b 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.63 2004/01/13 13:45:49 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.64 2004/01/17 19:35:36 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -57,9 +57,14 @@ struct rde_peer *peer_get(u_int32_t);
void peer_up(u_int32_t, struct session_up *);
void peer_down(u_int32_t);
+void network_init(struct network_head *);
+void network_add(struct network_config *);
+
volatile sig_atomic_t rde_quit = 0;
struct bgpd_config *conf, *nconf;
+time_t reloadtime;
struct rde_peer_head peerlist;
+struct rde_peer peerself;
struct imsgbuf ibuf_se;
struct imsgbuf ibuf_main;
@@ -81,8 +86,8 @@ u_long pathhashsize = 1024;
u_long nexthophashsize = 64;
int
-rde_main(struct bgpd_config *config, struct peer *peer_l, int pipe_m2r[2],
- int pipe_s2r[2])
+rde_main(struct bgpd_config *config, struct peer *peer_l,
+ struct network_head *net_l, int pipe_m2r[2], int pipe_s2r[2])
{
pid_t pid;
struct passwd *pw;
@@ -124,13 +129,16 @@ rde_main(struct bgpd_config *config, struct peer *peer_l, int pipe_m2r[2],
close(pipe_m2r[0]);
/* initialize the RIB structures */
- peer_init(peer_l, peerhashsize);
- path_init(pathhashsize);
- nexthop_init(nexthophashsize);
- pt_init();
imsg_init(&ibuf_se, pipe_s2r[1]);
imsg_init(&ibuf_main, pipe_m2r[1]);
+ pt_init();
+ path_init(pathhashsize);
+ nexthop_init(nexthophashsize);
+ peer_init(peer_l, peerhashsize);
+
+ network_init(net_l);
+
logit(LOG_INFO, "route decision engine ready");
while (rde_quit == 0) {
@@ -235,6 +243,7 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
switch (imsg.hdr.type) {
case IMSG_RECONF_CONF:
+ reloadtime = time(NULL);
if ((nconf = malloc(sizeof(struct bgpd_config))) ==
NULL)
fatal(NULL);
@@ -249,6 +258,9 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
sizeof(struct peer_config));
p->conf.reconf_action = RECONF_KEEP;
break;
+ case IMSG_RECONF_NETWORK:
+ network_add(imsg.data);
+ break;
case IMSG_RECONF_DONE:
if (nconf == NULL)
fatalx("got IMSG_RECONF_DONE but no config");
@@ -270,6 +282,7 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
memcpy(conf, nconf, sizeof(struct bgpd_config));
free(nconf);
nconf = NULL;
+ prefix_network_clean(&peerself, reloadtime);
logit(LOG_INFO, "RDE reconfigured");
break;
case IMSG_NEXTHOP_UPDATE:
@@ -588,13 +601,16 @@ rde_send_kroute(struct prefix *new, struct prefix *old)
enum imsg_type type;
if ((old == NULL || old->aspath->nexthop == NULL ||
- old->aspath->nexthop->state != NEXTHOP_REACH) &&
+ old->aspath->nexthop->state != NEXTHOP_REACH ||
+ old->aspath->nexthop->flags & NEXTHOP_ANNOUNCE) &&
(new == NULL || new->aspath->nexthop == NULL ||
- new->aspath->nexthop->state != NEXTHOP_REACH))
+ new->aspath->nexthop->state != NEXTHOP_REACH ||
+ new->aspath->nexthop->flags & NEXTHOP_ANNOUNCE))
return;
if (new == NULL || new->aspath->nexthop == NULL ||
- new->aspath->nexthop->state != NEXTHOP_REACH) {
+ new->aspath->nexthop->state != NEXTHOP_REACH ||
+ new->aspath->nexthop->flags & NEXTHOP_ANNOUNCE) {
type = IMSG_KROUTE_DELETE;
p = old;
kr.nexthop = 0;
@@ -853,3 +869,48 @@ peer_down(u_int32_t id)
if (peer->conf.reconf_action == RECONF_DELETE)
peer_remove(peer);
}
+
+/*
+ * network announcement stuff
+ */
+void
+network_init(struct network_head *net_l)
+{
+ struct network *n;
+
+ reloadtime = time(NULL);
+ bzero(&peerself, sizeof(peerself));
+ peerself.state = PEER_UP;
+ peerself.remote_bgpid = conf->bgpid;
+ peerself.conf.max_prefix = ULONG_MAX;
+ peerself.conf.remote_as = conf->as;
+ snprintf(peerself.conf.descr, sizeof(peerself.conf.descr),
+ "LOCAL AS %hd", conf->as);
+
+ for (n = TAILQ_FIRST(net_l); n != TAILQ_END(net_l);
+ n = TAILQ_FIRST(net_l)) {
+ TAILQ_REMOVE(net_l, n, network_l);
+ network_add(&n->net);
+ free(n);
+ }
+}
+
+void
+network_add(struct network_config *nc)
+{
+ struct attr_flags attrs;
+
+ bzero(&attrs, sizeof(attrs));
+
+ attrs.aspath = aspath_create(NULL, 0);
+ attrs.nexthop = INADDR_ANY;
+ /* med = 0 */
+ /* lpref = 0 */
+ attrs.origin = ORIGIN_IGP;
+ TAILQ_INIT(&attrs.others);
+
+ logit(LOG_DEBUG, "adding network %s/%d",
+ inet_ntoa(nc->prefix.v4), nc->prefixlen);
+ path_update(&peerself, &attrs, &nc->prefix, nc->prefixlen);
+}
+
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index 4c681ab967d..37ce57ba7ae 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.20 2004/01/13 16:08:04 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.21 2004/01/17 19:35:36 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -152,6 +152,10 @@ struct nexthop {
LIST_ENTRY(nexthop) nexthop_l;
enum nexthop_state state;
#if 0
+ /*
+ * currently we use the boolean nexthop state, this could be exchanged
+ * with a variable coast with a max for unreachable.
+ */
u_int32_t costs;
#endif
struct aspath_head path_h;
@@ -159,7 +163,9 @@ struct nexthop {
struct bgpd_addr true_nexthop;
struct bgpd_addr nexthop_net;
u_int8_t nexthop_netlen;
- u_int8_t connected;
+ u_int8_t flags;
+#define NEXTHOP_CONNECTED 0x1
+#define NEXTHOP_ANNOUNCE 0x2
};
LIST_HEAD(prefix_head, prefix);
@@ -171,13 +177,6 @@ struct rde_aspath {
struct nexthop *nexthop;
u_int16_t prefix_cnt; /* # of prefixes */
u_int16_t active_cnt; /* # of active prefixes */
- /*
- * currently we use the boolean nexthop state, this could be exchanged
- * with a variable coast with a max for unreachable.
- */
-#if 0
- u_int32_t nexthop_costs;
-#endif
struct attr_flags flags;
};
@@ -253,6 +252,7 @@ void prefix_remove(struct rde_peer *, struct bgpd_addr *, int);
struct prefix *prefix_bypeer(struct pt_entry *, struct rde_peer *);
void prefix_updateall(struct rde_aspath *, enum nexthop_state);
void prefix_destroy(struct prefix *);
+void prefix_network_clean(struct rde_peer *, time_t);
void nexthop_init(u_long);
void nexthop_add(struct rde_aspath *);
diff --git a/usr.sbin/bgpd/rde_decide.c b/usr.sbin/bgpd/rde_decide.c
index 1ca553fca50..d5ddf19e674 100644
--- a/usr.sbin/bgpd/rde_decide.c
+++ b/usr.sbin/bgpd/rde_decide.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_decide.c,v 1.21 2004/01/13 17:11:29 henning Exp $ */
+/* $OpenBSD: rde_decide.c,v 1.22 2004/01/17 19:35:36 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -537,12 +537,10 @@ up_generate_attr(struct rde_peer *peer, struct update_attr *upa,
if (peer->conf.ebgp == 0) {
/*
* if directly connected use peer->local_addr
- * This is only the case for announcements, which we
- * currenlty don't handle. It is currently unclear how
- * to recognize those routes. The connected flag is not
- * enough.
*/
- if (a->nexthop == peer->remote_addr.v4.s_addr)
+ if (nh->flags & NEXTHOP_ANNOUNCE)
+ nexthop = peer->local_addr.v4.s_addr;
+ else if (a->nexthop == peer->remote_addr.v4.s_addr)
/*
* per rfc: if remote peer address is equal to
* the nexthop set the nexthop to our local address.
@@ -553,7 +551,7 @@ up_generate_attr(struct rde_peer *peer, struct update_attr *upa,
nexthop = nh->exit_nexthop.v4.s_addr;
} else if (peer->conf.distance == 1) {
/* ebgp directly connected */
- if (nh->connected) {
+ if (nh->flags & NEXTHOP_CONNECTED) {
mask = 0xffffffff << (32 - nh->nexthop_netlen);
mask = htonl(mask);
if ((peer->remote_addr.v4.s_addr & mask) ==
@@ -567,8 +565,9 @@ up_generate_attr(struct rde_peer *peer, struct update_attr *upa,
} else
/* ebgp multihop */
/*
- * XXX for ebgp multihop nh->connected should always be false
- * so it should be possible to unify the two ebgp cases.
+ * XXX for ebgp multihop nh->flags should never have
+ * NEXTHOP_CONNECTED set so it should be possible to unify the
+ * two ebgp cases.
*/
nexthop = peer->local_addr.v4.s_addr;
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index c3dcd2931d3..6957ded483c 100644
--- a/usr.sbin/bgpd/rde_rib.c
+++ b/usr.sbin/bgpd/rde_rib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_rib.c,v 1.24 2004/01/13 16:08:04 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.25 2004/01/17 19:35:36 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -762,6 +762,8 @@ prefix_add(struct rde_aspath *asp, struct bgpd_addr *prefix, int prefixlen)
if (needlink == 1)
prefix_link(p, pte, asp);
+ else
+ p->lastchange = time(NULL);
return pte;
}
@@ -843,7 +845,7 @@ prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen)
return;
p = prefix_bypeer(pte, peer);
- if (p == NULL) /* Got a dummy withdrawn request. */
+ if (p == NULL) /* Got a dummy withdrawn request. */
return;
asp = p->aspath;
@@ -906,6 +908,38 @@ prefix_destroy(struct prefix *p)
}
/*
+ * helper function to clean up the connected networks after a reload
+ */
+void
+prefix_network_clean(struct rde_peer *peer, time_t reloadtime)
+{
+ struct rde_aspath *asp, *xasp;
+ struct prefix *p, *xp;
+ struct pt_entry *pte;
+
+ for (asp = LIST_FIRST(&peer->path_h);
+ asp != LIST_END(&peer->path_h);
+ asp = xasp) {
+ xasp = LIST_NEXT(asp, peer_l);
+ for (p = LIST_FIRST(&asp->prefix_h);
+ p != LIST_END(&asp->prefix_h);
+ p = xp) {
+ xp = LIST_NEXT(p, path_l);
+ if (reloadtime > p->lastchange) {
+ pte = p->prefix;
+ prefix_unlink(p);
+ prefix_free(p);
+
+ if (pt_empty(pte))
+ pt_remove(pte);
+ if (path_empty(asp))
+ path_destroy(asp);
+ }
+ }
+ }
+}
+
+/*
* Link a prefix into the different parent objects.
*/
static void
@@ -1030,7 +1064,8 @@ struct nexthop_table {
void
nexthop_init(u_long hashsize)
{
- u_long hs, i;
+ struct nexthop *nh;
+ u_long hs, i;
for (hs = 1; hs < hashsize; hs <<= 1)
;
@@ -1042,6 +1077,23 @@ nexthop_init(u_long hashsize)
LIST_INIT(&nexthoptable.nexthop_hashtbl[i]);
nexthoptable.nexthop_hashmask = hs - 1;
+
+ /* add dummy entry for connected networks */
+ nh = nexthop_alloc();
+ nh->state = NEXTHOP_REACH;
+ nh->exit_nexthop.af = AF_INET;
+ nh->exit_nexthop.v4.s_addr = INADDR_ANY;
+
+ LIST_INSERT_HEAD(NEXTHOP_HASH(nh->exit_nexthop.v4.s_addr), nh,
+ nexthop_l);
+
+ memcpy(&nh->true_nexthop, &nh->exit_nexthop,
+ sizeof(nh->true_nexthop));
+ nh->nexthop_netlen = 0;
+ nh->nexthop_net.af = AF_INET;
+ nh->nexthop_net.v4.s_addr = INADDR_ANY;
+
+ nh->flags = NEXTHOP_ANNOUNCE;
}
void
@@ -1080,6 +1132,10 @@ nexthop_remove(struct rde_aspath *asp)
/* see if list is empty */
nh = asp->nexthop;
+ /* never remove the dummy announce entry */
+ if (nh->flags & NEXTHOP_ANNOUNCE)
+ return;
+
if (LIST_EMPTY(&nh->path_h)) {
LIST_REMOVE(nh, nexthop_l);
rde_send_nexthop(&nh->exit_nexthop, 0);
@@ -1132,7 +1188,8 @@ nexthop_update(struct kroute_nexthop *msg)
nh->nexthop_net.af = AF_INET;
nh->nexthop_net.v4.s_addr = msg->kr.prefix;
- nh->connected = msg->connected;
+ if (msg->connected)
+ nh->flags |= NEXTHOP_CONNECTED;
LIST_FOREACH(asp, &nh->path_h, nexthop_l) {
path_updateall(asp, nh->state);
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index 8bda59bf73b..540049ff287 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.19 2004/01/11 18:42:25 henning Exp $ */
+/* $OpenBSD: session.h,v 1.20 2004/01/17 19:35:36 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -172,14 +172,15 @@ void log_conn_attempt(const struct peer *, struct in_addr);
/* parse.y */
int parse_config(char *, struct bgpd_config *, struct mrt_head *,
- struct peer **);
+ struct peer **, struct network_head *);
/* config.c */
int merge_config(struct bgpd_config *, struct bgpd_config *,
struct peer *);
/* rde.c */
-int rde_main(struct bgpd_config *, struct peer *, int[2], int[2]);
+int rde_main(struct bgpd_config *, struct peer *, struct network_head *,
+ int[2], int[2]);
/* control.c */
int control_listen(void);