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