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;
}
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)
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];
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,
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)
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,
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);
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;
}
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);
}
}
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;
/* 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:
&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;
}
}
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)
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;
}
struct nhrp_cie_header *cie;
struct nhrp_extension_header *ext;
struct nhrp_cache *c;
- union sockunion cie_nbma, cie_nbma_nat, cie_proto, *proto_addr, *nbma_addr;
+ union sockunion cie_nbma, cie_nbma_nat, cie_proto, *proto_addr, *nbma_addr, *claimed_nbma_addr;
int holdtime, prefix_len, hostprefix_len;
struct nhrp_interface *nifp = ifp->info;
struct nhrp_peer *peer;
else
nbma_addr = &pp->src_nbma;
+ if(sockunion_family(&cie_nbma) != AF_UNSPEC)
+ claimed_nbma_addr = &cie_nbma;
+ else
+ claimed_nbma_addr = &pp->src_nbma;
+
holdtime = htons(cie->holding_time);
debugf(NHRP_DEBUG_COMMON,
"shortcut res_rep: holdtime is %u (if 0, using %u)",
nbma_addr ? buf : "(NULL)");
if (!nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC, holdtime,
nhrp_peer_get(pp->ifp, nbma_addr),
- htons(cie->mtu), nbma_addr)) {
+ htons(cie->mtu), nbma_addr, claimed_nbma_addr)) {
cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED;
continue;
}
if (!nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC, holdtime,
nhrp_peer_ref(p->peer),
- htons(cie->mtu), nbma_natoa)) {
+ htons(cie->mtu), nbma_natoa, nbma_addr)) {
cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED;
continue;
}
nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC,
holding_time,
nhrp_peer_get(pp->ifp, nbma),
- htons(cie->mtu), nbma);
+ htons(cie->mtu), nbma, &cie_nbma);
} else {
debugf(NHRP_DEBUG_COMMON,
"Shortcut: no cache for nbma %s", buf[2]);
nhrp_cache_update_binding(c_dst_proto, NHRP_CACHE_DYNAMIC,
holding_time,
nhrp_peer_get(pp->ifp, nbma),
- htons(cie->mtu), nbma);
+ htons(cie->mtu), nbma, &cie_nbma);
} else {
debugf(NHRP_DEBUG_COMMON,
"Shortcut: no cache for nbma %s", buf[2]);
c->map = 1;
if (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, &nbma_addr), 0,
- NULL);
+ NULL, NULL);
return CMD_SUCCESS;
}
return CMD_SUCCESS;
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 CMD_SUCCESS;
}
{
struct info_ctx *ctx = pctx;
struct vty *vty = ctx->vty;
- char buf[2][SU_ADDRSTRLEN];
+ char buf[3][SU_ADDRSTRLEN];
struct json_object *json = NULL;
if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
if (!ctx->count && !ctx->json) {
- vty_out(vty, "%-8s %-8s %-24s %-24s %-6s %s\n", "Iface", "Type",
- "Protocol", "NBMA", "Flags", "Identity");
+ vty_out(vty, "%-8s %-8s %-24s %-24s %-24s %-6s %s\n", "Iface", "Type",
+ "Protocol", "NBMA", "Claimed NBMA", "Flags", "Identity");
}
ctx->count++;
else
snprintf(buf[1], sizeof(buf[1]), "-");
+ if (c->cur.peer && sockunion_family(&c->cur.remote_nbma_claimed) != AF_UNSPEC)
+ sockunion2str(&c->cur.remote_nbma_claimed,
+ buf[2], sizeof(buf[2]));
+
+ else
+ snprintf(buf[2], sizeof(buf[2]), "-");
+
if (ctx->json) {
json = json_object_new_object();
json_object_string_add(json, "interface", c->ifp->name);
nhrp_cache_type_str[c->cur.type]);
json_object_string_add(json, "protocol", buf[0]);
json_object_string_add(json, "nbma", buf[1]);
+ json_object_string_add(json, "claimed_nbma", buf[2]);
if (c->used)
json_object_boolean_true_add(json, "used");
json_object_array_add(ctx->json, json);
return;
}
- vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s\n", c->ifp->name,
+ vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %-24s %c%c%c %s\n",
+ c->ifp->name,
nhrp_cache_type_str[c->cur.type],
- buf[0], buf[1],
+ buf[0], buf[1], buf[2],
c->used ? 'U' : ' ', c->t_timeout ? 'T' : ' ',
c->t_auth ? 'A' : ' ',
c->cur.peer ? c->cur.peer->vc->remote.id : "-");
{
struct info_ctx *ctx = data;
if (c->cur.type <= NHRP_CACHE_DYNAMIC) {
- 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);
ctx->count++;
}
}
struct {
enum nhrp_cache_type type;
union sockunion remote_nbma_natoa;
+ union sockunion remote_nbma_claimed;
struct nhrp_peer *peer;
time_t expires;
uint32_t mtu;
void nhrp_cache_set_used(struct nhrp_cache *, int);
int nhrp_cache_update_binding(struct nhrp_cache *, enum nhrp_cache_type type,
int holding_time, struct nhrp_peer *p,
- uint32_t mtu, union sockunion *nbma_natoa);
+ uint32_t mtu, union sockunion *nbma_natoa,
+ union sockunion *claimed_nbma);
void nhrp_cache_notify_add(struct nhrp_cache *c, struct notifier_block *,
notifier_fn_t);
void nhrp_cache_notify_del(struct nhrp_cache *c, struct notifier_block *);