1 // SPDX-License-Identifier: ISC
5 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
6 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
7 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
8 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
18 DEFINE_HOOK(ldp_nbr_state_change
, (struct nbr
* nbr
, int old_state
),
21 static __inline
int nbr_id_compare(const struct nbr
*, const struct nbr
*);
22 static __inline
int nbr_addr_compare(const struct nbr
*,
24 static __inline
int nbr_pid_compare(const struct nbr
*,
26 static void nbr_update_peerid(struct nbr
*);
27 static void nbr_ktimer(struct thread
*thread
);
28 static void nbr_start_ktimer(struct nbr
*);
29 static void nbr_ktimeout(struct thread
*thread
);
30 static void nbr_start_ktimeout(struct nbr
*);
31 static void nbr_itimeout(struct thread
*thread
);
32 static void nbr_start_itimeout(struct nbr
*);
33 static void nbr_idtimer(struct thread
*thread
);
34 static int nbr_act_session_operational(struct nbr
*);
35 static void nbr_send_labelmappings(struct nbr
*);
36 static __inline
int nbr_params_compare(const struct nbr_params
*,
37 const struct nbr_params
*);
39 RB_GENERATE(nbr_id_head
, nbr
, id_tree
, nbr_id_compare
)
40 RB_GENERATE(nbr_addr_head
, nbr
, addr_tree
, nbr_addr_compare
)
41 RB_GENERATE(nbr_pid_head
, nbr
, pid_tree
, nbr_pid_compare
)
42 RB_GENERATE(nbrp_head
, nbr_params
, entry
, nbr_params_compare
)
47 enum nbr_action action
;
50 /* current state event that happened action to take resulting state */
52 {NBR_STA_PRESENT
, NBR_EVT_MATCH_ADJ
, NBR_ACT_NOTHING
, NBR_STA_INITIAL
},
53 {NBR_STA_INITIAL
, NBR_EVT_INIT_RCVD
, NBR_ACT_PASSIVE_INIT
, NBR_STA_OPENREC
},
54 {NBR_STA_OPENREC
, NBR_EVT_KEEPALIVE_RCVD
, NBR_ACT_SESSION_EST
, NBR_STA_OPER
},
56 {NBR_STA_PRESENT
, NBR_EVT_CONNECT_UP
, NBR_ACT_CONNECT_SETUP
, NBR_STA_INITIAL
},
57 {NBR_STA_INITIAL
, NBR_EVT_INIT_SENT
, NBR_ACT_NOTHING
, NBR_STA_OPENSENT
},
58 {NBR_STA_OPENSENT
, NBR_EVT_INIT_RCVD
, NBR_ACT_KEEPALIVE_SEND
, NBR_STA_OPENREC
},
59 /* Session Maintenance */
60 {NBR_STA_OPER
, NBR_EVT_PDU_RCVD
, NBR_ACT_RST_KTIMEOUT
, 0},
61 {NBR_STA_SESSION
, NBR_EVT_PDU_RCVD
, NBR_ACT_NOTHING
, 0},
62 {NBR_STA_OPER
, NBR_EVT_PDU_SENT
, NBR_ACT_RST_KTIMER
, 0},
63 {NBR_STA_SESSION
, NBR_EVT_PDU_SENT
, NBR_ACT_NOTHING
, 0},
65 {NBR_STA_PRESENT
, NBR_EVT_CLOSE_SESSION
, NBR_ACT_NOTHING
, 0},
66 {NBR_STA_SESSION
, NBR_EVT_CLOSE_SESSION
, NBR_ACT_CLOSE_SESSION
, NBR_STA_PRESENT
},
67 {-1, NBR_EVT_NOTHING
, NBR_ACT_NOTHING
, 0},
70 const char * const nbr_event_names
[] = {
82 const char * const nbr_action_names
[] = {
84 "RESET KEEPALIVE TIMEOUT",
85 "START NEIGHBOR SESSION",
86 "RESET KEEPALIVE TIMER",
87 "SETUP NEIGHBOR CONNECTION",
88 "SEND INIT AND KEEPALIVE",
93 struct nbr_id_head nbrs_by_id
= RB_INITIALIZER(&nbrs_by_id
);
94 struct nbr_addr_head nbrs_by_addr
= RB_INITIALIZER(&nbrs_by_addr
);
95 struct nbr_pid_head nbrs_by_pid
= RB_INITIALIZER(&nbrs_by_pid
);
98 nbr_id_compare(const struct nbr
*a
, const struct nbr
*b
)
100 return (ntohl(a
->id
.s_addr
) - ntohl(b
->id
.s_addr
));
104 nbr_addr_compare(const struct nbr
*a
, const struct nbr
*b
)
111 return (ldp_addrcmp(a
->af
, &a
->raddr
, &b
->raddr
));
115 nbr_pid_compare(const struct nbr
*a
, const struct nbr
*b
)
117 return (a
->peerid
- b
->peerid
);
121 nbr_fsm(struct nbr
*nbr
, enum nbr_event event
)
128 old_state
= nbr
->state
;
129 for (i
= 0; nbr_fsm_tbl
[i
].state
!= -1; i
++)
130 if ((nbr_fsm_tbl
[i
].state
& old_state
) &&
131 (nbr_fsm_tbl
[i
].event
== event
)) {
132 new_state
= nbr_fsm_tbl
[i
].new_state
;
136 if (nbr_fsm_tbl
[i
].state
== -1) {
137 /* event outside of the defined fsm, ignore it. */
138 log_warnx("%s: lsr-id %pI4, event %s not expected in state %s", __func__
, &nbr
->id
,
139 nbr_event_names
[event
], nbr_state_name(old_state
));
144 nbr
->state
= new_state
;
146 if (old_state
!= nbr
->state
) {
147 log_debug("%s: event %s resulted in action %s and changing state for lsr-id %pI4 from %s to %s",
148 __func__
, nbr_event_names
[event
],
149 nbr_action_names
[nbr_fsm_tbl
[i
].action
],
150 &nbr
->id
, nbr_state_name(old_state
),
151 nbr_state_name(nbr
->state
));
153 hook_call(ldp_nbr_state_change
, nbr
, old_state
);
155 if (nbr
->state
== NBR_STA_OPER
) {
156 gettimeofday(&now
, NULL
);
157 nbr
->uptime
= now
.tv_sec
;
161 if (nbr
->state
== NBR_STA_OPER
|| nbr
->state
== NBR_STA_PRESENT
)
162 nbr_stop_itimeout(nbr
);
164 nbr_start_itimeout(nbr
);
166 switch (nbr_fsm_tbl
[i
].action
) {
167 case NBR_ACT_RST_KTIMEOUT
:
168 nbr_start_ktimeout(nbr
);
170 case NBR_ACT_RST_KTIMER
:
171 nbr_start_ktimer(nbr
);
173 case NBR_ACT_SESSION_EST
:
174 nbr_act_session_operational(nbr
);
175 nbr_start_ktimer(nbr
);
176 nbr_start_ktimeout(nbr
);
178 send_address_all(nbr
, AF_INET
);
180 send_address_all(nbr
, AF_INET6
);
181 nbr_send_labelmappings(nbr
);
183 case NBR_ACT_CONNECT_SETUP
:
184 nbr
->tcp
= tcp_new(nbr
->fd
, nbr
);
186 /* trigger next state */
188 nbr_fsm(nbr
, NBR_EVT_INIT_SENT
);
190 case NBR_ACT_PASSIVE_INIT
:
194 case NBR_ACT_KEEPALIVE_SEND
:
195 nbr_start_ktimeout(nbr
);
198 case NBR_ACT_CLOSE_SESSION
:
199 ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN
, nbr
->peerid
, 0,
203 case NBR_ACT_NOTHING
:
212 nbr_new(struct in_addr id
, int af
, int ds_tlv
, union ldpd_addr
*addr
,
216 struct nbr_params
*nbrp
;
218 struct pending_conn
*pconn
;
220 log_debug("%s: lsr-id %pI4 transport-address %s", __func__
,
221 &id
, log_addr(af
, addr
));
223 if ((nbr
= calloc(1, sizeof(*nbr
))) == NULL
)
226 RB_INIT(nbr_adj_head
, &nbr
->adj_tree
);
227 nbr
->state
= NBR_STA_PRESENT
;
230 nbr
->ds_tlv
= ds_tlv
;
231 if (af
== AF_INET
|| ds_tlv
)
233 if (af
== AF_INET6
|| ds_tlv
)
236 nbr
->laddr
= (ldp_af_conf_get(leconf
, af
))->trans_addr
;
238 nbr
->raddr_scope
= scope_id
;
239 nbr
->conf_seqnum
= 0;
241 RB_FOREACH(adj
, global_adj_head
, &global
.adj_tree
) {
242 if (adj
->lsr_id
.s_addr
== nbr
->id
.s_addr
) {
244 RB_INSERT(nbr_adj_head
, &nbr
->adj_tree
, adj
);
248 if (RB_INSERT(nbr_id_head
, &nbrs_by_id
, nbr
) != NULL
)
249 fatalx("nbr_new: RB_INSERT(nbrs_by_id) failed");
250 if (RB_INSERT(nbr_addr_head
, &nbrs_by_addr
, nbr
) != NULL
)
251 fatalx("nbr_new: RB_INSERT(nbrs_by_addr) failed");
253 TAILQ_INIT(&nbr
->mapping_list
);
254 TAILQ_INIT(&nbr
->withdraw_list
);
255 TAILQ_INIT(&nbr
->request_list
);
256 TAILQ_INIT(&nbr
->release_list
);
257 TAILQ_INIT(&nbr
->abortreq_list
);
259 nbrp
= nbr_params_find(leconf
, nbr
->id
);
261 nbr
->auth
.method
= nbrp
->auth
.method
;
263 if (pfkey_establish(nbr
, nbrp
) == -1)
264 fatalx("pfkey setup failed");
267 (ldp_af_global_get(&global
, nbr
->af
))->ldp_session_socket
,
268 nbr
->af
, &nbr
->raddr
, nbrp
->auth
.md5key
);
272 pconn
= pending_conn_find(nbr
->af
, &nbr
->raddr
);
274 session_accept_nbr(nbr
, pconn
->fd
);
275 pending_conn_del(pconn
);
282 nbr_del(struct nbr
*nbr
)
286 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
288 nbr_fsm(nbr
, NBR_EVT_CLOSE_SESSION
);
293 (ldp_af_global_get(&global
, nbr
->af
))->ldp_session_socket
,
294 nbr
->af
, &nbr
->raddr
, NULL
);
296 nbr
->auth
.method
= AUTH_NONE
;
298 if (nbr_pending_connect(nbr
))
299 THREAD_OFF(nbr
->ev_connect
);
300 nbr_stop_ktimer(nbr
);
301 nbr_stop_ktimeout(nbr
);
302 nbr_stop_itimeout(nbr
);
303 nbr_stop_idtimer(nbr
);
305 mapping_list_clr(&nbr
->mapping_list
);
306 mapping_list_clr(&nbr
->withdraw_list
);
307 mapping_list_clr(&nbr
->request_list
);
308 mapping_list_clr(&nbr
->release_list
);
309 mapping_list_clr(&nbr
->abortreq_list
);
311 while (!RB_EMPTY(nbr_adj_head
, &nbr
->adj_tree
)) {
312 adj
= RB_ROOT(nbr_adj_head
, &nbr
->adj_tree
);
315 RB_REMOVE(nbr_adj_head
, &nbr
->adj_tree
, adj
);
319 RB_REMOVE(nbr_pid_head
, &nbrs_by_pid
, nbr
);
320 RB_REMOVE(nbr_id_head
, &nbrs_by_id
, nbr
);
321 RB_REMOVE(nbr_addr_head
, &nbrs_by_addr
, nbr
);
327 nbr_update_peerid(struct nbr
*nbr
)
329 static uint32_t peercnt
= 1;
332 RB_REMOVE(nbr_pid_head
, &nbrs_by_pid
, nbr
);
334 /* get next unused peerid */
335 while (nbr_find_peerid(++peercnt
))
337 nbr
->peerid
= peercnt
;
339 if (RB_INSERT(nbr_pid_head
, &nbrs_by_pid
, nbr
) != NULL
)
340 fatalx("nbr_update_peerid: RB_INSERT(nbrs_by_pid) failed");
344 nbr_find_ldpid(uint32_t lsr_id
)
347 n
.id
.s_addr
= lsr_id
;
348 return (RB_FIND(nbr_id_head
, &nbrs_by_id
, &n
));
351 struct nbr
*nbr_get_first_ldpid(void)
353 return (RB_MIN(nbr_id_head
, &nbrs_by_id
));
357 nbr_get_next_ldpid(uint32_t lsr_id
)
360 nbr
= nbr_find_ldpid(lsr_id
);
362 return (RB_NEXT(nbr_id_head
, nbr
));
368 nbr_find_addr(int af
, union ldpd_addr
*addr
)
373 return (RB_FIND(nbr_addr_head
, &nbrs_by_addr
, &n
));
377 nbr_find_peerid(uint32_t peerid
)
381 return (RB_FIND(nbr_pid_head
, &nbrs_by_pid
, &n
));
385 nbr_adj_count(struct nbr
*nbr
, int af
)
390 RB_FOREACH(adj
, nbr_adj_head
, &nbr
->adj_tree
)
391 if (adj_get_af(adj
) == af
)
398 nbr_session_active_role(struct nbr
*nbr
)
400 if (ldp_addrcmp(nbr
->af
, &nbr
->laddr
, &nbr
->raddr
) > 0)
408 /* Keepalive timer: timer to send keepalive message to neighbors */
410 static void nbr_ktimer(struct thread
*thread
)
412 struct nbr
*nbr
= THREAD_ARG(thread
);
414 nbr
->keepalive_timer
= NULL
;
416 nbr_start_ktimer(nbr
);
420 nbr_start_ktimer(struct nbr
*nbr
)
424 /* send three keepalives per period */
425 secs
= nbr
->keepalive
/ KEEPALIVE_PER_PERIOD
;
426 THREAD_OFF(nbr
->keepalive_timer
);
427 nbr
->keepalive_timer
= NULL
;
428 thread_add_timer(master
, nbr_ktimer
, nbr
, secs
, &nbr
->keepalive_timer
);
432 nbr_stop_ktimer(struct nbr
*nbr
)
434 THREAD_OFF(nbr
->keepalive_timer
);
437 /* Keepalive timeout: if the nbr hasn't sent keepalive */
439 static void nbr_ktimeout(struct thread
*thread
)
441 struct nbr
*nbr
= THREAD_ARG(thread
);
443 nbr
->keepalive_timeout
= NULL
;
445 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
447 session_shutdown(nbr
, S_KEEPALIVE_TMR
, 0, 0);
451 nbr_start_ktimeout(struct nbr
*nbr
)
453 THREAD_OFF(nbr
->keepalive_timeout
);
454 nbr
->keepalive_timeout
= NULL
;
455 thread_add_timer(master
, nbr_ktimeout
, nbr
, nbr
->keepalive
,
456 &nbr
->keepalive_timeout
);
460 nbr_stop_ktimeout(struct nbr
*nbr
)
462 THREAD_OFF(nbr
->keepalive_timeout
);
465 /* Session initialization timeout: if nbr got stuck in the initialization FSM */
467 static void nbr_itimeout(struct thread
*thread
)
469 struct nbr
*nbr
= THREAD_ARG(thread
);
471 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
473 nbr_fsm(nbr
, NBR_EVT_CLOSE_SESSION
);
477 nbr_start_itimeout(struct nbr
*nbr
)
481 secs
= INIT_FSM_TIMEOUT
;
482 THREAD_OFF(nbr
->init_timeout
);
483 nbr
->init_timeout
= NULL
;
484 thread_add_timer(master
, nbr_itimeout
, nbr
, secs
, &nbr
->init_timeout
);
488 nbr_stop_itimeout(struct nbr
*nbr
)
490 THREAD_OFF(nbr
->init_timeout
);
493 /* Init delay timer: timer to retry to iniziatize session */
495 static void nbr_idtimer(struct thread
*thread
)
497 struct nbr
*nbr
= THREAD_ARG(thread
);
499 nbr
->initdelay_timer
= NULL
;
501 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
503 nbr_establish_connection(nbr
);
507 nbr_start_idtimer(struct nbr
*nbr
)
511 secs
= INIT_DELAY_TMR
;
512 switch(nbr
->idtimer_cnt
) {
514 /* do not further increase the counter */
515 secs
= MAX_DELAY_TMR
;
528 THREAD_OFF(nbr
->initdelay_timer
);
529 nbr
->initdelay_timer
= NULL
;
530 thread_add_timer(master
, nbr_idtimer
, nbr
, secs
,
531 &nbr
->initdelay_timer
);
535 nbr_stop_idtimer(struct nbr
*nbr
)
537 THREAD_OFF(nbr
->initdelay_timer
);
541 nbr_pending_idtimer(struct nbr
*nbr
)
543 return (nbr
->initdelay_timer
!= NULL
);
547 nbr_pending_connect(struct nbr
*nbr
)
549 return (nbr
->ev_connect
!= NULL
);
552 static void nbr_connect_cb(struct thread
*thread
)
554 struct nbr
*nbr
= THREAD_ARG(thread
);
558 nbr
->ev_connect
= NULL
;
561 if (getsockopt(nbr
->fd
, SOL_SOCKET
, SO_ERROR
, &error
, &len
) < 0) {
562 log_warn("%s: getsockopt SOL_SOCKET SO_ERROR", __func__
);
569 log_debug("%s: error while connecting to %s: %s", __func__
,
570 log_addr(nbr
->af
, &nbr
->raddr
), strerror(errno
));
574 nbr_fsm(nbr
, NBR_EVT_CONNECT_UP
);
578 nbr_establish_connection(struct nbr
*nbr
)
580 union sockunion local_su
;
581 union sockunion remote_su
;
583 struct nbr_params
*nbrp
;
588 nbr
->fd
= socket(nbr
->af
, SOCK_STREAM
, 0);
590 log_warn("%s: error while creating socket", __func__
);
593 sock_set_nonblock(nbr
->fd
);
595 nbrp
= nbr_params_find(leconf
, nbr
->id
);
596 if (nbrp
&& nbrp
->auth
.method
== AUTH_MD5SIG
) {
598 if (sysdep
.no_pfkey
|| sysdep
.no_md5sig
) {
599 log_warnx("md5sig configured but not available");
603 if (setsockopt(nbr
->fd
, IPPROTO_TCP
, TCP_MD5SIG
,
604 &opt
, sizeof(opt
)) == -1) {
605 log_warn("setsockopt md5sig");
610 sock_set_md5sig(nbr
->fd
, nbr
->af
, &nbr
->raddr
,
615 if (nbr
->af
== AF_INET
) {
616 if (sock_set_ipv4_tos(nbr
->fd
, IPTOS_PREC_INTERNETCONTROL
) == -1)
617 log_warn("%s: lsr-id %pI4, sock_set_ipv4_tos error",
619 } else if (nbr
->af
== AF_INET6
) {
620 if (sock_set_ipv6_dscp(nbr
->fd
, IPTOS_PREC_INTERNETCONTROL
) == -1)
621 log_warn("%s: lsr-id %pI4, sock_set_ipv6_dscp error",
625 addr2sa(nbr
->af
, &nbr
->laddr
, 0, &local_su
);
626 addr2sa(nbr
->af
, &nbr
->raddr
, LDP_PORT
, &remote_su
);
627 if (nbr
->af
== AF_INET6
&& nbr
->raddr_scope
)
628 addscope(&remote_su
.sin6
, nbr
->raddr_scope
);
630 if (bind(nbr
->fd
, &local_su
.sa
, sockaddr_len(&local_su
.sa
)) == -1) {
631 log_warn("%s: error while binding socket to %s", __func__
,
632 log_sockaddr(&local_su
.sa
));
637 if (nbr_gtsm_check(nbr
->fd
, nbr
, nbrp
)) {
643 * Send an extra hello to guarantee that the remote peer has formed
644 * an adjacency as well.
646 RB_FOREACH(adj
, nbr_adj_head
, &nbr
->adj_tree
)
647 send_hello(adj
->source
.type
, adj
->source
.link
.ia
,
650 if (connect(nbr
->fd
, &remote_su
.sa
, sockaddr_len(&remote_su
.sa
))
652 if (errno
== EINPROGRESS
) {
653 thread_add_write(master
, nbr_connect_cb
, nbr
, nbr
->fd
,
657 log_warn("%s: error while connecting to %s", __func__
,
658 log_sockaddr(&remote_su
.sa
));
663 /* connection completed immediately */
664 nbr_fsm(nbr
, NBR_EVT_CONNECT_UP
);
670 nbr_gtsm_enabled(struct nbr
*nbr
, struct nbr_params
*nbrp
)
673 * RFC 6720 - Section 3:
674 * "This document allows for the implementation to provide an option to
675 * statically (e.g., via configuration) and/or dynamically override the
676 * default behavior and enable/disable GTSM on a per-peer basis".
678 if (nbrp
&& (nbrp
->flags
& F_NBRP_GTSM
))
679 return (nbrp
->gtsm_enabled
);
681 if ((ldp_af_conf_get(leconf
, nbr
->af
))->flags
& F_LDPD_AF_NO_GTSM
)
684 /* By default, GTSM support has to be negotiated for LDPv4 */
685 if (nbr
->af
== AF_INET
&& !(nbr
->flags
& F_NBR_GTSM_NEGOTIATED
))
692 nbr_gtsm_setup(int fd
, int af
, struct nbr_params
*nbrp
)
696 if (nbrp
&& (nbrp
->flags
& F_NBRP_GTSM_HOPS
))
697 ttl
= 256 - nbrp
->gtsm_hops
;
701 if (sock_set_ipv4_minttl(fd
, ttl
) == -1)
704 if (sock_set_ipv4_ucast_ttl(fd
, ttl
) == -1)
708 /* ignore any possible error */
709 sock_set_ipv6_minhopcount(fd
, ttl
);
711 if (sock_set_ipv6_ucast_hops(fd
, ttl
) == -1)
715 fatalx("nbr_gtsm_setup: unknown af");
722 nbr_gtsm_check(int fd
, struct nbr
*nbr
, struct nbr_params
*nbrp
)
724 if (!nbr_gtsm_enabled(nbr
, nbrp
)) {
727 sock_set_ipv4_ucast_ttl(fd
, -1);
731 * Send packets with a Hop Limit of 255 even when GSTM
732 * is disabled to guarantee interoperability.
734 sock_set_ipv6_ucast_hops(fd
, 255);
737 fatalx("nbr_gtsm_check: unknown af");
743 if (nbr_gtsm_setup(fd
, nbr
->af
, nbrp
) == -1) {
744 log_warnx("%s: error enabling GTSM for lsr-id %pI4", __func__
,
753 nbr_act_session_operational(struct nbr
*nbr
)
755 struct lde_nbr lde_nbr
;
757 nbr
->idtimer_cnt
= 0;
759 /* this is necessary to avoid ipc synchronization issues */
760 nbr_update_peerid(nbr
);
762 ldp_sync_fsm_nbr_event(nbr
, LDP_SYNC_EVT_LDP_SYNC_START
);
764 memset(&lde_nbr
, 0, sizeof(lde_nbr
));
765 lde_nbr
.id
= nbr
->id
;
766 lde_nbr
.v4_enabled
= nbr
->v4_enabled
;
767 lde_nbr
.v6_enabled
= nbr
->v6_enabled
;
768 lde_nbr
.flags
= nbr
->flags
;
769 return (ldpe_imsg_compose_lde(IMSG_NEIGHBOR_UP
, nbr
->peerid
, 0,
770 &lde_nbr
, sizeof(lde_nbr
)));
774 nbr_send_labelmappings(struct nbr
*nbr
)
776 ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL
, nbr
->peerid
, 0,
781 nbr_params_compare(const struct nbr_params
*a
, const struct nbr_params
*b
)
783 return (ntohl(a
->lsr_id
.s_addr
) - ntohl(b
->lsr_id
.s_addr
));
787 nbr_params_new(struct in_addr lsr_id
)
789 struct nbr_params
*nbrp
;
791 if ((nbrp
= calloc(1, sizeof(*nbrp
))) == NULL
)
794 nbrp
->lsr_id
= lsr_id
;
795 nbrp
->auth
.method
= AUTH_NONE
;
801 nbr_params_find(struct ldpd_conf
*xconf
, struct in_addr lsr_id
)
803 struct nbr_params nbrp
;
804 nbrp
.lsr_id
= lsr_id
;
805 return (RB_FIND(nbrp_head
, &xconf
->nbrp_tree
, &nbrp
));
809 nbr_get_keepalive(int af
, struct in_addr lsr_id
)
811 struct nbr_params
*nbrp
;
813 nbrp
= nbr_params_find(leconf
, lsr_id
);
814 if (nbrp
&& (nbrp
->flags
& F_NBRP_KEEPALIVE
))
815 return (nbrp
->keepalive
);
817 return ((ldp_af_conf_get(leconf
, af
))->keepalive
);
821 nbr_to_ctl(struct nbr
*nbr
)
823 static struct ctl_nbr nctl
;
828 nctl
.laddr
= nbr
->laddr
;
829 nctl
.lport
= nbr
->tcp
? nbr
->tcp
->lport
: 0;
830 nctl
.raddr
= nbr
->raddr
;
831 nctl
.rport
= nbr
->tcp
? nbr
->tcp
->rport
: 0;
832 nctl
.auth_method
= nbr
->auth
.method
;
833 nctl
.holdtime
= nbr
->keepalive
;
834 nctl
.nbr_state
= nbr
->state
;
835 nctl
.stats
= nbr
->stats
;
836 nctl
.flags
= nbr
->flags
;
837 nctl
.max_pdu_len
= nbr
->max_pdu_len
;
838 nctl
.hold_time_remaining
=
839 thread_timer_remain_second(nbr
->keepalive_timer
);
841 gettimeofday(&now
, NULL
);
842 if (nbr
->state
== NBR_STA_OPER
) {
843 nctl
.uptime
= now
.tv_sec
- nbr
->uptime
;
851 nbr_clear_ctl(struct ctl_nbr
*nctl
)
855 RB_FOREACH(nbr
, nbr_addr_head
, &nbrs_by_addr
) {
856 if (ldp_addrisset(nctl
->af
, &nctl
->raddr
) &&
857 ldp_addrcmp(nctl
->af
, &nctl
->raddr
, &nbr
->raddr
))
860 log_debug("%s: neighbor %s manually cleared", __func__
,
861 log_addr(nbr
->af
, &nbr
->raddr
));
862 session_shutdown(nbr
, S_SHUTDOWN
, 0, 0);