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