diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2013-06-01 01:34:58 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2013-06-01 01:34:58 +0000 |
commit | b9c01f34a32422d2c2334dbaad81f342f3d2f81c (patch) | |
tree | 15d9d047ec16d7ff9f277a8060641043e8a708ee | |
parent | 3d6fd0382d82211c3fc923a8af8cbd23a3121ffc (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.c | 38 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldp.h | 8 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.h | 3 | ||||
-rw-r--r-- | usr.sbin/ldpd/neighbor.c | 42 |
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); |