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