summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2013-06-04 02:25:28 +0000
committerclaudio <claudio@openbsd.org>2013-06-04 02:25:28 +0000
commit83dcf7379d84ec59098a3fd7e0cc9e7c08f87ce3 (patch)
tree62a39a40a0fb33ec6939ef10bf800f2ffd0453fa
parentSince we now have shm_{open,unlink}(), add the S_TYPEIS{MQ,SEM,SHM}() (diff)
downloadwireguard-openbsd-83dcf7379d84ec59098a3fd7e0cc9e7c08f87ce3.tar.xz
wireguard-openbsd-83dcf7379d84ec59098a3fd7e0cc9e7c08f87ce3.zip
Implement support for adjacencies and targeted hellos
Refactor adjacencies out of the neighbor handling so that it is possible to have more complex topologies with targeted sessions. From Renato Westphal
-rw-r--r--usr.sbin/ldpd/Makefile4
-rw-r--r--usr.sbin/ldpd/control.c5
-rw-r--r--usr.sbin/ldpd/hello.c142
-rw-r--r--usr.sbin/ldpd/interface.c11
-rw-r--r--usr.sbin/ldpd/ldp.h7
-rw-r--r--usr.sbin/ldpd/ldpd.c4
-rw-r--r--usr.sbin/ldpd/ldpd.conf.545
-rw-r--r--usr.sbin/ldpd/ldpd.h59
-rw-r--r--usr.sbin/ldpd/ldpe.c50
-rw-r--r--usr.sbin/ldpd/ldpe.h52
-rw-r--r--usr.sbin/ldpd/log.c4
-rw-r--r--usr.sbin/ldpd/neighbor.c64
-rw-r--r--usr.sbin/ldpd/packet.c32
-rw-r--r--usr.sbin/ldpd/parse.y159
-rw-r--r--usr.sbin/ldpd/printconf.c28
15 files changed, 464 insertions, 202 deletions
diff --git a/usr.sbin/ldpd/Makefile b/usr.sbin/ldpd/Makefile
index 792177b68fd..3ccc3e7b136 100644
--- a/usr.sbin/ldpd/Makefile
+++ b/usr.sbin/ldpd/Makefile
@@ -1,7 +1,7 @@
-# $OpenBSD: Makefile,v 1.4 2012/04/12 17:33:43 claudio Exp $
+# $OpenBSD: Makefile,v 1.5 2013/06/04 02:25:28 claudio Exp $
PROG= ldpd
-SRCS= accept.c address.c control.c hello.c init.c interface.c \
+SRCS= accept.c adjacency.c address.c control.c hello.c init.c interface.c \
keepalive.c kroute.c labelmapping.c lde.c lde_lib.c ldpd.c ldpe.c \
log.c neighbor.c notification.c packet.c parse.y printconf.c
diff --git a/usr.sbin/ldpd/control.c b/usr.sbin/ldpd/control.c
index 7b6aa47dcea..5da5b4d4c70 100644
--- a/usr.sbin/ldpd/control.c
+++ b/usr.sbin/ldpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.11 2013/03/11 17:40:11 deraadt Exp $ */
+/* $OpenBSD: control.c,v 1.12 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -248,6 +248,9 @@ control_dispatch_imsg(int fd, short event, void *bula)
0, -1, NULL, 0);
}
break;
+ case IMSG_CTL_SHOW_DISCOVERY:
+ ldpe_adj_ctl(c);
+ break;
case IMSG_CTL_SHOW_LIB:
c->iev.ibuf.pid = imsg.hdr.pid;
ldpe_imsg_compose_lde(imsg.hdr.type, 0, imsg.hdr.pid,
diff --git a/usr.sbin/ldpd/hello.c b/usr.sbin/ldpd/hello.c
index 9d887ace5ad..f1145f0dc9e 100644
--- a/usr.sbin/ldpd/hello.c
+++ b/usr.sbin/ldpd/hello.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hello.c,v 1.19 2013/06/04 00:56:49 claudio Exp $ */
+/* $OpenBSD: hello.c,v 1.20 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -36,23 +36,42 @@
#include "log.h"
#include "ldpe.h"
+extern struct ldpd_conf *leconf;
+
int tlv_decode_hello_prms(char *, u_int16_t, u_int16_t *, u_int16_t *);
int tlv_decode_opt_hello_prms(char *, u_int16_t, struct in_addr *,
u_int32_t *);
-int gen_hello_prms_tlv(struct iface *, struct ibuf *);
-int gen_opt4_hello_prms_tlv(struct iface *, struct ibuf *);
+int gen_hello_prms_tlv(struct ibuf *buf, u_int16_t, u_int16_t);
+int gen_opt4_hello_prms_tlv(struct ibuf *, u_int16_t, u_int32_t);
int
-send_hello(struct iface *iface)
+send_hello(enum hello_type type, struct iface *iface, struct tnbr *tnbr)
{
struct sockaddr_in dst;
struct ibuf *buf;
- u_int16_t size;
+ u_int16_t size, holdtime = 0, flags = 0;
+ int fd = 0;
dst.sin_port = htons(LDP_PORT);
dst.sin_family = AF_INET;
dst.sin_len = sizeof(struct sockaddr_in);
- inet_aton(AllRouters, &dst.sin_addr);
+
+ switch (type) {
+ case HELLO_LINK:
+ inet_aton(AllRouters, &dst.sin_addr);
+ holdtime = iface->hello_holdtime;
+ flags = 0;
+ fd = iface->discovery_fd;
+ break;
+ case HELLO_TARGETED:
+ dst.sin_addr.s_addr = tnbr->addr.s_addr;
+ holdtime = tnbr->hello_holdtime;
+ flags = TARGETED_HELLO;
+ if (tnbr->flags & F_TNBR_CONFIGURED)
+ flags |= REQUEST_TARG_HELLO;
+ fd = tnbr->discovery_fd;
+ break;
+ }
if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL)
fatal("send_hello");
@@ -67,10 +86,10 @@ send_hello(struct iface *iface)
gen_msg_tlv(buf, MSG_TYPE_HELLO, size);
- gen_hello_prms_tlv(iface, buf);
- gen_opt4_hello_prms_tlv(iface, buf);
+ gen_hello_prms_tlv(buf, holdtime, flags);
+ gen_opt4_hello_prms_tlv(buf, TLV_TYPE_IPV4TRANSADDR, ldpe_router_id());
- send_packet(iface, buf->buf, buf->wpos, &dst);
+ send_packet(fd, iface, buf->buf, buf->wpos, &dst);
ibuf_free(buf);
return (0);
@@ -81,12 +100,15 @@ recv_hello(struct iface *iface, struct in_addr src, char *buf, u_int16_t len)
{
struct ldp_msg hello;
struct ldp_hdr ldp;
- struct nbr *nbr = NULL;
- struct in_addr address;
+ struct adj *adj;
+ struct nbr *nbr;
struct in_addr lsr_id;
+ struct in_addr transport_addr;
u_int32_t conf_number;
u_int16_t holdtime, flags;
int r;
+ struct hello_source source;
+ struct tnbr *tnbr = NULL;
bcopy(buf, &ldp, sizeof(ldp));
buf += LDP_HDR_SIZE;
@@ -105,15 +127,47 @@ recv_hello(struct iface *iface, struct in_addr src, char *buf, u_int16_t len)
return;
}
+ bzero(&source, sizeof(source));
+ if (flags & TARGETED_HELLO) {
+ tnbr = tnbr_find(src);
+ if (!tnbr) {
+ if (!((flags & REQUEST_TARG_HELLO) &&
+ leconf->flags & LDPD_FLAG_TH_ACCEPT))
+ return;
+
+ tnbr = tnbr_new(src, 0);
+ if (!tnbr)
+ return;
+ tnbr_init(leconf, tnbr);
+ LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry);
+ }
+ source.type = HELLO_TARGETED;
+ source.target = tnbr;
+ } else {
+ if (ldp.lspace_id != 0) {
+ log_debug("recv_hello: invalid label space "
+ "ID %s, interface %s", ldp.lspace_id,
+ iface->name);
+ return;
+ }
+ source.type = HELLO_LINK;
+ source.link.iface = iface;
+ source.link.src_addr.s_addr = src.s_addr;
+ }
+
buf += r;
len -= r;
- r = tlv_decode_opt_hello_prms(buf, len, &address, &conf_number);
+ r = tlv_decode_opt_hello_prms(buf, len, &transport_addr,
+ &conf_number);
if (r == -1) {
log_debug("recv_hello: neighbor %s: failed to decode "
"optional params", inet_ntoa(lsr_id));
return;
}
+ if (transport_addr.s_addr == INADDR_ANY)
+ transport_addr.s_addr = src.s_addr;
+
if (r != len) {
log_debug("recv_hello: neighbor %s: unexpected data in message",
inet_ntoa(lsr_id));
@@ -122,29 +176,46 @@ recv_hello(struct iface *iface, struct in_addr src, char *buf, u_int16_t len)
nbr = nbr_find_ldpid(ldp.lsr_id);
if (!nbr) {
- struct in_addr a;
-
- if (address.s_addr == INADDR_ANY)
- a = src;
- else
- a = address;
-
- nbr = nbr_new(lsr_id, a);
-
- /* set neighbor parameters */
- nbr->hello_type = flags;
+ /* create new adjacency and new neighbor */
+ nbr = nbr_new(lsr_id, transport_addr);
+ adj = adj_new(nbr, &source, holdtime, transport_addr);
+ } else {
+ adj = adj_find(nbr, &source);
+ if (!adj) {
+ /* create new adjacency for existing neighbor */
+ adj = adj_new(nbr, &source, holdtime, transport_addr);
+
+ if (nbr->addr.s_addr != transport_addr.s_addr)
+ log_warnx("recv_hello: neighbor %s: multiple "
+ "adjacencies advertising different "
+ "transport addresses", inet_ntoa(lsr_id));
+ }
+ }
- /* XXX: lacks support for targeted hellos */
+ /* always update the holdtime to properly handle runtime changes */
+ switch (source.type) {
+ case HELLO_LINK:
if (holdtime == 0)
holdtime = LINK_DFLT_HOLDTIME;
-
- if (iface->holdtime < holdtime)
- nbr->holdtime = iface->holdtime;
+ if (iface->hello_holdtime < holdtime)
+ adj->holdtime = iface->hello_holdtime;
+ else
+ adj->holdtime = holdtime;
+ break;
+ case HELLO_TARGETED:
+ if (holdtime == 0)
+ holdtime = TARGETED_DFLT_HOLDTIME;
+ if (tnbr->hello_holdtime < holdtime)
+ adj->holdtime = tnbr->hello_holdtime;
else
- nbr->holdtime = holdtime;
+ adj->holdtime = holdtime;
+ break;
}
- nbr_fsm(nbr, NBR_EVT_HELLO_RCVD);
+ if (adj->holdtime != INFINITE_HOLDTIME)
+ adj_start_itimer(adj);
+ else
+ adj_stop_itimer(adj);
if (nbr->state == NBR_STA_PRESENT && nbr_session_active_role(nbr) &&
!nbr_pending_connect(nbr) && !nbr_pending_idtimer(nbr))
@@ -152,29 +223,28 @@ recv_hello(struct iface *iface, struct in_addr src, char *buf, u_int16_t len)
}
int
-gen_hello_prms_tlv(struct iface *iface, struct ibuf *buf)
+gen_hello_prms_tlv(struct ibuf *buf, u_int16_t holdtime, u_int16_t flags)
{
struct hello_prms_tlv parms;
bzero(&parms, sizeof(parms));
parms.type = htons(TLV_TYPE_COMMONHELLO);
parms.length = htons(sizeof(parms.holdtime) + sizeof(parms.flags));
- /* XXX */
- parms.holdtime = htons(iface->holdtime);
- parms.flags = 0;
+ parms.holdtime = htons(holdtime);
+ parms.flags = htons(flags);
return (ibuf_add(buf, &parms, sizeof(parms)));
}
int
-gen_opt4_hello_prms_tlv(struct iface *iface, struct ibuf *buf)
+gen_opt4_hello_prms_tlv(struct ibuf *buf, u_int16_t type, u_int32_t value)
{
struct hello_prms_opt4_tlv parms;
bzero(&parms, sizeof(parms));
- parms.type = htons(TLV_TYPE_IPV4TRANSADDR);
+ parms.type = htons(type);
parms.length = htons(4);
- parms.value = ldpe_router_id();
+ parms.value = value;
return (ibuf_add(buf, &parms, sizeof(parms)));
}
diff --git a/usr.sbin/ldpd/interface.c b/usr.sbin/ldpd/interface.c
index 2e91f158cb7..7c86d2b66f2 100644
--- a/usr.sbin/ldpd/interface.c
+++ b/usr.sbin/ldpd/interface.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: interface.c,v 1.16 2013/06/04 00:41:18 claudio Exp $ */
+/* $OpenBSD: interface.c,v 1.17 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -167,12 +167,17 @@ if_new(struct kif *kif)
void
if_del(struct iface *iface)
{
+ struct adj *adj;
struct if_addr *if_addr;
log_debug("if_del: interface %s", iface->name);
if_stop_hello_timer(iface);
+ while ((adj = LIST_FIRST(&iface->adj_list)) != NULL) {
+ LIST_REMOVE(adj, iface_entry);
+ adj_del(adj);
+ }
while ((if_addr = LIST_FIRST(&iface->addr_list)) != NULL)
LIST_REMOVE(if_addr, iface_entry);
@@ -208,7 +213,7 @@ if_hello_timer(int fd, short event, void *arg)
struct iface *iface = arg;
struct timeval tv;
- send_hello(iface);
+ send_hello(HELLO_LINK, iface, NULL);
/* reschedule hello_timer */
timerclear(&tv);
@@ -307,7 +312,7 @@ if_to_ctl(struct iface *iface)
ictl.state = iface->state;
ictl.mtu = iface->mtu;
ictl.baudrate = iface->baudrate;
- ictl.holdtime = iface->holdtime;
+ ictl.holdtime = iface->hello_holdtime;
ictl.hello_interval = iface->hello_interval;
ictl.flags = iface->flags;
ictl.type = iface->type;
diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h
index 115d23deae8..910b7be825c 100644
--- a/usr.sbin/ldpd/ldp.h
+++ b/usr.sbin/ldpd/ldp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldp.h,v 1.12 2013/06/04 01:32:16 claudio Exp $ */
+/* $OpenBSD: ldp.h,v 1.13 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -33,8 +33,6 @@
#define LINK_DFLT_HOLDTIME 15
#define TARGETED_DFLT_HOLDTIME 45
-
-#define DEFAULT_HOLDTIME 15
#define MIN_HOLDTIME 1
#define MAX_HOLDTIME 0xffff
#define INFINITE_HOLDTIME 0xffff
@@ -46,11 +44,10 @@
#define DEFAULT_HELLO_INTERVAL 5
#define MIN_HELLO_INTERVAL 1
-#define MAX_HELLO_INTERVAL 0xffff /* XXX */
+#define MAX_HELLO_INTERVAL 0xffff
#define INIT_DELAY_TMR 15
#define MAX_DELAY_TMR 120
-#define DEFAULT_NBR_TMOUT 86400 /* 24 hours */
/* LDP message types */
#define MSG_TYPE_NOTIFICATION 0x0001
diff --git a/usr.sbin/ldpd/ldpd.c b/usr.sbin/ldpd/ldpd.c
index c2f3b5d3517..9d53b5c13cd 100644
--- a/usr.sbin/ldpd/ldpd.c
+++ b/usr.sbin/ldpd/ldpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpd.c,v 1.16 2013/06/03 16:53:49 claudio Exp $ */
+/* $OpenBSD: ldpd.c,v 1.17 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -296,8 +296,6 @@ ldpd_shutdown(void)
free(iev_ldpe);
msgbuf_clear(&iev_lde->ibuf.w);
free(iev_lde);
-
- close(ldpd_conf->ldp_session_socket);
free(ldpd_conf);
log_info("terminating");
diff --git a/usr.sbin/ldpd/ldpd.conf.5 b/usr.sbin/ldpd/ldpd.conf.5
index 4f3d72eb6cc..71d4f3010d5 100644
--- a/usr.sbin/ldpd/ldpd.conf.5
+++ b/usr.sbin/ldpd/ldpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ldpd.conf.5,v 1.12 2013/06/01 20:07:07 jmc Exp $
+.\" $OpenBSD: ldpd.conf.5,v 1.13 2013/06/04 02:25:28 claudio Exp $
.\"
.\" Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
.\" 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: June 1 2013 $
+.Dd $Mdocdate: June 4 2013 $
.Dt LDPD.CONF 5
.Os
.Sh NAME
@@ -31,7 +31,7 @@ daemon implements the Label Distribution Protocol as described in RFC 5036.
.Sh SECTIONS
The
.Nm
-config file is divided into three main sections.
+config file is divided into four main sections.
.Bl -tag -width xxxx
.It Sy Macros
User-defined variables may be defined and used later, simplifying the
@@ -41,6 +41,8 @@ Global settings for
.Xr ldpd 8 .
.It Sy Interfaces Configuration
Interface-specific parameters.
+.It Sy Targeted neighbors Configuration
+Targeted neighbor specific parameters.
.El
.Sh MACROS
Much like
@@ -116,6 +118,17 @@ Select the advertisement mode.
advertises labels according to the distribution mode;
.Ic ondemand
advertises labels solely upon explicit request from peers.
+.Pp
+.It Xo
+.Ic targeted-hello-accept
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic yes ,
+allow LDP sessions to be established with remote neighbors that have not been
+specifically configured.
+The default is
+.Ic no .
.El
.Sh INTERFACES
Each interface can have several parameters configured individually, otherwise
@@ -127,14 +140,36 @@ interface em0 {
.Pp
Interface-specific parameters are listed below.
.Bl -tag -width Ds
-.It Ic holdtime Ar seconds
+.It Ic link-hello-holdtime Ar seconds
Set the hello holdtime in seconds.
The maximum time
.Xr ldpd 8
will wait between two consecutive hello messages from a peer before it is
marked as being down.
The default value is 15.
-.It Ic hello-interval Ar seconds
+.It Ic link-hello-interval Ar seconds
+Set the hello interval in seconds.
+The default value is 5; valid range is 1\-65535.
+.El
+.Sh TARGETED NEIGHBORS
+Each targeted neighbor can have several parameters configured individually,
+otherwise they are inherited.
+.Bd -literal -offset indent
+targeted-neighbor A.B.C.D {
+}
+.Ed
+.Pp
+Targeted-neighbor specific parameters are listed below.
+.Bl -tag -width Ds
+.It Ic targeted-hello-holdtime Ar seconds
+Set the hello holdtime in seconds.
+The maximum time
+.Xr ldpd 8
+will wait between two consecutive hello messages from a peer before it is
+marked as being down.
+The default value is 45.
+.Pp
+.It Ic targeted-hello-interval Ar seconds
Set the hello interval in seconds.
The default value is 5; valid range is 1\-65535.
.El
diff --git a/usr.sbin/ldpd/ldpd.h b/usr.sbin/ldpd/ldpd.h
index 156ca1d437f..b1e4da33580 100644
--- a/usr.sbin/ldpd/ldpd.h
+++ b/usr.sbin/ldpd/ldpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpd.h,v 1.39 2013/06/04 00:56:49 claudio Exp $ */
+/* $OpenBSD: ldpd.h,v 1.40 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -45,6 +45,7 @@
#define LDP_BACKLOG 128
#define LDPD_FLAG_NO_FIB_UPDATE 0x0001
+#define LDPD_FLAG_TH_ACCEPT 0x0002
#define F_LDPD_INSERTED 0x0001
#define F_CONNECTED 0x0002
@@ -71,6 +72,7 @@ enum imsg_type {
IMSG_NONE,
IMSG_CTL_RELOAD,
IMSG_CTL_SHOW_INTERFACE,
+ IMSG_CTL_SHOW_DISCOVERY,
IMSG_CTL_SHOW_NBR,
IMSG_CTL_SHOW_LIB,
IMSG_CTL_FIB_COUPLE,
@@ -140,20 +142,17 @@ enum iface_type {
};
/* neighbor states */
-#define NBR_STA_DOWN 0x0001
-#define NBR_STA_PRESENT 0x0002
-#define NBR_STA_INITIAL 0x0004
-#define NBR_STA_OPENREC 0x0008
-#define NBR_STA_OPENSENT 0x0010
-#define NBR_STA_OPER 0x0020
-#define NBR_STA_SESSION (NBR_STA_PRESENT | NBR_STA_INITIAL | \
- NBR_STA_OPENREC | NBR_STA_OPENSENT | \
- NBR_STA_OPER)
+#define NBR_STA_PRESENT 0x0001
+#define NBR_STA_INITIAL 0x0002
+#define NBR_STA_OPENREC 0x0004
+#define NBR_STA_OPENSENT 0x0008
+#define NBR_STA_OPER 0x0010
+#define NBR_STA_SESSION (NBR_STA_INITIAL | NBR_STA_OPENREC | \
+ NBR_STA_OPENSENT | NBR_STA_OPER)
/* neighbor events */
enum nbr_event {
NBR_EVT_NOTHING,
- NBR_EVT_HELLO_RCVD,
NBR_EVT_CONNECT_UP,
NBR_EVT_CLOSE_SESSION,
NBR_EVT_INIT_RCVD,
@@ -166,8 +165,6 @@ enum nbr_event {
/* neighbor actions */
enum nbr_action {
NBR_ACT_NOTHING,
- NBR_ACT_STRT_ITIMER,
- NBR_ACT_RST_ITIMER,
NBR_ACT_RST_KTIMEOUT,
NBR_ACT_SESSION_EST,
NBR_ACT_RST_KTIMER,
@@ -211,6 +208,7 @@ struct iface {
char name[IF_NAMESIZE];
LIST_HEAD(, if_addr) addr_list;
+ LIST_HEAD(, adj) adj_list;
u_int64_t baudrate;
time_t uptime;
@@ -219,7 +217,7 @@ struct iface {
int session_fd;
int state;
int mtu;
- u_int16_t holdtime;
+ u_int16_t hello_holdtime;
u_int16_t hello_interval;
u_int16_t flags;
enum iface_type type;
@@ -228,6 +226,20 @@ struct iface {
u_int8_t priority;
};
+/* source of targeted hellos */
+struct tnbr {
+ LIST_ENTRY(tnbr) entry;
+ struct event hello_timer;
+ int discovery_fd;
+ struct adj *adj;
+ struct in_addr addr;
+
+ u_int16_t hello_holdtime;
+ u_int16_t hello_interval;
+ u_int8_t flags;
+};
+#define F_TNBR_CONFIGURED 0x01
+
/* ldp_conf */
enum {
PROC_MAIN,
@@ -240,6 +252,11 @@ enum blockmodes {
BM_NONBLOCK
};
+enum hello_type {
+ HELLO_LINK,
+ HELLO_TARGETED
+};
+
#define MODE_DIST_INDEPENDENT 0x01
#define MODE_DIST_ORDERED 0x02
#define MODE_RET_LIBERAL 0x04
@@ -249,9 +266,11 @@ enum blockmodes {
struct ldpd_conf {
struct event disc_ev;
+ struct event edisc_ev;
struct in_addr rtr_id;
LIST_HEAD(, iface) iface_list;
LIST_HEAD(, if_addr) addr_list;
+ LIST_HEAD(, tnbr) tnbr_list;
u_int32_t opts;
#define LDPD_OPT_VERBOSE 0x00000001
@@ -259,10 +278,13 @@ struct ldpd_conf {
#define LDPD_OPT_NOACTION 0x00000004
time_t uptime;
int ldp_discovery_socket;
+ int ldp_ediscovery_socket;
int ldp_session_socket;
int flags;
u_int8_t mode;
u_int16_t keepalive;
+ u_int16_t thello_holdtime;
+ u_int16_t thello_interval;
};
/* kroute */
@@ -321,12 +343,19 @@ struct ctl_iface {
u_int8_t priority;
};
+struct ctl_adj {
+ struct in_addr id;
+ enum hello_type type;
+ char ifname[IF_NAMESIZE];
+ struct in_addr src_addr;
+ u_int16_t holdtime;
+};
+
struct ctl_nbr {
struct in_addr id;
struct in_addr addr;
struct in_addr dr;
struct in_addr bdr;
- time_t dead_timer;
time_t uptime;
u_int32_t db_sum_lst_cnt;
u_int32_t ls_req_lst_cnt;
diff --git a/usr.sbin/ldpd/ldpe.c b/usr.sbin/ldpd/ldpe.c
index a461db7dbb4..b20585e800c 100644
--- a/usr.sbin/ldpd/ldpe.c
+++ b/usr.sbin/ldpd/ldpe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.c,v 1.20 2013/06/04 00:45:00 claudio Exp $ */
+/* $OpenBSD: ldpe.c,v 1.21 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -73,6 +73,7 @@ ldpe(struct ldpd_conf *xconf, int pipe_parent2ldpe[2], int pipe_ldpe2lde[2],
int pipe_parent2lde[2])
{
struct iface *iface;
+ struct tnbr *tnbr;
struct passwd *pw;
struct event ev_sigint, ev_sigterm;
struct sockaddr_in disc_addr, sess_addr;
@@ -105,6 +106,9 @@ ldpe(struct ldpd_conf *xconf, int pipe_parent2ldpe[2], int pipe_ldpe2lde[2],
IPPROTO_UDP)) == -1)
fatal("error creating discovery socket");
+ if (if_set_reuse(xconf->ldp_discovery_socket, 1) == -1)
+ fatal("if_set_reuse");
+
if (bind(xconf->ldp_discovery_socket, (struct sockaddr *)&disc_addr,
sizeof(disc_addr)) == -1)
fatal("error binding discovery socket");
@@ -122,6 +126,30 @@ ldpe(struct ldpd_conf *xconf, int pipe_parent2ldpe[2], int pipe_ldpe2lde[2],
fatal("if_set_recvif");
if_set_recvbuf(xconf->ldp_discovery_socket);
+ /* create the extended discovery UDP socket */
+ disc_addr.sin_family = AF_INET;
+ disc_addr.sin_port = htons(LDP_PORT);
+ disc_addr.sin_addr.s_addr = xconf->rtr_id.s_addr;
+
+ if ((xconf->ldp_ediscovery_socket = socket(AF_INET, SOCK_DGRAM,
+ IPPROTO_UDP)) == -1)
+ fatal("error creating extended discovery socket");
+
+ if (if_set_reuse(xconf->ldp_ediscovery_socket, 1) == -1)
+ fatal("if_set_reuse");
+
+ if (bind(xconf->ldp_ediscovery_socket, (struct sockaddr *)&disc_addr,
+ sizeof(disc_addr)) == -1)
+ fatal("error binding extended discovery socket");
+
+ /* set some defaults */
+ if (if_set_tos(xconf->ldp_ediscovery_socket,
+ IPTOS_PREC_INTERNETCONTROL) == -1)
+ fatal("if_set_tos");
+ if (if_set_recvif(xconf->ldp_ediscovery_socket, 1) == -1)
+ fatal("if_set_recvif");
+ if_set_recvbuf(xconf->ldp_ediscovery_socket);
+
/* create the session TCP socket */
sess_addr.sin_family = AF_INET;
sess_addr.sin_port = htons(LDP_PORT);
@@ -197,10 +225,14 @@ ldpe(struct ldpd_conf *xconf, int pipe_parent2ldpe[2], int pipe_ldpe2lde[2],
event_add(&iev_main->ev, NULL);
event_set(&leconf->disc_ev, leconf->ldp_discovery_socket,
- EV_READ|EV_PERSIST, disc_recv_packet, leconf);
+ EV_READ|EV_PERSIST, disc_recv_packet, NULL);
event_add(&leconf->disc_ev, NULL);
- accept_add(leconf->ldp_session_socket, session_accept, leconf);
+ event_set(&leconf->edisc_ev, leconf->ldp_ediscovery_socket,
+ EV_READ|EV_PERSIST, disc_recv_packet, NULL);
+ event_add(&leconf->edisc_ev, NULL);
+
+ accept_add(leconf->ldp_session_socket, session_accept, NULL);
/* listen on ldpd control socket */
TAILQ_INIT(&ctl_conns);
control_listen();
@@ -212,6 +244,10 @@ ldpe(struct ldpd_conf *xconf, int pipe_parent2ldpe[2], int pipe_ldpe2lde[2],
LIST_FOREACH(iface, &leconf->iface_list, entry)
if_init(xconf, iface);
+ /* start configured targeted neighbors */
+ LIST_FOREACH(tnbr, &leconf->tnbr_list, entry)
+ tnbr_init(xconf, tnbr);
+
event_dispatch();
ldpe_shutdown();
@@ -223,6 +259,7 @@ void
ldpe_shutdown(void)
{
struct iface *iface;
+ struct tnbr *tnbr;
/* stop all interfaces */
while ((iface = LIST_FIRST(&leconf->iface_list)) != NULL) {
@@ -234,7 +271,14 @@ ldpe_shutdown(void)
if_del(iface);
}
+ /* stop all targeted neighbors */
+ while ((tnbr = LIST_FIRST(&leconf->tnbr_list)) != NULL) {
+ LIST_REMOVE(tnbr, entry);
+ tnbr_del(tnbr);
+ }
+
close(leconf->ldp_discovery_socket);
+ close(leconf->ldp_session_socket);
/* clean up */
msgbuf_write(&iev_lde->ibuf.w);
diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h
index ee70736ca29..33c68227f32 100644
--- a/usr.sbin/ldpd/ldpe.h
+++ b/usr.sbin/ldpd/ldpe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.h,v 1.24 2013/06/04 01:32:16 claudio Exp $ */
+/* $OpenBSD: ldpe.h,v 1.25 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
@@ -29,17 +29,31 @@
TAILQ_HEAD(ctl_conns, ctl_conn) ctl_conns;
-struct mapping_entry {
- TAILQ_ENTRY(mapping_entry) entry;
- struct map map;
+struct hello_source {
+ enum hello_type type;
+ struct {
+ struct iface *iface;
+ struct in_addr src_addr;
+ } link;
+ struct tnbr *target;
+};
+
+struct adj {
+ LIST_ENTRY(adj) nbr_entry;
+ LIST_ENTRY(adj) iface_entry;
+ struct nbr *nbr;
+ struct hello_source source;
+ struct event inactivity_timer;
+ u_int16_t holdtime;
+ struct in_addr addr;
};
struct nbr {
RB_ENTRY(nbr) id_tree, addr_tree, pid_tree;
struct evbuf wbuf;
struct event rev;
+ LIST_HEAD(, adj) adj_list; /* adjacencies */
struct event ev_connect;
- struct event inactivity_timer;
struct event keepalive_timer;
struct event keepalive_timeout;
struct event initdelay_timer;
@@ -62,15 +76,17 @@ struct nbr {
int state;
int idtimer_cnt;
- u_int16_t holdtime;
u_int16_t keepalive;
u_int8_t priority;
u_int8_t options;
u_int8_t flags;
- u_int8_t hello_type;
+};
+struct mapping_entry {
+ TAILQ_ENTRY(mapping_entry) entry;
+ struct map map;
};
/* accept.c */
@@ -81,7 +97,7 @@ void accept_pause(void);
void accept_unpause(void);
/* hello.c */
-int send_hello(struct iface *);
+int send_hello(enum hello_type, struct iface *, struct tnbr *);
void recv_hello(struct iface *, struct in_addr, char *, u_int16_t);
/* init.c */
@@ -146,6 +162,21 @@ int if_set_mcast_ttl(int, u_int8_t);
int if_set_tos(int, int);
int if_set_reuse(int, int);
+/* adjacency.c */
+struct adj *adj_new(struct nbr *, struct hello_source *, u_int16_t,
+ struct in_addr);
+void adj_del(struct adj *);
+struct adj *adj_find(struct nbr *, struct hello_source *);
+void adj_start_itimer(struct adj *);
+void adj_stop_itimer(struct adj *);
+struct tnbr *tnbr_new(struct in_addr, int);
+void tnbr_del(struct tnbr *);
+void tnbr_init(struct ldpd_conf *, struct tnbr *);
+struct tnbr *tnbr_find(struct in_addr);
+
+struct ctl_adj *adj_to_ctl(struct adj *);
+void ldpe_adj_ctl(struct ctl_conn *);
+
/* neighbor.c */
struct nbr *nbr_new(struct in_addr, struct in_addr);
void nbr_del(struct nbr *);
@@ -157,9 +188,6 @@ struct nbr *nbr_find_peerid(u_int32_t);
int nbr_fsm(struct nbr *, enum nbr_event);
int nbr_session_active_role(struct nbr *);
-void nbr_itimer(int, short, void *);
-void nbr_start_itimer(struct nbr *);
-void nbr_stop_itimer(struct nbr *);
void nbr_ktimer(int, short, void *);
void nbr_start_ktimer(struct nbr *);
void nbr_stop_ktimer(struct nbr *);
@@ -190,7 +218,7 @@ void ldpe_nbr_ctl(struct ctl_conn *);
/* packet.c */
int gen_ldp_hdr(struct ibuf *, u_int16_t);
int gen_msg_tlv(struct ibuf *, u_int32_t, u_int16_t);
-int send_packet(struct iface *, void *, size_t, struct sockaddr_in *);
+int send_packet(int, struct iface *, void *, size_t, struct sockaddr_in *);
void disc_recv_packet(int, short, void *);
void session_accept(int, short, void *);
diff --git a/usr.sbin/ldpd/log.c b/usr.sbin/ldpd/log.c
index d6fcc67f9e8..4ef03995d5a 100644
--- a/usr.sbin/ldpd/log.c
+++ b/usr.sbin/ldpd/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.11 2013/06/01 20:13:04 claudio Exp $ */
+/* $OpenBSD: log.c,v 1.12 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -179,8 +179,6 @@ const char *
nbr_state_name(int state)
{
switch (state) {
- case NBR_STA_DOWN:
- return ("DOWN");
case NBR_STA_PRESENT:
return ("PRESENT");
case NBR_STA_INITIAL:
diff --git a/usr.sbin/ldpd/neighbor.c b/usr.sbin/ldpd/neighbor.c
index 13b2df1d0c4..f9ecb08b36b 100644
--- a/usr.sbin/ldpd/neighbor.c
+++ b/usr.sbin/ldpd/neighbor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: neighbor.c,v 1.35 2013/06/04 01:32:16 claudio Exp $ */
+/* $OpenBSD: neighbor.c,v 1.36 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -92,9 +92,6 @@ struct {
int new_state;
} nbr_fsm_tbl[] = {
/* current state event that happened action to take resulting state */
-/* Discovery States */
- {NBR_STA_DOWN, NBR_EVT_HELLO_RCVD, NBR_ACT_STRT_ITIMER, NBR_STA_PRESENT},
- {NBR_STA_SESSION, NBR_EVT_HELLO_RCVD, NBR_ACT_RST_ITIMER, 0},
{NBR_STA_PRESENT, NBR_EVT_CONNECT_UP, NBR_ACT_CONNECT_SETUP, NBR_STA_INITIAL},
/* Passive Role */
{NBR_STA_INITIAL, NBR_EVT_INIT_RCVD, NBR_ACT_PASSIVE_INIT, NBR_STA_OPENREC},
@@ -106,13 +103,13 @@ struct {
{NBR_STA_OPER, NBR_EVT_PDU_RCVD, NBR_ACT_RST_KTIMEOUT, 0},
{NBR_STA_OPER, NBR_EVT_PDU_SENT, NBR_ACT_RST_KTIMER, 0},
/* Session Close */
+ {NBR_STA_PRESENT, NBR_EVT_CLOSE_SESSION, NBR_ACT_NOTHING, 0},
{NBR_STA_SESSION, NBR_EVT_CLOSE_SESSION, NBR_ACT_CLOSE_SESSION, NBR_STA_PRESENT},
{-1, NBR_EVT_NOTHING, NBR_ACT_NOTHING, 0},
};
const char * const nbr_event_names[] = {
"NOTHING",
- "HELLO RECEIVED",
"CONNECTION UP",
"SESSION CLOSE",
"INIT RECEIVED",
@@ -124,8 +121,6 @@ const char * const nbr_event_names[] = {
const char * const nbr_action_names[] = {
"NOTHING",
- "START INACTIVITY TIMER",
- "RESET INACTIVITY TIMER",
"RESET KEEPALIVE TIMEOUT",
"START NEIGHBOR SESSION",
"RESET KEEPALIVE TIMER",
@@ -178,13 +173,6 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event)
}
switch (nbr_fsm_tbl[i].action) {
- case NBR_ACT_RST_ITIMER:
- case NBR_ACT_STRT_ITIMER:
- if (nbr->holdtime != INFINITE_HOLDTIME)
- nbr_start_itimer(nbr);
- else
- nbr_stop_itimer(nbr);
- break;
case NBR_ACT_RST_KTIMEOUT:
nbr_start_ktimeout(nbr);
break;
@@ -240,7 +228,7 @@ nbr_new(struct in_addr id, struct in_addr addr)
if ((nbr->rbuf = calloc(1, sizeof(struct ibuf_read))) == NULL)
fatal("nbr_new");
- nbr->state = NBR_STA_DOWN;
+ nbr->state = NBR_STA_PRESENT;
nbr->id.s_addr = id.s_addr;
nbr->addr = addr;
@@ -263,7 +251,6 @@ nbr_new(struct in_addr id, struct in_addr addr)
TAILQ_INIT(&nbr->abortreq_list);
/* set event structures */
- evtimer_set(&nbr->inactivity_timer, nbr_itimer, nbr);
evtimer_set(&nbr->keepalive_timeout, nbr_ktimeout, nbr);
evtimer_set(&nbr->keepalive_timer, nbr_ktimer, nbr);
evtimer_set(&nbr->initdelay_timer, nbr_idtimer, nbr);
@@ -280,7 +267,6 @@ nbr_del(struct nbr *nbr)
if (event_pending(&nbr->ev_connect, EV_WRITE, NULL))
event_del(&nbr->ev_connect);
- nbr_stop_itimer(nbr);
nbr_stop_ktimer(nbr);
nbr_stop_ktimeout(nbr);
nbr_stop_idtimer(nbr);
@@ -334,39 +320,6 @@ nbr_session_active_role(struct nbr *nbr)
/* timers */
-/* Inactivity timer: timeout based on hellos */
-/* ARGSUSED */
-void
-nbr_itimer(int fd, short event, void *arg)
-{
- struct nbr *nbr = arg;
-
- log_debug("nbr_itimer: neighbor ID %s peerid %lu", inet_ntoa(nbr->id),
- nbr->peerid);
-
- nbr_del(nbr);
-}
-
-void
-nbr_start_itimer(struct nbr *nbr)
-{
- struct timeval tv;
-
- timerclear(&tv);
- tv.tv_sec = nbr->holdtime;
-
- if (evtimer_add(&nbr->inactivity_timer, &tv) == -1)
- fatal("nbr_start_itimer");
-}
-
-void
-nbr_stop_itimer(struct nbr *nbr)
-{
- if (evtimer_pending(&nbr->inactivity_timer, NULL) &&
- evtimer_del(&nbr->inactivity_timer) == -1)
- fatal("nbr_stop_itimer");
-}
-
/* Keepalive timer: timer to send keepalive message to neighbors */
void
@@ -672,22 +625,13 @@ struct ctl_nbr *
nbr_to_ctl(struct nbr *nbr)
{
static struct ctl_nbr nctl;
- struct timeval tv, now, res;
+ struct timeval now;
memcpy(&nctl.id, &nbr->id, sizeof(nctl.id));
memcpy(&nctl.addr, &nbr->addr, sizeof(nctl.addr));
nctl.nbr_state = nbr->state;
gettimeofday(&now, NULL);
- if (evtimer_pending(&nbr->inactivity_timer, &tv)) {
- timersub(&tv, &now, &res);
- if (nbr->state & NBR_STA_DOWN)
- nctl.dead_timer = DEFAULT_NBR_TMOUT - res.tv_sec;
- else
- nctl.dead_timer = res.tv_sec;
- } else
- nctl.dead_timer = 0;
-
if (nbr->state == NBR_STA_OPER) {
nctl.uptime = now.tv_sec - nbr->uptime;
} else
diff --git a/usr.sbin/ldpd/packet.c b/usr.sbin/ldpd/packet.c
index 87b6b4aa106..98637b8d769 100644
--- a/usr.sbin/ldpd/packet.c
+++ b/usr.sbin/ldpd/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.25 2013/06/03 16:53:49 claudio Exp $ */
+/* $OpenBSD: packet.c,v 1.26 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -81,22 +81,22 @@ gen_msg_tlv(struct ibuf *buf, u_int32_t type, u_int16_t size)
return (ibuf_add(buf, &msg, sizeof(msg)));
}
-/* send and receive packets */
+/* send packets */
int
-send_packet(struct iface *iface, void *pkt, size_t len, struct sockaddr_in *dst)
+send_packet(int fd, struct iface *iface, void *pkt, size_t len,
+ struct sockaddr_in *dst)
{
/* set outgoing interface for multicast traffic */
- if (IN_MULTICAST(ntohl(dst->sin_addr.s_addr)))
+ if (iface && IN_MULTICAST(ntohl(dst->sin_addr.s_addr)))
if (if_set_mcast(iface) == -1) {
log_warn("send_packet: error setting multicast "
"interface, %s", iface->name);
return (-1);
}
- if (sendto(iface->discovery_fd, pkt, len, 0,
- (struct sockaddr *)dst, sizeof(*dst)) == -1) {
- log_warn("send_packet: error sending packet on interface %s",
- iface->name);
+ if (sendto(fd, pkt, len, 0, (struct sockaddr *)dst,
+ sizeof(*dst)) == -1) {
+ log_warn("send_packet: error sending packet");
return (-1);
}
@@ -116,7 +116,7 @@ disc_recv_packet(int fd, short event, void *bula)
struct iovec iov;
struct ldp_hdr ldp_hdr;
struct ldp_msg ldp_msg;
- struct iface *iface;
+ struct iface *iface = NULL;
char *buf;
struct cmsghdr *cmsg;
ssize_t r;
@@ -156,7 +156,8 @@ disc_recv_packet(int fd, short event, void *bula)
len = (u_int16_t)r;
/* find a matching interface */
- if ((iface = disc_find_iface(ifindex, src.sin_addr)) == NULL) {
+ if ((fd == leconf->ldp_discovery_socket) &&
+ (iface = disc_find_iface(ifindex, src.sin_addr)) == NULL) {
log_debug("disc_recv_packet: cannot find a matching interface");
return;
}
@@ -174,13 +175,6 @@ disc_recv_packet(int fd, short event, void *bula)
return;
}
- if (ldp_hdr.lspace_id != 0) {
- log_debug("disc_recv_packet: invalid label space "
- "ID %s, interface %s", ldp_hdr.lspace_id,
- iface->name);
- return;
- }
-
if (ntohs(ldp_hdr.length) >
len - sizeof(ldp_hdr.version) - sizeof(ldp_hdr.length)) {
log_debug("disc_recv_packet: invalid LDP packet length %u",
@@ -202,8 +196,8 @@ disc_recv_packet(int fd, short event, void *bula)
recv_hello(iface, src.sin_addr, buf, len);
break;
default:
- log_debug("recv_packet: unknown LDP packet type, interface %s",
- iface->name);
+ log_debug("recv_packet: unknown LDP packet type, source %s",
+ inet_ntoa(src.sin_addr));
}
}
diff --git a/usr.sbin/ldpd/parse.y b/usr.sbin/ldpd/parse.y
index fa66d961121..e6130b2d1a4 100644
--- a/usr.sbin/ldpd/parse.y
+++ b/usr.sbin/ldpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.16 2013/06/03 16:58:14 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.17 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
@@ -84,17 +84,22 @@ static struct ldpd_conf *conf;
static int errors = 0;
struct iface *iface = NULL;
+struct tnbr *tnbr = NULL;
struct config_defaults {
- u_int16_t holdtime;
- u_int16_t hello_interval;
+ u_int16_t lhello_holdtime;
+ u_int16_t lhello_interval;
+ u_int16_t thello_holdtime;
+ u_int16_t thello_interval;
};
struct config_defaults globaldefs;
struct config_defaults ifacedefs;
+struct config_defaults tnbrdefs;
struct config_defaults *defs;
struct iface *conf_get_if(struct kif *);
+struct tnbr *conf_get_tnbr(struct in_addr);
typedef struct {
union {
@@ -106,11 +111,13 @@ typedef struct {
%}
-%token INTERFACE ROUTERID FIBUPDATE
-%token HOLDTIME HELLOINTERVAL KEEPALIVE
+%token INTERFACE TNEIGHBOR ROUTERID FIBUPDATE
+%token LHELLOHOLDTIME LHELLOINTERVAL
+%token THELLOHOLDTIME THELLOINTERVAL
+%token THELLOACCEPT
+%token KEEPALIVE
%token DISTRIBUTION RETENTION ADVERTISEMENT
%token EXTTAG
-%token HELLOINTERVAL
%token YES NO
%token ERROR
%token <v.string> STRING
@@ -125,6 +132,7 @@ grammar : /* empty */
| grammar conf_main '\n'
| grammar varset '\n'
| grammar interface '\n'
+ | grammar tneighbor '\n'
| grammar error '\n' { file->errors++; }
;
@@ -211,6 +219,12 @@ conf_main : ROUTERID STRING {
YYERROR;
}
}
+ | THELLOACCEPT yesno {
+ if ($2 == 0)
+ conf->flags &= ~LDPD_FLAG_TH_ACCEPT;
+ else
+ conf->flags |= LDPD_FLAG_TH_ACCEPT;
+ }
| KEEPALIVE NUMBER {
if ($2 < MIN_KEEPALIVE ||
$2 > MAX_KEEPALIVE) {
@@ -220,25 +234,48 @@ conf_main : ROUTERID STRING {
}
conf->keepalive = $2;
}
- | defaults
+ | iface_defaults
+ | tnbr_defaults
;
-defaults : HOLDTIME NUMBER {
+iface_defaults : LHELLOHOLDTIME NUMBER {
if ($2 < MIN_HOLDTIME ||
$2 > MAX_HOLDTIME) {
- yyerror("holdtime out of range (%d-%d)",
+ yyerror("hello holdtime out of range (%d-%d)",
MIN_HOLDTIME, MAX_HOLDTIME);
YYERROR;
}
- defs->holdtime = $2;
+ defs->lhello_holdtime = $2;
}
- | HELLOINTERVAL NUMBER {
+ | LHELLOINTERVAL NUMBER {
if ($2 < MIN_HELLO_INTERVAL ||
$2 > MAX_HELLO_INTERVAL) {
yyerror("hello-interval out of range (%d-%d)",
MIN_HELLO_INTERVAL, MAX_HELLO_INTERVAL);
YYERROR;
}
- defs->hello_interval = $2;
+ defs->lhello_interval = $2;
+ }
+ ;
+
+tnbr_defaults : THELLOHOLDTIME NUMBER {
+ if ($2 < MIN_HOLDTIME ||
+ $2 > MAX_HOLDTIME) {
+ yyerror("hello holdtime out of range (%d-%d)",
+ MIN_HOLDTIME, MAX_HOLDTIME);
+ YYERROR;
+ }
+ conf->thello_holdtime = $2;
+ defs->thello_holdtime = $2;
+ }
+ | THELLOINTERVAL NUMBER {
+ if ($2 < MIN_HELLO_INTERVAL ||
+ $2 > MAX_HELLO_INTERVAL) {
+ yyerror("hello-interval out of range (%d-%d)",
+ MIN_HELLO_INTERVAL, MAX_HELLO_INTERVAL);
+ YYERROR;
+ }
+ conf->thello_interval = $2;
+ defs->thello_interval = $2;
}
;
@@ -272,8 +309,8 @@ interface : INTERFACE STRING {
memcpy(&ifacedefs, defs, sizeof(ifacedefs));
defs = &ifacedefs;
} interface_block {
- iface->holdtime = defs->holdtime;
- iface->hello_interval = defs->hello_interval;
+ iface->hello_holdtime = defs->lhello_holdtime;
+ iface->hello_interval = defs->lhello_interval;
iface = NULL;
defs = &globaldefs;
@@ -285,8 +322,44 @@ interface_block : '{' optnl interfaceopts_l '}'
| /* nothing */
;
-interfaceopts_l : interfaceopts_l defaults nl
- | defaults optnl
+interfaceopts_l : interfaceopts_l iface_defaults nl
+ | iface_defaults optnl
+ ;
+
+tneighbor : TNEIGHBOR STRING {
+ struct in_addr addr;
+
+ if (inet_aton($2, &addr) == 0) {
+ yyerror(
+ "error parsing neighbor address");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+
+ tnbr = conf_get_tnbr(addr);
+ if (tnbr == NULL)
+ YYERROR;
+ LIST_INSERT_HEAD(&conf->tnbr_list, tnbr, entry);
+
+ memcpy(&tnbrdefs, defs, sizeof(tnbrdefs));
+ defs = &tnbrdefs;
+ } tneighbor_block {
+ tnbr->hello_holdtime = defs->thello_holdtime;
+ tnbr->hello_interval = defs->thello_interval;
+ tnbr = NULL;
+
+ defs = &globaldefs;
+ }
+ ;
+
+tneighbor_block : '{' optnl tneighboropts_l '}'
+ | '{' optnl '}'
+ | /* nothing */
+ ;
+
+tneighboropts_l : tneighboropts_l tnbr_defaults nl
+ | tnbr_defaults optnl
;
%%
@@ -323,18 +396,22 @@ lookup(char *s)
{
/* this has to be sorted always */
static const struct keywords keywords[] = {
- {"advertisement", ADVERTISEMENT},
- {"distribution", DISTRIBUTION},
- {"external-tag", EXTTAG},
- {"fib-update", FIBUPDATE},
- {"hello-interval", HELLOINTERVAL},
- {"holdtime", HOLDTIME},
- {"interface", INTERFACE},
- {"keepalive", KEEPALIVE},
- {"no", NO},
- {"retention", RETENTION},
- {"router-id", ROUTERID},
- {"yes", YES}
+ {"advertisement", ADVERTISEMENT},
+ {"distribution", DISTRIBUTION},
+ {"external-tag", EXTTAG},
+ {"fib-update", FIBUPDATE},
+ {"interface", INTERFACE},
+ {"keepalive", KEEPALIVE},
+ {"link-hello-holdtime", LHELLOHOLDTIME},
+ {"link-hello-interval", LHELLOINTERVAL},
+ {"no", NO},
+ {"retention", RETENTION},
+ {"router-id", ROUTERID},
+ {"targeted-hello-accept", THELLOACCEPT},
+ {"targeted-hello-holdtime", THELLOHOLDTIME},
+ {"targeted-hello-interval", THELLOINTERVAL},
+ {"targeted-neighbor", TNEIGHBOR},
+ {"yes", YES}
};
const struct keywords *p;
@@ -664,8 +741,12 @@ parse_config(char *filename, int opts)
bzero(&globaldefs, sizeof(globaldefs));
defs = &globaldefs;
- defs->holdtime = DEFAULT_HOLDTIME;
- defs->hello_interval = DEFAULT_HELLO_INTERVAL;
+ defs->lhello_holdtime = LINK_DFLT_HOLDTIME;
+ defs->lhello_interval = DEFAULT_HELLO_INTERVAL;
+ defs->thello_holdtime = TARGETED_DFLT_HOLDTIME;
+ defs->thello_interval = DEFAULT_HELLO_INTERVAL;
+ conf->thello_holdtime = TARGETED_DFLT_HOLDTIME;
+ conf->thello_interval = DEFAULT_HELLO_INTERVAL;
conf->mode = (MODE_DIST_INDEPENDENT | MODE_RET_LIBERAL |
MODE_ADV_UNSOLICITED);
@@ -798,6 +879,24 @@ conf_get_if(struct kif *kif)
return (i);
}
+struct tnbr *
+conf_get_tnbr(struct in_addr addr)
+{
+ struct tnbr *t;
+
+ LIST_FOREACH(t, &conf->tnbr_list, entry) {
+ if (t->addr.s_addr == addr.s_addr) {
+ yyerror("targeted neighbor %s already configured",
+ inet_ntoa(addr));
+ return (NULL);
+ }
+ }
+
+ t = tnbr_new(addr, 1);
+
+ return (t);
+}
+
void
clear_config(struct ldpd_conf *xconf)
{
diff --git a/usr.sbin/ldpd/printconf.c b/usr.sbin/ldpd/printconf.c
index 1d8b0714638..cbdddd52544 100644
--- a/usr.sbin/ldpd/printconf.c
+++ b/usr.sbin/ldpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.6 2013/06/03 16:58:14 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.7 2013/06/04 02:25:28 claudio Exp $ */
/*
* Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
@@ -30,6 +30,7 @@
void print_mainconf(struct ldpd_conf *);
void print_iface(struct iface *);
+void print_tnbr(struct tnbr *tnbr);
void
print_mainconf(struct ldpd_conf *conf)
@@ -56,6 +57,11 @@ print_mainconf(struct ldpd_conf *conf)
else
printf("advertisement unsolicited\n");
+ if (conf->flags & LDPD_FLAG_TH_ACCEPT)
+ printf("targeted-hello-accept yes\n");
+ else
+ printf("targeted-hello-accept no\n");
+
printf("keepalive %u\n", conf->keepalive);
}
@@ -63,8 +69,17 @@ void
print_iface(struct iface *iface)
{
printf("\ninterface %s {\n", iface->name);
- printf("\tholdtime %d\n", iface->holdtime);
- printf("\thello-interval %d\n", iface->hello_interval);
+ printf("\tlink-hello-holdtime %u\n", iface->hello_holdtime);
+ printf("\tlink-hello-interval %u\n", iface->hello_interval);
+ printf("}\n");
+}
+
+void
+print_tnbr(struct tnbr *tnbr)
+{
+ printf("\ntargeted-neighbor %s {\n", inet_ntoa(tnbr->addr));
+ printf("\ttargeted-hello-holdtime %u\n", tnbr->hello_holdtime);
+ printf("\ttargeted-hello-interval %u\n", tnbr->hello_interval);
printf("}\n");
}
@@ -72,11 +87,14 @@ void
print_config(struct ldpd_conf *conf)
{
struct iface *iface;
+ struct tnbr *tnbr;
print_mainconf(conf);
printf("\n");
- LIST_FOREACH(iface, &conf->iface_list, entry) {
+ LIST_FOREACH(iface, &conf->iface_list, entry)
print_iface(iface);
- }
+ printf("\n");
+ LIST_FOREACH(tnbr, &conf->tnbr_list, entry)
+ print_tnbr(tnbr);
}