mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 11:30:30 +00:00
Merge pull request #151 from opensourcerouting/ldpd-filtering
ldpd: introduce advanced filtering capabilities
This commit is contained in:
commit
ec26d1b6ce
12
ldpd/hello.c
12
ldpd/hello.c
@ -265,9 +265,15 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!tnbr) {
|
if (!tnbr) {
|
||||||
if (!((flags & F_HELLO_REQ_TARG) &&
|
struct ldpd_af_conf *af_conf;
|
||||||
((ldp_af_conf_get(leconf, af))->flags &
|
|
||||||
F_LDPD_AF_THELLO_ACCEPT)))
|
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;
|
return;
|
||||||
|
|
||||||
tnbr = tnbr_new(af, src);
|
tnbr = tnbr_new(af, src);
|
||||||
|
152
ldpd/lde.c
152
ldpd/lde.c
@ -58,7 +58,7 @@ struct ldpd_conf *ldeconf;
|
|||||||
struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs);
|
struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs);
|
||||||
|
|
||||||
static struct imsgev *iev_ldpe;
|
static struct imsgev *iev_ldpe;
|
||||||
static struct imsgev *iev_main;
|
static struct imsgev *iev_main, *iev_main_sync;
|
||||||
|
|
||||||
/* Master of threads. */
|
/* Master of threads. */
|
||||||
struct thread_master *master;
|
struct thread_master *master;
|
||||||
@ -133,15 +133,18 @@ lde(const char *user, const char *group)
|
|||||||
/* setup signal handler */
|
/* setup signal handler */
|
||||||
signal_init(master, array_size(lde_signals), lde_signals);
|
signal_init(master, array_size(lde_signals), lde_signals);
|
||||||
|
|
||||||
/* setup pipe and event handler to the parent process */
|
/* setup pipes and event handlers to the parent process */
|
||||||
if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
|
if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL)
|
||||||
fatal(NULL);
|
fatal(NULL);
|
||||||
imsg_init(&iev_main->ibuf, 3);
|
imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC);
|
||||||
iev_main->handler_read = lde_dispatch_parent;
|
iev_main->handler_read = lde_dispatch_parent;
|
||||||
iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
|
iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
|
||||||
iev_main, iev_main->ibuf.fd);
|
iev_main, iev_main->ibuf.fd);
|
||||||
iev_main->handler_write = ldp_write_handler;
|
iev_main->handler_write = ldp_write_handler;
|
||||||
iev_main->ev_write = NULL;
|
|
||||||
|
if ((iev_main_sync = calloc(1, sizeof(struct imsgev))) == NULL)
|
||||||
|
fatal(NULL);
|
||||||
|
imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
|
||||||
|
|
||||||
/* start the LIB garbage collector */
|
/* start the LIB garbage collector */
|
||||||
lde_gc_start_timer();
|
lde_gc_start_timer();
|
||||||
@ -162,6 +165,8 @@ lde_shutdown(void)
|
|||||||
close(iev_ldpe->ibuf.fd);
|
close(iev_ldpe->ibuf.fd);
|
||||||
msgbuf_clear(&iev_main->ibuf.w);
|
msgbuf_clear(&iev_main->ibuf.w);
|
||||||
close(iev_main->ibuf.fd);
|
close(iev_main->ibuf.fd);
|
||||||
|
msgbuf_clear(&iev_main_sync->ibuf.w);
|
||||||
|
close(iev_main_sync->ibuf.fd);
|
||||||
|
|
||||||
lde_gc_stop_timer();
|
lde_gc_stop_timer();
|
||||||
lde_nbr_clear();
|
lde_nbr_clear();
|
||||||
@ -171,6 +176,7 @@ lde_shutdown(void)
|
|||||||
|
|
||||||
free(iev_ldpe);
|
free(iev_ldpe);
|
||||||
free(iev_main);
|
free(iev_main);
|
||||||
|
free(iev_main_sync);
|
||||||
|
|
||||||
log_info("label decision engine exiting");
|
log_info("label decision engine exiting");
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -571,11 +577,67 @@ lde_dispatch_parent(struct thread *thread)
|
|||||||
return (0);
|
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
|
uint32_t
|
||||||
lde_assign_label(void)
|
lde_assign_label(struct fec *fec, int connected)
|
||||||
{
|
{
|
||||||
static uint32_t label = MPLS_LABEL_RESERVED_MAX;
|
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.
|
* TODO: request label to zebra or define a range of labels for ldpd.
|
||||||
*/
|
*/
|
||||||
@ -795,10 +857,24 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single)
|
|||||||
case FEC_TYPE_IPV4:
|
case FEC_TYPE_IPV4:
|
||||||
if (!ln->v4_enabled)
|
if (!ln->v4_enabled)
|
||||||
return;
|
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;
|
break;
|
||||||
case FEC_TYPE_IPV6:
|
case FEC_TYPE_IPV6:
|
||||||
if (!ln->v6_enabled)
|
if (!ln->v6_enabled)
|
||||||
return;
|
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;
|
break;
|
||||||
case FEC_TYPE_PWID:
|
case FEC_TYPE_PWID:
|
||||||
pw = (struct l2vpn_pw *) fn->data;
|
pw = (struct l2vpn_pw *) fn->data;
|
||||||
@ -1260,52 +1336,50 @@ lde_wdraw_del(struct lde_nbr *ln, struct lde_wdraw *lw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lde_change_egress_label(int af, int was_implicit)
|
lde_change_egress_label(int af)
|
||||||
{
|
{
|
||||||
struct lde_nbr *ln;
|
struct lde_nbr *ln;
|
||||||
struct fec *f;
|
struct fec *f;
|
||||||
struct fec_node *fn;
|
struct fec_node *fn;
|
||||||
|
|
||||||
|
/* explicitly withdraw all null labels */
|
||||||
RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
|
RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
|
||||||
/* explicit withdraw */
|
lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IMPLNULL, NULL);
|
||||||
if (was_implicit)
|
if (ln->v4_enabled)
|
||||||
lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IMPLNULL,
|
lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IPV4NULL,
|
||||||
NULL);
|
NULL);
|
||||||
else {
|
if (ln->v6_enabled)
|
||||||
if (ln->v4_enabled)
|
lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IPV6NULL,
|
||||||
lde_send_labelwithdraw(ln, NULL,
|
NULL);
|
||||||
MPLS_LABEL_IPV4NULL, NULL);
|
}
|
||||||
if (ln->v6_enabled)
|
|
||||||
lde_send_labelwithdraw(ln, NULL,
|
|
||||||
MPLS_LABEL_IPV6NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* advertise new label of connected prefixes */
|
/* update label of connected routes */
|
||||||
RB_FOREACH(f, fec_tree, &ft) {
|
RB_FOREACH(f, fec_tree, &ft) {
|
||||||
fn = (struct fec_node *)f;
|
fn = (struct fec_node *)f;
|
||||||
if (fn->local_label > MPLS_LABEL_RESERVED_MAX)
|
if (fn->local_label > MPLS_LABEL_RESERVED_MAX)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (af) {
|
||||||
|
case AF_INET:
|
||||||
|
if (fn->fec.type != FEC_TYPE_IPV4)
|
||||||
continue;
|
continue;
|
||||||
|
break;
|
||||||
switch (af) {
|
case AF_INET6:
|
||||||
case AF_INET:
|
if (fn->fec.type != FEC_TYPE_IPV6)
|
||||||
if (fn->fec.type != FEC_TYPE_IPV4)
|
continue;
|
||||||
continue;
|
break;
|
||||||
break;
|
default:
|
||||||
case AF_INET6:
|
fatalx("lde_change_egress_label: unknown af");
|
||||||
if (fn->fec.type != FEC_TYPE_IPV6)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fatalx("lde_change_egress_label: unknown af");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn->local_label = egress_label(fn->fec.type);
|
|
||||||
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,
|
lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -133,7 +133,8 @@ extern struct thread *gc_timer;
|
|||||||
void lde(const char *, const char *);
|
void lde(const char *, const char *);
|
||||||
int lde_imsg_compose_parent(int, pid_t, void *, uint16_t);
|
int lde_imsg_compose_parent(int, pid_t, void *, uint16_t);
|
||||||
int lde_imsg_compose_ldpe(int, uint32_t, 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_change_klabel(struct fec_node *, struct fec_nh *);
|
||||||
void lde_send_delete_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 *);
|
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);
|
void lde_req_del(struct lde_nbr *, struct lde_req *, int);
|
||||||
struct lde_wdraw *lde_wdraw_add(struct lde_nbr *, struct fec_node *);
|
struct lde_wdraw *lde_wdraw_add(struct lde_nbr *, struct fec_node *);
|
||||||
void lde_wdraw_del(struct lde_nbr *, struct lde_wdraw *);
|
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,
|
struct lde_addr *lde_address_find(struct lde_nbr *, int,
|
||||||
union ldpd_addr *);
|
union ldpd_addr *);
|
||||||
|
|
||||||
@ -169,7 +170,6 @@ void fec_snap(struct lde_nbr *);
|
|||||||
void fec_tree_clear(void);
|
void fec_tree_clear(void);
|
||||||
struct fec_nh *fec_nh_find(struct fec_node *, int, union ldpd_addr *,
|
struct fec_nh *fec_nh_find(struct fec_node *, int, union ldpd_addr *,
|
||||||
ifindex_t, uint8_t);
|
ifindex_t, uint8_t);
|
||||||
uint32_t egress_label(enum fec_type);
|
|
||||||
void lde_kernel_insert(struct fec *, int, union ldpd_addr *,
|
void lde_kernel_insert(struct fec *, int, union ldpd_addr *,
|
||||||
ifindex_t, uint8_t, int, void *);
|
ifindex_t, uint8_t, int, void *);
|
||||||
void lde_kernel_remove(struct fec *, int, union ldpd_addr *,
|
void lde_kernel_remove(struct fec *, int, union ldpd_addr *,
|
||||||
|
@ -305,25 +305,6 @@ fec_nh_del(struct fec_nh *fnh)
|
|||||||
free(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
|
void
|
||||||
lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
|
lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
|
||||||
ifindex_t ifindex, uint8_t priority, int connected, void *data)
|
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;
|
fn->data = data;
|
||||||
|
|
||||||
if (fn->local_label == NO_LABEL) {
|
if (fn->local_label == NO_LABEL) {
|
||||||
if (connected)
|
fn->local_label = lde_assign_label(&fn->fec, connected);
|
||||||
fn->local_label = egress_label(fn->fec.type);
|
|
||||||
else
|
|
||||||
fn->local_label = lde_assign_label();
|
|
||||||
|
|
||||||
/* FEC.1: perform lsr label distribution procedure */
|
/* FEC.1: perform lsr label distribution procedure */
|
||||||
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
|
if (fn->local_label != NO_LABEL)
|
||||||
lde_send_labelmapping(ln, fn, 1);
|
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
|
||||||
|
lde_send_labelmapping(ln, fn, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fnh = fec_nh_add(fn, af, nexthop, ifindex, priority);
|
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;
|
int msgsource = 0;
|
||||||
|
|
||||||
lde_map2fec(map, ln->id, &fec);
|
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);
|
fn = (struct fec_node *)fec_find(&ft, &fec);
|
||||||
if (fn == NULL)
|
if (fn == NULL)
|
||||||
fn = fec_add(&fec);
|
fn = fec_add(&fec);
|
||||||
|
@ -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_interface(struct vty *, struct vty_arg *[]);
|
||||||
int ldp_vty_trans_addr(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_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_ttl_security(struct vty *, struct vty_arg *[]);
|
||||||
int ldp_vty_router_id(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 *[]);
|
int ldp_vty_ds_cisco_interop(struct vty *, struct vty_arg *[]);
|
||||||
|
@ -30,7 +30,48 @@
|
|||||||
<option name="sent" help="Sent messages"/>
|
<option name="sent" help="Sent messages"/>
|
||||||
</options>
|
</options>
|
||||||
|
|
||||||
|
<!-- ACL -->
|
||||||
|
<options name="acl">
|
||||||
|
<option input="acl_range" help="IP access-list number"/>
|
||||||
|
<option input="acl_expanded_range" help="IP access-list number (expanded range)"/>
|
||||||
|
<option input="word" help="IP access-list name"/>
|
||||||
|
</options>
|
||||||
|
|
||||||
<!-- shared subtrees -->
|
<!-- shared subtrees -->
|
||||||
|
<subtree name="label_local_acls">
|
||||||
|
<option name="to" help="IP Access-list specifying controls on LDP Peers">
|
||||||
|
<select options="acl" arg="to_acl" function="inherited">
|
||||||
|
<option name="for" help="IP access-list for destination prefixes">
|
||||||
|
<select options="acl" arg="for_acl" function="inherited"/>
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</option>
|
||||||
|
<option name="for" help="IP access-list for destination prefixes">
|
||||||
|
<select options="acl" arg="for_acl" function="inherited">
|
||||||
|
<option name="to" help="IP Access-list specifying controls on LDP Peers">
|
||||||
|
<select options="acl" arg="to_acl" function="inherited"/>
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</option>
|
||||||
|
</subtree>
|
||||||
|
|
||||||
|
<subtree name="label_remote_acls">
|
||||||
|
<option name="from" help="Neighbor from whom to accept label advertisement">
|
||||||
|
<select options="acl" arg="from_acl" function="inherited">
|
||||||
|
<option name="for" help="IP access-list for destination prefixes">
|
||||||
|
<select options="acl" arg="for_acl" function="inherited"/>
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</option>
|
||||||
|
<option name="for" help="IP access-list for destination prefixes">
|
||||||
|
<select options="acl" arg="for_acl" function="inherited">
|
||||||
|
<option name="from" help="Neighbor from whom to accept label advertisement">
|
||||||
|
<select options="acl" arg="from_acl" function="inherited"/>
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</option>
|
||||||
|
</subtree>
|
||||||
|
|
||||||
<subtree name="discovery_link">
|
<subtree name="discovery_link">
|
||||||
<option name="discovery" help="Configure discovery parameters">
|
<option name="discovery" help="Configure discovery parameters">
|
||||||
<option name="hello" arg="hello_type" help="LDP Link Hellos">
|
<option name="hello" arg="hello_type" help="LDP Link Hellos">
|
||||||
@ -70,13 +111,33 @@
|
|||||||
<include subtree="discovery_targeted"/>
|
<include subtree="discovery_targeted"/>
|
||||||
<option name="discovery" help="Configure discovery parameters">
|
<option name="discovery" help="Configure discovery parameters">
|
||||||
<option name="targeted-hello" arg="hello_type" help="LDP Targeted Hellos">
|
<option name="targeted-hello" arg="hello_type" help="LDP Targeted Hellos">
|
||||||
<option name="accept" help="Accept and respond to targeted hellos" function="ldp_vty_targeted_hello_accept"/>
|
<option name="accept" help="Accept and respond to targeted hellos" function="ldp_vty_targeted_hello_accept">
|
||||||
|
<option name="from" help="Access list to specify acceptable targeted hello source">
|
||||||
|
<select options="acl" arg="from_acl" function="inherited"/>
|
||||||
|
</option>
|
||||||
|
</option>
|
||||||
</option>
|
</option>
|
||||||
</option>
|
</option>
|
||||||
<option name="label" help="Configure label control and policies">
|
<option name="label" help="Configure label control and policies">
|
||||||
<option name="local" help="Configure local label control and policies">
|
<option name="local" help="Configure local label control and policies">
|
||||||
<option name="advertise" help="Configure outbound label advertisement control">
|
<option name="advertise" help="Configure outbound label advertisement control" function="ldp_vty_label_advertise">
|
||||||
<option name="explicit-null" help="Configure explicit-null advertisement" function="ldp_vty_explicit_null"/>
|
<include subtree="label_local_acls"/>
|
||||||
|
<option name="explicit-null" help="Configure explicit-null advertisement" function="ldp_vty_label_expnull">
|
||||||
|
<option name="for" help="IP access-list for destination prefixes">
|
||||||
|
<select options="acl" arg="for_acl" function="inherited"/>
|
||||||
|
</option>
|
||||||
|
</option>
|
||||||
|
</option>
|
||||||
|
<option name="allocate" help="Configure label allocation control">
|
||||||
|
<option name="for" help="IP access-list">
|
||||||
|
<select options="acl" arg="for_acl" function="ldp_vty_label_allocate"/>
|
||||||
|
</option>
|
||||||
|
<option name="host-routes" arg="host-routes" help="allocate local label for host routes only" function="ldp_vty_label_allocate"/>
|
||||||
|
</option>
|
||||||
|
</option>
|
||||||
|
<option name="remote" help="Configure remote/peer label control and policies">
|
||||||
|
<option name="accept" help="Configure inbound label acceptance control" function="ldp_vty_label_accept">
|
||||||
|
<include subtree="label_remote_acls"/>
|
||||||
</option>
|
</option>
|
||||||
</option>
|
</option>
|
||||||
</option>
|
</option>
|
||||||
|
@ -182,9 +182,13 @@ ldp_af_config_write(struct vty *vty, int af, struct ldpd_conf *conf,
|
|||||||
vty_out(vty, " discovery hello interval %u%s",
|
vty_out(vty, " discovery hello interval %u%s",
|
||||||
af_conf->lhello_interval, VTY_NEWLINE);
|
af_conf->lhello_interval, VTY_NEWLINE);
|
||||||
|
|
||||||
if (af_conf->flags & F_LDPD_AF_THELLO_ACCEPT)
|
if (af_conf->flags & F_LDPD_AF_THELLO_ACCEPT) {
|
||||||
vty_out(vty, " discovery targeted-hello accept%s",
|
vty_out(vty, " discovery targeted-hello accept");
|
||||||
VTY_NEWLINE);
|
if (af_conf->acl_thello_accept_from[0] != '\0')
|
||||||
|
vty_out(vty, " from %s",
|
||||||
|
af_conf->acl_thello_accept_from);
|
||||||
|
vty_out(vty, "%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
if (af_conf->thello_holdtime != TARGETED_DFLT_HOLDTIME &&
|
if (af_conf->thello_holdtime != TARGETED_DFLT_HOLDTIME &&
|
||||||
af_conf->thello_holdtime != 0)
|
af_conf->thello_holdtime != 0)
|
||||||
@ -202,9 +206,48 @@ ldp_af_config_write(struct vty *vty, int af, struct ldpd_conf *conf,
|
|||||||
vty_out(vty, " ! Incomplete config, specify a discovery "
|
vty_out(vty, " ! Incomplete config, specify a discovery "
|
||||||
"transport-address%s", VTY_NEWLINE);
|
"transport-address%s", VTY_NEWLINE);
|
||||||
|
|
||||||
if (af_conf->flags & F_LDPD_AF_EXPNULL)
|
if ((af_conf->flags & F_LDPD_AF_ALLOCHOSTONLY) ||
|
||||||
vty_out(vty, " label local advertise explicit-null%s",
|
af_conf->acl_label_allocate_for[0] != '\0') {
|
||||||
VTY_NEWLINE);
|
vty_out(vty, " label local allocate");
|
||||||
|
if (af_conf->flags & F_LDPD_AF_ALLOCHOSTONLY)
|
||||||
|
vty_out(vty, " host-routes");
|
||||||
|
else
|
||||||
|
vty_out(vty, " for %s",
|
||||||
|
af_conf->acl_label_allocate_for);
|
||||||
|
vty_out(vty, "%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (af_conf->acl_label_advertise_for[0] != '\0' ||
|
||||||
|
af_conf->acl_label_advertise_to[0] != '\0') {
|
||||||
|
vty_out(vty, " label local advertise");
|
||||||
|
if (af_conf->acl_label_advertise_to[0] != '\0')
|
||||||
|
vty_out(vty, " to %s",
|
||||||
|
af_conf->acl_label_advertise_to);
|
||||||
|
if (af_conf->acl_label_advertise_for[0] != '\0')
|
||||||
|
vty_out(vty, " for %s",
|
||||||
|
af_conf->acl_label_advertise_for);
|
||||||
|
vty_out(vty, "%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (af_conf->flags & F_LDPD_AF_EXPNULL) {
|
||||||
|
vty_out(vty, " label local advertise explicit-null");
|
||||||
|
if (af_conf->acl_label_expnull_for[0] != '\0')
|
||||||
|
vty_out(vty, " for %s",
|
||||||
|
af_conf->acl_label_expnull_for);
|
||||||
|
vty_out(vty, "%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (af_conf->acl_label_accept_for[0] != '\0' ||
|
||||||
|
af_conf->acl_label_accept_from[0] != '\0') {
|
||||||
|
vty_out(vty, " label remote accept");
|
||||||
|
if (af_conf->acl_label_accept_from[0] != '\0')
|
||||||
|
vty_out(vty, " from %s",
|
||||||
|
af_conf->acl_label_accept_from);
|
||||||
|
if (af_conf->acl_label_accept_for[0] != '\0')
|
||||||
|
vty_out(vty, " for %s",
|
||||||
|
af_conf->acl_label_accept_for);
|
||||||
|
vty_out(vty, "%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
if (af_conf->flags & F_LDPD_AF_NO_GTSM)
|
if (af_conf->flags & F_LDPD_AF_NO_GTSM)
|
||||||
vty_out(vty, " ttl-security disable%s", VTY_NEWLINE);
|
vty_out(vty, " ttl-security disable%s", VTY_NEWLINE);
|
||||||
@ -681,19 +724,28 @@ ldp_vty_targeted_hello_accept(struct vty *vty, struct vty_arg *args[])
|
|||||||
struct ldpd_conf *vty_conf;
|
struct ldpd_conf *vty_conf;
|
||||||
struct ldpd_af_conf *af_conf;
|
struct ldpd_af_conf *af_conf;
|
||||||
int af;
|
int af;
|
||||||
|
const char *acl_from_str;
|
||||||
int disable;
|
int disable;
|
||||||
|
|
||||||
vty_conf = ldp_dup_config(ldpd_conf);
|
vty_conf = ldp_dup_config(ldpd_conf);
|
||||||
|
|
||||||
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
|
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
|
||||||
|
acl_from_str = vty_get_arg_value(args, "from_acl");
|
||||||
|
|
||||||
af = ldp_vty_get_af(vty);
|
af = ldp_vty_get_af(vty);
|
||||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||||
|
|
||||||
if (disable)
|
if (disable) {
|
||||||
af_conf->flags &= ~F_LDPD_AF_THELLO_ACCEPT;
|
af_conf->flags &= ~F_LDPD_AF_THELLO_ACCEPT;
|
||||||
else
|
af_conf->acl_thello_accept_from[0] = '\0';
|
||||||
|
} else {
|
||||||
af_conf->flags |= F_LDPD_AF_THELLO_ACCEPT;
|
af_conf->flags |= F_LDPD_AF_THELLO_ACCEPT;
|
||||||
|
if (acl_from_str)
|
||||||
|
strlcpy(af_conf->acl_thello_accept_from, acl_from_str,
|
||||||
|
sizeof(af_conf->acl_thello_accept_from));
|
||||||
|
else
|
||||||
|
af_conf->acl_thello_accept_from[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
ldp_reload(vty_conf);
|
ldp_reload(vty_conf);
|
||||||
|
|
||||||
@ -978,23 +1030,143 @@ cancel:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ldp_vty_explicit_null(struct vty *vty, struct vty_arg *args[])
|
ldp_vty_label_advertise(struct vty *vty, struct vty_arg *args[])
|
||||||
{
|
{
|
||||||
struct ldpd_conf *vty_conf;
|
struct ldpd_conf *vty_conf;
|
||||||
struct ldpd_af_conf *af_conf;
|
struct ldpd_af_conf *af_conf;
|
||||||
int af;
|
int af;
|
||||||
|
const char *acl_to_str;
|
||||||
|
const char *acl_for_str;
|
||||||
int disable;
|
int disable;
|
||||||
|
|
||||||
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
|
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
|
||||||
|
acl_to_str = vty_get_arg_value(args, "to_acl");
|
||||||
|
acl_for_str = vty_get_arg_value(args, "for_acl");
|
||||||
|
|
||||||
vty_conf = ldp_dup_config(ldpd_conf);
|
vty_conf = ldp_dup_config(ldpd_conf);
|
||||||
af = ldp_vty_get_af(vty);
|
af = ldp_vty_get_af(vty);
|
||||||
af_conf = ldp_af_conf_get(vty_conf, af);
|
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||||
|
|
||||||
if (disable)
|
if (disable) {
|
||||||
|
af_conf->acl_label_advertise_to[0] = '\0';
|
||||||
|
af_conf->acl_label_advertise_for[0] = '\0';
|
||||||
|
} else {
|
||||||
|
if (acl_to_str)
|
||||||
|
strlcpy(af_conf->acl_label_advertise_to, acl_to_str,
|
||||||
|
sizeof(af_conf->acl_label_advertise_to));
|
||||||
|
else
|
||||||
|
af_conf->acl_label_advertise_to[0] = '\0';
|
||||||
|
if (acl_for_str)
|
||||||
|
strlcpy(af_conf->acl_label_advertise_for, acl_for_str,
|
||||||
|
sizeof(af_conf->acl_label_advertise_for));
|
||||||
|
else
|
||||||
|
af_conf->acl_label_advertise_for[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
ldp_reload(vty_conf);
|
||||||
|
|
||||||
|
return (CMD_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldp_vty_label_allocate(struct vty *vty, struct vty_arg *args[])
|
||||||
|
{
|
||||||
|
struct ldpd_conf *vty_conf;
|
||||||
|
struct ldpd_af_conf *af_conf;
|
||||||
|
int af;
|
||||||
|
const char *acl_for_str;
|
||||||
|
const char *host_routes_str;
|
||||||
|
int disable;
|
||||||
|
|
||||||
|
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
|
||||||
|
acl_for_str = vty_get_arg_value(args, "for_acl");
|
||||||
|
host_routes_str = vty_get_arg_value(args, "host-routes");
|
||||||
|
|
||||||
|
vty_conf = ldp_dup_config(ldpd_conf);
|
||||||
|
af = ldp_vty_get_af(vty);
|
||||||
|
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||||
|
|
||||||
|
af_conf->flags &= ~F_LDPD_AF_ALLOCHOSTONLY;
|
||||||
|
af_conf->acl_label_allocate_for[0] = '\0';
|
||||||
|
if (!disable) {
|
||||||
|
if (host_routes_str)
|
||||||
|
af_conf->flags |= F_LDPD_AF_ALLOCHOSTONLY;
|
||||||
|
else
|
||||||
|
strlcpy(af_conf->acl_label_allocate_for, acl_for_str,
|
||||||
|
sizeof(af_conf->acl_label_allocate_for));
|
||||||
|
}
|
||||||
|
|
||||||
|
ldp_reload(vty_conf);
|
||||||
|
|
||||||
|
return (CMD_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldp_vty_label_expnull(struct vty *vty, struct vty_arg *args[])
|
||||||
|
{
|
||||||
|
struct ldpd_conf *vty_conf;
|
||||||
|
struct ldpd_af_conf *af_conf;
|
||||||
|
int af;
|
||||||
|
const char *acl_for_str;
|
||||||
|
int disable;
|
||||||
|
|
||||||
|
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
|
||||||
|
acl_for_str = vty_get_arg_value(args, "for_acl");
|
||||||
|
|
||||||
|
vty_conf = ldp_dup_config(ldpd_conf);
|
||||||
|
af = ldp_vty_get_af(vty);
|
||||||
|
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||||
|
|
||||||
|
if (disable) {
|
||||||
af_conf->flags &= ~F_LDPD_AF_EXPNULL;
|
af_conf->flags &= ~F_LDPD_AF_EXPNULL;
|
||||||
else
|
af_conf->acl_label_expnull_for[0] = '\0';
|
||||||
|
} else {
|
||||||
af_conf->flags |= F_LDPD_AF_EXPNULL;
|
af_conf->flags |= F_LDPD_AF_EXPNULL;
|
||||||
|
if (acl_for_str)
|
||||||
|
strlcpy(af_conf->acl_label_expnull_for, acl_for_str,
|
||||||
|
sizeof(af_conf->acl_label_expnull_for));
|
||||||
|
else
|
||||||
|
af_conf->acl_label_expnull_for[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
ldp_reload(vty_conf);
|
||||||
|
|
||||||
|
return (CMD_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldp_vty_label_accept(struct vty *vty, struct vty_arg *args[])
|
||||||
|
{
|
||||||
|
struct ldpd_conf *vty_conf;
|
||||||
|
struct ldpd_af_conf *af_conf;
|
||||||
|
int af;
|
||||||
|
const char *acl_from_str;
|
||||||
|
const char *acl_for_str;
|
||||||
|
int disable;
|
||||||
|
|
||||||
|
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
|
||||||
|
acl_from_str = vty_get_arg_value(args, "from_acl");
|
||||||
|
acl_for_str = vty_get_arg_value(args, "for_acl");
|
||||||
|
|
||||||
|
vty_conf = ldp_dup_config(ldpd_conf);
|
||||||
|
af = ldp_vty_get_af(vty);
|
||||||
|
af_conf = ldp_af_conf_get(vty_conf, af);
|
||||||
|
|
||||||
|
if (disable) {
|
||||||
|
af_conf->acl_label_accept_from[0] = '\0';
|
||||||
|
af_conf->acl_label_accept_for[0] = '\0';
|
||||||
|
} else {
|
||||||
|
if (acl_from_str)
|
||||||
|
strlcpy(af_conf->acl_label_accept_from, acl_from_str,
|
||||||
|
sizeof(af_conf->acl_label_accept_from));
|
||||||
|
else
|
||||||
|
af_conf->acl_label_accept_from[0] = '\0';
|
||||||
|
if (acl_for_str)
|
||||||
|
strlcpy(af_conf->acl_label_accept_for, acl_for_str,
|
||||||
|
sizeof(af_conf->acl_label_accept_for));
|
||||||
|
else
|
||||||
|
af_conf->acl_label_accept_for[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
ldp_reload(vty_conf);
|
ldp_reload(vty_conf);
|
||||||
|
|
||||||
|
@ -497,3 +497,11 @@ ldp_zebra_init(struct thread_master *master)
|
|||||||
zclient->redistribute_route_ipv6_add = ldp_zebra_read_route;
|
zclient->redistribute_route_ipv6_add = ldp_zebra_read_route;
|
||||||
zclient->redistribute_route_ipv6_del = ldp_zebra_read_route;
|
zclient->redistribute_route_ipv6_del = ldp_zebra_read_route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldp_zebra_destroy(void)
|
||||||
|
{
|
||||||
|
zclient_stop(zclient);
|
||||||
|
zclient_free(zclient);
|
||||||
|
zclient = NULL;
|
||||||
|
}
|
||||||
|
250
ldpd/ldpd.c
250
ldpd/ldpd.c
@ -39,10 +39,11 @@
|
|||||||
#include "sigevent.h"
|
#include "sigevent.h"
|
||||||
#include "zclient.h"
|
#include "zclient.h"
|
||||||
#include "vrf.h"
|
#include "vrf.h"
|
||||||
|
#include "filter.h"
|
||||||
#include "qobj.h"
|
#include "qobj.h"
|
||||||
|
|
||||||
static void ldpd_shutdown(void);
|
static void ldpd_shutdown(void);
|
||||||
static pid_t start_child(enum ldpd_process, char *, int,
|
static pid_t start_child(enum ldpd_process, char *, int, int,
|
||||||
const char *, const char *);
|
const char *, const char *);
|
||||||
static int main_dispatch_ldpe(struct thread *);
|
static int main_dispatch_ldpe(struct thread *);
|
||||||
static int main_dispatch_lde(struct thread *);
|
static int main_dispatch_lde(struct thread *);
|
||||||
@ -77,8 +78,8 @@ DEFINE_QOBJ_TYPE(ldpd_conf)
|
|||||||
struct ldpd_global global;
|
struct ldpd_global global;
|
||||||
struct ldpd_conf *ldpd_conf;
|
struct ldpd_conf *ldpd_conf;
|
||||||
|
|
||||||
static struct imsgev *iev_ldpe;
|
static struct imsgev *iev_ldpe, *iev_ldpe_sync;
|
||||||
static struct imsgev *iev_lde;
|
static struct imsgev *iev_lde, *iev_lde_sync;
|
||||||
static pid_t ldpe_pid;
|
static pid_t ldpe_pid;
|
||||||
static pid_t lde_pid;
|
static pid_t lde_pid;
|
||||||
|
|
||||||
@ -207,8 +208,8 @@ main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
char *saved_argv0;
|
char *saved_argv0;
|
||||||
int lflag = 0, eflag = 0;
|
int lflag = 0, eflag = 0;
|
||||||
int pipe_parent2ldpe[2];
|
int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2];
|
||||||
int pipe_parent2lde[2];
|
int pipe_parent2lde[2], pipe_parent2lde_sync[2];
|
||||||
char *p;
|
char *p;
|
||||||
char *vty_addr = NULL;
|
char *vty_addr = NULL;
|
||||||
int vty_port = LDP_VTY_PORT;
|
int vty_port = LDP_VTY_PORT;
|
||||||
@ -326,6 +327,7 @@ main(int argc, char *argv[])
|
|||||||
vty_config_lockless ();
|
vty_config_lockless ();
|
||||||
vty_init(master);
|
vty_init(master);
|
||||||
vrf_init();
|
vrf_init();
|
||||||
|
access_list_init ();
|
||||||
ldp_vty_init();
|
ldp_vty_init();
|
||||||
ldp_vty_if_init();
|
ldp_vty_if_init();
|
||||||
|
|
||||||
@ -347,22 +349,34 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1)
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1)
|
||||||
fatal("socketpair");
|
fatal("socketpair");
|
||||||
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
|
||||||
|
pipe_parent2ldpe_sync) == -1)
|
||||||
|
fatal("socketpair");
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2lde) == -1)
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2lde) == -1)
|
||||||
fatal("socketpair");
|
fatal("socketpair");
|
||||||
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
|
||||||
|
pipe_parent2lde_sync) == -1)
|
||||||
|
fatal("socketpair");
|
||||||
sock_set_nonblock(pipe_parent2ldpe[0]);
|
sock_set_nonblock(pipe_parent2ldpe[0]);
|
||||||
sock_set_cloexec(pipe_parent2ldpe[0]);
|
sock_set_cloexec(pipe_parent2ldpe[0]);
|
||||||
sock_set_nonblock(pipe_parent2ldpe[1]);
|
sock_set_nonblock(pipe_parent2ldpe[1]);
|
||||||
sock_set_cloexec(pipe_parent2ldpe[1]);
|
sock_set_cloexec(pipe_parent2ldpe[1]);
|
||||||
|
sock_set_nonblock(pipe_parent2ldpe_sync[0]);
|
||||||
|
sock_set_cloexec(pipe_parent2ldpe_sync[0]);
|
||||||
|
sock_set_cloexec(pipe_parent2ldpe_sync[1]);
|
||||||
sock_set_nonblock(pipe_parent2lde[0]);
|
sock_set_nonblock(pipe_parent2lde[0]);
|
||||||
sock_set_cloexec(pipe_parent2lde[0]);
|
sock_set_cloexec(pipe_parent2lde[0]);
|
||||||
sock_set_nonblock(pipe_parent2lde[1]);
|
sock_set_nonblock(pipe_parent2lde[1]);
|
||||||
sock_set_cloexec(pipe_parent2lde[1]);
|
sock_set_cloexec(pipe_parent2lde[1]);
|
||||||
|
sock_set_nonblock(pipe_parent2lde_sync[0]);
|
||||||
|
sock_set_cloexec(pipe_parent2lde_sync[0]);
|
||||||
|
sock_set_cloexec(pipe_parent2lde_sync[1]);
|
||||||
|
|
||||||
/* start children */
|
/* start children */
|
||||||
lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0,
|
lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0,
|
||||||
pipe_parent2lde[1], user, group);
|
pipe_parent2lde[1], pipe_parent2lde_sync[1], user, group);
|
||||||
ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0,
|
ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0,
|
||||||
pipe_parent2ldpe[1], user, group);
|
pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1], user, group);
|
||||||
|
|
||||||
/* drop privileges */
|
/* drop privileges */
|
||||||
if (user)
|
if (user)
|
||||||
@ -378,22 +392,34 @@ main(int argc, char *argv[])
|
|||||||
ldp_zebra_init(master);
|
ldp_zebra_init(master);
|
||||||
|
|
||||||
/* setup pipes to children */
|
/* setup pipes to children */
|
||||||
if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL ||
|
if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL ||
|
||||||
(iev_lde = malloc(sizeof(struct imsgev))) == NULL)
|
(iev_ldpe_sync = calloc(1, sizeof(struct imsgev))) == NULL ||
|
||||||
|
(iev_lde = calloc(1, sizeof(struct imsgev))) == NULL ||
|
||||||
|
(iev_lde_sync = calloc(1, sizeof(struct imsgev))) == NULL)
|
||||||
fatal(NULL);
|
fatal(NULL);
|
||||||
imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]);
|
imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]);
|
||||||
iev_ldpe->handler_read = main_dispatch_ldpe;
|
iev_ldpe->handler_read = main_dispatch_ldpe;
|
||||||
iev_ldpe->ev_read = thread_add_read(master, iev_ldpe->handler_read,
|
iev_ldpe->ev_read = thread_add_read(master, iev_ldpe->handler_read,
|
||||||
iev_ldpe, iev_ldpe->ibuf.fd);
|
iev_ldpe, iev_ldpe->ibuf.fd);
|
||||||
iev_ldpe->handler_write = ldp_write_handler;
|
iev_ldpe->handler_write = ldp_write_handler;
|
||||||
iev_ldpe->ev_write = NULL;
|
|
||||||
|
imsg_init(&iev_ldpe_sync->ibuf, pipe_parent2ldpe_sync[0]);
|
||||||
|
iev_ldpe_sync->handler_read = main_dispatch_ldpe;
|
||||||
|
iev_ldpe_sync->ev_read = thread_add_read(master,
|
||||||
|
iev_ldpe_sync->handler_read, iev_ldpe_sync, iev_ldpe_sync->ibuf.fd);
|
||||||
|
iev_ldpe_sync->handler_write = ldp_write_handler;
|
||||||
|
|
||||||
imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]);
|
imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]);
|
||||||
iev_lde->handler_read = main_dispatch_lde;
|
iev_lde->handler_read = main_dispatch_lde;
|
||||||
iev_lde->ev_read = thread_add_read(master, iev_lde->handler_read,
|
iev_lde->ev_read = thread_add_read(master, iev_lde->handler_read,
|
||||||
iev_lde, iev_lde->ibuf.fd);
|
iev_lde, iev_lde->ibuf.fd);
|
||||||
iev_lde->handler_write = ldp_write_handler;
|
iev_lde->handler_write = ldp_write_handler;
|
||||||
iev_lde->ev_write = NULL;
|
|
||||||
|
imsg_init(&iev_lde_sync->ibuf, pipe_parent2lde_sync[0]);
|
||||||
|
iev_lde_sync->handler_read = main_dispatch_lde;
|
||||||
|
iev_lde_sync->ev_read = thread_add_read(master,
|
||||||
|
iev_lde_sync->handler_read, iev_lde_sync, iev_lde_sync->ibuf.fd);
|
||||||
|
iev_lde_sync->handler_write = ldp_write_handler;
|
||||||
|
|
||||||
if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf))
|
if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf))
|
||||||
fatal("could not establish imsg links");
|
fatal("could not establish imsg links");
|
||||||
@ -453,12 +479,22 @@ ldpd_shutdown(void)
|
|||||||
free(iev_lde);
|
free(iev_lde);
|
||||||
|
|
||||||
log_info("terminating");
|
log_info("terminating");
|
||||||
|
|
||||||
|
vrf_terminate();
|
||||||
|
access_list_reset();
|
||||||
|
cmd_terminate();
|
||||||
|
vty_terminate();
|
||||||
|
ldp_zebra_destroy();
|
||||||
|
zprivs_terminate(&ldpd_privs);
|
||||||
|
thread_master_free(master);
|
||||||
|
closezlog(zlog_default);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pid_t
|
static pid_t
|
||||||
start_child(enum ldpd_process p, char *argv0, int fd, const char *user,
|
start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync,
|
||||||
const char *group)
|
const char *user, const char *group)
|
||||||
{
|
{
|
||||||
char *argv[7];
|
char *argv[7];
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
@ -470,12 +506,15 @@ start_child(enum ldpd_process p, char *argv0, int fd, const char *user,
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
close(fd);
|
close(fd_async);
|
||||||
|
close(fd_sync);
|
||||||
return (pid);
|
return (pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dup2(fd, 3) == -1)
|
if (dup2(fd_async, LDPD_FD_ASYNC) == -1)
|
||||||
fatal("cannot setup imsg fd");
|
fatal("cannot setup imsg async fd");
|
||||||
|
if (dup2(fd_sync, LDPD_FD_SYNC) == -1)
|
||||||
|
fatal("cannot setup imsg sync fd");
|
||||||
|
|
||||||
argv[argc++] = argv0;
|
argv[argc++] = argv0;
|
||||||
switch (p) {
|
switch (p) {
|
||||||
@ -536,6 +575,12 @@ main_dispatch_ldpe(struct thread *thread)
|
|||||||
af = imsg.hdr.pid;
|
af = imsg.hdr.pid;
|
||||||
main_imsg_send_net_sockets(af);
|
main_imsg_send_net_sockets(af);
|
||||||
break;
|
break;
|
||||||
|
case IMSG_ACL_CHECK:
|
||||||
|
if (imsg.hdr.len != IMSG_HEADER_SIZE +
|
||||||
|
sizeof(struct acl_check))
|
||||||
|
fatalx("IMSG_ACL_CHECK imsg with wrong len");
|
||||||
|
ldp_acl_reply(iev, (struct acl_check *)imsg.data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log_debug("%s: error handling imsg %d", __func__,
|
log_debug("%s: error handling imsg %d", __func__,
|
||||||
imsg.hdr.type);
|
imsg.hdr.type);
|
||||||
@ -617,6 +662,12 @@ main_dispatch_lde(struct thread *thread)
|
|||||||
log_warnx("%s: error unsetting pseudowire",
|
log_warnx("%s: error unsetting pseudowire",
|
||||||
__func__);
|
__func__);
|
||||||
break;
|
break;
|
||||||
|
case IMSG_ACL_CHECK:
|
||||||
|
if (imsg.hdr.len != IMSG_HEADER_SIZE +
|
||||||
|
sizeof(struct acl_check))
|
||||||
|
fatalx("IMSG_ACL_CHECK imsg with wrong len");
|
||||||
|
ldp_acl_reply(iev, (struct acl_check *)imsg.data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log_debug("%s: error handling imsg %d", __func__,
|
log_debug("%s: error handling imsg %d", __func__,
|
||||||
imsg.hdr.type);
|
imsg.hdr.type);
|
||||||
@ -693,10 +744,11 @@ main_imsg_compose_both(enum imsg_type type, void *buf, uint16_t len)
|
|||||||
void
|
void
|
||||||
imsg_event_add(struct imsgev *iev)
|
imsg_event_add(struct imsgev *iev)
|
||||||
{
|
{
|
||||||
THREAD_READ_ON(master, iev->ev_read, iev->handler_read, iev,
|
if (iev->handler_read)
|
||||||
iev->ibuf.fd);
|
THREAD_READ_ON(master, iev->ev_read, iev->handler_read, iev,
|
||||||
|
iev->ibuf.fd);
|
||||||
|
|
||||||
if (iev->ibuf.w.queued)
|
if (iev->handler_write && iev->ibuf.w.queued)
|
||||||
THREAD_WRITE_ON(master, iev->ev_write, iev->handler_write, iev,
|
THREAD_WRITE_ON(master, iev->ev_write, iev->handler_write, iev,
|
||||||
iev->ibuf.fd);
|
iev->ibuf.fd);
|
||||||
}
|
}
|
||||||
@ -794,6 +846,70 @@ main_imsg_send_net_socket(int af, enum socket_type type)
|
|||||||
sizeof(type));
|
sizeof(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldp_acl_request(struct imsgev *iev, char *acl_name, int af,
|
||||||
|
union ldpd_addr *addr, uint8_t prefixlen)
|
||||||
|
{
|
||||||
|
struct imsg imsg;
|
||||||
|
ssize_t n;
|
||||||
|
struct acl_check acl_check;
|
||||||
|
|
||||||
|
if (acl_name[0] == '\0')
|
||||||
|
return FILTER_PERMIT;
|
||||||
|
|
||||||
|
/* build request */
|
||||||
|
strlcpy(acl_check.acl, acl_name, sizeof(acl_check.acl));
|
||||||
|
acl_check.af = af;
|
||||||
|
acl_check.addr = *addr;
|
||||||
|
acl_check.prefixlen = prefixlen;
|
||||||
|
|
||||||
|
/* send (blocking) */
|
||||||
|
imsg_compose_event(iev, IMSG_ACL_CHECK, 0, 0, -1, &acl_check,
|
||||||
|
sizeof(acl_check));
|
||||||
|
imsg_flush(&iev->ibuf);
|
||||||
|
|
||||||
|
/* receive (blocking) and parse result */
|
||||||
|
if ((n = imsg_read(&iev->ibuf)) == -1)
|
||||||
|
fatal("imsg_read error");
|
||||||
|
if ((n = imsg_get(&iev->ibuf, &imsg)) == -1)
|
||||||
|
fatal("imsg_get");
|
||||||
|
if (imsg.hdr.type != IMSG_ACL_CHECK ||
|
||||||
|
imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(int))
|
||||||
|
fatalx("ldp_acl_request: invalid response");
|
||||||
|
|
||||||
|
return (*((int *)imsg.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldp_acl_reply(struct imsgev *iev, struct acl_check *acl_check)
|
||||||
|
{
|
||||||
|
struct access_list *alist;
|
||||||
|
struct prefix prefix;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
alist = access_list_lookup(family2afi(acl_check->af), acl_check->acl);
|
||||||
|
if (alist == NULL)
|
||||||
|
result = FILTER_DENY;
|
||||||
|
else {
|
||||||
|
prefix.family = acl_check->af;
|
||||||
|
switch (prefix.family) {
|
||||||
|
case AF_INET:
|
||||||
|
prefix.u.prefix4 = acl_check->addr.v4;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
prefix.u.prefix6 = acl_check->addr.v6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatalx("ldp_acl_reply: unknown af");
|
||||||
|
}
|
||||||
|
prefix.prefixlen = acl_check->prefixlen;
|
||||||
|
result = access_list_apply(alist, &prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
imsg_compose_event(iev, IMSG_ACL_CHECK, 0, 0, -1, &result,
|
||||||
|
sizeof(result));
|
||||||
|
}
|
||||||
|
|
||||||
struct ldpd_af_conf *
|
struct ldpd_af_conf *
|
||||||
ldp_af_conf_get(struct ldpd_conf *xconf, int af)
|
ldp_af_conf_get(struct ldpd_conf *xconf, int af)
|
||||||
{
|
{
|
||||||
@ -1140,8 +1256,7 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
|||||||
/* change of router-id requires resetting all neighborships */
|
/* change of router-id requires resetting all neighborships */
|
||||||
if (conf->rtr_id.s_addr != xconf->rtr_id.s_addr) {
|
if (conf->rtr_id.s_addr != xconf->rtr_id.s_addr) {
|
||||||
if (ldpd_process == PROC_LDP_ENGINE) {
|
if (ldpd_process == PROC_LDP_ENGINE) {
|
||||||
ldpe_reset_nbrs(AF_INET);
|
ldpe_reset_nbrs(AF_UNSPEC);
|
||||||
ldpe_reset_nbrs(AF_INET6);
|
|
||||||
if (conf->rtr_id.s_addr == INADDR_ANY ||
|
if (conf->rtr_id.s_addr == INADDR_ANY ||
|
||||||
xconf->rtr_id.s_addr == INADDR_ANY) {
|
xconf->rtr_id.s_addr == INADDR_ANY) {
|
||||||
if_update_all(AF_UNSPEC);
|
if_update_all(AF_UNSPEC);
|
||||||
@ -1174,61 +1289,98 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
|||||||
static void
|
static void
|
||||||
merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
|
merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
|
||||||
{
|
{
|
||||||
int egress_label_changed = 0;
|
int stop_init_backoff = 0;
|
||||||
int update_sockets = 0;
|
int remove_dynamic_tnbrs = 0;
|
||||||
|
int change_egress_label = 0;
|
||||||
|
int reset_nbrs_ipv4 = 0;
|
||||||
|
int reset_nbrs = 0;
|
||||||
|
int update_sockets = 0;
|
||||||
|
|
||||||
|
/* update timers */
|
||||||
if (af_conf->keepalive != xa->keepalive) {
|
if (af_conf->keepalive != xa->keepalive) {
|
||||||
af_conf->keepalive = xa->keepalive;
|
af_conf->keepalive = xa->keepalive;
|
||||||
if (ldpd_process == PROC_LDP_ENGINE)
|
stop_init_backoff = 1;
|
||||||
ldpe_stop_init_backoff(af);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
af_conf->lhello_holdtime = xa->lhello_holdtime;
|
af_conf->lhello_holdtime = xa->lhello_holdtime;
|
||||||
af_conf->lhello_interval = xa->lhello_interval;
|
af_conf->lhello_interval = xa->lhello_interval;
|
||||||
af_conf->thello_holdtime = xa->thello_holdtime;
|
af_conf->thello_holdtime = xa->thello_holdtime;
|
||||||
af_conf->thello_interval = xa->thello_interval;
|
af_conf->thello_interval = xa->thello_interval;
|
||||||
|
|
||||||
/* update flags */
|
/* update flags */
|
||||||
if (ldpd_process == PROC_LDP_ENGINE &&
|
if ((af_conf->flags & F_LDPD_AF_THELLO_ACCEPT) &&
|
||||||
(af_conf->flags & F_LDPD_AF_THELLO_ACCEPT) &&
|
|
||||||
!(xa->flags & F_LDPD_AF_THELLO_ACCEPT))
|
!(xa->flags & F_LDPD_AF_THELLO_ACCEPT))
|
||||||
ldpe_remove_dynamic_tnbrs(af);
|
remove_dynamic_tnbrs = 1;
|
||||||
|
|
||||||
if ((af_conf->flags & F_LDPD_AF_NO_GTSM) !=
|
if ((af_conf->flags & F_LDPD_AF_NO_GTSM) !=
|
||||||
(xa->flags & F_LDPD_AF_NO_GTSM)) {
|
(xa->flags & F_LDPD_AF_NO_GTSM)) {
|
||||||
if (af == AF_INET6)
|
if (af == AF_INET6)
|
||||||
/* need to set/unset IPV6_MINHOPCOUNT */
|
/* need to set/unset IPV6_MINHOPCOUNT */
|
||||||
update_sockets = 1;
|
update_sockets = 1;
|
||||||
else if (ldpd_process == PROC_LDP_ENGINE)
|
else
|
||||||
/* for LDPv4 just resetting the neighbors is enough */
|
/* for LDPv4 just resetting the neighbors is enough */
|
||||||
ldpe_reset_nbrs(af);
|
reset_nbrs_ipv4 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((af_conf->flags & F_LDPD_AF_EXPNULL) !=
|
if ((af_conf->flags & F_LDPD_AF_EXPNULL) !=
|
||||||
(xa->flags & F_LDPD_AF_EXPNULL))
|
(xa->flags & F_LDPD_AF_EXPNULL))
|
||||||
egress_label_changed = 1;
|
change_egress_label = 1;
|
||||||
|
|
||||||
af_conf->flags = xa->flags;
|
af_conf->flags = xa->flags;
|
||||||
|
|
||||||
if (egress_label_changed) {
|
/* update the transport address */
|
||||||
switch (ldpd_process) {
|
|
||||||
case PROC_LDE_ENGINE:
|
|
||||||
lde_change_egress_label(af, af_conf->flags &
|
|
||||||
F_LDPD_AF_EXPNULL);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ldp_addrcmp(af, &af_conf->trans_addr, &xa->trans_addr)) {
|
if (ldp_addrcmp(af, &af_conf->trans_addr, &xa->trans_addr)) {
|
||||||
af_conf->trans_addr = xa->trans_addr;
|
af_conf->trans_addr = xa->trans_addr;
|
||||||
update_sockets = 1;
|
update_sockets = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ldpd_process == PROC_MAIN && iev_ldpe && update_sockets)
|
/* update ACLs */
|
||||||
imsg_compose_event(iev_ldpe, IMSG_CLOSE_SOCKETS, af, 0, -1,
|
if (strcmp(af_conf->acl_label_advertise_to,
|
||||||
NULL, 0);
|
xa->acl_label_advertise_to) ||
|
||||||
|
strcmp(af_conf->acl_label_advertise_for,
|
||||||
|
xa->acl_label_advertise_for) ||
|
||||||
|
strcmp(af_conf->acl_label_accept_from,
|
||||||
|
xa->acl_label_accept_from) ||
|
||||||
|
strcmp(af_conf->acl_label_accept_for,
|
||||||
|
xa->acl_label_accept_for))
|
||||||
|
reset_nbrs = 1;
|
||||||
|
if (strcmp(af_conf->acl_thello_accept_from, xa->acl_thello_accept_from))
|
||||||
|
remove_dynamic_tnbrs = 1;
|
||||||
|
if (strcmp(af_conf->acl_label_expnull_for, xa->acl_label_expnull_for))
|
||||||
|
change_egress_label = 1;
|
||||||
|
strlcpy(af_conf->acl_thello_accept_from, xa->acl_thello_accept_from,
|
||||||
|
sizeof(af_conf->acl_thello_accept_from));
|
||||||
|
strlcpy(af_conf->acl_label_allocate_for, xa->acl_label_allocate_for,
|
||||||
|
sizeof(af_conf->acl_label_allocate_for));
|
||||||
|
strlcpy(af_conf->acl_label_advertise_to, xa->acl_label_advertise_to,
|
||||||
|
sizeof(af_conf->acl_label_advertise_to));
|
||||||
|
strlcpy(af_conf->acl_label_advertise_for, xa->acl_label_advertise_for,
|
||||||
|
sizeof(af_conf->acl_label_advertise_for));
|
||||||
|
strlcpy(af_conf->acl_label_accept_from, xa->acl_label_accept_from,
|
||||||
|
sizeof(af_conf->acl_label_accept_from));
|
||||||
|
strlcpy(af_conf->acl_label_accept_for, xa->acl_label_accept_for,
|
||||||
|
sizeof(af_conf->acl_label_accept_for));
|
||||||
|
strlcpy(af_conf->acl_label_expnull_for, xa->acl_label_expnull_for,
|
||||||
|
sizeof(af_conf->acl_label_expnull_for));
|
||||||
|
|
||||||
|
/* apply the new configuration */
|
||||||
|
switch (ldpd_process) {
|
||||||
|
case PROC_LDE_ENGINE:
|
||||||
|
if (change_egress_label)
|
||||||
|
lde_change_egress_label(af);
|
||||||
|
break;
|
||||||
|
case PROC_LDP_ENGINE:
|
||||||
|
if (stop_init_backoff)
|
||||||
|
ldpe_stop_init_backoff(af);
|
||||||
|
if (remove_dynamic_tnbrs)
|
||||||
|
ldpe_remove_dynamic_tnbrs(af);
|
||||||
|
if (reset_nbrs)
|
||||||
|
ldpe_reset_nbrs(AF_UNSPEC);
|
||||||
|
else if (reset_nbrs_ipv4)
|
||||||
|
ldpe_reset_nbrs(AF_INET);
|
||||||
|
break;
|
||||||
|
case PROC_MAIN:
|
||||||
|
if (update_sockets && iev_ldpe)
|
||||||
|
imsg_compose_event(iev_ldpe, IMSG_CLOSE_SOCKETS, af,
|
||||||
|
0, -1, NULL, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
28
ldpd/ldpd.h
28
ldpd/ldpd.h
@ -27,12 +27,16 @@
|
|||||||
#include "imsg.h"
|
#include "imsg.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "qobj.h"
|
#include "qobj.h"
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
#include "ldp.h"
|
#include "ldp.h"
|
||||||
|
|
||||||
#define CONF_FILE "/etc/ldpd.conf"
|
#define CONF_FILE "/etc/ldpd.conf"
|
||||||
#define LDPD_USER "_ldpd"
|
#define LDPD_USER "_ldpd"
|
||||||
|
|
||||||
|
#define LDPD_FD_ASYNC 3
|
||||||
|
#define LDPD_FD_SYNC 4
|
||||||
|
|
||||||
#define LDPD_OPT_VERBOSE 0x00000001
|
#define LDPD_OPT_VERBOSE 0x00000001
|
||||||
#define LDPD_OPT_VERBOSE2 0x00000002
|
#define LDPD_OPT_VERBOSE2 0x00000002
|
||||||
#define LDPD_OPT_NOACTION 0x00000004
|
#define LDPD_OPT_NOACTION 0x00000004
|
||||||
@ -135,7 +139,8 @@ enum imsg_type {
|
|||||||
IMSG_RECONF_L2VPN_IPW,
|
IMSG_RECONF_L2VPN_IPW,
|
||||||
IMSG_RECONF_END,
|
IMSG_RECONF_END,
|
||||||
IMSG_DEBUG_UPDATE,
|
IMSG_DEBUG_UPDATE,
|
||||||
IMSG_LOG
|
IMSG_LOG,
|
||||||
|
IMSG_ACL_CHECK
|
||||||
};
|
};
|
||||||
|
|
||||||
union ldpd_addr {
|
union ldpd_addr {
|
||||||
@ -408,12 +413,20 @@ struct ldpd_af_conf {
|
|||||||
uint16_t thello_holdtime;
|
uint16_t thello_holdtime;
|
||||||
uint16_t thello_interval;
|
uint16_t thello_interval;
|
||||||
union ldpd_addr trans_addr;
|
union ldpd_addr trans_addr;
|
||||||
|
char acl_thello_accept_from[ACL_NAMSIZ];
|
||||||
|
char acl_label_allocate_for[ACL_NAMSIZ];
|
||||||
|
char acl_label_advertise_to[ACL_NAMSIZ];
|
||||||
|
char acl_label_advertise_for[ACL_NAMSIZ];
|
||||||
|
char acl_label_expnull_for[ACL_NAMSIZ];
|
||||||
|
char acl_label_accept_from[ACL_NAMSIZ];
|
||||||
|
char acl_label_accept_for[ACL_NAMSIZ];
|
||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
#define F_LDPD_AF_ENABLED 0x0001
|
#define F_LDPD_AF_ENABLED 0x0001
|
||||||
#define F_LDPD_AF_THELLO_ACCEPT 0x0002
|
#define F_LDPD_AF_THELLO_ACCEPT 0x0002
|
||||||
#define F_LDPD_AF_EXPNULL 0x0004
|
#define F_LDPD_AF_EXPNULL 0x0004
|
||||||
#define F_LDPD_AF_NO_GTSM 0x0008
|
#define F_LDPD_AF_NO_GTSM 0x0008
|
||||||
|
#define F_LDPD_AF_ALLOCHOSTONLY 0x0010
|
||||||
|
|
||||||
struct ldpd_conf {
|
struct ldpd_conf {
|
||||||
struct in_addr rtr_id;
|
struct in_addr rtr_id;
|
||||||
@ -497,6 +510,13 @@ struct kif {
|
|||||||
int mtu;
|
int mtu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct acl_check {
|
||||||
|
char acl[ACL_NAMSIZ];
|
||||||
|
int af;
|
||||||
|
union ldpd_addr addr;
|
||||||
|
uint8_t prefixlen;
|
||||||
|
};
|
||||||
|
|
||||||
/* control data structures */
|
/* control data structures */
|
||||||
struct ctl_iface {
|
struct ctl_iface {
|
||||||
int af;
|
int af;
|
||||||
@ -627,6 +647,9 @@ void evbuf_event_add(struct evbuf *);
|
|||||||
void evbuf_init(struct evbuf *, int,
|
void evbuf_init(struct evbuf *, int,
|
||||||
int (*)(struct thread *), void *);
|
int (*)(struct thread *), void *);
|
||||||
void evbuf_clear(struct evbuf *);
|
void evbuf_clear(struct evbuf *);
|
||||||
|
int ldp_acl_request(struct imsgev *, char *, int,
|
||||||
|
union ldpd_addr *, uint8_t);
|
||||||
|
void ldp_acl_reply(struct imsgev *, struct acl_check *);
|
||||||
struct ldpd_af_conf *ldp_af_conf_get(struct ldpd_conf *, int);
|
struct ldpd_af_conf *ldp_af_conf_get(struct ldpd_conf *, int);
|
||||||
struct ldpd_af_global *ldp_af_global_get(struct ldpd_global *, int);
|
struct ldpd_af_global *ldp_af_global_get(struct ldpd_global *, int);
|
||||||
int ldp_is_dual_stack(struct ldpd_conf *);
|
int ldp_is_dual_stack(struct ldpd_conf *);
|
||||||
@ -694,7 +717,8 @@ int sock_set_ipv6_mcast_loop(int);
|
|||||||
extern struct thread_master *master;
|
extern struct thread_master *master;
|
||||||
|
|
||||||
/* ldp_zebra.c */
|
/* ldp_zebra.c */
|
||||||
void ldp_zebra_init(struct thread_master *);
|
void ldp_zebra_init(struct thread_master *);
|
||||||
|
void ldp_zebra_destroy(void);
|
||||||
|
|
||||||
/* compatibility */
|
/* compatibility */
|
||||||
#ifndef __OpenBSD__
|
#ifndef __OpenBSD__
|
||||||
|
27
ldpd/ldpe.c
27
ldpd/ldpe.c
@ -48,7 +48,7 @@ struct ldpd_conf *leconf;
|
|||||||
struct ldpd_sysdep sysdep;
|
struct ldpd_sysdep sysdep;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct imsgev *iev_main;
|
static struct imsgev *iev_main, *iev_main_sync;
|
||||||
static struct imsgev *iev_lde;
|
static struct imsgev *iev_lde;
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
static struct thread *pfkey_ev;
|
static struct thread *pfkey_ev;
|
||||||
@ -142,15 +142,18 @@ ldpe(const char *user, const char *group)
|
|||||||
/* setup signal handler */
|
/* setup signal handler */
|
||||||
signal_init(master, array_size(ldpe_signals), ldpe_signals);
|
signal_init(master, array_size(ldpe_signals), ldpe_signals);
|
||||||
|
|
||||||
/* setup pipe and event handler to the parent process */
|
/* setup pipes and event handlers to the parent process */
|
||||||
if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
|
if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL)
|
||||||
fatal(NULL);
|
fatal(NULL);
|
||||||
imsg_init(&iev_main->ibuf, 3);
|
imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC);
|
||||||
iev_main->handler_read = ldpe_dispatch_main;
|
iev_main->handler_read = ldpe_dispatch_main;
|
||||||
iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
|
iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
|
||||||
iev_main, iev_main->ibuf.fd);
|
iev_main, iev_main->ibuf.fd);
|
||||||
iev_main->handler_write = ldp_write_handler;
|
iev_main->handler_write = ldp_write_handler;
|
||||||
iev_main->ev_write = NULL;
|
|
||||||
|
if ((iev_main_sync = calloc(1, sizeof(struct imsgev))) == NULL)
|
||||||
|
fatal(NULL);
|
||||||
|
imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
if (sysdep.no_pfkey == 0)
|
if (sysdep.no_pfkey == 0)
|
||||||
@ -191,6 +194,8 @@ ldpe_shutdown(void)
|
|||||||
msgbuf_write(&iev_main->ibuf.w);
|
msgbuf_write(&iev_main->ibuf.w);
|
||||||
msgbuf_clear(&iev_main->ibuf.w);
|
msgbuf_clear(&iev_main->ibuf.w);
|
||||||
close(iev_main->ibuf.fd);
|
close(iev_main->ibuf.fd);
|
||||||
|
msgbuf_clear(&iev_main_sync->ibuf.w);
|
||||||
|
close(iev_main_sync->ibuf.fd);
|
||||||
|
|
||||||
control_cleanup();
|
control_cleanup();
|
||||||
config_clear(leconf);
|
config_clear(leconf);
|
||||||
@ -215,6 +220,7 @@ ldpe_shutdown(void)
|
|||||||
/* clean up */
|
/* clean up */
|
||||||
free(iev_lde);
|
free(iev_lde);
|
||||||
free(iev_main);
|
free(iev_main);
|
||||||
|
free(iev_main_sync);
|
||||||
free(pkt_ptr);
|
free(pkt_ptr);
|
||||||
|
|
||||||
log_info("ldp engine exiting");
|
log_info("ldp engine exiting");
|
||||||
@ -402,8 +408,7 @@ ldpe_dispatch_main(struct thread *thread)
|
|||||||
memcpy(&global.rtr_id, imsg.data,
|
memcpy(&global.rtr_id, imsg.data,
|
||||||
sizeof(global.rtr_id));
|
sizeof(global.rtr_id));
|
||||||
if (leconf->rtr_id.s_addr == INADDR_ANY) {
|
if (leconf->rtr_id.s_addr == INADDR_ANY) {
|
||||||
ldpe_reset_nbrs(AF_INET);
|
ldpe_reset_nbrs(AF_UNSPEC);
|
||||||
ldpe_reset_nbrs(AF_INET6);
|
|
||||||
}
|
}
|
||||||
if_update_all(AF_UNSPEC);
|
if_update_all(AF_UNSPEC);
|
||||||
tnbr_update_all(AF_UNSPEC);
|
tnbr_update_all(AF_UNSPEC);
|
||||||
@ -716,13 +721,19 @@ ldpe_close_sockets(int af)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldpe_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);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ldpe_reset_nbrs(int af)
|
ldpe_reset_nbrs(int af)
|
||||||
{
|
{
|
||||||
struct nbr *nbr;
|
struct nbr *nbr;
|
||||||
|
|
||||||
RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
|
RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
|
||||||
if (nbr->af == af)
|
if (af == AF_UNSPEC || nbr->af == af)
|
||||||
session_shutdown(nbr, S_SHUTDOWN, 0, 0);
|
session_shutdown(nbr, S_SHUTDOWN, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,6 +192,7 @@ int ldpe_imsg_compose_parent(int, pid_t, void *,
|
|||||||
uint16_t);
|
uint16_t);
|
||||||
int ldpe_imsg_compose_lde(int, uint32_t, pid_t, void *,
|
int ldpe_imsg_compose_lde(int, uint32_t, pid_t, void *,
|
||||||
uint16_t);
|
uint16_t);
|
||||||
|
int ldpe_acl_check(char *, int, union ldpd_addr *, uint8_t);
|
||||||
void ldpe_reset_nbrs(int);
|
void ldpe_reset_nbrs(int);
|
||||||
void ldpe_reset_ds_nbrs(void);
|
void ldpe_reset_ds_nbrs(void);
|
||||||
void ldpe_remove_dynamic_tnbrs(int);
|
void ldpe_remove_dynamic_tnbrs(int);
|
||||||
|
@ -1259,6 +1259,14 @@ filter_set_zebra (struct vty *vty, const char *name_str, const char *type_str,
|
|||||||
struct access_list *access;
|
struct access_list *access;
|
||||||
struct prefix p;
|
struct prefix p;
|
||||||
|
|
||||||
|
if (strlen(name_str) > ACL_NAMSIZ)
|
||||||
|
{
|
||||||
|
vty_out (vty, "%% ACL name %s is invalid: length exceeds "
|
||||||
|
"%d characters%s",
|
||||||
|
name_str, ACL_NAMSIZ, VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check of filter type. */
|
/* Check of filter type. */
|
||||||
if (strncmp (type_str, "p", 1) == 0)
|
if (strncmp (type_str, "p", 1) == 0)
|
||||||
type = FILTER_PERMIT;
|
type = FILTER_PERMIT;
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
|
|
||||||
#include "if.h"
|
#include "if.h"
|
||||||
|
|
||||||
|
/* Maximum ACL name length */
|
||||||
|
#define ACL_NAMSIZ 128
|
||||||
|
|
||||||
/* Filter direction. */
|
/* Filter direction. */
|
||||||
#define FILTER_IN 0
|
#define FILTER_IN 0
|
||||||
#define FILTER_OUT 1
|
#define FILTER_OUT 1
|
||||||
|
@ -482,11 +482,9 @@ DEFUN (vrf,
|
|||||||
{
|
{
|
||||||
int idx_name = 1;
|
int idx_name = 1;
|
||||||
const char *vrfname = argv[idx_name]->arg;
|
const char *vrfname = argv[idx_name]->arg;
|
||||||
|
|
||||||
struct vrf *vrfp;
|
struct vrf *vrfp;
|
||||||
size_t sl;
|
|
||||||
|
|
||||||
if ((sl = strlen(vrfname)) > VRF_NAMSIZ)
|
if (strlen(vrfname) > VRF_NAMSIZ)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% VRF name %s is invalid: length exceeds "
|
vty_out (vty, "%% VRF name %s is invalid: length exceeds "
|
||||||
"%d characters%s",
|
"%d characters%s",
|
||||||
|
@ -42,6 +42,8 @@ use XML::LibXML;
|
|||||||
"ipv6" => "X:X::X:X",
|
"ipv6" => "X:X::X:X",
|
||||||
"ipv6m" => "X:X::X:X/M",
|
"ipv6m" => "X:X::X:X/M",
|
||||||
"mtu" => "(1500-9180)",
|
"mtu" => "(1500-9180)",
|
||||||
|
"acl_range" => "(1-199)",
|
||||||
|
"acl_expanded_range" => "(1300-2699)",
|
||||||
# BGP specific
|
# BGP specific
|
||||||
"rd" => "ASN:nn_or_IP-address:nn",
|
"rd" => "ASN:nn_or_IP-address:nn",
|
||||||
"asn" => "(1-4294967295)",
|
"asn" => "(1-4294967295)",
|
||||||
@ -207,7 +209,7 @@ sub generate_code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# update the command string
|
# update the command string
|
||||||
if ($node{'function'} ne "inherited") {
|
if ($node{'function'} ne "inherited" and $node{'function'}) {
|
||||||
$function = $node{'function'};
|
$function = $node{'function'};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,7 +349,7 @@ addattr_l (struct nlmsghdr *n, unsigned int maxlen, int type,
|
|||||||
if (data)
|
if (data)
|
||||||
memcpy (RTA_DATA (rta), data, alen);
|
memcpy (RTA_DATA (rta), data, alen);
|
||||||
else
|
else
|
||||||
assert (len == 0);
|
assert (alen == 0);
|
||||||
|
|
||||||
n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len);
|
n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len);
|
||||||
|
|
||||||
@ -375,7 +375,7 @@ rta_addattr_l (struct rtattr *rta, unsigned int maxlen, int type,
|
|||||||
if (data)
|
if (data)
|
||||||
memcpy (RTA_DATA (subrta), data, alen);
|
memcpy (RTA_DATA (subrta), data, alen);
|
||||||
else
|
else
|
||||||
assert (len == 0);
|
assert (alen == 0);
|
||||||
|
|
||||||
rta->rta_len = NLMSG_ALIGN (rta->rta_len) + RTA_ALIGN (len);
|
rta->rta_len = NLMSG_ALIGN (rta->rta_len) + RTA_ALIGN (len);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user