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