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