summaryrefslogtreecommitdiffstats
path: root/nhrpd
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-11-17 07:11:26 +0100
committerDaniel Baumann <daniel@debian.org>2024-11-17 07:11:26 +0100
commitd5587ccda8edb748ca8bfd1f0ed92a801ac5bfc6 (patch)
tree705ea89e798053f9c227b85512bc9f5b437b0093 /nhrpd
parentReleasing debian version 10.1.1-3. (diff)
downloadfrr-d5587ccda8edb748ca8bfd1f0ed92a801ac5bfc6.tar.xz
frr-d5587ccda8edb748ca8bfd1f0ed92a801ac5bfc6.zip
Merging upstream version 10.2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'nhrpd')
-rw-r--r--nhrpd/nhrp_interface.c2
-rw-r--r--nhrpd/nhrp_nhs.c4
-rw-r--r--nhrpd/nhrp_packet.c27
-rw-r--r--nhrpd/nhrp_peer.c162
-rw-r--r--nhrpd/nhrp_protocol.h1
-rw-r--r--nhrpd/nhrp_shortcut.c98
-rw-r--r--nhrpd/nhrp_vty.c74
-rw-r--r--nhrpd/nhrpd.h17
-rw-r--r--nhrpd/subdir.am4
9 files changed, 333 insertions, 56 deletions
diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c
index 7d0ab976..e81a2efb 100644
--- a/nhrpd/nhrp_interface.c
+++ b/nhrpd/nhrp_interface.c
@@ -99,6 +99,8 @@ static int nhrp_if_delete_hook(struct interface *ifp)
free(nifp->ipsec_fallback_profile);
if (nifp->source)
free(nifp->source);
+ if (nifp->auth_token)
+ zbuf_free(nifp->auth_token);
XFREE(MTYPE_NHRP_IF, ifp->info);
return 0;
diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c
index f779f934..b8958ba2 100644
--- a/nhrpd/nhrp_nhs.c
+++ b/nhrpd/nhrp_nhs.c
@@ -216,7 +216,7 @@ static void nhrp_reg_send_req(struct event *t)
cie->holding_time = htons(if_ad->holdtime);
cie->mtu = htons(if_ad->mtu);
- nhrp_ext_request(zb, hdr, ifp);
+ nhrp_ext_request(zb, hdr);
/* Cisco NAT detection extension */
if (sockunion_family(&r->proto_addr) != AF_UNSPEC) {
@@ -240,7 +240,7 @@ static void nhrp_reg_send_req(struct event *t)
cie->mtu = htons(if_ad->mtu);
nhrp_ext_complete(zb, ext);
- nhrp_packet_complete(zb, hdr);
+ nhrp_packet_complete(zb, hdr, ifp);
nhrp_peer_send(r->peer, zb);
zbuf_free(zb);
}
diff --git a/nhrpd/nhrp_packet.c b/nhrpd/nhrp_packet.c
index c6bd3bbb..71f5c2f0 100644
--- a/nhrpd/nhrp_packet.c
+++ b/nhrpd/nhrp_packet.c
@@ -115,14 +115,32 @@ uint16_t nhrp_packet_calculate_checksum(const uint8_t *pdu, uint16_t len)
return (~csum) & 0xffff;
}
-void nhrp_packet_complete(struct zbuf *zb, struct nhrp_packet_header *hdr)
+void nhrp_packet_complete(struct zbuf *zb, struct nhrp_packet_header *hdr,
+ struct interface *ifp)
{
+ nhrp_packet_complete_auth(zb, hdr, ifp, true);
+}
+
+void nhrp_packet_complete_auth(struct zbuf *zb, struct nhrp_packet_header *hdr,
+ struct interface *ifp, bool auth)
+{
+ struct nhrp_interface *nifp = ifp->info;
+ struct zbuf *auth_token = nifp->auth_token;
+ struct nhrp_extension_header *dst;
unsigned short size;
+ if (auth && auth_token) {
+ dst = nhrp_ext_push(zb, hdr,
+ NHRP_EXTENSION_AUTHENTICATION |
+ NHRP_EXTENSION_FLAG_COMPULSORY);
+ zbuf_copy_peek(zb, auth_token, zbuf_size(auth_token));
+ nhrp_ext_complete(zb, dst);
+ }
+
if (hdr->extension_offset)
nhrp_ext_push(zb, hdr,
- NHRP_EXTENSION_END
- | NHRP_EXTENSION_FLAG_COMPULSORY);
+ NHRP_EXTENSION_END |
+ NHRP_EXTENSION_FLAG_COMPULSORY);
size = zb->tail - (uint8_t *)hdr;
hdr->packet_size = htons(size);
@@ -225,8 +243,7 @@ struct nhrp_extension_header *nhrp_ext_pull(struct zbuf *zb,
return ext;
}
-void nhrp_ext_request(struct zbuf *zb, struct nhrp_packet_header *hdr,
- struct interface *ifp)
+void nhrp_ext_request(struct zbuf *zb, struct nhrp_packet_header *hdr)
{
/* Place holders for standard extensions */
nhrp_ext_push(zb, hdr,
diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c
index 6e7857c7..fa11980c 100644
--- a/nhrpd/nhrp_peer.c
+++ b/nhrpd/nhrp_peer.c
@@ -597,13 +597,19 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *pp)
nhrp_ext_complete(zb, ext);
}
break;
+ case NHRP_EXTENSION_AUTHENTICATION:
+ /* Extensions can be copied from original packet except
+ * authentication extension which must be regenerated
+ * hop by hop.
+ */
+ break;
default:
if (nhrp_ext_reply(zb, hdr, ifp, ext, &payload) < 0)
goto err;
break;
}
}
- nhrp_packet_complete(zb, hdr);
+ nhrp_packet_complete(zb, hdr, ifp);
nhrp_peer_send(peer, zb);
err:
nhrp_peer_unref(peer);
@@ -730,7 +736,8 @@ static void nhrp_handle_registration_request(struct nhrp_packet_parser *p)
}
}
- nhrp_packet_complete(zb, hdr);
+ /* auth ext was validated and copied from the request */
+ nhrp_packet_complete_auth(zb, hdr, ifp, false);
nhrp_peer_send(p->peer, zb);
err:
zbuf_free(zb);
@@ -812,7 +819,7 @@ void nhrp_peer_send_indication(struct interface *ifp, uint16_t protocol_type,
/* Payload is the packet causing indication */
zbuf_copy(zb, pkt, zbuf_used(pkt));
- nhrp_packet_complete(zb, hdr);
+ nhrp_packet_complete(zb, hdr, ifp);
nhrp_peer_send(p, zb);
nhrp_peer_unref(p);
zbuf_free(zb);
@@ -958,9 +965,12 @@ static void nhrp_peer_forward(struct nhrp_peer *p,
if (type == NHRP_EXTENSION_END)
break;
- dst = nhrp_ext_push(zb, hdr, htons(ext->type));
- if (!dst)
- goto err;
+ dst = NULL;
+ if (type != NHRP_EXTENSION_AUTHENTICATION) {
+ dst = nhrp_ext_push(zb, hdr, htons(ext->type));
+ if (!dst)
+ goto err;
+ }
switch (type) {
case NHRP_EXTENSION_FORWARD_TRANSIT_NHS:
@@ -1045,6 +1055,12 @@ static void nhrp_peer_forward(struct nhrp_peer *p,
zbuf_put(zb, extpl.head, len);
}
break;
+ case NHRP_EXTENSION_AUTHENTICATION:
+ /* Extensions can be copied from original packet except
+ * authentication extension which must be regenerated
+ * hop by hop.
+ */
+ break;
default:
if (htons(ext->type) & NHRP_EXTENSION_FLAG_COMPULSORY)
/* FIXME: RFC says to just copy, but not
@@ -1060,10 +1076,11 @@ static void nhrp_peer_forward(struct nhrp_peer *p,
zbuf_copy(zb, &extpl, len);
break;
}
- nhrp_ext_complete(zb, dst);
+ if (dst)
+ nhrp_ext_complete(zb, dst);
}
- nhrp_packet_complete(zb, hdr);
+ nhrp_packet_complete_auth(zb, hdr, pp->ifp, true);
nhrp_peer_send(p, zb);
zbuf_free(zb);
zbuf_free(zb_copy);
@@ -1089,8 +1106,7 @@ static void nhrp_packet_debug(struct zbuf *zb, const char *dir)
reply = packet_types[hdr->type].type == PACKET_REPLY;
debugf(NHRP_DEBUG_COMMON, "%s %s(%d) %pSU -> %pSU", dir,
- (packet_types[hdr->type].name ? packet_types[hdr->type].name
- : "Unknown"),
+ (packet_types[hdr->type].name ? : "Unknown"),
hdr->type, reply ? &dst_proto : &src_proto,
reply ? &src_proto : &dst_proto);
}
@@ -1106,11 +1122,111 @@ static int proto2afi(uint16_t proto)
return AF_UNSPEC;
}
-struct nhrp_route_info {
- int local;
- struct interface *ifp;
- struct nhrp_vc *vc;
-};
+static int nhrp_packet_send_error(struct nhrp_packet_parser *pp,
+ uint16_t indication_code, uint16_t offset)
+{
+ union sockunion src_proto, dst_proto;
+ struct nhrp_packet_header *hdr;
+ struct zbuf *zb;
+
+ src_proto = pp->src_proto;
+ dst_proto = pp->dst_proto;
+ if (packet_types[pp->hdr->type].type != PACKET_REPLY) {
+ src_proto = pp->dst_proto;
+ dst_proto = pp->src_proto;
+ }
+ /* Create reply */
+ zb = zbuf_alloc(1500);
+ hdr = nhrp_packet_push(zb, NHRP_PACKET_ERROR_INDICATION, &pp->src_nbma,
+ &src_proto, &dst_proto);
+
+ hdr->u.error.code = htons(indication_code);
+ hdr->u.error.offset = htons(offset);
+ hdr->flags = pp->hdr->flags;
+ hdr->hop_count = 0; /* XXX: cisco returns 255 */
+
+ /* Payload is the packet causing error */
+ /* Don`t add extension according to RFC */
+ zbuf_put(zb, pp->hdr, sizeof(*pp->hdr));
+ zbuf_put(zb, sockunion_get_addr(&pp->src_nbma),
+ hdr->src_nbma_address_len);
+ zbuf_put(zb, sockunion_get_addr(&pp->src_proto),
+ hdr->src_protocol_address_len);
+ zbuf_put(zb, sockunion_get_addr(&pp->dst_proto),
+ hdr->dst_protocol_address_len);
+ nhrp_packet_complete_auth(zb, hdr, pp->ifp, false);
+
+ nhrp_peer_send(pp->peer, zb);
+ zbuf_free(zb);
+ return 0;
+}
+
+static bool nhrp_connection_authorized(struct nhrp_packet_parser *pp)
+{
+ struct nhrp_cisco_authentication_extension *auth_ext;
+ struct nhrp_interface *nifp = pp->ifp->info;
+ struct zbuf *auth = nifp->auth_token;
+ struct nhrp_extension_header *ext;
+ struct zbuf *extensions, pl;
+ int cmp = 1;
+ int pl_pass_length, auth_pass_length;
+ size_t auth_size, pl_size;
+
+ extensions = zbuf_alloc(zbuf_used(&pp->extensions));
+ zbuf_copy_peek(extensions, &pp->extensions, zbuf_used(&pp->extensions));
+ while ((ext = nhrp_ext_pull(extensions, &pl)) != NULL) {
+ switch (htons(ext->type) & ~NHRP_EXTENSION_FLAG_COMPULSORY) {
+ case NHRP_EXTENSION_AUTHENTICATION:
+ /* Size of authentication extensions
+ * (varies based on password length)
+ */
+ auth_size = zbuf_size(auth);
+ pl_size = zbuf_size(&pl);
+ auth_ext = (struct nhrp_cisco_authentication_extension *)
+ auth->buf;
+
+ if (auth_size == pl_size)
+ cmp = memcmp(auth_ext, pl.buf, auth_size);
+ else
+ cmp = 1;
+
+ if (unlikely(debug_flags & NHRP_DEBUG_COMMON)) {
+ /* 4 bytes in nhrp_cisco_authentication_extension are allocated
+ * toward the authentication type. The remaining bytes are used for the
+ * password - so the password length is just the length of the extension - 4
+ */
+ auth_pass_length = (auth_size - 4);
+ pl_pass_length = (pl_size - 4);
+ /* Because characters are to be printed in HEX, (2* the max pass length) + 1
+ * is needed for the string representation
+ */
+ char auth_pass[(2 * NHRP_CISCO_PASS_LEN) + 1] = { 0 },
+ pl_pass[(2 * NHRP_CISCO_PASS_LEN) + 1] = { 0 };
+ /* Converting bytes in buffer to HEX and saving output as a string -
+ * Passphrase is converted to HEX in order to avoid printing
+ * non ACII-compliant characters
+ */
+ for (int i = 0; i < (auth_pass_length); i++)
+ snprintf(auth_pass + (i * 2), 3, "%02X",
+ auth_ext->secret[i]);
+ for (int i = 0; i < (pl_pass_length); i++)
+ snprintf(pl_pass + (i * 2), 3, "%02X",
+ ((struct nhrp_cisco_authentication_extension *)pl.buf)
+ ->secret[i]);
+
+ debugf(NHRP_DEBUG_COMMON,
+ "Processing Authentication Extension for (%s:%s|%d)",
+ auth_pass, pl_pass, cmp);
+ }
+ break;
+ default:
+ /* Ignoring all received extensions except Authentication*/
+ break;
+ }
+ }
+ zbuf_free(extensions);
+ return cmp == 0;
+}
void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
{
@@ -1191,10 +1307,20 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
goto drop;
}
+ /* RFC2332 5.3.4 - Authentication is always done pairwise on an NHRP
+ * hop-by-hop basis; i.e. regenerated at each hop. */
nhrp_packet_debug(zb, "Recv");
-
- /* FIXME: Check authentication here. This extension needs to be
- * pre-handled. */
+ if (nifp->auth_token &&
+ (hdr->type != NHRP_PACKET_ERROR_INDICATION ||
+ hdr->u.error.code != NHRP_ERROR_AUTHENTICATION_FAILURE)) {
+ if (!nhrp_connection_authorized(&pp)) {
+ nhrp_packet_send_error(&pp,
+ NHRP_ERROR_AUTHENTICATION_FAILURE,
+ 0);
+ info = "authentication failure";
+ goto drop;
+ }
+ }
/* Figure out if this is local */
target_addr = (packet_types[hdr->type].type == PACKET_REPLY)
diff --git a/nhrpd/nhrp_protocol.h b/nhrpd/nhrp_protocol.h
index 8cf1ebbc..a4fb315b 100644
--- a/nhrpd/nhrp_protocol.h
+++ b/nhrpd/nhrp_protocol.h
@@ -73,6 +73,7 @@
/* NHRP Authentication extension types (ala Cisco) */
#define NHRP_AUTHENTICATION_PLAINTEXT 0x00000001
+#define NHRP_CISCO_PASS_LEN 8
/* NHRP Packet Structures */
struct nhrp_packet_header {
diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c
index e83ce7f5..55d61a90 100644
--- a/nhrpd/nhrp_shortcut.c
+++ b/nhrpd/nhrp_shortcut.c
@@ -21,14 +21,16 @@ static struct route_table *shortcut_rib[AFI_MAX];
static void nhrp_shortcut_do_purge(struct event *t);
static void nhrp_shortcut_delete(struct nhrp_shortcut *s,
void *arg __attribute__((__unused__)));
-static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s);
+static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s,
+ bool retry);
+static void nhrp_shortcut_retry_resolution_req(struct event *t);
static void nhrp_shortcut_check_use(struct nhrp_shortcut *s)
{
if (s->expiring && s->cache && s->cache->used) {
debugf(NHRP_DEBUG_ROUTE, "Shortcut %pFX used and expiring",
s->p);
- nhrp_shortcut_send_resolution_req(s);
+ nhrp_shortcut_send_resolution_req(s, false);
}
}
@@ -37,7 +39,7 @@ static void nhrp_shortcut_do_expire(struct event *t)
struct nhrp_shortcut *s = EVENT_ARG(t);
event_add_timer(master, nhrp_shortcut_do_purge, s, s->holding_time / 3,
- &s->t_timer);
+ &s->t_shortcut_purge);
s->expiring = 1;
nhrp_shortcut_check_use(s);
}
@@ -124,12 +126,12 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s,
s->route_installed = 0;
}
- EVENT_OFF(s->t_timer);
+ EVENT_OFF(s->t_shortcut_purge);
if (holding_time) {
s->expiring = 0;
s->holding_time = holding_time;
event_add_timer(master, nhrp_shortcut_do_expire, s,
- 2 * holding_time / 3, &s->t_timer);
+ 2 * holding_time / 3, &s->t_shortcut_purge);
}
}
@@ -139,7 +141,8 @@ static void nhrp_shortcut_delete(struct nhrp_shortcut *s,
struct route_node *rn;
afi_t afi = family2afi(PREFIX_FAMILY(s->p));
- EVENT_OFF(s->t_timer);
+ EVENT_OFF(s->t_shortcut_purge);
+ EVENT_OFF(s->t_retry_resolution);
nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);
debugf(NHRP_DEBUG_ROUTE, "Shortcut %pFX purged", s->p);
@@ -159,7 +162,8 @@ static void nhrp_shortcut_delete(struct nhrp_shortcut *s,
static void nhrp_shortcut_do_purge(struct event *t)
{
struct nhrp_shortcut *s = EVENT_ARG(t);
- s->t_timer = NULL;
+ s->t_shortcut_purge = NULL;
+ EVENT_OFF(s->t_retry_resolution);
nhrp_shortcut_delete(s, NULL);
}
@@ -206,8 +210,10 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid,
int holding_time = pp->if_ad->holdtime;
nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);
- EVENT_OFF(s->t_timer);
- event_add_timer(master, nhrp_shortcut_do_purge, s, 1, &s->t_timer);
+ EVENT_OFF(s->t_shortcut_purge);
+ EVENT_OFF(s->t_retry_resolution);
+ event_add_timer(master, nhrp_shortcut_do_purge, s, 1,
+ &s->t_shortcut_purge);
if (pp->hdr->type != NHRP_PACKET_RESOLUTION_REPLY) {
if (pp->hdr->type == NHRP_PACKET_ERROR_INDICATION
@@ -374,7 +380,8 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid,
debugf(NHRP_DEBUG_COMMON, "Shortcut: Resolution reply handled");
}
-static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)
+static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s,
+ bool retry)
{
struct zbuf *zb;
struct nhrp_packet_header *hdr;
@@ -389,6 +396,22 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)
!= NHRP_ROUTE_NBMA_NEXTHOP)
return;
+ /*Retry interval for NHRP resolution request
+ * will start at 1 second and will be doubled every time
+ * another resolution request is sent, until it is
+ * eventually upper-bounded by the purge time of
+ * the shortcut.
+ */
+ if (!retry)
+ s->retry_interval = 1;
+ event_add_timer(master, nhrp_shortcut_retry_resolution_req, s,
+ s->retry_interval, &s->t_retry_resolution);
+ if (s->retry_interval != (NHRPD_DEFAULT_PURGE_TIME / 4))
+ s->retry_interval = ((s->retry_interval * 2) <
+ (NHRPD_DEFAULT_PURGE_TIME / 4))
+ ? (s->retry_interval * 2)
+ : (NHRPD_DEFAULT_PURGE_TIME / 4);
+
if (s->type == NHRP_CACHE_INVALID || s->type == NHRP_CACHE_NEGATIVE)
s->type = NHRP_CACHE_INCOMPLETE;
@@ -401,9 +424,23 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)
zb, NHRP_PACKET_RESOLUTION_REQUEST, &nifp->nbma,
&nifp->afi[family2afi(sockunion_family(&s->addr))].addr,
&s->addr);
- hdr->u.request_id =
- htonl(nhrp_reqid_alloc(&nhrp_packet_reqid, &s->reqid,
- nhrp_shortcut_recv_resolution_rep));
+
+ /* RFC2332 - The value is taken from a 32 bit counter that is incremented
+ * each time a new "request" is transmitted. The same value MUST
+ * be used when resending a "request", i.e., when a "reply" has not been
+ * received for a "request" and a retry is sent after an
+ * appropriate interval
+ */
+ if (!retry)
+ hdr->u.request_id = htonl(
+ nhrp_reqid_alloc(&nhrp_packet_reqid, &s->reqid,
+ nhrp_shortcut_recv_resolution_rep));
+ else
+ /* Just pull request_id from existing incomplete
+ * shortcut in the case of a retry
+ */
+ hdr->u.request_id = htonl(s->reqid.request_id);
+
hdr->flags = htons(NHRP_FLAG_RESOLUTION_SOURCE_IS_ROUTER
| NHRP_FLAG_RESOLUTION_AUTHORATIVE
| NHRP_FLAG_RESOLUTION_SOURCE_STABLE);
@@ -412,7 +449,7 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)
* - Prefix length: widest acceptable prefix we accept (if U set, 0xff)
* - MTU: MTU of the source station
* - Holding Time: Max time to cache the source information
- * */
+ */
/* FIXME: push CIE for each local protocol address */
cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, NULL, NULL);
if_ad = &nifp->afi[family2afi(sockunion_family(&s->addr))];
@@ -425,7 +462,7 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)
"Shortcut res_req: set cie ht to %u and mtu to %u. shortcut ht is %u",
ntohs(cie->holding_time), ntohs(cie->mtu), s->holding_time);
- nhrp_ext_request(zb, hdr, ifp);
+ nhrp_ext_request(zb, hdr);
/* Cisco NAT detection extension */
hdr->flags |= htons(NHRP_FLAG_RESOLUTION_NAT);
@@ -438,7 +475,7 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)
nhrp_ext_complete(zb, ext);
}
- nhrp_packet_complete(zb, hdr);
+ nhrp_packet_complete(zb, hdr, ifp);
nhrp_peer_send(peer, zb);
nhrp_peer_unref(peer);
@@ -456,13 +493,25 @@ void nhrp_shortcut_initiate(union sockunion *addr)
s = nhrp_shortcut_get(&p);
if (s && s->type != NHRP_CACHE_INCOMPLETE) {
s->addr = *addr;
- EVENT_OFF(s->t_timer);
- event_add_timer(master, nhrp_shortcut_do_purge, s, 30,
- &s->t_timer);
- nhrp_shortcut_send_resolution_req(s);
+ EVENT_OFF(s->t_shortcut_purge);
+ EVENT_OFF(s->t_retry_resolution);
+
+ event_add_timer(master, nhrp_shortcut_do_purge, s,
+ NHRPD_DEFAULT_PURGE_TIME, &s->t_shortcut_purge);
+ nhrp_shortcut_send_resolution_req(s, false);
}
}
+static void nhrp_shortcut_retry_resolution_req(struct event *t)
+{
+ struct nhrp_shortcut *s = EVENT_ARG(t);
+
+ EVENT_OFF(s->t_retry_resolution);
+ debugf(NHRP_DEBUG_COMMON, "Shortcut: Retrying Resolution Request");
+ nhrp_shortcut_send_resolution_req(s, true);
+}
+
+
void nhrp_shortcut_init(void)
{
shortcut_rib[AFI_IP] = route_table_init();
@@ -503,13 +552,14 @@ struct purge_ctx {
void nhrp_shortcut_purge(struct nhrp_shortcut *s, int force)
{
- EVENT_OFF(s->t_timer);
+ EVENT_OFF(s->t_shortcut_purge);
+ EVENT_OFF(s->t_retry_resolution);
nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);
if (force) {
/* Immediate purge on route with draw or pending shortcut */
event_add_timer_msec(master, nhrp_shortcut_do_purge, s, 5,
- &s->t_timer);
+ &s->t_shortcut_purge);
} else {
/* Soft expire - force immediate renewal, but purge
* in few seconds to make sure stale route is not
@@ -518,8 +568,8 @@ void nhrp_shortcut_purge(struct nhrp_shortcut *s, int force)
* This allows to keep nhrp route up, and to not
* cause temporary rerouting via hubs causing latency
* jitter. */
- event_add_timer_msec(master, nhrp_shortcut_do_purge, s, 3000,
- &s->t_timer);
+ event_add_timer_msec(master, nhrp_shortcut_do_purge, s,
+ NHRPD_PURGE_EXPIRE, &s->t_shortcut_purge);
s->expiring = 1;
nhrp_shortcut_check_use(s);
}
diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c
index f91fcb53..199f4d75 100644
--- a/nhrpd/nhrp_vty.c
+++ b/nhrpd/nhrp_vty.c
@@ -12,6 +12,9 @@
#include "nhrpd.h"
#include "netlink.h"
+#include "nhrp_protocol.h"
+
+#include "nhrpd/nhrp_vty_clippy.c"
static int nhrp_config_write(struct vty *vty);
static struct cmd_node zebra_node = {
@@ -292,10 +295,15 @@ DEFUN(tunnel_protection, tunnel_protection_cmd,
}
DEFUN(no_tunnel_protection, no_tunnel_protection_cmd,
- "no tunnel protection",
+ "no tunnel protection [vici profile PROFILE [fallback-profile FALLBACK]]",
NO_STR
"NHRP/GRE integration\n"
- "IPsec protection\n")
+ "IPsec protection\n"
+ "VICI (StrongSwan)\n"
+ "IPsec profile\n"
+ "IPsec profile name\n"
+ "Fallback IPsec profile\n"
+ "Fallback IPsec profile name\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
@@ -459,6 +467,58 @@ DEFUN(if_no_nhrp_holdtime, if_no_nhrp_holdtime_cmd,
return CMD_SUCCESS;
}
+DEFPY(if_nhrp_authentication, if_nhrp_authentication_cmd,
+ AFI_CMD "nhrp authentication PASSWORD$password",
+ AFI_STR
+ NHRP_STR
+ "Specify plain text password used for authenticantion\n"
+ "Password, plain text, limited to 8 characters\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct nhrp_cisco_authentication_extension *auth;
+ struct nhrp_interface *nifp = ifp->info;
+ int pass_len = strlen(password);
+
+ if (pass_len > NHRP_CISCO_PASS_LEN) {
+ vty_out(vty, "Password size limit exceeded (%d>%d)\n",
+ pass_len, NHRP_CISCO_PASS_LEN);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (nifp->auth_token) {
+ zbuf_free(nifp->auth_token);
+ nifp->auth_token = NULL;
+ }
+
+ nifp->auth_token = zbuf_alloc(pass_len + sizeof(uint32_t));
+ auth = (struct nhrp_cisco_authentication_extension *)
+ nifp->auth_token->buf;
+ auth->type = htonl(NHRP_AUTHENTICATION_PLAINTEXT);
+ memcpy(auth->secret, password, pass_len);
+
+ return CMD_SUCCESS;
+}
+
+
+DEFPY(if_no_nhrp_authentication, if_no_nhrp_authentication_cmd,
+ "no " AFI_CMD "nhrp authentication PASSWORD$password",
+ NO_STR
+ AFI_STR
+ NHRP_STR
+ "Specify plain text password used for authenticantion\n"
+ "Password, plain text, limited to 8 characters\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct nhrp_interface *nifp = ifp->info;
+
+ if (nifp->auth_token) {
+ zbuf_free(nifp->auth_token);
+ nifp->auth_token = NULL;
+ }
+ return CMD_SUCCESS;
+}
+
+
DEFUN(if_nhrp_mtu, if_nhrp_mtu_cmd,
"ip nhrp mtu <(576-1500)|opennhrp>",
IP_STR
@@ -1053,6 +1113,7 @@ DEFUN(show_dmvpn, show_dmvpn_cmd,
static void clear_nhrp_cache(struct nhrp_cache *c, void *data)
{
struct info_ctx *ctx = data;
+
if (c->cur.type <= NHRP_CACHE_DYNAMIC) {
nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL,
NULL);
@@ -1129,6 +1190,7 @@ static void interface_config_write_nhrp_map(struct nhrp_cache_config *c,
static int interface_config_write(struct vty *vty)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct nhrp_cisco_authentication_extension *auth;
struct write_map_ctx mapctx;
struct interface *ifp;
struct nhrp_interface *nifp;
@@ -1155,6 +1217,12 @@ static int interface_config_write(struct vty *vty)
if (nifp->source)
vty_out(vty, " tunnel source %s\n", nifp->source);
+ if (nifp->auth_token) {
+ auth = (struct nhrp_cisco_authentication_extension *)
+ nifp->auth_token->buf;
+ vty_out(vty, " ip nhrp authentication %s\n", auth->secret);
+ }
+
for (afi = 0; afi < AFI_MAX; afi++) {
struct nhrp_afi_data *ad = &nifp->afi[afi];
@@ -1256,6 +1324,8 @@ void nhrp_config_init(void)
install_element(INTERFACE_NODE, &if_no_nhrp_network_id_cmd);
install_element(INTERFACE_NODE, &if_nhrp_holdtime_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_holdtime_cmd);
+ install_element(INTERFACE_NODE, &if_nhrp_authentication_cmd);
+ install_element(INTERFACE_NODE, &if_no_nhrp_authentication_cmd);
install_element(INTERFACE_NODE, &if_nhrp_mtu_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_mtu_cmd);
install_element(INTERFACE_NODE, &if_nhrp_flags_cmd);
diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h
index e389b748..6cab7b3a 100644
--- a/nhrpd/nhrpd.h
+++ b/nhrpd/nhrpd.h
@@ -15,7 +15,8 @@
DECLARE_MGROUP(NHRPD);
#define NHRPD_DEFAULT_HOLDTIME 7200
-
+#define NHRPD_DEFAULT_PURGE_TIME 30
+#define NHRPD_PURGE_EXPIRE 3000
#define NHRP_DEFAULT_CONFIG "nhrpd.conf"
extern struct event_loop *master;
@@ -250,10 +251,12 @@ struct nhrp_shortcut {
union sockunion addr;
struct nhrp_reqid reqid;
- struct event *t_timer;
+ struct event *t_shortcut_purge;
+ struct event *t_retry_resolution;
enum nhrp_cache_type type;
unsigned int holding_time;
+ unsigned int retry_interval;
unsigned route_installed : 1;
unsigned expiring : 1;
@@ -311,6 +314,7 @@ DECLARE_DLIST(nhrp_reglist, struct nhrp_registration, reglist_entry);
struct nhrp_interface {
struct interface *ifp;
+ struct zbuf *auth_token;
unsigned enabled : 1;
char *ipsec_profile, *ipsec_fallback_profile, *source;
@@ -480,9 +484,13 @@ struct nhrp_packet_header *nhrp_packet_push(struct zbuf *zb, uint8_t type,
const union sockunion *src_nbma,
const union sockunion *src_proto,
const union sockunion *dst_proto);
-void nhrp_packet_complete(struct zbuf *zb, struct nhrp_packet_header *hdr);
uint16_t nhrp_packet_calculate_checksum(const uint8_t *pdu, uint16_t len);
+void nhrp_packet_complete(struct zbuf *zb, struct nhrp_packet_header *hdr,
+ struct interface *ifp);
+void nhrp_packet_complete_auth(struct zbuf *zb, struct nhrp_packet_header *hdr,
+ struct interface *ifp, bool auth);
+
struct nhrp_packet_header *nhrp_packet_pull(struct zbuf *zb,
union sockunion *src_nbma,
union sockunion *src_proto,
@@ -501,8 +509,7 @@ nhrp_ext_push(struct zbuf *zb, struct nhrp_packet_header *hdr, uint16_t type);
void nhrp_ext_complete(struct zbuf *zb, struct nhrp_extension_header *ext);
struct nhrp_extension_header *nhrp_ext_pull(struct zbuf *zb,
struct zbuf *payload);
-void nhrp_ext_request(struct zbuf *zb, struct nhrp_packet_header *hdr,
- struct interface *);
+void nhrp_ext_request(struct zbuf *zb, struct nhrp_packet_header *hdr);
int nhrp_ext_reply(struct zbuf *zb, struct nhrp_packet_header *hdr,
struct interface *ifp, struct nhrp_extension_header *ext,
struct zbuf *extpayload);
diff --git a/nhrpd/subdir.am b/nhrpd/subdir.am
index 227ff6c6..94fb3bb5 100644
--- a/nhrpd/subdir.am
+++ b/nhrpd/subdir.am
@@ -42,3 +42,7 @@ noinst_HEADERS += \
nhrpd/zbuf.h \
nhrpd/znl.h \
# end
+
+clippy_scan += \
+ nhrpd/nhrp_vty.c \
+ # end