diff --git a/ldpd/hello.c b/ldpd/hello.c index 95be1d5111..e7935899b7 100644 --- a/ldpd/hello.c +++ b/ldpd/hello.c @@ -265,9 +265,15 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, } if (!tnbr) { - if (!((flags & F_HELLO_REQ_TARG) && - ((ldp_af_conf_get(leconf, af))->flags & - F_LDPD_AF_THELLO_ACCEPT))) + struct ldpd_af_conf *af_conf; + + if (!(flags & F_HELLO_REQ_TARG)) + return; + af_conf = ldp_af_conf_get(leconf, af); + if (!(af_conf->flags & F_LDPD_AF_THELLO_ACCEPT)) + return; + if (ldpe_acl_check(af_conf->acl_thello_accept_from, af, + src, (af == AF_INET) ? 32 : 128) != FILTER_PERMIT) return; tnbr = tnbr_new(af, src); diff --git a/ldpd/lde.c b/ldpd/lde.c index a28862881d..ff80047207 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -577,11 +577,67 @@ lde_dispatch_parent(struct thread *thread) return (0); } +int +lde_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen) +{ + return ldp_acl_request(iev_main_sync, acl_name, af, addr, prefixlen); +} + uint32_t -lde_assign_label(void) +lde_assign_label(struct fec *fec, int connected) { static uint32_t label = MPLS_LABEL_RESERVED_MAX; + /* should we allocate a label for this fec? */ + switch (fec->type) { + case FEC_TYPE_IPV4: + if ((ldeconf->ipv4.flags & F_LDPD_AF_ALLOCHOSTONLY) && + fec->u.ipv4.prefixlen != 32) + return (NO_LABEL); + if (lde_acl_check(ldeconf->ipv4.acl_label_allocate_for, + AF_INET, (union ldpd_addr *)&fec->u.ipv4.prefix, + fec->u.ipv4.prefixlen) != FILTER_PERMIT) + return (NO_LABEL); + break; + case FEC_TYPE_IPV6: + if ((ldeconf->ipv6.flags & F_LDPD_AF_ALLOCHOSTONLY) && + fec->u.ipv6.prefixlen != 128) + return (NO_LABEL); + if (lde_acl_check(ldeconf->ipv6.acl_label_allocate_for, + AF_INET6, (union ldpd_addr *)&fec->u.ipv6.prefix, + fec->u.ipv6.prefixlen) != FILTER_PERMIT) + return (NO_LABEL); + break; + default: + fatalx("lde_assign_label: unexpected fec type"); + break; + } + + if (connected) { + /* choose implicit or explicit-null depending on configuration */ + switch (fec->type) { + case FEC_TYPE_IPV4: + if (!(ldeconf->ipv4.flags & F_LDPD_AF_EXPNULL)) + return (MPLS_LABEL_IMPLNULL); + if (lde_acl_check(ldeconf->ipv4.acl_label_expnull_for, + AF_INET, (union ldpd_addr *)&fec->u.ipv4.prefix, + fec->u.ipv4.prefixlen) != FILTER_PERMIT) + return (MPLS_LABEL_IMPLNULL); + return (MPLS_LABEL_IPV4NULL); + case FEC_TYPE_IPV6: + if (!(ldeconf->ipv6.flags & F_LDPD_AF_EXPNULL)) + return (MPLS_LABEL_IMPLNULL); + if (lde_acl_check(ldeconf->ipv6.acl_label_expnull_for, + AF_INET6, (union ldpd_addr *)&fec->u.ipv6.prefix, + fec->u.ipv6.prefixlen) != FILTER_PERMIT) + return (MPLS_LABEL_IMPLNULL); + return (MPLS_LABEL_IPV6NULL); + default: + fatalx("lde_assign_label: unexpected fec type"); + break; + } + } + /* * TODO: request label to zebra or define a range of labels for ldpd. */ @@ -801,10 +857,24 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single) case FEC_TYPE_IPV4: if (!ln->v4_enabled) return; + if (lde_acl_check(ldeconf->ipv4.acl_label_advertise_to, + AF_INET, (union ldpd_addr *)&ln->id, 32) != FILTER_PERMIT) + return; + if (lde_acl_check(ldeconf->ipv4.acl_label_advertise_for, + AF_INET, (union ldpd_addr *)&fn->fec.u.ipv4.prefix, + fn->fec.u.ipv4.prefixlen) != FILTER_PERMIT) + return; break; case FEC_TYPE_IPV6: if (!ln->v6_enabled) return; + if (lde_acl_check(ldeconf->ipv6.acl_label_advertise_to, + AF_INET, (union ldpd_addr *)&ln->id, 32) != FILTER_PERMIT) + return; + if (lde_acl_check(ldeconf->ipv6.acl_label_advertise_for, + AF_INET6, (union ldpd_addr *)&fn->fec.u.ipv6.prefix, + fn->fec.u.ipv6.prefixlen) != FILTER_PERMIT) + return; break; case FEC_TYPE_PWID: pw = (struct l2vpn_pw *) fn->data; @@ -1266,7 +1336,7 @@ lde_wdraw_del(struct lde_nbr *ln, struct lde_wdraw *lw) } void -lde_change_egress_label(int af, int was_implicit) +lde_change_egress_label(int af) { struct lde_nbr *ln; struct fec *f; @@ -1274,17 +1344,13 @@ lde_change_egress_label(int af, int was_implicit) /* explicitly withdraw all null labels */ RB_FOREACH(ln, nbr_tree, &lde_nbrs) { - if (was_implicit) - lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IMPLNULL, + lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IMPLNULL, NULL); + if (ln->v4_enabled) + lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IPV4NULL, + NULL); + if (ln->v6_enabled) + lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IPV6NULL, NULL); - else { - if (ln->v4_enabled) - lde_send_labelwithdraw(ln, NULL, - MPLS_LABEL_IPV4NULL, NULL); - if (ln->v6_enabled) - lde_send_labelwithdraw(ln, NULL, - MPLS_LABEL_IPV6NULL, NULL); - } } /* update label of connected routes */ @@ -1306,9 +1372,10 @@ lde_change_egress_label(int af, int was_implicit) fatalx("lde_change_egress_label: unknown af"); } - fn->local_label = egress_label(fn->fec.type); - RB_FOREACH(ln, nbr_tree, &lde_nbrs) - lde_send_labelmapping(ln, fn, 0); + fn->local_label = lde_assign_label(&fn->fec, 1); + if (fn->local_label != NO_LABEL) + RB_FOREACH(ln, nbr_tree, &lde_nbrs) + lde_send_labelmapping(ln, fn, 0); } RB_FOREACH(ln, nbr_tree, &lde_nbrs) lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, diff --git a/ldpd/lde.h b/ldpd/lde.h index fe90b2c852..7fa5219b12 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -133,7 +133,8 @@ extern struct thread *gc_timer; void lde(const char *, const char *); int lde_imsg_compose_parent(int, pid_t, void *, uint16_t); int lde_imsg_compose_ldpe(int, uint32_t, pid_t, void *, uint16_t); -uint32_t lde_assign_label(void); +int lde_acl_check(char *, int, union ldpd_addr *, uint8_t); +uint32_t lde_assign_label(struct fec *, int); void lde_send_change_klabel(struct fec_node *, struct fec_nh *); void lde_send_delete_klabel(struct fec_node *, struct fec_nh *); void lde_fec2map(struct fec *, struct map *); @@ -154,7 +155,7 @@ struct lde_req *lde_req_add(struct lde_nbr *, struct fec *, int); void lde_req_del(struct lde_nbr *, struct lde_req *, int); struct lde_wdraw *lde_wdraw_add(struct lde_nbr *, struct fec_node *); void lde_wdraw_del(struct lde_nbr *, struct lde_wdraw *); -void lde_change_egress_label(int, int); +void lde_change_egress_label(int); struct lde_addr *lde_address_find(struct lde_nbr *, int, union ldpd_addr *); @@ -169,7 +170,6 @@ void fec_snap(struct lde_nbr *); void fec_tree_clear(void); struct fec_nh *fec_nh_find(struct fec_node *, int, union ldpd_addr *, ifindex_t, uint8_t); -uint32_t egress_label(enum fec_type); void lde_kernel_insert(struct fec *, int, union ldpd_addr *, ifindex_t, uint8_t, int, void *); void lde_kernel_remove(struct fec *, int, union ldpd_addr *, diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index df65edad1a..7a4cb760f1 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -305,25 +305,6 @@ fec_nh_del(struct fec_nh *fnh) free(fnh); } -uint32_t -egress_label(enum fec_type fec_type) -{ - switch (fec_type) { - case FEC_TYPE_IPV4: - if (ldeconf->ipv4.flags & F_LDPD_AF_EXPNULL) - return (MPLS_LABEL_IPV4NULL); - break; - case FEC_TYPE_IPV6: - if (ldeconf->ipv6.flags & F_LDPD_AF_EXPNULL) - return (MPLS_LABEL_IPV6NULL); - break; - default: - fatalx("egress_label: unexpected fec type"); - } - - return (MPLS_LABEL_IMPLNULL); -} - void lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop, ifindex_t ifindex, uint8_t priority, int connected, void *data) @@ -347,14 +328,12 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop, fn->data = data; if (fn->local_label == NO_LABEL) { - if (connected) - fn->local_label = egress_label(fn->fec.type); - else - fn->local_label = lde_assign_label(); + fn->local_label = lde_assign_label(&fn->fec, connected); /* FEC.1: perform lsr label distribution procedure */ - RB_FOREACH(ln, nbr_tree, &lde_nbrs) - lde_send_labelmapping(ln, fn, 1); + if (fn->local_label != NO_LABEL) + RB_FOREACH(ln, nbr_tree, &lde_nbrs) + lde_send_labelmapping(ln, fn, 1); } fnh = fec_nh_add(fn, af, nexthop, ifindex, priority); @@ -446,6 +425,30 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln) int msgsource = 0; lde_map2fec(map, ln->id, &fec); + + switch (fec.type) { + case FEC_TYPE_IPV4: + if (lde_acl_check(ldeconf->ipv4.acl_label_accept_from, + AF_INET, (union ldpd_addr *)&ln->id, 32) != FILTER_PERMIT) + return; + if (lde_acl_check(ldeconf->ipv4.acl_label_accept_for, + AF_INET, (union ldpd_addr *)&fec.u.ipv4.prefix, + fec.u.ipv4.prefixlen) != FILTER_PERMIT) + return; + break; + case FEC_TYPE_IPV6: + if (lde_acl_check(ldeconf->ipv6.acl_label_accept_from, + AF_INET, (union ldpd_addr *)&ln->id, 32) != FILTER_PERMIT) + return; + if (lde_acl_check(ldeconf->ipv6.acl_label_accept_for, + AF_INET6, (union ldpd_addr *)&fec.u.ipv6.prefix, + fec.u.ipv6.prefixlen) != FILTER_PERMIT) + return; + break; + default: + break; + } + fn = (struct fec_node *)fec_find(&ft, &fec); if (fn == NULL) fn = fec_add(&fec); diff --git a/ldpd/ldp_vty.h b/ldpd/ldp_vty.h index 735554badf..b0dc291434 100644 --- a/ldpd/ldp_vty.h +++ b/ldpd/ldp_vty.h @@ -47,7 +47,10 @@ int ldp_vty_session_holdtime(struct vty *, struct vty_arg *[]); int ldp_vty_interface(struct vty *, struct vty_arg *[]); int ldp_vty_trans_addr(struct vty *, struct vty_arg *[]); int ldp_vty_neighbor_targeted(struct vty *, struct vty_arg *[]); -int ldp_vty_explicit_null(struct vty *, struct vty_arg *[]); +int ldp_vty_label_advertise(struct vty *, struct vty_arg *[]); +int ldp_vty_label_allocate(struct vty *, struct vty_arg *[]); +int ldp_vty_label_expnull(struct vty *, struct vty_arg *[]); +int ldp_vty_label_accept(struct vty *, struct vty_arg *[]); int ldp_vty_ttl_security(struct vty *, struct vty_arg *[]); int ldp_vty_router_id(struct vty *, struct vty_arg *[]); int ldp_vty_ds_cisco_interop(struct vty *, struct vty_arg *[]); diff --git a/ldpd/ldp_vty.xml b/ldpd/ldp_vty.xml index 794f063c4d..966b634c27 100644 --- a/ldpd/ldp_vty.xml +++ b/ldpd/ldp_vty.xml @@ -30,7 +30,48 @@ + + + + + + + + + + + + + + + +