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
*, const struct nbr
*);
23 static __inline
int nbr_pid_compare(const struct nbr
*, const struct nbr
*);
24 static void nbr_update_peerid(struct nbr
*);
25 static void nbr_ktimer(struct event
*thread
);
26 static void nbr_start_ktimer(struct nbr
*);
27 static void nbr_ktimeout(struct event
*thread
);
28 static void nbr_start_ktimeout(struct nbr
*);
29 static void nbr_itimeout(struct event
*thread
);
30 static void nbr_start_itimeout(struct nbr
*);
31 static void nbr_idtimer(struct event
*thread
);
32 static int nbr_act_session_operational(struct nbr
*);
33 static void nbr_send_labelmappings(struct nbr
*);
34 static __inline
int nbr_params_compare(const struct nbr_params
*,
35 const struct nbr_params
*);
37 RB_GENERATE(nbr_id_head
, nbr
, id_tree
, nbr_id_compare
)
38 RB_GENERATE(nbr_addr_head
, nbr
, addr_tree
, nbr_addr_compare
)
39 RB_GENERATE(nbr_pid_head
, nbr
, pid_tree
, nbr_pid_compare
)
40 RB_GENERATE(nbrp_head
, nbr_params
, entry
, nbr_params_compare
)
45 enum nbr_action action
;
48 /* current state event that happened action to take resulting state */
50 {NBR_STA_PRESENT
, NBR_EVT_MATCH_ADJ
, NBR_ACT_NOTHING
, NBR_STA_INITIAL
},
51 {NBR_STA_INITIAL
, NBR_EVT_INIT_RCVD
, NBR_ACT_PASSIVE_INIT
, NBR_STA_OPENREC
},
52 {NBR_STA_OPENREC
, NBR_EVT_KEEPALIVE_RCVD
, NBR_ACT_SESSION_EST
, NBR_STA_OPER
},
54 {NBR_STA_PRESENT
, NBR_EVT_CONNECT_UP
, NBR_ACT_CONNECT_SETUP
, NBR_STA_INITIAL
},
55 {NBR_STA_INITIAL
, NBR_EVT_INIT_SENT
, NBR_ACT_NOTHING
, NBR_STA_OPENSENT
},
56 {NBR_STA_OPENSENT
, NBR_EVT_INIT_RCVD
, NBR_ACT_KEEPALIVE_SEND
, NBR_STA_OPENREC
},
57 /* Session Maintenance */
58 {NBR_STA_OPER
, NBR_EVT_PDU_RCVD
, NBR_ACT_RST_KTIMEOUT
, 0},
59 {NBR_STA_SESSION
, NBR_EVT_PDU_RCVD
, NBR_ACT_NOTHING
, 0},
60 {NBR_STA_OPER
, NBR_EVT_PDU_SENT
, NBR_ACT_RST_KTIMER
, 0},
61 {NBR_STA_SESSION
, NBR_EVT_PDU_SENT
, NBR_ACT_NOTHING
, 0},
63 {NBR_STA_PRESENT
, NBR_EVT_CLOSE_SESSION
, NBR_ACT_NOTHING
, 0},
64 {NBR_STA_SESSION
, NBR_EVT_CLOSE_SESSION
, NBR_ACT_CLOSE_SESSION
, NBR_STA_PRESENT
},
65 {-1, NBR_EVT_NOTHING
, NBR_ACT_NOTHING
, 0},
68 const char * const nbr_event_names
[] = {
80 const char * const nbr_action_names
[] = {
82 "RESET KEEPALIVE TIMEOUT",
83 "START NEIGHBOR SESSION",
84 "RESET KEEPALIVE TIMER",
85 "SETUP NEIGHBOR CONNECTION",
86 "SEND INIT AND KEEPALIVE",
91 struct nbr_id_head nbrs_by_id
= RB_INITIALIZER(&nbrs_by_id
);
92 struct nbr_addr_head nbrs_by_addr
= RB_INITIALIZER(&nbrs_by_addr
);
93 struct nbr_pid_head nbrs_by_pid
= RB_INITIALIZER(&nbrs_by_pid
);
96 nbr_id_compare(const struct nbr
*a
, const struct nbr
*b
)
98 return (ntohl(a
->id
.s_addr
) - ntohl(b
->id
.s_addr
));
102 nbr_addr_compare(const struct nbr
*a
, const struct nbr
*b
)
109 return (ldp_addrcmp(a
->af
, &a
->raddr
, &b
->raddr
));
113 nbr_pid_compare(const struct nbr
*a
, const struct nbr
*b
)
115 return (a
->peerid
- b
->peerid
);
119 nbr_fsm(struct nbr
*nbr
, enum nbr_event event
)
126 old_state
= nbr
->state
;
127 for (i
= 0; nbr_fsm_tbl
[i
].state
!= -1; i
++)
128 if (CHECK_FLAG(nbr_fsm_tbl
[i
].state
, old_state
) &&
129 (nbr_fsm_tbl
[i
].event
== event
)) {
130 new_state
= nbr_fsm_tbl
[i
].new_state
;
134 if (nbr_fsm_tbl
[i
].state
== -1) {
135 /* event outside of the defined fsm, ignore it. */
136 log_warnx("%s: lsr-id %pI4, event %s not expected in state %s", __func__
, &nbr
->id
,
137 nbr_event_names
[event
], nbr_state_name(old_state
));
142 nbr
->state
= new_state
;
144 if (old_state
!= nbr
->state
) {
145 log_debug("%s: event %s resulted in action %s and changing state for lsr-id %pI4 from %s to %s",
146 __func__
, nbr_event_names
[event
],
147 nbr_action_names
[nbr_fsm_tbl
[i
].action
],
148 &nbr
->id
, nbr_state_name(old_state
),
149 nbr_state_name(nbr
->state
));
151 hook_call(ldp_nbr_state_change
, nbr
, old_state
);
153 if (nbr
->state
== NBR_STA_OPER
) {
154 gettimeofday(&now
, NULL
);
155 nbr
->uptime
= now
.tv_sec
;
159 if (nbr
->state
== NBR_STA_OPER
|| nbr
->state
== NBR_STA_PRESENT
)
160 nbr_stop_itimeout(nbr
);
162 nbr_start_itimeout(nbr
);
164 switch (nbr_fsm_tbl
[i
].action
) {
165 case NBR_ACT_RST_KTIMEOUT
:
166 nbr_start_ktimeout(nbr
);
168 case NBR_ACT_RST_KTIMER
:
169 nbr_start_ktimer(nbr
);
171 case NBR_ACT_SESSION_EST
:
172 nbr_act_session_operational(nbr
);
173 nbr_start_ktimer(nbr
);
174 nbr_start_ktimeout(nbr
);
176 send_address_all(nbr
, AF_INET
);
178 send_address_all(nbr
, AF_INET6
);
179 nbr_send_labelmappings(nbr
);
181 case NBR_ACT_CONNECT_SETUP
:
182 nbr
->tcp
= tcp_new(nbr
->fd
, nbr
);
184 /* trigger next state */
186 nbr_fsm(nbr
, NBR_EVT_INIT_SENT
);
188 case NBR_ACT_PASSIVE_INIT
:
192 case NBR_ACT_KEEPALIVE_SEND
:
193 nbr_start_ktimeout(nbr
);
196 case NBR_ACT_CLOSE_SESSION
:
197 ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN
, nbr
->peerid
, 0, NULL
, 0);
200 case NBR_ACT_NOTHING
:
209 nbr_new(struct in_addr id
, int af
, int ds_tlv
, union ldpd_addr
*addr
,
213 struct nbr_params
*nbrp
;
215 struct pending_conn
*pconn
;
217 log_debug("%s: lsr-id %pI4 transport-address %s", __func__
,
218 &id
, log_addr(af
, addr
));
220 if ((nbr
= calloc(1, sizeof(*nbr
))) == NULL
)
223 RB_INIT(nbr_adj_head
, &nbr
->adj_tree
);
224 nbr
->state
= NBR_STA_PRESENT
;
227 nbr
->ds_tlv
= ds_tlv
;
228 if (af
== AF_INET
|| ds_tlv
)
230 if (af
== AF_INET6
|| ds_tlv
)
233 nbr
->laddr
= (ldp_af_conf_get(leconf
, af
))->trans_addr
;
235 nbr
->raddr_scope
= scope_id
;
236 nbr
->conf_seqnum
= 0;
238 RB_FOREACH(adj
, global_adj_head
, &global
.adj_tree
) {
239 if (adj
->lsr_id
.s_addr
== nbr
->id
.s_addr
) {
241 RB_INSERT(nbr_adj_head
, &nbr
->adj_tree
, adj
);
245 if (RB_INSERT(nbr_id_head
, &nbrs_by_id
, nbr
) != NULL
)
246 fatalx("nbr_new: RB_INSERT(nbrs_by_id) failed");
247 if (RB_INSERT(nbr_addr_head
, &nbrs_by_addr
, nbr
) != NULL
)
248 fatalx("nbr_new: RB_INSERT(nbrs_by_addr) failed");
250 TAILQ_INIT(&nbr
->mapping_list
);
251 TAILQ_INIT(&nbr
->withdraw_list
);
252 TAILQ_INIT(&nbr
->request_list
);
253 TAILQ_INIT(&nbr
->release_list
);
254 TAILQ_INIT(&nbr
->abortreq_list
);
256 nbrp
= nbr_params_find(leconf
, nbr
->id
);
258 nbr
->auth
.method
= nbrp
->auth
.method
;
260 if (pfkey_establish(nbr
, nbrp
) == -1)
261 fatalx("pfkey setup failed");
264 (ldp_af_global_get(&global
, nbr
->af
))->ldp_session_socket
,
265 nbr
->af
, &nbr
->raddr
, nbrp
->auth
.md5key
);
269 pconn
= pending_conn_find(nbr
->af
, &nbr
->raddr
);
271 session_accept_nbr(nbr
, pconn
->fd
);
272 pending_conn_del(pconn
);
279 nbr_del(struct nbr
*nbr
)
283 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
285 nbr_fsm(nbr
, NBR_EVT_CLOSE_SESSION
);
290 (ldp_af_global_get(&global
, nbr
->af
))->ldp_session_socket
,
291 nbr
->af
, &nbr
->raddr
, NULL
);
293 nbr
->auth
.method
= AUTH_NONE
;
295 if (nbr_pending_connect(nbr
))
296 EVENT_OFF(nbr
->ev_connect
);
297 nbr_stop_ktimer(nbr
);
298 nbr_stop_ktimeout(nbr
);
299 nbr_stop_itimeout(nbr
);
300 nbr_stop_idtimer(nbr
);
302 mapping_list_clr(&nbr
->mapping_list
);
303 mapping_list_clr(&nbr
->withdraw_list
);
304 mapping_list_clr(&nbr
->request_list
);
305 mapping_list_clr(&nbr
->release_list
);
306 mapping_list_clr(&nbr
->abortreq_list
);
308 while (!RB_EMPTY(nbr_adj_head
, &nbr
->adj_tree
)) {
309 adj
= RB_ROOT(nbr_adj_head
, &nbr
->adj_tree
);
312 RB_REMOVE(nbr_adj_head
, &nbr
->adj_tree
, adj
);
316 RB_REMOVE(nbr_pid_head
, &nbrs_by_pid
, nbr
);
317 RB_REMOVE(nbr_id_head
, &nbrs_by_id
, nbr
);
318 RB_REMOVE(nbr_addr_head
, &nbrs_by_addr
, nbr
);
324 nbr_update_peerid(struct nbr
*nbr
)
326 static uint32_t peercnt
= 1;
329 RB_REMOVE(nbr_pid_head
, &nbrs_by_pid
, nbr
);
331 /* get next unused peerid */
332 while (nbr_find_peerid(++peercnt
))
334 nbr
->peerid
= peercnt
;
336 if (RB_INSERT(nbr_pid_head
, &nbrs_by_pid
, nbr
) != NULL
)
337 fatalx("nbr_update_peerid: RB_INSERT(nbrs_by_pid) failed");
341 nbr_find_ldpid(uint32_t lsr_id
)
344 n
.id
.s_addr
= lsr_id
;
345 return (RB_FIND(nbr_id_head
, &nbrs_by_id
, &n
));
348 struct nbr
*nbr_get_first_ldpid(void)
350 return (RB_MIN(nbr_id_head
, &nbrs_by_id
));
354 nbr_get_next_ldpid(uint32_t lsr_id
)
357 nbr
= nbr_find_ldpid(lsr_id
);
359 return (RB_NEXT(nbr_id_head
, nbr
));
365 nbr_find_addr(int af
, union ldpd_addr
*addr
)
370 return (RB_FIND(nbr_addr_head
, &nbrs_by_addr
, &n
));
374 nbr_find_peerid(uint32_t peerid
)
378 return (RB_FIND(nbr_pid_head
, &nbrs_by_pid
, &n
));
382 nbr_adj_count(struct nbr
*nbr
, int af
)
387 RB_FOREACH(adj
, nbr_adj_head
, &nbr
->adj_tree
)
388 if (adj_get_af(adj
) == af
)
395 nbr_session_active_role(struct nbr
*nbr
)
397 if (ldp_addrcmp(nbr
->af
, &nbr
->laddr
, &nbr
->raddr
) > 0)
405 /* Keepalive timer: timer to send keepalive message to neighbors */
407 static void nbr_ktimer(struct event
*thread
)
409 struct nbr
*nbr
= EVENT_ARG(thread
);
411 nbr
->keepalive_timer
= NULL
;
413 nbr_start_ktimer(nbr
);
417 nbr_start_ktimer(struct nbr
*nbr
)
421 /* send three keepalives per period */
422 secs
= nbr
->keepalive
/ KEEPALIVE_PER_PERIOD
;
423 EVENT_OFF(nbr
->keepalive_timer
);
424 nbr
->keepalive_timer
= NULL
;
425 event_add_timer(master
, nbr_ktimer
, nbr
, secs
, &nbr
->keepalive_timer
);
429 nbr_stop_ktimer(struct nbr
*nbr
)
431 EVENT_OFF(nbr
->keepalive_timer
);
434 /* Keepalive timeout: if the nbr hasn't sent keepalive */
436 static void nbr_ktimeout(struct event
*thread
)
438 struct nbr
*nbr
= EVENT_ARG(thread
);
440 nbr
->keepalive_timeout
= NULL
;
442 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
444 session_shutdown(nbr
, S_KEEPALIVE_TMR
, 0, 0);
448 nbr_start_ktimeout(struct nbr
*nbr
)
450 EVENT_OFF(nbr
->keepalive_timeout
);
451 nbr
->keepalive_timeout
= NULL
;
452 event_add_timer(master
, nbr_ktimeout
, nbr
, nbr
->keepalive
,
453 &nbr
->keepalive_timeout
);
457 nbr_stop_ktimeout(struct nbr
*nbr
)
459 EVENT_OFF(nbr
->keepalive_timeout
);
462 /* Session initialization timeout: if nbr got stuck in the initialization FSM */
464 static void nbr_itimeout(struct event
*thread
)
466 struct nbr
*nbr
= EVENT_ARG(thread
);
468 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
470 nbr_fsm(nbr
, NBR_EVT_CLOSE_SESSION
);
474 nbr_start_itimeout(struct nbr
*nbr
)
478 secs
= INIT_FSM_TIMEOUT
;
479 EVENT_OFF(nbr
->init_timeout
);
480 nbr
->init_timeout
= NULL
;
481 event_add_timer(master
, nbr_itimeout
, nbr
, secs
, &nbr
->init_timeout
);
485 nbr_stop_itimeout(struct nbr
*nbr
)
487 EVENT_OFF(nbr
->init_timeout
);
490 /* Init delay timer: timer to retry to iniziatize session */
492 static void nbr_idtimer(struct event
*thread
)
494 struct nbr
*nbr
= EVENT_ARG(thread
);
496 nbr
->initdelay_timer
= NULL
;
498 log_debug("%s: lsr-id %pI4", __func__
, &nbr
->id
);
500 nbr_establish_connection(nbr
);
504 nbr_start_idtimer(struct nbr
*nbr
)
508 secs
= INIT_DELAY_TMR
;
509 switch(nbr
->idtimer_cnt
) {
511 /* do not further increase the counter */
512 secs
= MAX_DELAY_TMR
;
525 EVENT_OFF(nbr
->initdelay_timer
);
526 nbr
->initdelay_timer
= NULL
;
527 event_add_timer(master
, nbr_idtimer
, nbr
, secs
, &nbr
->initdelay_timer
);
531 nbr_stop_idtimer(struct nbr
*nbr
)
533 EVENT_OFF(nbr
->initdelay_timer
);
537 nbr_pending_idtimer(struct nbr
*nbr
)
539 return (nbr
->initdelay_timer
!= NULL
);
543 nbr_pending_connect(struct nbr
*nbr
)
545 return (nbr
->ev_connect
!= NULL
);
548 static void nbr_connect_cb(struct event
*thread
)
550 struct nbr
*nbr
= EVENT_ARG(thread
);
554 nbr
->ev_connect
= NULL
;
557 if (getsockopt(nbr
->fd
, SOL_SOCKET
, SO_ERROR
, &error
, &len
) < 0) {
558 log_warn("%s: getsockopt SOL_SOCKET SO_ERROR", __func__
);
565 log_debug("%s: error while connecting to %s: %s", __func__
,
566 log_addr(nbr
->af
, &nbr
->raddr
), strerror(errno
));
570 nbr_fsm(nbr
, NBR_EVT_CONNECT_UP
);
574 nbr_establish_connection(struct nbr
*nbr
)
576 union sockunion local_su
;
577 union sockunion remote_su
;
579 struct nbr_params
*nbrp
;
584 nbr
->fd
= socket(nbr
->af
, SOCK_STREAM
, 0);
586 log_warn("%s: error while creating socket", __func__
);
589 sock_set_nonblock(nbr
->fd
);
591 nbrp
= nbr_params_find(leconf
, nbr
->id
);
592 if (nbrp
&& nbrp
->auth
.method
== AUTH_MD5SIG
) {
594 if (sysdep
.no_pfkey
|| sysdep
.no_md5sig
) {
595 log_warnx("md5sig configured but not available");
599 if (setsockopt(nbr
->fd
, IPPROTO_TCP
, TCP_MD5SIG
,
600 &opt
, sizeof(opt
)) == -1) {
601 log_warn("setsockopt md5sig");
606 sock_set_md5sig(nbr
->fd
, nbr
->af
, &nbr
->raddr
, nbrp
->auth
.md5key
);
610 if (nbr
->af
== AF_INET
) {
611 if (sock_set_ipv4_tos(nbr
->fd
, IPTOS_PREC_INTERNETCONTROL
) == -1)
612 log_warn("%s: lsr-id %pI4, sock_set_ipv4_tos error",
614 } else if (nbr
->af
== AF_INET6
) {
615 if (sock_set_ipv6_dscp(nbr
->fd
, IPTOS_PREC_INTERNETCONTROL
) == -1)
616 log_warn("%s: lsr-id %pI4, sock_set_ipv6_dscp error",
620 addr2sa(nbr
->af
, &nbr
->laddr
, 0, &local_su
);
621 addr2sa(nbr
->af
, &nbr
->raddr
, LDP_PORT
, &remote_su
);
622 if (nbr
->af
== AF_INET6
&& nbr
->raddr_scope
)
623 addscope(&remote_su
.sin6
, nbr
->raddr_scope
);
625 if (bind(nbr
->fd
, &local_su
.sa
, sockaddr_len(&local_su
.sa
)) == -1) {
626 log_warn("%s: error while binding socket to %s", __func__
,
627 log_sockaddr(&local_su
.sa
));
632 if (nbr_gtsm_check(nbr
->fd
, nbr
, nbrp
)) {
638 * Send an extra hello to guarantee that the remote peer has formed
639 * an adjacency as well.
641 RB_FOREACH(adj
, nbr_adj_head
, &nbr
->adj_tree
)
642 send_hello(adj
->source
.type
, adj
->source
.link
.ia
,
645 if (connect(nbr
->fd
, &remote_su
.sa
, sockaddr_len(&remote_su
.sa
)) == -1) {
646 if (errno
== EINPROGRESS
) {
647 event_add_write(master
, nbr_connect_cb
, nbr
, nbr
->fd
,
651 log_warn("%s: error while connecting to %s", __func__
,
652 log_sockaddr(&remote_su
.sa
));
657 /* connection completed immediately */
658 nbr_fsm(nbr
, NBR_EVT_CONNECT_UP
);
664 nbr_gtsm_enabled(struct nbr
*nbr
, struct nbr_params
*nbrp
)
667 * RFC 6720 - Section 3:
668 * "This document allows for the implementation to provide an option to
669 * statically (e.g., via configuration) and/or dynamically override the
670 * default behavior and enable/disable GTSM on a per-peer basis".
672 if (nbrp
&& CHECK_FLAG(nbrp
->flags
, F_NBRP_GTSM
))
673 return (nbrp
->gtsm_enabled
);
675 if (CHECK_FLAG((ldp_af_conf_get(leconf
, nbr
->af
))->flags
, F_LDPD_AF_NO_GTSM
))
678 /* By default, GTSM support has to be negotiated for LDPv4 */
679 if (nbr
->af
== AF_INET
&& !CHECK_FLAG(nbr
->flags
, F_NBR_GTSM_NEGOTIATED
))
686 nbr_gtsm_setup(int fd
, int af
, struct nbr_params
*nbrp
)
690 if (nbrp
&& CHECK_FLAG(nbrp
->flags
, F_NBRP_GTSM_HOPS
))
691 ttl
= 256 - nbrp
->gtsm_hops
;
695 if (sock_set_ipv4_minttl(fd
, ttl
) == -1)
698 if (sock_set_ipv4_ucast_ttl(fd
, ttl
) == -1)
702 /* ignore any possible error */
703 sock_set_ipv6_minhopcount(fd
, ttl
);
705 if (sock_set_ipv6_ucast_hops(fd
, ttl
) == -1)
709 fatalx("nbr_gtsm_setup: unknown af");
716 nbr_gtsm_check(int fd
, struct nbr
*nbr
, struct nbr_params
*nbrp
)
718 if (!nbr_gtsm_enabled(nbr
, nbrp
)) {
721 sock_set_ipv4_ucast_ttl(fd
, -1);
725 * Send packets with a Hop Limit of 255 even when GSTM
726 * is disabled to guarantee interoperability.
728 sock_set_ipv6_ucast_hops(fd
, 255);
731 fatalx("nbr_gtsm_check: unknown af");
737 if (nbr_gtsm_setup(fd
, nbr
->af
, nbrp
) == -1) {
738 log_warnx("%s: error enabling GTSM for lsr-id %pI4", __func__
, &nbr
->id
);
746 nbr_act_session_operational(struct nbr
*nbr
)
748 struct lde_nbr lde_nbr
;
750 nbr
->idtimer_cnt
= 0;
752 /* this is necessary to avoid ipc synchronization issues */
753 nbr_update_peerid(nbr
);
755 ldp_sync_fsm_nbr_event(nbr
, LDP_SYNC_EVT_LDP_SYNC_START
);
757 memset(&lde_nbr
, 0, sizeof(lde_nbr
));
758 lde_nbr
.id
= nbr
->id
;
759 lde_nbr
.v4_enabled
= nbr
->v4_enabled
;
760 lde_nbr
.v6_enabled
= nbr
->v6_enabled
;
761 lde_nbr
.flags
= nbr
->flags
;
762 return (ldpe_imsg_compose_lde(IMSG_NEIGHBOR_UP
, nbr
->peerid
, 0,
763 &lde_nbr
, sizeof(lde_nbr
)));
767 nbr_send_labelmappings(struct nbr
*nbr
)
769 ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL
, nbr
->peerid
, 0, NULL
, 0);
773 nbr_params_compare(const struct nbr_params
*a
, const struct nbr_params
*b
)
775 return (ntohl(a
->lsr_id
.s_addr
) - ntohl(b
->lsr_id
.s_addr
));
779 nbr_params_new(struct in_addr lsr_id
)
781 struct nbr_params
*nbrp
;
783 if ((nbrp
= calloc(1, sizeof(*nbrp
))) == NULL
)
786 nbrp
->lsr_id
= lsr_id
;
787 nbrp
->auth
.method
= AUTH_NONE
;
793 nbr_params_find(struct ldpd_conf
*xconf
, struct in_addr lsr_id
)
795 struct nbr_params nbrp
;
796 nbrp
.lsr_id
= lsr_id
;
797 return (RB_FIND(nbrp_head
, &xconf
->nbrp_tree
, &nbrp
));
801 nbr_get_keepalive(int af
, struct in_addr lsr_id
)
803 struct nbr_params
*nbrp
;
805 nbrp
= nbr_params_find(leconf
, lsr_id
);
806 if (nbrp
&& CHECK_FLAG(nbrp
->flags
, F_NBRP_KEEPALIVE
))
807 return (nbrp
->keepalive
);
809 return ((ldp_af_conf_get(leconf
, af
))->keepalive
);
813 nbr_to_ctl(struct nbr
*nbr
)
815 static struct ctl_nbr nctl
;
820 nctl
.laddr
= nbr
->laddr
;
821 nctl
.lport
= nbr
->tcp
? nbr
->tcp
->lport
: 0;
822 nctl
.raddr
= nbr
->raddr
;
823 nctl
.rport
= nbr
->tcp
? nbr
->tcp
->rport
: 0;
824 nctl
.auth_method
= nbr
->auth
.method
;
825 nctl
.holdtime
= nbr
->keepalive
;
826 nctl
.nbr_state
= nbr
->state
;
827 nctl
.stats
= nbr
->stats
;
828 nctl
.flags
= nbr
->flags
;
829 nctl
.max_pdu_len
= nbr
->max_pdu_len
;
830 nctl
.hold_time_remaining
= event_timer_remain_second(nbr
->keepalive_timer
);
832 gettimeofday(&now
, NULL
);
833 if (nbr
->state
== NBR_STA_OPER
) {
834 nctl
.uptime
= now
.tv_sec
- nbr
->uptime
;
842 nbr_clear_ctl(struct ctl_nbr
*nctl
)
846 RB_FOREACH(nbr
, nbr_addr_head
, &nbrs_by_addr
) {
847 if (ldp_addrisset(nctl
->af
, &nctl
->raddr
) &&
848 ldp_addrcmp(nctl
->af
, &nctl
->raddr
, &nbr
->raddr
))
851 log_debug("%s: neighbor %s manually cleared", __func__
,
852 log_addr(nbr
->af
, &nbr
->raddr
));
853 session_shutdown(nbr
, S_SHUTDOWN
, 0, 0);