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