summaryrefslogtreecommitdiffstats
path: root/nhrpd/nhrp_peer.c
diff options
context:
space:
mode:
authorGhasem Naddaf <ghasem.naddaf@gmail.com>2020-02-27 19:55:47 +0100
committerGhasem Naddaf <ghasem.naddaf@gmail.com>2020-02-27 19:55:47 +0100
commit47d4075766baa2020fc8de913a1a74e7dc430c22 (patch)
treead4e21c5b5834ce88558a3c475c592eaf5644984 /nhrpd/nhrp_peer.c
parentnhrpd: fix netlink neigh message handling for lladdr (diff)
downloadfrr-47d4075766baa2020fc8de913a1a74e7dc430c22.tar.xz
frr-47d4075766baa2020fc8de913a1a74e7dc430c22.zip
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 <gshirazi@infoblox.com>
Diffstat (limited to 'nhrpd/nhrp_peer.c')
-rw-r--r--nhrpd/nhrp_peer.c138
1 files changed, 104 insertions, 34 deletions
diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c
index c5e985cda..90f0986eb 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);
}