diff --git a/ldpd/Makefile.am b/ldpd/Makefile.am index 19f819ae36..b760b44573 100644 --- a/ldpd/Makefile.am +++ b/ldpd/Makefile.am @@ -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 diff --git a/ldpd/adjacency.c b/ldpd/adjacency.c index 8659202ee4..3ec57f1589 100644 --- a/ldpd/adjacency.c +++ b/ldpd/adjacency.c @@ -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); } } diff --git a/ldpd/control.c b/ldpd/control.c index 5c530e1b70..d40e0342c1 100644 --- a/ldpd/control.c +++ b/ldpd/control.c @@ -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 */ diff --git a/ldpd/control.h b/ldpd/control.h index 32c49fdf87..0e66a1636a 100644 --- a/ldpd/control.h +++ b/ldpd/control.h @@ -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_ */ diff --git a/ldpd/interface.c b/ldpd/interface.c index 7be8be755e..440bb2dca0 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -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); } } diff --git a/ldpd/lde.c b/ldpd/lde.c index 36998e7cf8..0cfc02d5ba 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -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); } } diff --git a/ldpd/lde.h b/ldpd/lde.h index 57791cd1b0..1cce483832 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -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 *); diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index db2682a173..37a670bc8c 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -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 diff --git a/ldpd/ldp_vty_exec.c b/ldpd/ldp_vty_exec.c index a149b7fe35..ffd20abb4a 100644 --- a/ldpd/ldp_vty_exec.c +++ b/ldpd/ldp_vty_exec.c @@ -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); diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index fde6e56c64..3320238a05 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -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)); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index def3d2e2f3..f9e44012ef 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -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); diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 10742cf0dc..97239ed08e 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -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]; diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 1bec3d2a95..017eec2502 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -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; diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index a3f41a8b9f..d34ca4dc24 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -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); diff --git a/ldpd/log.c b/ldpd/log.c index 407668bb03..b138e5754a 100644 --- a/ldpd/log.c +++ b/ldpd/log.c @@ -25,15 +25,8 @@ #include #include -#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); - } -} diff --git a/ldpd/log.h b/ldpd/log.h index 4d6da43cac..8c236ff5fe 100644 --- a/ldpd/log.h +++ b/ldpd/log.h @@ -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 -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 */ diff --git a/ldpd/logmsg.c b/ldpd/logmsg.c new file mode 100644 index 0000000000..c819b33b43 --- /dev/null +++ b/ldpd/logmsg.c @@ -0,0 +1,487 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2003, 2004 Henning Brauer + * + * 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 + +#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); + } +} diff --git a/ldpd/notification.c b/ldpd/notification.c index f10faa4a54..4a5f3c8fa4 100644 --- a/ldpd/notification.c +++ b/ldpd/notification.c @@ -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); } diff --git a/ldpd/packet.c b/ldpd/packet.c index 46893b992b..df6bd8e57a 100644 --- a/ldpd/packet.c +++ b/ldpd/packet.c @@ -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);