diff options
author | Daniel Baumann <daniel@debian.org> | 2024-11-17 07:11:26 +0100 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-11-17 07:11:26 +0100 |
commit | d5587ccda8edb748ca8bfd1f0ed92a801ac5bfc6 (patch) | |
tree | 705ea89e798053f9c227b85512bc9f5b437b0093 /nhrpd | |
parent | Releasing debian version 10.1.1-3. (diff) | |
download | frr-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.c | 2 | ||||
-rw-r--r-- | nhrpd/nhrp_nhs.c | 4 | ||||
-rw-r--r-- | nhrpd/nhrp_packet.c | 27 | ||||
-rw-r--r-- | nhrpd/nhrp_peer.c | 162 | ||||
-rw-r--r-- | nhrpd/nhrp_protocol.h | 1 | ||||
-rw-r--r-- | nhrpd/nhrp_shortcut.c | 98 | ||||
-rw-r--r-- | nhrpd/nhrp_vty.c | 74 | ||||
-rw-r--r-- | nhrpd/nhrpd.h | 17 | ||||
-rw-r--r-- | nhrpd/subdir.am | 4 |
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 |