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