diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index bbaa630cd5..58ad167549 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -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) diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c index 10245d308a..555c0d1de1 100644 --- a/nhrpd/nhrp_nhs.c +++ b/nhrpd/nhrp_nhs.c @@ -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); + } +} diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 4c1d97a489..3cc91a9083 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -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; } diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 2e3164410c..9b8463fb54 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -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 ", + 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 nbma ", 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(®->peer->vc->remote.nbma, buf[0], sizeof buf[0]) : "-", + sockunion2str(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); } diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index cd2b0d5580..9a4f26d577 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -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); diff --git a/nhrpd/vici.c b/nhrpd/vici.c index 507dd14a9c..5491bacf7c 100644 --- a/nhrpd/vici.c +++ b/nhrpd/vici.c @@ -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);