]>
Commit | Line | Data |
---|---|---|
eac6e3f0 RW |
1 | /* |
2 | * Copyright (C) 2016 by Open Source Routing. | |
3 | * | |
4 | * This file is part of GNU Zebra. | |
5 | * | |
6 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2, or (at your option) any | |
9 | * later version. | |
10 | * | |
11 | * GNU Zebra is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
18 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
19 | * 02111-1307, USA. | |
20 | */ | |
21 | ||
22 | #include <zebra.h> | |
23 | ||
24 | #include "ldpd.h" | |
25 | #include "ldpe.h" | |
26 | #include "lde.h" | |
27 | #include "log.h" | |
28 | ||
29 | #include "command.h" | |
30 | #include "vrf.h" | |
31 | #include "if.h" | |
32 | #include "vty.h" | |
33 | #include "ldp_vty.h" | |
34 | ||
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 | ||
eac6e3f0 RW |
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 | ||
7d3d7491 | 145 | RB_FOREACH(iface, iface_head, &ldpd_conf->iface_tree) { |
eac6e3f0 RW |
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 | ||
45a8eba9 RW |
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 | } | |
eac6e3f0 RW |
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 | ||
45a8eba9 RW |
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 | } | |
eac6e3f0 RW |
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 | ||
7989cdba | 259 | RB_FOREACH(tnbr, tnbr_head, &ldpd_conf->tnbr_tree) { |
eac6e3f0 RW |
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 | ||
76c4abd1 | 311 | RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) { |
eac6e3f0 RW |
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 | ||
90d7e7bd | 387 | RB_FOREACH(l2vpn, l2vpn_head, &ldpd_conf->l2vpn_tree) { |
eac6e3f0 RW |
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 | ||
029c1958 | 400 | RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) |
eac6e3f0 RW |
401 | vty_out(vty, " member interface %s%s", lif->ifname, |
402 | VTY_NEWLINE); | |
403 | ||
20bacaeb | 404 | RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) |
eac6e3f0 | 405 | ldp_l2vpn_pw_config_write(vty, pw); |
20bacaeb | 406 | RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) |
eac6e3f0 RW |
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 | ||
90d7e7bd | 439 | RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) { |
eac6e3f0 RW |
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; | |
f82a5428 RW |
490 | } else { |
491 | ldp_clear_config(vty_conf); | |
eac6e3f0 | 492 | return (CMD_WARNING); |
f82a5428 | 493 | } |
eac6e3f0 RW |
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 | ||
eac6e3f0 RW |
548 | switch (vty->node) { |
549 | case LDP_NODE: | |
0b47280e | 550 | vty_conf = ldp_dup_config(ldpd_conf); |
eac6e3f0 RW |
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 | } | |
0b47280e | 571 | ldp_reload(vty_conf); |
eac6e3f0 RW |
572 | break; |
573 | case LDP_IPV4_NODE: | |
574 | case LDP_IPV6_NODE: | |
0b47280e | 575 | vty_conf = ldp_dup_config(ldpd_conf); |
eac6e3f0 RW |
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 | } | |
0b47280e | 598 | ldp_reload(vty_conf); |
eac6e3f0 RW |
599 | break; |
600 | case LDP_IPV4_IFACE_NODE: | |
601 | case LDP_IPV6_IFACE_NODE: | |
602 | af = ldp_vty_get_af(vty); | |
0b47280e RW |
603 | iface = VTY_GET_CONTEXT(iface); |
604 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&iface); | |
eac6e3f0 | 605 | |
0b47280e | 606 | ia = iface_af_get(iface, af); |
eac6e3f0 RW |
607 | if (disable) |
608 | ia->hello_holdtime = 0; | |
609 | else | |
610 | ia->hello_holdtime = secs; | |
0b47280e | 611 | ldp_reload_ref(vty_conf, (void **)&iface); |
eac6e3f0 RW |
612 | break; |
613 | default: | |
614 | fatalx("ldp_vty_disc_holdtime: unexpected node"); | |
615 | } | |
616 | ||
eac6e3f0 RW |
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 | ||
eac6e3f0 RW |
651 | switch (vty->node) { |
652 | case LDP_NODE: | |
0b47280e | 653 | vty_conf = ldp_dup_config(ldpd_conf); |
eac6e3f0 RW |
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 | } | |
0b47280e | 674 | ldp_reload(vty_conf); |
eac6e3f0 RW |
675 | break; |
676 | case LDP_IPV4_NODE: | |
677 | case LDP_IPV6_NODE: | |
0b47280e | 678 | vty_conf = ldp_dup_config(ldpd_conf); |
eac6e3f0 RW |
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 | } | |
0b47280e | 701 | ldp_reload(vty_conf); |
eac6e3f0 RW |
702 | break; |
703 | case LDP_IPV4_IFACE_NODE: | |
704 | case LDP_IPV6_IFACE_NODE: | |
705 | af = ldp_vty_get_af(vty); | |
0b47280e RW |
706 | iface = VTY_GET_CONTEXT(iface); |
707 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&iface); | |
eac6e3f0 | 708 | |
0b47280e | 709 | ia = iface_af_get(iface, af); |
eac6e3f0 RW |
710 | if (disable) |
711 | ia->hello_interval = 0; | |
712 | else | |
713 | ia->hello_interval = secs; | |
0b47280e | 714 | ldp_reload_ref(vty_conf, (void **)&iface); |
eac6e3f0 RW |
715 | break; |
716 | default: | |
717 | fatalx("ldp_vty_disc_interval: unexpected node"); | |
718 | } | |
719 | ||
eac6e3f0 RW |
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; | |
45a8eba9 | 729 | const char *acl_from_str; |
eac6e3f0 RW |
730 | int disable; |
731 | ||
732 | vty_conf = ldp_dup_config(ldpd_conf); | |
733 | ||
734 | disable = (vty_get_arg_value(args, "no")) ? 1 : 0; | |
45a8eba9 | 735 | acl_from_str = vty_get_arg_value(args, "from_acl"); |
eac6e3f0 RW |
736 | |
737 | af = ldp_vty_get_af(vty); | |
738 | af_conf = ldp_af_conf_get(vty_conf, af); | |
739 | ||
45a8eba9 | 740 | if (disable) { |
eac6e3f0 | 741 | af_conf->flags &= ~F_LDPD_AF_THELLO_ACCEPT; |
45a8eba9 RW |
742 | af_conf->acl_thello_accept_from[0] = '\0'; |
743 | } else { | |
eac6e3f0 | 744 | af_conf->flags |= F_LDPD_AF_THELLO_ACCEPT; |
45a8eba9 RW |
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 | } | |
eac6e3f0 RW |
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); | |
76c4abd1 | 797 | RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); |
eac6e3f0 RW |
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; | |
271327b1 RW |
890 | ia->hello_holdtime = 0; |
891 | ia->hello_interval = 0; | |
eac6e3f0 RW |
892 | ldp_reload(vty_conf); |
893 | return (CMD_SUCCESS); | |
894 | } | |
895 | ||
eac6e3f0 RW |
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 | ||
1306c09a | 903 | ifp = if_lookup_by_name(ifname, VRF_DEFAULT); |
eac6e3f0 RW |
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; | |
7d3d7491 | 914 | RB_INSERT(iface_head, &vty_conf->iface_tree, iface); |
0b47280e | 915 | ldp_reload_ref(vty_conf, (void **)&iface); |
eac6e3f0 RW |
916 | } else { |
917 | memset(&kif, 0, sizeof(kif)); | |
918 | strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); | |
919 | ||
920 | ia = iface_af_get(iface, af); | |
0b47280e RW |
921 | if (!ia->enabled) { |
922 | ia->enabled = 1; | |
923 | ldp_reload_ref(vty_conf, (void **)&iface); | |
f82a5428 RW |
924 | } else |
925 | ldp_clear_config(vty_conf); | |
0b47280e RW |
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; | |
eac6e3f0 RW |
937 | } |
938 | ||
eac6e3f0 RW |
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 | ||
7989cdba | 1013 | RB_REMOVE(tnbr_head, &vty_conf->tnbr_tree, tnbr); |
eac6e3f0 RW |
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; | |
7989cdba | 1024 | RB_INSERT(tnbr_head, &vty_conf->tnbr_tree, tnbr); |
eac6e3f0 RW |
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 | |
45a8eba9 | 1036 | ldp_vty_label_advertise(struct vty *vty, struct vty_arg *args[]) |
eac6e3f0 RW |
1037 | { |
1038 | struct ldpd_conf *vty_conf; | |
1039 | struct ldpd_af_conf *af_conf; | |
1040 | int af; | |
45a8eba9 RW |
1041 | const char *acl_to_str; |
1042 | const char *acl_for_str; | |
eac6e3f0 RW |
1043 | int disable; |
1044 | ||
1045 | disable = (vty_get_arg_value(args, "no")) ? 1 : 0; | |
45a8eba9 RW |
1046 | acl_to_str = vty_get_arg_value(args, "to_acl"); |
1047 | acl_for_str = vty_get_arg_value(args, "for_acl"); | |
eac6e3f0 RW |
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 | ||
45a8eba9 RW |
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) { | |
eac6e3f0 | 1124 | af_conf->flags &= ~F_LDPD_AF_EXPNULL; |
45a8eba9 RW |
1125 | af_conf->acl_label_expnull_for[0] = '\0'; |
1126 | } else { | |
eac6e3f0 | 1127 | af_conf->flags |= F_LDPD_AF_EXPNULL; |
45a8eba9 RW |
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 | } | |
eac6e3f0 RW |
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); | |
76c4abd1 | 1307 | RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); |
eac6e3f0 RW |
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); | |
76c4abd1 | 1373 | RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); |
eac6e3f0 RW |
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 | ||
90d7e7bd | 1413 | RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); |
eac6e3f0 RW |
1414 | l2vpn_del(l2vpn); |
1415 | ldp_reload(vty_conf); | |
1416 | return (CMD_SUCCESS); | |
1417 | } | |
1418 | ||
0b47280e RW |
1419 | if (l2vpn) { |
1420 | VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); | |
eac6e3f0 | 1421 | goto cancel; |
0b47280e | 1422 | } |
eac6e3f0 RW |
1423 | |
1424 | l2vpn = l2vpn_new(name_str); | |
1425 | l2vpn->type = L2VPN_TYPE_VPLS; | |
90d7e7bd | 1426 | RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); |
eac6e3f0 | 1427 | |
2f49a594 | 1428 | ldp_reload_ref(vty_conf, (void **)&l2vpn); |
0b47280e | 1429 | VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); |
eac6e3f0 RW |
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 | ||
0b47280e RW |
1449 | l2vpn = VTY_GET_CONTEXT(l2vpn); |
1450 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); | |
eac6e3f0 RW |
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 | ||
0b47280e | 1457 | ldp_reload_ref(vty_conf, (void **)&l2vpn); |
eac6e3f0 RW |
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 | ||
0b47280e RW |
1481 | l2vpn = VTY_GET_CONTEXT(l2vpn); |
1482 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); | |
eac6e3f0 RW |
1483 | |
1484 | if (disable) | |
1485 | l2vpn->mtu = DEFAULT_L2VPN_MTU; | |
1486 | else | |
1487 | l2vpn->mtu = mtu; | |
1488 | ||
0b47280e | 1489 | ldp_reload_ref(vty_conf, (void **)&l2vpn); |
eac6e3f0 RW |
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 | ||
0b47280e RW |
1511 | l2vpn = VTY_GET_CONTEXT(l2vpn); |
1512 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); | |
eac6e3f0 RW |
1513 | |
1514 | if (disable) | |
1515 | l2vpn->pw_type = DEFAULT_PW_TYPE; | |
1516 | else | |
1517 | l2vpn->pw_type = pw_type; | |
1518 | ||
0b47280e | 1519 | ldp_reload_ref(vty_conf, (void **)&l2vpn); |
eac6e3f0 RW |
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 | ||
0b47280e RW |
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); | |
eac6e3f0 RW |
1541 | lif = l2vpn_if_find_name(l2vpn, ifname); |
1542 | ||
1543 | if (disable) { | |
1544 | if (lif == NULL) | |
1545 | goto cancel; | |
1546 | ||
029c1958 | 1547 | RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); |
eac6e3f0 RW |
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 | ||
1306c09a | 1561 | ifp = if_lookup_by_name(ifname, VRF_DEFAULT); |
eac6e3f0 RW |
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); | |
029c1958 | 1570 | RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); |
eac6e3f0 | 1571 | |
0b47280e | 1572 | ldp_reload_ref(vty_conf, (void **)&l2vpn); |
eac6e3f0 RW |
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 | ||
0b47280e RW |
1595 | l2vpn = VTY_GET_CONTEXT(l2vpn); |
1596 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); | |
eac6e3f0 RW |
1597 | pw = l2vpn_pw_find_name(l2vpn, ifname); |
1598 | ||
1599 | if (disable) { | |
1600 | if (pw == NULL) | |
1601 | goto cancel; | |
1602 | ||
20bacaeb | 1603 | RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); |
eac6e3f0 RW |
1604 | free(pw); |
1605 | ldp_reload(vty_conf); | |
1606 | return (CMD_SUCCESS); | |
1607 | } | |
1608 | ||
1609 | if (pw) { | |
2f49a594 | 1610 | VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); |
eac6e3f0 RW |
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 | ||
1306c09a | 1619 | ifp = if_lookup_by_name(ifname, VRF_DEFAULT); |
eac6e3f0 RW |
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; | |
20bacaeb | 1629 | RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); |
eac6e3f0 | 1630 | |
0b47280e | 1631 | ldp_reload_ref(vty_conf, (void **)&pw); |
2f49a594 | 1632 | VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); |
eac6e3f0 | 1633 | |
eac6e3f0 RW |
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; | |
eac6e3f0 RW |
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 | ||
2f49a594 | 1652 | pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); |
0b47280e | 1653 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); |
eac6e3f0 RW |
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 | ||
0b47280e | 1664 | ldp_reload_ref(vty_conf, (void **)&pw); |
eac6e3f0 RW |
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; | |
eac6e3f0 RW |
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 | ||
2f49a594 | 1688 | pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); |
0b47280e | 1689 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); |
eac6e3f0 RW |
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 | ||
0b47280e | 1701 | ldp_reload_ref(vty_conf, (void **)&pw); |
eac6e3f0 RW |
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; | |
eac6e3f0 RW |
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 | ||
2f49a594 | 1724 | pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); |
0b47280e | 1725 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); |
eac6e3f0 RW |
1726 | |
1727 | if (disable) | |
1728 | pw->lsr_id.s_addr = INADDR_ANY; | |
1729 | else | |
1730 | pw->lsr_id = lsr_id; | |
1731 | ||
0b47280e | 1732 | ldp_reload_ref(vty_conf, (void **)&pw); |
eac6e3f0 RW |
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; | |
eac6e3f0 RW |
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 | ||
2f49a594 | 1756 | pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); |
0b47280e | 1757 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); |
eac6e3f0 RW |
1758 | |
1759 | if (disable) | |
1760 | pw->pwid = 0; | |
1761 | else | |
1762 | pw->pwid = pwid; | |
1763 | ||
0b47280e | 1764 | ldp_reload_ref(vty_conf, (void **)&pw); |
eac6e3f0 RW |
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; | |
eac6e3f0 RW |
1773 | struct l2vpn_pw *pw; |
1774 | int disable; | |
1775 | ||
1776 | disable = (vty_get_arg_value(args, "no")) ? 1 : 0; | |
1777 | ||
2f49a594 | 1778 | pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); |
0b47280e | 1779 | vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); |
eac6e3f0 RW |
1780 | |
1781 | if (disable) | |
1782 | pw->flags |= F_PW_STATUSTLV_CONF; | |
1783 | else | |
1784 | pw->flags &= ~F_PW_STATUSTLV_CONF; | |
1785 | ||
0b47280e | 1786 | ldp_reload_ref(vty_conf, (void **)&pw); |
eac6e3f0 RW |
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); | |
0b84f294 | 1796 | if_cmd_init (); |
eac6e3f0 | 1797 | } |
bbee85d2 RW |
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)); | |
1306c09a | 1812 | ifp = if_lookup_by_name(ifname, VRF_DEFAULT); |
bbee85d2 RW |
1813 | if (ifp) { |
1814 | kif.ifindex = ifp->ifindex; | |
1815 | kif.flags = ifp->flags; | |
1816 | } | |
1817 | ||
1818 | iface = if_new(&kif); | |
7d3d7491 | 1819 | RB_INSERT(iface_head, &conf->iface_tree, iface); |
bbee85d2 RW |
1820 | return (iface); |
1821 | } | |
1822 | ||
1823 | void | |
7d3d7491 | 1824 | iface_del_api(struct ldpd_conf *conf, struct iface *iface) |
bbee85d2 | 1825 | { |
7d3d7491 | 1826 | RB_REMOVE(iface_head, &conf->iface_tree, iface); |
bbee85d2 RW |
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; | |
7989cdba | 1843 | RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr); |
bbee85d2 RW |
1844 | return (tnbr); |
1845 | } | |
1846 | ||
1847 | void | |
7989cdba | 1848 | tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr) |
bbee85d2 | 1849 | { |
7989cdba | 1850 | RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); |
bbee85d2 RW |
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); | |
76c4abd1 | 1863 | RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp); |
bbee85d2 RW |
1864 | return (nbrp); |
1865 | } | |
1866 | ||
1867 | void | |
76c4abd1 | 1868 | nbrp_del_api(struct ldpd_conf *conf, struct nbr_params *nbrp) |
bbee85d2 | 1869 | { |
76c4abd1 | 1870 | RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); |
bbee85d2 RW |
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; | |
90d7e7bd | 1884 | RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn); |
bbee85d2 RW |
1885 | return (l2vpn); |
1886 | } | |
1887 | ||
1888 | void | |
90d7e7bd | 1889 | l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn) |
bbee85d2 RW |
1890 | { |
1891 | struct l2vpn_if *lif; | |
1892 | struct l2vpn_pw *pw; | |
1893 | ||
029c1958 RW |
1894 | while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) { |
1895 | RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); | |
bbee85d2 RW |
1896 | free(lif); |
1897 | } | |
20bacaeb RW |
1898 | while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) { |
1899 | RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); | |
bbee85d2 RW |
1900 | free(pw); |
1901 | } | |
20bacaeb RW |
1902 | while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) { |
1903 | RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); | |
bbee85d2 RW |
1904 | free(pw); |
1905 | } | |
90d7e7bd | 1906 | RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); |
bbee85d2 RW |
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)); | |
1306c09a | 1923 | ifp = if_lookup_by_name(ifname, VRF_DEFAULT); |
bbee85d2 RW |
1924 | if (ifp) { |
1925 | kif.ifindex = ifp->ifindex; | |
1926 | kif.flags = ifp->flags; | |
1927 | } | |
1928 | ||
1929 | lif = l2vpn_if_new(l2vpn, &kif); | |
029c1958 | 1930 | RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); |
bbee85d2 RW |
1931 | return (lif); |
1932 | } | |
1933 | ||
1934 | void | |
029c1958 | 1935 | l2vpn_if_del_api(struct l2vpn *l2vpn, struct l2vpn_if *lif) |
bbee85d2 | 1936 | { |
029c1958 | 1937 | RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); |
bbee85d2 RW |
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)); | |
1306c09a | 1954 | ifp = if_lookup_by_name(ifname, VRF_DEFAULT); |
bbee85d2 RW |
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; | |
20bacaeb | 1962 | RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); |
bbee85d2 RW |
1963 | return (pw); |
1964 | } | |
1965 | ||
1966 | void | |
20bacaeb | 1967 | l2vpn_pw_del_api(struct l2vpn *l2vpn, struct l2vpn_pw *pw) |
bbee85d2 | 1968 | { |
20bacaeb | 1969 | RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); |
bbee85d2 RW |
1970 | free(pw); |
1971 | } |