Skip to content

Commit

Permalink
Merge pull request #8240 from reubendowle/fixes/nhrp-nat
Browse files Browse the repository at this point in the history
nhrp: NAT fixes
  • Loading branch information
Jafaral authored Apr 4, 2021
2 parents 68cfcb7 + ba113ac commit 283981e
Show file tree
Hide file tree
Showing 10 changed files with 468 additions and 95 deletions.
19 changes: 16 additions & 3 deletions nhrpd/nhrp_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ static int nhrp_cache_do_timeout(struct thread *t)

c->t_timeout = NULL;
if (c->cur.type != NHRP_CACHE_INVALID)
nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL,
NULL);
return 0;
}

Expand Down Expand Up @@ -301,7 +302,8 @@ static void nhrp_cache_peer_notifier(struct notifier_block *n,
case NOTIFY_PEER_DOWN:
case NOTIFY_PEER_IFCONFIG_CHANGED:
notifier_call(&c->notifier_list, NOTIFY_CACHE_DOWN);
nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL,
NULL);
break;
case NOTIFY_PEER_NBMA_CHANGING:
if (c->cur.type == NHRP_CACHE_DYNAMIC)
Expand Down Expand Up @@ -422,7 +424,8 @@ static void nhrp_cache_newpeer_notifier(struct notifier_block *n,

int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type,
int holding_time, struct nhrp_peer *p,
uint32_t mtu, union sockunion *nbma_oa)
uint32_t mtu, union sockunion *nbma_oa,
union sockunion *nbma_claimed)
{
char buf[2][SU_ADDRSTRLEN];

Expand Down Expand Up @@ -464,6 +467,12 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type,
memset(&c->cur.remote_nbma_natoa, 0,
sizeof(c->cur.remote_nbma_natoa));

if (nbma_claimed)
c->cur.remote_nbma_claimed = *nbma_claimed;
else
memset(&c->cur.remote_nbma_claimed, 0,
sizeof(c->cur.remote_nbma_claimed));

nhrp_peer_unref(p);
} else {
debugf(NHRP_DEBUG_COMMON,
Expand All @@ -474,9 +483,13 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type,
c->new.type = type;
c->new.peer = p;
c->new.mtu = mtu;
c->new.holding_time = holding_time;
if (nbma_oa)
c->new.remote_nbma_natoa = *nbma_oa;

if (nbma_claimed)
c->new.remote_nbma_claimed = *nbma_claimed;

if (holding_time > 0)
c->new.expires = monotime(NULL) + holding_time;
else if (holding_time < 0)
Expand Down
10 changes: 5 additions & 5 deletions nhrpd/nhrp_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ static void nhrp_interface_update_address(struct interface *ifp, afi_t afi,
nc = nhrp_cache_get(ifp, &if_ad->addr, 0);
if (nc)
nhrp_cache_update_binding(nc, NHRP_CACHE_LOCAL, -1,
NULL, 0, NULL);
NULL, 0, NULL, NULL);
}

debugf(NHRP_DEBUG_KERNEL, "%s: IPv%d address changed to %s", ifp->name,
Expand All @@ -267,7 +267,7 @@ static void nhrp_interface_update_address(struct interface *ifp, afi_t afi,
nc = nhrp_cache_get(ifp, &addr, 1);
if (nc)
nhrp_cache_update_binding(nc, NHRP_CACHE_LOCAL, 0, NULL,
0, NULL);
0, NULL, NULL);
}

notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_ADDRESS_CHANGED);
Expand Down Expand Up @@ -364,7 +364,7 @@ static void interface_config_update_nhrp_map(struct nhrp_cache_config *cc,
if (c && c->map) {
nhrp_cache_update_binding(
c, c->cur.type, -1,
nhrp_peer_get(ifp, &nbma_addr), 0, NULL);
nhrp_peer_get(ifp, &nbma_addr), 0, NULL, NULL);
}
return;
}
Expand All @@ -375,11 +375,11 @@ static void interface_config_update_nhrp_map(struct nhrp_cache_config *cc,
c->map = 1;
if (cc->type == NHRP_CACHE_LOCAL)
nhrp_cache_update_binding(c, NHRP_CACHE_LOCAL, 0, NULL, 0,
NULL);
NULL, NULL);
else {
nhrp_cache_update_binding(c, NHRP_CACHE_STATIC, 0,
nhrp_peer_get(ifp, &cc->nbma), 0,
NULL);
NULL, NULL);
}
}

Expand Down
70 changes: 62 additions & 8 deletions nhrpd/nhrp_nhs.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)
struct nhrp_cie_header *cie;
struct nhrp_cache *c;
struct zbuf extpl;
union sockunion cie_nbma, cie_proto, *proto;
union sockunion cie_nbma, cie_nbma_nhs, cie_proto, cie_proto_nhs,
*proto;
char buf[64];
int ok = 0, holdtime;
unsigned short mtu = 0;

Expand Down Expand Up @@ -66,6 +68,7 @@ static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)

/* Parse extensions */
sockunion_family(&nifp->nat_nbma) = AF_UNSPEC;
sockunion_family(&cie_nbma_nhs) = AF_UNSPEC;
while ((ext = nhrp_ext_pull(&p->extensions, &extpl)) != NULL) {
switch (htons(ext->type) & ~NHRP_EXTENSION_FLAG_COMPULSORY) {
case NHRP_EXTENSION_NAT_ADDRESS:
Expand All @@ -75,10 +78,17 @@ static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)
&cie_proto)) {
nifp->nat_nbma = cie_nbma;
debugf(NHRP_DEBUG_IF,
"%s: NAT detected, real NBMA address: %pSU",
ifp->name, &nifp->nbma);
"%s: NAT detected, real NBMA address: %s",
ifp->name,
sockunion2str(&nifp->nbma, buf,
sizeof(buf)));
}
break;
case NHRP_EXTENSION_RESPONDER_ADDRESS:
/* NHS adds its own record as responder address */
nhrp_cie_pull(&extpl, p->hdr, &cie_nbma_nhs,
&cie_proto_nhs);
break;
}
}

Expand All @@ -96,7 +106,8 @@ static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)
c = nhrp_cache_get(ifp, &p->dst_proto, 1);
if (c)
nhrp_cache_update_binding(c, NHRP_CACHE_NHS, holdtime,
nhrp_peer_ref(r->peer), mtu, NULL);
nhrp_peer_ref(r->peer), mtu, NULL,
&cie_nbma_nhs);
}

static int nhrp_reg_timeout(struct thread *t)
Expand All @@ -111,7 +122,7 @@ static int nhrp_reg_timeout(struct thread *t)
c = nhrp_cache_get(r->nhs->ifp, &r->proto_addr, 0);
if (c)
nhrp_cache_update_binding(c, NHRP_CACHE_NHS, -1, NULL,
0, NULL);
0, NULL, NULL);
sockunion_family(&r->proto_addr) = AF_UNSPEC;
}

Expand Down Expand Up @@ -162,7 +173,7 @@ static int nhrp_reg_send_req(struct thread *t)
struct interface *ifp = nhs->ifp;
struct nhrp_interface *nifp = ifp->info;
struct nhrp_afi_data *if_ad = &nifp->afi[nhs->afi];
union sockunion *dst_proto;
union sockunion *dst_proto, nhs_proto;
struct zbuf *zb;
struct nhrp_packet_header *hdr;
struct nhrp_extension_header *ext;
Expand Down Expand Up @@ -207,17 +218,34 @@ static int nhrp_reg_send_req(struct thread *t)
/* FIXME: push CIE for each local protocol address */
cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, NULL, NULL);
/* RFC2332 5.2.1 if unique is set then prefix length must be 0xff */
cie->prefix_length = (if_ad->flags & NHRP_IFF_REG_NO_UNIQUE) ? 8 * sockunion_get_addrlen(dst_proto) : 0xff;
cie->prefix_length = (if_ad->flags & NHRP_IFF_REG_NO_UNIQUE)
? 8 * sockunion_get_addrlen(dst_proto)
: 0xff;
cie->holding_time = htons(if_ad->holdtime);
cie->mtu = htons(if_ad->mtu);

nhrp_ext_request(zb, hdr, ifp);

/* Cisco NAT detection extension */
if (sockunion_family(&r->proto_addr) != AF_UNSPEC) {
nhs_proto = r->proto_addr;
} else if (sockunion_family(&nhs->proto_addr) != AF_UNSPEC) {
nhs_proto = nhs->proto_addr;
} else {
/* cisco magic: If NHS is not known then use all 0s as
* client protocol address in NAT Extension header
*/
memset(&nhs_proto, 0, sizeof(nhs_proto));
sockunion_family(&nhs_proto) = afi2family(nhs->afi);
}

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);
/* push NHS details */
cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, &r->peer->vc->remote.nbma,
&nhs_proto);
cie->prefix_length = 8 * sockunion_get_addrlen(&if_ad->addr);
cie->mtu = htons(if_ad->mtu);
nhrp_ext_complete(zb, ext);

nhrp_packet_complete(zb, hdr);
Expand Down Expand Up @@ -442,3 +470,29 @@ void nhrp_nhs_foreach(struct interface *ifp, afi_t afi,
cb(nhs, 0, ctx);
}
}

int nhrp_nhs_match_ip(union sockunion *in_ip, struct nhrp_interface *nifp)
{
int i;
struct nhrp_nhs *nhs;
struct nhrp_registration *reg;

for (i = 0; i < AFI_MAX; i++) {
list_for_each_entry(nhs, &nifp->afi[i].nhslist_head,
nhslist_entry)
{
if (!list_empty(&nhs->reglist_head)) {
list_for_each_entry(reg, &nhs->reglist_head,
reglist_entry)
{
if (!sockunion_cmp(
in_ip,
&reg->peer->vc->remote
.nbma))
return 1;
}
}
}
}
return 0;
}
1 change: 1 addition & 0 deletions nhrpd/nhrp_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ int nhrp_ext_reply(struct zbuf *zb, struct nhrp_packet_header *hdr,
&ad->addr);
if (!cie)
goto err;
cie->mtu = htons(ad->mtu);
cie->holding_time = htons(ad->holdtime);
break;
default:
Expand Down
Loading

0 comments on commit 283981e

Please sign in to comment.