From: Ghasem Naddaf Date: Thu, 27 Feb 2020 18:55:47 +0000 (-0800) Subject: nhrpd: add holdtime and MTU to CIE X-Git-Tag: base_7.4~233^2~3 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=47d4075766baa2020fc8de913a1a74e7dc430c22;p=matthieu%2Ffrr.git nhrpd: add holdtime and MTU to CIE nhrp_shortcut_send_resolution_req: Add Holding time and MTU to the resolution request CIE according to RFC2332 Sec. 5.2.1. nhrp_handle_resolution_req: Parse Holding time and MTU from CIE and update the requestor's binding. Also, when preparing the resolution reply, copy the Holding time and MTU to the CIE according to RFC2332 Sec. 5.2.2. Signed-off-by: Ghasem Naddaf --- diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index c5e985cdac..90f0986eba 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -314,23 +314,29 @@ void nhrp_peer_send(struct nhrp_peer *p, struct zbuf *zb) zbuf_reset(zb); } -static void nhrp_handle_resolution_req(struct nhrp_packet_parser *p) +static void nhrp_handle_resolution_req(struct nhrp_packet_parser *pp) { + struct interface *ifp = pp->ifp; struct zbuf *zb, payload; struct nhrp_packet_header *hdr; struct nhrp_cie_header *cie; struct nhrp_extension_header *ext; - struct nhrp_interface *nifp; + struct nhrp_cache *c; + union sockunion cie_nbma, cie_proto, *proto_addr, *nbma_addr; + int holdtime, prefix_len, hostprefix_len; + struct nhrp_interface *nifp = ifp->info; struct nhrp_peer *peer; + size_t paylen; + char buf[SU_ADDRSTRLEN]; - if (!(p->if_ad->flags & NHRP_IFF_SHORTCUT)) { + if (!(pp->if_ad->flags & NHRP_IFF_SHORTCUT)) { debugf(NHRP_DEBUG_COMMON, "Shortcuts disabled"); /* FIXME: Send error indication? */ return; } - if (p->if_ad->network_id && p->route_type == NHRP_ROUTE_OFF_NBMA - && p->route_prefix.prefixlen < 8) { + if (pp->if_ad->network_id && pp->route_type == NHRP_ROUTE_OFF_NBMA + && pp->route_prefix.prefixlen < 8) { debugf(NHRP_DEBUG_COMMON, "Shortcut to more generic than /8 dropped"); return; @@ -338,45 +344,105 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *p) debugf(NHRP_DEBUG_COMMON, "Parsing and replying to Resolution Req"); - if (nhrp_route_address(p->ifp, &p->src_proto, NULL, &peer) + if (nhrp_route_address(ifp, &pp->src_proto, NULL, &peer) != NHRP_ROUTE_NBMA_NEXTHOP) return; -#if 0 - /* FIXME: Update requestors binding if CIE specifies holding time */ - nhrp_cache_update_binding( - NHRP_CACHE_CACHED, &p->src_proto, - nhrp_peer_get(p->ifp, &p->src_nbma), - htons(cie->holding_time)); -#endif + /* Copy payload CIE */ + hostprefix_len = 8 * sockunion_get_addrlen(&pp->if_ad->addr); + paylen = zbuf_used(&pp->payload); + debugf(NHRP_DEBUG_COMMON, "shortcut res_rep: paylen %zu", paylen); + + while ((cie = nhrp_cie_pull(&pp->payload, pp->hdr, &cie_nbma, + &cie_proto)) + != NULL) { + prefix_len = cie->prefix_length; + debugf(NHRP_DEBUG_COMMON, + "shortcut res_rep: parsing CIE with " + "prefixlen=%u", + prefix_len); + if (prefix_len == 0 || prefix_len >= hostprefix_len) + prefix_len = hostprefix_len; + + if (prefix_len != hostprefix_len + && !(pp->hdr->flags + & htons(NHRP_FLAG_REGISTRATION_UNIQUE))) { + cie->code = NHRP_CODE_BINDING_NON_UNIQUE; + continue; + } + + /* We currently support only unique prefix registrations */ + if (prefix_len != hostprefix_len) { + cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED; + continue; + } + + proto_addr = (sockunion_family(&cie_proto) == AF_UNSPEC) + ? &pp->src_proto + : &cie_proto; + nbma_addr = (sockunion_family(&cie_nbma) == AF_UNSPEC) + ? &pp->src_nbma + : &cie_nbma; + + holdtime = htons(cie->holding_time); + debugf(NHRP_DEBUG_COMMON, + "shortcut res_rep: holdtime is %u " + "(if 0, using %u)", + holdtime, pp->if_ad->holdtime); + if (!holdtime) + holdtime = pp->if_ad->holdtime; + + c = nhrp_cache_get(ifp, proto_addr, 1); + if (!c) { + debugf(NHRP_DEBUG_COMMON, + "shortcut res_rep: no cache " + "found"); + cie->code = NHRP_CODE_INSUFFICIENT_RESOURCES; + continue; + } + if (nbma_addr) + sockunion2str(nbma_addr, buf, sizeof buf); + + debugf(NHRP_DEBUG_COMMON, + "shortcut res_rep: updating " + "binding for nmba addr %s", + nbma_addr ? buf : "(NULL)"); + if (!nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC, holdtime, + nhrp_peer_ref(pp->peer), + htons(cie->mtu), nbma_addr)) { + cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED; + continue; + } - nifp = peer->ifp->info; + cie->code = NHRP_CODE_SUCCESS; + } /* Create reply */ zb = zbuf_alloc(1500); - hdr = nhrp_packet_push(zb, NHRP_PACKET_RESOLUTION_REPLY, &p->src_nbma, - &p->src_proto, &p->dst_proto); + hdr = nhrp_packet_push(zb, NHRP_PACKET_RESOLUTION_REPLY, &pp->src_nbma, + &pp->src_proto, &pp->dst_proto); /* Copied information from request */ - hdr->flags = - p->hdr->flags & htons(NHRP_FLAG_RESOLUTION_SOURCE_IS_ROUTER - | NHRP_FLAG_RESOLUTION_SOURCE_STABLE); + hdr->flags = pp->hdr->flags + & htons(NHRP_FLAG_RESOLUTION_SOURCE_IS_ROUTER + | NHRP_FLAG_RESOLUTION_SOURCE_STABLE); hdr->flags |= htons(NHRP_FLAG_RESOLUTION_DESTINATION_STABLE | NHRP_FLAG_RESOLUTION_AUTHORATIVE); - hdr->u.request_id = p->hdr->u.request_id; + hdr->u.request_id = pp->hdr->u.request_id; - /* CIE payload */ + /* CIE payload for the reply packet */ cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, &nifp->nbma, - &p->if_ad->addr); - cie->holding_time = htons(p->if_ad->holdtime); - cie->mtu = htons(p->if_ad->mtu); - if (p->if_ad->network_id && p->route_type == NHRP_ROUTE_OFF_NBMA) - cie->prefix_length = p->route_prefix.prefixlen; + &pp->if_ad->addr); + cie->holding_time = htons(pp->if_ad->holdtime); + cie->mtu = htons(pp->if_ad->mtu); + if (pp->if_ad->network_id && pp->route_type == NHRP_ROUTE_OFF_NBMA) + cie->prefix_length = pp->route_prefix.prefixlen; else - cie->prefix_length = 8 * sockunion_get_addrlen(&p->if_ad->addr); + cie->prefix_length = + 8 * sockunion_get_addrlen(&pp->if_ad->addr); /* Handle extensions */ - while ((ext = nhrp_ext_pull(&p->extensions, &payload)) != NULL) { + while ((ext = nhrp_ext_pull(&pp->extensions, &payload)) != NULL) { switch (htons(ext->type) & ~NHRP_EXTENSION_FLAG_COMPULSORY) { case NHRP_EXTENSION_NAT_ADDRESS: if (sockunion_family(&nifp->nat_nbma) == AF_UNSPEC) @@ -386,13 +452,13 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *p) if (!ext) goto err; cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, - &nifp->nat_nbma, &p->if_ad->addr); + &nifp->nat_nbma, &pp->if_ad->addr); if (!cie) goto err; nhrp_ext_complete(zb, ext); break; default: - if (nhrp_ext_reply(zb, hdr, p->ifp, ext, &payload) < 0) + if (nhrp_ext_reply(zb, hdr, ifp, ext, &payload) < 0) goto err; break; } @@ -657,7 +723,7 @@ enum packet_type_t { PACKET_INDICATION, }; -static const struct { +static struct { enum packet_type_t type; const char *name; void (*handler)(struct nhrp_packet_parser *); @@ -898,11 +964,15 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb) if (extoff) { assert(zb->head > zb->buf); uint32_t header_offset = zb->head - zb->buf; - if ((extoff >= realsize) || (extoff < (header_offset))) { - info = "extoff larger than packet, or smaller than header"; + if (extoff >= realsize) { + info = "extoff larger than packet"; + goto drop; + } + if (extoff < header_offset) { + info = "extoff smaller than header offset"; goto drop; } - paylen = extoff - (zb->head - zb->buf); + paylen = extoff - header_offset; } else { paylen = zbuf_used(zb); } diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c index b3fdecf0ec..1f83b793af 100644 --- a/nhrpd/nhrp_shortcut.c +++ b/nhrpd/nhrp_shortcut.c @@ -306,7 +306,9 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s) struct nhrp_packet_header *hdr; struct interface *ifp; struct nhrp_interface *nifp; + struct nhrp_afi_data *if_ad; struct nhrp_peer *peer; + struct nhrp_cie_header *cie; if (nhrp_route_address(NULL, &s->addr, NULL, &peer) != NHRP_ROUTE_NBMA_NEXTHOP) @@ -336,7 +338,16 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s) * - MTU: MTU of the source station * - Holding Time: Max time to cache the source information * */ - /* FIXME: Send holding time, and MTU */ + /* FIXME: push CIE for each local protocol address */ + cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, NULL, NULL); + cie->prefix_length = 0xff; + if_ad = &nifp->afi[family2afi(sockunion_family(&s->addr))]; + cie->holding_time = htons(if_ad->holdtime); + cie->mtu = htons(if_ad->mtu); + debugf(NHRP_DEBUG_COMMON, + "Shortcut res_req: set cie holdtime to %u " + "and mtu to %u. shortcut's holdtime is %u.", + ntohs(cie->holding_time), ntohs(cie->mtu), s->holding_time); nhrp_ext_request(zb, hdr, ifp);