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