2 * Copyright (C) 2016 by Open Source Routing.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; see the file COPYING; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
33 static void ldp_af_iface_config_write(struct vty
*, int);
34 static void ldp_af_config_write(struct vty
*, int, struct ldpd_conf
*,
35 struct ldpd_af_conf
*);
36 static void ldp_l2vpn_pw_config_write(struct vty
*, struct l2vpn_pw
*);
37 static int ldp_vty_get_af(struct vty
*);
38 static int ldp_iface_is_configured(struct ldpd_conf
*, const char *);
40 struct cmd_node ldp_node
=
47 struct cmd_node ldp_ipv4_node
=
50 "%s(config-ldp-af)# ",
54 struct cmd_node ldp_ipv6_node
=
57 "%s(config-ldp-af)# ",
61 struct cmd_node ldp_ipv4_iface_node
=
64 "%s(config-ldp-af-if)# ",
68 struct cmd_node ldp_ipv6_iface_node
=
71 "%s(config-ldp-af-if)# ",
75 struct cmd_node ldp_l2vpn_node
=
82 struct cmd_node ldp_pseudowire_node
=
85 "%s(config-l2vpn-pw)# ",
90 ldp_get_address(const char *str
, int *af
, union ldpd_addr
*addr
)
92 memset(addr
, 0, sizeof(*addr
));
94 if (inet_pton(AF_INET
, str
, &addr
->v4
) == 1) {
99 if (inet_pton(AF_INET6
, str
, &addr
->v6
) == 1) {
108 ldp_af_iface_config_write(struct vty
*vty
, int af
)
113 RB_FOREACH(iface
, iface_head
, &ldpd_conf
->iface_tree
) {
114 ia
= iface_af_get(iface
, af
);
118 vty_out (vty
, " !\n");
119 vty_out (vty
, " interface %s\n", iface
->name
);
121 if (ia
->hello_holdtime
!= LINK_DFLT_HOLDTIME
&&
122 ia
->hello_holdtime
!= 0)
123 vty_out (vty
, " discovery hello holdtime %u\n",
125 if (ia
->hello_interval
!= DEFAULT_HELLO_INTERVAL
&&
126 ia
->hello_interval
!= 0)
127 vty_out (vty
, " discovery hello interval %u\n",
133 ldp_af_config_write(struct vty
*vty
, int af
, struct ldpd_conf
*conf
,
134 struct ldpd_af_conf
*af_conf
)
138 if (!(af_conf
->flags
& F_LDPD_AF_ENABLED
))
141 vty_out (vty
, " !\n");
142 vty_out (vty
, " address-family %s\n", af_name(af
));
144 if (af_conf
->lhello_holdtime
!= LINK_DFLT_HOLDTIME
&&
145 af_conf
->lhello_holdtime
!= 0 )
146 vty_out (vty
, " discovery hello holdtime %u\n",
147 af_conf
->lhello_holdtime
);
148 if (af_conf
->lhello_interval
!= DEFAULT_HELLO_INTERVAL
&&
149 af_conf
->lhello_interval
!= 0)
150 vty_out (vty
, " discovery hello interval %u\n",
151 af_conf
->lhello_interval
);
153 if (af_conf
->flags
& F_LDPD_AF_THELLO_ACCEPT
) {
154 vty_out(vty
, " discovery targeted-hello accept");
155 if (af_conf
->acl_thello_accept_from
[0] != '\0')
156 vty_out(vty
, " from %s",
157 af_conf
->acl_thello_accept_from
);
158 vty_out (vty
, VTYNL
);
161 if (af_conf
->thello_holdtime
!= TARGETED_DFLT_HOLDTIME
&&
162 af_conf
->thello_holdtime
!= 0)
163 vty_out (vty
, " discovery targeted-hello holdtime %u\n",
164 af_conf
->thello_holdtime
);
165 if (af_conf
->thello_interval
!= DEFAULT_HELLO_INTERVAL
&&
166 af_conf
->thello_interval
!= 0)
167 vty_out (vty
, " discovery targeted-hello interval %u\n",
168 af_conf
->thello_interval
);
170 if (ldp_addrisset(af
, &af_conf
->trans_addr
))
171 vty_out (vty
, " discovery transport-address %s\n",
172 log_addr(af
, &af_conf
->trans_addr
));
175 " ! Incomplete config, specify a discovery transport-address\n");
177 if ((af_conf
->flags
& F_LDPD_AF_ALLOCHOSTONLY
) ||
178 af_conf
->acl_label_allocate_for
[0] != '\0') {
179 vty_out(vty
, " label local allocate");
180 if (af_conf
->flags
& F_LDPD_AF_ALLOCHOSTONLY
)
181 vty_out(vty
, " host-routes");
183 vty_out(vty
, " for %s",
184 af_conf
->acl_label_allocate_for
);
185 vty_out (vty
, VTYNL
);
188 if (af_conf
->acl_label_advertise_for
[0] != '\0' ||
189 af_conf
->acl_label_advertise_to
[0] != '\0') {
190 vty_out(vty
, " label local advertise");
191 if (af_conf
->acl_label_advertise_to
[0] != '\0')
192 vty_out(vty
, " to %s",
193 af_conf
->acl_label_advertise_to
);
194 if (af_conf
->acl_label_advertise_for
[0] != '\0')
195 vty_out(vty
, " for %s",
196 af_conf
->acl_label_advertise_for
);
197 vty_out (vty
, VTYNL
);
200 if (af_conf
->flags
& F_LDPD_AF_EXPNULL
) {
201 vty_out(vty
, " label local advertise explicit-null");
202 if (af_conf
->acl_label_expnull_for
[0] != '\0')
203 vty_out(vty
, " for %s",
204 af_conf
->acl_label_expnull_for
);
205 vty_out (vty
, VTYNL
);
208 if (af_conf
->acl_label_accept_for
[0] != '\0' ||
209 af_conf
->acl_label_accept_from
[0] != '\0') {
210 vty_out(vty
, " label remote accept");
211 if (af_conf
->acl_label_accept_from
[0] != '\0')
212 vty_out(vty
, " from %s",
213 af_conf
->acl_label_accept_from
);
214 if (af_conf
->acl_label_accept_for
[0] != '\0')
215 vty_out(vty
, " for %s",
216 af_conf
->acl_label_accept_for
);
217 vty_out (vty
, VTYNL
);
220 if (af_conf
->flags
& F_LDPD_AF_NO_GTSM
)
221 vty_out (vty
, " ttl-security disable\n");
223 if (af_conf
->keepalive
!= DEFAULT_KEEPALIVE
)
224 vty_out (vty
, " session holdtime %u\n",af_conf
->keepalive
);
226 RB_FOREACH(tnbr
, tnbr_head
, &ldpd_conf
->tnbr_tree
) {
227 if (tnbr
->af
== af
) {
228 vty_out (vty
, " !\n");
229 vty_out (vty
, " neighbor %s targeted\n",
230 log_addr(tnbr
->af
, &tnbr
->addr
));
234 ldp_af_iface_config_write(vty
, af
);
236 vty_out (vty
, " !\n");
240 ldp_config_write(struct vty
*vty
)
242 struct nbr_params
*nbrp
;
244 if (!(ldpd_conf
->flags
& F_LDPD_ENABLED
))
247 vty_out (vty
, "mpls ldp\n");
249 if (ldpd_conf
->rtr_id
.s_addr
!= 0)
250 vty_out (vty
, " router-id %s\n",
251 inet_ntoa(ldpd_conf
->rtr_id
));
253 if (ldpd_conf
->lhello_holdtime
!= LINK_DFLT_HOLDTIME
&&
254 ldpd_conf
->lhello_holdtime
!= 0)
255 vty_out (vty
, " discovery hello holdtime %u\n",
256 ldpd_conf
->lhello_holdtime
);
257 if (ldpd_conf
->lhello_interval
!= DEFAULT_HELLO_INTERVAL
&&
258 ldpd_conf
->lhello_interval
!= 0)
259 vty_out (vty
, " discovery hello interval %u\n",
260 ldpd_conf
->lhello_interval
);
262 if (ldpd_conf
->thello_holdtime
!= TARGETED_DFLT_HOLDTIME
&&
263 ldpd_conf
->thello_holdtime
!= 0)
264 vty_out (vty
, " discovery targeted-hello holdtime %u\n",
265 ldpd_conf
->thello_holdtime
);
266 if (ldpd_conf
->thello_interval
!= DEFAULT_HELLO_INTERVAL
&&
267 ldpd_conf
->thello_interval
!= 0)
268 vty_out (vty
, " discovery targeted-hello interval %u\n",
269 ldpd_conf
->thello_interval
);
271 if (ldpd_conf
->trans_pref
== DUAL_STACK_LDPOV4
)
273 " dual-stack transport-connection prefer ipv4\n");
275 if (ldpd_conf
->flags
& F_LDPD_DS_CISCO_INTEROP
)
276 vty_out (vty
, " dual-stack cisco-interop\n");
278 RB_FOREACH(nbrp
, nbrp_head
, &ldpd_conf
->nbrp_tree
) {
279 if (nbrp
->flags
& F_NBRP_KEEPALIVE
)
280 vty_out (vty
, " neighbor %s session holdtime %u\n",
281 inet_ntoa(nbrp
->lsr_id
),nbrp
->keepalive
);
283 if (nbrp
->flags
& F_NBRP_GTSM
) {
284 if (nbrp
->gtsm_enabled
)
285 vty_out (vty
, " neighbor %s ttl-security hops "
286 "%u\n", inet_ntoa(nbrp
->lsr_id
),
289 vty_out (vty
, " neighbor %s ttl-security "
290 "disable\n",inet_ntoa(nbrp
->lsr_id
));
293 if (nbrp
->auth
.method
== AUTH_MD5SIG
)
294 vty_out (vty
, " neighbor %s password %s\n",
295 inet_ntoa(nbrp
->lsr_id
),nbrp
->auth
.md5key
);
298 ldp_af_config_write(vty
, AF_INET
, ldpd_conf
, &ldpd_conf
->ipv4
);
299 ldp_af_config_write(vty
, AF_INET6
, ldpd_conf
, &ldpd_conf
->ipv6
);
300 vty_out (vty
, " !\n");
301 vty_out (vty
, "!\n");
307 ldp_l2vpn_pw_config_write(struct vty
*vty
, struct l2vpn_pw
*pw
)
309 int missing_lsrid
= 0;
310 int missing_pwid
= 0;
312 vty_out (vty
, " !\n");
313 vty_out (vty
, " member pseudowire %s\n", pw
->ifname
);
315 if (pw
->lsr_id
.s_addr
!= INADDR_ANY
)
316 vty_out (vty
, " neighbor lsr-id %s\n",inet_ntoa(pw
->lsr_id
));
320 if (pw
->flags
& F_PW_STATIC_NBR_ADDR
)
321 vty_out (vty
, " neighbor address %s\n",
322 log_addr(pw
->af
, &pw
->addr
));
325 vty_out (vty
, " pw-id %u\n", pw
->pwid
);
329 if (!(pw
->flags
& F_PW_CWORD_CONF
))
330 vty_out (vty
, " control-word exclude\n");
332 if (!(pw
->flags
& F_PW_STATUSTLV_CONF
))
333 vty_out (vty
, " pw-status disable\n");
337 " ! Incomplete config, specify a neighbor lsr-id\n");
339 vty_out (vty
," ! Incomplete config, specify a pw-id\n");
343 ldp_l2vpn_config_write(struct vty
*vty
)
346 struct l2vpn_if
*lif
;
349 RB_FOREACH(l2vpn
, l2vpn_head
, &ldpd_conf
->l2vpn_tree
) {
350 vty_out (vty
, "l2vpn %s type vpls\n", l2vpn
->name
);
352 if (l2vpn
->pw_type
!= DEFAULT_PW_TYPE
)
353 vty_out (vty
, " vc type ethernet-tagged\n");
355 if (l2vpn
->mtu
!= DEFAULT_L2VPN_MTU
)
356 vty_out (vty
, " mtu %u\n", l2vpn
->mtu
);
358 if (l2vpn
->br_ifname
[0] != '\0')
359 vty_out (vty
, " bridge %s\n",l2vpn
->br_ifname
);
361 RB_FOREACH(lif
, l2vpn_if_head
, &l2vpn
->if_tree
)
362 vty_out (vty
, " member interface %s\n",lif
->ifname
);
364 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
365 ldp_l2vpn_pw_config_write(vty
, pw
);
366 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
)
367 ldp_l2vpn_pw_config_write(vty
, pw
);
369 vty_out (vty
, " !\n");
370 vty_out (vty
, "!\n");
377 ldp_vty_get_af(struct vty
*vty
)
381 case LDP_IPV4_IFACE_NODE
:
384 case LDP_IPV6_IFACE_NODE
:
387 fatalx("ldp_vty_get_af: unexpected node");
392 ldp_iface_is_configured(struct ldpd_conf
*xconf
, const char *ifname
)
396 if (if_lookup_name(xconf
, ifname
))
399 RB_FOREACH(l2vpn
, l2vpn_head
, &xconf
->l2vpn_tree
) {
400 if (l2vpn_if_find(l2vpn
, ifname
))
402 if (l2vpn_pw_find(l2vpn
, ifname
))
410 ldp_vty_mpls_ldp(struct vty
*vty
, int disable
)
413 vty_conf
->flags
&= ~F_LDPD_ENABLED
;
415 vty
->node
= LDP_NODE
;
416 vty_conf
->flags
|= F_LDPD_ENABLED
;
419 ldp_config_apply(vty
, vty_conf
);
421 return (CMD_SUCCESS
);
425 ldp_vty_address_family(struct vty
*vty
, int disable
, const char *af_str
)
427 struct ldpd_af_conf
*af_conf
;
430 if (strcmp(af_str
, "ipv4") == 0) {
432 af_conf
= &vty_conf
->ipv4
;
433 } else if (strcmp(af_str
, "ipv6") == 0) {
435 af_conf
= &vty_conf
->ipv6
;
437 return (CMD_WARNING
);
440 af_conf
->flags
&= ~F_LDPD_AF_ENABLED
;
441 ldp_config_apply(vty
, vty_conf
);
442 return (CMD_SUCCESS
);
447 vty
->node
= LDP_IPV4_NODE
;
450 vty
->node
= LDP_IPV6_NODE
;
453 fatalx("ldp_vty_address_family: unknown af");
455 af_conf
->flags
|= F_LDPD_AF_ENABLED
;
457 ldp_config_apply(vty
, vty_conf
);
459 return (CMD_SUCCESS
);
463 ldp_vty_disc_holdtime(struct vty
*vty
, int disable
, const char *hello_type_str
,
464 const char *seconds_str
)
466 struct ldpd_af_conf
*af_conf
;
472 enum hello_type hello_type
;
474 secs
= strtol(seconds_str
, &ep
, 10);
475 if (*ep
!= '\0' || secs
< MIN_HOLDTIME
|| secs
> MAX_HOLDTIME
) {
476 vty_out (vty
, "%% Invalid holdtime\n");
477 return (CMD_WARNING
);
480 if (hello_type_str
[0] == 'h')
481 hello_type
= HELLO_LINK
;
483 hello_type
= HELLO_TARGETED
;
488 switch (hello_type
) {
490 vty_conf
->lhello_holdtime
= LINK_DFLT_HOLDTIME
;
493 vty_conf
->thello_holdtime
=
494 TARGETED_DFLT_HOLDTIME
;
498 switch (hello_type
) {
500 vty_conf
->lhello_holdtime
= secs
;
503 vty_conf
->thello_holdtime
= secs
;
507 ldp_config_apply(vty
, vty_conf
);
511 af
= ldp_vty_get_af(vty
);
512 af_conf
= ldp_af_conf_get(vty_conf
, af
);
515 switch (hello_type
) {
517 af_conf
->lhello_holdtime
= 0;
520 af_conf
->thello_holdtime
= 0;
524 switch (hello_type
) {
526 af_conf
->lhello_holdtime
= secs
;
529 af_conf
->thello_holdtime
= secs
;
533 ldp_config_apply(vty
, vty_conf
);
535 case LDP_IPV4_IFACE_NODE
:
536 case LDP_IPV6_IFACE_NODE
:
537 af
= ldp_vty_get_af(vty
);
538 iface
= VTY_GET_CONTEXT(iface
);
539 VTY_CHECK_CONTEXT(iface
);
541 ia
= iface_af_get(iface
, af
);
543 ia
->hello_holdtime
= 0;
545 ia
->hello_holdtime
= secs
;
547 ldp_config_apply(vty
, vty_conf
);
550 fatalx("ldp_vty_disc_holdtime: unexpected node");
553 return (CMD_SUCCESS
);
557 ldp_vty_disc_interval(struct vty
*vty
, int disable
, const char *hello_type_str
,
558 const char *seconds_str
)
560 struct ldpd_af_conf
*af_conf
;
566 enum hello_type hello_type
;
568 secs
= strtol(seconds_str
, &ep
, 10);
569 if (*ep
!= '\0' || secs
< MIN_HELLO_INTERVAL
||
570 secs
> MAX_HELLO_INTERVAL
) {
571 vty_out (vty
, "%% Invalid interval\n");
572 return (CMD_WARNING
);
575 if (hello_type_str
[0] == 'h')
576 hello_type
= HELLO_LINK
;
578 hello_type
= HELLO_TARGETED
;
583 switch (hello_type
) {
585 vty_conf
->lhello_interval
= LINK_DFLT_HOLDTIME
;
588 vty_conf
->thello_interval
=
589 TARGETED_DFLT_HOLDTIME
;
593 switch (hello_type
) {
595 vty_conf
->lhello_interval
= secs
;
598 vty_conf
->thello_interval
= secs
;
602 ldp_config_apply(vty
, vty_conf
);
606 af
= ldp_vty_get_af(vty
);
607 af_conf
= ldp_af_conf_get(vty_conf
, af
);
610 switch (hello_type
) {
612 af_conf
->lhello_interval
= 0;
615 af_conf
->thello_interval
= 0;
619 switch (hello_type
) {
621 af_conf
->lhello_interval
= secs
;
624 af_conf
->thello_interval
= secs
;
628 ldp_config_apply(vty
, vty_conf
);
630 case LDP_IPV4_IFACE_NODE
:
631 case LDP_IPV6_IFACE_NODE
:
632 af
= ldp_vty_get_af(vty
);
633 iface
= VTY_GET_CONTEXT(iface
);
634 VTY_CHECK_CONTEXT(iface
);
636 ia
= iface_af_get(iface
, af
);
638 ia
->hello_interval
= 0;
640 ia
->hello_interval
= secs
;
642 ldp_config_apply(vty
, vty_conf
);
645 fatalx("ldp_vty_disc_interval: unexpected node");
648 return (CMD_SUCCESS
);
652 ldp_vty_targeted_hello_accept(struct vty
*vty
, int disable
,
653 const char *acl_from_str
)
655 struct ldpd_af_conf
*af_conf
;
658 af
= ldp_vty_get_af(vty
);
659 af_conf
= ldp_af_conf_get(vty_conf
, af
);
662 af_conf
->flags
&= ~F_LDPD_AF_THELLO_ACCEPT
;
663 af_conf
->acl_thello_accept_from
[0] = '\0';
665 af_conf
->flags
|= F_LDPD_AF_THELLO_ACCEPT
;
667 strlcpy(af_conf
->acl_thello_accept_from
, acl_from_str
,
668 sizeof(af_conf
->acl_thello_accept_from
));
670 af_conf
->acl_thello_accept_from
[0] = '\0';
673 ldp_config_apply(vty
, vty_conf
);
675 return (CMD_SUCCESS
);
679 ldp_vty_nbr_session_holdtime(struct vty
*vty
, int disable
,
680 const char *lsr_id_str
, const char *seconds_str
)
684 struct in_addr lsr_id
;
685 struct nbr_params
*nbrp
;
687 if (inet_pton(AF_INET
, lsr_id_str
, &lsr_id
) != 1 ||
688 bad_addr_v4(lsr_id
)) {
689 vty_out (vty
, "%% Malformed address\n");
690 return (CMD_WARNING
);
693 secs
= strtol(seconds_str
, &ep
, 10);
694 if (*ep
!= '\0' || secs
< MIN_KEEPALIVE
|| secs
> MAX_KEEPALIVE
) {
695 vty_out (vty
, "%% Invalid holdtime\n");
696 return (CMD_SUCCESS
);
699 nbrp
= nbr_params_find(vty_conf
, lsr_id
);
703 return (CMD_SUCCESS
);
706 nbrp
->flags
&= ~F_NBRP_KEEPALIVE
;
709 nbrp
= nbr_params_new(lsr_id
);
710 RB_INSERT(nbrp_head
, &vty_conf
->nbrp_tree
, nbrp
);
711 QOBJ_REG(nbrp
, nbr_params
);
712 } else if (nbrp
->keepalive
== secs
)
713 return (CMD_SUCCESS
);
715 nbrp
->keepalive
= secs
;
716 nbrp
->flags
|= F_NBRP_KEEPALIVE
;
719 ldp_config_apply(vty
, vty_conf
);
721 return (CMD_SUCCESS
);
725 ldp_vty_af_session_holdtime(struct vty
*vty
, int disable
,
726 const char *seconds_str
)
728 struct ldpd_af_conf
*af_conf
;
733 secs
= strtol(seconds_str
, &ep
, 10);
734 if (*ep
!= '\0' || secs
< MIN_KEEPALIVE
|| secs
> MAX_KEEPALIVE
) {
735 vty_out (vty
, "%% Invalid holdtime\n");
736 return (CMD_SUCCESS
);
739 af
= ldp_vty_get_af(vty
);
740 af_conf
= ldp_af_conf_get(vty_conf
, af
);
743 af_conf
->keepalive
= DEFAULT_KEEPALIVE
;
745 af_conf
->keepalive
= secs
;
747 ldp_config_apply(vty
, vty_conf
);
749 return (CMD_SUCCESS
);
753 ldp_vty_interface(struct vty
*vty
, int disable
, const char *ifname
)
759 af
= ldp_vty_get_af(vty
);
760 iface
= if_lookup_name(vty_conf
, ifname
);
764 return (CMD_SUCCESS
);
766 ia
= iface_af_get(iface
, af
);
767 if (ia
->enabled
== 0)
768 return (CMD_SUCCESS
);
771 ia
->hello_holdtime
= 0;
772 ia
->hello_interval
= 0;
774 ldp_config_apply(vty
, vty_conf
);
776 return (CMD_SUCCESS
);
780 if (ldp_iface_is_configured(vty_conf
, ifname
)) {
781 vty_out (vty
,"%% Interface is already in use\n");
782 return (CMD_SUCCESS
);
785 iface
= if_new(ifname
);
786 ia
= iface_af_get(iface
, af
);
788 RB_INSERT(iface_head
, &vty_conf
->iface_tree
, iface
);
789 QOBJ_REG(iface
, iface
);
791 ldp_config_apply(vty
, vty_conf
);
793 ia
= iface_af_get(iface
, af
);
796 ldp_config_apply(vty
, vty_conf
);
802 VTY_PUSH_CONTEXT(LDP_IPV4_IFACE_NODE
, iface
);
805 VTY_PUSH_CONTEXT(LDP_IPV6_IFACE_NODE
, iface
);
811 return (CMD_SUCCESS
);
815 ldp_vty_trans_addr(struct vty
*vty
, int disable
, const char *addr_str
)
817 struct ldpd_af_conf
*af_conf
;
820 af
= ldp_vty_get_af(vty
);
821 af_conf
= ldp_af_conf_get(vty_conf
, af
);
824 memset(&af_conf
->trans_addr
, 0, sizeof(af_conf
->trans_addr
));
826 if (inet_pton(af
, addr_str
, &af_conf
->trans_addr
) != 1 ||
827 bad_addr(af
, &af_conf
->trans_addr
)) {
828 vty_out (vty
, "%% Malformed address\n");
829 return (CMD_SUCCESS
);
833 ldp_config_apply(vty
, vty_conf
);
835 return (CMD_SUCCESS
);
839 ldp_vty_neighbor_targeted(struct vty
*vty
, int disable
, const char *addr_str
)
842 union ldpd_addr addr
;
845 af
= ldp_vty_get_af(vty
);
847 if (inet_pton(af
, addr_str
, &addr
) != 1 ||
848 bad_addr(af
, &addr
)) {
849 vty_out (vty
, "%% Malformed address\n");
850 return (CMD_WARNING
);
852 if (af
== AF_INET6
&& IN6_IS_SCOPE_EMBED(&addr
.v6
)) {
853 vty_out (vty
, "%% Address can not be link-local\n");
854 return (CMD_WARNING
);
857 tnbr
= tnbr_find(vty_conf
, af
, &addr
);
861 return (CMD_SUCCESS
);
864 RB_REMOVE(tnbr_head
, &vty_conf
->tnbr_tree
, tnbr
);
867 ldp_config_apply(vty
, vty_conf
);
869 return (CMD_SUCCESS
);
873 return (CMD_SUCCESS
);
875 tnbr
= tnbr_new(af
, &addr
);
876 tnbr
->flags
|= F_TNBR_CONFIGURED
;
877 RB_INSERT(tnbr_head
, &vty_conf
->tnbr_tree
, tnbr
);
878 QOBJ_REG(tnbr
, tnbr
);
880 ldp_config_apply(vty
, vty_conf
);
882 return (CMD_SUCCESS
);
886 ldp_vty_label_advertise(struct vty
*vty
, int disable
, const char *acl_to_str
,
887 const char *acl_for_str
)
889 struct ldpd_af_conf
*af_conf
;
892 af
= ldp_vty_get_af(vty
);
893 af_conf
= ldp_af_conf_get(vty_conf
, af
);
896 af_conf
->acl_label_advertise_to
[0] = '\0';
897 af_conf
->acl_label_advertise_for
[0] = '\0';
900 strlcpy(af_conf
->acl_label_advertise_to
, acl_to_str
,
901 sizeof(af_conf
->acl_label_advertise_to
));
903 af_conf
->acl_label_advertise_to
[0] = '\0';
905 strlcpy(af_conf
->acl_label_advertise_for
, acl_for_str
,
906 sizeof(af_conf
->acl_label_advertise_for
));
908 af_conf
->acl_label_advertise_for
[0] = '\0';
911 ldp_config_apply(vty
, vty_conf
);
913 return (CMD_SUCCESS
);
917 ldp_vty_label_allocate(struct vty
*vty
, int disable
, int host_routes
,
918 const char *acl_for_str
)
920 struct ldpd_af_conf
*af_conf
;
923 af
= ldp_vty_get_af(vty
);
924 af_conf
= ldp_af_conf_get(vty_conf
, af
);
926 af_conf
->flags
&= ~F_LDPD_AF_ALLOCHOSTONLY
;
927 af_conf
->acl_label_allocate_for
[0] = '\0';
930 af_conf
->flags
|= F_LDPD_AF_ALLOCHOSTONLY
;
932 strlcpy(af_conf
->acl_label_allocate_for
, acl_for_str
,
933 sizeof(af_conf
->acl_label_allocate_for
));
936 ldp_config_apply(vty
, vty_conf
);
938 return (CMD_SUCCESS
);
942 ldp_vty_label_expnull(struct vty
*vty
, int disable
, const char *acl_for_str
)
944 struct ldpd_af_conf
*af_conf
;
947 af
= ldp_vty_get_af(vty
);
948 af_conf
= ldp_af_conf_get(vty_conf
, af
);
951 af_conf
->flags
&= ~F_LDPD_AF_EXPNULL
;
952 af_conf
->acl_label_expnull_for
[0] = '\0';
954 af_conf
->flags
|= F_LDPD_AF_EXPNULL
;
956 strlcpy(af_conf
->acl_label_expnull_for
, acl_for_str
,
957 sizeof(af_conf
->acl_label_expnull_for
));
959 af_conf
->acl_label_expnull_for
[0] = '\0';
962 ldp_config_apply(vty
, vty_conf
);
964 return (CMD_SUCCESS
);
968 ldp_vty_label_accept(struct vty
*vty
, int disable
, const char *acl_from_str
,
969 const char *acl_for_str
)
971 struct ldpd_af_conf
*af_conf
;
974 af
= ldp_vty_get_af(vty
);
975 af_conf
= ldp_af_conf_get(vty_conf
, af
);
978 af_conf
->acl_label_accept_from
[0] = '\0';
979 af_conf
->acl_label_accept_for
[0] = '\0';
982 strlcpy(af_conf
->acl_label_accept_from
, acl_from_str
,
983 sizeof(af_conf
->acl_label_accept_from
));
985 af_conf
->acl_label_accept_from
[0] = '\0';
987 strlcpy(af_conf
->acl_label_accept_for
, acl_for_str
,
988 sizeof(af_conf
->acl_label_accept_for
));
990 af_conf
->acl_label_accept_for
[0] = '\0';
993 ldp_config_apply(vty
, vty_conf
);
995 return (CMD_SUCCESS
);
999 ldp_vty_ttl_security(struct vty
*vty
, int disable
)
1001 struct ldpd_af_conf
*af_conf
;
1004 af
= ldp_vty_get_af(vty
);
1005 af_conf
= ldp_af_conf_get(vty_conf
, af
);
1008 af_conf
->flags
&= ~F_LDPD_AF_NO_GTSM
;
1010 af_conf
->flags
|= F_LDPD_AF_NO_GTSM
;
1012 ldp_config_apply(vty
, vty_conf
);
1014 return (CMD_SUCCESS
);
1018 ldp_vty_router_id(struct vty
*vty
, int disable
, const char *addr_str
)
1021 vty_conf
->rtr_id
.s_addr
= INADDR_ANY
;
1023 if (inet_pton(AF_INET
, addr_str
, &vty_conf
->rtr_id
) != 1 ||
1024 bad_addr_v4(vty_conf
->rtr_id
)) {
1025 vty_out (vty
, "%% Malformed address\n");
1026 return (CMD_SUCCESS
);
1030 ldp_config_apply(vty
, vty_conf
);
1032 return (CMD_SUCCESS
);
1036 ldp_vty_ds_cisco_interop(struct vty
*vty
, int disable
)
1039 vty_conf
->flags
&= ~F_LDPD_DS_CISCO_INTEROP
;
1041 vty_conf
->flags
|= F_LDPD_DS_CISCO_INTEROP
;
1043 ldp_config_apply(vty
, vty_conf
);
1045 return (CMD_SUCCESS
);
1049 ldp_vty_trans_pref_ipv4(struct vty
*vty
, int disable
)
1052 vty_conf
->trans_pref
= DUAL_STACK_LDPOV6
;
1054 vty_conf
->trans_pref
= DUAL_STACK_LDPOV4
;
1056 ldp_config_apply(vty
, vty_conf
);
1058 return (CMD_SUCCESS
);
1062 ldp_vty_neighbor_password(struct vty
*vty
, int disable
, const char *lsr_id_str
,
1063 const char *password_str
)
1065 struct in_addr lsr_id
;
1066 size_t password_len
;
1067 struct nbr_params
*nbrp
;
1069 if (inet_pton(AF_INET
, lsr_id_str
, &lsr_id
) != 1 ||
1070 bad_addr_v4(lsr_id
)) {
1071 vty_out (vty
, "%% Malformed address\n");
1072 return (CMD_WARNING
);
1075 nbrp
= nbr_params_find(vty_conf
, lsr_id
);
1079 return (CMD_SUCCESS
);
1081 memset(&nbrp
->auth
, 0, sizeof(nbrp
->auth
));
1082 nbrp
->auth
.method
= AUTH_NONE
;
1085 nbrp
= nbr_params_new(lsr_id
);
1086 RB_INSERT(nbrp_head
, &vty_conf
->nbrp_tree
, nbrp
);
1087 QOBJ_REG(nbrp
, nbr_params
);
1088 } else if (nbrp
->auth
.method
== AUTH_MD5SIG
&&
1089 strcmp(nbrp
->auth
.md5key
, password_str
) == 0)
1090 return (CMD_SUCCESS
);
1092 password_len
= strlcpy(nbrp
->auth
.md5key
, password_str
,
1093 sizeof(nbrp
->auth
.md5key
));
1094 if (password_len
>= sizeof(nbrp
->auth
.md5key
))
1095 vty_out(vty
, "%% password has been truncated to %zu "
1096 "characters.", sizeof(nbrp
->auth
.md5key
) - 1);
1097 nbrp
->auth
.md5key_len
= password_len
;
1098 nbrp
->auth
.method
= AUTH_MD5SIG
;
1101 ldp_config_apply(vty
, vty_conf
);
1103 return (CMD_SUCCESS
);
1107 ldp_vty_neighbor_ttl_security(struct vty
*vty
, int disable
,
1108 const char *lsr_id_str
, const char *hops_str
)
1110 struct in_addr lsr_id
;
1111 struct nbr_params
*nbrp
;
1115 if (inet_pton(AF_INET
, lsr_id_str
, &lsr_id
) != 1 ||
1116 bad_addr_v4(lsr_id
)) {
1117 vty_out (vty
, "%% Malformed address\n");
1118 return (CMD_WARNING
);
1122 hops
= strtol(hops_str
, &ep
, 10);
1123 if (*ep
!= '\0' || hops
< 1 || hops
> 254) {
1124 vty_out (vty
, "%% Invalid hop count\n");
1125 return (CMD_SUCCESS
);
1129 nbrp
= nbr_params_find(vty_conf
, lsr_id
);
1133 return (CMD_SUCCESS
);
1135 nbrp
->flags
&= ~(F_NBRP_GTSM
|F_NBRP_GTSM_HOPS
);
1136 nbrp
->gtsm_enabled
= 0;
1137 nbrp
->gtsm_hops
= 0;
1140 nbrp
= nbr_params_new(lsr_id
);
1141 RB_INSERT(nbrp_head
, &vty_conf
->nbrp_tree
, nbrp
);
1142 QOBJ_REG(nbrp
, nbr_params
);
1145 nbrp
->flags
|= F_NBRP_GTSM
;
1146 nbrp
->flags
&= ~F_NBRP_GTSM_HOPS
;
1148 nbrp
->gtsm_enabled
= 1;
1149 nbrp
->gtsm_hops
= hops
;
1150 nbrp
->flags
|= F_NBRP_GTSM_HOPS
;
1152 nbrp
->gtsm_enabled
= 0;
1155 ldp_config_apply(vty
, vty_conf
);
1157 return (CMD_SUCCESS
);
1161 ldp_vty_l2vpn(struct vty
*vty
, int disable
, const char *name_str
)
1163 struct l2vpn
*l2vpn
;
1164 struct l2vpn_if
*lif
;
1165 struct l2vpn_pw
*pw
;
1167 l2vpn
= l2vpn_find(vty_conf
, name_str
);
1171 return (CMD_SUCCESS
);
1173 RB_FOREACH(lif
, l2vpn_if_head
, &l2vpn
->if_tree
)
1175 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_tree
)
1177 RB_FOREACH(pw
, l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
)
1180 RB_REMOVE(l2vpn_head
, &vty_conf
->l2vpn_tree
, l2vpn
);
1183 ldp_config_apply(vty
, vty_conf
);
1185 return (CMD_SUCCESS
);
1189 VTY_PUSH_CONTEXT(LDP_L2VPN_NODE
, l2vpn
);
1190 return (CMD_SUCCESS
);
1193 l2vpn
= l2vpn_new(name_str
);
1194 l2vpn
->type
= L2VPN_TYPE_VPLS
;
1195 RB_INSERT(l2vpn_head
, &vty_conf
->l2vpn_tree
, l2vpn
);
1196 QOBJ_REG(l2vpn
, l2vpn
);
1198 VTY_PUSH_CONTEXT(LDP_L2VPN_NODE
, l2vpn
);
1200 ldp_config_apply(vty
, vty_conf
);
1202 return (CMD_SUCCESS
);
1206 ldp_vty_l2vpn_bridge(struct vty
*vty
, int disable
, const char *ifname
)
1208 VTY_DECLVAR_CONTEXT(l2vpn
, l2vpn
);
1211 memset(l2vpn
->br_ifname
, 0, sizeof(l2vpn
->br_ifname
));
1213 strlcpy(l2vpn
->br_ifname
, ifname
, sizeof(l2vpn
->br_ifname
));
1215 ldp_config_apply(vty
, vty_conf
);
1217 return (CMD_SUCCESS
);
1221 ldp_vty_l2vpn_mtu(struct vty
*vty
, int disable
, const char *mtu_str
)
1223 VTY_DECLVAR_CONTEXT(l2vpn
, l2vpn
);
1227 mtu
= strtol(mtu_str
, &ep
, 10);
1228 if (*ep
!= '\0' || mtu
< MIN_L2VPN_MTU
|| mtu
> MAX_L2VPN_MTU
) {
1229 vty_out (vty
, "%% Invalid MTU\n");
1230 return (CMD_WARNING
);
1234 l2vpn
->mtu
= DEFAULT_L2VPN_MTU
;
1238 ldp_config_apply(vty
, vty_conf
);
1240 return (CMD_SUCCESS
);
1244 ldp_vty_l2vpn_pwtype(struct vty
*vty
, int disable
, const char *type_str
)
1246 VTY_DECLVAR_CONTEXT(l2vpn
, l2vpn
);
1249 if (strcmp(type_str
, "ethernet") == 0)
1250 pw_type
= PW_TYPE_ETHERNET
;
1252 pw_type
= PW_TYPE_ETHERNET_TAGGED
;
1255 l2vpn
->pw_type
= DEFAULT_PW_TYPE
;
1257 l2vpn
->pw_type
= pw_type
;
1259 ldp_config_apply(vty
, vty_conf
);
1261 return (CMD_SUCCESS
);
1265 ldp_vty_l2vpn_interface(struct vty
*vty
, int disable
, const char *ifname
)
1267 VTY_DECLVAR_CONTEXT(l2vpn
, l2vpn
);
1268 struct l2vpn_if
*lif
;
1270 lif
= l2vpn_if_find(l2vpn
, ifname
);
1274 return (CMD_SUCCESS
);
1277 RB_REMOVE(l2vpn_if_head
, &l2vpn
->if_tree
, lif
);
1280 ldp_config_apply(vty
, vty_conf
);
1282 return (CMD_SUCCESS
);
1286 return (CMD_SUCCESS
);
1288 if (ldp_iface_is_configured(vty_conf
, ifname
)) {
1289 vty_out (vty
, "%% Interface is already in use\n");
1290 return (CMD_SUCCESS
);
1293 lif
= l2vpn_if_new(l2vpn
, ifname
);
1294 RB_INSERT(l2vpn_if_head
, &l2vpn
->if_tree
, lif
);
1295 QOBJ_REG(lif
, l2vpn_if
);
1297 ldp_config_apply(vty
, vty_conf
);
1299 return (CMD_SUCCESS
);
1303 ldp_vty_l2vpn_pseudowire(struct vty
*vty
, int disable
, const char *ifname
)
1305 VTY_DECLVAR_CONTEXT(l2vpn
, l2vpn
);
1306 struct l2vpn_pw
*pw
;
1308 pw
= l2vpn_pw_find(l2vpn
, ifname
);
1312 return (CMD_SUCCESS
);
1315 if (pw
->lsr_id
.s_addr
== INADDR_ANY
|| pw
->pwid
== 0)
1316 RB_REMOVE(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, pw
);
1318 RB_REMOVE(l2vpn_pw_head
, &l2vpn
->pw_tree
, pw
);
1321 ldp_config_apply(vty
, vty_conf
);
1323 return (CMD_SUCCESS
);
1327 VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE
, pw
);
1328 return (CMD_SUCCESS
);
1331 if (ldp_iface_is_configured(vty_conf
, ifname
)) {
1332 vty_out (vty
, "%% Interface is already in use\n");
1333 return (CMD_SUCCESS
);
1336 pw
= l2vpn_pw_new(l2vpn
, ifname
);
1337 pw
->flags
= F_PW_STATUSTLV_CONF
|F_PW_CWORD_CONF
;
1338 RB_INSERT(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, pw
);
1339 QOBJ_REG(pw
, l2vpn_pw
);
1341 VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE
, pw
);
1343 ldp_config_apply(vty
, vty_conf
);
1345 return (CMD_SUCCESS
);
1349 ldp_vty_l2vpn_pw_cword(struct vty
*vty
, int disable
, const char *preference_str
)
1351 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw
, pw
);
1354 pw
->flags
|= F_PW_CWORD_CONF
;
1356 if (preference_str
[0] == 'e')
1357 pw
->flags
&= ~F_PW_CWORD_CONF
;
1359 pw
->flags
|= F_PW_CWORD_CONF
;
1362 ldp_config_apply(vty
, vty_conf
);
1364 return (CMD_SUCCESS
);
1368 ldp_vty_l2vpn_pw_nbr_addr(struct vty
*vty
, int disable
, const char *addr_str
)
1370 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw
, pw
);
1372 union ldpd_addr addr
;
1374 if (ldp_get_address(addr_str
, &af
, &addr
) == -1 ||
1375 bad_addr(af
, &addr
)) {
1376 vty_out (vty
, "%% Malformed address\n");
1377 return (CMD_WARNING
);
1382 memset(&pw
->addr
, 0, sizeof(pw
->addr
));
1383 pw
->flags
&= ~F_PW_STATIC_NBR_ADDR
;
1387 pw
->flags
|= F_PW_STATIC_NBR_ADDR
;
1390 ldp_config_apply(vty
, vty_conf
);
1392 return (CMD_SUCCESS
);
1396 ldp_vty_l2vpn_pw_nbr_id(struct vty
*vty
, int disable
, const char *lsr_id_str
)
1398 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw
, pw
);
1399 struct in_addr lsr_id
;
1401 if (inet_pton(AF_INET
, lsr_id_str
, &lsr_id
) != 1 ||
1402 bad_addr_v4(lsr_id
)) {
1403 vty_out (vty
, "%% Malformed address\n");
1404 return (CMD_WARNING
);
1408 pw
->lsr_id
.s_addr
= INADDR_ANY
;
1410 pw
->lsr_id
= lsr_id
;
1412 ldp_config_apply(vty
, vty_conf
);
1414 return (CMD_SUCCESS
);
1418 ldp_vty_l2vpn_pw_pwid(struct vty
*vty
, int disable
, const char *pwid_str
)
1420 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw
, pw
);
1424 pwid
= strtol(pwid_str
, &ep
, 10);
1425 if (*ep
!= '\0' || pwid
< MIN_PWID_ID
|| pwid
> MAX_PWID_ID
) {
1426 vty_out (vty
, "%% Invalid pw-id\n");
1427 return (CMD_WARNING
);
1435 ldp_config_apply(vty
, vty_conf
);
1437 return (CMD_SUCCESS
);
1441 ldp_vty_l2vpn_pw_pwstatus(struct vty
*vty
, int disable
)
1443 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw
, pw
);
1446 pw
->flags
|= F_PW_STATUSTLV_CONF
;
1448 pw
->flags
&= ~F_PW_STATUSTLV_CONF
;
1450 ldp_config_apply(vty
, vty_conf
);
1452 return (CMD_SUCCESS
);
1456 iface_new_api(struct ldpd_conf
*conf
, const char *name
)
1458 const char *ifname
= name
;
1459 struct iface
*iface
;
1461 if (ldp_iface_is_configured(conf
, ifname
))
1464 iface
= if_new(name
);
1465 RB_INSERT(iface_head
, &conf
->iface_tree
, iface
);
1466 QOBJ_REG(iface
, iface
);
1471 iface_del_api(struct ldpd_conf
*conf
, struct iface
*iface
)
1474 RB_REMOVE(iface_head
, &conf
->iface_tree
, iface
);
1479 tnbr_new_api(struct ldpd_conf
*conf
, int af
, union ldpd_addr
*addr
)
1483 if (af
== AF_INET6
&& IN6_IS_SCOPE_EMBED(&addr
->v6
))
1486 if (tnbr_find(conf
, af
, addr
))
1489 tnbr
= tnbr_new(af
, addr
);
1490 tnbr
->flags
|= F_TNBR_CONFIGURED
;
1491 RB_INSERT(tnbr_head
, &conf
->tnbr_tree
, tnbr
);
1492 QOBJ_REG(tnbr
, tnbr
);
1497 tnbr_del_api(struct ldpd_conf
*conf
, struct tnbr
*tnbr
)
1500 RB_REMOVE(tnbr_head
, &conf
->tnbr_tree
, tnbr
);
1505 nbrp_new_api(struct ldpd_conf
*conf
, struct in_addr lsr_id
)
1507 struct nbr_params
*nbrp
;
1509 if (nbr_params_find(conf
, lsr_id
))
1512 nbrp
= nbr_params_new(lsr_id
);
1513 RB_INSERT(nbrp_head
, &conf
->nbrp_tree
, nbrp
);
1514 QOBJ_REG(nbrp
, nbr_params
);
1519 nbrp_del_api(struct ldpd_conf
*conf
, struct nbr_params
*nbrp
)
1522 RB_REMOVE(nbrp_head
, &conf
->nbrp_tree
, nbrp
);
1527 l2vpn_new_api(struct ldpd_conf
*conf
, const char *name
)
1529 struct l2vpn
*l2vpn
;
1531 if (l2vpn_find(conf
, name
))
1534 l2vpn
= l2vpn_new(name
);
1535 l2vpn
->type
= L2VPN_TYPE_VPLS
;
1536 RB_INSERT(l2vpn_head
, &conf
->l2vpn_tree
, l2vpn
);
1537 QOBJ_REG(l2vpn
, l2vpn
);
1542 l2vpn_del_api(struct ldpd_conf
*conf
, struct l2vpn
*l2vpn
)
1544 struct l2vpn_if
*lif
;
1545 struct l2vpn_pw
*pw
;
1547 while ((lif
= RB_ROOT(l2vpn_if_head
, &l2vpn
->if_tree
)) != NULL
) {
1549 RB_REMOVE(l2vpn_if_head
, &l2vpn
->if_tree
, lif
);
1552 while ((pw
= RB_ROOT(l2vpn_pw_head
, &l2vpn
->pw_tree
)) != NULL
) {
1554 RB_REMOVE(l2vpn_pw_head
, &l2vpn
->pw_tree
, pw
);
1557 while ((pw
= RB_ROOT(l2vpn_pw_head
,
1558 &l2vpn
->pw_inactive_tree
)) != NULL
) {
1560 RB_REMOVE(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, pw
);
1564 RB_REMOVE(l2vpn_head
, &conf
->l2vpn_tree
, l2vpn
);
1569 l2vpn_if_new_api(struct ldpd_conf
*conf
, struct l2vpn
*l2vpn
,
1572 struct l2vpn_if
*lif
;
1574 if (ldp_iface_is_configured(conf
, ifname
))
1577 lif
= l2vpn_if_new(l2vpn
, ifname
);
1578 RB_INSERT(l2vpn_if_head
, &l2vpn
->if_tree
, lif
);
1579 QOBJ_REG(lif
, l2vpn_if
);
1584 l2vpn_if_del_api(struct l2vpn
*l2vpn
, struct l2vpn_if
*lif
)
1587 RB_REMOVE(l2vpn_if_head
, &l2vpn
->if_tree
, lif
);
1592 l2vpn_pw_new_api(struct ldpd_conf
*conf
, struct l2vpn
*l2vpn
,
1595 struct l2vpn_pw
*pw
;
1597 if (ldp_iface_is_configured(conf
, ifname
))
1600 pw
= l2vpn_pw_new(l2vpn
, ifname
);
1601 pw
->flags
= F_PW_STATUSTLV_CONF
|F_PW_CWORD_CONF
;
1602 RB_INSERT(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, pw
);
1603 QOBJ_REG(pw
, l2vpn_pw
);
1608 l2vpn_pw_del_api(struct l2vpn
*l2vpn
, struct l2vpn_pw
*pw
)
1611 RB_REMOVE(l2vpn_pw_head
, &l2vpn
->pw_inactive_tree
, pw
);