Merge pull request #675 from opensourcerouting/ldpd-cherry-picks

ldpd: cherry-pick fixes from master to stable/3.0
This commit is contained in:
Donald Sharp 2017-06-06 08:24:47 -04:00 committed by GitHub
commit f46f475631
19 changed files with 869 additions and 758 deletions

View File

@ -16,7 +16,7 @@ EXTRA_DIST += ldp_vty.xml
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

View File

@ -29,6 +29,8 @@ static __inline int adj_compare(struct adj *, struct adj *);
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 *);
@ -245,9 +247,7 @@ tnbr_new(int af, union ldpd_addr *addr)
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);
}
@ -273,6 +273,23 @@ tnbr_check(struct ldpd_conf *xconf, struct tnbr *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)
{
@ -292,16 +309,12 @@ 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);
}
}

View File

@ -37,7 +37,7 @@ struct ctl_conns ctl_conns;
static int control_fd;
int
control_init(void)
control_init(char *path)
{
struct sockaddr_un s_un;
int fd;
@ -51,28 +51,28 @@ control_init(void)
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);
}
@ -93,11 +93,11 @@ control_listen(void)
}
void
control_cleanup(void)
control_cleanup(char *path)
{
accept_del(control_fd);
close(control_fd);
unlink(ctl_sock_path);
unlink(path);
}
/* ARGSUSED */

View File

@ -29,9 +29,9 @@ TAILQ_HEAD(ctl_conns, ctl_conn);
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_ */

View File

@ -287,8 +287,9 @@ if_start(struct iface *iface, int af)
}
send_hello(HELLO_LINK, ia, NULL);
if_start_hello_timer(ia);
ia->state = IF_STA_ACTIVE;
return (0);
}
@ -318,9 +319,11 @@ if_reset(struct iface *iface, int af)
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);
}
@ -367,14 +370,12 @@ if_update_af(struct iface_af *ia)
!socket_ok || !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 && ia->iface->operative && addr_ok &&
socket_ok && rtr_id_ok)
return;
ia->state = IF_STA_DOWN;
if_reset(ia->iface, ia->af);
}
}

View File

@ -80,10 +80,6 @@ static zebra_capabilities_t _caps_p [] =
static struct zebra_privs_t lde_privs =
{
#if defined(FRR_USER) && defined(FRR_GROUP)
.user = FRR_USER,
.group = FRR_GROUP,
#endif
#if defined(VTY_GROUP)
.vty_group = VTY_GROUP,
#endif
@ -119,13 +115,6 @@ static struct quagga_signal_t lde_signals[] =
},
};
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)
@ -137,44 +126,30 @@ zclient_sync_init(u_short instance)
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();
log_warnx("Error connecting synchronous zclient!");
sleep(1);
}
/* make socket non-blocking */
sock_set_nonblock(zclient_sync->sock);
/* Connect to label manager */
while (lm_label_manager_connect (zclient_sync) != 0) {
fprintf(stderr, "Error connecting to label manager!\n");
lde_sleep();
log_warnx("Error connecting to label manager!");
sleep(1);
}
}
/* 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();
@ -194,27 +169,44 @@ lde(const char *user, const char *group, u_short instance)
fatal(NULL);
imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
/* 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);
lde_label_list_init();
/* 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 */
lde_privs.user = init->user;
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();
/* Init synchronous zclient and label list */
zclient_serv_path_set(init->zclient_serv_path);
zclient_sync_init(init->instance);
lde_label_list_init();
}
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);
@ -226,7 +218,8 @@ lde_shutdown(void)
config_clear(ldeconf);
free(iev_ldpe);
if (iev_ldpe)
free(iev_ldpe);
free(iev_main);
free(iev_main_sync);
@ -241,6 +234,13 @@ lde_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
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)
@ -552,6 +552,14 @@ lde_dispatch_parent(struct thread *thread)
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)
@ -903,10 +911,23 @@ lde_map2fec(struct map *map, struct in_addr lsr_id, struct fec *fec)
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
@ -1212,6 +1233,7 @@ lde_nbr_new(uint32_t peerid, struct lde_nbr *new)
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);
@ -1267,6 +1289,7 @@ lde_nbr_del(struct lde_nbr *ln)
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);
@ -1417,6 +1440,30 @@ lde_map_free(void *ptr)
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)
{
@ -1613,8 +1660,8 @@ 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);
}
}

View File

@ -95,6 +95,7 @@ struct lde_nbr {
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;
};
@ -139,8 +140,10 @@ extern struct nbr_tree lde_nbrs;
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 *);
@ -169,6 +172,8 @@ struct lde_nbr *lde_nbr_find_by_lsrid(struct in_addr);
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 *);

View File

@ -383,20 +383,23 @@ lde_kernel_update(struct fec *fec)
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;
/*
* 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 {
uint32_t previous_label;
previous_label = fn->local_label;
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) {
@ -659,6 +662,7 @@ lde_check_release(struct map *map, struct lde_nbr *ln)
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 ||
@ -674,17 +678,24 @@ lde_check_release(struct map *map, struct lde_nbr *ln)
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
@ -699,6 +710,7 @@ lde_check_release_wcard(struct map *map, struct lde_nbr *ln)
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;
@ -708,17 +720,24 @@ lde_check_release_wcard(struct map *map, struct lde_nbr *ln)
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

View File

@ -517,8 +517,7 @@ show_nbr_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
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);
@ -909,6 +908,7 @@ show_nbr_capabilities_msg(struct vty *vty, struct imsg *imsg, struct show_params
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);

View File

@ -360,6 +360,7 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
struct kroute kr;
int nhnum = 0, nhlen;
size_t nhmark;
int add = 0;
memset(&kr, 0, sizeof(kr));
s = zclient->ibuf;
@ -426,21 +427,14 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
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--) {
@ -457,19 +451,14 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
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));

View File

@ -44,8 +44,7 @@
#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 *,
@ -77,6 +76,7 @@ DEFINE_QOBJ_TYPE(l2vpn)
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;
@ -200,14 +200,10 @@ main(int argc, char *argv[])
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)
@ -241,17 +237,14 @@ main(int argc, char *argv[])
* 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':
@ -266,8 +259,11 @@ main(int argc, char *argv[])
}
}
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;
@ -281,14 +277,14 @@ main(int argc, char *argv[])
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,
@ -316,11 +312,9 @@ main(int argc, char *argv[])
/* 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);
@ -388,6 +382,7 @@ main(int argc, char *argv[])
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);
@ -452,11 +447,9 @@ ldpd_shutdown(void)
}
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;
@ -487,29 +480,6 @@ start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync,
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 */
#ifdef HAVE_TCP_ZEBRA
#else
argv[argc++] = (char *)"-z";
argv[argc++] = (char *)zclient_serv_path_get();
#endif
/* instance */
if (instance) {
argv[argc++] = (char *)"-n";
argv[argc++] = (char *)instance;
}
argv[argc++] = NULL;
execvp(argv0, argv);
@ -1709,8 +1679,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
session_shutdown(nbr, S_SHUTDOWN, 0, 0);
}
}
if (ldpd_process == PROC_LDE_ENGINE &&
!reset_nbr && reinstall_pwfec)
if (ldpd_process == PROC_LDE_ENGINE && reinstall_pwfec)
l2vpn_pw_exit(pw);
pw->lsr_id = xp->lsr_id;
pw->af = xp->af;
@ -1732,8 +1701,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
pw->flags &= ~F_PW_STATIC_NBR_ADDR;
if (ldpd_process == PROC_LDP_ENGINE && reinstall_tnbr)
ldpe_l2vpn_pw_init(pw);
if (ldpd_process == PROC_LDE_ENGINE &&
!reset_nbr && reinstall_pwfec) {
if (ldpd_process == PROC_LDE_ENGINE && reinstall_pwfec) {
l2vpn->pw_type = xl->pw_type;
l2vpn->mtu = xl->mtu;
l2vpn_pw_init(pw);

View File

@ -147,7 +147,16 @@ enum imsg_type {
IMSG_LOG,
IMSG_ACL_CHECK,
IMSG_GET_LABEL_CHUNK,
IMSG_RELEASE_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 {
@ -439,6 +448,12 @@ enum ldpd_process {
PROC_LDE_ENGINE
} ldpd_process;
static const char * const log_procnames[] = {
"parent",
"ldpe",
"lde"
};
enum socket_type {
LDP_SOCKET_DISC,
LDP_SOCKET_EDISC,
@ -504,7 +519,6 @@ struct ldpd_af_global {
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;
@ -649,6 +663,7 @@ struct ctl_pw {
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 *);
@ -762,6 +777,30 @@ int sock_set_ipv6_mcast_hops(int, int);
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];

View File

@ -66,10 +66,6 @@ static zebra_capabilities_t _caps_p [] =
struct zebra_privs_t ldpe_privs =
{
#if defined(FRR_USER) && defined(FRR_GROUP)
.user = FRR_USER,
.group = FRR_GROUP,
#endif
#if defined(VTY_GROUP)
.vty_group = VTY_GROUP,
#endif
@ -103,46 +99,17 @@ static struct quagga_signal_t ldpe_signals[] =
/* 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);
@ -160,7 +127,43 @@ ldpe(const char *user, const char *group, const char *ctl_path)
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 */
ldpe_privs.user = init->user;
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);
@ -174,16 +177,10 @@ ldpe(const char *user, const char *group, const char *ctl_path)
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
@ -193,16 +190,18 @@ ldpe_shutdown(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__
@ -223,7 +222,8 @@ ldpe_shutdown(void)
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);
@ -239,6 +239,13 @@ ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
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)
@ -351,6 +358,14 @@ ldpe_dispatch_main(struct thread *thread)
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;

View File

@ -195,9 +195,11 @@ int tlv_decode_fec_elm(struct nbr *, struct ldp_msg *, char *,
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);

View File

@ -25,15 +25,8 @@
#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, ...)
@ -53,11 +46,13 @@ vlog(int pri, const char *fmt, va_list ap)
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);
@ -73,16 +68,16 @@ log_warn(const char *emsg, ...)
/* 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);
@ -95,7 +90,7 @@ log_warnx(const char *emsg, ...)
va_list ap;
va_start(ap, emsg);
vlog(LOG_CRIT, emsg, ap);
vlog(LOG_ERR, emsg, ap);
va_end(ap);
}
@ -133,15 +128,15 @@ void
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);
}
@ -152,465 +147,3 @@ fatalx(const char *emsg)
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);
}
}

View File

@ -16,50 +16,32 @@
* 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 */

487
ldpd/logmsg.c Normal file
View File

@ -0,0 +1,487 @@
/* $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);
}
}

View File

@ -237,6 +237,16 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len)
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);
}

View File

@ -27,7 +27,7 @@
#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 **);
@ -134,7 +134,7 @@ disc_recv_packet(struct thread *thread)
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;
@ -212,9 +212,11 @@ disc_recv_packet(struct thread *thread)
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;
@ -280,8 +282,7 @@ disc_recv_packet(struct thread *thread)
}
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;
@ -299,7 +300,7 @@ disc_find_iface(unsigned int ifindex, int af, union ldpd_addr *src,
* "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);
@ -519,6 +520,8 @@ session_read(struct thread *thread)
return (0);
}
break;
case MSG_TYPE_NOTIFICATION:
break;
default:
if (nbr->state != NBR_STA_OPER) {
session_shutdown(nbr, S_SHUTDOWN,
@ -661,8 +664,6 @@ session_shutdown(struct nbr *nbr, uint32_t status, uint32_t msg_id,
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);