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