libldp_a_SOURCES = \
accept.c address.c adjacency.c control.c hello.c init.c interface.c \
keepalive.c l2vpn.c labelmapping.c lde.c lde_lib.c ldpd.c \
- ldpe.c log.c neighbor.c notification.c packet.c pfkey.c \
+ ldpe.c log.c logmsg.c neighbor.c notification.c packet.c pfkey.c \
socket.c util.c ldp_vty_cmds.c ldp_vty_conf.c ldp_vty_exec.c \
ldp_debug.c ldp_zebra.c
static int adj_itimer(struct thread *);
static __inline int tnbr_compare(struct tnbr *, struct tnbr *);
static void tnbr_del(struct ldpd_conf *, struct tnbr *);
+static void tnbr_start(struct tnbr *);
+static void tnbr_stop(struct tnbr *);
static int tnbr_hello_timer(struct thread *);
static void tnbr_start_hello_timer(struct tnbr *);
static void tnbr_stop_hello_timer(struct tnbr *);
static void
tnbr_del(struct ldpd_conf *xconf, struct tnbr *tnbr)
{
- tnbr_stop_hello_timer(tnbr);
- if (tnbr->adj)
- adj_del(tnbr->adj, S_SHUTDOWN);
+ tnbr_stop(tnbr);
RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr);
free(tnbr);
}
return (tnbr);
}
+static void
+tnbr_start(struct tnbr *tnbr)
+{
+ send_hello(HELLO_TARGETED, NULL, tnbr);
+ tnbr_start_hello_timer(tnbr);
+ tnbr->state = TNBR_STA_ACTIVE;
+}
+
+static void
+tnbr_stop(struct tnbr *tnbr)
+{
+ tnbr_stop_hello_timer(tnbr);
+ if (tnbr->adj)
+ adj_del(tnbr->adj, S_SHUTDOWN);
+ tnbr->state = TNBR_STA_DOWN;
+}
+
void
tnbr_update(struct tnbr *tnbr)
{
if (!socket_ok || !rtr_id_ok)
return;
- tnbr->state = TNBR_STA_ACTIVE;
- send_hello(HELLO_TARGETED, NULL, tnbr);
-
- tnbr_start_hello_timer(tnbr);
+ tnbr_start(tnbr);
} else if (tnbr->state == TNBR_STA_ACTIVE) {
if (socket_ok && rtr_id_ok)
return;
- tnbr->state = TNBR_STA_DOWN;
- tnbr_stop_hello_timer(tnbr);
+ tnbr_stop(tnbr);
}
}
static int control_fd;
int
-control_init(void)
+control_init(char *path)
{
struct sockaddr_un s_un;
int fd;
memset(&s_un, 0, sizeof(s_un));
s_un.sun_family = AF_UNIX;
- strlcpy(s_un.sun_path, ctl_sock_path, sizeof(s_un.sun_path));
+ strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path));
- if (unlink(ctl_sock_path) == -1)
+ if (unlink(path) == -1)
if (errno != ENOENT) {
- log_warn("%s: unlink %s", __func__, ctl_sock_path);
+ log_warn("%s: unlink %s", __func__, path);
close(fd);
return (-1);
}
old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
if (bind(fd, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
- log_warn("%s: bind: %s", __func__, ctl_sock_path);
+ log_warn("%s: bind: %s", __func__, path);
close(fd);
umask(old_umask);
return (-1);
}
umask(old_umask);
- if (chmod(ctl_sock_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
+ if (chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
log_warn("%s: chmod", __func__);
close(fd);
- (void)unlink(ctl_sock_path);
+ (void)unlink(path);
return (-1);
}
}
void
-control_cleanup(void)
+control_cleanup(char *path)
{
accept_del(control_fd);
close(control_fd);
- unlink(ctl_sock_path);
+ unlink(path);
}
/* ARGSUSED */
extern struct ctl_conns ctl_conns;
-int control_init(void);
+int control_init(char *);
int control_listen(void);
-void control_cleanup(void);
+void control_cleanup(char *);
int control_imsg_relay(struct imsg *);
#endif /* _CONTROL_H_ */
}
send_hello(HELLO_LINK, ia, NULL);
-
if_start_hello_timer(ia);
+ ia->state = IF_STA_ACTIVE;
+
return (0);
}
if_leave_ipv6_group(iface, &global.mcast_addr_v6);
break;
default:
- fatalx("if_start: unknown af");
+ fatalx("if_reset: unknown af");
}
+ ia->state = IF_STA_DOWN;
+
return (0);
}
!rtr_id_ok)
return;
- ia->state = IF_STA_ACTIVE;
if_start(ia->iface, ia->af);
} else if (ia->state == IF_STA_ACTIVE) {
if (ia->enabled && link_ok && addr_ok && socket_ok && rtr_id_ok)
return;
- ia->state = IF_STA_DOWN;
if_reset(ia->iface, ia->af);
}
}
static int lde_address_add(struct lde_nbr *, struct lde_addr *);
static int lde_address_del(struct lde_nbr *, struct lde_addr *);
static void lde_address_list_free(struct lde_nbr *);
-static void zclient_sync_init (u_short instance);
+static void zclient_sync_init(u_short instance);
static void lde_label_list_init(void);
-static int lde_get_label_chunk (void);
+static int lde_get_label_chunk(void);
static void on_get_label_chunk_response(uint32_t start, uint32_t end);
static uint32_t lde_get_next_label(void);
};
/* List of chunks of labels externally assigned by Zebra */
-struct list *label_chunk_list;
-struct listnode *current_label_chunk;
+static struct list *label_chunk_list;
+static struct listnode *current_label_chunk;
+
+/* Synchronous zclient to request labels */
+static struct zclient *zclient_sync;
/* SIGINT / SIGTERM handler. */
static void
},
};
-static void
-lde_sleep (void)
-{
- sleep(1);
- if (lde_signals[0].caught || lde_signals[1].caught)
- lde_shutdown();
-}
-struct zclient *zclient_sync = NULL;
-static void
-zclient_sync_init(u_short instance)
-{
- /* Initialize special zclient for synchronous message exchanges. */
- log_debug("Initializing synchronous zclient for label manager");
- zclient_sync = zclient_new(master);
- zclient_sync->sock = -1;
- zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
- zclient_sync->instance = instance;
- while (zclient_socket_connect (zclient_sync) < 0) {
- fprintf(stderr, "Error connecting synchronous zclient!\n");
- lde_sleep();
- }
-
- /* Connect to label manager */
- while (lm_label_manager_connect (zclient_sync) != 0) {
- fprintf(stderr, "Error connecting to label manager!\n");
- lde_sleep();
- }
-}
-
/* label decision engine */
void
-lde(const char *user, const char *group, u_short instance)
+lde(void)
{
struct thread thread;
- struct timeval now;
-
- ldeconf = config_new_empty();
#ifdef HAVE_SETPROCTITLE
setproctitle("label decision engine");
#endif
ldpd_process = PROC_LDE_ENGINE;
-
- /* drop privileges */
- if (user)
- lde_privs.user = user;
- if (group)
- lde_privs.group = group;
- zprivs_init(&lde_privs);
-
-#ifdef HAVE_PLEDGE
- if (pledge("stdio recvfd unix", NULL) == -1)
- fatal("pledge");
-#endif
+ log_procname = log_procnames[PROC_LDE_ENGINE];
master = thread_master_create();
fatal(NULL);
imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
+ /* create base configuration */
+ ldeconf = config_new_empty();
+
+ /* Fetch next active thread. */
+ while (thread_fetch(master, &thread))
+ thread_call(&thread);
+}
+
+void
+lde_init(struct ldpd_init *init)
+{
+ /* drop privileges */
+ if (init->user)
+ lde_privs.user = init->user;
+ if (init->group)
+ lde_privs.group = init->group;
+ zprivs_init(&lde_privs);
+
+#ifdef HAVE_PLEDGE
+ if (pledge("stdio recvfd unix", NULL) == -1)
+ fatal("pledge");
+#endif
+
/* start the LIB garbage collector */
lde_gc_start_timer();
- gettimeofday(&now, NULL);
- global.uptime = now.tv_sec;
-
/* Init synchronous zclient and label list */
- zclient_sync_init(instance);
+ zclient_serv_path_set(init->zclient_serv_path);
+ zclient_sync_init(init->instance);
lde_label_list_init();
-
- /* Fetch next active thread. */
- while (thread_fetch(master, &thread))
- thread_call(&thread);
}
static void
lde_shutdown(void)
{
/* close pipes */
- msgbuf_clear(&iev_ldpe->ibuf.w);
- close(iev_ldpe->ibuf.fd);
+ if (iev_ldpe) {
+ msgbuf_clear(&iev_ldpe->ibuf.w);
+ close(iev_ldpe->ibuf.fd);
+ }
msgbuf_clear(&iev_main->ibuf.w);
close(iev_main->ibuf.fd);
msgbuf_clear(&iev_main_sync->ibuf.w);
config_clear(ldeconf);
- free(iev_ldpe);
+ if (iev_ldpe)
+ free(iev_ldpe);
free(iev_main);
free(iev_main_sync);
return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
}
+void
+lde_imsg_compose_parent_sync(int type, pid_t pid, void *data, uint16_t datalen)
+{
+ imsg_compose_event(iev_main_sync, type, 0, pid, -1, data, datalen);
+ imsg_flush(&iev_main_sync->ibuf);
+}
+
int
lde_imsg_compose_ldpe(int type, uint32_t peerid, pid_t pid, void *data,
uint16_t datalen)
iev_ldpe->handler_write = ldp_write_handler;
iev_ldpe->ev_write = NULL;
break;
+ case IMSG_INIT:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct ldpd_init))
+ fatalx("INIT imsg with wrong len");
+
+ memcpy(&init, imsg.data, sizeof(init));
+ lde_init(&init);
+ break;
case IMSG_RECONF_CONF:
if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
NULL)
fn->local_label > MPLS_LABEL_RESERVED_MAX)
return (fn->local_label);
- return lde_get_next_label ();
+ return (lde_get_next_label());
}
void
void
lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single)
{
- struct lde_req *lre;
- struct lde_map *me;
- struct map map;
- struct l2vpn_pw *pw;
+ struct lde_wdraw *lw;
+ struct lde_map *me;
+ struct lde_req *lre;
+ struct map map;
+ struct l2vpn_pw *pw;
+
+ /*
+ * We shouldn't send a new label mapping if we have a pending
+ * label release to receive. In this case, schedule to send a
+ * label mapping as soon as a label release is received.
+ */
+ lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
+ if (lw) {
+ if (!fec_find(&ln->sent_map_pending, &fn->fec))
+ lde_map_pending_add(ln, fn);
+ return;
+ }
/*
* This function skips SL.1 - 3 and SL.9 - 14 because the label
ln->peerid = peerid;
fec_init(&ln->recv_map);
fec_init(&ln->sent_map);
+ fec_init(&ln->sent_map_pending);
fec_init(&ln->recv_req);
fec_init(&ln->sent_req);
fec_init(&ln->sent_wdraw);
fec_clear(&ln->recv_map, lde_map_free);
fec_clear(&ln->sent_map, lde_map_free);
+ fec_clear(&ln->sent_map_pending, free);
fec_clear(&ln->recv_req, free);
fec_clear(&ln->sent_req, free);
fec_clear(&ln->sent_wdraw, free);
free(map);
}
+struct fec *
+lde_map_pending_add(struct lde_nbr *ln, struct fec_node *fn)
+{
+ struct fec *map;
+
+ map = calloc(1, sizeof(*map));
+ if (map == NULL)
+ fatal(__func__);
+
+ *map = fn->fec;
+ if (fec_insert(&ln->sent_map_pending, map))
+ log_warnx("failed to add %s to sent map (pending)",
+ log_fec(map));
+
+ return (map);
+}
+
+void
+lde_map_pending_del(struct lde_nbr *ln, struct fec *map)
+{
+ fec_remove(&ln->sent_map_pending, map);
+ free(map);
+}
+
struct lde_req *
lde_req_add(struct lde_nbr *ln, struct fec *fec, int sent)
{
}
}
+static void
+zclient_sync_init(u_short instance)
+{
+ /* Initialize special zclient for synchronous message exchanges. */
+ log_debug("Initializing synchronous zclient for label manager");
+ zclient_sync = zclient_new(master);
+ zclient_sync->sock = -1;
+ zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
+ zclient_sync->instance = instance;
+ while (zclient_socket_connect(zclient_sync) < 0) {
+ log_warnx("Error connecting synchronous zclient!");
+ sleep(1);
+ }
+
+ /* Connect to label manager */
+ while (lm_label_manager_connect(zclient_sync) != 0) {
+ log_warnx("Error connecting to label manager!");
+ sleep(1);
+ }
+}
+
static void
lde_del_label_chunk(void *val)
{
free(val);
}
+
static int
lde_get_label_chunk(void)
{
- int ret;
- uint32_t start, end;
+ int ret;
+ uint32_t start, end;
log_debug("Getting label chunk");
ret = lm_get_label_chunk(zclient_sync, 0, CHUNK_SIZE, &start, &end);
- if (ret < 0)
- {
+ if (ret < 0) {
log_warnx("Error getting label chunk!");
close(zclient_sync->sock);
zclient_sync->sock = -1;
on_get_label_chunk_response(start, end);
- return 0;
+ return (0);
}
+
static void
lde_label_list_init(void)
{
/* get first chunk */
while (lde_get_label_chunk () != 0) {
- fprintf(stderr, "Error getting first label chunk!\n");
- lde_sleep();
+ log_warnx("Error getting first label chunk!");
+ sleep(1);
}
}
static uint32_t
lde_get_next_label(void)
{
- struct label_chunk *label_chunk;
- uint32_t i, pos, size;
- uint32_t label = NO_LABEL;
+ struct label_chunk *label_chunk;
+ uint32_t i, pos, size;
+ uint32_t label = NO_LABEL;
while (current_label_chunk) {
label_chunk = listgetdata(current_label_chunk);
end:
/* we moved till the last chunk, or were not able to find a label,
so let's ask for another one */
- if (!current_label_chunk || current_label_chunk == listtail(label_chunk_list)
- || label == NO_LABEL) {
+ if (!current_label_chunk ||
+ current_label_chunk == listtail(label_chunk_list) ||
+ label == NO_LABEL) {
if (lde_get_label_chunk() != 0)
log_warn("%s: Error getting label chunk!", __func__);
}
- return label;
+ return (label);
}
struct fec_tree sent_req;
struct fec_tree recv_map;
struct fec_tree sent_map;
+ struct fec_tree sent_map_pending;
struct fec_tree sent_wdraw;
TAILQ_HEAD(, lde_addr) addr_list;
};
extern struct thread *gc_timer;
/* lde.c */
-void lde(const char *, const char *, u_short instance);
+void lde(void);
+void lde_init(struct ldpd_init *);
int lde_imsg_compose_parent(int, pid_t, void *, uint16_t);
+void lde_imsg_compose_parent_sync(int, pid_t, void *, uint16_t);
int lde_imsg_compose_ldpe(int, uint32_t, pid_t, void *, uint16_t);
int lde_acl_check(char *, int, union ldpd_addr *, uint8_t);
uint32_t lde_update_label(struct fec_node *);
struct lde_nbr *lde_nbr_find_by_addr(int, union ldpd_addr *);
struct lde_map *lde_map_add(struct lde_nbr *, struct fec_node *, int);
void lde_map_del(struct lde_nbr *, struct lde_map *, int);
+struct fec *lde_map_pending_add(struct lde_nbr *, struct fec_node *);
+void lde_map_pending_del(struct lde_nbr *, struct fec *);
struct lde_req *lde_req_add(struct lde_nbr *, struct fec *, int);
void lde_req_del(struct lde_nbr *, struct lde_req *, int);
struct lde_wdraw *lde_wdraw_add(struct lde_nbr *, struct fec_node *);
if (LIST_EMPTY(&fn->nexthops)) {
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
lde_send_labelwithdraw(ln, fn, NULL, NULL);
- fn->local_label = NO_LABEL;
fn->data = NULL;
- } else {
- uint32_t previous_label;
- previous_label = fn->local_label;
+ /*
+ * Do not deallocate the local label now, do that only in the
+ * LIB garbage collector. This will prevent ldpd from changing
+ * the input label of some prefixes too often when running on
+ * an unstable network. Also, restart the garbage collector
+ * timer so that labels are deallocated only when the network
+ * is stabilized.
+ */
+ lde_gc_start_timer();
+ } else {
fn->local_label = lde_update_label(fn);
-
- if (fn->local_label != NO_LABEL &&
- fn->local_label != previous_label) {
+ if (fn->local_label != NO_LABEL && RB_EMPTY(&fn->upstream))
/* FEC.1: perform lsr label distribution procedure */
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
lde_send_labelmapping(ln, fn, 1);
- }
}
LIST_FOREACH(fnh, &fn->nexthops, entry) {
struct fec_node *fn;
struct lde_wdraw *lw;
struct lde_map *me;
+ struct fec *pending_map;
/* wildcard label release */
if (map->type == MAP_TYPE_WILDCARD ||
if (fn == NULL)
return;
+ /* LRl.6: check sent map list and remove it if available */
+ me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
+ if (me && (map->label == NO_LABEL || map->label == me->map.label))
+ lde_map_del(ln, me, 1);
+
/* LRl.3: first check if we have a pending withdraw running */
lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
/* LRl.4: delete record of outstanding label withdraw */
lde_wdraw_del(ln, lw);
- }
- /* LRl.6: check sent map list and remove it if available */
- me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
- if (me && (map->label == NO_LABEL || map->label == me->map.label))
- lde_map_del(ln, me, 1);
+ /* send pending label mapping if any */
+ pending_map = fec_find(&ln->sent_map_pending, &fn->fec);
+ if (pending_map) {
+ lde_send_labelmapping(ln, fn, 1);
+ lde_map_pending_del(ln, pending_map);
+ }
+ }
/*
* LRl.11 - 13 are unnecessary since we remove the label from
struct fec_node *fn;
struct lde_wdraw *lw;
struct lde_map *me;
+ struct fec *pending_map;
RB_FOREACH(f, fec_tree, &ft) {
fn = (struct fec_node *)f;
if (lde_wildcard_apply(map, &fn->fec, me) == 0)
continue;
+ /* LRl.6: check sent map list and remove it if available */
+ if (me &&
+ (map->label == NO_LABEL || map->label == me->map.label))
+ lde_map_del(ln, me, 1);
+
/* LRl.3: first check if we have a pending withdraw running */
lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
/* LRl.4: delete record of outstanding lbl withdraw */
lde_wdraw_del(ln, lw);
- }
- /* LRl.6: check sent map list and remove it if available */
- if (me &&
- (map->label == NO_LABEL || map->label == me->map.label))
- lde_map_del(ln, me, 1);
+ /* send pending label mapping if any */
+ pending_map = fec_find(&ln->sent_map_pending, &fn->fec);
+ if (pending_map) {
+ lde_send_labelmapping(ln, fn, 1);
+ lde_map_pending_del(ln, pending_map);
+ }
+ }
/*
* LRl.11 - 13 are unnecessary since we remove the label from
struct iface *iface;
if (ldp_iface_is_configured(conf, ifname))
- return NULL;
+ return (NULL);
iface = if_new(name);
RB_INSERT(iface_head, &conf->iface_tree, iface);
nbr_state_name(nbr->nbr_state), addr);
if (strlen(addr) > 15)
vty_out(vty, "%s%48s", VTY_NEWLINE, " ");
- vty_out(vty, " %8s%s", nbr->uptime == 0 ? "-" :
- log_time(nbr->uptime), VTY_NEWLINE);
+ vty_out(vty, " %8s%s", log_time(nbr->uptime), VTY_NEWLINE);
break;
case IMSG_CTL_END:
return (1);
vty_out(vty, "Peer LDP Identifier: %s:0%s", inet_ntoa(nbr->id),
VTY_NEWLINE);
show_nbr_capabilities(vty, nbr);
+ vty_out(vty, "%s", VTY_NEWLINE);
break;
case IMSG_CTL_END:
vty_out(vty, "%s", VTY_NEWLINE);
struct kroute kr;
int nhnum = 0, nhlen;
size_t nhmark;
+ int add = 0;
memset(&kr, 0, sizeof(kr));
s = zclient->ibuf;
if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP))
stream_set_getp(s, nhmark);
- if (nhnum == 0) {
- switch (command) {
- case ZEBRA_REDISTRIBUTE_IPV4_ADD:
- case ZEBRA_REDISTRIBUTE_IPV6_ADD:
- return (0);
- case ZEBRA_REDISTRIBUTE_IPV4_DEL:
- case ZEBRA_REDISTRIBUTE_IPV6_DEL:
- debug_zebra_in("route delete %s/%d (%s)",
- log_addr(kr.af, &kr.prefix), kr.prefixlen,
- zebra_route_string(type));
- break;
- default:
- fatalx("ldp_zebra_read_route: unknown command");
- }
- }
+ if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD ||
+ command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
+ add = 1;
+
+ if (nhnum == 0)
+ debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete",
+ log_addr(kr.af, &kr.prefix), kr.prefixlen,
+ zebra_route_string(type));
/* loop through all the nexthops */
for (; nhnum > 0; nhnum--) {
stream_getc(s); /* ifindex_num, unused. */
kr.ifindex = stream_getl(s);
- switch (command) {
- case ZEBRA_REDISTRIBUTE_IPV4_ADD:
- case ZEBRA_REDISTRIBUTE_IPV6_ADD:
- debug_zebra_in("route add %s/%d nexthop %s "
- "ifindex %u (%s)", log_addr(kr.af, &kr.prefix),
- kr.prefixlen, log_addr(kr.af, &kr.nexthop),
- kr.ifindex, zebra_route_string(type));
+ debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)",
+ (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix),
+ kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex,
+ zebra_route_string(type));
+
+ if (add)
main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr,
sizeof(kr));
- break;
- default:
- break;
- }
}
main_imsg_compose_lde(IMSG_NETWORK_UPDATE, 0, &kr, sizeof(kr));
#include "libfrr.h"
static void ldpd_shutdown(void);
-static pid_t start_child(enum ldpd_process, char *, int, int,
- const char *, const char *, const char *, const char *);
+static pid_t start_child(enum ldpd_process, char *, int, int);
static int main_dispatch_ldpe(struct thread *);
static int main_dispatch_lde(struct thread *);
static int main_imsg_send_ipc_sockets(struct imsgbuf *,
DEFINE_QOBJ_TYPE(ldpd_conf)
struct ldpd_global global;
+struct ldpd_init init;
struct ldpd_conf *ldpd_conf, *vty_conf;
static struct imsgev *iev_ldpe, *iev_ldpe_sync;
int lflag = 0, eflag = 0;
int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2];
int pipe_parent2lde[2], pipe_parent2lde_sync[2];
- char *ctl_sock_custom_path = NULL;
char *ctl_sock_name;
- const char *user = NULL;
- const char *group = NULL;
- u_short instance = 0;
- const char *instance_char = NULL;
ldpd_process = PROC_MAIN;
+ log_procname = log_procnames[ldpd_process];
saved_argv0 = argv[0];
if (saved_argv0 == NULL)
* sensible config
*/
ctl_sock_name = (char *)LDPD_SOCKET;
- ctl_sock_custom_path = optarg;
- strlcpy(ctl_sock_path, ctl_sock_custom_path,
- sizeof(ctl_sock_path));
+ strlcpy(ctl_sock_path, optarg, sizeof(ctl_sock_path));
strlcat(ctl_sock_path, "/", sizeof(ctl_sock_path));
strlcat(ctl_sock_path, ctl_sock_name,
sizeof(ctl_sock_path));
break;
case 'n':
- instance = atoi(optarg);
- instance_char = optarg;
- if (instance < 1)
+ init.instance = atoi(optarg);
+ if (init.instance < 1)
exit(0);
break;
case 'L':
}
}
- user = ldpd_privs.user;
- group = ldpd_privs.group;
+ strlcpy(init.user, ldpd_privs.user, sizeof(init.user));
+ strlcpy(init.group, ldpd_privs.group, sizeof(init.group));
+ strlcpy(init.ctl_sock_path, ctl_sock_path, sizeof(init.ctl_sock_path));
+ strlcpy(init.zclient_serv_path, zclient_serv_path_get(),
+ sizeof(init.zclient_serv_path));
argc -= optind;
argv += optind;
exit(1);
}
- if (lflag)
- lde(user, group, instance);
- else if (eflag)
- ldpe(user, group, ctl_sock_path);
-
openzlog(ldpd_di.progname, "LDP", 0,
LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON);
+ if (lflag)
+ lde();
+ else if (eflag)
+ ldpe();
+
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1)
fatal("socketpair");
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
/* start children */
lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0,
- pipe_parent2lde[1], pipe_parent2lde_sync[1],
- user, group, ctl_sock_custom_path, instance_char);
+ pipe_parent2lde[1], pipe_parent2lde_sync[1]);
ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0,
- pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1],
- user, group, ctl_sock_custom_path, instance_char);
+ pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1]);
/* drop privileges */
zprivs_init(&ldpd_privs);
if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf))
fatal("could not establish imsg links");
+ main_imsg_compose_both(IMSG_INIT, &init, sizeof(init));
main_imsg_compose_both(IMSG_DEBUG_UPDATE, &ldp_debug,
sizeof(ldp_debug));
main_imsg_send_config(ldpd_conf);
}
static pid_t
-start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync,
- const char *user, const char *group, const char *ctl_sock_custom_path,
- const char *instance)
+start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync)
{
- char *argv[13];
+ char *argv[3];
int argc = 0;
pid_t pid;
argv[argc++] = (char *)"-E";
break;
}
- if (user) {
- argv[argc++] = (char *)"-u";
- argv[argc++] = (char *)user;
- }
- if (group) {
- argv[argc++] = (char *)"-g";
- argv[argc++] = (char *)group;
- }
- if (ctl_sock_custom_path) {
- argv[argc++] = (char *)"--ctl_socket";
- argv[argc++] = (char *)ctl_sock_custom_path;
- }
- /* zclient serv path */
- argv[argc++] = (char *)"-z";
- argv[argc++] = (char *)zclient_serv_path_get();
- /* instance */
- if (instance) {
- argv[argc++] = (char *)"-n";
- argv[argc++] = (char *)instance;
- }
argv[argc++] = NULL;
execvp(argv0, argv);
IMSG_DEBUG_UPDATE,
IMSG_LOG,
IMSG_ACL_CHECK,
- IMSG_GET_LABEL_CHUNK,
- IMSG_RELEASE_LABEL_CHUNK
+ IMSG_INIT
+};
+
+struct ldpd_init {
+ char user[256];
+ char group[256];
+ char ctl_sock_path[MAXPATHLEN];
+ char zclient_serv_path[MAXPATHLEN];
+ u_short instance;
};
union ldpd_addr {
PROC_LDE_ENGINE
} ldpd_process;
+static const char * const log_procnames[] = {
+ "parent",
+ "ldpe",
+ "lde"
+};
+
enum socket_type {
LDP_SOCKET_DISC,
LDP_SOCKET_EDISC,
struct ldpd_global {
int cmd_opts;
int sighup;
- time_t uptime;
struct in_addr rtr_id;
struct ldpd_af_global ipv4;
struct ldpd_af_global ipv6;
extern struct ldpd_conf *ldpd_conf, *vty_conf;
extern struct ldpd_global global;
+extern struct ldpd_init init;
/* parse.y */
struct ldpd_conf *parse_config(char *);
int sock_set_ipv6_mcast(struct iface *);
int sock_set_ipv6_mcast_loop(int);
+/* logmsg.h */
+struct in6_addr;
+union ldpd_addr;
+struct hello_source;
+struct fec;
+
+const char *log_sockaddr(void *);
+const char *log_in6addr(const struct in6_addr *);
+const char *log_in6addr_scope(const struct in6_addr *, unsigned int);
+const char *log_addr(int, const union ldpd_addr *);
+char *log_label(uint32_t);
+const char *log_time(time_t);
+char *log_hello_src(const struct hello_source *);
+const char *log_map(const struct map *);
+const char *log_fec(const struct fec *);
+const char *af_name(int);
+const char *socket_name(int);
+const char *nbr_state_name(int);
+const char *if_state_name(int);
+const char *if_type_name(enum iface_type);
+const char *msg_name(uint16_t);
+const char *status_code_name(uint32_t);
+const char *pw_type_name(uint16_t);
+
/* quagga */
extern struct thread_master *master;
extern char ctl_sock_path[MAXPATHLEN];
/* label distribution protocol engine */
void
-ldpe(const char *user, const char *group, const char *ctl_path)
+ldpe(void)
{
struct thread thread;
- leconf = config_new_empty();
-
#ifdef HAVE_SETPROCTITLE
setproctitle("ldp engine");
#endif
ldpd_process = PROC_LDP_ENGINE;
-
- LIST_INIT(&global.addr_list);
- RB_INIT(&global.adj_tree);
- TAILQ_INIT(&global.pending_conns);
- if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
- fatal("inet_pton");
- if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
- fatal("inet_pton");
-#ifdef __OpenBSD__
- global.pfkeysock = pfkey_init();
-#endif
-
- /* drop privileges */
- if (user)
- ldpe_privs.user = user;
- if (group)
- ldpe_privs.group = group;
- zprivs_init(&ldpe_privs);
-
- strlcpy(ctl_sock_path, ctl_path, sizeof(ctl_sock_path));
- if (control_init() == -1)
- fatalx("control socket setup failed");
-
-#ifdef HAVE_PLEDGE
- if (pledge("stdio cpath inet mcast recvfd", NULL) == -1)
- fatal("pledge");
-#endif
+ log_procname = log_procnames[ldpd_process];
master = thread_master_create();
- accept_init();
/* setup signal handler */
signal_init(master, array_size(ldpe_signals), ldpe_signals);
fatal(NULL);
imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
+ /* create base configuration */
+ leconf = config_new_empty();
+
+ /* Fetch next active thread. */
+ while (thread_fetch(master, &thread))
+ thread_call(&thread);
+}
+
+void
+ldpe_init(struct ldpd_init *init)
+{
+ /* drop privileges */
+ if (init->user)
+ ldpe_privs.user = init->user;
+ if (init->group)
+ ldpe_privs.group = init->group;
+ zprivs_init(&ldpe_privs);
+
+ /* listen on ldpd control socket */
+ strlcpy(ctl_sock_path, init->ctl_sock_path, sizeof(ctl_sock_path));
+ if (control_init(ctl_sock_path) == -1)
+ fatalx("control socket setup failed");
+ TAILQ_INIT(&ctl_conns);
+ control_listen();
+
+#ifdef HAVE_PLEDGE
+ if (pledge("stdio cpath inet mcast recvfd", NULL) == -1)
+ fatal("pledge");
+#endif
+
+ LIST_INIT(&global.addr_list);
+ RB_INIT(&global.adj_tree);
+ TAILQ_INIT(&global.pending_conns);
+ if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
+ fatal("inet_pton");
+ if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
+ fatal("inet_pton");
#ifdef __OpenBSD__
+ global.pfkeysock = pfkey_init();
if (sysdep.no_pfkey == 0)
pfkey_ev = thread_add_read(master, ldpe_dispatch_pfkey,
NULL, global.pfkeysock);
global.ipv6.ldp_edisc_socket = -1;
global.ipv6.ldp_session_socket = -1;
- /* listen on ldpd control socket */
- TAILQ_INIT(&ctl_conns);
- control_listen();
-
if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
fatal(__func__);
- /* Fetch next active thread. */
- while (thread_fetch(master, &thread))
- thread_call(&thread);
+ accept_init();
}
static void
struct adj *adj;
/* close pipes */
- msgbuf_write(&iev_lde->ibuf.w);
- msgbuf_clear(&iev_lde->ibuf.w);
- close(iev_lde->ibuf.fd);
+ if (iev_lde) {
+ msgbuf_write(&iev_lde->ibuf.w);
+ msgbuf_clear(&iev_lde->ibuf.w);
+ close(iev_lde->ibuf.fd);
+ }
msgbuf_write(&iev_main->ibuf.w);
msgbuf_clear(&iev_main->ibuf.w);
close(iev_main->ibuf.fd);
msgbuf_clear(&iev_main_sync->ibuf.w);
close(iev_main_sync->ibuf.fd);
- control_cleanup();
+ control_cleanup(ctl_sock_path);
config_clear(leconf);
#ifdef __OpenBSD__
adj_del(adj, S_SHUTDOWN);
/* clean up */
- free(iev_lde);
+ if (iev_lde)
+ free(iev_lde);
free(iev_main);
free(iev_main_sync);
free(pkt_ptr);
return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
}
+void
+ldpe_imsg_compose_parent_sync(int type, pid_t pid, void *data, uint16_t datalen)
+{
+ imsg_compose_event(iev_main_sync, type, 0, pid, -1, data, datalen);
+ imsg_flush(&iev_main_sync->ibuf);
+}
+
int
ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
uint16_t datalen)
iev_lde->handler_write = ldp_write_handler;
iev_lde->ev_write = NULL;
break;
+ case IMSG_INIT:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct ldpd_init))
+ fatalx("INIT imsg with wrong len");
+
+ memcpy(&init, imsg.data, sizeof(init));
+ ldpe_init(&init);
+ break;
case IMSG_CLOSE_SOCKETS:
af = imsg.hdr.peerid;
uint16_t, struct map *);
/* ldpe.c */
-void ldpe(const char *, const char *, const char *);
+void ldpe(void);
+void ldpe_init(struct ldpd_init *);
int ldpe_imsg_compose_parent(int, pid_t, void *,
uint16_t);
+void ldpe_imsg_compose_parent_sync(int, pid_t, void *, uint16_t);
int ldpe_imsg_compose_lde(int, uint32_t, pid_t, void *,
uint16_t);
int ldpe_acl_check(char *, int, union ldpd_addr *, uint8_t);
#include <lib/log.h>
#include <lib/log_int.h>
-#include "mpls.h"
-static const char * const procnames[] = {
- "parent",
- "ldpe",
- "lde"
-};
-
-void vlog(int, const char *, va_list);
+const char *log_procname;
void
logit(int pri, const char *fmt, ...)
switch (ldpd_process) {
case PROC_LDE_ENGINE:
vsnprintf(buf, sizeof(buf), fmt, ap);
- lde_imsg_compose_parent(IMSG_LOG, pri, buf, strlen(buf) + 1);
+ lde_imsg_compose_parent_sync(IMSG_LOG, pri, buf,
+ strlen(buf) + 1);
break;
case PROC_LDP_ENGINE:
vsnprintf(buf, sizeof(buf), fmt, ap);
- ldpe_imsg_compose_parent(IMSG_LOG, pri, buf, strlen(buf) + 1);
+ ldpe_imsg_compose_parent_sync(IMSG_LOG, pri, buf,
+ strlen(buf) + 1);
break;
case PROC_MAIN:
vzlog(pri, fmt, ap);
/* best effort to even work in out of memory situations */
if (emsg == NULL)
- logit(LOG_CRIT, "%s", strerror(errno));
+ logit(LOG_ERR, "%s", strerror(errno));
else {
va_start(ap, emsg);
if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
/* we tried it... */
- vlog(LOG_CRIT, emsg, ap);
- logit(LOG_CRIT, "%s", strerror(errno));
+ vlog(LOG_ERR, emsg, ap);
+ logit(LOG_ERR, "%s", strerror(errno));
} else {
- vlog(LOG_CRIT, nfmt, ap);
+ vlog(LOG_ERR, nfmt, ap);
free(nfmt);
}
va_end(ap);
va_list ap;
va_start(ap, emsg);
- vlog(LOG_CRIT, emsg, ap);
+ vlog(LOG_ERR, emsg, ap);
va_end(ap);
}
fatal(const char *emsg)
{
if (emsg == NULL)
- logit(LOG_CRIT, "fatal in %s: %s", procnames[ldpd_process],
+ logit(LOG_CRIT, "fatal in %s: %s", log_procname,
strerror(errno));
else
if (errno)
logit(LOG_CRIT, "fatal in %s: %s: %s",
- procnames[ldpd_process], emsg, strerror(errno));
+ log_procname, emsg, strerror(errno));
else
logit(LOG_CRIT, "fatal in %s: %s",
- procnames[ldpd_process], emsg);
+ log_procname, emsg);
exit(1);
}
errno = 0;
fatal(emsg);
}
-
-#define NUM_LOGS 4
-const char *
-log_sockaddr(void *vp)
-{
- static char buf[NUM_LOGS][NI_MAXHOST];
- static int round = 0;
- struct sockaddr *sa = vp;
-
- round = (round + 1) % NUM_LOGS;
-
- if (getnameinfo(sa, sockaddr_len(sa), buf[round], NI_MAXHOST, NULL, 0,
- NI_NUMERICHOST))
- return ("(unknown)");
- else
- return (buf[round]);
-}
-
-const char *
-log_in6addr(const struct in6_addr *addr)
-{
- struct sockaddr_in6 sa_in6;
-
- memset(&sa_in6, 0, sizeof(sa_in6));
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- sa_in6.sin6_len = sizeof(sa_in6);
-#endif
- sa_in6.sin6_family = AF_INET6;
- sa_in6.sin6_addr = *addr;
-
- recoverscope(&sa_in6);
-
- return (log_sockaddr(&sa_in6));
-}
-
-const char *
-log_in6addr_scope(const struct in6_addr *addr, unsigned int ifindex)
-{
- struct sockaddr_in6 sa_in6;
-
- memset(&sa_in6, 0, sizeof(sa_in6));
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- sa_in6.sin6_len = sizeof(sa_in6);
-#endif
- sa_in6.sin6_family = AF_INET6;
- sa_in6.sin6_addr = *addr;
-
- addscope(&sa_in6, ifindex);
-
- return (log_sockaddr(&sa_in6));
-}
-
-const char *
-log_addr(int af, const union ldpd_addr *addr)
-{
- static char buf[NUM_LOGS][INET6_ADDRSTRLEN];
- static int round = 0;
-
- switch (af) {
- case AF_INET:
- round = (round + 1) % NUM_LOGS;
- if (inet_ntop(AF_INET, &addr->v4, buf[round],
- sizeof(buf[round])) == NULL)
- return ("???");
- return (buf[round]);
- case AF_INET6:
- return (log_in6addr(&addr->v6));
- default:
- break;
- }
-
- return ("???");
-}
-
-#define TF_BUFS 4
-#define TF_LEN 32
-
-char *
-log_label(uint32_t label)
-{
- char *buf;
- static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */
- static int idx = 0;
-
- buf = tfbuf[idx++];
- if (idx == TF_BUFS)
- idx = 0;
-
- switch (label) {
- case NO_LABEL:
- snprintf(buf, TF_LEN, "-");
- break;
- case MPLS_LABEL_IMPLNULL:
- snprintf(buf, TF_LEN, "imp-null");
- break;
- case MPLS_LABEL_IPV4NULL:
- case MPLS_LABEL_IPV6NULL:
- snprintf(buf, TF_LEN, "exp-null");
- break;
- default:
- snprintf(buf, TF_LEN, "%u", label);
- break;
- }
-
- return (buf);
-}
-
-const char *
-log_time(time_t t)
-{
- char *buf;
- static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */
- static int idx = 0;
- unsigned int sec, min, hrs, day, week;
-
- buf = tfbuf[idx++];
- if (idx == TF_BUFS)
- idx = 0;
-
- week = t;
-
- sec = week % 60;
- week /= 60;
- min = week % 60;
- week /= 60;
- hrs = week % 24;
- week /= 24;
- day = week % 7;
- week /= 7;
-
- if (week > 0)
- snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
- else if (day > 0)
- snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
- else
- snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
-
- return (buf);
-}
-
-char *
-log_hello_src(const struct hello_source *src)
-{
- static char buf[64];
-
- switch (src->type) {
- case HELLO_LINK:
- snprintf(buf, sizeof(buf), "iface %s",
- src->link.ia->iface->name);
- break;
- case HELLO_TARGETED:
- snprintf(buf, sizeof(buf), "source %s",
- log_addr(src->target->af, &src->target->addr));
- break;
- }
-
- return (buf);
-}
-
-const char *
-log_map(const struct map *map)
-{
- static char buf[128];
-
- switch (map->type) {
- case MAP_TYPE_WILDCARD:
- if (snprintf(buf, sizeof(buf), "wildcard") < 0)
- return ("???");
- break;
- case MAP_TYPE_PREFIX:
- if (snprintf(buf, sizeof(buf), "%s/%u",
- log_addr(map->fec.prefix.af, &map->fec.prefix.prefix),
- map->fec.prefix.prefixlen) == -1)
- return ("???");
- break;
- case MAP_TYPE_PWID:
- if (snprintf(buf, sizeof(buf), "pw-id %u group-id %u (%s)",
- map->fec.pwid.pwid, map->fec.pwid.group_id,
- pw_type_name(map->fec.pwid.type)) == -1)
- return ("???");
- break;
- case MAP_TYPE_TYPED_WCARD:
- if (snprintf(buf, sizeof(buf), "typed wildcard") < 0)
- return ("???");
- switch (map->fec.twcard.type) {
- case MAP_TYPE_PREFIX:
- if (snprintf(buf + strlen(buf), sizeof(buf) -
- strlen(buf), " (prefix, address-family %s)",
- af_name(map->fec.twcard.u.prefix_af)) < 0)
- return ("???");
- break;
- case MAP_TYPE_PWID:
- if (snprintf(buf + strlen(buf), sizeof(buf) -
- strlen(buf), " (pwid, type %s)",
- pw_type_name(map->fec.twcard.u.pw_type)) < 0)
- return ("???");
- break;
- default:
- if (snprintf(buf + strlen(buf), sizeof(buf) -
- strlen(buf), " (unknown type)") < 0)
- return ("???");
- break;
- }
- break;
- default:
- return ("???");
- }
-
- return (buf);
-}
-
-const char *
-log_fec(const struct fec *fec)
-{
- static char buf[64];
- union ldpd_addr addr;
-
- switch (fec->type) {
- case FEC_TYPE_IPV4:
- addr.v4 = fec->u.ipv4.prefix;
- if (snprintf(buf, sizeof(buf), "ipv4 %s/%u",
- log_addr(AF_INET, &addr), fec->u.ipv4.prefixlen) == -1)
- return ("???");
- break;
- case FEC_TYPE_IPV6:
- addr.v6 = fec->u.ipv6.prefix;
- if (snprintf(buf, sizeof(buf), "ipv6 %s/%u",
- log_addr(AF_INET6, &addr), fec->u.ipv6.prefixlen) == -1)
- return ("???");
- break;
- case FEC_TYPE_PWID:
- if (snprintf(buf, sizeof(buf),
- "pwid %u (%s) - %s",
- fec->u.pwid.pwid, pw_type_name(fec->u.pwid.type),
- inet_ntoa(fec->u.pwid.lsr_id)) == -1)
- return ("???");
- break;
- default:
- return ("???");
- }
-
- return (buf);
-}
-
-/* names */
-const char *
-af_name(int af)
-{
- switch (af) {
- case AF_INET:
- return ("ipv4");
- case AF_INET6:
- return ("ipv6");
-#ifdef AF_MPLS
- case AF_MPLS:
- return ("mpls");
-#endif
- default:
- return ("UNKNOWN");
- }
-}
-
-const char *
-socket_name(int type)
-{
- switch (type) {
- case LDP_SOCKET_DISC:
- return ("discovery");
- case LDP_SOCKET_EDISC:
- return ("extended discovery");
- case LDP_SOCKET_SESSION:
- return ("session");
- default:
- return ("UNKNOWN");
- }
-}
-
-const char *
-nbr_state_name(int state)
-{
- switch (state) {
- case NBR_STA_PRESENT:
- return ("PRESENT");
- case NBR_STA_INITIAL:
- return ("INITIALIZED");
- case NBR_STA_OPENREC:
- return ("OPENREC");
- case NBR_STA_OPENSENT:
- return ("OPENSENT");
- case NBR_STA_OPER:
- return ("OPERATIONAL");
- default:
- return ("UNKNOWN");
- }
-}
-
-const char *
-if_state_name(int state)
-{
- switch (state) {
- case IF_STA_DOWN:
- return ("DOWN");
- case IF_STA_ACTIVE:
- return ("ACTIVE");
- default:
- return ("UNKNOWN");
- }
-}
-
-const char *
-if_type_name(enum iface_type type)
-{
- switch (type) {
- case IF_TYPE_POINTOPOINT:
- return ("POINTOPOINT");
- case IF_TYPE_BROADCAST:
- return ("BROADCAST");
- }
- /* NOTREACHED */
- return ("UNKNOWN");
-}
-
-const char *
-msg_name(uint16_t msg)
-{
- static char buf[16];
-
- switch (msg) {
- case MSG_TYPE_NOTIFICATION:
- return ("notification");
- case MSG_TYPE_HELLO:
- return ("hello");
- case MSG_TYPE_INIT:
- return ("initialization");
- case MSG_TYPE_KEEPALIVE:
- return ("keepalive");
- case MSG_TYPE_CAPABILITY:
- return ("capability");
- case MSG_TYPE_ADDR:
- return ("address");
- case MSG_TYPE_ADDRWITHDRAW:
- return ("address withdraw");
- case MSG_TYPE_LABELMAPPING:
- return ("label mapping");
- case MSG_TYPE_LABELREQUEST:
- return ("label request");
- case MSG_TYPE_LABELWITHDRAW:
- return ("label withdraw");
- case MSG_TYPE_LABELRELEASE:
- return ("label release");
- case MSG_TYPE_LABELABORTREQ:
- default:
- snprintf(buf, sizeof(buf), "[%08x]", msg);
- return (buf);
- }
-}
-
-const char *
-status_code_name(uint32_t status)
-{
- static char buf[16];
-
- switch (status) {
- case S_SUCCESS:
- return ("Success");
- case S_BAD_LDP_ID:
- return ("Bad LDP Identifier");
- case S_BAD_PROTO_VER:
- return ("Bad Protocol Version");
- case S_BAD_PDU_LEN:
- return ("Bad PDU Length");
- case S_UNKNOWN_MSG:
- return ("Unknown Message Type");
- case S_BAD_MSG_LEN:
- return ("Bad Message Length");
- case S_UNKNOWN_TLV:
- return ("Unknown TLV");
- case S_BAD_TLV_LEN:
- return ("Bad TLV Length");
- case S_BAD_TLV_VAL:
- return ("Malformed TLV Value");
- case S_HOLDTIME_EXP:
- return ("Hold Timer Expired");
- case S_SHUTDOWN:
- return ("Shutdown");
- case S_LOOP_DETECTED:
- return ("Loop Detected");
- case S_UNKNOWN_FEC:
- return ("Unknown FEC");
- case S_NO_ROUTE:
- return ("No Route");
- case S_NO_LABEL_RES:
- return ("No Label Resources");
- case S_AVAILABLE:
- return ("Label Resources Available");
- case S_NO_HELLO:
- return ("Session Rejected, No Hello");
- case S_PARM_ADV_MODE:
- return ("Rejected Advertisement Mode Parameter");
- case S_MAX_PDU_LEN:
- return ("Rejected Max PDU Length Parameter");
- case S_PARM_L_RANGE:
- return ("Rejected Label Range Parameter");
- case S_KEEPALIVE_TMR:
- return ("KeepAlive Timer Expired");
- case S_LAB_REQ_ABRT:
- return ("Label Request Aborted");
- case S_MISS_MSG:
- return ("Missing Message Parameters");
- case S_UNSUP_ADDR:
- return ("Unsupported Address Family");
- case S_KEEPALIVE_BAD:
- return ("Bad KeepAlive Time");
- case S_INTERN_ERR:
- return ("Internal Error");
- case S_ILLEGAL_CBIT:
- return ("Illegal C-Bit");
- case S_WRONG_CBIT:
- return ("Wrong C-Bit");
- case S_INCPT_BITRATE:
- return ("Incompatible bit-rate");
- case S_CEP_MISCONF:
- return ("CEP-TDM mis-configuration");
- case S_PW_STATUS:
- return ("PW Status");
- case S_UNASSIGN_TAI:
- return ("Unassigned/Unrecognized TAI");
- case S_MISCONF_ERR:
- return ("Generic Misconfiguration Error");
- case S_WITHDRAW_MTHD:
- return ("Label Withdraw PW Status Method");
- case S_UNSSUPORTDCAP:
- return ("Unsupported Capability");
- case S_ENDOFLIB:
- return ("End-of-LIB");
- case S_TRANS_MISMTCH:
- return ("Transport Connection Mismatch");
- case S_DS_NONCMPLNCE:
- return ("Dual-Stack Noncompliance");
- default:
- snprintf(buf, sizeof(buf), "[%08x]", status);
- return (buf);
- }
-}
-
-const char *
-pw_type_name(uint16_t pw_type)
-{
- static char buf[64];
-
- switch (pw_type) {
- case PW_TYPE_ETHERNET_TAGGED:
- return ("Eth Tagged");
- case PW_TYPE_ETHERNET:
- return ("Ethernet");
- case PW_TYPE_WILDCARD:
- return ("Wildcard");
- default:
- snprintf(buf, sizeof(buf), "[%0x]", pw_type);
- return (buf);
- }
-}
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef _LOG_H_
-#define _LOG_H_
+#ifndef LOG_H
+#define LOG_H
#include <stdarg.h>
-struct in6_addr;
-union ldpd_addr;
-struct hello_source;
-struct fec;
+extern const char *log_procname;
-void logit(int, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)));
-void log_warn(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_warnx(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_info(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_notice(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_debug(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void fatal(const char *)
- __attribute__ ((noreturn))
- __attribute__((__format__ (printf, 1, 0)));
-void fatalx(const char *)
- __attribute__ ((noreturn))
- __attribute__((__format__ (printf, 1, 0)));
-const char *log_sockaddr(void *);
-const char *log_in6addr(const struct in6_addr *);
-const char *log_in6addr_scope(const struct in6_addr *, unsigned int);
-const char *log_addr(int, const union ldpd_addr *);
-char *log_label(uint32_t);
-const char *log_time(time_t);
-char *log_hello_src(const struct hello_source *);
-const char *log_map(const struct map *);
-const char *log_fec(const struct fec *);
-const char *af_name(int);
-const char *socket_name(int);
-const char *nbr_state_name(int);
-const char *if_state_name(int);
-const char *if_type_name(enum iface_type);
-const char *msg_name(uint16_t);
-const char *status_code_name(uint32_t);
-const char *pw_type_name(uint16_t);
+void logit(int, const char *, ...)
+ __attribute__((__format__ (printf, 2, 3)));
+void vlog(int, const char *, va_list)
+ __attribute__((__format__ (printf, 2, 0)));
+void log_warn(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_warnx(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_info(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_notice(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_debug(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void fatal(const char *)
+ __attribute__ ((noreturn))
+ __attribute__((__format__ (printf, 1, 0)));
+void fatalx(const char *)
+ __attribute__ ((noreturn))
+ __attribute__((__format__ (printf, 1, 0)));
-#endif /* _LOG_H_ */
+#endif /* LOG_H */
--- /dev/null
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <zebra.h>
+
+#include "mpls.h"
+
+#include "ldpd.h"
+#include "ldpe.h"
+#include "lde.h"
+
+#define NUM_LOGS 4
+const char *
+log_sockaddr(void *vp)
+{
+ static char buf[NUM_LOGS][NI_MAXHOST];
+ static int round = 0;
+ struct sockaddr *sa = vp;
+
+ round = (round + 1) % NUM_LOGS;
+
+ if (getnameinfo(sa, sockaddr_len(sa), buf[round], NI_MAXHOST, NULL, 0,
+ NI_NUMERICHOST))
+ return ("(unknown)");
+ else
+ return (buf[round]);
+}
+
+const char *
+log_in6addr(const struct in6_addr *addr)
+{
+ struct sockaddr_in6 sa_in6;
+
+ memset(&sa_in6, 0, sizeof(sa_in6));
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+ sa_in6.sin6_len = sizeof(sa_in6);
+#endif
+ sa_in6.sin6_family = AF_INET6;
+ sa_in6.sin6_addr = *addr;
+
+ recoverscope(&sa_in6);
+
+ return (log_sockaddr(&sa_in6));
+}
+
+const char *
+log_in6addr_scope(const struct in6_addr *addr, unsigned int ifindex)
+{
+ struct sockaddr_in6 sa_in6;
+
+ memset(&sa_in6, 0, sizeof(sa_in6));
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+ sa_in6.sin6_len = sizeof(sa_in6);
+#endif
+ sa_in6.sin6_family = AF_INET6;
+ sa_in6.sin6_addr = *addr;
+
+ addscope(&sa_in6, ifindex);
+
+ return (log_sockaddr(&sa_in6));
+}
+
+const char *
+log_addr(int af, const union ldpd_addr *addr)
+{
+ static char buf[NUM_LOGS][INET6_ADDRSTRLEN];
+ static int round = 0;
+
+ switch (af) {
+ case AF_INET:
+ round = (round + 1) % NUM_LOGS;
+ if (inet_ntop(AF_INET, &addr->v4, buf[round],
+ sizeof(buf[round])) == NULL)
+ return ("???");
+ return (buf[round]);
+ case AF_INET6:
+ return (log_in6addr(&addr->v6));
+ default:
+ break;
+ }
+
+ return ("???");
+}
+
+#define TF_BUFS 4
+#define TF_LEN 32
+
+char *
+log_label(uint32_t label)
+{
+ char *buf;
+ static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */
+ static int idx = 0;
+
+ buf = tfbuf[idx++];
+ if (idx == TF_BUFS)
+ idx = 0;
+
+ switch (label) {
+ case NO_LABEL:
+ snprintf(buf, TF_LEN, "-");
+ break;
+ case MPLS_LABEL_IMPLNULL:
+ snprintf(buf, TF_LEN, "imp-null");
+ break;
+ case MPLS_LABEL_IPV4NULL:
+ case MPLS_LABEL_IPV6NULL:
+ snprintf(buf, TF_LEN, "exp-null");
+ break;
+ default:
+ snprintf(buf, TF_LEN, "%u", label);
+ break;
+ }
+
+ return (buf);
+}
+
+const char *
+log_time(time_t t)
+{
+ char *buf;
+ static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */
+ static int idx = 0;
+ unsigned int sec, min, hrs, day, week;
+
+ buf = tfbuf[idx++];
+ if (idx == TF_BUFS)
+ idx = 0;
+
+ week = t;
+
+ sec = week % 60;
+ week /= 60;
+ min = week % 60;
+ week /= 60;
+ hrs = week % 24;
+ week /= 24;
+ day = week % 7;
+ week /= 7;
+
+ if (week > 0)
+ snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
+ else if (day > 0)
+ snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
+ else
+ snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
+
+ return (buf);
+}
+
+char *
+log_hello_src(const struct hello_source *src)
+{
+ static char buf[64];
+
+ switch (src->type) {
+ case HELLO_LINK:
+ snprintf(buf, sizeof(buf), "iface %s",
+ src->link.ia->iface->name);
+ break;
+ case HELLO_TARGETED:
+ snprintf(buf, sizeof(buf), "source %s",
+ log_addr(src->target->af, &src->target->addr));
+ break;
+ }
+
+ return (buf);
+}
+
+const char *
+log_map(const struct map *map)
+{
+ static char buf[128];
+
+ switch (map->type) {
+ case MAP_TYPE_WILDCARD:
+ if (snprintf(buf, sizeof(buf), "wildcard") < 0)
+ return ("???");
+ break;
+ case MAP_TYPE_PREFIX:
+ if (snprintf(buf, sizeof(buf), "%s/%u",
+ log_addr(map->fec.prefix.af, &map->fec.prefix.prefix),
+ map->fec.prefix.prefixlen) == -1)
+ return ("???");
+ break;
+ case MAP_TYPE_PWID:
+ if (snprintf(buf, sizeof(buf), "pw-id %u group-id %u (%s)",
+ map->fec.pwid.pwid, map->fec.pwid.group_id,
+ pw_type_name(map->fec.pwid.type)) == -1)
+ return ("???");
+ break;
+ case MAP_TYPE_TYPED_WCARD:
+ if (snprintf(buf, sizeof(buf), "typed wildcard") < 0)
+ return ("???");
+ switch (map->fec.twcard.type) {
+ case MAP_TYPE_PREFIX:
+ if (snprintf(buf + strlen(buf), sizeof(buf) -
+ strlen(buf), " (prefix, address-family %s)",
+ af_name(map->fec.twcard.u.prefix_af)) < 0)
+ return ("???");
+ break;
+ case MAP_TYPE_PWID:
+ if (snprintf(buf + strlen(buf), sizeof(buf) -
+ strlen(buf), " (pwid, type %s)",
+ pw_type_name(map->fec.twcard.u.pw_type)) < 0)
+ return ("???");
+ break;
+ default:
+ if (snprintf(buf + strlen(buf), sizeof(buf) -
+ strlen(buf), " (unknown type)") < 0)
+ return ("???");
+ break;
+ }
+ break;
+ default:
+ return ("???");
+ }
+
+ return (buf);
+}
+
+const char *
+log_fec(const struct fec *fec)
+{
+ static char buf[64];
+ union ldpd_addr addr;
+
+ switch (fec->type) {
+ case FEC_TYPE_IPV4:
+ addr.v4 = fec->u.ipv4.prefix;
+ if (snprintf(buf, sizeof(buf), "ipv4 %s/%u",
+ log_addr(AF_INET, &addr), fec->u.ipv4.prefixlen) == -1)
+ return ("???");
+ break;
+ case FEC_TYPE_IPV6:
+ addr.v6 = fec->u.ipv6.prefix;
+ if (snprintf(buf, sizeof(buf), "ipv6 %s/%u",
+ log_addr(AF_INET6, &addr), fec->u.ipv6.prefixlen) == -1)
+ return ("???");
+ break;
+ case FEC_TYPE_PWID:
+ if (snprintf(buf, sizeof(buf),
+ "pwid %u (%s) - %s",
+ fec->u.pwid.pwid, pw_type_name(fec->u.pwid.type),
+ inet_ntoa(fec->u.pwid.lsr_id)) == -1)
+ return ("???");
+ break;
+ default:
+ return ("???");
+ }
+
+ return (buf);
+}
+
+/* names */
+const char *
+af_name(int af)
+{
+ switch (af) {
+ case AF_INET:
+ return ("ipv4");
+ case AF_INET6:
+ return ("ipv6");
+#ifdef AF_MPLS
+ case AF_MPLS:
+ return ("mpls");
+#endif
+ default:
+ return ("UNKNOWN");
+ }
+}
+
+const char *
+socket_name(int type)
+{
+ switch (type) {
+ case LDP_SOCKET_DISC:
+ return ("discovery");
+ case LDP_SOCKET_EDISC:
+ return ("extended discovery");
+ case LDP_SOCKET_SESSION:
+ return ("session");
+ default:
+ return ("UNKNOWN");
+ }
+}
+
+const char *
+nbr_state_name(int state)
+{
+ switch (state) {
+ case NBR_STA_PRESENT:
+ return ("PRESENT");
+ case NBR_STA_INITIAL:
+ return ("INITIALIZED");
+ case NBR_STA_OPENREC:
+ return ("OPENREC");
+ case NBR_STA_OPENSENT:
+ return ("OPENSENT");
+ case NBR_STA_OPER:
+ return ("OPERATIONAL");
+ default:
+ return ("UNKNOWN");
+ }
+}
+
+const char *
+if_state_name(int state)
+{
+ switch (state) {
+ case IF_STA_DOWN:
+ return ("DOWN");
+ case IF_STA_ACTIVE:
+ return ("ACTIVE");
+ default:
+ return ("UNKNOWN");
+ }
+}
+
+const char *
+if_type_name(enum iface_type type)
+{
+ switch (type) {
+ case IF_TYPE_POINTOPOINT:
+ return ("POINTOPOINT");
+ case IF_TYPE_BROADCAST:
+ return ("BROADCAST");
+ }
+ /* NOTREACHED */
+ return ("UNKNOWN");
+}
+
+const char *
+msg_name(uint16_t msg)
+{
+ static char buf[16];
+
+ switch (msg) {
+ case MSG_TYPE_NOTIFICATION:
+ return ("notification");
+ case MSG_TYPE_HELLO:
+ return ("hello");
+ case MSG_TYPE_INIT:
+ return ("initialization");
+ case MSG_TYPE_KEEPALIVE:
+ return ("keepalive");
+ case MSG_TYPE_CAPABILITY:
+ return ("capability");
+ case MSG_TYPE_ADDR:
+ return ("address");
+ case MSG_TYPE_ADDRWITHDRAW:
+ return ("address withdraw");
+ case MSG_TYPE_LABELMAPPING:
+ return ("label mapping");
+ case MSG_TYPE_LABELREQUEST:
+ return ("label request");
+ case MSG_TYPE_LABELWITHDRAW:
+ return ("label withdraw");
+ case MSG_TYPE_LABELRELEASE:
+ return ("label release");
+ case MSG_TYPE_LABELABORTREQ:
+ default:
+ snprintf(buf, sizeof(buf), "[%08x]", msg);
+ return (buf);
+ }
+}
+
+const char *
+status_code_name(uint32_t status)
+{
+ static char buf[16];
+
+ switch (status) {
+ case S_SUCCESS:
+ return ("Success");
+ case S_BAD_LDP_ID:
+ return ("Bad LDP Identifier");
+ case S_BAD_PROTO_VER:
+ return ("Bad Protocol Version");
+ case S_BAD_PDU_LEN:
+ return ("Bad PDU Length");
+ case S_UNKNOWN_MSG:
+ return ("Unknown Message Type");
+ case S_BAD_MSG_LEN:
+ return ("Bad Message Length");
+ case S_UNKNOWN_TLV:
+ return ("Unknown TLV");
+ case S_BAD_TLV_LEN:
+ return ("Bad TLV Length");
+ case S_BAD_TLV_VAL:
+ return ("Malformed TLV Value");
+ case S_HOLDTIME_EXP:
+ return ("Hold Timer Expired");
+ case S_SHUTDOWN:
+ return ("Shutdown");
+ case S_LOOP_DETECTED:
+ return ("Loop Detected");
+ case S_UNKNOWN_FEC:
+ return ("Unknown FEC");
+ case S_NO_ROUTE:
+ return ("No Route");
+ case S_NO_LABEL_RES:
+ return ("No Label Resources");
+ case S_AVAILABLE:
+ return ("Label Resources Available");
+ case S_NO_HELLO:
+ return ("Session Rejected, No Hello");
+ case S_PARM_ADV_MODE:
+ return ("Rejected Advertisement Mode Parameter");
+ case S_MAX_PDU_LEN:
+ return ("Rejected Max PDU Length Parameter");
+ case S_PARM_L_RANGE:
+ return ("Rejected Label Range Parameter");
+ case S_KEEPALIVE_TMR:
+ return ("KeepAlive Timer Expired");
+ case S_LAB_REQ_ABRT:
+ return ("Label Request Aborted");
+ case S_MISS_MSG:
+ return ("Missing Message Parameters");
+ case S_UNSUP_ADDR:
+ return ("Unsupported Address Family");
+ case S_KEEPALIVE_BAD:
+ return ("Bad KeepAlive Time");
+ case S_INTERN_ERR:
+ return ("Internal Error");
+ case S_ILLEGAL_CBIT:
+ return ("Illegal C-Bit");
+ case S_WRONG_CBIT:
+ return ("Wrong C-Bit");
+ case S_INCPT_BITRATE:
+ return ("Incompatible bit-rate");
+ case S_CEP_MISCONF:
+ return ("CEP-TDM mis-configuration");
+ case S_PW_STATUS:
+ return ("PW Status");
+ case S_UNASSIGN_TAI:
+ return ("Unassigned/Unrecognized TAI");
+ case S_MISCONF_ERR:
+ return ("Generic Misconfiguration Error");
+ case S_WITHDRAW_MTHD:
+ return ("Label Withdraw PW Status Method");
+ case S_UNSSUPORTDCAP:
+ return ("Unsupported Capability");
+ case S_ENDOFLIB:
+ return ("End-of-LIB");
+ case S_TRANS_MISMTCH:
+ return ("Transport Connection Mismatch");
+ case S_DS_NONCMPLNCE:
+ return ("Dual-Stack Noncompliance");
+ default:
+ snprintf(buf, sizeof(buf), "[%08x]", status);
+ return (buf);
+ }
+}
+
+const char *
+pw_type_name(uint16_t pw_type)
+{
+ static char buf[64];
+
+ switch (pw_type) {
+ case PW_TYPE_ETHERNET_TAGGED:
+ return ("Eth Tagged");
+ case PW_TYPE_ETHERNET:
+ return ("Ethernet");
+ case PW_TYPE_WILDCARD:
+ return ("Wildcard");
+ default:
+ snprintf(buf, sizeof(buf), "[%0x]", pw_type);
+ return (buf);
+ }
+}
if (nbr->state == NBR_STA_OPENSENT)
nbr_start_idtimer(nbr);
+ /*
+ * RFC 5036 - Section 3.5.1.1:
+ * "When an LSR receives a Shutdown message during session
+ * initialization, it SHOULD transmit a Shutdown message and
+ * then close the transport connection".
+ */
+ if (nbr->state != NBR_STA_OPER && nm.status_code == S_SHUTDOWN)
+ send_notification(nbr->tcp, S_SHUTDOWN,
+ msg.id, msg.type);
+
nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
return (-1);
}
#include "sockopt.h"
static struct iface *disc_find_iface(unsigned int, int,
- union ldpd_addr *, int);
+ union ldpd_addr *);
static int session_read(struct thread *);
static int session_write(struct thread *);
static ssize_t session_get_pdu(struct ibuf_read *, char **);
int af;
union ldpd_addr src;
unsigned int ifindex = 0;
- struct iface *iface;
+ struct iface *iface = NULL;
uint16_t len;
struct ldp_hdr ldp_hdr;
uint16_t pdu_len;
ifindex = getsockopt_ifindex(af, &m);
/* find a matching interface */
- iface = disc_find_iface(ifindex, af, &src, multicast);
- if (iface == NULL)
- return (0);
+ if (multicast) {
+ iface = disc_find_iface(ifindex, af, &src);
+ if (iface == NULL)
+ return (0);
+ }
/* check packet size */
len = (uint16_t)r;
}
static struct iface *
-disc_find_iface(unsigned int ifindex, int af, union ldpd_addr *src,
- int multicast)
+disc_find_iface(unsigned int ifindex, int af, union ldpd_addr *src)
{
struct iface *iface;
struct iface_af *ia;
* "Link-local IPv6 address MUST be used as the source IP address in
* IPv6 LDP Link Hellos".
*/
- if (multicast && af == AF_INET6 && !IN6_IS_ADDR_LINKLOCAL(&src->v6))
+ if (af == AF_INET6 && !IN6_IS_ADDR_LINKLOCAL(&src->v6))
return (NULL);
return (iface);
return (0);
}
break;
+ case MSG_TYPE_NOTIFICATION:
+ break;
default:
if (nbr->state != NBR_STA_OPER) {
session_shutdown(nbr, S_SHUTDOWN,
case NBR_STA_OPENREC:
case NBR_STA_OPENSENT:
case NBR_STA_OPER:
- log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
-
send_notification(nbr->tcp, status, msg_id, msg_type);
nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);