Merge pull request #403 from donaldsharp/nhrpd2

Nhrpd2
This commit is contained in:
Russ White 2017-04-25 10:24:23 -04:00 committed by GitHub
commit e546c80068
6 changed files with 160 additions and 56 deletions

View File

@ -393,6 +393,8 @@ void nhrp_interface_set_protection(struct interface *ifp, const char *profile, c
if (nifp->ipsec_fallback_profile) free(nifp->ipsec_fallback_profile);
nifp->ipsec_fallback_profile = fallback_profile ? strdup(fallback_profile) : NULL;
notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_ADDRESS_CHANGED);
}
void nhrp_interface_set_source(struct interface *ifp, const char *ifname)

View File

@ -18,19 +18,6 @@ DEFINE_MTYPE_STATIC(NHRPD, NHRP_NHS, "NHRP next hop server")
DEFINE_MTYPE_STATIC(NHRPD, NHRP_REGISTRATION, "NHRP registration entries")
static int nhrp_nhs_resolve(struct thread *t);
struct nhrp_registration {
struct list_head reglist_entry;
struct thread *t_register;
struct nhrp_nhs *nhs;
struct nhrp_reqid reqid;
unsigned int timeout;
unsigned mark : 1;
union sockunion proto_addr;
struct nhrp_peer *peer;
struct notifier_block peer_notifier;
};
static int nhrp_reg_send_req(struct thread *t);
static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)
@ -370,3 +357,18 @@ void nhrp_nhs_terminate(void)
}
}
}
void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, void (*cb)(struct nhrp_nhs *, struct nhrp_registration *, void *), void *ctx)
{
struct nhrp_interface *nifp = ifp->info;
struct nhrp_nhs *nhs;
struct nhrp_registration *reg;
list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry) {
if (!list_empty(&nhs->reglist_head)) {
list_for_each_entry(reg, &nhs->reglist_head, reglist_entry)
cb(nhs, reg, ctx);
} else
cb(nhs, 0, ctx);
}
}

View File

@ -250,6 +250,8 @@ int nhrp_peer_check(struct nhrp_peer *p, int establish)
return 0;
if (p->requested)
return 0;
if (!nifp->ipsec_profile)
return 0;
if (sockunion_family(&vc->local.nbma) == AF_UNSPEC)
return 0;
@ -730,6 +732,15 @@ static void nhrp_packet_debug(struct zbuf *zb, const char *dir)
reply ? buf[0] : buf[1]);
}
static int proto2afi(uint16_t proto)
{
switch (proto) {
case ETH_P_IP: return AFI_IP;
case ETH_P_IPV6: return AFI_IP6;
}
return AF_UNSPEC;
}
struct nhrp_route_info {
int local;
struct interface *ifp;
@ -749,7 +760,7 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
const char *info = NULL;
union sockunion *target_addr;
unsigned paylen, extoff, extlen, realsize;
afi_t afi;
afi_t nbma_afi, proto_afi;
debugf(NHRP_DEBUG_KERNEL, "PACKET: Recv %s -> %s",
sockunion2str(&vc->remote.nbma, buf[0], sizeof buf[0]),
@ -777,20 +788,21 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
pp.hdr = hdr;
pp.peer = p;
afi = htons(hdr->afnum);
nbma_afi = htons(hdr->afnum);
proto_afi = proto2afi(htons(hdr->protocol_type));
if (hdr->type > ZEBRA_NUM_OF(packet_types) ||
hdr->version != NHRP_VERSION_RFC2332 ||
afi >= AFI_MAX ||
nbma_afi >= AFI_MAX || proto_afi == AF_UNSPEC ||
packet_types[hdr->type].type == PACKET_UNKNOWN ||
htons(hdr->packet_size) > realsize) {
zlog_info("From %s: error: packet type %d, version %d, AFI %d, size %d (real size %d)",
zlog_info("From %s: error: packet type %d, version %d, AFI %d, proto %x, size %d (real size %d)",
sockunion2str(&vc->remote.nbma, buf[0], sizeof buf[0]),
(int) hdr->type, (int) hdr->version, (int) afi,
(int) htons(hdr->packet_size),
(int) realsize);
(int) hdr->type, (int) hdr->version,
(int) nbma_afi, (int) htons(hdr->protocol_type),
(int) htons(hdr->packet_size), (int) realsize);
goto drop;
}
pp.if_ad = &((struct nhrp_interface *)ifp->info)->afi[afi];
pp.if_ad = &((struct nhrp_interface *)ifp->info)->afi[proto_afi];
extoff = htons(hdr->extension_offset);
if (extoff) {
@ -806,7 +818,7 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
extlen = zbuf_used(zb);
zbuf_init(&pp.extensions, zbuf_pulln(zb, extlen), extlen, extlen);
if (!nifp->afi[afi].network_id) {
if (!nifp->afi[proto_afi].network_id) {
info = "nhrp not enabled";
goto drop;
}

View File

@ -504,6 +504,32 @@ DEFUN(if_nhrp_map, if_nhrp_map_cmd,
return CMD_SUCCESS;
}
DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd,
"no " AFI_CMD " nhrp map <A.B.C.D|X:X::X:X>",
NO_STR
AFI_STR
NHRP_STR
"Nexthop Server configuration\n"
"IPv4 protocol address\n"
"IPv6 protocol address\n")
{
VTY_DECLVAR_CONTEXT(interface,ifp);
afi_t afi = cmd_to_afi(argv[1]);
union sockunion proto_addr;
struct nhrp_cache *c;
if (str2sockunion(argv[4]->arg, &proto_addr) < 0 ||
afi2family(afi) != sockunion_family(&proto_addr))
return nhrp_vty_return(vty, NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH);
c = nhrp_cache_get(ifp, &proto_addr, 0);
if (!c || !c->map)
return nhrp_vty_return(vty, NHRP_ERR_ENTRY_NOT_FOUND);
nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);
return CMD_SUCCESS;
}
DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>",
AFI_STR
@ -592,6 +618,56 @@ static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
VTY_NEWLINE);
}
static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg, void *pctx)
{
struct info_ctx *ctx = pctx;
struct vty *vty = ctx->vty;
char buf[2][SU_ADDRSTRLEN];
if (!ctx->count) {
vty_out(vty, "%-8s %-24s %-16s %-16s%s",
"Iface",
"FQDN",
"NBMA",
"Protocol",
VTY_NEWLINE);
}
ctx->count++;
vty_out(vty, "%-8s %-24s %-16s %-16s%s",
n->ifp->name,
n->nbma_fqdn,
(reg && reg->peer) ? sockunion2str(&reg->peer->vc->remote.nbma, buf[0], sizeof buf[0]) : "-",
sockunion2str(reg ? &reg->proto_addr : &n->proto_addr, buf[1], sizeof buf[1]),
VTY_NEWLINE);
}
static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
{
struct info_ctx *ctx = pctx;
struct nhrp_cache *c;
struct vty *vty = ctx->vty;
char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
if (!ctx->count) {
vty_out(vty, "%-8s %-24s %-24s %s%s",
"Type",
"Prefix",
"Via",
"Identity",
VTY_NEWLINE);
}
ctx->count++;
c = s->cache;
vty_out(ctx->vty, "%-8s %-24s %-24s %s%s",
nhrp_cache_type_str[s->type],
prefix2str(s->p, buf1, sizeof buf1),
c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "",
(c && c->cur.peer) ? c->cur.peer->vc->remote.id : "",
VTY_NEWLINE);
}
static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
{
struct info_ctx *ctx = pctx;
@ -631,38 +707,13 @@ static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
vty_out(ctx->vty, "%s", VTY_NEWLINE);
}
static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
{
struct info_ctx *ctx = pctx;
struct nhrp_cache *c;
struct vty *vty = ctx->vty;
char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
if (!ctx->count) {
vty_out(vty, "%-8s %-24s %-24s %s%s",
"Type",
"Prefix",
"Via",
"Identity",
VTY_NEWLINE);
}
ctx->count++;
c = s->cache;
vty_out(ctx->vty, "%-8s %-24s %-24s %s%s",
nhrp_cache_type_str[s->type],
prefix2str(s->p, buf1, sizeof buf1),
c ? sockunion2str(&c->remote_addr, buf2, sizeof buf2) : "",
(c && c->cur.peer) ? c->cur.peer->vc->remote.id : "",
VTY_NEWLINE);
}
DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
"show " AFI_CMD " nhrp [cache|shortcut|opennhrp]",
"show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp]",
SHOW_STR
AFI_STR
"NHRP information\n"
"Forwarding cache information\n"
"Next hop server information\n"
"Shortcut information\n"
"opennhrpctl style cache dump\n")
{
@ -676,13 +727,16 @@ DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
if (argc <= 3 || argv[3]->text[0] == 'c') {
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx);
} else if (argv[3]->text[0] == 'o') {
} else if (argv[3]->text[0] == 'n') {
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
nhrp_nhs_foreach(ifp, ctx.afi, show_ip_nhrp_nhs, &ctx);
} else if (argv[3]->text[0] == 's') {
nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
} else {
vty_out(vty, "Status: ok%s%s", VTY_NEWLINE, VTY_NEWLINE);
ctx.count++;
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp))
nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx);
} else {
nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
}
if (!ctx.count) {
@ -919,6 +973,7 @@ void nhrp_config_init(void)
install_element(INTERFACE_NODE, &if_nhrp_reg_flags_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd);
install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
}

View File

@ -254,6 +254,18 @@ struct nhrp_nhs {
struct list_head reglist_head;
};
struct nhrp_registration {
struct list_head reglist_entry;
struct thread *t_register;
struct nhrp_nhs *nhs;
struct nhrp_reqid reqid;
unsigned int timeout;
unsigned mark : 1;
union sockunion proto_addr;
struct nhrp_peer *peer;
struct notifier_block peer_notifier;
};
#define NHRP_IFF_SHORTCUT 0x0001
#define NHRP_IFF_REDIRECT 0x0002
#define NHRP_IFF_REG_NO_UNIQUE 0x0100
@ -311,6 +323,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn);
int nhrp_nhs_free(struct nhrp_nhs *nhs);
void nhrp_nhs_terminate(void);
void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, void (*cb)(struct nhrp_nhs *, struct nhrp_registration *, void *), void *ctx);
void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp);
void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix *p, struct interface *ifp, const union sockunion *nexthop, uint32_t mtu);

View File

@ -220,6 +220,23 @@ static void parse_sa_message(
}
}
static void parse_cmd_response(
struct vici_message_ctx *ctx,
enum vici_type_t msgtype,
const struct blob *key, const struct blob *val)
{
char buf[512];
switch (msgtype) {
case VICI_KEY_VALUE:
if (blob_equal(key, "errmsg") && blob2buf(val, buf, sizeof(buf)))
zlog_err("VICI: strongSwan: %s", buf);
break;
default:
break;
}
}
static void vici_recv_sa(struct vici_conn *vici, struct zbuf *msg, int event)
{
char buf[32];
@ -265,11 +282,14 @@ static void vici_recv_message(struct vici_conn *vici, struct zbuf *msg)
else if (blob_equal(&name, "child-state-destroying"))
vici_recv_sa(vici, msg, 2);
break;
case VICI_CMD_RESPONSE:
vici_parse_message(vici, msg, parse_cmd_response, 0);
break;
case VICI_EVENT_UNKNOWN:
case VICI_CMD_UNKNOWN:
zlog_err("VICI: StrongSwan does not support mandatory events (unpatched?)");
break;
case VICI_EVENT_CONFIRM:
case VICI_CMD_RESPONSE:
break;
default:
zlog_notice("VICI: Unrecognized message type %d", msgtype);
@ -449,9 +469,9 @@ void vici_request_vc(const char *profile, union sockunion *src, union sockunion
vici_submit_request(
vici, "initiate",
VICI_KEY_VALUE, "child", strlen(profile), profile,
VICI_KEY_VALUE, "timeout", 2, "-1",
VICI_KEY_VALUE, "async", 1, "1",
VICI_KEY_VALUE, "init-limits", 1, prio ? "0" : "1",
VICI_KEY_VALUE, "timeout", (size_t) 2, "-1",
VICI_KEY_VALUE, "async", (size_t) 1, "1",
VICI_KEY_VALUE, "init-limits", (size_t) 1, prio ? "0" : "1",
VICI_KEY_VALUE, "my-host", strlen(buf[0]), buf[0],
VICI_KEY_VALUE, "other-host", strlen(buf[1]), buf[1],
VICI_END);