Browse Source

nhrp: improve CIE prefix length handling

RFC2332 states that prefix length MUST be 0xff for unique bindings.
However, it seems at least some Cisco firmwares use host prefix
length instead (which on wire level makes sense). Relax the handling
of prefix length to treat all value longer than address length as
0xff. Additionally treat 0x00 the same way too, this is required
by the RFC. This also fixes the prefix length address family to be
checked against protocol address.
Timo Teräs 2 years ago
parent
commit
8e8945bb1b
3 changed files with 10 additions and 5 deletions
  1. 1 1
      nhrpd/nhrp_nhs.c
  2. 8 3
      nhrpd/nhrp_peer.c
  3. 1 1
      nhrpd/nhrp_shortcut.c

+ 1 - 1
nhrpd/nhrp_nhs.c

@@ -181,7 +181,7 @@ static int nhrp_reg_send_req(struct thread *t)
 	hdr->flags |= htons(NHRP_FLAG_REGISTRATION_NAT);
 	ext = nhrp_ext_push(zb, hdr, NHRP_EXTENSION_NAT_ADDRESS);
 	cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, &nifp->nbma, &if_ad->addr);
-	cie->prefix_length = 8 * sockunion_get_addrlen(&nifp->nbma);
+	cie->prefix_length = 8 * sockunion_get_addrlen(&if_ad->addr);
 	nhrp_ext_complete(zb, ext);
 
 	nhrp_packet_complete(zb, hdr);

+ 8 - 3
nhrpd/nhrp_peer.c

@@ -383,11 +383,12 @@ static void nhrp_handle_registration_request(struct nhrp_packet_parser *p)
 	struct nhrp_extension_header *ext;
 	struct nhrp_cache *c;
 	union sockunion cie_nbma, cie_proto, *proto_addr, *nbma_addr, *nbma_natoa;
-	int holdtime, natted = 0;
+	int holdtime, prefix_len, hostprefix_len, natted = 0;
 	size_t paylen;
 	void *pay;
 
 	debugf(NHRP_DEBUG_COMMON, "Parsing and replying to Registration Req");
+	hostprefix_len = 8 * sockunion_get_addrlen(&p->if_ad->addr);
 
 	if (!sockunion_same(&p->src_nbma, &p->peer->vc->remote.nbma))
 		natted = 1;
@@ -409,13 +410,17 @@ static void nhrp_handle_registration_request(struct nhrp_packet_parser *p)
 	zbuf_init(&payload, pay, paylen, paylen);
 
 	while ((cie = nhrp_cie_pull(&payload, hdr, &cie_nbma, &cie_proto)) != NULL) {
-		if (cie->prefix_length != 0xff && !(p->hdr->flags & htons(NHRP_FLAG_REGISTRATION_UNIQUE))) {
+		prefix_len = cie->prefix_length;
+		if (prefix_len == 0 || prefix_len >= hostprefix_len)
+			prefix_len = hostprefix_len;
+
+		if (prefix_len != hostprefix_len && !(p->hdr->flags & htons(NHRP_FLAG_REGISTRATION_UNIQUE))) {
 			cie->code = NHRP_CODE_BINDING_NON_UNIQUE;
 			continue;
 		}
 
 		/* We currently support only unique prefix registrations */
-		if (cie->prefix_length != 0xff) {
+		if (prefix_len != hostprefix_len) {
 			cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED;
 			continue;
 		}

+ 1 - 1
nhrpd/nhrp_shortcut.c

@@ -224,7 +224,7 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid, void *ar
 	prefix.prefixlen = cie->prefix_length;
 
 	/* Sanity check prefix length */
-	if (prefix.prefixlen >= 8*prefix_blen(&prefix)) {
+	if (prefix.prefixlen >= 8*prefix_blen(&prefix) || prefix.prefixlen == 0) {
 		prefix.prefixlen = 8*prefix_blen(&prefix);
 	} else if (nhrp_route_address(NULL, &pp->dst_proto, &route_prefix, NULL) == NHRP_ROUTE_NBMA_NEXTHOP) {
 		if (prefix.prefixlen < route_prefix.prefixlen)