]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/neighbor.c
zebra: use ifindex vs ifp to avoid use-after-free on shutdown
[mirror_frr.git] / ldpd / neighbor.c
1 // SPDX-License-Identifier: ISC
2 /* $OpenBSD$ */
3
4 /*
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>
9 */
10
11 #include <zebra.h>
12
13 #include "ldpd.h"
14 #include "ldpe.h"
15 #include "lde.h"
16 #include "log.h"
17
18 DEFINE_HOOK(ldp_nbr_state_change, (struct nbr * nbr, int old_state),
19 (nbr, old_state));
20
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 *);
36
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)
41
42 const struct {
43 int state;
44 enum nbr_event event;
45 enum nbr_action action;
46 int new_state;
47 } nbr_fsm_tbl[] = {
48 /* current state event that happened action to take resulting state */
49 /* Passive Role */
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},
53 /* Active Role */
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},
62 /* Session Close */
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},
66 };
67
68 const char * const nbr_event_names[] = {
69 "NOTHING",
70 "ADJACENCY MATCHED",
71 "CONNECTION UP",
72 "SESSION CLOSE",
73 "INIT RECEIVED",
74 "KEEPALIVE RECEIVED",
75 "PDU RECEIVED",
76 "PDU SENT",
77 "INIT SENT"
78 };
79
80 const char * const nbr_action_names[] = {
81 "NOTHING",
82 "RESET KEEPALIVE TIMEOUT",
83 "START NEIGHBOR SESSION",
84 "RESET KEEPALIVE TIMER",
85 "SETUP NEIGHBOR CONNECTION",
86 "SEND INIT AND KEEPALIVE",
87 "SEND KEEPALIVE",
88 "CLOSE SESSION"
89 };
90
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);
94
95 static __inline int
96 nbr_id_compare(const struct nbr *a, const struct nbr *b)
97 {
98 return (ntohl(a->id.s_addr) - ntohl(b->id.s_addr));
99 }
100
101 static __inline int
102 nbr_addr_compare(const struct nbr *a, const struct nbr *b)
103 {
104 if (a->af < b->af)
105 return (-1);
106 if (a->af > b->af)
107 return (1);
108
109 return (ldp_addrcmp(a->af, &a->raddr, &b->raddr));
110 }
111
112 static __inline int
113 nbr_pid_compare(const struct nbr *a, const struct nbr *b)
114 {
115 return (a->peerid - b->peerid);
116 }
117
118 int
119 nbr_fsm(struct nbr *nbr, enum nbr_event event)
120 {
121 struct timeval now;
122 int old_state;
123 int new_state = 0;
124 int i;
125
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;
131 break;
132 }
133
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));
138 return (0);
139 }
140
141 if (new_state != 0)
142 nbr->state = new_state;
143
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));
150
151 hook_call(ldp_nbr_state_change, nbr, old_state);
152
153 if (nbr->state == NBR_STA_OPER) {
154 gettimeofday(&now, NULL);
155 nbr->uptime = now.tv_sec;
156 }
157 }
158
159 if (nbr->state == NBR_STA_OPER || nbr->state == NBR_STA_PRESENT)
160 nbr_stop_itimeout(nbr);
161 else
162 nbr_start_itimeout(nbr);
163
164 switch (nbr_fsm_tbl[i].action) {
165 case NBR_ACT_RST_KTIMEOUT:
166 nbr_start_ktimeout(nbr);
167 break;
168 case NBR_ACT_RST_KTIMER:
169 nbr_start_ktimer(nbr);
170 break;
171 case NBR_ACT_SESSION_EST:
172 nbr_act_session_operational(nbr);
173 nbr_start_ktimer(nbr);
174 nbr_start_ktimeout(nbr);
175 if (nbr->v4_enabled)
176 send_address_all(nbr, AF_INET);
177 if (nbr->v6_enabled)
178 send_address_all(nbr, AF_INET6);
179 nbr_send_labelmappings(nbr);
180 break;
181 case NBR_ACT_CONNECT_SETUP:
182 nbr->tcp = tcp_new(nbr->fd, nbr);
183
184 /* trigger next state */
185 send_init(nbr);
186 nbr_fsm(nbr, NBR_EVT_INIT_SENT);
187 break;
188 case NBR_ACT_PASSIVE_INIT:
189 send_init(nbr);
190 send_keepalive(nbr);
191 break;
192 case NBR_ACT_KEEPALIVE_SEND:
193 nbr_start_ktimeout(nbr);
194 send_keepalive(nbr);
195 break;
196 case NBR_ACT_CLOSE_SESSION:
197 ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0, NULL, 0);
198 session_close(nbr);
199 break;
200 case NBR_ACT_NOTHING:
201 /* do nothing */
202 break;
203 }
204
205 return (0);
206 }
207
208 struct nbr *
209 nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr,
210 uint32_t scope_id)
211 {
212 struct nbr *nbr;
213 struct nbr_params *nbrp;
214 struct adj *adj;
215 struct pending_conn *pconn;
216
217 log_debug("%s: lsr-id %pI4 transport-address %s", __func__,
218 &id, log_addr(af, addr));
219
220 if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
221 fatal(__func__);
222
223 RB_INIT(nbr_adj_head, &nbr->adj_tree);
224 nbr->state = NBR_STA_PRESENT;
225 nbr->peerid = 0;
226 nbr->af = af;
227 nbr->ds_tlv = ds_tlv;
228 if (af == AF_INET || ds_tlv)
229 nbr->v4_enabled = 1;
230 if (af == AF_INET6 || ds_tlv)
231 nbr->v6_enabled = 1;
232 nbr->id = id;
233 nbr->laddr = (ldp_af_conf_get(leconf, af))->trans_addr;
234 nbr->raddr = *addr;
235 nbr->raddr_scope = scope_id;
236 nbr->conf_seqnum = 0;
237
238 RB_FOREACH(adj, global_adj_head, &global.adj_tree) {
239 if (adj->lsr_id.s_addr == nbr->id.s_addr) {
240 adj->nbr = nbr;
241 RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj);
242 }
243 }
244
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");
249
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);
255
256 nbrp = nbr_params_find(leconf, nbr->id);
257 if (nbrp) {
258 nbr->auth.method = nbrp->auth.method;
259 #ifdef __OpenBSD__
260 if (pfkey_establish(nbr, nbrp) == -1)
261 fatalx("pfkey setup failed");
262 #else
263 sock_set_md5sig(
264 (ldp_af_global_get(&global, nbr->af))->ldp_session_socket,
265 nbr->af, &nbr->raddr, nbrp->auth.md5key);
266 #endif
267 }
268
269 pconn = pending_conn_find(nbr->af, &nbr->raddr);
270 if (pconn) {
271 session_accept_nbr(nbr, pconn->fd);
272 pending_conn_del(pconn);
273 }
274
275 return (nbr);
276 }
277
278 void
279 nbr_del(struct nbr *nbr)
280 {
281 struct adj *adj;
282
283 log_debug("%s: lsr-id %pI4", __func__, &nbr->id);
284
285 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
286 #ifdef __OpenBSD__
287 pfkey_remove(nbr);
288 #else
289 sock_set_md5sig(
290 (ldp_af_global_get(&global, nbr->af))->ldp_session_socket,
291 nbr->af, &nbr->raddr, NULL);
292 #endif
293 nbr->auth.method = AUTH_NONE;
294
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);
301
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);
307
308 while (!RB_EMPTY(nbr_adj_head, &nbr->adj_tree)) {
309 adj = RB_ROOT(nbr_adj_head, &nbr->adj_tree);
310
311 adj->nbr = NULL;
312 RB_REMOVE(nbr_adj_head, &nbr->adj_tree, adj);
313 }
314
315 if (nbr->peerid)
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);
319
320 free(nbr);
321 }
322
323 static void
324 nbr_update_peerid(struct nbr *nbr)
325 {
326 static uint32_t peercnt = 1;
327
328 if (nbr->peerid)
329 RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr);
330
331 /* get next unused peerid */
332 while (nbr_find_peerid(++peercnt))
333 ;
334 nbr->peerid = peercnt;
335
336 if (RB_INSERT(nbr_pid_head, &nbrs_by_pid, nbr) != NULL)
337 fatalx("nbr_update_peerid: RB_INSERT(nbrs_by_pid) failed");
338 }
339
340 struct nbr *
341 nbr_find_ldpid(uint32_t lsr_id)
342 {
343 struct nbr n;
344 n.id.s_addr = lsr_id;
345 return (RB_FIND(nbr_id_head, &nbrs_by_id, &n));
346 }
347
348 struct nbr *nbr_get_first_ldpid(void)
349 {
350 return (RB_MIN(nbr_id_head, &nbrs_by_id));
351 }
352
353 struct nbr *
354 nbr_get_next_ldpid(uint32_t lsr_id)
355 {
356 struct nbr *nbr;
357 nbr = nbr_find_ldpid(lsr_id);
358 if (nbr)
359 return (RB_NEXT(nbr_id_head, nbr));
360 return NULL;
361 }
362
363
364 struct nbr *
365 nbr_find_addr(int af, union ldpd_addr *addr)
366 {
367 struct nbr n;
368 n.af = af;
369 n.raddr = *addr;
370 return (RB_FIND(nbr_addr_head, &nbrs_by_addr, &n));
371 }
372
373 struct nbr *
374 nbr_find_peerid(uint32_t peerid)
375 {
376 struct nbr n;
377 n.peerid = peerid;
378 return (RB_FIND(nbr_pid_head, &nbrs_by_pid, &n));
379 }
380
381 int
382 nbr_adj_count(struct nbr *nbr, int af)
383 {
384 struct adj *adj;
385 int total = 0;
386
387 RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree)
388 if (adj_get_af(adj) == af)
389 total++;
390
391 return (total);
392 }
393
394 int
395 nbr_session_active_role(struct nbr *nbr)
396 {
397 if (ldp_addrcmp(nbr->af, &nbr->laddr, &nbr->raddr) > 0)
398 return (1);
399
400 return (0);
401 }
402
403 /* timers */
404
405 /* Keepalive timer: timer to send keepalive message to neighbors */
406
407 static void nbr_ktimer(struct event *thread)
408 {
409 struct nbr *nbr = EVENT_ARG(thread);
410
411 nbr->keepalive_timer = NULL;
412 send_keepalive(nbr);
413 nbr_start_ktimer(nbr);
414 }
415
416 static void
417 nbr_start_ktimer(struct nbr *nbr)
418 {
419 int secs;
420
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);
426 }
427
428 void
429 nbr_stop_ktimer(struct nbr *nbr)
430 {
431 EVENT_OFF(nbr->keepalive_timer);
432 }
433
434 /* Keepalive timeout: if the nbr hasn't sent keepalive */
435
436 static void nbr_ktimeout(struct event *thread)
437 {
438 struct nbr *nbr = EVENT_ARG(thread);
439
440 nbr->keepalive_timeout = NULL;
441
442 log_debug("%s: lsr-id %pI4", __func__, &nbr->id);
443
444 session_shutdown(nbr, S_KEEPALIVE_TMR, 0, 0);
445 }
446
447 static void
448 nbr_start_ktimeout(struct nbr *nbr)
449 {
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);
454 }
455
456 void
457 nbr_stop_ktimeout(struct nbr *nbr)
458 {
459 EVENT_OFF(nbr->keepalive_timeout);
460 }
461
462 /* Session initialization timeout: if nbr got stuck in the initialization FSM */
463
464 static void nbr_itimeout(struct event *thread)
465 {
466 struct nbr *nbr = EVENT_ARG(thread);
467
468 log_debug("%s: lsr-id %pI4", __func__, &nbr->id);
469
470 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
471 }
472
473 static void
474 nbr_start_itimeout(struct nbr *nbr)
475 {
476 int secs;
477
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);
482 }
483
484 void
485 nbr_stop_itimeout(struct nbr *nbr)
486 {
487 EVENT_OFF(nbr->init_timeout);
488 }
489
490 /* Init delay timer: timer to retry to iniziatize session */
491
492 static void nbr_idtimer(struct event *thread)
493 {
494 struct nbr *nbr = EVENT_ARG(thread);
495
496 nbr->initdelay_timer = NULL;
497
498 log_debug("%s: lsr-id %pI4", __func__, &nbr->id);
499
500 nbr_establish_connection(nbr);
501 }
502
503 void
504 nbr_start_idtimer(struct nbr *nbr)
505 {
506 int secs;
507
508 secs = INIT_DELAY_TMR;
509 switch(nbr->idtimer_cnt) {
510 default:
511 /* do not further increase the counter */
512 secs = MAX_DELAY_TMR;
513 break;
514 case 2:
515 secs *= 2;
516 /* FALLTHROUGH */
517 case 1:
518 secs *= 2;
519 /* FALLTHROUGH */
520 case 0:
521 nbr->idtimer_cnt++;
522 break;
523 }
524
525 EVENT_OFF(nbr->initdelay_timer);
526 nbr->initdelay_timer = NULL;
527 event_add_timer(master, nbr_idtimer, nbr, secs, &nbr->initdelay_timer);
528 }
529
530 void
531 nbr_stop_idtimer(struct nbr *nbr)
532 {
533 EVENT_OFF(nbr->initdelay_timer);
534 }
535
536 int
537 nbr_pending_idtimer(struct nbr *nbr)
538 {
539 return (nbr->initdelay_timer != NULL);
540 }
541
542 int
543 nbr_pending_connect(struct nbr *nbr)
544 {
545 return (nbr->ev_connect != NULL);
546 }
547
548 static void nbr_connect_cb(struct event *thread)
549 {
550 struct nbr *nbr = EVENT_ARG(thread);
551 int error;
552 socklen_t len;
553
554 nbr->ev_connect = NULL;
555
556 len = sizeof(error);
557 if (getsockopt(nbr->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
558 log_warn("%s: getsockopt SOL_SOCKET SO_ERROR", __func__);
559 return;
560 }
561
562 if (error) {
563 close(nbr->fd);
564 errno = error;
565 log_debug("%s: error while connecting to %s: %s", __func__,
566 log_addr(nbr->af, &nbr->raddr), strerror(errno));
567 return;
568 }
569
570 nbr_fsm(nbr, NBR_EVT_CONNECT_UP);
571 }
572
573 int
574 nbr_establish_connection(struct nbr *nbr)
575 {
576 union sockunion local_su;
577 union sockunion remote_su;
578 struct adj *adj;
579 struct nbr_params *nbrp;
580 #ifdef __OpenBSD__
581 int opt = 1;
582 #endif
583
584 nbr->fd = socket(nbr->af, SOCK_STREAM, 0);
585 if (nbr->fd == -1) {
586 log_warn("%s: error while creating socket", __func__);
587 return (-1);
588 }
589 sock_set_nonblock(nbr->fd);
590
591 nbrp = nbr_params_find(leconf, nbr->id);
592 if (nbrp && nbrp->auth.method == AUTH_MD5SIG) {
593 #ifdef __OpenBSD__
594 if (sysdep.no_pfkey || sysdep.no_md5sig) {
595 log_warnx("md5sig configured but not available");
596 close(nbr->fd);
597 return (-1);
598 }
599 if (setsockopt(nbr->fd, IPPROTO_TCP, TCP_MD5SIG,
600 &opt, sizeof(opt)) == -1) {
601 log_warn("setsockopt md5sig");
602 close(nbr->fd);
603 return (-1);
604 }
605 #else
606 sock_set_md5sig(nbr->fd, nbr->af, &nbr->raddr, nbrp->auth.md5key);
607 #endif
608 }
609
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",
613 __func__, &nbr->id);
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",
617 __func__, &nbr->id);
618 }
619
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);
624
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));
628 close(nbr->fd);
629 return (-1);
630 }
631
632 if (nbr_gtsm_check(nbr->fd, nbr, nbrp)) {
633 close(nbr->fd);
634 return (-1);
635 }
636
637 /*
638 * Send an extra hello to guarantee that the remote peer has formed
639 * an adjacency as well.
640 */
641 RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree)
642 send_hello(adj->source.type, adj->source.link.ia,
643 adj->source.target);
644
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,
648 &nbr->ev_connect);
649 return (0);
650 }
651 log_warn("%s: error while connecting to %s", __func__,
652 log_sockaddr(&remote_su.sa));
653 close(nbr->fd);
654 return (-1);
655 }
656
657 /* connection completed immediately */
658 nbr_fsm(nbr, NBR_EVT_CONNECT_UP);
659
660 return (0);
661 }
662
663 int
664 nbr_gtsm_enabled(struct nbr *nbr, struct nbr_params *nbrp)
665 {
666 /*
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".
671 */
672 if (nbrp && CHECK_FLAG(nbrp->flags, F_NBRP_GTSM))
673 return (nbrp->gtsm_enabled);
674
675 if (CHECK_FLAG((ldp_af_conf_get(leconf, nbr->af))->flags, F_LDPD_AF_NO_GTSM))
676 return (0);
677
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))
680 return (0);
681
682 return (1);
683 }
684
685 int
686 nbr_gtsm_setup(int fd, int af, struct nbr_params *nbrp)
687 {
688 int ttl = 255;
689
690 if (nbrp && CHECK_FLAG(nbrp->flags, F_NBRP_GTSM_HOPS))
691 ttl = 256 - nbrp->gtsm_hops;
692
693 switch (af) {
694 case AF_INET:
695 if (sock_set_ipv4_minttl(fd, ttl) == -1)
696 return (-1);
697 ttl = 255;
698 if (sock_set_ipv4_ucast_ttl(fd, ttl) == -1)
699 return (-1);
700 break;
701 case AF_INET6:
702 /* ignore any possible error */
703 sock_set_ipv6_minhopcount(fd, ttl);
704 ttl = 255;
705 if (sock_set_ipv6_ucast_hops(fd, ttl) == -1)
706 return (-1);
707 break;
708 default:
709 fatalx("nbr_gtsm_setup: unknown af");
710 }
711
712 return (0);
713 }
714
715 int
716 nbr_gtsm_check(int fd, struct nbr *nbr, struct nbr_params *nbrp)
717 {
718 if (!nbr_gtsm_enabled(nbr, nbrp)) {
719 switch (nbr->af) {
720 case AF_INET:
721 sock_set_ipv4_ucast_ttl(fd, -1);
722 break;
723 case AF_INET6:
724 /*
725 * Send packets with a Hop Limit of 255 even when GSTM
726 * is disabled to guarantee interoperability.
727 */
728 sock_set_ipv6_ucast_hops(fd, 255);
729 break;
730 default:
731 fatalx("nbr_gtsm_check: unknown af");
732 break;
733 }
734 return (0);
735 }
736
737 if (nbr_gtsm_setup(fd, nbr->af, nbrp) == -1) {
738 log_warnx("%s: error enabling GTSM for lsr-id %pI4", __func__, &nbr->id);
739 return (-1);
740 }
741
742 return (0);
743 }
744
745 static int
746 nbr_act_session_operational(struct nbr *nbr)
747 {
748 struct lde_nbr lde_nbr;
749
750 nbr->idtimer_cnt = 0;
751
752 /* this is necessary to avoid ipc synchronization issues */
753 nbr_update_peerid(nbr);
754
755 ldp_sync_fsm_nbr_event(nbr, LDP_SYNC_EVT_LDP_SYNC_START);
756
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)));
764 }
765
766 static void
767 nbr_send_labelmappings(struct nbr *nbr)
768 {
769 ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL, nbr->peerid, 0, NULL, 0);
770 }
771
772 static __inline int
773 nbr_params_compare(const struct nbr_params *a, const struct nbr_params *b)
774 {
775 return (ntohl(a->lsr_id.s_addr) - ntohl(b->lsr_id.s_addr));
776 }
777
778 struct nbr_params *
779 nbr_params_new(struct in_addr lsr_id)
780 {
781 struct nbr_params *nbrp;
782
783 if ((nbrp = calloc(1, sizeof(*nbrp))) == NULL)
784 fatal(__func__);
785
786 nbrp->lsr_id = lsr_id;
787 nbrp->auth.method = AUTH_NONE;
788
789 return (nbrp);
790 }
791
792 struct nbr_params *
793 nbr_params_find(struct ldpd_conf *xconf, struct in_addr lsr_id)
794 {
795 struct nbr_params nbrp;
796 nbrp.lsr_id = lsr_id;
797 return (RB_FIND(nbrp_head, &xconf->nbrp_tree, &nbrp));
798 }
799
800 uint16_t
801 nbr_get_keepalive(int af, struct in_addr lsr_id)
802 {
803 struct nbr_params *nbrp;
804
805 nbrp = nbr_params_find(leconf, lsr_id);
806 if (nbrp && CHECK_FLAG(nbrp->flags, F_NBRP_KEEPALIVE))
807 return (nbrp->keepalive);
808
809 return ((ldp_af_conf_get(leconf, af))->keepalive);
810 }
811
812 struct ctl_nbr *
813 nbr_to_ctl(struct nbr *nbr)
814 {
815 static struct ctl_nbr nctl;
816 struct timeval now;
817
818 nctl.af = nbr->af;
819 nctl.id = nbr->id;
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);
831
832 gettimeofday(&now, NULL);
833 if (nbr->state == NBR_STA_OPER) {
834 nctl.uptime = now.tv_sec - nbr->uptime;
835 } else
836 nctl.uptime = 0;
837
838 return (&nctl);
839 }
840
841 void
842 nbr_clear_ctl(struct ctl_nbr *nctl)
843 {
844 struct nbr *nbr;
845
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))
849 continue;
850
851 log_debug("%s: neighbor %s manually cleared", __func__,
852 log_addr(nbr->af, &nbr->raddr));
853 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
854 }
855 }