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