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