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