summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2013-06-01 01:34:58 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2013-06-01 01:34:58 +0000
commitb9c01f34a32422d2c2334dbaad81f342f3d2f81c (patch)
tree15d9d047ec16d7ff9f277a8060641043e8a708ee
parent3d6fd0382d82211c3fc923a8af8cbd23a3121ffc (diff)
Always advertise the Router-ID as the transport address.
RFC 5036 - Section 2.5.2 says: An LSR MUST advertise the same transport address in all Hellos that advertise the same label space... To satisfy this condition, always advertise the Router-ID as the transport address by using the "IPv4 Transport Address" TLV in the generated Hello messages. From Renato Westphal
-rw-r--r--usr.sbin/ldpd/hello.c38
-rw-r--r--usr.sbin/ldpd/ldp.h8
-rw-r--r--usr.sbin/ldpd/ldpe.h3
-rw-r--r--usr.sbin/ldpd/neighbor.c42
4 files changed, 66 insertions, 25 deletions
diff --git a/usr.sbin/ldpd/hello.c b/usr.sbin/ldpd/hello.c
index 137b6e4f9eb..d56905d3de9 100644
--- a/usr.sbin/ldpd/hello.c
+++ b/usr.sbin/ldpd/hello.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hello.c,v 1.14 2013/05/31 14:10:10 claudio Exp $ */
+/* $OpenBSD: hello.c,v 1.15 2013/06/01 01:34:56 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -39,7 +39,8 @@
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 *, u_int16_t);
+int gen_hello_prms_tlv(struct iface *, struct ibuf *);
+int gen_opt4_hello_prms_tlv(struct iface *, struct ibuf *);
int
send_hello(struct iface *iface)
@@ -60,7 +61,8 @@ send_hello(struct iface *iface)
fatal("send_hello");
size = LDP_HDR_SIZE + sizeof(struct ldp_msg) +
- sizeof(struct hello_prms_tlv);
+ sizeof(struct hello_prms_tlv) +
+ sizeof(struct hello_prms_opt4_tlv);
gen_ldp_hdr(buf, iface, size);
@@ -68,9 +70,8 @@ send_hello(struct iface *iface)
gen_msg_tlv(buf, MSG_TYPE_HELLO, size);
- size -= sizeof(struct ldp_msg);
-
- gen_hello_prms_tlv(iface, buf, size);
+ gen_hello_prms_tlv(iface, buf);
+ gen_opt4_hello_prms_tlv(iface, buf);
send_packet(iface, buf->buf, buf->wpos, &dst);
ibuf_free(buf);
@@ -148,23 +149,19 @@ recv_hello(struct iface *iface, struct in_addr src, char *buf, u_int16_t len)
nbr_fsm(nbr, NBR_EVT_HELLO_RCVD);
- if (ntohl(nbr->addr.s_addr) < ntohl(nbr->iface->addr.s_addr) &&
- nbr->state == NBR_STA_PRESENT && !nbr_pending_connect(nbr) &&
- !nbr_pending_idtimer(nbr))
+ if (nbr->state == NBR_STA_PRESENT && nbr_session_active_role(nbr) &&
+ !nbr_pending_connect(nbr) && !nbr_pending_idtimer(nbr))
nbr_establish_connection(nbr);
}
int
-gen_hello_prms_tlv(struct iface *iface, struct ibuf *buf, u_int16_t size)
+gen_hello_prms_tlv(struct iface *iface, struct ibuf *buf)
{
struct hello_prms_tlv parms;
- /* We want just the size of the value */
- size -= TLV_HDR_LEN;
-
bzero(&parms, sizeof(parms));
parms.type = htons(TLV_TYPE_COMMONHELLO);
- parms.length = htons(size);
+ parms.length = htons(sizeof(parms.holdtime) + sizeof(parms.flags));
/* XXX */
parms.holdtime = htons(iface->holdtime);
parms.flags = 0;
@@ -173,6 +170,19 @@ gen_hello_prms_tlv(struct iface *iface, struct ibuf *buf, u_int16_t size)
}
int
+gen_opt4_hello_prms_tlv(struct iface *iface, struct ibuf *buf)
+{
+ struct hello_prms_opt4_tlv parms;
+
+ bzero(&parms, sizeof(parms));
+ parms.type = htons(TLV_TYPE_IPV4TRANSADDR);
+ parms.length = htons(4);
+ parms.value = ldpe_router_id();
+
+ return (ibuf_add(buf, &parms, sizeof(parms)));
+}
+
+int
tlv_decode_hello_prms(char *buf, u_int16_t len, u_int16_t *holdtime,
u_int16_t *flags)
{
diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h
index 6558bbedbd3..b810d19a3dd 100644
--- a/usr.sbin/ldpd/ldp.h
+++ b/usr.sbin/ldpd/ldp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldp.h,v 1.10 2013/05/30 16:14:50 claudio Exp $ */
+/* $OpenBSD: ldp.h,v 1.11 2013/06/01 01:34:57 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -126,6 +126,12 @@ struct hello_prms_tlv {
u_int16_t flags;
};
+struct hello_prms_opt4_tlv {
+ u_int16_t type;
+ u_int16_t length;
+ u_int32_t value;
+};
+
#define HELLO_PRMS_SIZE 8
#define S_SUCCESS 0x00000000
diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h
index 5051d5c30c7..0cd8367daaf 100644
--- a/usr.sbin/ldpd/ldpe.h
+++ b/usr.sbin/ldpd/ldpe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.h,v 1.17 2013/05/31 14:10:10 claudio Exp $ */
+/* $OpenBSD: ldpe.h,v 1.18 2013/06/01 01:34:57 claudio Exp $ */
/*
* Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
@@ -159,6 +159,7 @@ struct nbr *nbr_find_ldpid(u_int32_t, u_int16_t);
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 *);
diff --git a/usr.sbin/ldpd/neighbor.c b/usr.sbin/ldpd/neighbor.c
index 04a700852d5..9ab7cdaa74a 100644
--- a/usr.sbin/ldpd/neighbor.c
+++ b/usr.sbin/ldpd/neighbor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: neighbor.c,v 1.26 2013/05/31 14:10:10 claudio Exp $ */
+/* $OpenBSD: neighbor.c,v 1.27 2013/06/01 01:34:57 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -333,6 +333,15 @@ nbr_find_ldpid(u_int32_t rtr_id, u_int16_t lspace)
return (RB_FIND(nbr_id_head, &nbrs_by_id, &n));
}
+int
+nbr_session_active_role(struct nbr *nbr)
+{
+ if (ntohl(ldpe_router_id()) > ntohl(nbr->addr.s_addr))
+ return 1;
+
+ return 0;
+}
+
/* timers */
/* Inactivity timer: timeout based on hellos */
@@ -445,7 +454,7 @@ nbr_idtimer(int fd, short event, void *arg)
{
struct nbr *nbr = arg;
- if (ntohl(nbr->addr.s_addr) >= ntohl(nbr->iface->addr.s_addr))
+ if (!nbr_session_active_role(nbr))
return;
log_debug("nbr_idtimer: neighbor ID %s peerid %lu", inet_ntoa(nbr->id),
@@ -519,12 +528,8 @@ nbr_connect_cb(int fd, short event, void *arg)
int
nbr_establish_connection(struct nbr *nbr)
{
- struct sockaddr_in in;
-
- bzero(&in, sizeof(in));
- in.sin_family = AF_INET;
- in.sin_port = htons(LDP_PORT);
- in.sin_addr.s_addr = nbr->addr.s_addr;
+ struct sockaddr_in local_sa;
+ struct sockaddr_in remote_sa;
nbr->fd = socket(AF_INET, SOCK_STREAM, 0);
if (nbr->fd == -1) {
@@ -535,7 +540,26 @@ nbr_establish_connection(struct nbr *nbr)
session_socket_blockmode(nbr->fd, BM_NONBLOCK);
- if (connect(nbr->fd, (struct sockaddr *)&in, sizeof(in)) == -1) {
+ bzero(&local_sa, sizeof(local_sa));
+ local_sa.sin_family = AF_INET;
+ local_sa.sin_port = htons(0);
+ local_sa.sin_addr.s_addr = ldpe_router_id();
+
+ if (bind(nbr->fd, (struct sockaddr *) &local_sa,
+ sizeof(struct sockaddr_in)) == -1) {
+ log_debug("nbr_establish_connection: error while "
+ "binding socket to %s", inet_ntoa(local_sa.sin_addr));
+ close(nbr->fd);
+ return (-1);
+ }
+
+ bzero(&remote_sa, sizeof(remote_sa));
+ remote_sa.sin_family = AF_INET;
+ remote_sa.sin_port = htons(LDP_PORT);
+ remote_sa.sin_addr.s_addr = nbr->addr.s_addr;
+
+ if (connect(nbr->fd, (struct sockaddr *)&remote_sa,
+ sizeof(remote_sa)) == -1) {
if (errno == EINPROGRESS) {
event_set(&nbr->ev_connect, nbr->fd, EV_WRITE,
nbr_connect_cb, nbr);