]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/ldp_vty_conf.c
Merge pull request #5985 from Naveenaidu/5984-cleanup-is_selfroute
[mirror_frr.git] / ldpd / ldp_vty_conf.c
CommitLineData
eac6e3f0
RW
1/*
2 * Copyright (C) 2016 by Open Source Routing.
3 *
180fc2cd
RW
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.
eac6e3f0 8 *
180fc2cd 9 * This program is distributed in the hope that it will be useful, but
eac6e3f0
RW
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.
13 *
180fc2cd
RW
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,
17 * MA 02110-1301 USA
eac6e3f0
RW
18 */
19
20#include <zebra.h>
21
22#include "ldpd.h"
23#include "ldpe.h"
24#include "lde.h"
25#include "log.h"
26
27#include "command.h"
28#include "vrf.h"
29#include "if.h"
30#include "vty.h"
31#include "ldp_vty.h"
32
eac6e3f0
RW
33static void ldp_af_iface_config_write(struct vty *, int);
34static void ldp_af_config_write(struct vty *, int, struct ldpd_conf *,
35 struct ldpd_af_conf *);
36static void ldp_l2vpn_pw_config_write(struct vty *, struct l2vpn_pw *);
37static int ldp_vty_get_af(struct vty *);
38static int ldp_iface_is_configured(struct ldpd_conf *, const char *);
eac6e3f0 39
eac6e3f0
RW
40struct cmd_node ldp_node =
41{
42 LDP_NODE,
43 "%s(config-ldp)# ",
44 1,
45};
46
47struct cmd_node ldp_ipv4_node =
48{
49 LDP_IPV4_NODE,
50 "%s(config-ldp-af)# ",
51 1,
52};
53
54struct cmd_node ldp_ipv6_node =
55{
56 LDP_IPV6_NODE,
57 "%s(config-ldp-af)# ",
58 1,
59};
60
61struct cmd_node ldp_ipv4_iface_node =
62{
63 LDP_IPV4_IFACE_NODE,
64 "%s(config-ldp-af-if)# ",
65 1,
66};
67
68struct cmd_node ldp_ipv6_iface_node =
69{
70 LDP_IPV6_IFACE_NODE,
71 "%s(config-ldp-af-if)# ",
72 1,
73};
74
75struct cmd_node ldp_l2vpn_node =
76{
77 LDP_L2VPN_NODE,
78 "%s(config-l2vpn)# ",
79 1,
80};
81
82struct cmd_node ldp_pseudowire_node =
83{
84 LDP_PSEUDOWIRE_NODE,
85 "%s(config-l2vpn-pw)# ",
86 1,
87};
88
89int
90ldp_get_address(const char *str, int *af, union ldpd_addr *addr)
91{
0ef34ac5 92 if (!str || !af || !addr)
93 return (-1);
94
eac6e3f0
RW
95 memset(addr, 0, sizeof(*addr));
96
97 if (inet_pton(AF_INET, str, &addr->v4) == 1) {
98 *af = AF_INET;
99 return (0);
100 }
101
102 if (inet_pton(AF_INET6, str, &addr->v6) == 1) {
103 *af = AF_INET6;
104 return (0);
105 }
106
107 return (-1);
108}
109
eac6e3f0
RW
110static void
111ldp_af_iface_config_write(struct vty *vty, int af)
112{
113 struct iface *iface;
114 struct iface_af *ia;
115
7d3d7491 116 RB_FOREACH(iface, iface_head, &ldpd_conf->iface_tree) {
eac6e3f0
RW
117 ia = iface_af_get(iface, af);
118 if (!ia->enabled)
119 continue;
120
5c7571d4
DL
121 vty_out (vty, " !\n");
122 vty_out (vty, " interface %s\n", iface->name);
eac6e3f0
RW
123
124 if (ia->hello_holdtime != LINK_DFLT_HOLDTIME &&
125 ia->hello_holdtime != 0)
5c7571d4 126 vty_out (vty, " discovery hello holdtime %u\n",
96ade3ed 127 ia->hello_holdtime);
eac6e3f0
RW
128 if (ia->hello_interval != DEFAULT_HELLO_INTERVAL &&
129 ia->hello_interval != 0)
5c7571d4 130 vty_out (vty, " discovery hello interval %u\n",
96ade3ed 131 ia->hello_interval);
eac6e3f0
RW
132 }
133}
134
135static void
136ldp_af_config_write(struct vty *vty, int af, struct ldpd_conf *conf,
137 struct ldpd_af_conf *af_conf)
138{
139 struct tnbr *tnbr;
140
141 if (!(af_conf->flags & F_LDPD_AF_ENABLED))
142 return;
143
5c7571d4
DL
144 vty_out (vty, " !\n");
145 vty_out (vty, " address-family %s\n", af_name(af));
eac6e3f0
RW
146
147 if (af_conf->lhello_holdtime != LINK_DFLT_HOLDTIME &&
148 af_conf->lhello_holdtime != 0 )
5c7571d4 149 vty_out (vty, " discovery hello holdtime %u\n",
96ade3ed 150 af_conf->lhello_holdtime);
eac6e3f0
RW
151 if (af_conf->lhello_interval != DEFAULT_HELLO_INTERVAL &&
152 af_conf->lhello_interval != 0)
5c7571d4 153 vty_out (vty, " discovery hello interval %u\n",
96ade3ed 154 af_conf->lhello_interval);
eac6e3f0 155
45a8eba9
RW
156 if (af_conf->flags & F_LDPD_AF_THELLO_ACCEPT) {
157 vty_out(vty, " discovery targeted-hello accept");
158 if (af_conf->acl_thello_accept_from[0] != '\0')
159 vty_out(vty, " from %s",
160 af_conf->acl_thello_accept_from);
6d3c2ed4 161 vty_out (vty, "\n");
45a8eba9 162 }
eac6e3f0
RW
163
164 if (af_conf->thello_holdtime != TARGETED_DFLT_HOLDTIME &&
165 af_conf->thello_holdtime != 0)
5c7571d4 166 vty_out (vty, " discovery targeted-hello holdtime %u\n",
96ade3ed 167 af_conf->thello_holdtime);
eac6e3f0
RW
168 if (af_conf->thello_interval != DEFAULT_HELLO_INTERVAL &&
169 af_conf->thello_interval != 0)
5c7571d4 170 vty_out (vty, " discovery targeted-hello interval %u\n",
96ade3ed 171 af_conf->thello_interval);
eac6e3f0
RW
172
173 if (ldp_addrisset(af, &af_conf->trans_addr))
5c7571d4 174 vty_out (vty, " discovery transport-address %s\n",
96ade3ed
QY
175 log_addr(af, &af_conf->trans_addr));
176 else
181039f3
DL
177 vty_out (vty,
178 " ! Incomplete config, specify a discovery transport-address\n");
eac6e3f0 179
45a8eba9
RW
180 if ((af_conf->flags & F_LDPD_AF_ALLOCHOSTONLY) ||
181 af_conf->acl_label_allocate_for[0] != '\0') {
182 vty_out(vty, " label local allocate");
183 if (af_conf->flags & F_LDPD_AF_ALLOCHOSTONLY)
184 vty_out(vty, " host-routes");
185 else
186 vty_out(vty, " for %s",
187 af_conf->acl_label_allocate_for);
6d3c2ed4 188 vty_out (vty, "\n");
45a8eba9
RW
189 }
190
191 if (af_conf->acl_label_advertise_for[0] != '\0' ||
192 af_conf->acl_label_advertise_to[0] != '\0') {
193 vty_out(vty, " label local advertise");
194 if (af_conf->acl_label_advertise_to[0] != '\0')
195 vty_out(vty, " to %s",
196 af_conf->acl_label_advertise_to);
197 if (af_conf->acl_label_advertise_for[0] != '\0')
198 vty_out(vty, " for %s",
199 af_conf->acl_label_advertise_for);
6d3c2ed4 200 vty_out (vty, "\n");
45a8eba9
RW
201 }
202
203 if (af_conf->flags & F_LDPD_AF_EXPNULL) {
204 vty_out(vty, " label local advertise explicit-null");
205 if (af_conf->acl_label_expnull_for[0] != '\0')
206 vty_out(vty, " for %s",
207 af_conf->acl_label_expnull_for);
6d3c2ed4 208 vty_out (vty, "\n");
45a8eba9
RW
209 }
210
211 if (af_conf->acl_label_accept_for[0] != '\0' ||
212 af_conf->acl_label_accept_from[0] != '\0') {
213 vty_out(vty, " label remote accept");
214 if (af_conf->acl_label_accept_from[0] != '\0')
215 vty_out(vty, " from %s",
216 af_conf->acl_label_accept_from);
217 if (af_conf->acl_label_accept_for[0] != '\0')
218 vty_out(vty, " for %s",
219 af_conf->acl_label_accept_for);
6d3c2ed4 220 vty_out (vty, "\n");
45a8eba9 221 }
eac6e3f0
RW
222
223 if (af_conf->flags & F_LDPD_AF_NO_GTSM)
5c7571d4 224 vty_out (vty, " ttl-security disable\n");
eac6e3f0
RW
225
226 if (af_conf->keepalive != DEFAULT_KEEPALIVE)
5c7571d4 227 vty_out (vty, " session holdtime %u\n",af_conf->keepalive);
eac6e3f0 228
7989cdba 229 RB_FOREACH(tnbr, tnbr_head, &ldpd_conf->tnbr_tree) {
eac6e3f0 230 if (tnbr->af == af) {
5c7571d4
DL
231 vty_out (vty, " !\n");
232 vty_out (vty, " neighbor %s targeted\n",
96ade3ed 233 log_addr(tnbr->af, &tnbr->addr));
eac6e3f0
RW
234 }
235 }
236
237 ldp_af_iface_config_write(vty, af);
238
3b2d98c5 239 vty_out(vty, " !\n");
983bd6f7 240 vty_out(vty, " exit-address-family\n");
eac6e3f0
RW
241}
242
243int
244ldp_config_write(struct vty *vty)
245{
246 struct nbr_params *nbrp;
247
248 if (!(ldpd_conf->flags & F_LDPD_ENABLED))
249 return (0);
250
5c7571d4 251 vty_out (vty, "mpls ldp\n");
eac6e3f0 252
975a328e
DA
253 if (ldpd_conf->rtr_id.s_addr != INADDR_ANY)
254 vty_out(vty, " router-id %s\n", inet_ntoa(ldpd_conf->rtr_id));
eac6e3f0
RW
255
256 if (ldpd_conf->lhello_holdtime != LINK_DFLT_HOLDTIME &&
257 ldpd_conf->lhello_holdtime != 0)
5c7571d4 258 vty_out (vty, " discovery hello holdtime %u\n",
96ade3ed 259 ldpd_conf->lhello_holdtime);
eac6e3f0
RW
260 if (ldpd_conf->lhello_interval != DEFAULT_HELLO_INTERVAL &&
261 ldpd_conf->lhello_interval != 0)
5c7571d4 262 vty_out (vty, " discovery hello interval %u\n",
96ade3ed 263 ldpd_conf->lhello_interval);
eac6e3f0
RW
264
265 if (ldpd_conf->thello_holdtime != TARGETED_DFLT_HOLDTIME &&
266 ldpd_conf->thello_holdtime != 0)
5c7571d4 267 vty_out (vty, " discovery targeted-hello holdtime %u\n",
96ade3ed 268 ldpd_conf->thello_holdtime);
eac6e3f0
RW
269 if (ldpd_conf->thello_interval != DEFAULT_HELLO_INTERVAL &&
270 ldpd_conf->thello_interval != 0)
5c7571d4 271 vty_out (vty, " discovery targeted-hello interval %u\n",
96ade3ed 272 ldpd_conf->thello_interval);
eac6e3f0
RW
273
274 if (ldpd_conf->trans_pref == DUAL_STACK_LDPOV4)
5c7571d4
DL
275 vty_out (vty,
276 " dual-stack transport-connection prefer ipv4\n");
eac6e3f0
RW
277
278 if (ldpd_conf->flags & F_LDPD_DS_CISCO_INTEROP)
5c7571d4 279 vty_out (vty, " dual-stack cisco-interop\n");
eac6e3f0 280
76c4abd1 281 RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) {
eac6e3f0 282 if (nbrp->flags & F_NBRP_KEEPALIVE)
5c7571d4 283 vty_out (vty, " neighbor %s session holdtime %u\n",
96ade3ed 284 inet_ntoa(nbrp->lsr_id),nbrp->keepalive);
eac6e3f0
RW
285
286 if (nbrp->flags & F_NBRP_GTSM) {
287 if (nbrp->gtsm_enabled)
181039f3
DL
288 vty_out (vty, " neighbor %s ttl-security hops "
289 "%u\n", inet_ntoa(nbrp->lsr_id),
96ade3ed 290 nbrp->gtsm_hops);
eac6e3f0 291 else
181039f3
DL
292 vty_out (vty, " neighbor %s ttl-security "
293 "disable\n",inet_ntoa(nbrp->lsr_id));
eac6e3f0
RW
294 }
295
296 if (nbrp->auth.method == AUTH_MD5SIG)
5c7571d4 297 vty_out (vty, " neighbor %s password %s\n",
96ade3ed 298 inet_ntoa(nbrp->lsr_id),nbrp->auth.md5key);
eac6e3f0
RW
299 }
300
301 ldp_af_config_write(vty, AF_INET, ldpd_conf, &ldpd_conf->ipv4);
302 ldp_af_config_write(vty, AF_INET6, ldpd_conf, &ldpd_conf->ipv6);
5c7571d4
DL
303 vty_out (vty, " !\n");
304 vty_out (vty, "!\n");
eac6e3f0
RW
305
306 return (1);
307}
308
309static void
310ldp_l2vpn_pw_config_write(struct vty *vty, struct l2vpn_pw *pw)
311{
312 int missing_lsrid = 0;
313 int missing_pwid = 0;
314
5c7571d4
DL
315 vty_out (vty, " !\n");
316 vty_out (vty, " member pseudowire %s\n", pw->ifname);
eac6e3f0
RW
317
318 if (pw->lsr_id.s_addr != INADDR_ANY)
5c7571d4 319 vty_out (vty, " neighbor lsr-id %s\n",inet_ntoa(pw->lsr_id));
96ade3ed
QY
320 else
321 missing_lsrid = 1;
eac6e3f0
RW
322
323 if (pw->flags & F_PW_STATIC_NBR_ADDR)
5c7571d4 324 vty_out (vty, " neighbor address %s\n",
96ade3ed 325 log_addr(pw->af, &pw->addr));
eac6e3f0
RW
326
327 if (pw->pwid != 0)
5c7571d4 328 vty_out (vty, " pw-id %u\n", pw->pwid);
eac6e3f0
RW
329 else
330 missing_pwid = 1;
331
332 if (!(pw->flags & F_PW_CWORD_CONF))
5c7571d4 333 vty_out (vty, " control-word exclude\n");
eac6e3f0
RW
334
335 if (!(pw->flags & F_PW_STATUSTLV_CONF))
5c7571d4 336 vty_out (vty, " pw-status disable\n");
eac6e3f0
RW
337
338 if (missing_lsrid)
181039f3
DL
339 vty_out (vty,
340 " ! Incomplete config, specify a neighbor lsr-id\n");
eac6e3f0 341 if (missing_pwid)
5c7571d4 342 vty_out (vty," ! Incomplete config, specify a pw-id\n");
eac6e3f0
RW
343}
344
345int
346ldp_l2vpn_config_write(struct vty *vty)
347{
348 struct l2vpn *l2vpn;
349 struct l2vpn_if *lif;
350 struct l2vpn_pw *pw;
351
90d7e7bd 352 RB_FOREACH(l2vpn, l2vpn_head, &ldpd_conf->l2vpn_tree) {
5c7571d4 353 vty_out (vty, "l2vpn %s type vpls\n", l2vpn->name);
eac6e3f0
RW
354
355 if (l2vpn->pw_type != DEFAULT_PW_TYPE)
5c7571d4 356 vty_out (vty, " vc type ethernet-tagged\n");
eac6e3f0
RW
357
358 if (l2vpn->mtu != DEFAULT_L2VPN_MTU)
5c7571d4 359 vty_out (vty, " mtu %u\n", l2vpn->mtu);
eac6e3f0
RW
360
361 if (l2vpn->br_ifname[0] != '\0')
5c7571d4 362 vty_out (vty, " bridge %s\n",l2vpn->br_ifname);
eac6e3f0 363
029c1958 364 RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
5c7571d4 365 vty_out (vty, " member interface %s\n",lif->ifname);
eac6e3f0 366
20bacaeb 367 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
eac6e3f0 368 ldp_l2vpn_pw_config_write(vty, pw);
20bacaeb 369 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
eac6e3f0
RW
370 ldp_l2vpn_pw_config_write(vty, pw);
371
5c7571d4
DL
372 vty_out (vty, " !\n");
373 vty_out (vty, "!\n");
eac6e3f0
RW
374 }
375
376 return (0);
377}
378
379static int
380ldp_vty_get_af(struct vty *vty)
381{
382 switch (vty->node) {
383 case LDP_IPV4_NODE:
384 case LDP_IPV4_IFACE_NODE:
385 return (AF_INET);
386 case LDP_IPV6_NODE:
387 case LDP_IPV6_IFACE_NODE:
388 return (AF_INET6);
389 default:
390 fatalx("ldp_vty_get_af: unexpected node");
391 }
392}
393
394static int
395ldp_iface_is_configured(struct ldpd_conf *xconf, const char *ifname)
396{
397 struct l2vpn *l2vpn;
398
399 if (if_lookup_name(xconf, ifname))
400 return (1);
401
90d7e7bd 402 RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
52bd4c23 403 if (l2vpn_if_find(l2vpn, ifname))
eac6e3f0 404 return (1);
52bd4c23 405 if (l2vpn_pw_find(l2vpn, ifname))
eac6e3f0
RW
406 return (1);
407 }
408
409 return (0);
410}
411
412int
1224e5c4 413ldp_vty_mpls_ldp(struct vty *vty, const char *negate)
eac6e3f0 414{
1224e5c4 415 if (negate)
eac6e3f0
RW
416 vty_conf->flags &= ~F_LDPD_ENABLED;
417 else {
418 vty->node = LDP_NODE;
419 vty_conf->flags |= F_LDPD_ENABLED;
420 }
421
e4a82008 422 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
423
424 return (CMD_SUCCESS);
425}
426
427int
1224e5c4 428ldp_vty_address_family(struct vty *vty, const char *negate, const char *af_str)
eac6e3f0 429{
eac6e3f0
RW
430 struct ldpd_af_conf *af_conf;
431 int af;
eac6e3f0 432
e59294e2 433 if (af_str == NULL)
434 return (CMD_WARNING_CONFIG_FAILED);
435
eac6e3f0
RW
436 if (strcmp(af_str, "ipv4") == 0) {
437 af = AF_INET;
438 af_conf = &vty_conf->ipv4;
439 } else if (strcmp(af_str, "ipv6") == 0) {
440 af = AF_INET6;
441 af_conf = &vty_conf->ipv6;
56b8a8d2 442 } else
f1a05de9 443 return (CMD_WARNING_CONFIG_FAILED);
eac6e3f0 444
1224e5c4 445 if (negate) {
eac6e3f0 446 af_conf->flags &= ~F_LDPD_AF_ENABLED;
e4a82008 447 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
448 return (CMD_SUCCESS);
449 }
450
451 switch (af) {
452 case AF_INET:
453 vty->node = LDP_IPV4_NODE;
454 break;
455 case AF_INET6:
456 vty->node = LDP_IPV6_NODE;
457 break;
458 default:
459 fatalx("ldp_vty_address_family: unknown af");
460 }
461 af_conf->flags |= F_LDPD_AF_ENABLED;
462
e4a82008 463 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
464
465 return (CMD_SUCCESS);
466}
467
16cd3d9d
RW
468int ldp_vty_disc_holdtime(struct vty *vty, const char *negate,
469 enum hello_type hello_type, long secs)
eac6e3f0 470{
eac6e3f0
RW
471 struct ldpd_af_conf *af_conf;
472 struct iface *iface;
473 struct iface_af *ia;
474 int af;
eac6e3f0 475
eac6e3f0
RW
476 switch (vty->node) {
477 case LDP_NODE:
1224e5c4 478 if (negate) {
eac6e3f0
RW
479 switch (hello_type) {
480 case HELLO_LINK:
481 vty_conf->lhello_holdtime = LINK_DFLT_HOLDTIME;
482 break;
483 case HELLO_TARGETED:
484 vty_conf->thello_holdtime =
485 TARGETED_DFLT_HOLDTIME;
486 break;
487 }
488 } else {
489 switch (hello_type) {
490 case HELLO_LINK:
491 vty_conf->lhello_holdtime = secs;
492 break;
493 case HELLO_TARGETED:
494 vty_conf->thello_holdtime = secs;
495 break;
496 }
497 }
e4a82008 498 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
499 break;
500 case LDP_IPV4_NODE:
501 case LDP_IPV6_NODE:
502 af = ldp_vty_get_af(vty);
503 af_conf = ldp_af_conf_get(vty_conf, af);
504
1224e5c4 505 if (negate) {
eac6e3f0
RW
506 switch (hello_type) {
507 case HELLO_LINK:
508 af_conf->lhello_holdtime = 0;
509 break;
510 case HELLO_TARGETED:
511 af_conf->thello_holdtime = 0;
512 break;
513 }
514 } else {
515 switch (hello_type) {
516 case HELLO_LINK:
517 af_conf->lhello_holdtime = secs;
518 break;
519 case HELLO_TARGETED:
520 af_conf->thello_holdtime = secs;
521 break;
522 }
523 }
e4a82008 524 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
525 break;
526 case LDP_IPV4_IFACE_NODE:
527 case LDP_IPV6_IFACE_NODE:
528 af = ldp_vty_get_af(vty);
1d75a89d 529 iface = VTY_GET_CONTEXT(iface);
dbce3582 530 VTY_CHECK_CONTEXT(iface);
eac6e3f0 531
0b47280e 532 ia = iface_af_get(iface, af);
1224e5c4 533 if (negate)
eac6e3f0
RW
534 ia->hello_holdtime = 0;
535 else
536 ia->hello_holdtime = secs;
1d75a89d 537
e4a82008 538 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
539 break;
540 default:
541 fatalx("ldp_vty_disc_holdtime: unexpected node");
542 }
543
eac6e3f0
RW
544 return (CMD_SUCCESS);
545}
546
547int
1224e5c4 548ldp_vty_disc_interval(struct vty *vty, const char *negate,
16cd3d9d 549 enum hello_type hello_type, long secs)
eac6e3f0 550{
eac6e3f0
RW
551 struct ldpd_af_conf *af_conf;
552 struct iface *iface;
553 struct iface_af *ia;
554 int af;
eac6e3f0 555
eac6e3f0
RW
556 switch (vty->node) {
557 case LDP_NODE:
1224e5c4 558 if (negate) {
eac6e3f0
RW
559 switch (hello_type) {
560 case HELLO_LINK:
cd49efda
RW
561 vty_conf->lhello_interval =
562 DEFAULT_HELLO_INTERVAL;
eac6e3f0
RW
563 break;
564 case HELLO_TARGETED:
565 vty_conf->thello_interval =
cd49efda 566 DEFAULT_HELLO_INTERVAL;
eac6e3f0
RW
567 break;
568 }
569 } else {
570 switch (hello_type) {
571 case HELLO_LINK:
572 vty_conf->lhello_interval = secs;
573 break;
574 case HELLO_TARGETED:
575 vty_conf->thello_interval = secs;
576 break;
577 }
578 }
e4a82008 579 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
580 break;
581 case LDP_IPV4_NODE:
582 case LDP_IPV6_NODE:
583 af = ldp_vty_get_af(vty);
584 af_conf = ldp_af_conf_get(vty_conf, af);
585
1224e5c4 586 if (negate) {
eac6e3f0
RW
587 switch (hello_type) {
588 case HELLO_LINK:
589 af_conf->lhello_interval = 0;
590 break;
591 case HELLO_TARGETED:
592 af_conf->thello_interval = 0;
593 break;
594 }
595 } else {
596 switch (hello_type) {
597 case HELLO_LINK:
598 af_conf->lhello_interval = secs;
599 break;
600 case HELLO_TARGETED:
601 af_conf->thello_interval = secs;
602 break;
603 }
604 }
e4a82008 605 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
606 break;
607 case LDP_IPV4_IFACE_NODE:
608 case LDP_IPV6_IFACE_NODE:
609 af = ldp_vty_get_af(vty);
1d75a89d 610 iface = VTY_GET_CONTEXT(iface);
dbce3582 611 VTY_CHECK_CONTEXT(iface);
eac6e3f0 612
0b47280e 613 ia = iface_af_get(iface, af);
1224e5c4 614 if (negate)
eac6e3f0
RW
615 ia->hello_interval = 0;
616 else
617 ia->hello_interval = secs;
1d75a89d 618
e4a82008 619 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
620 break;
621 default:
622 fatalx("ldp_vty_disc_interval: unexpected node");
623 }
624
eac6e3f0
RW
625 return (CMD_SUCCESS);
626}
627
628int
1224e5c4 629ldp_vty_targeted_hello_accept(struct vty *vty, const char *negate,
c740f7d3 630 const char *acl_from_str)
eac6e3f0 631{
eac6e3f0
RW
632 struct ldpd_af_conf *af_conf;
633 int af;
eac6e3f0
RW
634
635 af = ldp_vty_get_af(vty);
636 af_conf = ldp_af_conf_get(vty_conf, af);
637
1224e5c4 638 if (negate) {
eac6e3f0 639 af_conf->flags &= ~F_LDPD_AF_THELLO_ACCEPT;
45a8eba9
RW
640 af_conf->acl_thello_accept_from[0] = '\0';
641 } else {
eac6e3f0 642 af_conf->flags |= F_LDPD_AF_THELLO_ACCEPT;
45a8eba9
RW
643 if (acl_from_str)
644 strlcpy(af_conf->acl_thello_accept_from, acl_from_str,
645 sizeof(af_conf->acl_thello_accept_from));
646 else
647 af_conf->acl_thello_accept_from[0] = '\0';
648 }
eac6e3f0 649
e4a82008 650 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
651
652 return (CMD_SUCCESS);
653}
654
c740f7d3 655int
1224e5c4
RW
656ldp_vty_nbr_session_holdtime(struct vty *vty, const char *negate,
657 struct in_addr lsr_id, long secs)
eac6e3f0 658{
eac6e3f0 659 struct nbr_params *nbrp;
eac6e3f0 660
1224e5c4 661 if (bad_addr_v4(lsr_id)) {
5c7571d4 662 vty_out (vty, "%% Malformed address\n");
f1a05de9 663 return (CMD_WARNING_CONFIG_FAILED);
eac6e3f0
RW
664 }
665
1d75a89d
RW
666 nbrp = nbr_params_find(vty_conf, lsr_id);
667
1224e5c4 668 if (negate) {
eac6e3f0 669 if (nbrp == NULL)
56b8a8d2 670 return (CMD_SUCCESS);
eac6e3f0
RW
671
672 nbrp->keepalive = 0;
673 nbrp->flags &= ~F_NBRP_KEEPALIVE;
674 } else {
675 if (nbrp == NULL) {
676 nbrp = nbr_params_new(lsr_id);
76c4abd1 677 RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp);
1d75a89d 678 QOBJ_REG(nbrp, nbr_params);
eac6e3f0 679 } else if (nbrp->keepalive == secs)
56b8a8d2 680 return (CMD_SUCCESS);
eac6e3f0
RW
681
682 nbrp->keepalive = secs;
683 nbrp->flags |= F_NBRP_KEEPALIVE;
684 }
685
e4a82008 686 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
687
688 return (CMD_SUCCESS);
eac6e3f0
RW
689}
690
c740f7d3 691int
1224e5c4 692ldp_vty_af_session_holdtime(struct vty *vty, const char *negate, long secs)
eac6e3f0 693{
eac6e3f0
RW
694 struct ldpd_af_conf *af_conf;
695 int af;
eac6e3f0 696
eac6e3f0
RW
697 af = ldp_vty_get_af(vty);
698 af_conf = ldp_af_conf_get(vty_conf, af);
699
1224e5c4 700 if (negate)
eac6e3f0
RW
701 af_conf->keepalive = DEFAULT_KEEPALIVE;
702 else
703 af_conf->keepalive = secs;
704
e4a82008 705 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
706
707 return (CMD_SUCCESS);
708}
709
710int
1224e5c4 711ldp_vty_interface(struct vty *vty, const char *negate, const char *ifname)
eac6e3f0 712{
eac6e3f0
RW
713 int af;
714 struct iface *iface;
715 struct iface_af *ia;
eac6e3f0 716
e59294e2 717 if (ifname == NULL) {
718 vty_out (vty, "%% Missing IF name\n");
719 return (CMD_WARNING_CONFIG_FAILED);
720 }
721
eac6e3f0
RW
722 af = ldp_vty_get_af(vty);
723 iface = if_lookup_name(vty_conf, ifname);
724
1224e5c4 725 if (negate) {
eac6e3f0 726 if (iface == NULL)
56b8a8d2 727 return (CMD_SUCCESS);
eac6e3f0
RW
728
729 ia = iface_af_get(iface, af);
730 if (ia->enabled == 0)
56b8a8d2 731 return (CMD_SUCCESS);
eac6e3f0
RW
732
733 ia->enabled = 0;
271327b1
RW
734 ia->hello_holdtime = 0;
735 ia->hello_interval = 0;
1d75a89d 736
e4a82008 737 ldp_config_apply(vty, vty_conf);
1d75a89d 738
eac6e3f0
RW
739 return (CMD_SUCCESS);
740 }
741
eac6e3f0
RW
742 if (iface == NULL) {
743 if (ldp_iface_is_configured(vty_conf, ifname)) {
5c7571d4 744 vty_out (vty,"%% Interface is already in use\n");
56b8a8d2 745 return (CMD_SUCCESS);
eac6e3f0
RW
746 }
747
52b530fc 748 iface = if_new(ifname);
eac6e3f0
RW
749 ia = iface_af_get(iface, af);
750 ia->enabled = 1;
7d3d7491 751 RB_INSERT(iface_head, &vty_conf->iface_tree, iface);
1d75a89d
RW
752 QOBJ_REG(iface, iface);
753
e4a82008 754 ldp_config_apply(vty, vty_conf);
eac6e3f0 755 } else {
eac6e3f0 756 ia = iface_af_get(iface, af);
0b47280e
RW
757 if (!ia->enabled) {
758 ia->enabled = 1;
e4a82008 759 ldp_config_apply(vty, vty_conf);
56b8a8d2 760 }
0b47280e
RW
761 }
762
763 switch (af) {
764 case AF_INET:
1d75a89d 765 VTY_PUSH_CONTEXT(LDP_IPV4_IFACE_NODE, iface);
0b47280e
RW
766 break;
767 case AF_INET6:
1d75a89d 768 VTY_PUSH_CONTEXT(LDP_IPV6_IFACE_NODE, iface);
0b47280e
RW
769 break;
770 default:
771 break;
eac6e3f0
RW
772 }
773
eac6e3f0 774 return (CMD_SUCCESS);
eac6e3f0
RW
775}
776
777int
1224e5c4 778ldp_vty_trans_addr(struct vty *vty, const char *negate, const char *addr_str)
eac6e3f0 779{
eac6e3f0
RW
780 struct ldpd_af_conf *af_conf;
781 int af;
eac6e3f0 782
eac6e3f0
RW
783 af = ldp_vty_get_af(vty);
784 af_conf = ldp_af_conf_get(vty_conf, af);
785
1224e5c4 786 if (negate)
eac6e3f0
RW
787 memset(&af_conf->trans_addr, 0, sizeof(af_conf->trans_addr));
788 else {
e59294e2 789 if (addr_str == NULL
790 || inet_pton(af, addr_str, &af_conf->trans_addr) != 1
791 || bad_addr(af, &af_conf->trans_addr)) {
5c7571d4 792 vty_out (vty, "%% Malformed address\n");
56b8a8d2 793 return (CMD_SUCCESS);
eac6e3f0
RW
794 }
795 }
796
e4a82008 797 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
798
799 return (CMD_SUCCESS);
eac6e3f0
RW
800}
801
802int
1224e5c4 803ldp_vty_neighbor_targeted(struct vty *vty, const char *negate, const char *addr_str)
eac6e3f0 804{
eac6e3f0
RW
805 int af;
806 union ldpd_addr addr;
807 struct tnbr *tnbr;
eac6e3f0
RW
808
809 af = ldp_vty_get_af(vty);
810
e59294e2 811 if (addr_str == NULL || inet_pton(af, addr_str, &addr) != 1 ||
eac6e3f0 812 bad_addr(af, &addr)) {
5c7571d4 813 vty_out (vty, "%% Malformed address\n");
f1a05de9 814 return (CMD_WARNING_CONFIG_FAILED);
eac6e3f0
RW
815 }
816 if (af == AF_INET6 && IN6_IS_SCOPE_EMBED(&addr.v6)) {
5c7571d4 817 vty_out (vty, "%% Address can not be link-local\n");
f1a05de9 818 return (CMD_WARNING_CONFIG_FAILED);
eac6e3f0
RW
819 }
820
eac6e3f0
RW
821 tnbr = tnbr_find(vty_conf, af, &addr);
822
1224e5c4 823 if (negate) {
eac6e3f0 824 if (tnbr == NULL)
56b8a8d2 825 return (CMD_SUCCESS);
eac6e3f0 826
1d75a89d 827 QOBJ_UNREG(tnbr);
7989cdba 828 RB_REMOVE(tnbr_head, &vty_conf->tnbr_tree, tnbr);
eac6e3f0 829 free(tnbr);
1d75a89d 830
e4a82008 831 ldp_config_apply(vty, vty_conf);
1d75a89d 832
eac6e3f0
RW
833 return (CMD_SUCCESS);
834 }
835
836 if (tnbr)
56b8a8d2 837 return (CMD_SUCCESS);
eac6e3f0
RW
838
839 tnbr = tnbr_new(af, &addr);
840 tnbr->flags |= F_TNBR_CONFIGURED;
7989cdba 841 RB_INSERT(tnbr_head, &vty_conf->tnbr_tree, tnbr);
1d75a89d 842 QOBJ_REG(tnbr, tnbr);
eac6e3f0 843
e4a82008 844 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
845
846 return (CMD_SUCCESS);
eac6e3f0
RW
847}
848
849int
1224e5c4 850ldp_vty_label_advertise(struct vty *vty, const char *negate, const char *acl_to_str,
c740f7d3 851 const char *acl_for_str)
eac6e3f0 852{
eac6e3f0
RW
853 struct ldpd_af_conf *af_conf;
854 int af;
eac6e3f0 855
eac6e3f0
RW
856 af = ldp_vty_get_af(vty);
857 af_conf = ldp_af_conf_get(vty_conf, af);
858
1224e5c4 859 if (negate) {
45a8eba9
RW
860 af_conf->acl_label_advertise_to[0] = '\0';
861 af_conf->acl_label_advertise_for[0] = '\0';
862 } else {
863 if (acl_to_str)
864 strlcpy(af_conf->acl_label_advertise_to, acl_to_str,
865 sizeof(af_conf->acl_label_advertise_to));
866 else
867 af_conf->acl_label_advertise_to[0] = '\0';
868 if (acl_for_str)
869 strlcpy(af_conf->acl_label_advertise_for, acl_for_str,
870 sizeof(af_conf->acl_label_advertise_for));
871 else
872 af_conf->acl_label_advertise_for[0] = '\0';
873 }
874
e4a82008 875 ldp_config_apply(vty, vty_conf);
45a8eba9
RW
876
877 return (CMD_SUCCESS);
878}
879
880int
1224e5c4 881ldp_vty_label_allocate(struct vty *vty, const char *negate, const char *host_routes,
c740f7d3 882 const char *acl_for_str)
45a8eba9 883{
45a8eba9
RW
884 struct ldpd_af_conf *af_conf;
885 int af;
45a8eba9 886
45a8eba9
RW
887 af = ldp_vty_get_af(vty);
888 af_conf = ldp_af_conf_get(vty_conf, af);
889
890 af_conf->flags &= ~F_LDPD_AF_ALLOCHOSTONLY;
891 af_conf->acl_label_allocate_for[0] = '\0';
1224e5c4 892 if (!negate) {
c740f7d3 893 if (host_routes)
45a8eba9
RW
894 af_conf->flags |= F_LDPD_AF_ALLOCHOSTONLY;
895 else
896 strlcpy(af_conf->acl_label_allocate_for, acl_for_str,
897 sizeof(af_conf->acl_label_allocate_for));
898 }
899
e4a82008 900 ldp_config_apply(vty, vty_conf);
45a8eba9
RW
901
902 return (CMD_SUCCESS);
903}
904
905int
1224e5c4 906ldp_vty_label_expnull(struct vty *vty, const char *negate, const char *acl_for_str)
45a8eba9 907{
45a8eba9
RW
908 struct ldpd_af_conf *af_conf;
909 int af;
45a8eba9 910
45a8eba9
RW
911 af = ldp_vty_get_af(vty);
912 af_conf = ldp_af_conf_get(vty_conf, af);
913
1224e5c4 914 if (negate) {
eac6e3f0 915 af_conf->flags &= ~F_LDPD_AF_EXPNULL;
45a8eba9
RW
916 af_conf->acl_label_expnull_for[0] = '\0';
917 } else {
eac6e3f0 918 af_conf->flags |= F_LDPD_AF_EXPNULL;
45a8eba9
RW
919 if (acl_for_str)
920 strlcpy(af_conf->acl_label_expnull_for, acl_for_str,
921 sizeof(af_conf->acl_label_expnull_for));
922 else
923 af_conf->acl_label_expnull_for[0] = '\0';
924 }
925
e4a82008 926 ldp_config_apply(vty, vty_conf);
45a8eba9
RW
927
928 return (CMD_SUCCESS);
929}
930
931int
1224e5c4 932ldp_vty_label_accept(struct vty *vty, const char *negate, const char *acl_from_str,
c740f7d3 933 const char *acl_for_str)
45a8eba9 934{
45a8eba9
RW
935 struct ldpd_af_conf *af_conf;
936 int af;
45a8eba9 937
45a8eba9
RW
938 af = ldp_vty_get_af(vty);
939 af_conf = ldp_af_conf_get(vty_conf, af);
940
1224e5c4 941 if (negate) {
45a8eba9
RW
942 af_conf->acl_label_accept_from[0] = '\0';
943 af_conf->acl_label_accept_for[0] = '\0';
944 } else {
945 if (acl_from_str)
946 strlcpy(af_conf->acl_label_accept_from, acl_from_str,
947 sizeof(af_conf->acl_label_accept_from));
948 else
949 af_conf->acl_label_accept_from[0] = '\0';
950 if (acl_for_str)
951 strlcpy(af_conf->acl_label_accept_for, acl_for_str,
952 sizeof(af_conf->acl_label_accept_for));
953 else
954 af_conf->acl_label_accept_for[0] = '\0';
955 }
eac6e3f0 956
e4a82008 957 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
958
959 return (CMD_SUCCESS);
960}
961
962int
1224e5c4 963ldp_vty_ttl_security(struct vty *vty, const char *negate)
eac6e3f0 964{
eac6e3f0
RW
965 struct ldpd_af_conf *af_conf;
966 int af;
eac6e3f0 967
eac6e3f0
RW
968 af = ldp_vty_get_af(vty);
969 af_conf = ldp_af_conf_get(vty_conf, af);
970
1224e5c4 971 if (negate)
eac6e3f0
RW
972 af_conf->flags &= ~F_LDPD_AF_NO_GTSM;
973 else
974 af_conf->flags |= F_LDPD_AF_NO_GTSM;
975
e4a82008 976 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
977
978 return (CMD_SUCCESS);
979}
980
981int
1224e5c4 982ldp_vty_router_id(struct vty *vty, const char *negate, struct in_addr address)
eac6e3f0 983{
1224e5c4 984 if (negate)
eac6e3f0
RW
985 vty_conf->rtr_id.s_addr = INADDR_ANY;
986 else {
1224e5c4 987 if (bad_addr_v4(address)) {
5c7571d4 988 vty_out (vty, "%% Malformed address\n");
56b8a8d2 989 return (CMD_SUCCESS);
eac6e3f0 990 }
1224e5c4 991 vty_conf->rtr_id = address;
eac6e3f0
RW
992 }
993
e4a82008 994 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
995
996 return (CMD_SUCCESS);
eac6e3f0
RW
997}
998
999int
1224e5c4 1000ldp_vty_ds_cisco_interop(struct vty *vty, const char * negate)
eac6e3f0 1001{
1224e5c4 1002 if (negate)
eac6e3f0
RW
1003 vty_conf->flags &= ~F_LDPD_DS_CISCO_INTEROP;
1004 else
1005 vty_conf->flags |= F_LDPD_DS_CISCO_INTEROP;
1006
e4a82008 1007 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1008
1009 return (CMD_SUCCESS);
1010}
1011
1012int
1224e5c4 1013ldp_vty_trans_pref_ipv4(struct vty *vty, const char *negate)
eac6e3f0 1014{
1224e5c4 1015 if (negate)
eac6e3f0
RW
1016 vty_conf->trans_pref = DUAL_STACK_LDPOV6;
1017 else
1018 vty_conf->trans_pref = DUAL_STACK_LDPOV4;
1019
e4a82008 1020 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1021
1022 return (CMD_SUCCESS);
1023}
1024
1025int
1224e5c4 1026ldp_vty_neighbor_password(struct vty *vty, const char *negate, struct in_addr lsr_id,
c740f7d3 1027 const char *password_str)
eac6e3f0 1028{
eac6e3f0
RW
1029 size_t password_len;
1030 struct nbr_params *nbrp;
eac6e3f0 1031
e59294e2 1032 if (password_str == NULL) {
1033 vty_out (vty, "%% Missing password\n");
1034 return (CMD_WARNING_CONFIG_FAILED);
1035 }
1036
1224e5c4 1037 if (bad_addr_v4(lsr_id)) {
5c7571d4 1038 vty_out (vty, "%% Malformed address\n");
f1a05de9 1039 return (CMD_WARNING_CONFIG_FAILED);
eac6e3f0
RW
1040 }
1041
eac6e3f0
RW
1042 nbrp = nbr_params_find(vty_conf, lsr_id);
1043
1224e5c4 1044 if (negate) {
eac6e3f0 1045 if (nbrp == NULL)
56b8a8d2 1046 return (CMD_SUCCESS);
eac6e3f0
RW
1047
1048 memset(&nbrp->auth, 0, sizeof(nbrp->auth));
1049 nbrp->auth.method = AUTH_NONE;
1050 } else {
1051 if (nbrp == NULL) {
1052 nbrp = nbr_params_new(lsr_id);
76c4abd1 1053 RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp);
1d75a89d 1054 QOBJ_REG(nbrp, nbr_params);
eac6e3f0
RW
1055 } else if (nbrp->auth.method == AUTH_MD5SIG &&
1056 strcmp(nbrp->auth.md5key, password_str) == 0)
56b8a8d2 1057 return (CMD_SUCCESS);
eac6e3f0
RW
1058
1059 password_len = strlcpy(nbrp->auth.md5key, password_str,
1060 sizeof(nbrp->auth.md5key));
1061 if (password_len >= sizeof(nbrp->auth.md5key))
1062 vty_out(vty, "%% password has been truncated to %zu "
1063 "characters.", sizeof(nbrp->auth.md5key) - 1);
1064 nbrp->auth.md5key_len = password_len;
1065 nbrp->auth.method = AUTH_MD5SIG;
1066 }
1067
e4a82008 1068 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1069
1070 return (CMD_SUCCESS);
eac6e3f0
RW
1071}
1072
1073int
1224e5c4
RW
1074ldp_vty_neighbor_ttl_security(struct vty *vty, const char *negate,
1075 struct in_addr lsr_id, const char *hops_str)
eac6e3f0 1076{
eac6e3f0
RW
1077 struct nbr_params *nbrp;
1078 long int hops = 0;
1079 char *ep;
eac6e3f0 1080
1224e5c4 1081 if (bad_addr_v4(lsr_id)) {
5c7571d4 1082 vty_out (vty, "%% Malformed address\n");
f1a05de9 1083 return (CMD_WARNING_CONFIG_FAILED);
eac6e3f0
RW
1084 }
1085
1086 if (hops_str) {
1087 hops = strtol(hops_str, &ep, 10);
1088 if (*ep != '\0' || hops < 1 || hops > 254) {
5c7571d4 1089 vty_out (vty, "%% Invalid hop count\n");
eac6e3f0
RW
1090 return (CMD_SUCCESS);
1091 }
1092 }
1093
eac6e3f0
RW
1094 nbrp = nbr_params_find(vty_conf, lsr_id);
1095
1224e5c4 1096 if (negate) {
eac6e3f0 1097 if (nbrp == NULL)
56b8a8d2 1098 return (CMD_SUCCESS);
eac6e3f0
RW
1099
1100 nbrp->flags &= ~(F_NBRP_GTSM|F_NBRP_GTSM_HOPS);
1101 nbrp->gtsm_enabled = 0;
1102 nbrp->gtsm_hops = 0;
1103 } else {
1104 if (nbrp == NULL) {
1105 nbrp = nbr_params_new(lsr_id);
76c4abd1 1106 RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp);
1d75a89d 1107 QOBJ_REG(nbrp, nbr_params);
eac6e3f0
RW
1108 }
1109
1110 nbrp->flags |= F_NBRP_GTSM;
1111 nbrp->flags &= ~F_NBRP_GTSM_HOPS;
1112 if (hops_str) {
1113 nbrp->gtsm_enabled = 1;
1114 nbrp->gtsm_hops = hops;
1115 nbrp->flags |= F_NBRP_GTSM_HOPS;
1116 } else
1117 nbrp->gtsm_enabled = 0;
1118 }
1119
e4a82008 1120 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1121
1122 return (CMD_SUCCESS);
eac6e3f0
RW
1123}
1124
1125int
1224e5c4 1126ldp_vty_l2vpn(struct vty *vty, const char *negate, const char *name_str)
eac6e3f0 1127{
eac6e3f0 1128 struct l2vpn *l2vpn;
1d75a89d
RW
1129 struct l2vpn_if *lif;
1130 struct l2vpn_pw *pw;
eac6e3f0 1131
e59294e2 1132 if (name_str == NULL) {
1133 vty_out (vty, "%% Missing name\n");
1134 return (CMD_WARNING_CONFIG_FAILED);
1135 }
1136
eac6e3f0
RW
1137 l2vpn = l2vpn_find(vty_conf, name_str);
1138
1224e5c4 1139 if (negate) {
eac6e3f0 1140 if (l2vpn == NULL)
56b8a8d2 1141 return (CMD_SUCCESS);
eac6e3f0 1142
1d75a89d
RW
1143 RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
1144 QOBJ_UNREG(lif);
1145 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
1146 QOBJ_UNREG(pw);
1147 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
1148 QOBJ_UNREG(pw);
1149 QOBJ_UNREG(l2vpn);
90d7e7bd 1150 RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn);
eac6e3f0 1151 l2vpn_del(l2vpn);
1d75a89d 1152
e4a82008 1153 ldp_config_apply(vty, vty_conf);
1d75a89d 1154
eac6e3f0
RW
1155 return (CMD_SUCCESS);
1156 }
1157
0b47280e 1158 if (l2vpn) {
1d75a89d 1159 VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn);
56b8a8d2 1160 return (CMD_SUCCESS);
0b47280e 1161 }
eac6e3f0
RW
1162
1163 l2vpn = l2vpn_new(name_str);
1164 l2vpn->type = L2VPN_TYPE_VPLS;
90d7e7bd 1165 RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn);
1d75a89d
RW
1166 QOBJ_REG(l2vpn, l2vpn);
1167
1168 VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn);
eac6e3f0 1169
e4a82008 1170 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1171
1172 return (CMD_SUCCESS);
eac6e3f0
RW
1173}
1174
1175int
1224e5c4 1176ldp_vty_l2vpn_bridge(struct vty *vty, const char *negate, const char *ifname)
eac6e3f0 1177{
1d75a89d 1178 VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
eac6e3f0 1179
1224e5c4 1180 if (negate)
eac6e3f0 1181 memset(l2vpn->br_ifname, 0, sizeof(l2vpn->br_ifname));
e59294e2 1182 else {
1183 if (ifname == NULL) {
1184 vty_out (vty, "%% Missing IF name\n");
1185 return (CMD_WARNING_CONFIG_FAILED);
1186 }
eac6e3f0 1187 strlcpy(l2vpn->br_ifname, ifname, sizeof(l2vpn->br_ifname));
e59294e2 1188 }
eac6e3f0 1189
e4a82008 1190 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1191
1192 return (CMD_SUCCESS);
1193}
1194
1195int
1224e5c4 1196ldp_vty_l2vpn_mtu(struct vty *vty, const char *negate, long mtu)
eac6e3f0 1197{
1d75a89d 1198 VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
eac6e3f0 1199
1224e5c4 1200 if (negate)
eac6e3f0
RW
1201 l2vpn->mtu = DEFAULT_L2VPN_MTU;
1202 else
1203 l2vpn->mtu = mtu;
1204
e4a82008 1205 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1206
1207 return (CMD_SUCCESS);
1208}
1209
1210int
1224e5c4 1211ldp_vty_l2vpn_pwtype(struct vty *vty, const char *negate, const char *type_str)
eac6e3f0 1212{
1d75a89d 1213 VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
eac6e3f0 1214 int pw_type;
eac6e3f0 1215
e59294e2 1216 if (type_str == NULL) {
1217 vty_out (vty, "%% Missing type\n");
1218 return (CMD_WARNING_CONFIG_FAILED);
1219 }
1220
eac6e3f0
RW
1221 if (strcmp(type_str, "ethernet") == 0)
1222 pw_type = PW_TYPE_ETHERNET;
1223 else
1224 pw_type = PW_TYPE_ETHERNET_TAGGED;
1225
1224e5c4 1226 if (negate)
eac6e3f0
RW
1227 l2vpn->pw_type = DEFAULT_PW_TYPE;
1228 else
1229 l2vpn->pw_type = pw_type;
1230
e4a82008 1231 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1232
1233 return (CMD_SUCCESS);
1234}
1235
1236int
1224e5c4 1237ldp_vty_l2vpn_interface(struct vty *vty, const char *negate, const char *ifname)
eac6e3f0 1238{
1d75a89d 1239 VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
eac6e3f0 1240 struct l2vpn_if *lif;
eac6e3f0 1241
e59294e2 1242 if (ifname == NULL) {
1243 vty_out (vty, "%% Missing IF name\n");
1244 return (CMD_WARNING_CONFIG_FAILED);
1245 }
1246
52bd4c23 1247 lif = l2vpn_if_find(l2vpn, ifname);
eac6e3f0 1248
1224e5c4 1249 if (negate) {
eac6e3f0 1250 if (lif == NULL)
56b8a8d2 1251 return (CMD_SUCCESS);
eac6e3f0 1252
1d75a89d 1253 QOBJ_UNREG(lif);
029c1958 1254 RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
eac6e3f0 1255 free(lif);
1d75a89d 1256
e4a82008 1257 ldp_config_apply(vty, vty_conf);
1d75a89d 1258
eac6e3f0
RW
1259 return (CMD_SUCCESS);
1260 }
1261
1262 if (lif)
56b8a8d2 1263 return (CMD_SUCCESS);
eac6e3f0
RW
1264
1265 if (ldp_iface_is_configured(vty_conf, ifname)) {
5c7571d4 1266 vty_out (vty, "%% Interface is already in use\n");
56b8a8d2 1267 return (CMD_SUCCESS);
eac6e3f0
RW
1268 }
1269
52b530fc 1270 lif = l2vpn_if_new(l2vpn, ifname);
029c1958 1271 RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
1d75a89d 1272 QOBJ_REG(lif, l2vpn_if);
eac6e3f0 1273
e4a82008 1274 ldp_config_apply(vty, vty_conf);
eac6e3f0 1275
eac6e3f0
RW
1276 return (CMD_SUCCESS);
1277}
1278
1279int
1224e5c4 1280ldp_vty_l2vpn_pseudowire(struct vty *vty, const char *negate, const char *ifname)
eac6e3f0 1281{
1d75a89d 1282 VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
eac6e3f0 1283 struct l2vpn_pw *pw;
eac6e3f0 1284
e59294e2 1285 if (ifname == NULL) {
1286 vty_out (vty, "%% Missing IF name\n");
1287 return (CMD_WARNING_CONFIG_FAILED);
1288 }
1289
52bd4c23 1290 pw = l2vpn_pw_find(l2vpn, ifname);
eac6e3f0 1291
1224e5c4 1292 if (negate) {
eac6e3f0 1293 if (pw == NULL)
56b8a8d2 1294 return (CMD_SUCCESS);
eac6e3f0 1295
1d75a89d
RW
1296 QOBJ_UNREG(pw);
1297 if (pw->lsr_id.s_addr == INADDR_ANY || pw->pwid == 0)
1298 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
1299 else
1300 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
eac6e3f0 1301 free(pw);
1d75a89d 1302
e4a82008 1303 ldp_config_apply(vty, vty_conf);
1d75a89d 1304
eac6e3f0
RW
1305 return (CMD_SUCCESS);
1306 }
1307
1308 if (pw) {
1d75a89d 1309 VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw);
56b8a8d2 1310 return (CMD_SUCCESS);
eac6e3f0
RW
1311 }
1312
1313 if (ldp_iface_is_configured(vty_conf, ifname)) {
5c7571d4 1314 vty_out (vty, "%% Interface is already in use\n");
56b8a8d2 1315 return (CMD_SUCCESS);
eac6e3f0
RW
1316 }
1317
52b530fc 1318 pw = l2vpn_pw_new(l2vpn, ifname);
eac6e3f0 1319 pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
20bacaeb 1320 RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
1d75a89d
RW
1321 QOBJ_REG(pw, l2vpn_pw);
1322
1323 VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw);
eac6e3f0 1324
e4a82008 1325 ldp_config_apply(vty, vty_conf);
eac6e3f0 1326
eac6e3f0 1327 return (CMD_SUCCESS);
eac6e3f0
RW
1328}
1329
1330int
1224e5c4 1331ldp_vty_l2vpn_pw_cword(struct vty *vty, const char *negate, const char *preference_str)
eac6e3f0 1332{
1d75a89d 1333 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
eac6e3f0 1334
1224e5c4 1335 if (negate)
eac6e3f0
RW
1336 pw->flags |= F_PW_CWORD_CONF;
1337 else {
e59294e2 1338 if (!preference_str) {
1339 vty_out (vty, "%% Missing preference\n");
1340 return (CMD_WARNING_CONFIG_FAILED);
1341 }
eac6e3f0
RW
1342 if (preference_str[0] == 'e')
1343 pw->flags &= ~F_PW_CWORD_CONF;
1344 else
1345 pw->flags |= F_PW_CWORD_CONF;
1346 }
1347
e4a82008 1348 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1349
1350 return (CMD_SUCCESS);
1351}
1352
1353int
1224e5c4 1354ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, const char *negate, const char *addr_str)
eac6e3f0 1355{
1d75a89d 1356 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
eac6e3f0
RW
1357 int af;
1358 union ldpd_addr addr;
eac6e3f0
RW
1359
1360 if (ldp_get_address(addr_str, &af, &addr) == -1 ||
1361 bad_addr(af, &addr)) {
5c7571d4 1362 vty_out (vty, "%% Malformed address\n");
f1a05de9 1363 return (CMD_WARNING_CONFIG_FAILED);
eac6e3f0
RW
1364 }
1365
1224e5c4 1366 if (negate) {
eac6e3f0
RW
1367 pw->af = AF_UNSPEC;
1368 memset(&pw->addr, 0, sizeof(pw->addr));
1369 pw->flags &= ~F_PW_STATIC_NBR_ADDR;
1370 } else {
1371 pw->af = af;
1372 pw->addr = addr;
1373 pw->flags |= F_PW_STATIC_NBR_ADDR;
1374 }
1375
e4a82008 1376 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1377
1378 return (CMD_SUCCESS);
1379}
1380
1381int
1224e5c4 1382ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, const char *negate, struct in_addr lsr_id)
eac6e3f0 1383{
1d75a89d 1384 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
eac6e3f0 1385
1224e5c4 1386 if (bad_addr_v4(lsr_id)) {
5c7571d4 1387 vty_out (vty, "%% Malformed address\n");
f1a05de9 1388 return (CMD_WARNING_CONFIG_FAILED);
eac6e3f0
RW
1389 }
1390
1224e5c4 1391 if (negate)
eac6e3f0
RW
1392 pw->lsr_id.s_addr = INADDR_ANY;
1393 else
1394 pw->lsr_id = lsr_id;
1395
e4a82008 1396 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1397
1398 return (CMD_SUCCESS);
1399}
1400
1401int
1224e5c4 1402ldp_vty_l2vpn_pw_pwid(struct vty *vty, const char *negate, long pwid)
eac6e3f0 1403{
1d75a89d 1404 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
eac6e3f0 1405
1224e5c4 1406 if (negate)
eac6e3f0
RW
1407 pw->pwid = 0;
1408 else
1409 pw->pwid = pwid;
1410
e4a82008 1411 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1412
1413 return (CMD_SUCCESS);
1414}
1415
1416int
1224e5c4 1417ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, const char *negate)
eac6e3f0 1418{
1d75a89d 1419 VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
eac6e3f0 1420
1224e5c4 1421 if (negate)
eac6e3f0
RW
1422 pw->flags |= F_PW_STATUSTLV_CONF;
1423 else
1424 pw->flags &= ~F_PW_STATUSTLV_CONF;
1425
e4a82008 1426 ldp_config_apply(vty, vty_conf);
eac6e3f0
RW
1427
1428 return (CMD_SUCCESS);
1429}
1430
bbee85d2
RW
1431struct iface *
1432iface_new_api(struct ldpd_conf *conf, const char *name)
1433{
1434 const char *ifname = name;
1435 struct iface *iface;
bbee85d2
RW
1436
1437 if (ldp_iface_is_configured(conf, ifname))
5afba51d 1438 return (NULL);
bbee85d2 1439
52b530fc 1440 iface = if_new(name);
7d3d7491 1441 RB_INSERT(iface_head, &conf->iface_tree, iface);
1d75a89d 1442 QOBJ_REG(iface, iface);
bbee85d2
RW
1443 return (iface);
1444}
1445
1446void
7d3d7491 1447iface_del_api(struct ldpd_conf *conf, struct iface *iface)
bbee85d2 1448{
1d75a89d 1449 QOBJ_UNREG(iface);
7d3d7491 1450 RB_REMOVE(iface_head, &conf->iface_tree, iface);
bbee85d2
RW
1451 free(iface);
1452}
1453
1454struct tnbr *
1455tnbr_new_api(struct ldpd_conf *conf, int af, union ldpd_addr *addr)
1456{
1457 struct tnbr *tnbr;
1458
1459 if (af == AF_INET6 && IN6_IS_SCOPE_EMBED(&addr->v6))
1460 return (NULL);
1461
1462 if (tnbr_find(conf, af, addr))
1463 return (NULL);
1464
1465 tnbr = tnbr_new(af, addr);
1466 tnbr->flags |= F_TNBR_CONFIGURED;
7989cdba 1467 RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr);
1d75a89d 1468 QOBJ_REG(tnbr, tnbr);
bbee85d2
RW
1469 return (tnbr);
1470}
1471
1472void
7989cdba 1473tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr)
bbee85d2 1474{
1d75a89d 1475 QOBJ_UNREG(tnbr);
7989cdba 1476 RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
bbee85d2
RW
1477 free(tnbr);
1478}
1479
1480struct nbr_params *
1481nbrp_new_api(struct ldpd_conf *conf, struct in_addr lsr_id)
1482{
1483 struct nbr_params *nbrp;
1484
1485 if (nbr_params_find(conf, lsr_id))
1486 return (NULL);
1487
1488 nbrp = nbr_params_new(lsr_id);
76c4abd1 1489 RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp);
1d75a89d 1490 QOBJ_REG(nbrp, nbr_params);
bbee85d2
RW
1491 return (nbrp);
1492}
1493
1494void
76c4abd1 1495nbrp_del_api(struct ldpd_conf *conf, struct nbr_params *nbrp)
bbee85d2 1496{
1d75a89d 1497 QOBJ_UNREG(nbrp);
76c4abd1 1498 RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
bbee85d2
RW
1499 free(nbrp);
1500}
1501
1502struct l2vpn *
1503l2vpn_new_api(struct ldpd_conf *conf, const char *name)
1504{
1505 struct l2vpn *l2vpn;
1506
1507 if (l2vpn_find(conf, name))
1508 return (NULL);
1509
1510 l2vpn = l2vpn_new(name);
1511 l2vpn->type = L2VPN_TYPE_VPLS;
90d7e7bd 1512 RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn);
1d75a89d 1513 QOBJ_REG(l2vpn, l2vpn);
bbee85d2
RW
1514 return (l2vpn);
1515}
1516
1517void
90d7e7bd 1518l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn)
bbee85d2
RW
1519{
1520 struct l2vpn_if *lif;
1521 struct l2vpn_pw *pw;
1522
55cd0f61
DS
1523 while (!RB_EMPTY(l2vpn_if_head, &l2vpn->if_tree)) {
1524 lif = RB_ROOT(l2vpn_if_head, &l2vpn->if_tree);
1525
1d75a89d 1526 QOBJ_UNREG(lif);
029c1958 1527 RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
bbee85d2
RW
1528 free(lif);
1529 }
55cd0f61
DS
1530 while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_tree)) {
1531 pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_tree);
1532
1d75a89d 1533 QOBJ_UNREG(pw);
20bacaeb 1534 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
bbee85d2
RW
1535 free(pw);
1536 }
55cd0f61
DS
1537 while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_inactive_tree)) {
1538 pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_inactive_tree);
1539
1d75a89d 1540 QOBJ_UNREG(pw);
20bacaeb 1541 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
bbee85d2
RW
1542 free(pw);
1543 }
1d75a89d 1544 QOBJ_UNREG(l2vpn);
90d7e7bd 1545 RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
bbee85d2
RW
1546 free(l2vpn);
1547}
1548
1549struct l2vpn_if *
1550l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
1551 const char *ifname)
1552{
1553 struct l2vpn_if *lif;
bbee85d2
RW
1554
1555 if (ldp_iface_is_configured(conf, ifname))
1556 return (NULL);
1557
52b530fc 1558 lif = l2vpn_if_new(l2vpn, ifname);
029c1958 1559 RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
1d75a89d 1560 QOBJ_REG(lif, l2vpn_if);
bbee85d2
RW
1561 return (lif);
1562}
1563
1564void
029c1958 1565l2vpn_if_del_api(struct l2vpn *l2vpn, struct l2vpn_if *lif)
bbee85d2 1566{
1d75a89d 1567 QOBJ_UNREG(lif);
029c1958 1568 RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
bbee85d2
RW
1569 free(lif);
1570}
1571
1572struct l2vpn_pw *
1573l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
1574 const char *ifname)
1575{
1576 struct l2vpn_pw *pw;
bbee85d2
RW
1577
1578 if (ldp_iface_is_configured(conf, ifname))
1579 return (NULL);
1580
52b530fc 1581 pw = l2vpn_pw_new(l2vpn, ifname);
bbee85d2 1582 pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
20bacaeb 1583 RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
1d75a89d 1584 QOBJ_REG(pw, l2vpn_pw);
bbee85d2
RW
1585 return (pw);
1586}
1587
1588void
20bacaeb 1589l2vpn_pw_del_api(struct l2vpn *l2vpn, struct l2vpn_pw *pw)
bbee85d2 1590{
1d75a89d 1591 QOBJ_UNREG(pw);
20bacaeb 1592 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
bbee85d2
RW
1593 free(pw);
1594}